From ff576535848be7ead804f7db288a79bf9eb9e591 Mon Sep 17 00:00:00 2001 From: Alexander Suslikov Date: Thu, 31 Jan 2019 15:45:20 +0300 Subject: [PATCH] Filled update_tx_approvals in sidechain_net_manager --- .../chain/include/graphene/chain/config.hpp | 1 + .../bitcoin_transaction_confirmations.hpp | 13 +- .../sidechain/sidechain_parameters.hpp | 2 + .../sidechain/network/bitcoin_rpc_client.cpp | 24 ++- .../sidechain/network/bitcoin_rpc_client.hpp | 2 +- .../network/sidechain_net_manager.hpp | 2 + .../network/sidechain_net_manager.cpp | 141 ++++++++++-------- 7 files changed, 111 insertions(+), 74 deletions(-) diff --git a/libraries/chain/include/graphene/chain/config.hpp b/libraries/chain/include/graphene/chain/config.hpp index 7affde31..db7e390c 100644 --- a/libraries/chain/include/graphene/chain/config.hpp +++ b/libraries/chain/include/graphene/chain/config.hpp @@ -234,6 +234,7 @@ #define SIDECHAIN_MAX_SHARE_SUPPLY int64_t(21000000ll * 100000000ll) #define SIDECHAIN_DEFAULT_NUMBER_UNCONFIRMED_VINS 25 #define SIDECHAIN_DEFAULT_NUMBER_SIG_MULTISIG 5 +#define SIDECHAIN_DEFAULT_NUMBER_OF_CONFIRMATIONS 6 #define SIDECHAIN_DEFAULT_CONDENSING_TX_VINS_NUMBER 5 #define SIDECHAIN_DEFAULT_CONDENSING_TX_VOUTS_NUMBER 5 #define SIDECHAIN_DEFAULT_PERCENTAGE_PAYMENT_TO_WIT 0.001 diff --git a/libraries/sidechain/include/sidechain/bitcoin_transaction_confirmations.hpp b/libraries/sidechain/include/sidechain/bitcoin_transaction_confirmations.hpp index 95e32c45..35ef7ec8 100644 --- a/libraries/sidechain/include/sidechain/bitcoin_transaction_confirmations.hpp +++ b/libraries/sidechain/include/sidechain/bitcoin_transaction_confirmations.hpp @@ -16,23 +16,24 @@ namespace graphene { namespace chain { class database; } } namespace sidechain { -struct btc_tx_confirmations +struct bitcoin_transaction_confirmations { - btc_tx_confirmations() = default; + bitcoin_transaction_confirmations() = default; - btc_tx_confirmations( fc::sha256 trx_id ) : transaction_id( trx_id ) {} + bitcoin_transaction_confirmations( fc::sha256 trx_id ) : transaction_id( trx_id ) {} fc::sha256 transaction_id; - uint64_t count_blocks = 0; + uint64_t count_block = 0; bool confirmed = false; + bool missing = false; }; struct by_hash; -using btc_tx_confirmations_index = boost::multi_index_container, member> + ordered_unique, member> > >; diff --git a/libraries/sidechain/include/sidechain/sidechain_parameters.hpp b/libraries/sidechain/include/sidechain/sidechain_parameters.hpp index 0d67963c..b0b540dc 100644 --- a/libraries/sidechain/include/sidechain/sidechain_parameters.hpp +++ b/libraries/sidechain/include/sidechain/sidechain_parameters.hpp @@ -8,6 +8,7 @@ namespace sidechain { uint8_t multisig_sigs_num = SIDECHAIN_DEFAULT_NUMBER_SIG_MULTISIG; uint8_t condensing_tx_vins_num = SIDECHAIN_DEFAULT_CONDENSING_TX_VINS_NUMBER; uint8_t condensing_tx_vouts_num = SIDECHAIN_DEFAULT_CONDENSING_TX_VOUTS_NUMBER; + uint8_t confirmations_num = SIDECHAIN_DEFAULT_NUMBER_OF_CONFIRMATIONS; graphene::chain::account_id_type managing_account; graphene::chain::asset_id_type asset_id; @@ -19,6 +20,7 @@ FC_REFLECT( sidechain::sidechain_parameters_extension, (multisig_sigs_num) (condensing_tx_vins_num) (condensing_tx_vins_num) + (confirmations_num) (managing_account) (asset_id) ) \ No newline at end of file diff --git a/libraries/sidechain/network/bitcoin_rpc_client.cpp b/libraries/sidechain/network/bitcoin_rpc_client.cpp index 850b0178..9a1609e3 100644 --- a/libraries/sidechain/network/bitcoin_rpc_client.cpp +++ b/libraries/sidechain/network/bitcoin_rpc_client.cpp @@ -39,13 +39,14 @@ int32_t bitcoin_rpc_client::receive_confirmations_tx( const std::string& tx_hash const auto reply = send_post_request( body ); if ( reply.status != 200 ) - return -1; + return 0; const auto result = std::string( reply.body.begin(), reply.body.end() ); std::stringstream ss( result ); boost::property_tree::ptree tx; boost::property_tree::read_json( ss, tx ); + if( tx.count( "result" ) ) { if( tx.get_child( "result" ).count( "confirmations" ) ) { return tx.get_child( "result" ).get_child( "confirmations" ).get_value(); @@ -93,19 +94,32 @@ uint64_t bitcoin_rpc_client::receive_estimated_fee() return 0; } -std::string bitcoin_rpc_client::send_btc_tx( const std::string& tx_hex ) +void bitcoin_rpc_client::send_btc_tx( const std::string& tx_hex ) { const auto body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"send_tx\", \"method\": \"sendrawtransaction\", \"params\": [") + std::string("\"") + tx_hex + std::string("\"") + std::string("] }"); const auto reply = send_post_request( body ); - if( reply.body.empty() || reply.status != 200 ) - return ""; + if( reply.body.empty() ) + return; std::string reply_str( reply.body.begin(), reply.body.end() ); - return reply_str; + std::stringstream ss(reply_str); + boost::property_tree::ptree json; + boost::property_tree::read_json( ss, json ); + + if( reply.status == 200 ) { + idump(( tx_hex )); + return; + } else if( json.count( "error" ) && !json.get_child( "error" ).empty() ) { + const auto error_code = json.get_child( "error" ).get_child( "code" ).get_value(); + if( error_code == -27 ) // transaction already in block chain + return; + + wlog( "BTC tx is not sent! Reply: ${msg}", ("msg", reply_str) ); + } } bool bitcoin_rpc_client::connection_is_not_defined() const diff --git a/libraries/sidechain/network/include/sidechain/network/bitcoin_rpc_client.hpp b/libraries/sidechain/network/include/sidechain/network/bitcoin_rpc_client.hpp index 96a32cd8..f94d789d 100644 --- a/libraries/sidechain/network/include/sidechain/network/bitcoin_rpc_client.hpp +++ b/libraries/sidechain/network/include/sidechain/network/bitcoin_rpc_client.hpp @@ -20,7 +20,7 @@ public: uint64_t receive_estimated_fee(); - std::string send_btc_tx( const std::string& tx_hex ); + void send_btc_tx( const std::string& tx_hex ); bool connection_is_not_defined() const; diff --git a/libraries/sidechain/network/include/sidechain/network/sidechain_net_manager.hpp b/libraries/sidechain/network/include/sidechain/network/sidechain_net_manager.hpp index f010877a..1595ce6b 100644 --- a/libraries/sidechain/network/include/sidechain/network/sidechain_net_manager.hpp +++ b/libraries/sidechain/network/include/sidechain/network/sidechain_net_manager.hpp @@ -35,6 +35,8 @@ private: std::vector extract_info_from_block( const std::string& _block ); + void update_transaction_status( std::vector trx_for_check ); + inline uint64_t parse_amount(std::string raw); std::unique_ptr listener; diff --git a/libraries/sidechain/network/sidechain_net_manager.cpp b/libraries/sidechain/network/sidechain_net_manager.cpp index d1c6239b..93ea3d9e 100644 --- a/libraries/sidechain/network/sidechain_net_manager.cpp +++ b/libraries/sidechain/network/sidechain_net_manager.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -43,15 +44,67 @@ void sidechain_net_manager::initialize_manager( graphene::chain::database* _db, } ); } +void sidechain_net_manager::update_tx_infos( const std::string& block_hash ) +{ + std::string block = bitcoin_client->receive_full_block( block_hash ); + if( block != "" ) { + const auto& vins = extract_info_from_block( block ); + for( const auto& v : vins ) { + db->i_w_info.insert_info_for_vin( prev_out{ v.out.hash_tx, v.out.n_vout, v.out.amount }, v.address ); + } + } +} + +void sidechain_net_manager::update_tx_approvals() +{ + std::vector trx_for_check; + const auto& confirmations_num = db->get_sidechain_params().confirmations_num; + + db->bitcoin_confirmations.safe_for([&]( btc_tx_confirmations_index::iterator itr_b, btc_tx_confirmations_index::iterator itr_e ){ + for(auto iter = itr_b; iter != itr_e; iter++) { + db->bitcoin_confirmations.modify( iter->transaction_id, [&]( bitcoin_transaction_confirmations& obj ) { + obj.count_block++; + }); + + if( iter->count_block == confirmations_num ) { + trx_for_check.push_back( iter->transaction_id ); + } + } + }); + + update_transaction_status( trx_for_check ); + +} + +void sidechain_net_manager::update_estimated_fee() +{ + db->estimated_feerate = bitcoin_client->receive_estimated_fee(); +} + +void sidechain_net_manager::send_btc_tx( const sidechain::bitcoin_transaction& trx ) +{ + db->bitcoin_confirmations.insert( bitcoin_transaction_confirmations( trx.get_txid() ) ); + + FC_ASSERT( !bitcoin_client->connection_is_not_defined() ); + const auto tx_hex = fc::to_hex( pack( trx ) ); + + bitcoin_client->send_btc_tx( tx_hex ); +} + +bool sidechain_net_manager::connection_is_not_defined() const +{ + return listener->connection_is_not_defined() && bitcoin_client->connection_is_not_defined(); +} + +void sidechain_net_manager::handle_block( const std::string& block_hash ) +{ + update_tx_approvals(); + update_estimated_fee(); + update_tx_infos( block_hash ); +} + std::vector sidechain_net_manager::extract_info_from_block( const std::string& _block ) { - -// std::map test = { {"2MsmG481n4W4AC1QcPgBUJQrVRTrLNM2GpB", false}, -// {"2N2LkZG2Zp9eXGjSJzP9taR1gYdZBPzH7S7", false}, -// {"2N4MCW3XggAxs9C8Dh2vNcx7uH8zUqoLMjA", false}, -// {"2NEkNoDyQ9tyREFDAPehi9Jr2m6EFiTDxAS", false}, -// {"2N1rQcKr4F14L8dfnNiUVpc4LzcZTWN9Kpd", false} }; - std::stringstream ss( _block ); boost::property_tree::ptree block; boost::property_tree::read_json( ss, block ); @@ -86,66 +139,30 @@ std::vector sidechain_net_manager::extract_info_from_block( const return result; } -void sidechain_net_manager::update_tx_infos( const std::string& block_hash ) +void sidechain_net_manager::update_transaction_status( std::vector trx_for_check ) { - std::string block = bitcoin_client->receive_full_block( block_hash ); - if( block != "" ) { - const auto& vins = extract_info_from_block( block ); - for( const auto& v : vins ) { - db->i_w_info.insert_info_for_vin( prev_out{ v.out.hash_tx, v.out.n_vout, v.out.amount }, v.address ); + const auto& confirmations_num = db->get_sidechain_params().confirmations_num; + + for( const auto& trx : trx_for_check ) { + auto confirmations = bitcoin_client->receive_confirmations_tx( trx.str() ); + db->bitcoin_confirmations.modify( trx, [&]( bitcoin_transaction_confirmations& obj ) { + obj.count_block = confirmations; + }); + + if( confirmations >= confirmations_num ) { + db->bitcoin_confirmations.modify( trx, [&]( bitcoin_transaction_confirmations& obj ) { + obj.confirmed = true; + }); + + } else if( confirmations == 0 ) { + auto is_in_mempool = bitcoin_client->receive_mempool_entry_tx( trx.str() ); + db->bitcoin_confirmations.modify( trx, [&]( bitcoin_transaction_confirmations& obj ) { + obj.missing = !is_in_mempool; + }); } } } -void sidechain_net_manager::update_tx_approvals() -{ - -} - -void sidechain_net_manager::update_estimated_fee() -{ - auto estimated_fee = bitcoin_client->receive_estimated_fee(); -} - -void sidechain_net_manager::send_btc_tx( const sidechain::bitcoin_transaction& trx ) -{ - db->bitcoin_confirmations.insert( btc_tx_confirmations( trx.get_txid() ) ); - - FC_ASSERT( !bitcoin_client->connection_is_not_defined() ); - const auto tx_hex = fc::to_hex( pack( trx ) ); - - auto reply = bitcoin_client->send_btc_tx( tx_hex ); - - std::stringstream ss(reply); - boost::property_tree::ptree json; - boost::property_tree::read_json(ss, json); - - if( !json.get_child( "error" ).empty() ) { - wlog( "BTC tx is not sent! Reply: ${msg}", ("msg", reply) ); - const auto error_code = json.get_child( "error" ).get_child( "code" ).get_value(); - - if( error_code != -27 ) // transaction already in block chain - return; - } - - if( reply == "" ){ - wlog( "Don't receive successful reply status" ); - return; - } -} - -bool sidechain_net_manager::connection_is_not_defined() const -{ - return listener->connection_is_not_defined() && bitcoin_client->connection_is_not_defined(); -} - -void sidechain_net_manager::handle_block( const std::string& block_hash ) -{ - update_tx_approvals(); - update_estimated_fee(); - update_tx_infos( block_hash ); -} - // Removes dot from amount output: "50.00000000" inline uint64_t sidechain_net_manager::parse_amount(std::string raw) { raw.erase(std::remove(raw.begin(), raw.end(), '.'), raw.end());