diff --git a/libraries/chain/db_block.cpp b/libraries/chain/db_block.cpp index d82dde79..905abb21 100644 --- a/libraries/chain/db_block.cpp +++ b/libraries/chain/db_block.cpp @@ -81,7 +81,18 @@ const signed_transaction& database::get_recent_transaction(const transaction_id_ * @return true if we switched forks as a result of this push. */ bool database::push_block( const signed_block& new_block, uint32_t skip ) +{ + bool result; + with_skip_flags( skip, [&]() + { + result = _push_block( new_block ); + } ); + return result; +} + +bool database::_push_block( const signed_block& new_block ) { try { + uint32_t skip = get_node_properties().skip_flags; if( !(skip&skip_fork_db) ) { auto new_head = _fork_db.push_block( new_block ); @@ -182,12 +193,23 @@ bool database::push_block( const signed_block& new_block, uint32_t skip ) */ processed_transaction database::push_transaction( const signed_transaction& trx, uint32_t skip ) { + processed_transaction result; + with_skip_flags( skip, [&]() + { + result = _push_transaction( trx ); + } ); + return result; +} + +processed_transaction database::_push_transaction( const signed_transaction& trx ) +{ + uint32_t skip = get_node_properties().skip_flags; //wdump((trx.digest())(trx.id())); // If this is the first transaction pushed after applying a block, start a new undo session. // This allows us to quickly rewind to the clean state of the head block, in case a new block arrives. if( !_pending_block_session ) _pending_block_session = _undo_db.start_undo_session(); auto session = _undo_db.start_undo_session(); - auto processed_trx = apply_transaction( trx, skip ); + auto processed_trx = _apply_transaction( trx ); _pending_block.transactions.push_back(processed_trx); FC_ASSERT( (skip & skip_block_size_check) || @@ -240,8 +262,23 @@ signed_block database::generate_block( const fc::ecc::private_key& block_signing_private_key, uint32_t skip /* = 0 */ ) +{ + signed_block result; + with_skip_flags( skip, [&]() + { + result = _generate_block( when, witness_id, block_signing_private_key ); + } ); + return result; +} + +signed_block database::_generate_block( + fc::time_point_sec when, + witness_id_type witness_id, + const fc::ecc::private_key& block_signing_private_key + ) { try { + uint32_t skip = get_node_properties().skip_flags; uint32_t slot_num = get_slot_at_time( when ); witness_id_type scheduled_witness = get_scheduled_witness( slot_num ).first; FC_ASSERT( scheduled_witness == witness_id ); @@ -322,7 +359,17 @@ const vector& database::get_applied_operations() const //////////////////// private methods //////////////////// void database::apply_block( const signed_block& next_block, uint32_t skip ) +{ + with_skip_flags( skip, [&]() + { + _apply_block( next_block ); + } ); + return; +} + +void database::_apply_block( const signed_block& next_block ) { try { + uint32_t skip = get_node_properties().skip_flags; _applied_ops.clear(); FC_ASSERT( (skip & skip_merkle_check) || next_block.transaction_merkle_root == next_block.calculate_merkle_root(), "", ("next_block.transaction_merkle_root",next_block.transaction_merkle_root)("calc",next_block.calculate_merkle_root())("next_block",next_block)("id",next_block.id()) ); @@ -375,16 +422,27 @@ void database::apply_block( const signed_block& next_block, uint32_t skip ) update_pending_block(next_block, current_block_interval); -} FC_CAPTURE_AND_RETHROW( (next_block.block_num())(skip) ) } +} FC_CAPTURE_AND_RETHROW( (next_block.block_num()) ) } processed_transaction database::apply_transaction( const signed_transaction& trx, uint32_t skip ) +{ + processed_transaction result; + with_skip_flags( skip, [&]() + { + result = _apply_transaction( trx ); + } ); + return result; +} + +processed_transaction database::_apply_transaction( const signed_transaction& trx ) { try { + uint32_t skip = get_node_properties().skip_flags; trx.validate(); auto& trx_idx = get_mutable_index_type(); auto trx_id = trx.id(); FC_ASSERT( (skip & skip_transaction_dupe_check) || trx_idx.indices().get().find(trx_id) == trx_idx.indices().get().end() ); - transaction_evaluation_state eval_state(this, skip&skip_authority_check ); + transaction_evaluation_state eval_state(this); const chain_parameters& chain_parameters = get_global_properties().parameters; eval_state._trx = &trx; diff --git a/libraries/chain/db_getter.cpp b/libraries/chain/db_getter.cpp index 24b3465f..7268fcf3 100644 --- a/libraries/chain/db_getter.cpp +++ b/libraries/chain/db_getter.cpp @@ -63,4 +63,14 @@ decltype( chain_parameters::block_interval ) database::block_interval( )const return get_global_properties().parameters.block_interval; } +const node_property_object& database::get_node_properties()const +{ + return _node_property_object; +} + +node_property_object& database::node_properties() +{ + return _node_property_object; +} + } } diff --git a/libraries/chain/include/graphene/chain/database.hpp b/libraries/chain/include/graphene/chain/database.hpp index 20b9f726..b149b324 100644 --- a/libraries/chain/include/graphene/chain/database.hpp +++ b/libraries/chain/include/graphene/chain/database.hpp @@ -64,6 +64,31 @@ namespace graphene { namespace chain { vector initial_committee; }; + namespace detail + { + /** + * Class used to help the with_skip_flags implementation. + * It must be defined in this header because it must be + * available to the with_skip_flags implementation, + * which is a template and therefore must also be defined + * in this header. + */ + struct skip_flags_restorer + { + skip_flags_restorer( node_property_object& npo, uint32_t old_skip_flags ) + : _npo( npo ), _old_skip_flags( old_skip_flags ) + {} + + ~skip_flags_restorer() + { + _npo.skip_flags = _old_skip_flags; + } + + node_property_object& _npo; + uint32_t _old_skip_flags; + }; + } + /** * @class database * @brief tracks the blockchain state in an extensible manner @@ -124,6 +149,9 @@ namespace graphene { namespace chain { bool push_block( const signed_block& b, uint32_t skip = skip_nothing ); processed_transaction push_transaction( const signed_transaction& trx, uint32_t skip = skip_nothing ); + bool _push_block( const signed_block& b ); + processed_transaction _push_transaction( const signed_transaction& trx ); + ///@throws fc::exception if the proposed transaction fails to apply. processed_transaction push_proposal( const proposal_object& proposal ); @@ -131,7 +159,12 @@ namespace graphene { namespace chain { const fc::time_point_sec when, witness_id_type witness_id, const fc::ecc::private_key& block_signing_private_key, - uint32_t skip = 0 + uint32_t skip + ); + signed_block _generate_block( + const fc::time_point_sec when, + witness_id_type witness_id, + const fc::ecc::private_key& block_signing_private_key ); void pop_block(); @@ -225,6 +258,25 @@ namespace graphene { namespace chain { decltype( chain_parameters::block_interval ) block_interval( )const; + node_property_object& node_properties(); + + /** + * Set the skip_flags to the given value, call callback, + * then reset skip_flags to their previous value after + * callback is done. + */ + template< typename Lambda > + void with_skip_flags( + uint32_t skip_flags, + Lambda callback ) + { + node_property_object& npo = node_properties(); + detail::skip_flags_restorer restorer( npo, npo.skip_flags ); + npo.skip_flags = skip_flags; + callback(); + return; + } + //////////////////// db_init.cpp //////////////////// void initialize_evaluators(); @@ -350,12 +402,15 @@ namespace graphene { namespace chain { void apply_block( const signed_block& next_block, uint32_t skip = skip_nothing ); processed_transaction apply_transaction( const signed_transaction& trx, uint32_t skip = skip_nothing ); + void _apply_block( const signed_block& next_block ); + processed_transaction _apply_transaction( const signed_transaction& trx ); operation_result apply_operation( transaction_evaluation_state& eval_state, const operation& op ); ///Steps involved in applying a new block ///@{ - const witness_object& validate_block_header( const signed_block& next_block )const; + const witness_object& validate_block_header( uint32_t skip, const signed_block& next_block )const; + const witness_object& _validate_block_header( const signed_block& next_block )const; void create_block_summary(const signed_block& next_block); //////////////////// db_update.cpp //////////////////// @@ -419,6 +474,8 @@ namespace graphene { namespace chain { vector _witness_count_histogram_buffer; vector _committee_count_histogram_buffer; uint64_t _total_voting_stake; + + node_property_object _node_property_object; }; namespace detail diff --git a/libraries/chain/include/graphene/chain/node_property_object.hpp b/libraries/chain/include/graphene/chain/node_property_object.hpp index b06099ef..92addff9 100644 --- a/libraries/chain/include/graphene/chain/node_property_object.hpp +++ b/libraries/chain/include/graphene/chain/node_property_object.hpp @@ -36,6 +36,6 @@ namespace graphene { namespace chain { node_property_object() : skip_flags(0) {} ~node_property_object(){} - bool skip_authority_check; + uint32_t skip_flags; }; } } // graphene::chain