Implement recent_slots_filled and use it to measure witness participation
This commit is contained in:
parent
78f0cfa5cc
commit
c019f18bd4
9 changed files with 30 additions and 18 deletions
|
|
@ -73,14 +73,4 @@ node_property_object& database::node_properties()
|
||||||
return _node_property_object;
|
return _node_property_object;
|
||||||
}
|
}
|
||||||
|
|
||||||
double database::witness_participation_rate()const
|
|
||||||
{
|
|
||||||
if( head_block_num() < 10 ) return 1; // sample size is too small
|
|
||||||
uint32_t produced = std::min<uint32_t>( head_block_num()-1, 100 );
|
|
||||||
auto prior = fetch_block_by_number( head_block_num() - produced );
|
|
||||||
auto delta_time = head_block_time() - prior->timestamp;
|
|
||||||
auto expected_slots = delta_time.to_seconds() / get_global_properties().parameters.block_interval;
|
|
||||||
return double(produced) / expected_slots;
|
|
||||||
}
|
|
||||||
|
|
||||||
} }
|
} }
|
||||||
|
|
|
||||||
|
|
@ -525,6 +525,8 @@ void database::init_genesis(const genesis_state_type& genesis_state)
|
||||||
_wso.scheduler.produce_schedule(rng);
|
_wso.scheduler.produce_schedule(rng);
|
||||||
|
|
||||||
_wso.last_scheduling_block = 0;
|
_wso.last_scheduling_block = 0;
|
||||||
|
|
||||||
|
_wso.recent_slots_filled = fc::uint128::max_value();
|
||||||
});
|
});
|
||||||
assert( wso.id == witness_schedule_id_type() );
|
assert( wso.id == witness_schedule_id_type() );
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -141,6 +141,16 @@ void database::update_witness_schedule(const signed_block& next_block)
|
||||||
memcpy(_wso.rng_seed.begin(), dpo.random.data(), dpo.random.data_size());
|
memcpy(_wso.rng_seed.begin(), dpo.random.data(), dpo.random.data_size());
|
||||||
}
|
}
|
||||||
_wso.last_scheduling_block = next_block.block_num();
|
_wso.last_scheduling_block = next_block.block_num();
|
||||||
|
_wso.recent_slots_filled = (
|
||||||
|
(_wso.recent_slots_filled << 1)
|
||||||
|
+ 1) << (schedule_slot - 1);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t database::witness_participation_rate()const
|
||||||
|
{
|
||||||
|
const witness_schedule_object& wso = get(witness_schedule_id_type());
|
||||||
|
return uint64_t(GRAPHENE_100_PERCENT) * wso.recent_slots_filled.popcount() / 128;
|
||||||
|
}
|
||||||
|
|
||||||
} }
|
} }
|
||||||
|
|
|
||||||
|
|
@ -138,9 +138,9 @@ namespace graphene { namespace chain {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate the percent of block production slots that were missed in the
|
* Calculate the percent of block production slots that were missed in the
|
||||||
* past 100 blocks.
|
* past 128 blocks, not including the current block.
|
||||||
*/
|
*/
|
||||||
double witness_participation_rate()const;
|
uint32_t witness_participation_rate()const;
|
||||||
|
|
||||||
void add_checkpoints( const flat_map<uint32_t,block_id_type>& checkpts );
|
void add_checkpoints( const flat_map<uint32_t,block_id_type>& checkpts );
|
||||||
const flat_map<uint32_t,block_id_type> get_checkpoints()const { return _checkpoints; }
|
const flat_map<uint32_t,block_id_type> get_checkpoints()const { return _checkpoints; }
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,8 @@
|
||||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include <fc/uint128.hpp>
|
||||||
|
|
||||||
#include <graphene/chain/protocol/chain_parameters.hpp>
|
#include <graphene/chain/protocol/chain_parameters.hpp>
|
||||||
#include <graphene/chain/database.hpp>
|
#include <graphene/chain/database.hpp>
|
||||||
#include <graphene/db/object.hpp>
|
#include <graphene/db/object.hpp>
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
// needed to serialize witness_scheduler
|
// needed to serialize witness_scheduler
|
||||||
#include <fc/container/deque.hpp>
|
#include <fc/container/deque.hpp>
|
||||||
|
#include <fc/uint128.hpp>
|
||||||
|
|
||||||
#include <graphene/chain/protocol/types.hpp>
|
#include <graphene/chain/protocol/types.hpp>
|
||||||
#include <graphene/chain/witness_scheduler.hpp>
|
#include <graphene/chain/witness_scheduler.hpp>
|
||||||
|
|
@ -57,6 +58,12 @@ class witness_schedule_object : public abstract_object<witness_schedule_object>
|
||||||
uint32_t last_scheduling_block;
|
uint32_t last_scheduling_block;
|
||||||
uint64_t slots_since_genesis = 0;
|
uint64_t slots_since_genesis = 0;
|
||||||
fc::array< char, sizeof(secret_hash_type) > rng_seed;
|
fc::array< char, sizeof(secret_hash_type) > rng_seed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Not necessary for consensus, but used for figuring out the participation rate.
|
||||||
|
* The nth bit is 0 if the nth slot was unfilled, else it is 1.
|
||||||
|
*/
|
||||||
|
fc::uint128 recent_slots_filled;
|
||||||
};
|
};
|
||||||
|
|
||||||
} }
|
} }
|
||||||
|
|
@ -77,4 +84,5 @@ FC_REFLECT_DERIVED( graphene::chain::witness_schedule_object, (graphene::chain::
|
||||||
(last_scheduling_block)
|
(last_scheduling_block)
|
||||||
(slots_since_genesis)
|
(slots_since_genesis)
|
||||||
(rng_seed)
|
(rng_seed)
|
||||||
|
(recent_slots_filled)
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
Subproject commit 0391665471b4dffb7af951853a777565a7ae9a74
|
Subproject commit 5f43c06bae6d03e319dd2f230fe7cbd74399a773
|
||||||
|
|
@ -57,7 +57,7 @@ private:
|
||||||
boost::program_options::variables_map _options;
|
boost::program_options::variables_map _options;
|
||||||
bool _production_enabled = false;
|
bool _production_enabled = false;
|
||||||
bool _consecutive_production_enabled = false;
|
bool _consecutive_production_enabled = false;
|
||||||
int _required_witness_participation = 33;
|
uint32_t _required_witness_participation = 33 * GRAPHENE_1_PERCENT;
|
||||||
|
|
||||||
std::map<chain::public_key_type, fc::ecc::private_key> _private_keys;
|
std::map<chain::public_key_type, fc::ecc::private_key> _private_keys;
|
||||||
std::set<chain::witness_id_type> _witnesses;
|
std::set<chain::witness_id_type> _witnesses;
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ void witness_plugin::plugin_set_program_options(
|
||||||
string witness_id_example = fc::json::to_string(chain::witness_id_type());
|
string witness_id_example = fc::json::to_string(chain::witness_id_type());
|
||||||
command_line_options.add_options()
|
command_line_options.add_options()
|
||||||
("enable-stale-production", bpo::bool_switch()->notifier([this](bool e){_production_enabled = e;}), "Enable block production, even if the chain is stale.")
|
("enable-stale-production", bpo::bool_switch()->notifier([this](bool e){_production_enabled = e;}), "Enable block production, even if the chain is stale.")
|
||||||
("required-participation", bpo::bool_switch()->notifier([this](int e){_required_witness_participation = e;}), "Percent of witnesses (0-99) that must be participating in order to produce blocks")
|
("required-participation", bpo::bool_switch()->notifier([this](int e){_required_witness_participation = uint32_t(e*GRAPHENE_1_PERCENT);}), "Percent of witnesses (0-99) that must be participating in order to produce blocks")
|
||||||
("allow-consecutive", bpo::bool_switch()->notifier([this](bool e){_consecutive_production_enabled = e;}), "Allow block production, even if the last block was produced by the same witness.")
|
("allow-consecutive", bpo::bool_switch()->notifier([this](bool e){_consecutive_production_enabled = e;}), "Allow block production, even if the last block was produced by the same witness.")
|
||||||
("witness-id,w", bpo::value<vector<string>>()->composing()->multitoken(),
|
("witness-id,w", bpo::value<vector<string>>()->composing()->multitoken(),
|
||||||
("ID of witness controlled by this node (e.g. " + witness_id_example + ", quotes are required, may specify multiple times)").c_str())
|
("ID of witness controlled by this node (e.g. " + witness_id_example + ", quotes are required, may specify multiple times)").c_str())
|
||||||
|
|
@ -191,11 +191,11 @@ void witness_plugin::block_production_loop()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
double prate = db.witness_participation_rate();
|
uint32_t prate = db.witness_participation_rate();
|
||||||
if( int(100*prate) < _required_witness_participation )
|
if( prate < _required_witness_participation )
|
||||||
{
|
{
|
||||||
elog("Not producing block because node appers to be on a minority fork with only ${x}% witness participation",
|
elog("Not producing block because node appers to be on a minority fork with only ${x}% witness participation",
|
||||||
("x",uint32_t(100*prate) ) );
|
("x",uint32_t(100*uint64_t(prate) / GRAPHENE_1_PERCENT) ) );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue