diff --git a/libraries/chain/bitcoin_transaction_evaluator.cpp b/libraries/chain/bitcoin_transaction_evaluator.cpp index 4c0d54f2..0b2d8ec6 100644 --- a/libraries/chain/bitcoin_transaction_evaluator.cpp +++ b/libraries/chain/bitcoin_transaction_evaluator.cpp @@ -25,21 +25,11 @@ object_id_type bitcoin_transaction_send_evaluator::do_apply( const bitcoin_trans { bitcoin_transaction_send_operation& mutable_op = const_cast( op ); database& d = db(); - std::vector< info_for_used_vin_id_type > new_vins; sidechain::bytes wit_script; finalize_bitcoin_transaction( mutable_op ); - for( auto itr : op.vins ){ - auto itr_id = d.create< info_for_used_vin_object >( [&]( info_for_used_vin_object& obj ) - { - obj.identifier = itr.identifier; - obj.out = itr.out; - obj.address = itr.address; - obj.script = itr.script; - }).get_id(); - new_vins.push_back( itr_id ); - } + auto new_vins = create_transaction_vins( mutable_op ); const bitcoin_transaction_object& btc_tx = d.create< bitcoin_transaction_object >( [&]( bitcoin_transaction_object& obj ) { @@ -62,6 +52,27 @@ object_id_type bitcoin_transaction_send_evaluator::do_apply( const bitcoin_trans return btc_tx.id; } +std::vector< info_for_used_vin_id_type > bitcoin_transaction_send_evaluator::create_transaction_vins( bitcoin_transaction_send_operation& op ) +{ + database& d = db(); + std::vector< info_for_used_vin_id_type > new_vins; + + for( auto itr : op.vins ){ + auto itr_id = d.create< info_for_used_vin_object >( [&]( info_for_used_vin_object& obj ) + { + obj.identifier = itr.identifier; + obj.out = itr.out; + obj.address = itr.address; + obj.script = itr.script; + }).get_id(); + new_vins.push_back( itr_id ); + + auto obj_itr = d.i_w_info.find_info_for_vin( itr.identifier ); + if( obj_itr.valid() ) + d.i_w_info.remove_info_for_vin( *obj_itr ); + } +} + void bitcoin_transaction_send_evaluator::finalize_bitcoin_transaction( bitcoin_transaction_send_operation& op ) { database& d = db(); diff --git a/libraries/chain/include/graphene/chain/bitcoin_transaction_evaluator.hpp b/libraries/chain/include/graphene/chain/bitcoin_transaction_evaluator.hpp index 9a9364d4..3d456477 100644 --- a/libraries/chain/include/graphene/chain/bitcoin_transaction_evaluator.hpp +++ b/libraries/chain/include/graphene/chain/bitcoin_transaction_evaluator.hpp @@ -15,6 +15,8 @@ public: object_id_type do_apply( const bitcoin_transaction_send_operation& op ); + std::vector< info_for_used_vin_id_type > create_transaction_vins( bitcoin_transaction_send_operation& op ); + void finalize_bitcoin_transaction( bitcoin_transaction_send_operation& op ); void send_bitcoin_transaction( const bitcoin_transaction_object& btc_tx ); diff --git a/libraries/chain/include/graphene/chain/bitcoin_transaction_object.hpp b/libraries/chain/include/graphene/chain/bitcoin_transaction_object.hpp index b2adc786..eb4beea7 100644 --- a/libraries/chain/include/graphene/chain/bitcoin_transaction_object.hpp +++ b/libraries/chain/include/graphene/chain/bitcoin_transaction_object.hpp @@ -20,7 +20,7 @@ class bitcoin_transaction_object : public abstract_object vouts; sidechain::bitcoin_transaction transaction; - std::string transaction_id; + fc::sha256 transaction_id; uint64_t fee_for_size; @@ -33,7 +33,7 @@ typedef boost::multi_index_container< bitcoin_transaction_object, indexed_by< ordered_unique< tag< by_id >, member< object, object_id_type, &object::id > >, - ordered_unique< tag< by_transaction_id >, member< bitcoin_transaction_object, string, &bitcoin_transaction_object::transaction_id > > + ordered_unique< tag< by_transaction_id >, member< bitcoin_transaction_object, fc::sha256, &bitcoin_transaction_object::transaction_id > > > > bitcoin_transaction_multi_index_container; typedef generic_index bitcoin_transaction_index; diff --git a/libraries/chain/include/graphene/chain/database.hpp b/libraries/chain/include/graphene/chain/database.hpp index fbcb8c5c..6b6d42de 100644 --- a/libraries/chain/include/graphene/chain/database.hpp +++ b/libraries/chain/include/graphene/chain/database.hpp @@ -41,6 +41,7 @@ #include #include +#include #include #include @@ -538,6 +539,8 @@ namespace graphene { namespace chain { sidechain::input_withdrawal_info i_w_info; + sidechain::thread_safe_index bitcoin_confirmations; + sidechain::primary_wallet_vout_manager pw_vout_manager; std::atomic estimated_feerate; diff --git a/libraries/chain/proposal_evaluator.cpp b/libraries/chain/proposal_evaluator.cpp index 2e592f42..6314f6ae 100644 --- a/libraries/chain/proposal_evaluator.cpp +++ b/libraries/chain/proposal_evaluator.cpp @@ -151,16 +151,15 @@ void sidechain_hardfork_visitor::operator()( const bitcoin_transaction_send_oper }); for( auto& vin : v.vins ) { - auto itr = db.i_w_info.find_info_for_vin( vin.identifier ); - if( !itr.first ) - continue; - db.i_w_info.mark_as_used_vin( *itr.second ); + auto obj = db.i_w_info.find_info_for_vin( vin.identifier ); + if( obj.valid() ) + db.i_w_info.mark_as_used_vin( *obj ); } for( auto& vout : v.vouts ) { - auto itr = db.i_w_info.find_info_for_vout( vout ); - FC_ASSERT( itr.first, "info_for_vout_object don't exist." ); - db.i_w_info.mark_as_used_vout( *itr.second ); + auto obj = db.i_w_info.find_info_for_vout( vout ); + FC_ASSERT( obj.valid(), "info_for_vout_object don't exist." ); + db.i_w_info.mark_as_used_vout( *obj ); } fc::sha256 hashid = v.pw_vin.valid() ? *v.pw_vin : SIDECHAIN_NULL_HASH; diff --git a/libraries/sidechain/include/sidechain/bitcoin_transaction_confirmations.hpp b/libraries/sidechain/include/sidechain/bitcoin_transaction_confirmations.hpp new file mode 100644 index 00000000..95e32c45 --- /dev/null +++ b/libraries/sidechain/include/sidechain/bitcoin_transaction_confirmations.hpp @@ -0,0 +1,39 @@ +#pragma once + +#include +#include +#include + +#include +#include + +#include + +using boost::multi_index_container; +using namespace boost::multi_index; + +namespace graphene { namespace chain { class database; } } + +namespace sidechain { + +struct btc_tx_confirmations +{ + btc_tx_confirmations() = default; + + btc_tx_confirmations( fc::sha256 trx_id ) : transaction_id( trx_id ) {} + + fc::sha256 transaction_id; + + uint64_t count_blocks = 0; + bool confirmed = false; +}; + +struct by_hash; + +using btc_tx_confirmations_index = boost::multi_index_container, member> + > +>; + +} \ No newline at end of file diff --git a/libraries/sidechain/include/sidechain/input_withdrawal_info.hpp b/libraries/sidechain/include/sidechain/input_withdrawal_info.hpp index b1534e92..461122b0 100644 --- a/libraries/sidechain/include/sidechain/input_withdrawal_info.hpp +++ b/libraries/sidechain/include/sidechain/input_withdrawal_info.hpp @@ -59,17 +59,10 @@ class input_withdrawal_info { public: - - using iterator_identifier_vin = typename info_for_vin_index::template index::type::iterator; - using iterator_id_vout = typename graphene::chain::info_for_vout_index::index_type::template index::type::iterator; - - input_withdrawal_info( graphene::chain::database& _db ) : db( _db ) {} - fc::optional get_info_for_pw_vin(); - void insert_info_for_vin( const prev_out& out, const std::string& address, bytes script = bytes() ); void modify_info_for_vin( const info_for_vin& obj, const std::function& func ); @@ -78,7 +71,7 @@ public: void remove_info_for_vin( const info_for_vin& obj ); - std::pair find_info_for_vin( fc::sha256 identifier ); + fc::optional find_info_for_vin( fc::sha256 identifier ); size_t size_info_for_vins() { return info_for_vins.size(); } @@ -91,7 +84,7 @@ public: void remove_info_for_vout( const info_for_vout& obj ); - std::pair find_info_for_vout( graphene::chain::info_for_vout_id_type id ); + fc::optional find_info_for_vout( graphene::chain::info_for_vout_id_type id ); size_t size_info_for_vouts(); diff --git a/libraries/sidechain/include/sidechain/thread_safe_index.hpp b/libraries/sidechain/include/sidechain/thread_safe_index.hpp index 6c0e1d7d..4e45ebe1 100644 --- a/libraries/sidechain/include/sidechain/thread_safe_index.hpp +++ b/libraries/sidechain/include/sidechain/thread_safe_index.hpp @@ -1,31 +1,33 @@ #pragma once #include +#include namespace sidechain { -struct by_identifier; - template class thread_safe_index { public: using iterator = typename T1::iterator; - using iterator_identifier = typename T1::template index::type::iterator; std::pair insert( const typename T1::value_type& value ) { std::lock_guard locker( lock ); return data.insert( value ); } - void modify( const typename T1::value_type& obj, const std::function& func ) { + template + void modify( const Key _key, const std::function& func ) { std::lock_guard locker( lock ); - data.modify( data.iterator_to(obj), [&func]( typename T1::value_type& obj ) { func(obj); } ); + const auto& obj = *find_iterator( _key ); + data.modify( data.iterator_to( obj ), [&func]( typename T1::value_type& obj ) { func( obj ); } ); } - void remove( const typename T1::value_type& obj ) { + template + void remove( const Key _key ) { std::lock_guard locker( lock ); + const auto& obj = *find_iterator( _key ); data.erase( data.iterator_to( obj ) ); } @@ -34,14 +36,15 @@ public: return data.size(); } - std::pair find( fc::sha256 identifier ) { + template + fc::optional find( const Key _key ) { std::lock_guard locker( lock ); - auto& index = data.template get(); - auto it = index.find( identifier ); + auto& index = data.template get(); + auto it = index.find( _key ); if( it != index.end() ) { - return std::make_pair(true, it); + return fc::optional(*it); } - return std::make_pair(false, it); + return fc::optional(); } template @@ -54,6 +57,14 @@ public: private: + template + typename T1::template index::type::iterator find_iterator( const Key _key ) { + auto& index = data.template get(); + auto it = index.find( _key ); + return it; + } + + std::recursive_mutex lock; T1 data; diff --git a/libraries/sidechain/input_withdrawal_info.cpp b/libraries/sidechain/input_withdrawal_info.cpp index c839ede7..40657f52 100644 --- a/libraries/sidechain/input_withdrawal_info.cpp +++ b/libraries/sidechain/input_withdrawal_info.cpp @@ -40,24 +40,24 @@ void input_withdrawal_info::insert_info_for_vin( const prev_out& out, const std: void input_withdrawal_info::modify_info_for_vin( const info_for_vin& obj, const std::function& func ) { - info_for_vins.modify( obj, func ); + info_for_vins.modify( obj.identifier, func ); } void input_withdrawal_info::mark_as_used_vin( const info_for_vin& obj ) { - info_for_vins.modify( obj, [&]( info_for_vin& o ) { + info_for_vins.modify( obj.identifier, [&]( info_for_vin& o ) { o.created = true; - } ); + }); } void input_withdrawal_info::remove_info_for_vin( const info_for_vin& obj ) { - info_for_vins.remove( obj ); + info_for_vins.remove( obj.identifier ); } -std::pair input_withdrawal_info::find_info_for_vin( fc::sha256 identifier ) +fc::optional input_withdrawal_info::find_info_for_vin( fc::sha256 identifier ) { - return info_for_vins.find( identifier ); + return info_for_vins.find( identifier ); } std::vector input_withdrawal_info::get_info_for_vins() @@ -100,21 +100,28 @@ void input_withdrawal_info::insert_info_for_vout( const graphene::chain::account void input_withdrawal_info::mark_as_used_vout( const graphene::chain::info_for_vout_object& obj ) { - db.modify( obj, [&]( graphene::chain::info_for_vout_object& o ) { + const auto& info_for_vout_idx = db.get_index_type().indices().get< graphene::chain::by_id >(); + auto itr = info_for_vout_idx.find( obj.id ); + + db.modify( *itr, [&]( graphene::chain::info_for_vout_object& o ) { o.created = true; }); } void input_withdrawal_info::remove_info_for_vout( const info_for_vout& obj ) { - db.remove( obj ); + const auto& info_for_vout_idx = db.get_index_type().indices().get< graphene::chain::by_id >(); + auto itr = info_for_vout_idx.find( obj.id ); + db.remove( *itr ); } -std::pair input_withdrawal_info::find_info_for_vout( graphene::chain::info_for_vout_id_type id ) +fc::optional input_withdrawal_info::find_info_for_vout( graphene::chain::info_for_vout_id_type id ) { const auto& info_for_vout_idx = db.get_index_type().indices().get< graphene::chain::by_id >(); auto itr = info_for_vout_idx.find( id ); - return std::make_pair( itr != info_for_vout_idx.end(), itr ); + if( itr != info_for_vout_idx.end() ) + return fc::optional( *itr ); + return fc::optional(); } size_t input_withdrawal_info::size_info_for_vouts() diff --git a/libraries/sidechain/network/sidechain_net_manager.cpp b/libraries/sidechain/network/sidechain_net_manager.cpp index cae92489..adae9f35 100644 --- a/libraries/sidechain/network/sidechain_net_manager.cpp +++ b/libraries/sidechain/network/sidechain_net_manager.cpp @@ -109,6 +109,8 @@ void sidechain_net_manager::update_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 ) ); idump((tx_hex)); diff --git a/tests/tests/input_withdrawal_info_tests.cpp b/tests/tests/input_withdrawal_info_tests.cpp index 48ae4fe0..2f07bb16 100644 --- a/tests/tests/input_withdrawal_info_tests.cpp +++ b/tests/tests/input_withdrawal_info_tests.cpp @@ -37,8 +37,8 @@ BOOST_AUTO_TEST_CASE( input_withdrawal_info_id_test ) prev_out out = { std::to_string( i ), static_cast( i ), static_cast< uint64_t >( i ) }; infos.insert_info_for_vin( out, "addr" + std::to_string( i ), { 0x01, 0x02, 0x03 } ); auto identifier = fc::sha256::hash( std::to_string( i ) + std::to_string( i ) ); - BOOST_CHECK( infos.find_info_for_vin( identifier ).first ); - BOOST_CHECK( infos.find_info_for_vin( identifier ).second->id == i ); + BOOST_CHECK( infos.find_info_for_vin( identifier ).valid() ); + BOOST_CHECK( infos.find_info_for_vin( identifier )->id == i ); } info_for_vin::count_id_info_for_vin = 0; @@ -54,14 +54,14 @@ BOOST_AUTO_TEST_CASE( input_withdrawal_info_check_data_test ) for( size_t i = 0; i < 10; i++ ) { auto identifier = fc::sha256::hash( std::to_string( i ) + std::to_string( i ) ); - BOOST_CHECK( infos.find_info_for_vin( identifier ).first ); - BOOST_CHECK( infos.find_info_for_vin( identifier ).second->id == i ); - BOOST_CHECK( infos.find_info_for_vin( identifier ).second->out.hash_tx == std::to_string( i ) ); - BOOST_CHECK( infos.find_info_for_vin( identifier ).second->out.n_vout == i ); - BOOST_CHECK( infos.find_info_for_vin( identifier ).second->out.amount == i ); - BOOST_CHECK( infos.find_info_for_vin( identifier ).second->address == "addr" + std::to_string( i ) ); + BOOST_CHECK( infos.find_info_for_vin( identifier ).valid() ); + BOOST_CHECK( infos.find_info_for_vin( identifier )->id == i ); + BOOST_CHECK( infos.find_info_for_vin( identifier )->out.hash_tx == std::to_string( i ) ); + BOOST_CHECK( infos.find_info_for_vin( identifier )->out.n_vout == i ); + BOOST_CHECK( infos.find_info_for_vin( identifier )->out.amount == i ); + BOOST_CHECK( infos.find_info_for_vin( identifier )->address == "addr" + std::to_string( i ) ); std::vector script = { 0x01, 0x02, 0x03 }; - BOOST_CHECK( infos.find_info_for_vin( identifier ).second->script == script ); + BOOST_CHECK( infos.find_info_for_vin( identifier )->script == script ); } info_for_vin::count_id_info_for_vin = 0; @@ -79,8 +79,8 @@ BOOST_AUTO_TEST_CASE( input_withdrawal_info_modify_test ) if( i % 2 == 0 ) { auto identifier = fc::sha256::hash( std::to_string( i ) + std::to_string( i ) ); auto iter = infos.find_info_for_vin( identifier ); - BOOST_CHECK( iter.first ); - infos.modify_info_for_vin( *iter.second, [&]( info_for_vin& obj ) { + BOOST_CHECK( iter.valid() ); + infos.modify_info_for_vin( *iter, [&]( info_for_vin& obj ) { obj.out.hash_tx = std::to_string( i + 1 ); obj.out.n_vout = i + 1; obj.out.amount = i + 1; @@ -92,14 +92,14 @@ BOOST_AUTO_TEST_CASE( input_withdrawal_info_modify_test ) for( size_t i = 0; i < 10; i++ ) { if( i % 2 == 0 ) { auto identifier = fc::sha256::hash( std::to_string( i ) + std::to_string( i ) ); - BOOST_CHECK( infos.find_info_for_vin( identifier ).first ); - BOOST_CHECK( infos.find_info_for_vin( identifier ).second->id == i ); - BOOST_CHECK( infos.find_info_for_vin( identifier ).second->out.hash_tx == std::to_string( i + 1 ) ); - BOOST_CHECK( infos.find_info_for_vin( identifier ).second->out.n_vout == i + 1 ); - BOOST_CHECK( infos.find_info_for_vin( identifier ).second->out.amount == i + 1 ); - BOOST_CHECK( infos.find_info_for_vin( identifier ).second->address == "addr" + std::to_string( i ) + std::to_string( i ) ); + BOOST_CHECK( infos.find_info_for_vin( identifier ).valid() ); + BOOST_CHECK( infos.find_info_for_vin( identifier )->id == i ); + BOOST_CHECK( infos.find_info_for_vin( identifier )->out.hash_tx == std::to_string( i + 1 ) ); + BOOST_CHECK( infos.find_info_for_vin( identifier )->out.n_vout == i + 1 ); + BOOST_CHECK( infos.find_info_for_vin( identifier )->out.amount == i + 1 ); + BOOST_CHECK( infos.find_info_for_vin( identifier )->address == "addr" + std::to_string( i ) + std::to_string( i ) ); std::vector script = { 0x01, 0x02, 0x03 }; - BOOST_CHECK( infos.find_info_for_vin( identifier ).second->script == script ); + BOOST_CHECK( infos.find_info_for_vin( identifier )->script == script ); } } @@ -118,17 +118,17 @@ BOOST_AUTO_TEST_CASE( input_withdrawal_info_remove_vin_test ) if( i % 2 == 0 ) { auto identifier = fc::sha256::hash( std::to_string( i ) + std::to_string( i ) ); auto iter = infos.find_info_for_vin( identifier ); - BOOST_CHECK( iter.first ); - infos.remove_info_for_vin( *iter.second ); + BOOST_CHECK( iter.valid() ); + infos.remove_info_for_vin( *iter ); } } for( size_t i = 0; i < 10; i++ ) { auto identifier = fc::sha256::hash( std::to_string( i ) + std::to_string( i ) ); if( i % 2 == 0 ) { - BOOST_CHECK( !infos.find_info_for_vin( identifier ).first ); + BOOST_CHECK( !infos.find_info_for_vin( identifier ).valid() ); } else { - BOOST_CHECK( infos.find_info_for_vin( identifier ).first ); + BOOST_CHECK( infos.find_info_for_vin( identifier ).valid() ); } } @@ -149,7 +149,7 @@ BOOST_AUTO_TEST_CASE( input_withdrawal_info_get_info_for_vins_test ) for( size_t i = 0; i < 7; i++ ) { auto identifier = fc::sha256::hash( std::to_string( i ) + std::to_string( i ) ); auto iter = infos.find_info_for_vin( identifier ); - infos.mark_as_used_vin( *iter.second ); + infos.mark_as_used_vin( *iter ); } const auto& vins2 = infos.get_info_for_vins(); @@ -184,16 +184,16 @@ BOOST_AUTO_TEST_CASE( input_withdrawal_info_remove_vout_test ) for( size_t i = 0; i < 10; i++ ) { if( i % 2 == 0 ) { auto iter = infos.find_info_for_vout( graphene::chain::info_for_vout_id_type(i) ); - BOOST_CHECK( iter.first ); - infos.remove_info_for_vout( *iter.second ); + BOOST_CHECK( iter.valid() ); + infos.remove_info_for_vout( *iter ); } } for( size_t i = 0; i < 10; i++ ) { if( i % 2 == 0 ) { - BOOST_CHECK( !infos.find_info_for_vout( graphene::chain::info_for_vout_id_type(i) ).first ); + BOOST_CHECK( !infos.find_info_for_vout( graphene::chain::info_for_vout_id_type(i) ).valid() ); } else { - BOOST_CHECK( infos.find_info_for_vout( graphene::chain::info_for_vout_id_type(i) ).first ); + BOOST_CHECK( infos.find_info_for_vout( graphene::chain::info_for_vout_id_type(i) ).valid() ); } } } @@ -210,7 +210,7 @@ BOOST_AUTO_TEST_CASE( input_withdrawal_info_get_info_for_vouts_test ) for( size_t i = 0; i < 7; i++ ) { auto iter = infos.find_info_for_vout( graphene::chain::info_for_vout_id_type(i) ); - infos.mark_as_used_vout( *iter.second ); + infos.mark_as_used_vout( *iter ); } const auto& vouts2 = infos.get_info_for_vouts();