Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dpos pbft #1

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions libraries/chain/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ add_library( eosio_chain
block_header_state.cpp
block_state.cpp
fork_database.cpp
pbft_database.cpp
pbft.cpp
controller.cpp
authorization_manager.cpp
resource_limits.cpp
Expand Down
9 changes: 5 additions & 4 deletions libraries/chain/block_header_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ namespace eosio { namespace chain {
result.pending_schedule = pending_schedule;
result.dpos_proposed_irreversible_blocknum = dpos_proposed_irreversible_blocknum;
result.bft_irreversible_blocknum = bft_irreversible_blocknum;
result.pbft_stable_checkpoint_blocknum = pbft_stable_checkpoint_blocknum;

result.producer_to_last_implied_irb[prokey.producer_name] = result.dpos_proposed_irreversible_blocknum;
result.dpos_irreversible_blocknum = result.calc_dpos_last_irreversible();
Expand Down Expand Up @@ -91,7 +92,7 @@ namespace eosio { namespace chain {

bool block_header_state::maybe_promote_pending() {
if( pending_schedule.producers.size() &&
dpos_irreversible_blocknum >= pending_schedule_lib_num )
bft_irreversible_blocknum >= pending_schedule_lib_num )
{
active_schedule = move( pending_schedule );

Expand All @@ -101,7 +102,7 @@ namespace eosio { namespace chain {
if( existing != producer_to_last_produced.end() ) {
new_producer_to_last_produced[pro.producer_name] = existing->second;
} else {
new_producer_to_last_produced[pro.producer_name] = dpos_irreversible_blocknum;
new_producer_to_last_produced[pro.producer_name] = bft_irreversible_blocknum;
}
}

Expand All @@ -111,7 +112,7 @@ namespace eosio { namespace chain {
if( existing != producer_to_last_implied_irb.end() ) {
new_producer_to_last_implied_irb[pro.producer_name] = existing->second;
} else {
new_producer_to_last_implied_irb[pro.producer_name] = dpos_irreversible_blocknum;
new_producer_to_last_implied_irb[pro.producer_name] = bft_irreversible_blocknum;
}
}

Expand Down Expand Up @@ -163,7 +164,7 @@ namespace eosio { namespace chain {
/// below this point is state changes that cannot be validated with headers alone, but never-the-less,
/// must result in header state changes

result.set_confirmed( h.confirmed );
// result.set_confirmed( h.confirmed );

auto was_pending_promoted = result.maybe_promote_pending();

Expand Down
121 changes: 117 additions & 4 deletions libraries/chain/controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,19 +108,31 @@ struct pending_state {

optional<block_id_type> _producer_block_id;

std::function<signature_type(digest_type)> _signer;

void push() {
_db_session.push();
}
};

struct pending_pbft_state {
block_id_type pbft_lib;
bool contains_proposed_schedule;
};

struct controller_impl {
controller& self;
chainbase::database db;
chainbase::database reversible_blocks; ///< a special database to persist blocks that have successfully been applied but are still reversible
block_log blog;
optional<pending_state> pending;
optional<pending_pbft_state> pending_pbft_lib;
optional<block_id_type> pending_pbft_checkpoint;
optional<block_num_type> last_proposed_schedule_block_num;
optional<block_num_type> last_promoted_proposed_schedule_block_num;
block_state_ptr head;
fork_database fork_db;
optional<block_id_type> pbft_prepared_block_id;
wasm_interface wasmif;
resource_limits_manager resource_limits;
authorization_manager authorization;
Expand Down Expand Up @@ -670,9 +682,13 @@ struct controller_impl {
void commit_block( bool add_to_fork_db ) {
auto reset_pending_on_exit = fc::make_scoped_exit([this]{
pending.reset();
set_pbft_lib();
set_pbft_lscb();
});

try {
set_pbft_lib();
set_pbft_lscb();
if (add_to_fork_db) {
pending->_pending_block_state->validated = true;
auto new_bsp = fork_db.add(pending->_pending_block_state);
Expand Down Expand Up @@ -1096,7 +1112,7 @@ struct controller_impl {
pending->_pending_block_state = std::make_shared<block_state>( *head, when ); // promotes pending schedule (if any) to active
pending->_pending_block_state->in_current_chain = true;

pending->_pending_block_state->set_confirmed(confirm_block_count);
// pending->_pending_block_state->set_confirmed(confirm_block_count);

auto was_pending_promoted = pending->_pending_block_state->maybe_promote_pending();

Expand All @@ -1105,17 +1121,20 @@ struct controller_impl {

const auto& gpo = db.get<global_property_object>();
if( gpo.proposed_schedule_block_num.valid() && // if there is a proposed schedule that was proposed in a block ...
( *gpo.proposed_schedule_block_num <= pending->_pending_block_state->dpos_irreversible_blocknum ) && // ... that has now become irreversible ...
( *gpo.proposed_schedule_block_num <= pending->_pending_block_state->pbft_stable_checkpoint_blocknum ) && // ... that has now become irreversible ...
pending->_pending_block_state->pending_schedule.producers.size() == 0 && // ... and there is room for a new pending schedule ...
!was_pending_promoted // ... and not just because it was promoted to active at the start of this block, then:
!was_pending_promoted && // ... and not just because it was promoted to active at the start of this block, then:
pending->_pending_block_state->block_num == *gpo.proposed_schedule_block_num + 12 //TODO: to be optimised.
)
{
// Promote proposed schedule to pending schedule.
if( !replaying ) {
ilog( "promoting proposed schedule (set in block ${proposed_num}) to pending; current block: ${n} lib: ${lib} schedule: ${schedule} ",
("proposed_num", *gpo.proposed_schedule_block_num)("n", pending->_pending_block_state->block_num)
("lib", pending->_pending_block_state->dpos_irreversible_blocknum)
("lib", pending->_pending_block_state->bft_irreversible_blocknum)
("schedule", static_cast<producer_schedule_type>(gpo.proposed_schedule) ) );
last_promoted_proposed_schedule_block_num.reset();
last_promoted_proposed_schedule_block_num.emplace(pending->_pending_block_state->block_num);
}
pending->_pending_block_state->set_new_producers( gpo.proposed_schedule );
db.modify( gpo, [&]( auto& gp ) {
Expand Down Expand Up @@ -1236,6 +1255,9 @@ struct controller_impl {
EOS_ASSERT( b, block_validate_exception, "trying to push empty block" );
EOS_ASSERT( s != controller::block_status::incomplete, block_validate_exception, "invalid block status for a completed block" );
emit( self.pre_accepted_block, b );

set_pbft_lib();
set_pbft_lscb();
bool trust = !conf.force_all_checks && (s == controller::block_status::irreversible || s == controller::block_status::validated);
auto new_header_state = fork_db.add( b, trust );
if (conf.trusted_producers.count(b->producer)) {
Expand Down Expand Up @@ -1263,6 +1285,44 @@ struct controller_impl {
}
}

void pbft_commit_local( const block_id_type& id ) {
pending_pbft_lib.reset();
auto contains_proposed_schedule = false;
const auto& gpo = db.get<global_property_object>();
if (gpo.proposed_schedule_block_num.valid() && fork_db.get_block(id)->block_num == *gpo.proposed_schedule_block_num) {
contains_proposed_schedule = true;
last_proposed_schedule_block_num.reset();
last_proposed_schedule_block_num.emplace(*gpo.proposed_schedule_block_num);
}
pending_pbft_lib.emplace(pending_pbft_state{id, contains_proposed_schedule});
}

void set_pbft_lib() {

if ((!pending || pending->_block_status != controller::block_status::incomplete) && pending_pbft_lib ) {
fork_db.set_bft_irreversible(pending_pbft_lib->pbft_lib);
ilog("=====Committed local===== [lib: ${num}]", ("num", fork_db.get_block(pending_pbft_lib->pbft_lib)->block_num));
pending_pbft_lib.reset();
if (read_mode != db_read_mode::IRREVERSIBLE) {
maybe_switch_forks();
}
}
}

void set_pbft_latest_checkpoint( const block_id_type& id ) {
pending_pbft_checkpoint.reset();
pending_pbft_checkpoint.emplace(id);
}

void set_pbft_lscb() {
if ((!pending || pending->_block_status != controller::block_status::incomplete) && pending_pbft_checkpoint) {
fork_db.set_latest_checkpoint(*pending_pbft_checkpoint);
ilog("======set stable checkpoint====== [lscb: ${h}]", ("h", fork_db.get_block(*pending_pbft_checkpoint)->block_num));
pending_pbft_checkpoint.reset();

}
}

void maybe_switch_forks( controller::block_status s = controller::block_status::complete ) {
auto new_head = fork_db.head();

Expand Down Expand Up @@ -1604,6 +1664,15 @@ chainbase::database& controller::mutable_db()const { return my->db; }

const fork_database& controller::fork_db()const { return my->fork_db; }

//pbft_controller& controller::pbft()const { return my->pbft_ctrl; }

set<chain::account_name> controller::my_producers()const{
return my->conf.my_producers;
}

std::map<chain::public_key_type, signature_provider_type> controller::my_signature_providers()const{
return my->conf.my_signature_providers;
}

void controller::start_block( block_timestamp_type when, uint16_t confirm_block_count) {
validate_db_available_size();
Expand Down Expand Up @@ -1640,6 +1709,24 @@ void controller::push_confirmation( const header_confirmation& c ) {
my->push_confirmation( c );
}

void controller::pbft_commit_local( const block_id_type& id ) {
validate_db_available_size();
my->pbft_commit_local(id);
}

bool controller::pending_pbft_lib() {
if (my->pending_pbft_lib) return true;
return false;
}

void controller::set_pbft_latest_checkpoint( const block_id_type& id ) {
my->set_pbft_latest_checkpoint(id);
}

void controller::set_pbft_prepared_block_id(optional<block_id_type> bid){
my->pbft_prepared_block_id = bid;
}

transaction_trace_ptr controller::push_transaction( const transaction_metadata_ptr& trx, fc::time_point deadline, uint32_t billed_cpu_time_us ) {
validate_db_available_size();
EOS_ASSERT( get_read_mode() != chain::db_read_mode::READ_ONLY, transaction_type_exception, "push transaction not allowed in read-only mode" );
Expand Down Expand Up @@ -1759,6 +1846,32 @@ block_id_type controller::last_irreversible_block_id() const {

}

uint32_t controller::last_stable_checkpoint_block_num() const {
return my->head->pbft_stable_checkpoint_blocknum;
}

signed_block_ptr controller::last_irreversible_block() const {
auto lib_num = last_irreversible_block_num();

if (lib_num > 0)
return fetch_block_by_number(lib_num);
return signed_block_ptr();
}

block_num_type controller::last_proposed_schedule_block_num() const {
if (my->last_proposed_schedule_block_num) {
return *my->last_proposed_schedule_block_num;
}
return block_num_type{};
}

block_num_type controller::last_promoted_proposed_schedule_block_num() const {
if (my->last_promoted_proposed_schedule_block_num) {
return *my->last_promoted_proposed_schedule_block_num;
}
return block_num_type{};
}

const dynamic_global_property_object& controller::get_dynamic_global_properties()const {
return my->db.get<dynamic_global_property_object>();
}
Expand Down
Loading