提交 c0d4755c 编写于 作者: D Daniel Larimer

async push transaction api

...@@ -294,7 +294,9 @@ struct controller_impl { ...@@ -294,7 +294,9 @@ struct controller_impl {
if( add_to_fork_db ) { if( add_to_fork_db ) {
pending->_pending_block_state->validated = true; pending->_pending_block_state->validated = true;
head = fork_db.add( pending->_pending_block_state ); auto new_bsp = fork_db.add( pending->_pending_block_state );
head = fork_db.head();
FC_ASSERT( new_bsp == head, "committed block did not become the new head in fork database" );
} }
pending->push(); pending->push();
...@@ -466,6 +468,7 @@ struct controller_impl { ...@@ -466,6 +468,7 @@ struct controller_impl {
pending = db.start_undo_session(true); pending = db.start_undo_session(true);
pending->_pending_block_state = std::make_shared<block_state>( *head, when ); pending->_pending_block_state = std::make_shared<block_state>( *head, when );
pending->_pending_block_state->in_current_chain = true;
try { try {
auto onbtrx = std::make_shared<transaction_metadata>( get_on_block_transaction() ); auto onbtrx = std::make_shared<transaction_metadata>( get_on_block_transaction() );
...@@ -522,22 +525,28 @@ struct controller_impl { ...@@ -522,22 +525,28 @@ struct controller_impl {
try { try {
abort_block(); abort_block();
apply_block( b ); apply_block( b );
fork_db.mark_in_current_chain( new_head, true );
fork_db.set_validity( new_head, true ); fork_db.set_validity( new_head, true );
head = new_head; head = new_head;
} catch ( const fc::exception& e ) { } catch ( const fc::exception& e ) {
fork_db.set_validity( new_head, false ); fork_db.set_validity( new_head, false ); // Removes new_head from fork_db index, so no need to mark it as not in the current chain.
throw; throw;
} }
} else { } else if( new_head->id != head->id ) {
auto branches = fork_db.fetch_branch_from( new_head->id, head->id ); auto branches = fork_db.fetch_branch_from( new_head->id, head->id );
while( head_block_id() != branches.second.back()->header.previous ) for( auto itr = branches.second.begin(); itr != branches.second.end(); ++itr ) {
fork_db.mark_in_current_chain( *itr , false );
pop_block(); pop_block();
}
FC_ASSERT( head_block_id() == branches.second.back()->header.previous,
"loss of sync between fork_db and chainbase during fork switch" ); // _should_ never fail
for( auto ritr = branches.first.rbegin(); ritr != branches.first.rend(); ++ritr) { for( auto ritr = branches.first.rbegin(); ritr != branches.first.rend(); ++ritr) {
optional<fc::exception> except; optional<fc::exception> except;
try { try {
apply_block( (*ritr)->block ); apply_block( (*ritr)->block );
fork_db.mark_in_current_chain( *ritr, true );
} }
catch (const fc::exception& e) { except = e; } catch (const fc::exception& e) { except = e; }
if (except) { if (except) {
...@@ -549,12 +558,17 @@ struct controller_impl { ...@@ -549,12 +558,17 @@ struct controller_impl {
} }
// pop all blocks from the bad fork // pop all blocks from the bad fork
while( head_block_id() != branches.second.back()->header.previous ) for( auto itr = (ritr + 1).base(); itr != branches.second.end(); ++itr ) {
fork_db.mark_in_current_chain( *itr , false );
pop_block(); pop_block();
}
FC_ASSERT( head_block_id() == branches.second.back()->header.previous,
"loss of sync between fork_db and chainbase during fork switch reversal" ); // _should_ never fail
// re-apply good blocks // re-apply good blocks
for( auto ritr = branches.second.rbegin(); ritr != branches.second.rend(); ++ritr ) { for( auto ritr = branches.second.rbegin(); ritr != branches.second.rend(); ++ritr ) {
apply_block( (*ritr)->block ); apply_block( (*ritr)->block );
fork_db.mark_in_current_chain( *ritr, true );
} }
throw *except; throw *except;
} // end if exception } // end if exception
...@@ -646,18 +660,6 @@ struct controller_impl { ...@@ -646,18 +660,6 @@ struct controller_impl {
}); });
} }
/**
* This method only works for blocks within the TAPOS range, (last 65K blocks). It
* will return block_id_type() for older blocks.
*/
block_id_type get_block_id_for_num( uint32_t block_num ) {
auto sid = block_num & 0xffff;
auto id = db.get<block_summary_object,by_id>(sid).block_id;
auto num = block_header::num_from_id( id );
if( num == block_num ) return id;
return block_id_type();
}
void clear_expired_transactions() { void clear_expired_transactions() {
//Look for expired transactions in the deduplication list, and remove them. //Look for expired transactions in the deduplication list, and remove them.
auto& transaction_idx = db.get_mutable_index<transaction_multi_index>(); auto& transaction_idx = db.get_mutable_index<transaction_multi_index>();
...@@ -851,9 +853,8 @@ void controller::log_irreversible_blocks() { ...@@ -851,9 +853,8 @@ void controller::log_irreversible_blocks() {
if( lib > 1 ) { if( lib > 1 ) {
while( log_head && log_head->block_num() < lib ) { while( log_head && log_head->block_num() < lib ) {
auto lhead = log_head->block_num(); auto lhead = log_head->block_num();
auto blk_id = my->get_block_id_for_num( lhead + 1 ); auto blk = my->fork_db.get_block_in_current_chain_by_num( lhead + 1 );
auto blk = my->fork_db.get_block( blk_id ); FC_ASSERT( blk, "unable to find block state", ("block_num",lhead+1));
FC_ASSERT( blk, "unable to find block state", ("id",blk_id));
irreversible_block( blk ); irreversible_block( blk );
my->blog.append( *blk->block ); my->blog.append( *blk->block );
my->fork_db.prune( blk ); my->fork_db.prune( blk );
...@@ -873,8 +874,7 @@ signed_block_ptr controller::fetch_block_by_number( uint32_t block_num )const { ...@@ -873,8 +874,7 @@ signed_block_ptr controller::fetch_block_by_number( uint32_t block_num )const {
optional<signed_block> b = my->blog.read_block_by_num(block_num); optional<signed_block> b = my->blog.read_block_by_num(block_num);
if( b ) return std::make_shared<signed_block>( move(*b) ); if( b ) return std::make_shared<signed_block>( move(*b) );
auto blk_id = my->get_block_id_for_num( block_num ); auto blk_state = my->fork_db.get_block_in_current_chain_by_num( block_num );
auto blk_state = my->fork_db.get_block( blk_id );
if( blk_state ) return blk_state->block; if( blk_state ) return blk_state->block;
return signed_block_ptr(); return signed_block_ptr();
} }
......
...@@ -25,7 +25,13 @@ namespace eosio { namespace chain { ...@@ -25,7 +25,13 @@ namespace eosio { namespace chain {
hashed_non_unique< tag<by_prev>, const_mem_fun<block_header_state, hashed_non_unique< tag<by_prev>, const_mem_fun<block_header_state,
const block_id_type&, &block_header_state::prev>, const block_id_type&, &block_header_state::prev>,
std::hash<block_id_type>>, std::hash<block_id_type>>,
ordered_non_unique< tag<by_block_num>, member<block_header_state,uint32_t,&block_header_state::block_num>>, ordered_non_unique< tag<by_block_num>,
composite_key< block_state,
member<block_header_state,uint32_t,&block_header_state::block_num>,
member<block_state,bool,&block_state::in_current_chain>
>,
composite_key_compare< std::less<uint32_t>, std::greater<bool> >
>,
ordered_non_unique< tag<by_lib_block_num>, ordered_non_unique< tag<by_lib_block_num>,
composite_key< block_header_state, composite_key< block_header_state,
member<block_header_state,uint32_t,&block_header_state::dpos_last_irreversible_blocknum>, member<block_header_state,uint32_t,&block_header_state::dpos_last_irreversible_blocknum>,
...@@ -135,7 +141,7 @@ namespace eosio { namespace chain { ...@@ -135,7 +141,7 @@ namespace eosio { namespace chain {
auto first_branch = get_block(first); auto first_branch = get_block(first);
auto second_branch = get_block(second); auto second_branch = get_block(second);
while( first_branch->block_num> second_branch->block_num ) while( first_branch->block_num > second_branch->block_num )
{ {
result.first.push_back(first_branch); result.first.push_back(first_branch);
first_branch = get_block( first_branch->header.previous ); first_branch = get_block( first_branch->header.previous );
...@@ -193,6 +199,20 @@ namespace eosio { namespace chain { ...@@ -193,6 +199,20 @@ namespace eosio { namespace chain {
h->validated = true; h->validated = true;
} }
} }
void fork_database::mark_in_current_chain( const block_state_ptr& h, bool in_current_chain ) {
if( h->in_current_chain == in_current_chain )
return;
auto& by_id_idx = my->index.get<by_block_id>();
auto itr = by_id_idx.find( h->id );
FC_ASSERT( itr != by_id_idx.end(), "could not find block in fork database" );
by_id_idx.modify( itr, [&]( auto& bsp ) { // Need to modify this way rather than directly so that Boost MultiIndex can re-sort
bsp->in_current_chain = in_current_chain;
});
}
void fork_database::prune( const block_state_ptr& h ) { void fork_database::prune( const block_state_ptr& h ) {
auto num = h->block_num; auto num = h->block_num;
...@@ -201,13 +221,11 @@ namespace eosio { namespace chain { ...@@ -201,13 +221,11 @@ namespace eosio { namespace chain {
my->index.erase(itr); my->index.erase(itr);
auto& numidx = my->index.get<by_block_num>(); auto& numidx = my->index.get<by_block_num>();
auto nitr = numidx.find( num ); for( auto nitr = numidx.lower_bound( num ); nitr != numidx.end() && (*nitr)->block_num == num; ++nitr ) {
if( nitr != numidx.end() ) {
remove( (*nitr)->id ); remove( (*nitr)->id );
} }
} }
block_state_ptr fork_database::get_block(const block_id_type& id)const { block_state_ptr fork_database::get_block(const block_id_type& id)const {
auto itr = my->index.find( id ); auto itr = my->index.find( id );
if( itr != my->index.end() ) if( itr != my->index.end() )
...@@ -215,6 +233,14 @@ namespace eosio { namespace chain { ...@@ -215,6 +233,14 @@ namespace eosio { namespace chain {
return block_state_ptr(); return block_state_ptr();
} }
block_state_ptr fork_database::get_block_in_current_chain_by_num( uint32_t n )const {
const auto& numidx = my->index.get<by_block_num>();
auto nitr = numidx.lower_bound( n );
FC_ASSERT( nitr != numidx.end() && (*nitr)->block_num == n,
"could not find block in fork database with block number ${block_num}", ("block_num", n) );
FC_ASSERT( (*nitr)->in_current_chain == true,
"block (with block number ${block_num}) found in fork database is not in the current chain", ("block_num", n) );
return *nitr;
}
} } /// eosio::chain } } /// eosio::chain
...@@ -20,6 +20,7 @@ namespace eosio { namespace chain { ...@@ -20,6 +20,7 @@ namespace eosio { namespace chain {
/// weak_ptr prev_block_state.... /// weak_ptr prev_block_state....
signed_block_ptr block; signed_block_ptr block;
bool validated = false; bool validated = false;
bool in_current_chain = false;
/// this data is redundant with the data stored in block, but facilitates /// this data is redundant with the data stored in block, but facilitates
/// recapturing transactions when we pop a block /// recapturing transactions when we pop a block
......
...@@ -26,6 +26,7 @@ namespace eosio { namespace chain { ...@@ -26,6 +26,7 @@ namespace eosio { namespace chain {
~fork_database(); ~fork_database();
block_state_ptr get_block(const block_id_type& id)const; block_state_ptr get_block(const block_id_type& id)const;
block_state_ptr get_block_in_current_chain_by_num( uint32_t n )const;
// vector<block_state_ptr> get_blocks_by_number(uint32_t n)const; // vector<block_state_ptr> get_blocks_by_number(uint32_t n)const;
/** /**
...@@ -34,7 +35,7 @@ namespace eosio { namespace chain { ...@@ -34,7 +35,7 @@ namespace eosio { namespace chain {
void set( block_state_ptr s ); void set( block_state_ptr s );
/** this method will attempt to append the block to an exsting /** this method will attempt to append the block to an exsting
* block_state and will return a pointer to the head block or * block_state and will return a pointer to the new block state or
* throw on error. * throw on error.
*/ */
block_state_ptr add( signed_block_ptr b ); block_state_ptr add( signed_block_ptr b );
...@@ -56,6 +57,7 @@ namespace eosio { namespace chain { ...@@ -56,6 +57,7 @@ namespace eosio { namespace chain {
* than the LIB are pruned after emitting irreversible signal. * than the LIB are pruned after emitting irreversible signal.
*/ */
void set_validity( const block_state_ptr& h, bool valid ); void set_validity( const block_state_ptr& h, bool valid );
void mark_in_current_chain( const block_state_ptr& h, bool in_current_chain );
void prune( const block_state_ptr& h ); void prune( const block_state_ptr& h );
/** /**
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册