27 #include <graphene/chain/hardfork.hpp>
46 namespace graphene {
namespace chain {
59 const auto& trx_idx = get_index_type<transaction_index>().indices().get<by_trx_id>();
60 return trx_idx.find(
id ) != trx_idx.end();
79 if( results.size() == 1 )
80 return results[0]->data;
87 auto&
index = get_index_type<transaction_index>().indices().
get<by_trx_id>();
95 pair<fork_database::branch_type, fork_database::branch_type> branches
97 if( !((branches.first.back()->previous_id() == branches.second.back()->previous_id())) )
101 (branches.first.size())
102 (branches.second.size()) );
103 assert(branches.first.back()->previous_id() == branches.second.back()->previous_id());
105 std::vector<block_id_type> result;
106 for (
const item_ptr& fork_block : branches.second)
107 result.emplace_back(fork_block->id);
108 result.emplace_back(branches.first.back()->previous_id());
127 result = _push_block(new_block);
133 bool database::_push_block(
const signed_block& new_block)
142 GRAPHENE_ASSERT( prev_block, unlinkable_block_exception,
"block does not link to known chain" );
144 verify_signing_witness( new_block, *prev_block );
147 const shared_ptr<fork_item> new_head = _fork_db.
push_block(new_block);
155 wlog(
"Switching to fork: ${id}", (
"id",new_head->data.id()) );
166 for(
auto ritr = branches.first.rbegin(); ritr != branches.first.rend(); ++ritr )
168 ilog(
"pushing block from fork #${n} ${id}", (
"n",(*ritr)->data.block_num())(
"id",(*ritr)->id) );
169 optional<fc::exception> except;
173 update_witnesses( **ritr );
174 _block_id_to_block.
store( (*ritr)->id, (*ritr)->data );
180 wlog(
"exception thrown while switching forks ${e}", (
"e",except->to_detail_string() ) );
182 while( ritr != branches.first.rend() )
184 ilog(
"removing block from fork_db #${n} ${id}",
185 (
"n",(*ritr)->data.block_num())(
"id",(*ritr)->id) );
186 _fork_db.
remove( (*ritr)->id );
189 _fork_db.
set_head( branches.second.front() );
198 ilog(
"Switching back to fork: ${id}", (
"id",branches.second.front()->data.id()) );
200 for(
auto ritr2 = branches.second.rbegin(); ritr2 != branches.second.rend(); ++ritr2 )
202 ilog(
"pushing block #${n} ${id}", (
"n",(*ritr2)->data.block_num())(
"id",(*ritr2)->id) );
205 _block_id_to_block.
store( (*ritr2)->id, (*ritr2)->data );
220 update_witnesses( *new_head );
221 _block_id_to_block.
store(new_block.
id(), new_block);
232 void database::verify_signing_witness(
const signed_block& new_block,
const fork_item& fork_entry )
const
234 FC_ASSERT( new_block.timestamp >= fork_entry.next_block_time );
235 uint32_t slot_num = ( new_block.timestamp - fork_entry.next_block_time ).to_seconds() / block_interval();
236 uint64_t
index = ( fork_entry.next_block_aslot + slot_num ) % fork_entry.scheduled_witnesses->size();
237 const auto& scheduled_witness = (*fork_entry.scheduled_witnesses)[
index];
238 FC_ASSERT( new_block.witness == scheduled_witness.first,
"Witness produced block at wrong time",
239 (
"block witness",new_block.witness)(
"scheduled",scheduled_witness)(
"slot_num",slot_num) );
240 FC_ASSERT( new_block.validate_signee( scheduled_witness.second ) );
243 void database::update_witnesses( fork_item& fork_entry )
const
245 if( fork_entry.scheduled_witnesses )
return;
248 fork_entry.next_block_aslot = dpo.current_aslot + 1;
252 fork_entry.scheduled_witnesses = std::make_shared< vector< pair< witness_id_type, public_key_type > > >();
253 fork_entry.scheduled_witnesses->reserve( wso.current_shuffled_witnesses.size() );
254 for(
size_t i = 0; i < wso.current_shuffled_witnesses.size(); ++i )
256 const auto&
witness = wso.current_shuffled_witnesses[i](*this);
257 fork_entry.scheduled_witnesses->emplace_back( wso.current_shuffled_witnesses[i],
witness.signing_key );
286 if( !_pending_tx_session.valid() )
295 auto processed_trx = _apply_transaction( trx );
296 _pending_tx.push_back(processed_trx);
300 temp_session.merge();
304 return processed_trx;
310 return _apply_transaction( trx );
316 : orig_value(nesting_counter), counter(nesting_counter)
319 "Max undo session nesting depth exceeded!" );
327 if( counter != orig_value )
328 elog(
"Unexpected undo session nesting count value: ${n} != ${o}", (
"n",counter)(
"o",orig_value) );
332 const uint32_t orig_value;
343 eval_state.
_trx = &ptrx;
344 size_t old_applied_ops_size = _applied_ops.size();
345 auto old_vop = _current_virtual_op;
355 const auto& samet_fund_idx = get_index_type<samet_fund_index>().indices().get<by_unpaid>();
356 FC_ASSERT( samet_fund_idx.empty() || samet_fund_idx.begin()->unpaid_amount == 0,
357 "Unpaid SameT Fund debt detected" );
363 for(
size_t i=old_applied_ops_size,n=_applied_ops.size(); i<n; i++ )
365 ilog(
"removing failed operation from applied_ops: ${op}", (
"op", *(_applied_ops[i])) );
366 _applied_ops[i].reset();
371 _current_virtual_op = old_vop;
372 _applied_ops.resize( old_applied_ops_size );
384 witness_id_type witness_id,
392 result = _generate_block( when, witness_id, block_signing_private_key );
399 witness_id_type witness_id,
408 FC_ASSERT( scheduled_witness == witness_id );
423 _pending_tx_session.reset();
436 static const size_t max_partial_block_header_size = (
fc::raw::pack_size( signed_block_header() )
441 const size_t max_block_header_size = max_partial_block_header_size +
fc::raw::pack_size( witness_id );
443 size_t total_block_size = max_block_header_size;
445 signed_block pending_block;
449 uint64_t postponed_tx_count = 0;
450 for(
const processed_transaction& tx : _pending_tx )
455 if( new_total_size > maximum_block_size )
457 postponed_tx_count++;
464 processed_transaction ptx = _apply_transaction( tx );
467 ptx.operation_results.clear();
474 if( new_total_size > maximum_block_size )
476 postponed_tx_count++;
480 temp_session.merge();
482 total_block_size = new_total_size;
483 pending_block.transactions.push_back( ptx );
488 wlog(
"Transaction was not processed while generating block due to ${e}", (
"e", e) );
489 wlog(
"The transaction was ${t}", (
"t", tx) );
492 if( postponed_tx_count > 0 )
494 wlog(
"Postponed ${n} transactions due to block size limit", (
"n", postponed_tx_count) );
497 _pending_tx_session.reset();
506 pending_block.timestamp = when;
507 pending_block.transaction_merkle_root = pending_block.calculate_merkle_root();
508 pending_block.witness = witness_id;
511 pending_block.sign( block_signing_private_key );
516 return pending_block;
525 _pending_tx_session.reset();
526 auto fork_db_head = _fork_db.
head();
527 FC_ASSERT( fork_db_head,
"Trying to pop() from empty fork database!?" );
533 FC_ASSERT( fork_db_head,
"Trying to pop() block that's not in fork database!?" );
537 fork_db_head->data.transactions.begin(),
538 fork_db_head->data.transactions.end() );
543 assert( (_pending_tx.size() == 0) || _pending_tx_session.valid() );
545 _pending_tx_session.reset();
552 ++_current_virtual_op;
553 return _applied_ops.size() - 1;
557 assert( op_id < _applied_ops.size() );
558 if( _applied_ops[op_id] )
559 _applied_ops[op_id]->result = result;
562 elog(
"Could not set operation result (head_block_num=${b})", (
"b",
head_block_num()) );
576 if( !_checkpoints.empty() && _checkpoints.rbegin()->second !=
block_id_type() )
578 auto itr = _checkpoints.find( block_num );
579 if( itr != _checkpoints.end() )
580 FC_ASSERT( next_block.
id() == itr->second,
"Block did not match checkpoint", (
"checkpoint",*itr)(
"block_id",next_block.
id()) );
582 if( _checkpoints.rbegin()->first >= block_num )
588 _apply_block( next_block );
593 void database::_apply_block(
const signed_block& next_block )
595 uint32_t next_block_num = next_block.
block_num();
597 _applied_ops.clear();
608 (
"next_block",next_block)
609 (
"id",next_block.
id()) );
611 const witness_object& signing_witness = validate_block_header(skip, next_block);
613 bool maint_needed = (dynamic_global_props.next_maintenance_time <= next_block.
timestamp);
622 _current_trx_in_block = 0;
626 _issue_453_affected_assets.clear();
628 signed_block processed_block( next_block );
629 for(
auto& trx : processed_block.transactions )
638 ++_current_trx_in_block;
641 _current_op_in_trx = 0;
642 _current_virtual_op = 0;
644 const uint32_t missed = update_witness_missed_blocks( next_block );
645 update_global_dynamic_data( next_block, missed );
646 update_signing_witness(signing_witness, next_block);
647 update_last_irreversible_block();
653 perform_chain_maintenance( next_block );
655 create_block_summary(next_block);
656 clear_expired_transactions();
657 clear_expired_proposals();
658 clear_expired_orders();
659 clear_expired_force_settlements();
660 clear_expired_htlcs();
661 update_expired_feeds();
662 update_core_exchange_rates();
663 update_withdraw_permissions();
664 update_credit_offers_and_deals();
671 update_maintenance_flag( maint_needed );
672 update_witness_schedule();
678 _applied_ops.clear();
693 result = _apply_transaction(trx);
704 auto& trx_idx = get_mutable_index_type<transaction_index>();
708 GRAPHENE_ASSERT( trx_idx.indices().get<by_trx_id>().find(trx.
id()) == trx_idx.indices().get<by_trx_id>().end(),
709 duplicate_transaction,
710 "Transaction '${txid}' is already in the database",
713 transaction_evaluation_state eval_state(
this);
715 eval_state._trx = &trx;
719 bool allow_non_immediate_owner = (
head_block_time() >= HARDFORK_CORE_584_TIME );
720 auto get_active = [
this]( account_id_type id ) {
return &id(*this).active; };
721 auto get_owner = [
this]( account_id_type id ) {
return &id(*this).owner; };
726 trx.
verify_authority(chain_id, get_active, get_owner, get_custom, allow_non_immediate_owner,
737 const auto& tapos_block_summary = block_summary_id_type( trx.
ref_block_num )(*this);
746 (
"trx.expiration",trx.
expiration)(
"now",now)(
"max_til_exp",chain_parameters.maximum_time_until_expiration));
751 "Transaction exceeds maximum transaction size." );
757 create<transaction_history_object>([&trx](transaction_history_object& transaction) {
758 transaction.trx_id = trx.
id();
759 transaction.trx = trx;
763 eval_state.operation_results.reserve(trx.
operations.size());
766 processed_transaction ptrx(trx);
767 _current_op_in_trx = 0;
768 for(
const auto& op : ptrx.operations )
770 _current_virtual_op = 0;
771 eval_state.operation_results.emplace_back(
apply_operation(eval_state, op,
false));
772 ++_current_op_in_trx;
774 ptrx.operation_results = std::move(eval_state.operation_results);
777 const auto& samet_fund_idx = get_index_type<samet_fund_index>().indices().get<by_unpaid>();
778 FC_ASSERT( samet_fund_idx.empty() || samet_fund_idx.begin()->unpaid_amount == 0,
779 "Unpaid SameT Fund debt detected" );
787 int i_which = op.
which();
788 uint64_t u_which = uint64_t( i_which );
789 FC_ASSERT( i_which >= 0,
"Negative operation tag in operation ${op}", (
"op",op) );
790 FC_ASSERT( u_which < _operation_evaluators.size(),
"No registered evaluator for operation ${op}", (
"op",op) );
791 unique_ptr<op_evaluator>& eval = _operation_evaluators[ u_which ];
792 FC_ASSERT( eval,
"No registered evaluator for operation ${op}", (
"op",op) );
794 auto result = eval->evaluate( eval_state, op,
true );
804 size_t old_applied_ops_size = _applied_ops.size();
805 auto old_vop = _current_virtual_op;
814 temp_session.merge();
819 wlog(
"Failed to push virtual operation ${op} at block ${n}; exception was ${e}",
821 _current_virtual_op = old_vop;
822 _applied_ops.resize( old_applied_ops_size );
827 const witness_object& database::validate_block_header( uint32_t skip,
const signed_block& next_block )
const
831 const witness_object&
witness = next_block.witness(*
this);
843 FC_ASSERT( next_block.witness == scheduled_witness,
"Witness produced block at wrong time",
844 (
"block witness",next_block.witness)(
"scheduled",scheduled_witness)(
"slot_num",slot_num) );
850 void database::create_block_summary(
const signed_block& next_block)
852 block_summary_id_type sid(next_block.block_num() & 0xffff );
853 modify( sid(*
this), [&](block_summary_object& p) {
854 p.block_id = next_block.id();
860 for(
const auto& i : checkpts )
861 _checkpoints[i.first] = i.second;
866 return (_checkpoints.size() > 0) && (_checkpoints.rbegin()->first >=
head_block_num());
873 template<
typename Trx>
874 void database::_precompute_parallel(
const Trx* trx,
const size_t count,
const uint32_t skip )
const
876 for(
size_t i = 0; i < count; ++i, ++trx )
880 trx->get_packed_size();
890 std::vector<fc::future<void>> workers;
893 if( (skip & skip_expensive) == skip_expensive )
898 uint32_t chunk_size = ( block.
transactions.size() + chunks - 1 ) / chunks;
899 workers.reserve( chunks + 1 );
900 for(
size_t base = 0; base < block.
transactions.size(); base += chunk_size )
901 workers.push_back(
fc::do_parallel( [
this,&block,base,chunk_size,skip] () {
902 _precompute_parallel( &block.transactions[base],
903 ( ( base + chunk_size ) < block.transactions.size() ) ? chunk_size
904 : ( block.transactions.size() - base ),
911 workers.push_back(
fc::do_parallel( [&block] () { block.signee(); } ) );
916 if( workers.empty() )
919 auto first = workers.begin();
921 while( ++
worker != workers.end() )