Skip to content

Commit

Permalink
Cache witness signing key for block producing #125
Browse files Browse the repository at this point in the history
  • Loading branch information
abitmore committed Jul 29, 2018
1 parent b8bafdd commit ac49b7f
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 10 deletions.
63 changes: 59 additions & 4 deletions libraries/chain/db_block.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -331,10 +331,19 @@ signed_block database::_generate_block(
witness_id_type scheduled_witness = get_scheduled_witness( slot_num );
FC_ASSERT( scheduled_witness == witness_id );

const auto& witness_obj = witness_id(*this);

if( !(skip & skip_witness_signature) )
FC_ASSERT( witness_obj.signing_key == block_signing_private_key.get_public_key() );
{
auto signing_key = find_witness_key_from_cache( witness_id );
if( signing_key.valid() ) // witness in cache
{
FC_ASSERT( *signing_key == block_signing_private_key.get_public_key() );
}
else // witness not in cache
{
const auto& witness_obj = witness_id(*this);
FC_ASSERT( witness_obj.signing_key == block_signing_private_key.get_public_key() );
}
}

static const size_t max_block_header_size = fc::raw::pack_size( signed_block_header() ) + 4;
auto maximum_block_size = get_global_properties().parameters.maximum_block_size;
Expand All @@ -353,11 +362,12 @@ signed_block database::_generate_block(
// the value of the "when" variable is known, which means we need to
// re-apply pending transactions in this method.
//

// pop pending state (reset to head block state)
_pending_tx_session.reset();
_pending_tx_session = _undo_db.start_undo_session();

uint64_t postponed_tx_count = 0;
// pop pending state (reset to head block state)
for( const processed_transaction& tx : _pending_tx )
{
size_t new_total_size = total_block_size + fc::raw::pack_size( tx );
Expand Down Expand Up @@ -436,6 +446,9 @@ void database::pop_block()

_popped_tx.insert( _popped_tx.begin(), head_block->transactions.begin(), head_block->transactions.end() );

// Note: for better performance, can move this to where calls pop_block();
refresh_witness_key_cache();

} FC_CAPTURE_AND_RETHROW() }

void database::clear_pending()
Expand Down Expand Up @@ -511,6 +524,9 @@ void database::_apply_block( const signed_block& next_block )

_issue_453_affected_assets.clear();

if( !(skip&skip_witness_key_cache_update) )
skip |= force_witness_key_cache_update;

for( const auto& trx : next_block.transactions )
{
/* We do not need to push the undo state for each transaction
Expand Down Expand Up @@ -699,4 +715,43 @@ bool database::before_last_checkpoint()const
return (_checkpoints.size() > 0) && (_checkpoints.rbegin()->first >= head_block_num());
}

void database::init_witness_key_cache( std::set<witness_id_type>& witnesses )
{
for( const witness_id_type& wit : witnesses )
_witness_key_cache[wit]; // add it
}

void database::update_witness_key_cache( witness_id_type wit, const public_key_type& pub_key )
{
if( _witness_key_cache.empty() )
return;
uint32_t skip = get_node_properties().skip_flags;
if( (skip&force_witness_key_cache_update) )
{
auto itr = _witness_key_cache.find( wit );
if( itr != _witness_key_cache.end() )
itr->second = pub_key;
}
}

void database::refresh_witness_key_cache()
{
for( auto& wit_key : _witness_key_cache )
{
const witness_object* wit_obj = find( wit_key.first );
if( wit_obj )
wit_key.second = wit_obj->signing_key;
else
wit_key.second.reset();
}
}

optional<public_key_type> database::find_witness_key_from_cache( witness_id_type wit ) const
{
auto itr = _witness_key_cache.find( wit );
if( itr != _witness_key_cache.end() )
return itr->second;
return optional<public_key_type>();
}

} }
2 changes: 2 additions & 0 deletions libraries/chain/db_management.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ void database::reindex( fc::path data_dir )
skip_transaction_dupe_check |
skip_tapos_check |
skip_witness_schedule_check |
skip_witness_key_cache_update |
skip_authority_check);
else
{
Expand Down Expand Up @@ -185,6 +186,7 @@ void database::open(
("last_block->id", last_block)("head_block_id",head_block_num()) );
reindex( data_dir );
}
refresh_witness_key_cache();
_opened = true;
}
FC_CAPTURE_LOG_AND_RETHROW( (data_dir) )
Expand Down
14 changes: 12 additions & 2 deletions libraries/chain/include/graphene/chain/database.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,10 @@ namespace graphene { namespace chain {
skip_merkle_check = 1 << 7, ///< used while reindexing
skip_assert_evaluation = 1 << 8, ///< used while reindexing
skip_undo_history_check = 1 << 9, ///< used while reindexing
skip_witness_schedule_check = 1 << 10, ///< used while reindexing
skip_validate = 1 << 11 ///< used prior to checkpoint, skips validate() call on transaction
skip_witness_schedule_check = 1 << 10, ///< used while reindexing
skip_validate = 1 << 11, ///< used prior to checkpoint, skips validate() call on transaction
skip_witness_key_cache_update = 1 << 12, ///< used while reindexing -- do not update cache
force_witness_key_cache_update = 1 << 13 ///< used while applying a block but not applying pending transactions
};

/**
Expand Down Expand Up @@ -435,11 +437,19 @@ 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 );
operation_result apply_operation( transaction_evaluation_state& eval_state, const operation& op );

void init_witness_key_cache( std::set<witness_id_type>& witnesses );
void update_witness_key_cache( witness_id_type wit, const public_key_type& pub_key );
void refresh_witness_key_cache();
optional<public_key_type> find_witness_key_from_cache( witness_id_type wit ) const;

private:
void _apply_block( const signed_block& next_block );
processed_transaction _apply_transaction( const signed_transaction& trx );
void _cancel_bids_and_revive_mpa( const asset_object& bitasset, const asset_bitasset_data_object& bad );

flat_map< witness_id_type, optional<public_key_type> > _witness_key_cache;

///Steps involved in applying a new block
///@{

Expand Down
14 changes: 11 additions & 3 deletions libraries/chain/witness_evaluator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,21 @@ void_result witness_create_evaluator::do_evaluate( const witness_create_operatio

object_id_type witness_create_evaluator::do_apply( const witness_create_operation& op )
{ try {
database& _db = db();
vote_id_type vote_id;
db().modify(db().get_global_properties(), [&vote_id](global_property_object& p) {
_db.modify( _db.get_global_properties(), [&vote_id](global_property_object& p) {
vote_id = get_next_vote_id(p, vote_id_type::witness);
});

const auto& new_witness_object = db().create<witness_object>( [&]( witness_object& obj ){
const auto& new_witness_object = _db.create<witness_object>( [&op,&vote_id]( witness_object& obj ){
obj.witness_account = op.witness_account;
obj.signing_key = op.block_signing_key;
obj.vote_id = vote_id;
obj.url = op.url;
});

_db.update_witness_key_cache( new_witness_object.id, op.block_signing_key );

return new_witness_object.id;
} FC_CAPTURE_AND_RETHROW( (op) ) }

Expand All @@ -63,13 +67,17 @@ void_result witness_update_evaluator::do_apply( const witness_update_operation&
database& _db = db();
_db.modify(
_db.get(op.witness),
[&]( witness_object& wit )
[&op]( witness_object& wit )
{
if( op.new_url.valid() )
wit.url = *op.new_url;
if( op.new_signing_key.valid() )
wit.signing_key = *op.new_signing_key;
});

if( op.new_signing_key.valid() )
_db.update_witness_key_cache( op.witness, *op.new_signing_key );

return void_result();
} FC_CAPTURE_AND_RETHROW( (op) ) }

Expand Down
5 changes: 4 additions & 1 deletion libraries/plugins/witness/witness.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,9 @@ void witness_plugin::plugin_startup()
new_chain_banner(d);
_production_skip_flags |= graphene::chain::database::skip_undo_history_check;
}

d.init_witness_key_cache( _witnesses );

schedule_production_loop();
} else
elog("No witnesses configured! Please add witness IDs and private keys to configuration.");
Expand Down Expand Up @@ -250,7 +253,7 @@ block_production_condition::block_production_condition_enum witness_plugin::mayb
}

fc::time_point_sec scheduled_time = db.get_slot_time( slot );
graphene::chain::public_key_type scheduled_key = scheduled_witness( db ).signing_key;
graphene::chain::public_key_type scheduled_key = *db.find_witness_key_from_cache( scheduled_witness ); // should be valid
auto private_key_itr = _private_keys.find( scheduled_key );

if( private_key_itr == _private_keys.end() )
Expand Down
6 changes: 6 additions & 0 deletions tests/tests/block_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,12 @@ BOOST_AUTO_TEST_CASE( change_signing_key )
PUSH_TX( db, wu_trx, 0 );
};

// Initialize witness key cache
std::set< witness_id_type > witnesses;
for( uint32_t i = 0; i <= 11; ++i ) // 11 init witnesses and 0 is reserved
witnesses.insert( witness_id_type(i) );
db.init_witness_key_cache( witnesses );

// open database
db.open(data_dir.path(), make_genesis, "TEST");

Expand Down

0 comments on commit ac49b7f

Please sign in to comment.