Skip to content

Commit 1a4134c

Browse files
committed
Cache witness signing key for block producing bitshares#125
1 parent 57f7ee4 commit 1a4134c

File tree

5 files changed

+88
-10
lines changed

5 files changed

+88
-10
lines changed

libraries/chain/db_block.cpp

+59-4
Original file line numberDiff line numberDiff line change
@@ -331,10 +331,19 @@ signed_block database::_generate_block(
331331
witness_id_type scheduled_witness = get_scheduled_witness( slot_num );
332332
FC_ASSERT( scheduled_witness == witness_id );
333333

334-
const auto& witness_obj = witness_id(*this);
335-
336334
if( !(skip & skip_witness_signature) )
337-
FC_ASSERT( witness_obj.signing_key == block_signing_private_key.get_public_key() );
335+
{
336+
auto signing_key = find_witness_key_from_cache( witness_id );
337+
if( signing_key.valid() ) // witness in cache
338+
{
339+
FC_ASSERT( *signing_key == block_signing_private_key.get_public_key() );
340+
}
341+
else // witness not in cache
342+
{
343+
const auto& witness_obj = witness_id(*this);
344+
FC_ASSERT( witness_obj.signing_key == block_signing_private_key.get_public_key() );
345+
}
346+
}
338347

339348
static const size_t max_block_header_size = fc::raw::pack_size( signed_block_header() ) + 4;
340349
auto maximum_block_size = get_global_properties().parameters.maximum_block_size;
@@ -353,11 +362,12 @@ signed_block database::_generate_block(
353362
// the value of the "when" variable is known, which means we need to
354363
// re-apply pending transactions in this method.
355364
//
365+
366+
// pop pending state (reset to head block state)
356367
_pending_tx_session.reset();
357368
_pending_tx_session = _undo_db.start_undo_session();
358369

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

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

449+
// Note: for better performance, can move this to where calls pop_block();
450+
refresh_witness_key_cache();
451+
439452
} FC_CAPTURE_AND_RETHROW() }
440453

441454
void database::clear_pending()
@@ -511,6 +524,9 @@ void database::_apply_block( const signed_block& next_block )
511524

512525
_issue_453_affected_assets.clear();
513526

