Libbitcoin subscribe to address #807
17 changed files with 561 additions and 353 deletions
|
|
@ -210,8 +210,8 @@ network_node_api::network_node_api(application &a) :
|
|||
}
|
||||
|
||||
/*
|
||||
* Remove expired transactions from pending_transactions
|
||||
*/
|
||||
* Remove expired transactions from pending_transactions
|
||||
*/
|
||||
for (const auto &transaction : _pending_transactions) {
|
||||
if (transaction.second.expiration < block.timestamp) {
|
||||
auto transaction_it = _pending_transactions.find(transaction.second.id());
|
||||
|
|
@ -366,10 +366,9 @@ vector<operation_history_object> history_api::get_account_history(const std::str
|
|||
_app.elasticsearch_thread = std::make_shared<fc::thread>("elasticsearch");
|
||||
|
||||
return _app.elasticsearch_thread->async([&es, &account, &stop, &limit, &start]() {
|
||||
return es->get_account_history(account, stop, limit, start);
|
||||
},
|
||||
"thread invoke for method " BOOST_PP_STRINGIZE(method_name))
|
||||
.wait();
|
||||
return es->get_account_history(account, stop, limit, start);
|
||||
},
|
||||
"thread invoke for method " BOOST_PP_STRINGIZE(method_name)).wait();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -391,8 +391,8 @@ public:
|
|||
}
|
||||
|
||||
/**
|
||||
* If delegate has the item, the network has no need to fetch it.
|
||||
*/
|
||||
* If delegate has the item, the network has no need to fetch it.
|
||||
*/
|
||||
virtual bool has_item(const net::item_id &id) override {
|
||||
try {
|
||||
if (id.item_type == graphene::net::block_message_type)
|
||||
|
|
@ -404,13 +404,13 @@ public:
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief allows the application to validate an item prior to broadcasting to peers.
|
||||
*
|
||||
* @param sync_mode true if the message was fetched through the sync process, false during normal operation
|
||||
* @returns true if this message caused the blockchain to switch forks, false if it did not
|
||||
*
|
||||
* @throws exception if error validating the item, otherwise the item is safe to broadcast on.
|
||||
*/
|
||||
* @brief allows the application to validate an item prior to broadcasting to peers.
|
||||
*
|
||||
* @param sync_mode true if the message was fetched through the sync process, false during normal operation
|
||||
* @returns true if this message caused the blockchain to switch forks, false if it did not
|
||||
*
|
||||
* @throws exception if error validating the item, otherwise the item is safe to broadcast on.
|
||||
*/
|
||||
virtual bool handle_block(const graphene::net::block_message &blk_msg, bool sync_mode,
|
||||
std::vector<fc::uint160_t> &contained_transaction_message_ids) override {
|
||||
|
||||
|
|
@ -498,14 +498,14 @@ public:
|
|||
}
|
||||
|
||||
/**
|
||||
* Assuming all data elements are ordered in some way, this method should
|
||||
* return up to limit ids that occur *after* the last ID in synopsis that
|
||||
* we recognize.
|
||||
*
|
||||
* On return, remaining_item_count will be set to the number of items
|
||||
* in our blockchain after the last item returned in the result,
|
||||
* or 0 if the result contains the last item in the blockchain
|
||||
*/
|
||||
* Assuming all data elements are ordered in some way, this method should
|
||||
* return up to limit ids that occur *after* the last ID in synopsis that
|
||||
* we recognize.
|
||||
*
|
||||
* On return, remaining_item_count will be set to the number of items
|
||||
* in our blockchain after the last item returned in the result,
|
||||
* or 0 if the result contains the last item in the blockchain
|
||||
*/
|
||||
virtual std::vector<item_hash_t> get_block_ids(const std::vector<item_hash_t> &blockchain_synopsis,
|
||||
uint32_t &remaining_item_count,
|
||||
uint32_t limit) override {
|
||||
|
|
@ -552,8 +552,8 @@ public:
|
|||
}
|
||||
|
||||
/**
|
||||
* Given the hash of the requested data, fetch the body.
|
||||
*/
|
||||
* Given the hash of the requested data, fetch the body.
|
||||
*/
|
||||
virtual message get_item(const item_id &id) override {
|
||||
try {
|
||||
// ilog("Request for item ${id}", ("id", id));
|
||||
|
|
@ -576,63 +576,63 @@ public:
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns a synopsis of the blockchain used for syncing. This consists of a list of
|
||||
* block hashes at intervals exponentially increasing towards the genesis block.
|
||||
* When syncing to a peer, the peer uses this data to determine if we're on the same
|
||||
* fork as they are, and if not, what blocks they need to send us to get us on their
|
||||
* fork.
|
||||
*
|
||||
* In the over-simplified case, this is a straighforward synopsis of our current
|
||||
* preferred blockchain; when we first connect up to a peer, this is what we will be sending.
|
||||
* It looks like this:
|
||||
* If the blockchain is empty, it will return the empty list.
|
||||
* If the blockchain has one block, it will return a list containing just that block.
|
||||
* If it contains more than one block:
|
||||
* the first element in the list will be the hash of the highest numbered block that
|
||||
* we cannot undo
|
||||
* the second element will be the hash of an item at the half way point in the undoable
|
||||
* segment of the blockchain
|
||||
* the third will be ~3/4 of the way through the undoable segment of the block chain
|
||||
* the fourth will be at ~7/8...
|
||||
* &c.
|
||||
* the last item in the list will be the hash of the most recent block on our preferred chain
|
||||
* so if the blockchain had 26 blocks labeled a - z, the synopsis would be:
|
||||
* a n u x z
|
||||
* the idea being that by sending a small (<30) number of block ids, we can summarize a huge
|
||||
* blockchain. The block ids are more dense near the end of the chain where because we are
|
||||
* more likely to be almost in sync when we first connect, and forks are likely to be short.
|
||||
* If the peer we're syncing with in our example is on a fork that started at block 'v',
|
||||
* then they will reply to our synopsis with a list of all blocks starting from block 'u',
|
||||
* the last block they know that we had in common.
|
||||
*
|
||||
* In the real code, there are several complications.
|
||||
*
|
||||
* First, as an optimization, we don't usually send a synopsis of the entire blockchain, we
|
||||
* send a synopsis of only the segment of the blockchain that we have undo data for. If their
|
||||
* fork doesn't build off of something in our undo history, we would be unable to switch, so there's
|
||||
* no reason to fetch the blocks.
|
||||
*
|
||||
* Second, when a peer replies to our initial synopsis and gives us a list of the blocks they think
|
||||
* we are missing, they only send a chunk of a few thousand blocks at once. After we get those
|
||||
* block ids, we need to request more blocks by sending another synopsis (we can't just say "send me
|
||||
* the next 2000 ids" because they may have switched forks themselves and they don't track what
|
||||
* they've sent us). For faster performance, we want to get a fairly long list of block ids first,
|
||||
* then start downloading the blocks.
|
||||
* The peer doesn't handle these follow-up block id requests any different from the initial request;
|
||||
* it treats the synopsis we send as our blockchain and bases its response entirely off that. So to
|
||||
* get the response we want (the next chunk of block ids following the last one they sent us, or,
|
||||
* failing that, the shortest fork off of the last list of block ids they sent), we need to construct
|
||||
* a synopsis as if our blockchain was made up of:
|
||||
* 1. the blocks in our block chain up to the fork point (if there is a fork) or the head block (if no fork)
|
||||
* 2. the blocks we've already pushed from their fork (if there's a fork)
|
||||
* 3. the block ids they've previously sent us
|
||||
* Segment 3 is handled in the p2p code, it just tells us the number of blocks it has (in
|
||||
* number_of_blocks_after_reference_point) so we can leave space in the synopsis for them.
|
||||
* We're responsible for constructing the synopsis of Segments 1 and 2 from our active blockchain and
|
||||
* fork database. The reference_point parameter is the last block from that peer that has been
|
||||
* successfully pushed to the blockchain, so that tells us whether the peer is on a fork or on
|
||||
* the main chain.
|
||||
*/
|
||||
* Returns a synopsis of the blockchain used for syncing. This consists of a list of
|
||||
* block hashes at intervals exponentially increasing towards the genesis block.
|
||||
* When syncing to a peer, the peer uses this data to determine if we're on the same
|
||||
* fork as they are, and if not, what blocks they need to send us to get us on their
|
||||
* fork.
|
||||
*
|
||||
* In the over-simplified case, this is a straighforward synopsis of our current
|
||||
* preferred blockchain; when we first connect up to a peer, this is what we will be sending.
|
||||
* It looks like this:
|
||||
* If the blockchain is empty, it will return the empty list.
|
||||
* If the blockchain has one block, it will return a list containing just that block.
|
||||
* If it contains more than one block:
|
||||
* the first element in the list will be the hash of the highest numbered block that
|
||||
* we cannot undo
|
||||
* the second element will be the hash of an item at the half way point in the undoable
|
||||
* segment of the blockchain
|
||||
* the third will be ~3/4 of the way through the undoable segment of the block chain
|
||||
* the fourth will be at ~7/8...
|
||||
* &c.
|
||||
* the last item in the list will be the hash of the most recent block on our preferred chain
|
||||
* so if the blockchain had 26 blocks labeled a - z, the synopsis would be:
|
||||
* a n u x z
|
||||
* the idea being that by sending a small (<30) number of block ids, we can summarize a huge
|
||||
* blockchain. The block ids are more dense near the end of the chain where because we are
|
||||
* more likely to be almost in sync when we first connect, and forks are likely to be short.
|
||||
* If the peer we're syncing with in our example is on a fork that started at block 'v',
|
||||
* then they will reply to our synopsis with a list of all blocks starting from block 'u',
|
||||
* the last block they know that we had in common.
|
||||
*
|
||||
* In the real code, there are several complications.
|
||||
*
|
||||
* First, as an optimization, we don't usually send a synopsis of the entire blockchain, we
|
||||
* send a synopsis of only the segment of the blockchain that we have undo data for. If their
|
||||
* fork doesn't build off of something in our undo history, we would be unable to switch, so there's
|
||||
* no reason to fetch the blocks.
|
||||
*
|
||||
* Second, when a peer replies to our initial synopsis and gives us a list of the blocks they think
|
||||
* we are missing, they only send a chunk of a few thousand blocks at once. After we get those
|
||||
* block ids, we need to request more blocks by sending another synopsis (we can't just say "send me
|
||||
* the next 2000 ids" because they may have switched forks themselves and they don't track what
|
||||
* they've sent us). For faster performance, we want to get a fairly long list of block ids first,
|
||||
* then start downloading the blocks.
|
||||
* The peer doesn't handle these follow-up block id requests any different from the initial request;
|
||||
* it treats the synopsis we send as our blockchain and bases its response entirely off that. So to
|
||||
* get the response we want (the next chunk of block ids following the last one they sent us, or,
|
||||
* failing that, the shortest fork off of the last list of block ids they sent), we need to construct
|
||||
* a synopsis as if our blockchain was made up of:
|
||||
* 1. the blocks in our block chain up to the fork point (if there is a fork) or the head block (if no fork)
|
||||
* 2. the blocks we've already pushed from their fork (if there's a fork)
|
||||
* 3. the block ids they've previously sent us
|
||||
* Segment 3 is handled in the p2p code, it just tells us the number of blocks it has (in
|
||||
* number_of_blocks_after_reference_point) so we can leave space in the synopsis for them.
|
||||
* We're responsible for constructing the synopsis of Segments 1 and 2 from our active blockchain and
|
||||
* fork database. The reference_point parameter is the last block from that peer that has been
|
||||
* successfully pushed to the blockchain, so that tells us whether the peer is on a fork or on
|
||||
* the main chain.
|
||||
*/
|
||||
virtual std::vector<item_hash_t> get_blockchain_synopsis(const item_hash_t &reference_point,
|
||||
uint32_t number_of_blocks_after_reference_point) override {
|
||||
try {
|
||||
|
|
@ -733,26 +733,26 @@ public:
|
|||
low_block_num += (true_high_block_num - low_block_num + 2) / 2;
|
||||
} while (low_block_num <= high_block_num);
|
||||
|
||||
//idump((synopsis));
|
||||
// idump((synopsis));
|
||||
return synopsis;
|
||||
}
|
||||
FC_CAPTURE_AND_RETHROW()
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this after the call to handle_message succeeds.
|
||||
*
|
||||
* @param item_type the type of the item we're synchronizing, will be the same as item passed to the sync_from() call
|
||||
* @param item_count the number of items known to the node that haven't been sent to handle_item() yet.
|
||||
* After `item_count` more calls to handle_item(), the node will be in sync
|
||||
*/
|
||||
* Call this after the call to handle_message succeeds.
|
||||
*
|
||||
* @param item_type the type of the item we're synchronizing, will be the same as item passed to the sync_from() call
|
||||
* @param item_count the number of items known to the node that haven't been sent to handle_item() yet.
|
||||
* After `item_count` more calls to handle_item(), the node will be in sync
|
||||
*/
|
||||
virtual void sync_status(uint32_t item_type, uint32_t item_count) override {
|
||||
// any status reports to GUI go here
|
||||
}
|
||||
|
||||
/**
|
||||
* Call any time the number of connected peers changes.
|
||||
*/
|
||||
* Call any time the number of connected peers changes.
|
||||
*/
|
||||
virtual void connection_count_changed(uint32_t c) override {
|
||||
// any status reports to GUI go here
|
||||
}
|
||||
|
|
@ -769,9 +769,9 @@ public:
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the time a block was produced (if block_id = 0, returns genesis time).
|
||||
* If we don't know about the block, returns time_point_sec::min()
|
||||
*/
|
||||
* Returns the time a block was produced (if block_id = 0, returns genesis time).
|
||||
* If we don't know about the block, returns time_point_sec::min()
|
||||
*/
|
||||
virtual fc::time_point_sec get_block_time(const item_hash_t &block_id) override {
|
||||
try {
|
||||
auto opt_block = _chain_db->fetch_block_by_id(block_id);
|
||||
|
|
|
|||
|
|
@ -313,7 +313,7 @@ public:
|
|||
uint32_t api_limit_get_trade_history = 100;
|
||||
uint32_t api_limit_get_trade_history_by_sequence = 100;
|
||||
|
||||
//private:
|
||||
// private:
|
||||
const account_object *get_account_from_string(const std::string &name_or_id,
|
||||
bool throw_if_not_found = true) const;
|
||||
const asset_object *get_asset_from_string(const std::string &symbol_or_id,
|
||||
|
|
@ -470,7 +470,7 @@ void database_api::set_subscribe_callback(std::function<void(const variant &)> c
|
|||
}
|
||||
|
||||
void database_api_impl::set_subscribe_callback(std::function<void(const variant &)> cb, bool notify_remove_create) {
|
||||
//edump((clear_filter));
|
||||
// edump((clear_filter));
|
||||
_subscribe_callback = cb;
|
||||
_notify_remove_create = notify_remove_create;
|
||||
_subscribed_accounts.clear();
|
||||
|
|
@ -2903,7 +2903,7 @@ graphene::app::gpos_info database_api::get_gpos_info(const account_id_type accou
|
|||
}
|
||||
|
||||
graphene::app::gpos_info database_api_impl::get_gpos_info(const account_id_type account) const {
|
||||
FC_ASSERT(_db.head_block_time() > HARDFORK_GPOS_TIME); //Can be deleted after GPOS hardfork time
|
||||
FC_ASSERT(_db.head_block_time() > HARDFORK_GPOS_TIME); // Can be deleted after GPOS hardfork time
|
||||
gpos_info result;
|
||||
|
||||
result.vesting_factor = _db.calculate_vesting_factor(account(_db));
|
||||
|
|
@ -3550,9 +3550,9 @@ void database_api_impl::handle_object_changed(bool force_notify, bool full_objec
|
|||
/// pushing the future back / popping the prior future if it is complete.
|
||||
/// if a connection hangs then this could get backed up and result in
|
||||
/// a failure to exit cleanly.
|
||||
//fc::async([capture_this,this,updates,market_broadcast_queue](){
|
||||
//if( _subscribe_callback )
|
||||
// _subscribe_callback( updates );
|
||||
// fc::async([capture_this,this,updates,market_broadcast_queue](){
|
||||
// if( _subscribe_callback )
|
||||
// _subscribe_callback( updates );
|
||||
|
||||
for (auto id : ids) {
|
||||
if (id.is<call_order_object>()) {
|
||||
|
|
|
|||
|
|
@ -85,10 +85,10 @@ struct asset_holders {
|
|||
};
|
||||
|
||||
/**
|
||||
* @brief The history_api class implements the RPC API for account history
|
||||
*
|
||||
* This API contains methods to access account histories
|
||||
*/
|
||||
* @brief The history_api class implements the RPC API for account history
|
||||
*
|
||||
* This API contains methods to access account histories
|
||||
*/
|
||||
class history_api {
|
||||
public:
|
||||
history_api(application &app) :
|
||||
|
|
@ -97,27 +97,27 @@ public:
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief Get operations relevant to the specificed account
|
||||
* @param account_id_or_name The account ID or name whose history should be queried
|
||||
* @param stop ID of the earliest operation to retrieve
|
||||
* @param limit Maximum number of operations to retrieve (must not exceed 100)
|
||||
* @param start ID of the most recent operation to retrieve
|
||||
* @return A list of operations performed by account, ordered from most recent to oldest.
|
||||
*/
|
||||
* @brief Get operations relevant to the specificed account
|
||||
* @param account_id_or_name The account ID or name whose history should be queried
|
||||
* @param stop ID of the earliest operation to retrieve
|
||||
* @param limit Maximum number of operations to retrieve (must not exceed 100)
|
||||
* @param start ID of the most recent operation to retrieve
|
||||
* @return A list of operations performed by account, ordered from most recent to oldest.
|
||||
*/
|
||||
vector<operation_history_object> get_account_history(const std::string account_id_or_name,
|
||||
operation_history_id_type stop = operation_history_id_type(),
|
||||
unsigned limit = 100,
|
||||
operation_history_id_type start = operation_history_id_type()) const;
|
||||
|
||||
/**
|
||||
* @brief Get only asked operations relevant to the specified account
|
||||
* @param account_id_or_name The account ID or name whose history should be queried
|
||||
* @param operation_id The ID of the operation we want to get operations in the account( 0 = transfer , 1 = limit order create, ...)
|
||||
* @param stop ID of the earliest operation to retrieve
|
||||
* @param limit Maximum number of operations to retrieve (must not exceed 100)
|
||||
* @param start ID of the most recent operation to retrieve
|
||||
* @return A list of operations performed by account, ordered from most recent to oldest.
|
||||
*/
|
||||
* @brief Get only asked operations relevant to the specified account
|
||||
* @param account_id_or_name The account ID or name whose history should be queried
|
||||
* @param operation_id The ID of the operation we want to get operations in the account( 0 = transfer , 1 = limit order create, ...)
|
||||
* @param stop ID of the earliest operation to retrieve
|
||||
* @param limit Maximum number of operations to retrieve (must not exceed 100)
|
||||
* @param start ID of the most recent operation to retrieve
|
||||
* @return A list of operations performed by account, ordered from most recent to oldest.
|
||||
*/
|
||||
vector<operation_history_object> get_account_history_operations(const std::string account_id_or_name,
|
||||
int operation_id,
|
||||
operation_history_id_type start = operation_history_id_type(),
|
||||
|
|
@ -125,17 +125,17 @@ public:
|
|||
unsigned limit = 100) const;
|
||||
|
||||
/**
|
||||
* @breif Get operations relevant to the specified account referenced
|
||||
* by an event numbering specific to the account. The current number of operations
|
||||
* for the account can be found in the account statistics (or use 0 for start).
|
||||
* @param account_id_or_name The account ID or name whose history should be queried
|
||||
* @param stop Sequence number of earliest operation. 0 is default and will
|
||||
* query 'limit' number of operations.
|
||||
* @param limit Maximum number of operations to retrieve (must not exceed 100)
|
||||
* @param start Sequence number of the most recent operation to retrieve.
|
||||
* 0 is default, which will start querying from the most recent operation.
|
||||
* @return A list of operations performed by account, ordered from most recent to oldest.
|
||||
*/
|
||||
* @breif Get operations relevant to the specified account referenced
|
||||
* by an event numbering specific to the account. The current number of operations
|
||||
* for the account can be found in the account statistics (or use 0 for start).
|
||||
* @param account_id_or_name The account ID or name whose history should be queried
|
||||
* @param stop Sequence number of earliest operation. 0 is default and will
|
||||
* query 'limit' number of operations.
|
||||
* @param limit Maximum number of operations to retrieve (must not exceed 100)
|
||||
* @param start Sequence number of the most recent operation to retrieve.
|
||||
* 0 is default, which will start querying from the most recent operation.
|
||||
* @return A list of operations performed by account, ordered from most recent to oldest.
|
||||
*/
|
||||
vector<operation_history_object> get_relative_account_history(const std::string account_id_or_name,
|
||||
uint32_t stop = 0,
|
||||
unsigned limit = 100,
|
||||
|
|
@ -156,8 +156,8 @@ private:
|
|||
};
|
||||
|
||||
/**
|
||||
* @brief Block api
|
||||
*/
|
||||
* @brief Block api
|
||||
*/
|
||||
class block_api {
|
||||
public:
|
||||
block_api(graphene::chain::database &db);
|
||||
|
|
@ -170,8 +170,8 @@ private:
|
|||
};
|
||||
|
||||
/**
|
||||
* @brief The network_broadcast_api class allows broadcasting of transactions.
|
||||
*/
|
||||
* @brief The network_broadcast_api class allows broadcasting of transactions.
|
||||
*/
|
||||
class network_broadcast_api : public std::enable_shared_from_this<network_broadcast_api> {
|
||||
public:
|
||||
network_broadcast_api(application &a);
|
||||
|
|
@ -186,36 +186,36 @@ public:
|
|||
typedef std::function<void(variant /*transaction_confirmation*/)> confirmation_callback;
|
||||
|
||||
/**
|
||||
* @brief Broadcast a transaction to the network
|
||||
* @param trx The transaction to broadcast
|
||||
*
|
||||
* The transaction will be checked for validity in the local database prior to broadcasting. If it fails to
|
||||
* apply locally, an error will be thrown and the transaction will not be broadcast.
|
||||
*/
|
||||
* @brief Broadcast a transaction to the network
|
||||
* @param trx The transaction to broadcast
|
||||
*
|
||||
* The transaction will be checked for validity in the local database prior to broadcasting. If it fails to
|
||||
* apply locally, an error will be thrown and the transaction will not be broadcast.
|
||||
*/
|
||||
void broadcast_transaction(const signed_transaction &trx);
|
||||
|
||||
/** this version of broadcast transaction registers a callback method that will be called when the transaction is
|
||||
* included into a block. The callback method includes the transaction id, block number, and transaction number in the
|
||||
* block.
|
||||
*/
|
||||
* included into a block. The callback method includes the transaction id, block number, and transaction number in the
|
||||
* block.
|
||||
*/
|
||||
void broadcast_transaction_with_callback(confirmation_callback cb, const signed_transaction &trx);
|
||||
|
||||
/** this version of broadcast transaction registers a callback method that will be called when the transaction is
|
||||
* included into a block. The callback method includes the transaction id, block number, and transaction number in the
|
||||
* block.
|
||||
*/
|
||||
* included into a block. The callback method includes the transaction id, block number, and transaction number in the
|
||||
* block.
|
||||
*/
|
||||
fc::variant broadcast_transaction_synchronous(const signed_transaction &trx);
|
||||
|
||||
void broadcast_block(const signed_block &block);
|
||||
|
||||
/**
|
||||
* @brief Not reflected, thus not accessible to API clients.
|
||||
*
|
||||
* This function is registered to receive the applied_block
|
||||
* signal from the chain database when a block is received.
|
||||
* It then dispatches callbacks to clients who have requested
|
||||
* to be notified when a particular txid is included in a block.
|
||||
*/
|
||||
* @brief Not reflected, thus not accessible to API clients.
|
||||
*
|
||||
* This function is registered to receive the applied_block
|
||||
* signal from the chain database when a block is received.
|
||||
* It then dispatches callbacks to clients who have requested
|
||||
* to be notified when a particular txid is included in a block.
|
||||
*/
|
||||
void on_applied_block(const signed_block &b);
|
||||
|
||||
private:
|
||||
|
|
@ -225,60 +225,60 @@ private:
|
|||
};
|
||||
|
||||
/**
|
||||
* @brief The network_node_api class allows maintenance of p2p connections.
|
||||
*/
|
||||
* @brief The network_node_api class allows maintenance of p2p connections.
|
||||
*/
|
||||
class network_node_api {
|
||||
public:
|
||||
network_node_api(application &a);
|
||||
|
||||
/**
|
||||
* @brief Return general network information, such as p2p port
|
||||
*/
|
||||
* @brief Return general network information, such as p2p port
|
||||
*/
|
||||
fc::variant_object get_info() const;
|
||||
|
||||
/**
|
||||
* @brief add_node Connect to a new peer
|
||||
* @param ep The IP/Port of the peer to connect to
|
||||
*/
|
||||
* @brief add_node Connect to a new peer
|
||||
* @param ep The IP/Port of the peer to connect to
|
||||
*/
|
||||
void add_node(const fc::ip::endpoint &ep);
|
||||
|
||||
/**
|
||||
* @brief Get status of all current connections to peers
|
||||
*/
|
||||
* @brief Get status of all current connections to peers
|
||||
*/
|
||||
std::vector<net::peer_status> get_connected_peers() const;
|
||||
|
||||
/**
|
||||
* @brief Get advanced node parameters, such as desired and max
|
||||
* number of connections
|
||||
*/
|
||||
* @brief Get advanced node parameters, such as desired and max
|
||||
* number of connections
|
||||
*/
|
||||
fc::variant_object get_advanced_node_parameters() const;
|
||||
|
||||
/**
|
||||
* @brief Set advanced node parameters, such as desired and max
|
||||
* number of connections
|
||||
* @param params a JSON object containing the name/value pairs for the parameters to set
|
||||
*/
|
||||
* @brief Set advanced node parameters, such as desired and max
|
||||
* number of connections
|
||||
* @param params a JSON object containing the name/value pairs for the parameters to set
|
||||
*/
|
||||
void set_advanced_node_parameters(const fc::variant_object ¶ms);
|
||||
|
||||
/**
|
||||
* @brief Return list of potential peers
|
||||
*/
|
||||
* @brief Return list of potential peers
|
||||
*/
|
||||
std::vector<net::potential_peer_record> get_potential_peers() const;
|
||||
|
||||
/**
|
||||
* @brief Return list of pending transactions.
|
||||
*/
|
||||
* @brief Return list of pending transactions.
|
||||
*/
|
||||
map<transaction_id_type, signed_transaction> list_pending_transactions() const;
|
||||
|
||||
/**
|
||||
* @brief Subscribes caller for notifications about pending transactions.
|
||||
* @param callback a functional object which will be called when new transaction is created.
|
||||
*/
|
||||
* @brief Subscribes caller for notifications about pending transactions.
|
||||
* @param callback a functional object which will be called when new transaction is created.
|
||||
*/
|
||||
void subscribe_to_pending_transactions(std::function<void(const variant &)> callback);
|
||||
|
||||
/**
|
||||
* @brief Unsubscribes caller from notifications about pending transactions.
|
||||
*/
|
||||
* @brief Unsubscribes caller from notifications about pending transactions.
|
||||
*/
|
||||
void unsubscribe_from_pending_transactions();
|
||||
|
||||
private:
|
||||
|
|
@ -290,33 +290,33 @@ private:
|
|||
};
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
* @brief
|
||||
*/
|
||||
class asset_api {
|
||||
public:
|
||||
asset_api(graphene::app::application &app);
|
||||
~asset_api();
|
||||
|
||||
/**
|
||||
* @brief Get asset holders for a specific asset
|
||||
* @param asset The specific asset id or symbol
|
||||
* @param start The start index
|
||||
* @param limit Maximum limit must not exceed 100
|
||||
* @return A list of asset holders for the specified asset
|
||||
*/
|
||||
* @brief Get asset holders for a specific asset
|
||||
* @param asset The specific asset id or symbol
|
||||
* @param start The start index
|
||||
* @param limit Maximum limit must not exceed 100
|
||||
* @return A list of asset holders for the specified asset
|
||||
*/
|
||||
vector<account_asset_balance> get_asset_holders(std::string asset, uint32_t start, uint32_t limit) const;
|
||||
|
||||
/**
|
||||
* @brief Get asset holders count for a specific asset
|
||||
* @param asset The specific asset id or symbol
|
||||
* @return Holders count for the specified asset
|
||||
*/
|
||||
* @brief Get asset holders count for a specific asset
|
||||
* @param asset The specific asset id or symbol
|
||||
* @return Holders count for the specified asset
|
||||
*/
|
||||
int get_asset_holders_count(std::string asset) const;
|
||||
|
||||
/**
|
||||
* @brief Get all asset holders
|
||||
* @return A list of all asset holders
|
||||
*/
|
||||
* @brief Get all asset holders
|
||||
* @return A list of all asset holders
|
||||
*/
|
||||
vector<asset_holders> get_all_asset_holders() const;
|
||||
|
||||
uint32_t api_limit_get_asset_holders = 100;
|
||||
|
|
@ -337,24 +337,24 @@ extern template class fc::api<graphene::debug_witness::debug_api>;
|
|||
|
||||
namespace graphene { namespace app {
|
||||
/**
|
||||
* @brief The login_api class implements the bottom layer of the RPC API
|
||||
*
|
||||
* All other APIs must be requested from this API.
|
||||
*/
|
||||
* @brief The login_api class implements the bottom layer of the RPC API
|
||||
*
|
||||
* All other APIs must be requested from this API.
|
||||
*/
|
||||
class login_api {
|
||||
public:
|
||||
login_api(application &a);
|
||||
~login_api();
|
||||
|
||||
/**
|
||||
* @brief Authenticate to the RPC server
|
||||
* @param user Username to login with
|
||||
* @param password Password to login with
|
||||
* @return True if logged in successfully; false otherwise
|
||||
*
|
||||
* @note This must be called prior to requesting other APIs. Other APIs may not be accessible until the client
|
||||
* has sucessfully authenticated.
|
||||
*/
|
||||
* @brief Authenticate to the RPC server
|
||||
* @param user Username to login with
|
||||
* @param password Password to login with
|
||||
* @return True if logged in successfully; false otherwise
|
||||
*
|
||||
* @note This must be called prior to requesting other APIs. Other APIs may not be accessible until the client
|
||||
* has sucessfully authenticated.
|
||||
*/
|
||||
bool login(const string &user, const string &password);
|
||||
/// @brief Retrieve the network block API
|
||||
fc::api<block_api> block() const;
|
||||
|
|
|
|||
|
|
@ -198,10 +198,10 @@ public:
|
|||
optional<block_header> get_block_header(uint32_t block_num) const;
|
||||
|
||||
/**
|
||||
* @brief Retrieve multiple block header by block numbers
|
||||
* @param block_num vector containing heights of the block whose header should be returned
|
||||
* @return array of headers of the referenced blocks, or null if no matching block was found
|
||||
*/
|
||||
* @brief Retrieve multiple block header by block numbers
|
||||
* @param block_num vector containing heights of the block whose header should be returned
|
||||
* @return array of headers of the referenced blocks, or null if no matching block was found
|
||||
*/
|
||||
map<uint32_t, optional<block_header>> get_block_header_batch(const vector<uint32_t> block_nums) const;
|
||||
|
||||
/**
|
||||
|
|
@ -279,12 +279,12 @@ public:
|
|||
vector<vector<account_id_type>> get_key_references(vector<public_key_type> key) const;
|
||||
|
||||
/**
|
||||
* Determine whether a textual representation of a public key
|
||||
* (in Base-58 format) is *currently* linked
|
||||
* to any *registered* (i.e. non-stealth) account on the blockchain
|
||||
* @param public_key Public key
|
||||
* @return Whether a public key is known
|
||||
*/
|
||||
* Determine whether a textual representation of a public key
|
||||
* (in Base-58 format) is *currently* linked
|
||||
* to any *registered* (i.e. non-stealth) account on the blockchain
|
||||
* @param public_key Public key
|
||||
* @return Whether a public key is known
|
||||
*/
|
||||
bool is_public_key_registered(string public_key) const;
|
||||
|
||||
//////////////
|
||||
|
|
|
|||
|
|
@ -152,7 +152,7 @@ void bitcoin_transaction_builder::add_in(payment_type type, tx_in txin, const by
|
|||
txin.scriptSig = script_code;
|
||||
break;
|
||||
default: {
|
||||
if (txin.prevout.hash == fc::sha256("0000000000000000000000000000000000000000000000000000000000000000")) { //coinbase
|
||||
if (txin.prevout.hash == fc::sha256("0000000000000000000000000000000000000000000000000000000000000000")) { // coinbase
|
||||
FC_ASSERT(script_code != bytes());
|
||||
txin.scriptSig = script_code;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
namespace graphene { namespace peerplays_sidechain {
|
||||
|
||||
libbitcoin_client::libbitcoin_client(std::string url) :
|
||||
libbitcoin_client::libbitcoin_client(const std::string &url) :
|
||||
obelisk_client(LIBBITCOIN_SERVER_TIMEOUT, LIBBITCOIN_SERVER_RETRIES) {
|
||||
|
||||
std::string reg_expr = "^((?P<Protocol>https|http|tcp):\\/\\/)?(?P<Host>[a-zA-Z0-9\\-\\.]+)(:(?P<Port>\\d{1,5}))?(?P<Target>\\/.+)?";
|
||||
|
|
@ -50,11 +50,19 @@ libbitcoin_client::libbitcoin_client(std::string url) :
|
|||
if (!obelisk_client.connect(connection)) {
|
||||
elog("Can't connect libbitcoin for url: ${url}", ("url", final_url));
|
||||
}
|
||||
|
||||
is_connected = true;
|
||||
}
|
||||
|
||||
std::string libbitcoin_client::send_transaction(std::string tx) {
|
||||
libbitcoin_client::~libbitcoin_client() {
|
||||
if (poller_trx_thr.joinable()) {
|
||||
stop_poller_trx_thread = true;
|
||||
poller_transacion_done.notify_all();
|
||||
poller_trx_thr.join();
|
||||
}
|
||||
stop = true;
|
||||
sub_thr.detach();
|
||||
}
|
||||
|
||||
std::string libbitcoin_client::send_transaction(const std::string &tx) {
|
||||
|
||||
std::string res;
|
||||
|
||||
|
|
@ -78,32 +86,45 @@ std::string libbitcoin_client::send_transaction(std::string tx) {
|
|||
return res;
|
||||
}
|
||||
|
||||
libbitcoin::chain::output::list libbitcoin_client::get_transaction(std::string tx_id, std::string &tx_hash, uint32_t &confirmitions) {
|
||||
|
||||
libbitcoin::chain::output::list outs;
|
||||
|
||||
bool libbitcoin_client::get_transaction(const std::string &tx, libbitcoin::chain::transaction &trx) {
|
||||
bool result = false;
|
||||
auto error_handler = [&](const std::error_code &ec) {
|
||||
elog("error on fetch_trx_by_hash: ${hash} ${error_code}", ("hash", tx_id)("error_code", ec.message()));
|
||||
elog("error on fetch_trx_by_hash: ${hash} ${error_code}", ("hash", tx)("error_code", ec.message()));
|
||||
result = false;
|
||||
};
|
||||
|
||||
auto transaction_handler = [&](const libbitcoin::chain::transaction &tx_handler) {
|
||||
tx_hash = libbitcoin::config::hash256(tx_handler.hash(false)).to_string();
|
||||
// TODO try to find this value (confirmitions)
|
||||
confirmitions = 1;
|
||||
outs = tx_handler.outputs();
|
||||
trx = tx_handler;
|
||||
result = true;
|
||||
};
|
||||
|
||||
libbitcoin::hash_digest hash = libbitcoin::config::hash256(tx_id);
|
||||
libbitcoin::hash_digest hash = libbitcoin::config::hash256(tx);
|
||||
|
||||
// obelisk_client.blockchain_fetch_transaction (error_handler, transaction_handler,hash);
|
||||
obelisk_client.blockchain_fetch_transaction2(error_handler, transaction_handler, hash);
|
||||
|
||||
obelisk_client.wait();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
libbitcoin::chain::output::list libbitcoin_client::get_transaction_outs(const std::string &tx_id, std::string &tx_hash, uint32_t &confirmitions) {
|
||||
|
||||
libbitcoin::chain::output::list outs;
|
||||
libbitcoin::chain::transaction trx;
|
||||
|
||||
if (get_transaction(tx_id, trx)) {
|
||||
|
||||
tx_hash = libbitcoin::config::hash256(trx.hash(false)).to_string();
|
||||
// TODO try to find this value (confirmitions)
|
||||
confirmitions = 1;
|
||||
outs = trx.outputs();
|
||||
}
|
||||
|
||||
return outs;
|
||||
}
|
||||
|
||||
std::vector<list_unspent_replay> libbitcoin_client::listunspent(std::string address, double amount) {
|
||||
std::vector<list_unspent_replay> libbitcoin_client::listunspent(const std::string &address, double amount) {
|
||||
std::vector<list_unspent_replay> result;
|
||||
|
||||
auto error_handler = [&](const std::error_code &ec) {
|
||||
|
|
@ -133,7 +154,9 @@ std::vector<list_unspent_replay> libbitcoin_client::listunspent(std::string addr
|
|||
|
||||
bool libbitcoin_client::get_is_test_net() {
|
||||
|
||||
bool result = false;
|
||||
if (is_test_net != -1) {
|
||||
return is_test_net;
|
||||
}
|
||||
|
||||
auto error_handler = [&](const std::error_code &ec) {
|
||||
elog("error on fetching genesis block ${error_code}", ("error_code", ec.message()));
|
||||
|
|
@ -142,17 +165,19 @@ bool libbitcoin_client::get_is_test_net() {
|
|||
auto block_header_handler = [&](const libbitcoin::chain::header &block_header) {
|
||||
std::string hash_str = libbitcoin::config::hash256(block_header.hash()).to_string();
|
||||
if (hash_str == GENESIS_TESTNET_HASH || hash_str == GENESIS_REGTEST_HASH) {
|
||||
result = true;
|
||||
is_test_net = 1;
|
||||
} else {
|
||||
is_test_net = 0;
|
||||
}
|
||||
};
|
||||
|
||||
obelisk_client.blockchain_fetch_block_header(error_handler, block_header_handler, 0);
|
||||
|
||||
obelisk_client.wait();
|
||||
return result;
|
||||
return is_test_net;
|
||||
}
|
||||
|
||||
uint64_t libbitcoin_client::get_fee_from_trx(libbitcoin::chain::transaction trx) {
|
||||
uint64_t libbitcoin_client::get_fee_from_trx(const libbitcoin::chain::transaction &trx) {
|
||||
bool general_fee_est_error = false;
|
||||
|
||||
if (trx.is_coinbase()) {
|
||||
|
|
@ -201,7 +226,7 @@ uint64_t libbitcoin_client::get_fee_from_trx(libbitcoin::chain::transaction trx)
|
|||
}
|
||||
}
|
||||
|
||||
uint64_t libbitcoin_client::get_average_fee_from_trxs(std::vector<libbitcoin::chain::transaction> trx_list) {
|
||||
uint64_t libbitcoin_client::get_average_fee_from_trxs(const std::vector<libbitcoin::chain::transaction> &trx_list) {
|
||||
std::vector<uint64_t> fee_per_trxs;
|
||||
|
||||
for (auto &trx : trx_list) {
|
||||
|
|
@ -224,4 +249,81 @@ uint64_t libbitcoin_client::get_average_fee_from_trxs(std::vector<libbitcoin::ch
|
|||
|
||||
return average_estimated_fee;
|
||||
}
|
||||
|
||||
void libbitcoin_client::subscribe_to_address(const std::string &address_str, address_update_handler address_updated_callback_handler,
|
||||
subscription_expired_handler subcription_expired_callback_handler) {
|
||||
|
||||
subscription_add = address_str;
|
||||
this->address_updated_callback_handler = address_updated_callback_handler;
|
||||
this->subcription_expired_callback_handler = subcription_expired_callback_handler;
|
||||
sub_thr = std::thread(&libbitcoin_client::subscription_thr, this);
|
||||
poller_trx_thr = std::thread(&libbitcoin_client::poller_transaction_thr, this);
|
||||
}
|
||||
|
||||
void libbitcoin_client::poller_transaction_thr() {
|
||||
std::unique_lock<std::mutex> lck(trxs_pool_mutex);
|
||||
|
||||
while (!stop_poller_trx_thread) {
|
||||
|
||||
libbitcoin::chain::transaction trx;
|
||||
if (!target_trxs_pool.empty() && get_transaction(libbitcoin::config::hash256(target_trxs_pool.back()).to_string(), trx)) {
|
||||
target_trxs_pool.pop_back();
|
||||
address_updated_callback_handler(trx, get_is_test_net());
|
||||
}
|
||||
|
||||
poller_transacion_done.wait_for(lck, std::chrono::minutes(1));
|
||||
}
|
||||
|
||||
wlog("Exit from poller_transaction_thr() ...");
|
||||
}
|
||||
|
||||
bool libbitcoin_client::is_target_trxs_pool_empty() {
|
||||
std::unique_lock<std::mutex> lck(trxs_pool_mutex);
|
||||
return target_trxs_pool.empty();
|
||||
}
|
||||
|
||||
void libbitcoin_client::subscription_thr() {
|
||||
|
||||
libbitcoin::wallet::payment_address address(subscription_add);
|
||||
|
||||
auto on_subscribed = [&](const std::error_code &error) {
|
||||
ilog("On subscribed ${error}", ("error", error.message()));
|
||||
};
|
||||
|
||||
auto on_error = [&](const std::error_code &error) {
|
||||
elog("On subscribed there is an error: ${error}", ("error", error.message()));
|
||||
};
|
||||
|
||||
auto on_update = [&](const std::error_code &error, uint16_t sequence, size_t height, const libbitcoin::hash_digest &tx_hash) {
|
||||
wlog("On update value error: ${error}", ("error", error.value()));
|
||||
if (!error.value()) {
|
||||
wlog("sequence: ${sequence}, height: ${height}, hash: ${hash}", ("sequence", sequence)("height", height)("hash", libbitcoin::config::hash256(tx_hash).to_string()));
|
||||
libbitcoin::chain::transaction trx;
|
||||
if (height == 0) {
|
||||
std::unique_lock<std::mutex> lck(trxs_pool_mutex);
|
||||
target_trxs_pool.emplace_back(tx_hash);
|
||||
} else if ((get_transaction(libbitcoin::config::hash256(tx_hash).to_string(), trx))) {
|
||||
address_updated_callback_handler(trx, get_is_test_net());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
obelisk_client.set_on_update(on_update);
|
||||
obelisk_client.subscribe_address(on_error, on_subscribed, address);
|
||||
obelisk_client.wait();
|
||||
|
||||
obelisk_client.monitor(SUBSCRIBE_TIME_DURATION);
|
||||
|
||||
if (poller_trx_thr.joinable()) {
|
||||
stop_poller_trx_thread = true;
|
||||
poller_transacion_done.notify_all();
|
||||
poller_trx_thr.join();
|
||||
}
|
||||
|
||||
if (!stop) {
|
||||
ilog("Subsription monitor expired, renew if needed ...");
|
||||
subcription_expired_callback_handler(subscription_add);
|
||||
}
|
||||
}
|
||||
|
||||
}} // namespace graphene::peerplays_sidechain
|
||||
|
|
@ -384,7 +384,7 @@ rpc_client::~rpc_client() {
|
|||
if (connection_selection_task.valid())
|
||||
connection_selection_task.cancel_and_wait(__FUNCTION__);
|
||||
} catch (fc::canceled_exception &) {
|
||||
//Expected exception. Move along.
|
||||
// Expected exception. Move along.
|
||||
} catch (fc::exception &e) {
|
||||
edump((e.to_detail_string()));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
#define DEAFULT_LIBBITCOIN_TRX_FEE (20000)
|
||||
#define MAX_TRXS_IN_MEMORY_POOL (30000)
|
||||
#define MIN_TRXS_IN_BUCKET (100)
|
||||
#define SUBSCRIBE_TIME_DURATION (30)
|
||||
|
||||
#define GENESIS_MAINNET_HASH "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"
|
||||
#define GENESIS_TESTNET_HASH "000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943"
|
||||
|
|
@ -19,8 +20,8 @@
|
|||
|
||||
namespace graphene { namespace peerplays_sidechain {
|
||||
|
||||
typedef std::function<void(const libbitcoin::chain::block &)>
|
||||
block_update_handler;
|
||||
using address_update_handler = std::function<void(const libbitcoin::chain::transaction &trx, const bool &is_test_net)>;
|
||||
using subscription_expired_handler = std::function<void(const std::string &)>;
|
||||
|
||||
struct list_unspent_replay {
|
||||
std::string hash;
|
||||
|
|
@ -30,24 +31,43 @@ struct list_unspent_replay {
|
|||
|
||||
class libbitcoin_client {
|
||||
public:
|
||||
libbitcoin_client(std::string url);
|
||||
std::string send_transaction(const std::string tx);
|
||||
libbitcoin::chain::output::list get_transaction(std::string tx_id, std::string &tx_hash, uint32_t &confirmitions);
|
||||
std::vector<list_unspent_replay> listunspent(std::string address, double amount);
|
||||
uint64_t get_average_fee_from_trxs(std::vector<libbitcoin::chain::transaction> trx_list);
|
||||
uint64_t get_fee_from_trx(libbitcoin::chain::transaction trx);
|
||||
explicit libbitcoin_client(const std::string &url);
|
||||
~libbitcoin_client();
|
||||
std::string send_transaction(const std::string &tx);
|
||||
bool get_transaction(const std::string &tx, libbitcoin::chain::transaction &trx);
|
||||
libbitcoin::chain::output::list get_transaction_outs(const std::string &tx_id, std::string &tx_hash, uint32_t &confirmitions);
|
||||
std::vector<list_unspent_replay> listunspent(const std::string &address, double amount);
|
||||
uint64_t get_average_fee_from_trxs(const std::vector<libbitcoin::chain::transaction> &trx_list);
|
||||
uint64_t get_fee_from_trx(const libbitcoin::chain::transaction &trx);
|
||||
bool get_is_test_net();
|
||||
void subscribe_to_address(const std::string &address_str, address_update_handler address_updated_callback_handler,
|
||||
subscription_expired_handler subcription_expired_callback_handler);
|
||||
bool is_target_trxs_pool_empty();
|
||||
|
||||
private:
|
||||
void subscription_thr();
|
||||
void poller_transaction_thr();
|
||||
|
||||
libbitcoin::client::obelisk_client obelisk_client;
|
||||
libbitcoin::protocol::zmq::identifier id;
|
||||
std::string subscription_add;
|
||||
address_update_handler address_updated_callback_handler;
|
||||
subscription_expired_handler subcription_expired_callback_handler;
|
||||
|
||||
std::string protocol;
|
||||
std::string host;
|
||||
std::string port;
|
||||
std::string url;
|
||||
|
||||
bool is_connected = false;
|
||||
std::vector<libbitcoin::hash_digest> target_trxs_pool;
|
||||
std::mutex trxs_pool_mutex;
|
||||
std::condition_variable poller_transacion_done;
|
||||
|
||||
int16_t is_test_net = -1;
|
||||
std::thread sub_thr;
|
||||
std::thread poller_trx_thr;
|
||||
bool stop = false;
|
||||
bool stop_poller_trx_thread = false;
|
||||
};
|
||||
|
||||
}} // namespace graphene::peerplays_sidechain
|
||||
|
|
@ -22,15 +22,15 @@ typedef fc::ecc::private_key private_key_type;
|
|||
typedef fc::sha256 chain_id_type;
|
||||
typedef std::string account_name_type;
|
||||
typedef fc::ripemd160 block_id_type;
|
||||
//typedef fc::ripemd160 checksum_type;
|
||||
// typedef fc::ripemd160 checksum_type;
|
||||
typedef fc::ripemd160 transaction_id_type;
|
||||
typedef fc::sha256 digest_type;
|
||||
typedef fc::ecc::compact_signature signature_type;
|
||||
typedef fc::safe<int64_t> share_type;
|
||||
//typedef safe<uint64_t> ushare_type;
|
||||
//typedef uint16_t weight_type;
|
||||
//typedef uint32_t contribution_id_type;
|
||||
//typedef fixed_string<32> custom_id_type;
|
||||
// typedef safe<uint64_t> ushare_type;
|
||||
// typedef uint16_t weight_type;
|
||||
// typedef uint32_t contribution_id_type;
|
||||
// typedef fixed_string<32> custom_id_type;
|
||||
|
||||
struct public_key_type {
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@
|
|||
|
||||
namespace graphene { namespace peerplays_sidechain {
|
||||
|
||||
#define SUBSCRIPTION_THREAD_INTERVAL (10000)
|
||||
|
||||
class btc_txout {
|
||||
public:
|
||||
std::string txid_;
|
||||
|
|
@ -63,6 +65,7 @@ public:
|
|||
std::string label;
|
||||
};
|
||||
|
||||
virtual ~bitcoin_client_base() = default;
|
||||
virtual uint64_t estimatesmartfee(uint16_t conf_target = 1) = 0;
|
||||
virtual std::vector<info_for_vin> getblock(const block_data &block, int32_t verbosity = 2) = 0;
|
||||
virtual btc_tx getrawtransaction(const std::string &txid, const bool verbose = false) = 0;
|
||||
|
|
@ -70,9 +73,7 @@ public:
|
|||
virtual std::string getblockchaininfo() = 0;
|
||||
virtual std::vector<btc_txout> listunspent_by_address_and_amount(const std::string &address, double transfer_amount, const uint32_t minconf = 1, const uint32_t maxconf = 9999999) = 0;
|
||||
virtual std::string sendrawtransaction(const std::string &tx_hex) = 0;
|
||||
virtual void importmulti(const std::vector<multi_params> &address_or_script_array, const bool rescan = true) {
|
||||
;
|
||||
};
|
||||
virtual void importmulti(const std::vector<multi_params> &address_or_script_array, const bool rescan = true){};
|
||||
virtual std::string loadwallet(const std::string &filename) {
|
||||
return "";
|
||||
};
|
||||
|
|
@ -100,20 +101,20 @@ public:
|
|||
public:
|
||||
bitcoin_rpc_client(const std::vector<rpc_credentials> &_credentials, bool _debug_rpc_calls, bool _simulate_connection_reselection);
|
||||
|
||||
uint64_t estimatesmartfee(uint16_t conf_target = 1);
|
||||
uint64_t estimatesmartfee(uint16_t conf_target = 1) final;
|
||||
std::vector<info_for_vin> getblock(const block_data &block, int32_t verbosity = 2);
|
||||
btc_tx getrawtransaction(const std::string &txid, const bool verbose = false);
|
||||
void getnetworkinfo();
|
||||
std::string getblockchaininfo();
|
||||
void importmulti(const std::vector<multi_params> &address_or_script_array, const bool rescan = true);
|
||||
btc_tx getrawtransaction(const std::string &txid, const bool verbose = false) final;
|
||||
void getnetworkinfo() final;
|
||||
std::string getblockchaininfo() final;
|
||||
void importmulti(const std::vector<multi_params> &address_or_script_array, const bool rescan = true) final;
|
||||
std::vector<btc_txout> listunspent(const uint32_t minconf = 1, const uint32_t maxconf = 9999999);
|
||||
std::vector<btc_txout> listunspent_by_address_and_amount(const std::string &address, double transfer_amount, const uint32_t minconf = 1, const uint32_t maxconf = 9999999);
|
||||
std::string loadwallet(const std::string &filename);
|
||||
std::string sendrawtransaction(const std::string &tx_hex);
|
||||
std::string walletlock();
|
||||
bool walletpassphrase(const std::string &passphrase, uint32_t timeout = 60);
|
||||
std::vector<btc_txout> listunspent_by_address_and_amount(const std::string &address, double transfer_amount, const uint32_t minconf = 1, const uint32_t maxconf = 9999999) final;
|
||||
std::string loadwallet(const std::string &filename) final;
|
||||
std::string sendrawtransaction(const std::string &tx_hex) final;
|
||||
std::string walletlock() final;
|
||||
bool walletpassphrase(const std::string &passphrase, uint32_t timeout = 60) final;
|
||||
|
||||
virtual uint64_t ping(rpc_connection &conn) const override;
|
||||
uint64_t ping(rpc_connection &conn) const final;
|
||||
|
||||
private:
|
||||
std::string ip;
|
||||
|
|
@ -126,14 +127,14 @@ private:
|
|||
|
||||
class bitcoin_libbitcoin_client : public bitcoin_client_base, public libbitcoin_client {
|
||||
public:
|
||||
bitcoin_libbitcoin_client(std::string url);
|
||||
uint64_t estimatesmartfee(uint16_t conf_target = 1);
|
||||
explicit bitcoin_libbitcoin_client(const std::string &url);
|
||||
uint64_t estimatesmartfee(uint16_t conf_target = 1) final;
|
||||
std::vector<info_for_vin> getblock(const block_data &block, int32_t verbosity = 2);
|
||||
btc_tx getrawtransaction(const std::string &txid, const bool verbose = false);
|
||||
void getnetworkinfo();
|
||||
std::string getblockchaininfo();
|
||||
std::vector<btc_txout> listunspent_by_address_and_amount(const std::string &address, double transfer_amount, const uint32_t minconf = 1, const uint32_t maxconf = 9999999);
|
||||
std::string sendrawtransaction(const std::string &tx_hex);
|
||||
btc_tx getrawtransaction(const std::string &txid, const bool verbose = false) final;
|
||||
void getnetworkinfo() final;
|
||||
std::string getblockchaininfo() final;
|
||||
std::vector<btc_txout> listunspent_by_address_and_amount(const std::string &address, double transfer_amount, const uint32_t minconf = 1, const uint32_t maxconf = 9999999) final;
|
||||
std::string sendrawtransaction(const std::string &tx_hex) final;
|
||||
|
||||
private:
|
||||
bool is_test_net = false;
|
||||
|
|
@ -145,13 +146,11 @@ private:
|
|||
|
||||
class zmq_listener_base {
|
||||
public:
|
||||
virtual ~zmq_listener_base(){};
|
||||
zmq_listener_base(std::string _ip, uint32_t _block_zmq_port, uint32_t _trx_zmq_port = 0) {
|
||||
ip = _ip;
|
||||
block_zmq_port = _block_zmq_port;
|
||||
trx_zmq_port = _trx_zmq_port;
|
||||
stopped = false;
|
||||
};
|
||||
virtual ~zmq_listener_base() = default;
|
||||
zmq_listener_base(const std::string &_ip, uint32_t _block_zmq_port, uint32_t _trx_zmq_port = 0) :
|
||||
ip(_ip),
|
||||
block_zmq_port(_block_zmq_port),
|
||||
trx_zmq_port(_trx_zmq_port){};
|
||||
virtual void start() = 0;
|
||||
boost::signals2::signal<void(const block_data &)> block_event_received;
|
||||
boost::signals2::signal<void(const libbitcoin::chain::transaction &)> trx_event_received;
|
||||
|
|
@ -160,16 +159,16 @@ protected:
|
|||
std::string ip;
|
||||
uint32_t block_zmq_port;
|
||||
uint32_t trx_zmq_port;
|
||||
std::atomic_bool stopped;
|
||||
std::atomic_bool stopped{false};
|
||||
std::thread block_thr;
|
||||
std::thread trx_thr;
|
||||
};
|
||||
|
||||
class zmq_listener : public zmq_listener_base {
|
||||
public:
|
||||
zmq_listener(std::string _ip, uint32_t _block_zmq_port, uint32_t _trx_zmq_port = 0);
|
||||
virtual ~zmq_listener();
|
||||
void start();
|
||||
zmq_listener(const std::string &_ip, uint32_t _block_zmq_port, uint32_t _trx_zmq_port = 0);
|
||||
~zmq_listener() final;
|
||||
void start() final;
|
||||
|
||||
private:
|
||||
void handle_zmq();
|
||||
|
|
@ -181,9 +180,9 @@ private:
|
|||
|
||||
class zmq_listener_libbitcoin : public zmq_listener_base {
|
||||
public:
|
||||
zmq_listener_libbitcoin(std::string _ip, uint32_t _block_zmq_port = 9093, uint32_t _trx_zmq_port = 9094);
|
||||
virtual ~zmq_listener_libbitcoin();
|
||||
void start();
|
||||
zmq_listener_libbitcoin(const std::string &_ip, uint32_t _block_zmq_port = 9093, uint32_t _trx_zmq_port = 9094);
|
||||
~zmq_listener_libbitcoin() final;
|
||||
void start() final;
|
||||
|
||||
private:
|
||||
void handle_block();
|
||||
|
|
@ -232,7 +231,7 @@ private:
|
|||
uint32_t bitcoin_major_version;
|
||||
|
||||
std::mutex event_handler_mutex;
|
||||
typedef std::lock_guard<decltype(event_handler_mutex)> scoped_lock;
|
||||
using scoped_lock = std::lock_guard<decltype(event_handler_mutex)>;
|
||||
|
||||
std::string create_primary_wallet_address(const std::vector<son_sidechain_info> &son_pubkeys);
|
||||
|
||||
|
|
@ -244,11 +243,21 @@ private:
|
|||
std::string sign_transaction(const sidechain_transaction_object &sto);
|
||||
std::string send_transaction(const sidechain_transaction_object &sto);
|
||||
|
||||
void extract_deposit(const std::vector<info_for_vin> &vins);
|
||||
void block_handle_event(const block_data &event_data);
|
||||
void subscribe_address_thread();
|
||||
void trx_handle_event(const libbitcoin::chain::transaction &event_data);
|
||||
void subscription_expired_event(const std::string &address);
|
||||
std::string get_redeemscript_for_userdeposit(const std::string &user_address);
|
||||
void on_changed_objects(const vector<object_id_type> &ids, const flat_set<account_id_type> &accounts);
|
||||
void on_changed_objects_cb(const vector<object_id_type> &ids, const flat_set<account_id_type> &accounts);
|
||||
|
||||
std::map<std::string, std::pair<std::unique_ptr<libbitcoin_client>, bool>> libbitcoin_clients;
|
||||
void trx_event(const libbitcoin::chain::transaction &trx, const bool &is_test_net);
|
||||
|
||||
bool stop_sub_thr = true;
|
||||
|
||||
std::thread subscribe_thr;
|
||||
};
|
||||
|
||||
}} // namespace graphene::peerplays_sidechain
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ peerplays_sidechain_plugin_impl::~peerplays_sidechain_plugin_impl() {
|
|||
if (_heartbeat_task.valid())
|
||||
_heartbeat_task.cancel_and_wait(__FUNCTION__);
|
||||
} catch (fc::canceled_exception &) {
|
||||
//Expected exception. Move along.
|
||||
// Expected exception. Move along.
|
||||
} catch (fc::exception &e) {
|
||||
edump((e.to_detail_string()));
|
||||
}
|
||||
|
|
@ -156,7 +156,7 @@ peerplays_sidechain_plugin_impl::~peerplays_sidechain_plugin_impl() {
|
|||
_son_processing_task.at(active_sidechain_type).wait();
|
||||
}
|
||||
} catch (fc::canceled_exception &) {
|
||||
//Expected exception. Move along.
|
||||
// Expected exception. Move along.
|
||||
} catch (fc::exception &e) {
|
||||
edump((e.to_detail_string()));
|
||||
}
|
||||
|
|
@ -540,11 +540,11 @@ void peerplays_sidechain_plugin_impl::son_processing(sidechain_type sidechain) {
|
|||
return;
|
||||
}
|
||||
|
||||
//fc::time_point now_fine = fc::time_point::now();
|
||||
//fc::time_point_sec now = now_fine + fc::microseconds(500000);
|
||||
//if (plugin.database().get_slot_time(1) < now) {
|
||||
// return; // Not synced
|
||||
//}
|
||||
// fc::time_point now_fine = fc::time_point::now();
|
||||
// fc::time_point_sec now = now_fine + fc::microseconds(500000);
|
||||
// if (plugin.database().get_slot_time(1) < now) {
|
||||
// return; // Not synced
|
||||
// }
|
||||
|
||||
const fc::time_point now_fine = fc::time_point::now();
|
||||
const fc::time_point_sec now = now_fine - fc::milliseconds(3000);
|
||||
|
|
@ -873,15 +873,12 @@ void peerplays_sidechain_plugin_impl::settle_sidechain_transactions(sidechain_ty
|
|||
|
||||
void peerplays_sidechain_plugin_impl::on_applied_block(const signed_block &b) {
|
||||
if (first_block_skipped) {
|
||||
if(son_processing_enabled) {
|
||||
if (son_processing_enabled) {
|
||||
schedule_son_processing();
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
const fc::time_point now_fine = fc::time_point::now();
|
||||
const fc::time_point_sec now = now_fine + fc::microseconds( 500000 );
|
||||
if( plugin.database().get_slot_time(1) >= now )
|
||||
{
|
||||
const fc::time_point_sec now = now_fine + fc::microseconds(500000);
|
||||
if (plugin.database().get_slot_time(1) >= now) {
|
||||
son_processing_enabled = true;
|
||||
schedule_son_processing();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -184,11 +184,11 @@ void sidechain_net_handler::sidechain_event_data_received(const sidechain_event_
|
|||
|
||||
bool enable_peerplays_asset_deposits = false;
|
||||
#ifdef ENABLE_PEERPLAYS_ASSET_DEPOSITS
|
||||
//enable_peerplays_asset_deposits = (sed.sidechain == sidechain_type::peerplays) &&
|
||||
// (sed.sidechain_currency.compare("BTC") != 0) &&
|
||||
// (sed.sidechain_currency.compare("ETH") != 0) &&
|
||||
// (sed.sidechain_currency.compare("HBD") != 0) &&
|
||||
// (sed.sidechain_currency.compare("HIVE") != 0);
|
||||
// enable_peerplays_asset_deposits = (sed.sidechain == sidechain_type::peerplays) &&
|
||||
// (sed.sidechain_currency.compare("BTC") != 0) &&
|
||||
// (sed.sidechain_currency.compare("ETH") != 0) &&
|
||||
// (sed.sidechain_currency.compare("HBD") != 0) &&
|
||||
// (sed.sidechain_currency.compare("HIVE") != 0);
|
||||
#endif
|
||||
|
||||
const bool deposit_condition = (sed.peerplays_to == gpo.parameters.son_account()) &&
|
||||
|
|
@ -451,7 +451,7 @@ void sidechain_net_handler::process_deposits() {
|
|||
if (swdo.id == object_id_type(0, 0, 0) || !plugin.can_son_participate(sidechain, chain::operation::tag<chain::son_wallet_deposit_process_operation>::value, swdo.id)) {
|
||||
return;
|
||||
}
|
||||
//Ignore the deposits which are not valid anymore, considered refunds.
|
||||
// Ignore the deposits which are not valid anymore, considered refunds.
|
||||
const auto &sidechain_addresses_idx = database.get_index_type<sidechain_address_index>().indices().get<by_sidechain_and_deposit_address_and_expires>();
|
||||
const auto &addr_itr = sidechain_addresses_idx.find(std::make_tuple(sidechain, swdo.sidechain_from, time_point_sec::maximum()));
|
||||
if (addr_itr == sidechain_addresses_idx.end()) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#include <graphene/peerplays_sidechain/sidechain_net_handler_bitcoin.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <thread>
|
||||
|
||||
#include <boost/algorithm/hex.hpp>
|
||||
#include <boost/property_tree/json_parser.hpp>
|
||||
|
|
@ -332,7 +333,7 @@ bool bitcoin_rpc_client::walletpassphrase(const std::string &passphrase, uint32_
|
|||
else
|
||||
return true;
|
||||
}
|
||||
bitcoin_libbitcoin_client::bitcoin_libbitcoin_client(std::string url) :
|
||||
bitcoin_libbitcoin_client::bitcoin_libbitcoin_client(const std::string &url) :
|
||||
libbitcoin_client(url) {
|
||||
|
||||
estimate_fee_ext = std::unique_ptr<estimate_fee_external>(new estimate_fee_external());
|
||||
|
|
@ -426,7 +427,7 @@ btc_tx bitcoin_libbitcoin_client::getrawtransaction(const std::string &txid, con
|
|||
std::string tx_hash;
|
||||
uint32_t confirmitions;
|
||||
|
||||
libbitcoin::chain::output::list outs = get_transaction(txid, tx_hash, confirmitions);
|
||||
libbitcoin::chain::output::list outs = get_transaction_outs(txid, tx_hash, confirmitions);
|
||||
|
||||
if (tx_hash.empty()) {
|
||||
return tx;
|
||||
|
|
@ -507,7 +508,7 @@ uint64_t bitcoin_rpc_client::ping(rpc_connection &conn) const {
|
|||
|
||||
// =============================================================================
|
||||
|
||||
zmq_listener::zmq_listener(std::string _ip, uint32_t _zmq_block_port, uint32_t _zmq_trx_port) :
|
||||
zmq_listener::zmq_listener(const std::string &_ip, uint32_t _zmq_block_port, uint32_t _zmq_trx_port) :
|
||||
zmq_listener_base(_ip, _zmq_block_port, _zmq_trx_port),
|
||||
ctx(1),
|
||||
socket(ctx, ZMQ_SUB) {
|
||||
|
|
@ -577,7 +578,7 @@ void zmq_listener::handle_zmq() {
|
|||
|
||||
// =============================================================================
|
||||
|
||||
zmq_listener_libbitcoin::zmq_listener_libbitcoin(std::string _ip, uint32_t _block_zmq_port, uint32_t _trx_zmq_port) :
|
||||
zmq_listener_libbitcoin::zmq_listener_libbitcoin(const std::string &_ip, uint32_t _block_zmq_port, uint32_t _trx_zmq_port) :
|
||||
zmq_listener_base(_ip, _block_zmq_port, _trx_zmq_port),
|
||||
block_socket(block_context, libbitcoin::protocol::zmq::socket::role::subscriber),
|
||||
trx_socket(trx_context, libbitcoin::protocol::zmq::socket::role::subscriber) {
|
||||
|
|
@ -726,10 +727,19 @@ sidechain_net_handler_bitcoin::sidechain_net_handler_bitcoin(peerplays_sidechain
|
|||
}
|
||||
|
||||
listener = std::unique_ptr<zmq_listener>(new zmq_listener(ips[0], bitcoin_node_zmq_port));
|
||||
listener->block_event_received.connect([this](const block_data &block_event_data) {
|
||||
std::thread(&sidechain_net_handler_bitcoin::block_handle_event, this, block_event_data).detach();
|
||||
});
|
||||
|
||||
listener->trx_event_received.connect([this](const libbitcoin::chain::transaction &trx_event_data) {
|
||||
std::thread(&sidechain_net_handler_bitcoin::trx_handle_event, this, trx_event_data).detach();
|
||||
});
|
||||
|
||||
listener->start();
|
||||
} else {
|
||||
bitcoin_client = std::unique_ptr<bitcoin_libbitcoin_client>(new bitcoin_libbitcoin_client(libbitcoin_server_ip));
|
||||
|
||||
listener = std::unique_ptr<zmq_listener_libbitcoin>(new zmq_listener_libbitcoin(libbitcoin_server_ip, libbitcoin_block_zmq_port, libbitcoin_trx_zmq_port));
|
||||
stop_sub_thr = false;
|
||||
subscribe_thr = std::thread(&sidechain_net_handler_bitcoin::subscribe_address_thread, this);
|
||||
}
|
||||
|
||||
std::string chain_info = bitcoin_client->getblockchaininfo();
|
||||
|
|
@ -745,16 +755,6 @@ sidechain_net_handler_bitcoin::sidechain_net_handler_bitcoin(peerplays_sidechain
|
|||
|
||||
bitcoin_client->getnetworkinfo();
|
||||
|
||||
listener->block_event_received.connect([this](const block_data &block_event_data) {
|
||||
std::thread(&sidechain_net_handler_bitcoin::block_handle_event, this, block_event_data).detach();
|
||||
});
|
||||
|
||||
listener->trx_event_received.connect([this](const libbitcoin::chain::transaction &trx_event_data) {
|
||||
std::thread(&sidechain_net_handler_bitcoin::trx_handle_event, this, trx_event_data).detach();
|
||||
});
|
||||
|
||||
listener->start();
|
||||
|
||||
database.changed_objects.connect([this](const vector<object_id_type> &ids, const flat_set<account_id_type> &accounts) {
|
||||
on_changed_objects(ids, accounts);
|
||||
});
|
||||
|
|
@ -765,6 +765,11 @@ sidechain_net_handler_bitcoin::~sidechain_net_handler_bitcoin() {
|
|||
if (on_changed_objects_task.valid()) {
|
||||
on_changed_objects_task.cancel_and_wait(__FUNCTION__);
|
||||
}
|
||||
|
||||
if (subscribe_thr.joinable()) {
|
||||
stop_sub_thr = true;
|
||||
subscribe_thr.join();
|
||||
}
|
||||
} catch (fc::canceled_exception &) {
|
||||
// Expected exception. Move along.
|
||||
} catch (fc::exception &e) {
|
||||
|
|
@ -1655,15 +1660,84 @@ std::string sidechain_net_handler_bitcoin::send_transaction(const sidechain_tran
|
|||
return tx.get_txid().str();
|
||||
}
|
||||
|
||||
void sidechain_net_handler_bitcoin::block_handle_event(const block_data &event_data) {
|
||||
void sidechain_net_handler_bitcoin::subscribe_address_thread() {
|
||||
while (!stop_sub_thr) {
|
||||
const auto &sidechain_addresses_idx = database.get_index_type<sidechain_address_index>();
|
||||
const auto &sidechain_addresses_by_sidechain_idx = sidechain_addresses_idx.indices().get<by_sidechain>();
|
||||
const auto &sidechain_addresses_by_sidechain_range = sidechain_addresses_by_sidechain_idx.equal_range(sidechain);
|
||||
std::for_each(sidechain_addresses_by_sidechain_range.first, sidechain_addresses_by_sidechain_range.second,
|
||||
[&](const sidechain_address_object &sao) {
|
||||
scoped_lock interlock(event_handler_mutex);
|
||||
if (!sao.deposit_address.empty() && (!libbitcoin_clients[sao.deposit_address].first || !libbitcoin_clients[sao.deposit_address].second)) {
|
||||
|
||||
auto vins = bitcoin_client->getblock(event_data);
|
||||
if (sao.expires > database.head_block_time()) {
|
||||
if (!libbitcoin_clients[sao.deposit_address].first) {
|
||||
libbitcoin_clients[sao.deposit_address] = std::make_pair(std::unique_ptr<libbitcoin_client>(new libbitcoin_client(libbitcoin_server_ip)), true);
|
||||
}
|
||||
|
||||
add_to_son_listener_log("BLOCK : " + event_data.block_hash);
|
||||
auto trx_event_callback = std::bind(&sidechain_net_handler_bitcoin::trx_event, this, std::placeholders::_1, std::placeholders::_2);
|
||||
auto sub_expired_callback = std::bind(&sidechain_net_handler_bitcoin::subscription_expired_event, this, std::placeholders::_1);
|
||||
libbitcoin_clients[sao.deposit_address].first->subscribe_to_address(sao.deposit_address, trx_event_callback, sub_expired_callback);
|
||||
libbitcoin_clients[sao.deposit_address].second = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(SUBSCRIPTION_THREAD_INTERVAL));
|
||||
}
|
||||
|
||||
ilog("Exit from subsription thread ....");
|
||||
}
|
||||
|
||||
void sidechain_net_handler_bitcoin::subscription_expired_event(const std::string &address) {
|
||||
scoped_lock interlock(event_handler_mutex);
|
||||
const auto &sidechain_addresses_idx = database.get_index_type<sidechain_address_index>().indices().get<by_sidechain_and_deposit_address_and_expires>();
|
||||
if (libbitcoin_clients[address].first && libbitcoin_clients[address].first->is_target_trxs_pool_empty()) {
|
||||
libbitcoin_clients.erase(address);
|
||||
libbitcoin_clients[address].first = nullptr;
|
||||
} else {
|
||||
libbitcoin_clients[address].second = false;
|
||||
}
|
||||
}
|
||||
|
||||
void sidechain_net_handler_bitcoin::trx_event(const libbitcoin::chain::transaction &trx, const bool &is_test_net) {
|
||||
scoped_lock interlock(event_handler_mutex);
|
||||
std::vector<info_for_vin> result;
|
||||
uint32_t vout_seq = 0;
|
||||
for (const auto &o : trx.outputs()) {
|
||||
std::vector<std::string> address_list;
|
||||
|
||||
libbitcoin::wallet::payment_address::list addresses;
|
||||
if (is_test_net) {
|
||||
addresses = o.addresses(libbitcoin::wallet::payment_address::testnet_p2kh,
|
||||
libbitcoin::wallet::payment_address::testnet_p2sh);
|
||||
} else {
|
||||
addresses = o.addresses();
|
||||
}
|
||||
|
||||
for (auto &payment_address : addresses) {
|
||||
std::stringstream ss;
|
||||
ss << payment_address;
|
||||
address_list.emplace_back(ss.str());
|
||||
}
|
||||
|
||||
// addres list consists usual of one element
|
||||
for (auto &address : address_list) {
|
||||
const auto address_base58 = address;
|
||||
info_for_vin vin;
|
||||
vin.out.hash_tx = libbitcoin::config::hash256(trx.hash()).to_string();
|
||||
vin.out.amount = std::floor(o.value());
|
||||
vin.out.n_vout = vout_seq;
|
||||
vin.address = address_base58;
|
||||
result.push_back(vin);
|
||||
}
|
||||
vout_seq++;
|
||||
}
|
||||
|
||||
extract_deposit(result);
|
||||
}
|
||||
|
||||
void sidechain_net_handler_bitcoin::extract_deposit(const std::vector<info_for_vin> &vins) {
|
||||
const auto &sidechain_addresses_idx = database.get_index_type<sidechain_address_index>().indices().get<by_sidechain_and_deposit_address_and_expires>();
|
||||
for (const auto &v : vins) {
|
||||
// !!! EXTRACT DEPOSIT ADDRESS FROM SIDECHAIN ADDRESS OBJECT
|
||||
const auto &addr_itr = sidechain_addresses_idx.find(std::make_tuple(sidechain, v.address, time_point_sec::maximum()));
|
||||
|
|
@ -1697,6 +1771,13 @@ void sidechain_net_handler_bitcoin::block_handle_event(const block_data &event_d
|
|||
}
|
||||
}
|
||||
|
||||
void sidechain_net_handler_bitcoin::block_handle_event(const block_data &event_data) {
|
||||
auto vins = bitcoin_client->getblock(event_data);
|
||||
add_to_son_listener_log("BLOCK : " + event_data.block_hash);
|
||||
scoped_lock interlock(event_handler_mutex);
|
||||
extract_deposit(vins);
|
||||
}
|
||||
|
||||
void sidechain_net_handler_bitcoin::trx_handle_event(const libbitcoin::chain::transaction &trx_data) {
|
||||
bitcoin_client->import_trx_to_memory_pool(trx_data);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -757,8 +757,8 @@ bool sidechain_net_handler_ethereum::settle_sidechain_transaction(const sidechai
|
|||
if ("0x1" == json_receipt.get<std::string>("result.status")) {
|
||||
count += 1;
|
||||
//! Fixme - compare data somehow?
|
||||
//if( sto.transaction == entry_receipt.second.get<std::string>("data") ) {
|
||||
//}
|
||||
// if( sto.transaction == entry_receipt.second.get<std::string>("data") ) {
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -858,14 +858,14 @@ bool sidechain_net_handler_hive::settle_sidechain_transaction(const sidechain_tr
|
|||
boost::property_tree::ptree tx_json;
|
||||
boost::property_tree::read_json(ss_tx, tx_json);
|
||||
|
||||
//const chain::global_property_object &gpo = database.get_global_properties();
|
||||
// const chain::global_property_object &gpo = database.get_global_properties();
|
||||
|
||||
std::string tx_txid = tx_json.get<std::string>("result.transaction_id");
|
||||
uint32_t tx_block_num = tx_json.get<uint32_t>("result.block_num");
|
||||
const uint32_t last_irreversible_block = std::stoul(rpc_client->get_last_irreversible_block_num());
|
||||
|
||||
//std::string tx_address = addr.get_address();
|
||||
//int64_t tx_amount = -1;
|
||||
// std::string tx_address = addr.get_address();
|
||||
// int64_t tx_amount = -1;
|
||||
|
||||
if (tx_block_num <= last_irreversible_block) {
|
||||
if (sto.object_id.is<son_wallet_withdraw_id_type>()) {
|
||||
|
|
@ -918,15 +918,15 @@ void sidechain_net_handler_hive::hive_listener_loop() {
|
|||
}
|
||||
}
|
||||
|
||||
//std::string reply = rpc_client->get_last_irreversible_block_num();
|
||||
//if (!reply.empty()) {
|
||||
// uint64_t last_irreversible_block = std::stoul(reply);
|
||||
// if (last_irreversible_block != last_block_received) {
|
||||
// std::string event_data = std::to_string(last_irreversible_block);
|
||||
// handle_event(event_data);
|
||||
// last_block_received = last_irreversible_block;
|
||||
// }
|
||||
//}
|
||||
// std::string reply = rpc_client->get_last_irreversible_block_num();
|
||||
// if (!reply.empty()) {
|
||||
// uint64_t last_irreversible_block = std::stoul(reply);
|
||||
// if (last_irreversible_block != last_block_received) {
|
||||
// std::string event_data = std::to_string(last_irreversible_block);
|
||||
// handle_event(event_data);
|
||||
// last_block_received = last_irreversible_block;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
void sidechain_net_handler_hive::handle_event(const std::string &event_data) {
|
||||
|
|
@ -960,7 +960,7 @@ void sidechain_net_handler_hive::handle_event(const std::string &event_data) {
|
|||
const auto &amount_child = op_value.get_child("amount");
|
||||
|
||||
uint64_t amount = amount_child.get<uint64_t>("amount");
|
||||
//uint64_t precision = amount_child.get<uint64_t>("precision");
|
||||
// uint64_t precision = amount_child.get<uint64_t>("precision");
|
||||
std::string nai = amount_child.get<std::string>("nai");
|
||||
std::string sidechain_currency = "";
|
||||
price sidechain_currency_price = {};
|
||||
|
|
|
|||
|
|
@ -24,15 +24,15 @@ namespace graphene { namespace peerplays_sidechain {
|
|||
|
||||
sidechain_net_handler_peerplays::sidechain_net_handler_peerplays(peerplays_sidechain_plugin &_plugin, const boost::program_options::variables_map &options) :
|
||||
sidechain_net_handler(sidechain_type::peerplays, _plugin, options) {
|
||||
//const auto &assets_by_symbol = database.get_index_type<asset_index>().indices().get<by_symbol>();
|
||||
//const auto get_asset_id = [&assets_by_symbol](const string &symbol) {
|
||||
// auto asset_itr = assets_by_symbol.find(symbol);
|
||||
// FC_ASSERT(asset_itr != assets_by_symbol.end(), "Unable to find asset '${sym}'", ("sym", symbol));
|
||||
// return asset_itr->get_id();
|
||||
//};
|
||||
//tracked_assets.push_back(get_asset_id("PBTC"));
|
||||
//tracked_assets.push_back(get_asset_id("PETH"));
|
||||
//tracked_assets.push_back(get_asset_id("PEOS"));
|
||||
// const auto &assets_by_symbol = database.get_index_type<asset_index>().indices().get<by_symbol>();
|
||||
// const auto get_asset_id = [&assets_by_symbol](const string &symbol) {
|
||||
// auto asset_itr = assets_by_symbol.find(symbol);
|
||||
// FC_ASSERT(asset_itr != assets_by_symbol.end(), "Unable to find asset '${sym}'", ("sym", symbol));
|
||||
// return asset_itr->get_id();
|
||||
// };
|
||||
// tracked_assets.push_back(get_asset_id("PBTC"));
|
||||
// tracked_assets.push_back(get_asset_id("PETH"));
|
||||
// tracked_assets.push_back(get_asset_id("PEOS"));
|
||||
|
||||
if (options.count("peerplays-private-key")) {
|
||||
const std::vector<std::string> pub_priv_keys = options["peerplays-private-key"].as<std::vector<std::string>>();
|
||||
|
|
@ -284,8 +284,8 @@ bool sidechain_net_handler_peerplays::settle_sidechain_transaction(const sidecha
|
|||
}
|
||||
|
||||
if (sto.object_id.is<son_wallet_deposit_id_type>()) {
|
||||
//auto swdo = database.get<son_wallet_deposit_object>(sto.object_id);
|
||||
//settle_amount = asset(swdo.sidechain_amount, swdo.sidechain_currency);
|
||||
// auto swdo = database.get<son_wallet_deposit_object>(sto.object_id);
|
||||
// settle_amount = asset(swdo.sidechain_amount, swdo.sidechain_currency);
|
||||
}
|
||||
|
||||
if (sto.object_id.is<son_wallet_withdraw_id_type>()) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue