Skip to content

Commit

Permalink
Merge branch 'GH-525-block-propagation-3.1' into GH-525-block-propaga…
Browse files Browse the repository at this point in the history
…tion-3.2
  • Loading branch information
heifner committed Dec 20, 2022
2 parents 6f3ad96 + 9b5ec62 commit 95d5620
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 58 deletions.
14 changes: 7 additions & 7 deletions libraries/chain/controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2136,14 +2136,14 @@ struct controller_impl {
} FC_CAPTURE_AND_RETHROW() } /// apply_block


block_state_ptr create_block_state( const block_id_type& id, const signed_block_ptr& b, const block_header_state_ptr& prev ) {
block_state_ptr create_block_state( const block_id_type& id, const signed_block_ptr& b, const block_header_state& prev ) {
auto trx_mroot = calculate_trx_merkle( b->transactions );
EOS_ASSERT( b->transaction_mroot == trx_mroot, block_validate_exception,
"invalid block transaction merkle root ${b} != ${c}", ("b", b->transaction_mroot)("c", trx_mroot) );

const bool skip_validate_signee = false;
auto bsp = std::make_shared<block_state>(
*prev,
prev,
b,
protocol_features.get_protocol_feature_set(),
[this]( block_timestamp_type timestamp,
Expand All @@ -2170,19 +2170,18 @@ struct controller_impl {
EOS_ASSERT( prev, unlinkable_block_exception,
"unlinkable block ${id}", ("id", id)("previous", b->previous) );

return control->create_block_state( id, b, prev );
return control->create_block_state( id, b, *prev );
} );
}

block_state_ptr create_block_state( const block_id_type& id, const signed_block_ptr& b ) {
EOS_ASSERT( b, block_validate_exception, "null block" );

block_state_ptr bsp;
// previous not found could mean that previous block not applied yet
auto prev = fork_db.get_block_header( b->previous );
if( !prev ) return bsp;
if( !prev ) return {};

return create_block_state( id, b, prev );
return create_block_state( id, b, *prev );
}

void push_block( controller::block_report& br,
Expand Down Expand Up @@ -2922,7 +2921,8 @@ block_state_ptr controller::create_block_state( const block_id_type& id, const s

void controller::push_block( controller::block_report& br,
const block_state_ptr& bsp,
const forked_branch_callback& forked_branch_cb, const trx_meta_cache_lookup& trx_lookup )
const forked_branch_callback& forked_branch_cb,
const trx_meta_cache_lookup& trx_lookup )
{
validate_db_available_size();
my->push_block( br, bsp, forked_branch_cb, trx_lookup );
Expand Down
85 changes: 50 additions & 35 deletions libraries/chain/fork_database.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,12 @@ namespace eosio { namespace chain {
block_state_ptr head;
fc::path datadir;

void open_impl( const std::function<void( block_timestamp_type,
const flat_set<digest_type>&,
const vector<digest_type>& )>& validator );
void close_impl();


block_header_state_ptr get_block_header_impl( const block_id_type& id )const;
block_state_ptr get_block_impl( const block_id_type& id )const;
void reset_impl( const block_header_state& root_bhs );
Expand Down Expand Up @@ -101,10 +107,17 @@ namespace eosio { namespace chain {
const vector<digest_type>& )>& validator )
{
std::lock_guard g( my->mtx );
if (!fc::is_directory(my->datadir))
fc::create_directories(my->datadir);
my->open_impl( validator );
}

void fork_database_impl::open_impl( const std::function<void( block_timestamp_type,
const flat_set<digest_type>&,
const vector<digest_type>& )>& validator )
{
if (!fc::is_directory(datadir))
fc::create_directories(datadir);

auto fork_db_dat = my->datadir / config::forkdb_filename;
auto fork_db_dat = datadir / config::forkdb_filename;
if( fc::exists( fork_db_dat ) ) {
try {
string content;
Expand All @@ -115,57 +128,57 @@ namespace eosio { namespace chain {
// validate totem
uint32_t totem = 0;
fc::raw::unpack( ds, totem );
EOS_ASSERT( totem == magic_number, fork_database_exception,
EOS_ASSERT( totem == fork_database::magic_number, fork_database_exception,
"Fork database file '${filename}' has unexpected magic number: ${actual_totem}. Expected ${expected_totem}",
("filename", fork_db_dat.generic_string())
("actual_totem", totem)
("expected_totem", magic_number)
("expected_totem", fork_database::magic_number)
);

// validate version
uint32_t version = 0;
fc::raw::unpack( ds, version );
EOS_ASSERT( version >= min_supported_version && version <= max_supported_version,
EOS_ASSERT( version >= fork_database::min_supported_version && version <= fork_database::max_supported_version,
fork_database_exception,
"Unsupported version of fork database file '${filename}'. "
"Fork database version is ${version} while code supports version(s) [${min},${max}]",
("filename", fork_db_dat.generic_string())
("version", version)
("min", min_supported_version)
("max", max_supported_version)
("min", fork_database::min_supported_version)
("max", fork_database::max_supported_version)
);

block_header_state bhs;
fc::raw::unpack( ds, bhs );
my->reset_impl( bhs );
reset_impl( bhs );

unsigned_int size; fc::raw::unpack( ds, size );
for( uint32_t i = 0, n = size.value; i < n; ++i ) {
block_state s;
fc::raw::unpack( ds, s );
// do not populate transaction_metadatas, they will be created as needed in apply_block with appropriate key recovery
s.header_exts = s.block->validate_and_extract_header_extensions();
my->add_impl( std::make_shared<block_state>( std::move( s ) ), false, true, validator );
add_impl( std::make_shared<block_state>( std::move( s ) ), false, true, validator );
}
block_id_type head_id;
fc::raw::unpack( ds, head_id );

if( my->root->id == head_id ) {
my->head = my->root;
if( root->id == head_id ) {
head = root;
} else {
my->head = my->get_block_impl( head_id );
EOS_ASSERT( my->head, fork_database_exception,
head = get_block_impl( head_id );
EOS_ASSERT( head, fork_database_exception,
"could not find head while reconstructing fork database from file; '${filename}' is likely corrupted",
("filename", fork_db_dat.generic_string()) );
}

auto candidate = my->index.get<by_lib_block_num>().begin();
if( candidate == my->index.get<by_lib_block_num>().end() || !(*candidate)->is_valid() ) {
EOS_ASSERT( my->head->id == my->root->id, fork_database_exception,
auto candidate = index.get<by_lib_block_num>().begin();
if( candidate == index.get<by_lib_block_num>().end() || !(*candidate)->is_valid() ) {
EOS_ASSERT( head->id == root->id, fork_database_exception,
"head not set to root despite no better option available; '${filename}' is likely corrupted",
("filename", fork_db_dat.generic_string()) );
} else {
EOS_ASSERT( !first_preferred( **candidate, *my->head ), fork_database_exception,
EOS_ASSERT( !first_preferred( **candidate, *head ), fork_database_exception,
"head not set to best available option available; '${filename}' is likely corrupted",
("filename", fork_db_dat.generic_string()) );
}
Expand All @@ -177,24 +190,28 @@ namespace eosio { namespace chain {

void fork_database::close() {
std::lock_guard g( my->mtx );
auto fork_db_dat = my->datadir / config::forkdb_filename;
my->close_impl();
}

void fork_database_impl::close_impl() {
auto fork_db_dat = datadir / config::forkdb_filename;

if( !my->root ) {
if( my->index.size() > 0 ) {
if( !root ) {
if( index.size() > 0 ) {
elog( "fork_database is in a bad state when closing; not writing out '${filename}'",
("filename", fork_db_dat.generic_string()) );
}
return;
}

std::ofstream out( fork_db_dat.generic_string().c_str(), std::ios::out | std::ios::binary | std::ofstream::trunc );
fc::raw::pack( out, magic_number );
fc::raw::pack( out, max_supported_version ); // write out current version which is always max_supported_version
fc::raw::pack( out, *static_cast<block_header_state*>(&*my->root) );
uint32_t num_blocks_in_fork_db = my->index.size();
fc::raw::pack( out, fork_database::magic_number );
fc::raw::pack( out, fork_database::max_supported_version ); // write out current version which is always max_supported_version
fc::raw::pack( out, *static_cast<block_header_state*>(&*root) );
uint32_t num_blocks_in_fork_db = index.size();
fc::raw::pack( out, unsigned_int{num_blocks_in_fork_db} );

const auto& indx = my->index.get<by_lib_block_num>();
const auto& indx = index.get<by_lib_block_num>();

auto unvalidated_itr = indx.rbegin();
auto unvalidated_end = boost::make_reverse_iterator( indx.lower_bound( false ) );
Expand Down Expand Up @@ -229,18 +246,18 @@ namespace eosio { namespace chain {
fc::raw::pack( out, *(*itr) );
}

if( my->head ) {
fc::raw::pack( out, my->head->id );
if( head ) {
fc::raw::pack( out, head->id );
} else {
elog( "head not set in fork database; '${filename}' will be corrupted",
("filename", fork_db_dat.generic_string()) );
}

my->index.clear();
index.clear();
}

fork_database::~fork_database() {
close();
my->close_impl();
}

void fork_database::reset( const block_header_state& root_bhs ) {
Expand Down Expand Up @@ -519,9 +536,7 @@ namespace eosio { namespace chain {
}

for( const auto& block_id : remove_queue ) {
auto itr = index.find( block_id );
if( itr != index.end() )
index.erase(itr);
index.erase( block_id );
}
}

Expand Down Expand Up @@ -550,12 +565,12 @@ namespace eosio { namespace chain {
}
}

block_state_ptr fork_database::get_block(const block_id_type& id)const {
block_state_ptr fork_database::get_block(const block_id_type& id)const {
std::shared_lock g( my->mtx );
return my->get_block_impl(id);
}

block_state_ptr fork_database_impl::get_block_impl(const block_id_type& id)const {
block_state_ptr fork_database_impl::get_block_impl(const block_id_type& id)const {
auto itr = index.find( id );
if( itr != index.end() )
return *itr;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,6 @@ namespace eosio { namespace chain { namespace plugin_interface {
}

namespace incoming {
namespace channels {
using transaction = channel_decl<struct transaction_tag, packed_transaction_ptr>;
}

namespace methods {
// synchronously push a block/trx to a single provider, block_state_ptr may be null
using block_sync = method_decl<chain_plugin_interface, bool(const signed_block_ptr&, const std::optional<block_id_type>&, const block_state_ptr&), first_provider_policy>;
Expand Down
2 changes: 1 addition & 1 deletion plugins/chain_plugin/chain_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2170,7 +2170,7 @@ fc::variant read_only::get_block_header_state(const get_block_header_state_param

void read_write::push_block(read_write::push_block_params&& params, next_function<read_write::push_block_results> next) {
try {
app().get_method<incoming::methods::block_sync>()(std::make_shared<signed_block>( std::move( params ) ), std::optional<block_id_type>{}, block_state_ptr{});
app().get_method<incoming::methods::block_sync>()(std::make_shared<signed_block>( std::move(params) ), std::optional<block_id_type>{}, block_state_ptr{});
} catch ( boost::interprocess::bad_alloc& ) {
chain_plugin::handle_db_exhaustion();
} catch ( const std::bad_alloc& ) {
Expand Down
11 changes: 1 addition & 10 deletions plugins/producer_plugin/producer_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -328,9 +328,7 @@ class producer_plugin_impl : public std::enable_shared_from_this<producer_plugin

chain_plugin* chain_plug = nullptr;

incoming::channels::transaction::channel_type::handle _incoming_transaction_subscription;

compat::channels::transaction_ack::channel_type& _transaction_ack_channel;
compat::channels::transaction_ack::channel_type& _transaction_ack_channel;

incoming::methods::block_sync::method_type::handle _incoming_block_sync_provider;
incoming::methods::transaction_async::method_type::handle _incoming_transaction_async_provider;
Expand Down Expand Up @@ -962,13 +960,6 @@ void producer_plugin::plugin_initialize(const boost::program_options::variables_
}
}

my->_incoming_transaction_subscription = app().get_channel<incoming::channels::transaction>().subscribe(
[this](const packed_transaction_ptr& trx) {
try {
my->on_incoming_transaction_async(trx, false, false, false, [](const auto&){});
} LOG_AND_DROP();
});

my->_incoming_block_sync_provider = app().get_method<incoming::methods::block_sync>().register_provider(
[this](const signed_block_ptr& block, const std::optional<block_id_type>& block_id, const block_state_ptr& bsp) {
return my->on_incoming_block(block, block_id, bsp);
Expand Down
2 changes: 1 addition & 1 deletion unittests/block_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ BOOST_AUTO_TEST_CASE(block_with_invalid_tx_mroot_test)
auto bsf = validator.control->create_block_state_future( copy_b->calculate_id(), copy_b );
validator.control->abort_block();
controller::block_report br;
BOOST_REQUIRE_EXCEPTION(validator.control->push_block( br, bsf.get(), forked_branch_callback{}, trx_meta_cache_lookup{} ), fc::exception ,
BOOST_REQUIRE_EXCEPTION(validator.control->push_block( br, bsf.get(), forked_branch_callback{}, trx_meta_cache_lookup{} ), fc::exception,
[] (const fc::exception &e)->bool {
return e.code() == block_validate_exception::code_value &&
e.to_detail_string().find("invalid block transaction merkle root") != std::string::npos;
Expand Down

0 comments on commit 95d5620

Please sign in to comment.