Made thread_safe_index methods with typename, changed input_withdrawal_info

This commit is contained in:
Alexander Suslikov 2019-01-29 16:52:40 +03:00 committed by Anzhy Cherrnyavski
parent ffc51ba1ea
commit 787a0382be
11 changed files with 145 additions and 78 deletions

View file

@ -25,21 +25,11 @@ object_id_type bitcoin_transaction_send_evaluator::do_apply( const bitcoin_trans
{
bitcoin_transaction_send_operation& mutable_op = const_cast<bitcoin_transaction_send_operation&>( 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();

View file

@ -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 );

View file

@ -20,7 +20,7 @@ class bitcoin_transaction_object : public abstract_object<bitcoin_transaction_ob
std::vector< info_for_vout_id_type > 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_object, bitcoin_transaction_multi_index_container> bitcoin_transaction_index;

View file

@ -41,6 +41,7 @@
#include <graphene/chain/protocol/protocol.hpp>
#include <sidechain/input_withdrawal_info.hpp>
#include <sidechain/bitcoin_transaction_confirmations.hpp>
#include <sidechain/primary_wallet_vout_manager.hpp>
#include <atomic>
@ -538,6 +539,8 @@ namespace graphene { namespace chain {
sidechain::input_withdrawal_info i_w_info;
sidechain::thread_safe_index<sidechain::btc_tx_confirmations_index> bitcoin_confirmations;
sidechain::primary_wallet_vout_manager pw_vout_manager;
std::atomic<uint64_t> estimated_feerate;

View file

@ -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;

View file

@ -0,0 +1,39 @@
#pragma once
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <sidechain/thread_safe_index.hpp>
#include <fc/crypto/sha256.hpp>
#include <graphene/chain/protocol/types.hpp>
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<btc_tx_confirmations,
indexed_by<
ordered_unique<tag<by_hash>, member<btc_tx_confirmations, fc::sha256, &btc_tx_confirmations::transaction_id>>
>
>;
}

View file

@ -59,17 +59,10 @@ class input_withdrawal_info
{
public:
using iterator_identifier_vin = typename info_for_vin_index::template index<by_identifier>::type::iterator;
using iterator_id_vout = typename graphene::chain::info_for_vout_index::index_type::template index<graphene::chain::by_id>::type::iterator;
input_withdrawal_info( graphene::chain::database& _db ) : db( _db ) {}
fc::optional<info_for_vin> 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<void( info_for_vin& e )>& func );
@ -78,7 +71,7 @@ public:
void remove_info_for_vin( const info_for_vin& obj );
std::pair<bool, input_withdrawal_info::iterator_identifier_vin> find_info_for_vin( fc::sha256 identifier );
fc::optional<info_for_vin> 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<bool, input_withdrawal_info::iterator_id_vout> find_info_for_vout( graphene::chain::info_for_vout_id_type id );
fc::optional<graphene::chain::info_for_vout_object> find_info_for_vout( graphene::chain::info_for_vout_id_type id );
size_t size_info_for_vouts();

View file

@ -1,31 +1,33 @@
#pragma once
#include <mutex>
#include <fc/optional.hpp>
namespace sidechain {
struct by_identifier;
template<class T1>
class thread_safe_index {
public:
using iterator = typename T1::iterator;
using iterator_identifier = typename T1::template index<by_identifier>::type::iterator;
std::pair<iterator,bool> insert( const typename T1::value_type& value ) {
std::lock_guard<std::recursive_mutex> locker( lock );
return data.insert( value );
}
void modify( const typename T1::value_type& obj, const std::function<void( typename T1::value_type& e)>& func ) {
template<class T2, typename Key>
void modify( const Key _key, const std::function<void( typename T1::value_type& e)>& func ) {
std::lock_guard<std::recursive_mutex> locker( lock );
data.modify( data.iterator_to(obj), [&func]( typename T1::value_type& obj ) { func(obj); } );
const auto& obj = *find_iterator<T2>( _key );
data.modify( data.iterator_to( obj ), [&func]( typename T1::value_type& obj ) { func( obj ); } );
}
void remove( const typename T1::value_type& obj ) {
template<class T2, typename Key>
void remove( const Key _key ) {
std::lock_guard<std::recursive_mutex> locker( lock );
const auto& obj = *find_iterator<T2>( _key );
data.erase( data.iterator_to( obj ) );
}
@ -34,14 +36,15 @@ public:
return data.size();
}
std::pair<bool, iterator_identifier> find( fc::sha256 identifier ) {
template<class T2, typename Key>
fc::optional<typename T1::value_type> find( const Key _key ) {
std::lock_guard<std::recursive_mutex> locker( lock );
auto& index = data.template get<by_identifier>();
auto it = index.find( identifier );
auto& index = data.template get<T2>();
auto it = index.find( _key );
if( it != index.end() ) {
return std::make_pair(true, it);
return fc::optional<typename T1::value_type>(*it);
}
return std::make_pair(false, it);
return fc::optional<typename T1::value_type>();
}
template<class T2>
@ -54,6 +57,14 @@ public:
private:
template<class T2, typename Key>
typename T1::template index<T2>::type::iterator find_iterator( const Key _key ) {
auto& index = data.template get<T2>();
auto it = index.find( _key );
return it;
}
std::recursive_mutex lock;
T1 data;

View file

@ -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<void( info_for_vin& e )>& func )
{
info_for_vins.modify( obj, func );
info_for_vins.modify<by_identifier>( 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<by_identifier>( 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<by_identifier>( obj.identifier );
}
std::pair<bool, input_withdrawal_info::iterator_identifier_vin> input_withdrawal_info::find_info_for_vin( fc::sha256 identifier )
fc::optional<info_for_vin> input_withdrawal_info::find_info_for_vin( fc::sha256 identifier )
{
return info_for_vins.find( identifier );
return info_for_vins.find<by_identifier>( identifier );
}
std::vector<info_for_vin> 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<graphene::chain::info_for_vout_object>( obj, [&]( graphene::chain::info_for_vout_object& o ) {
const auto& info_for_vout_idx = db.get_index_type<graphene::chain::info_for_vout_index>().indices().get< graphene::chain::by_id >();
auto itr = info_for_vout_idx.find( obj.id );
db.modify<graphene::chain::info_for_vout_object>( *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<graphene::chain::info_for_vout_index>().indices().get< graphene::chain::by_id >();
auto itr = info_for_vout_idx.find( obj.id );
db.remove( *itr );
}
std::pair<bool, input_withdrawal_info::iterator_id_vout> input_withdrawal_info::find_info_for_vout( graphene::chain::info_for_vout_id_type id )
fc::optional<graphene::chain::info_for_vout_object> 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<graphene::chain::info_for_vout_index>().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<graphene::chain::info_for_vout_object>( *itr );
return fc::optional<graphene::chain::info_for_vout_object>();
}
size_t input_withdrawal_info::size_info_for_vouts()

View file

@ -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));

View file

@ -37,8 +37,8 @@ BOOST_AUTO_TEST_CASE( input_withdrawal_info_id_test )
prev_out out = { std::to_string( i ), static_cast<uint32_t>( 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<char> 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<char> 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();