527+
if( !(skip&skip_witness_key_cache_update) )
528+
skip |= force_witness_key_cache_update;
529+
514530
for( const auto& trx : next_block.transactions )
515531
{
516532
/* We do not need to push the undo state for each transaction
@@ -699,4 +715,43 @@ bool database::before_last_checkpoint()const
699715
return (_checkpoints.size() > 0) && (_checkpoints.rbegin()->first >= head_block_num());
700716
}
701717

718+
void database::init_witness_key_cache( std::set<witness_id_type>& witnesses )
719+
{
720+
for( const witness_id_type& wit : witnesses )
721+
_witness_key_cache[wit]; // add it
722+
}
723+
724+
void database::update_witness_key_cache( witness_id_type wit, const public_key_type& pub_key )
725+
{
726+
if( _witness_key_cache.empty() )
727+
return;
728+
uint32_t skip = get_node_properties().skip_flags;
729+
if( (skip&force_witness_key_cache_update) )
730+
{
731+
auto itr = _witness_key_cache.find( wit );
732+
if( itr != _witness_key_cache.end() )
733+
itr->second = pub_key;
734+
}
735+
}
736+
737+
void database::refresh_witness_key_cache()
738+
{
739+
for( auto& wit_key : _witness_key_cache )
740+
{
741+
const witness_object* wit_obj = find( wit_key.first );
742+
if( wit_obj )
743+
wit_key.second = wit_obj->signing_key;
744+
else
745+
wit_key.second.reset();
746+
}
747+
}
748+
749+
optional<public_key_type> database::find_witness_key_from_cache( witness_id_type wit ) const
750+
{
751+
auto itr = _witness_key_cache.find( wit );
752+
if( itr != _witness_key_cache.end() )
753+
return itr->second;
754+
return optional<public_key_type>();
755+
}
756+
702757
} }

libraries/chain/db_management.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ void database::reindex( fc::path data_dir )
108108
skip_transaction_dupe_check |
109109
skip_tapos_check |
110110
skip_witness_schedule_check |
111+
skip_witness_key_cache_update |
111112
skip_authority_check);
112113
else
113114
{
@@ -185,6 +186,7 @@ void database::open(
185186
("last_block->id", last_block)("head_block_id",head_block_num()) );
186187
reindex( data_dir );
187188
}
189+
refresh_witness_key_cache();
188190
_opened = true;
189191
}
190192
FC_CAPTURE_LOG_AND_RETHROW( (data_dir) )

libraries/chain/include/graphene/chain/database.hpp

+12-2
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,10 @@ namespace graphene { namespace chain {
7575
skip_merkle_check = 1 << 7, ///< used while reindexing
7676
skip_assert_evaluation = 1 << 8, ///< used while reindexing
7777
skip_undo_history_check = 1 << 9, ///< used while reindexing
78-
skip_witness_schedule_check = 1 << 10, ///< used while reindexing
79-
skip_validate = 1 << 11 ///< used prior to checkpoint, skips validate() call on transaction
78+
skip_witness_schedule_check = 1 << 10, ///< used while reindexing
79+
skip_validate = 1 << 11, ///< used prior to checkpoint, skips validate() call on transaction
80+
skip_witness_key_cache_update = 1 << 12, ///< used while reindexing -- do not update cache
81+
force_witness_key_cache_update = 1 << 13 ///< used while applying a block but not applying pending transactions
8082
};
8183

8284
/**
@@ -435,11 +437,19 @@ namespace graphene { namespace chain {
435437
void apply_block( const signed_block& next_block, uint32_t skip = skip_nothing );
436438
processed_transaction apply_transaction( const signed_transaction& trx, uint32_t skip = skip_nothing );
437439
operation_result apply_operation( transaction_evaluation_state& eval_state, const operation& op );
440+
441+
void init_witness_key_cache( std::set<witness_id_type>& witnesses );
442+
void update_witness_key_cache( witness_id_type wit, const public_key_type& pub_key );
443+
void refresh_witness_key_cache();
444+
optional<public_key_type> find_witness_key_from_cache( witness_id_type wit ) const;
445+
438446
private:
439447
void _apply_block( const signed_block& next_block );
440448
processed_transaction _apply_transaction( const signed_transaction& trx );
441449
void _cancel_bids_and_revive_mpa( const asset_object& bitasset, const asset_bitasset_data_object& bad );
442450

451+
flat_map< witness_id_type, optional<public_key_type> > _witness_key_cache;
452+
443453
///Steps involved in applying a new block
444454
///@{
445455

libraries/chain/witness_evaluator.cpp

+11-3
Original file line numberDiff line numberDiff line change
@@ -38,17 +38,21 @@ void_result witness_create_evaluator::do_evaluate( const witness_create_operatio
3838

3939
object_id_type witness_create_evaluator::do_apply( const witness_create_operation& op )
4040
{ try {
41+
database& _db = db();
4142
vote_id_type vote_id;
42-
db().modify(db().get_global_properties(), [&vote_id](global_property_object& p) {
43+
_db.modify( _db.get_global_properties(), [&vote_id](global_property_object& p) {
4344
vote_id = get_next_vote_id(p, vote_id_type::witness);
4445
});
4546

46-
const auto& new_witness_object = db().create<witness_object>( [&]( witness_object& obj ){
47+
const auto& new_witness_object = _db.create<witness_object>( [&op,&vote_id]( witness_object& obj ){
4748
obj.witness_account = op.witness_account;
4849
obj.signing_key = op.block_signing_key;
4950
obj.vote_id = vote_id;
5051
obj.url = op.url;
5152
});
53+
54+
_db.update_witness_key_cache( new_witness_object.id, op.block_signing_key );
55+
5256
return new_witness_object.id;
5357
} FC_CAPTURE_AND_RETHROW( (op) ) }
5458

@@ -63,13 +67,17 @@ void_result witness_update_evaluator::do_apply( const witness_update_operation&
6367
database& _db = db();
6468
_db.modify(
6569
_db.get(op.witness),
66-
[&]( witness_object& wit )
70+
[&op]( witness_object& wit )
6771
{
6872
if( op.new_url.valid() )
6973
wit.url = *op.new_url;
7074
if( op.new_signing_key.valid() )
7175
wit.signing_key = *op.new_signing_key;
7276
});
77+
78+
if( op.new_signing_key.valid() )
79+
_db.update_witness_key_cache( op.witness, *op.new_signing_key );
80+
7381
return void_result();
7482
} FC_CAPTURE_AND_RETHROW( (op) ) }
7583

libraries/plugins/witness/witness.cpp

+4-1
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,9 @@ void witness_plugin::plugin_startup()
130130
new_chain_banner(d);
131131
_production_skip_flags |= graphene::chain::database::skip_undo_history_check;
132132
}
133+
134+
d.init_witness_key_cache( _witnesses );
135+
133136
schedule_production_loop();
134137
} else
135138
elog("No witnesses configured! Please add witness IDs and private keys to configuration.");
@@ -250,7 +253,7 @@ block_production_condition::block_production_condition_enum witness_plugin::mayb
250253
}
251254

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

256259
if( private_key_itr == _private_keys.end() )

0 commit comments

Comments
 (0)