From 320cba9f428c894ce623607f0f77d9775c565571 Mon Sep 17 00:00:00 2001 From: Anzhy Cherrnyavski Date: Fri, 8 Feb 2019 12:00:49 +0300 Subject: [PATCH] Added checking bitcoin inputs --- .../bitcoin_transaction_confirmations.hpp | 4 ++- .../sidechain/sidechain_proposal_checker.hpp | 1 + .../network/sidechain_net_manager.hpp | 2 ++ .../network/sidechain_net_manager.cpp | 29 ++++++++++++++++++- tests/tests/bitcoin_issue_tests.cpp | 18 ++++++------ 5 files changed, 43 insertions(+), 11 deletions(-) diff --git a/libraries/sidechain/include/sidechain/bitcoin_transaction_confirmations.hpp b/libraries/sidechain/include/sidechain/bitcoin_transaction_confirmations.hpp index 860f9c44..89e4f20d 100644 --- a/libraries/sidechain/include/sidechain/bitcoin_transaction_confirmations.hpp +++ b/libraries/sidechain/include/sidechain/bitcoin_transaction_confirmations.hpp @@ -20,7 +20,8 @@ struct bitcoin_transaction_confirmations { bitcoin_transaction_confirmations() = default; - bitcoin_transaction_confirmations( fc::sha256 trx_id ) : id( count_id_tx_conf++ ), transaction_id( trx_id ) {} + bitcoin_transaction_confirmations( const fc::sha256& trx_id, const std::set& vins ) : + id( count_id_tx_conf++ ), transaction_id( trx_id ), valid_vins( vins ) {} struct comparer { bool operator()( const bitcoin_transaction_confirmations& lhs, const bitcoin_transaction_confirmations& rhs ) const { @@ -36,6 +37,7 @@ struct bitcoin_transaction_confirmations bool is_confirmed_and_not_used() const { return !used && confirmed; } fc::sha256 transaction_id; + std::set valid_vins; uint64_t count_block = 0; bool confirmed = false; diff --git a/libraries/sidechain/include/sidechain/sidechain_proposal_checker.hpp b/libraries/sidechain/include/sidechain/sidechain_proposal_checker.hpp index 53c26e2d..4fe601a5 100644 --- a/libraries/sidechain/include/sidechain/sidechain_proposal_checker.hpp +++ b/libraries/sidechain/include/sidechain/sidechain_proposal_checker.hpp @@ -12,6 +12,7 @@ class sidechain_proposal_checker { public: + sidechain_proposal_checker( graphene::chain::database& _db ) : db(_db) {} bool check_bitcoin_transaction_send_operation( const bitcoin_transaction_send_operation& op ); 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 1595ce6b..2fa9e080 100644 --- a/libraries/sidechain/network/include/sidechain/network/sidechain_net_manager.hpp +++ b/libraries/sidechain/network/include/sidechain/network/sidechain_net_manager.hpp @@ -37,6 +37,8 @@ private: void update_transaction_status( std::vector trx_for_check ); + std::set get_valid_vins( const std::string tx_hash ); + 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 73c6aa0d..1b68c877 100644 --- a/libraries/sidechain/network/sidechain_net_manager.cpp +++ b/libraries/sidechain/network/sidechain_net_manager.cpp @@ -86,7 +86,11 @@ void sidechain_net_manager::update_estimated_fee() void sidechain_net_manager::send_btc_tx( const sidechain::bitcoin_transaction& trx ) { - db->bitcoin_confirmations.insert( bitcoin_transaction_confirmations( trx.get_txid() ) ); + std::set valid_vins; + for( const auto& v : trx.vin ) { + valid_vins.insert( v.prevout.hash ); + } + db->bitcoin_confirmations.insert( bitcoin_transaction_confirmations( trx.get_txid(), valid_vins ) ); FC_ASSERT( !bitcoin_client->connection_is_not_defined() ); const auto tx_hex = fc::to_hex( pack( trx ) ); @@ -142,6 +146,22 @@ std::vector sidechain_net_manager::extract_info_from_block( const return result; } +std::set sidechain_net_manager::get_valid_vins( const std::string tx_hash ) +{ + const auto& confirmations_obj = db->bitcoin_confirmations.find( fc::sha256( tx_hash ) ); + FC_ASSERT( confirmations_obj.valid() ); + + std::set valid_vins; + for( const auto& v : confirmations_obj->valid_vins ) { + auto confirmations = bitcoin_client->receive_confirmations_tx( v.str() ); + if( confirmations == 0 ) { + continue; + } + valid_vins.insert( v ); + } + return valid_vins; +} + void sidechain_net_manager::update_transaction_status( std::vector trx_for_check ) { const auto& confirmations_num = db->get_sidechain_params().confirmations_num; @@ -159,8 +179,15 @@ void sidechain_net_manager::update_transaction_status( std::vector t } else if( confirmations == 0 ) { auto is_in_mempool = bitcoin_client->receive_mempool_entry_tx( trx.str() ); + + std::set valid_vins; + if( !is_in_mempool ) { + valid_vins = get_valid_vins( trx.str() ); + } + db->bitcoin_confirmations.modify( trx, [&]( bitcoin_transaction_confirmations& obj ) { obj.missing = !is_in_mempool; + obj.valid_vins = valid_vins; }); } } diff --git a/tests/tests/bitcoin_issue_tests.cpp b/tests/tests/bitcoin_issue_tests.cpp index c88d5c5f..a5726c07 100644 --- a/tests/tests/bitcoin_issue_tests.cpp +++ b/tests/tests/bitcoin_issue_tests.cpp @@ -58,7 +58,7 @@ BOOST_AUTO_TEST_CASE( check_deleting_all_btc_transaction_information ) const auto& vouts_info_idx = db.get_index_type().indices().get(); create_bitcoin_issue_operation_environment( db ); - db.bitcoin_confirmations.insert( sidechain::bitcoin_transaction_confirmations( fc::sha256( "1111111111111111111111111111111111111111111111111111111111111111" ) ) ); + db.bitcoin_confirmations.insert( sidechain::bitcoin_transaction_confirmations( fc::sha256( std::string( 64,'1' ) ), std::set() ) ); FC_ASSERT( btc_trx_idx.size() == 1 ); FC_ASSERT( vins_info_idx.size() == 3 ); @@ -67,7 +67,7 @@ BOOST_AUTO_TEST_CASE( check_deleting_all_btc_transaction_information ) bitcoin_issue_operation op; op.payer = db.get_sidechain_account_id(); - op.transaction_ids = { fc::sha256( "1111111111111111111111111111111111111111111111111111111111111111" ) }; + op.transaction_ids = { fc::sha256( std::string( 64,'1' ) ) }; db.apply_operation( context, op ); FC_ASSERT( btc_trx_idx.size() == 0 ); @@ -85,7 +85,7 @@ BOOST_AUTO_TEST_CASE( check_adding_issue_to_accounts ) bitcoin_issue_operation op; op.payer = db.get_sidechain_account_id(); - op.transaction_ids = { fc::sha256( "1111111111111111111111111111111111111111111111111111111111111111" ) }; + op.transaction_ids = { fc::sha256( std::string( 64,'1' ) ) }; db.apply_operation( context, op ); @@ -107,7 +107,7 @@ BOOST_AUTO_TEST_CASE( check_bitcoin_issue_operation_throw ) const auto& vouts_info_idx = db.get_index_type().indices().get(); create_bitcoin_issue_operation_environment( db ); - db.bitcoin_confirmations.insert( sidechain::bitcoin_transaction_confirmations( fc::sha256( "1111111111111111111111111111111111111111111111111111111111111111" ) ) ); + db.bitcoin_confirmations.insert( sidechain::bitcoin_transaction_confirmations( fc::sha256( std::string( 64,'1' ) ), std::set() ) ); { auto session = db._undo_db.start_undo_session(); @@ -116,7 +116,7 @@ BOOST_AUTO_TEST_CASE( check_bitcoin_issue_operation_throw ) bitcoin_issue_operation op; op.payer = db.get_sidechain_account_id(); - op.transaction_ids = { fc::sha256( "1111111111111111111111111111111111111111111111111111111111111111" ) }; + op.transaction_ids = { fc::sha256( std::string( 64,'1' ) ) }; GRAPHENE_REQUIRE_THROW( db.apply_operation( context, op ) , fc::exception ); session.undo(); @@ -129,7 +129,7 @@ BOOST_AUTO_TEST_CASE( check_bitcoin_issue_operation_throw ) bitcoin_issue_operation op; op.payer = db.get_sidechain_account_id(); - op.transaction_ids = { fc::sha256( "1111111111111111111111111111111111111111111111111111111111111111" ) }; + op.transaction_ids = { fc::sha256( std::string( 64,'1' ) ) }; GRAPHENE_REQUIRE_THROW( db.apply_operation( context, op ) , fc::exception ); session.undo(); @@ -142,7 +142,7 @@ BOOST_AUTO_TEST_CASE( check_bitcoin_issue_operation_throw ) bitcoin_issue_operation op; op.payer = db.get_sidechain_account_id(); - op.transaction_ids = { fc::sha256( "1111111111111111111111111111111111111111111111111111111111111111" ) }; + op.transaction_ids = { fc::sha256( std::string( 64,'1' ) ) }; GRAPHENE_REQUIRE_THROW( db.apply_operation( context, op ) , fc::exception ); session.undo(); @@ -155,7 +155,7 @@ BOOST_AUTO_TEST_CASE( check_bitcoin_issue_operation_throw ) bitcoin_issue_operation op; op.payer = db.get_sidechain_account_id(); - op.transaction_ids = { fc::sha256( "1111111111111111111111111111111111111111111111111111111111111111" ) }; + op.transaction_ids = { fc::sha256( std::string( 64,'1' ) ) }; GRAPHENE_REQUIRE_THROW( db.apply_operation( context, op ) , fc::exception ); session.undo(); @@ -166,7 +166,7 @@ BOOST_AUTO_TEST_CASE( check_bitcoin_issue_operation_throw ) bitcoin_issue_operation op; op.payer = account_id_type(1); - op.transaction_ids = { fc::sha256( "1111111111111111111111111111111111111111111111111111111111111111" ) }; + op.transaction_ids = { fc::sha256( std::string( 64,'1' ) ) }; GRAPHENE_REQUIRE_THROW( db.apply_operation( context, op ) , fc::exception ); session.undo();