Skip to content

Commit

Permalink
dpos pbft
Browse files Browse the repository at this point in the history
  • Loading branch information
qianxiaofeng committed Dec 4, 2018
1 parent 59626f1 commit 13ba0a3
Show file tree
Hide file tree
Showing 29 changed files with 3,700 additions and 67 deletions.
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

0 comments on commit 13ba0a3

Please sign in to comment.