1 #include <bitcoin/bitcoin.hpp>
2 using namespace libbitcoin;
4 #include "/home/genjix/python-bitcoin/src/primitive.h"
6 namespace ph = std::placeholders;
8 int cmp(const bc::message::output_point& a,
9 const bc::message::output_point& b)
11 if (a.index < b.index)
13 else if (a.index > b.index)
18 else if (a.hash > b.hash)
23 struct outpoint_less_cmp
25 bool operator()(const bc::message::output_point& a,
26 const bc::message::output_point& b)
28 return cmp(a, b) == -1;
32 struct address_less_cmp
34 bool operator()(const payment_address& a, const payment_address& b)
36 if (a.hash() < b.hash())
38 else if (a.hash() > b.hash())
40 if (a.version() < b.version())
47 : public std::enable_shared_from_this<memory_buffer>
57 message::output_point previous_output;
59 typedef std::vector<check_item> check_result;
60 typedef std::shared_ptr<check_result> check_result_ptr;
62 typedef std::function<
63 void (const std::error_code&)> receive_handler;
64 typedef std::function<
65 void (const std::error_code&, check_result_ptr)> check_handler;
67 memory_buffer(async_service_ptr service, blockchain_ptr chain,
68 transaction_pool_ptr txpool)
69 : strand_(service->get_service()), chain_(chain), txpool_(txpool)
73 void set_handles(python::object handle_tx_stored,
74 python::object handle_tx_confirmed)
76 auto this_ptr = shared_from_this();
78 [&, this_ptr, handle_tx_stored, handle_tx_confirmed]()
80 handle_tx_stored_ = handle_tx_stored;
81 handle_tx_confirmed_ = handle_tx_confirmed;
85 void receive(const message::transaction& tx,
86 python::object handle_receive)
89 strand_.wrap(std::bind(&memory_buffer::confirmed,
90 shared_from_this(), ph::_1, tx)),
91 strand_.wrap(std::bind(&memory_buffer::stored,
92 shared_from_this(), ph::_1, tx, handle_receive)));
95 void check(const message::output_point_list& output_points,
96 const std::string& address, check_handler handle_check)
101 void stored(const std::error_code& ec, const message::transaction& tx,
102 python::object handle_receive)
106 pyfunction<const std::error_code&> f(handle_receive);
110 const hash_digest& tx_hash = hash_transaction(tx);
111 for (uint32_t input_index = 0;
112 input_index < tx.inputs.size(); ++input_index)
114 const auto& prevout = tx.inputs[input_index].previous_output;
115 lookup_input_[prevout] =
116 message::input_point{tx_hash, input_index};
118 for (uint32_t output_index = 0;
119 output_index < tx.outputs.size(); ++output_index)
121 payment_address address;
122 if (extract(address, tx.outputs[output_index].output_script))
124 lookup_address_.insert(
125 std::make_pair(address,
126 message::output_point{tx_hash, output_index}));
129 timestamps_[tx_hash] = time(nullptr);
130 pyfunction<const std::error_code&> f(handle_receive);
131 f(std::error_code());
133 if (!handle_tx_stored_.is_none())
135 pyfunction<const message::transaction&> g(handle_tx_stored_);
140 void confirmed(const std::error_code& ec, const message::transaction& tx)
142 const hash_digest& tx_hash = hash_transaction(tx);
145 std::cerr << "Problem confirming transaction "
146 << pretty_hex(tx_hash) << " : " << ec.message() << std::endl;
149 std::cout << "Confirmed " << pretty_hex(tx_hash) << std::endl;
150 for (uint32_t input_index = 0;
151 input_index < tx.inputs.size(); ++input_index)
153 const auto& prevout = tx.inputs[input_index].previous_output;
154 auto it = lookup_input_.find(prevout);
155 BITCOIN_ASSERT(it != lookup_input_.end());
156 BITCOIN_ASSERT((it->second ==
157 message::input_point{tx_hash, input_index}));
158 lookup_input_.erase(it);
160 for (uint32_t output_index = 0;
161 output_index < tx.outputs.size(); ++output_index)
163 message::output_point outpoint{tx_hash, output_index};
164 payment_address address;
165 if (extract(address, tx.outputs[output_index].output_script))
167 auto range = lookup_address_.equal_range(address);
168 auto it = range.first;
169 for (; it != range.second; ++it)
171 if (it->second == outpoint)
173 lookup_address_.erase(it);
177 BITCOIN_ASSERT(it != range.second);
180 auto time_it = timestamps_.find(tx_hash);
181 BITCOIN_ASSERT(time_it != timestamps_.end());
182 timestamps_.erase(time_it);
184 if (!handle_tx_stored_.is_none())
186 pyfunction<const message::transaction&> f(handle_tx_confirmed_);
191 io_service::strand strand_;
192 blockchain_ptr chain_;
193 transaction_pool_ptr txpool_;
195 std::map<message::output_point,
196 message::input_point, outpoint_less_cmp> lookup_input_;
197 std::multimap<payment_address,
198 message::output_point, address_less_cmp> lookup_address_;
199 std::map<hash_digest, uint64_t> timestamps_;
201 python::object handle_tx_stored_, handle_tx_confirmed_;
204 typedef std::shared_ptr<memory_buffer> memory_buffer_ptr;