Skip to content

Commit

Permalink
Merge pull request #125 from AntelopeIO/GH-5-diff-producers
Browse files Browse the repository at this point in the history
IF: Use proposer diffs in instant_finality_extension
  • Loading branch information
heifner authored May 10, 2024
2 parents 72c2958 + 35910b6 commit 5ce056a
Show file tree
Hide file tree
Showing 11 changed files with 148 additions and 69 deletions.
37 changes: 23 additions & 14 deletions libraries/chain/block_header_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,14 +79,15 @@ const finalizer_policy& block_header_state::get_last_proposed_finalizer_policy()
return *active_finalizer_policy;
}

finalizer_policy_diff block_header_state::calculate_finalizer_policy_diff(const finalizer_policy& new_policy) const {
return get_last_proposed_finalizer_policy().create_diff(new_policy);
}

finalizer_policy block_header_state::calculate_finalizer_policy(const finalizer_policy_diff& diff) const {
finalizer_policy result = get_last_proposed_finalizer_policy();
result.apply_diff(diff);
return result;
// The last proposed proposer policy, if none proposed then the active proposer policy
const proposer_policy& block_header_state::get_last_proposed_proposer_policy() const {
if (proposer_policies.empty()) {
assert(active_proposer_policy);
return *active_proposer_policy;
}
auto it = proposer_policies.rbegin();
assert(it != proposer_policies.rend());
return *it->second;
}

// -------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -125,10 +126,14 @@ void finish_next(const block_header_state& prev,
}
}

if (if_ext.new_proposer_policy) {
std::optional<proposer_policy> new_proposer_policy;
if (if_ext.new_proposer_policy_diff) {
new_proposer_policy = prev.get_last_proposed_proposer_policy().apply_diff(*if_ext.new_proposer_policy_diff);
}
if (new_proposer_policy) {
// called when assembling the block
next_header_state.proposer_policies[if_ext.new_proposer_policy->active_time] =
std::move(if_ext.new_proposer_policy);
next_header_state.proposer_policies[new_proposer_policy->active_time] =
std::make_shared<proposer_policy>(std::move(*new_proposer_policy));
}

// finality_core
Expand Down Expand Up @@ -179,7 +184,7 @@ void finish_next(const block_header_state& prev,
}

if (if_ext.new_finalizer_policy_diff) {
finalizer_policy new_finalizer_policy = prev.calculate_finalizer_policy(*if_ext.new_finalizer_policy_diff);
finalizer_policy new_finalizer_policy = prev.get_last_proposed_finalizer_policy().apply_diff(*if_ext.new_finalizer_policy_diff);

// a new `finalizer_policy` was proposed in the previous block, and is present in the previous
// block's header extensions.
Expand Down Expand Up @@ -230,11 +235,15 @@ block_header_state block_header_state::next(block_header_state_input& input) con
// ------------------
std::optional<finalizer_policy_diff> new_finalizer_policy_diff;
if (input.new_finalizer_policy) {
new_finalizer_policy_diff = calculate_finalizer_policy_diff(*input.new_finalizer_policy);
new_finalizer_policy_diff = get_last_proposed_finalizer_policy().create_diff(*input.new_finalizer_policy);
}
std::optional<proposer_policy_diff> new_proposer_policy_diff;
if (input.new_proposer_policy) {
new_proposer_policy_diff = get_last_proposed_proposer_policy().create_diff(*input.new_proposer_policy);
}
instant_finality_extension new_if_ext { input.most_recent_ancestor_with_qc,
std::move(new_finalizer_policy_diff),
std::move(input.new_proposer_policy) };
std::move(new_proposer_policy_diff) };

uint16_t if_ext_id = instant_finality_extension::extension_id();
emplace_extension(next_header_state.header.header_extensions, if_ext_id, fc::raw::pack(new_if_ext));
Expand Down
3 changes: 1 addition & 2 deletions libraries/chain/block_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,7 @@ block_state_ptr block_state::create_if_genesis_block(const block_state_legacy& b
assert(bsp.block->contains_header_extension(instant_finality_extension::extension_id())); // required by transition mechanism
instant_finality_extension if_ext = bsp.block->extract_header_extension<instant_finality_extension>();
assert(if_ext.new_finalizer_policy_diff); // required by transition mechanism
result.active_finalizer_policy = std::make_shared<finalizer_policy>();
result.active_finalizer_policy->apply_diff(std::move(*if_ext.new_finalizer_policy_diff));
result.active_finalizer_policy = std::make_shared<finalizer_policy>(finalizer_policy{}.apply_diff(std::move(*if_ext.new_finalizer_policy_diff)));
result.active_proposer_policy = std::make_shared<proposer_policy>();
result.active_proposer_policy->active_time = bsp.timestamp();
result.active_proposer_policy->proposer_schedule = bsp.active_schedule;
Expand Down
10 changes: 5 additions & 5 deletions libraries/chain/controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -706,7 +706,7 @@ struct building_block {
assembled_block assemble_block(boost::asio::io_context& ioc,
const protocol_feature_set& pfs,
fork_database& fork_db,
std::unique_ptr<proposer_policy> new_proposer_policy,
std::optional<proposer_policy> new_proposer_policy,
std::optional<finalizer_policy> new_finalizer_policy,
bool validating,
std::optional<qc_data_t> validating_qc_data,
Expand Down Expand Up @@ -3164,13 +3164,13 @@ struct controller_impl {
resource_limits.process_block_usage(bb.block_num());

// Any proposer policy?
auto process_new_proposer_policy = [&](auto&) -> std::unique_ptr<proposer_policy> {
std::unique_ptr<proposer_policy> new_proposer_policy;
auto process_new_proposer_policy = [&](auto&) -> std::optional<proposer_policy> {
std::optional<proposer_policy> new_proposer_policy;
const auto& gpo = db.get<global_property_object>();
if (gpo.proposed_schedule_block_num) {
std::optional<uint32_t> version = pending->get_next_proposer_schedule_version(gpo.proposed_schedule.producers);
if (version) {
new_proposer_policy = std::make_unique<proposer_policy>();
new_proposer_policy.emplace();
new_proposer_policy->active_time = detail::get_next_next_round_block_time(bb.timestamp());
new_proposer_policy->proposer_schedule = producer_authority_schedule::from_shared(gpo.proposed_schedule);
new_proposer_policy->proposer_schedule.version = *version;
Expand All @@ -3186,7 +3186,7 @@ struct controller_impl {
}
return new_proposer_policy;
};
auto new_proposer_policy = apply_s<std::unique_ptr<proposer_policy>>(chain_head, process_new_proposer_policy);
auto new_proposer_policy = apply_s<std::optional<proposer_policy>>(chain_head, process_new_proposer_policy);

// Any finalizer policy?
std::optional<finalizer_policy> new_finalizer_policy = std::nullopt;
Expand Down
5 changes: 2 additions & 3 deletions libraries/chain/include/eosio/chain/block_header_state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ struct building_block_input {
// this struct can be extracted from a building block
struct block_header_state_input : public building_block_input {
digest_type transaction_mroot; // Comes from std::get<checksum256_type>(building_block::trx_mroot_or_receipt_digests)
std::shared_ptr<proposer_policy> new_proposer_policy; // Comes from building_block::new_proposer_policy
std::optional<proposer_policy> new_proposer_policy; // Comes from building_block::new_proposer_policy
std::optional<finalizer_policy> new_finalizer_policy; // Comes from building_block::new_finalizer_policy
qc_claim_t most_recent_ancestor_with_qc; // Comes from traversing branch from parent and calling get_best_qc()
digest_type finality_mroot_claim;
Expand Down Expand Up @@ -131,8 +131,7 @@ struct block_header_state {
const producer_authority& get_scheduled_producer(block_timestamp_type t) const;

const finalizer_policy& get_last_proposed_finalizer_policy() const;
finalizer_policy_diff calculate_finalizer_policy_diff(const finalizer_policy& new_policy) const;
finalizer_policy calculate_finalizer_policy(const finalizer_policy_diff& diff) const;
const proposer_policy& get_last_proposed_proposer_policy() const;
};

using block_header_state_ptr = std::shared_ptr<block_header_state>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,13 @@ namespace eosio::chain {

template <typename X>
requires std::same_as<std::decay_t<X>, finalizer_policy_diff>
void apply_diff(X&& diff) {
generation = diff.generation;
threshold = diff.threshold;
finalizers = finalizers_differ::apply_diff(std::move(finalizers), std::forward<X>(diff).finalizers_diff);
[[nodiscard]] finalizer_policy apply_diff(X&& diff) const {
finalizer_policy result;
result.generation = diff.generation;
result.threshold = diff.threshold;
auto copy = finalizers;
result.finalizers = finalizers_differ::apply_diff(std::move(copy), std::forward<X>(diff).finalizers_diff);
return result;
}

// max accumulated weak weight before becoming weak_final
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ struct instant_finality_extension : fc::reflect_init {

instant_finality_extension() = default;
instant_finality_extension(qc_claim_t qc_claim,
std::optional<finalizer_policy_diff> new_finalizer_policy_diff,
std::shared_ptr<proposer_policy> new_proposer_policy) :
std::optional<finalizer_policy_diff>&& new_finalizer_policy_diff,
std::optional<proposer_policy_diff>&& new_proposer_policy_diff) :
qc_claim(qc_claim),
new_finalizer_policy_diff(std::move(new_finalizer_policy_diff)),
new_proposer_policy(std::move(new_proposer_policy))
new_proposer_policy_diff(std::move(new_proposer_policy_diff))
{}

void reflector_init() const {
Expand All @@ -27,9 +27,9 @@ struct instant_finality_extension : fc::reflect_init {

qc_claim_t qc_claim;
std::optional<finalizer_policy_diff> new_finalizer_policy_diff;
std::shared_ptr<proposer_policy> new_proposer_policy;
std::optional<proposer_policy_diff> new_proposer_policy_diff;
};

} /// eosio::chain

FC_REFLECT( eosio::chain::instant_finality_extension, (qc_claim)(new_finalizer_policy_diff)(new_proposer_policy) )
FC_REFLECT( eosio::chain::instant_finality_extension, (qc_claim)(new_finalizer_policy_diff)(new_proposer_policy_diff) )
34 changes: 31 additions & 3 deletions libraries/chain/include/eosio/chain/finality/proposer_policy.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,44 @@

namespace eosio::chain {

static_assert(std::numeric_limits<uint8_t>::max() >= config::max_producers - 1);
using producer_auth_differ = fc::ordered_diff<producer_authority, uint8_t>;
using producer_auth_diff_t = producer_auth_differ::diff_result;

struct proposer_policy_diff {
uint32_t version = 0; ///< sequentially incrementing version number of producer_authority_schedule
block_timestamp_type active_time; // block when schedule will become active
producer_auth_diff_t producer_auth_diff;
};

struct proposer_policy {
constexpr static uint8_t current_schema_version = 1;
uint8_t schema_version {current_schema_version};
// Useful for light clients, not necessary for nodeos
block_timestamp_type active_time; // block when schedule will become active
producer_authority_schedule proposer_schedule;

proposer_policy_diff create_diff(const proposer_policy& target) const {
return {.version = target.proposer_schedule.version,
.active_time = target.active_time,
.producer_auth_diff = producer_auth_differ::diff(proposer_schedule.producers, target.proposer_schedule.producers)};
}

template <typename X>
requires std::same_as<std::decay_t<X>, proposer_policy_diff>
[[nodiscard]] proposer_policy apply_diff(X&& diff) const {
proposer_policy result;
result.proposer_schedule.version = diff.version;
result.active_time = diff.active_time;
auto copy = proposer_schedule.producers;
result.proposer_schedule.producers = producer_auth_differ::apply_diff(std::move(copy),
std::forward<X>(diff).producer_auth_diff);
return result;
}
};

using proposer_policy_ptr = std::shared_ptr<proposer_policy>;

} /// eosio::chain

FC_REFLECT( eosio::chain::proposer_policy, (schema_version)(active_time)(proposer_schedule) )
FC_REFLECT( eosio::chain::proposer_policy, (active_time)(proposer_schedule) )
FC_REFLECT( eosio::chain::producer_auth_diff_t, (remove_indexes)(insert_indexes) )
FC_REFLECT( eosio::chain::proposer_policy_diff, (version)(active_time)(producer_auth_diff) )
4 changes: 1 addition & 3 deletions libraries/testing/include/eosio/testing/tester.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -861,9 +861,7 @@ namespace eosio::testing {
auto b = produce_block();

BOOST_REQUIRE_EQUAL(t.lib_block->block_num(), pt_block->block_num());
finalizer_policy fin_policy;
fin_policy.apply_diff(*fin_policy_diff);
return fin_policy;
return finalizer_policy{}.apply_diff(*fin_policy_diff);
}

Tester& t;
Expand Down
19 changes: 9 additions & 10 deletions unittests/block_header_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ BOOST_AUTO_TEST_CASE(instant_finality_extension_with_empty_values_test)
header.header_extensions,
instant_finality_extension::extension_id(),
fc::raw::pack( instant_finality_extension{qc_claim_t{last_qc_block_num, is_last_strong_qc},
std::optional<finalizer_policy_diff>{}, std::shared_ptr<proposer_policy>{}} )
std::optional<finalizer_policy_diff>{}, std::optional<proposer_policy_diff>{}} )
);

std::optional<block_header_extension> ext = header.extract_header_extension(instant_finality_extension::extension_id());
Expand All @@ -34,7 +34,7 @@ BOOST_AUTO_TEST_CASE(instant_finality_extension_with_empty_values_test)
BOOST_REQUIRE_EQUAL( if_extension.qc_claim.block_num, last_qc_block_num );
BOOST_REQUIRE_EQUAL( if_extension.qc_claim.is_strong_qc, is_last_strong_qc );
BOOST_REQUIRE( !if_extension.new_finalizer_policy_diff );
BOOST_REQUIRE( !if_extension.new_proposer_policy );
BOOST_REQUIRE( !if_extension.new_proposer_policy_diff );
}

// test for instant_finality_extension uniqueness
Expand All @@ -46,19 +46,19 @@ BOOST_AUTO_TEST_CASE(instant_finality_extension_uniqueness_test)
header.header_extensions,
instant_finality_extension::extension_id(),
fc::raw::pack( instant_finality_extension{qc_claim_t{0, false}, {std::nullopt},
std::shared_ptr<proposer_policy>{}} )
std::optional<proposer_policy_diff>{}} )
);

std::vector<finalizer_authority> finalizers { {"test description", 50, fc::crypto::blslib::bls_public_key{"PUB_BLS_qVbh4IjYZpRGo8U_0spBUM-u-r_G0fMo4MzLZRsKWmm5uyeQTp74YFaMN9IDWPoVVT5rj_Tw1gvps6K9_OZ6sabkJJzug3uGfjA6qiaLbLh5Fnafwv-nVgzzzBlU2kwRrcHc8Q" }} };
auto fin_policy = std::make_shared<finalizer_policy>();
finalizer_policy_diff new_finalizer_policy_diff = fin_policy->create_diff(finalizer_policy{.generation = 1, .threshold = 100, .finalizers = finalizers});

proposer_policy_ptr new_proposer_policy = std::make_shared<proposer_policy>(1, block_timestamp_type{200}, producer_authority_schedule{} );
proposer_policy_diff new_proposer_policy_diff = proposer_policy_diff{.version = 1, .active_time = block_timestamp_type{200}, .producer_auth_diff = {}};

emplace_extension(
header.header_extensions,
instant_finality_extension::extension_id(),
fc::raw::pack( instant_finality_extension{qc_claim_t{100, true}, new_finalizer_policy_diff, new_proposer_policy} )
fc::raw::pack( instant_finality_extension{qc_claim_t{100, true}, new_finalizer_policy_diff, new_proposer_policy_diff} )
);

BOOST_CHECK_THROW(header.validate_and_extract_header_extensions(), invalid_block_header_extension);
Expand All @@ -75,12 +75,12 @@ BOOST_AUTO_TEST_CASE(instant_finality_extension_with_values_test)
auto fin_policy = std::make_shared<finalizer_policy>();
finalizer_policy_diff new_finalizer_policy_diff = fin_policy->create_diff(finalizer_policy{.generation = 1, .threshold = 100, .finalizers = finalizers});

proposer_policy_ptr new_proposer_policy = std::make_shared<proposer_policy>(1, block_timestamp_type{200}, producer_authority_schedule{} );
proposer_policy_diff new_proposer_policy_diff = proposer_policy_diff{.version = 1, .active_time = block_timestamp_type{200}, .producer_auth_diff = {}};

emplace_extension(
header.header_extensions,
instant_finality_extension::extension_id(),
fc::raw::pack( instant_finality_extension{qc_claim_t{last_qc_block_num, is_strong_qc}, new_finalizer_policy_diff, new_proposer_policy} )
fc::raw::pack( instant_finality_extension{qc_claim_t{last_qc_block_num, is_strong_qc}, new_finalizer_policy_diff, new_proposer_policy_diff} )
);

std::optional<block_header_extension> ext = header.extract_header_extension(instant_finality_extension::extension_id());
Expand All @@ -98,9 +98,8 @@ BOOST_AUTO_TEST_CASE(instant_finality_extension_with_values_test)
BOOST_REQUIRE_EQUAL(if_extension.new_finalizer_policy_diff->finalizers_diff.insert_indexes[0].second.weight, 50u);
BOOST_REQUIRE_EQUAL(if_extension.new_finalizer_policy_diff->finalizers_diff.insert_indexes[0].second.public_key.to_string(), "PUB_BLS_qVbh4IjYZpRGo8U_0spBUM-u-r_G0fMo4MzLZRsKWmm5uyeQTp74YFaMN9IDWPoVVT5rj_Tw1gvps6K9_OZ6sabkJJzug3uGfjA6qiaLbLh5Fnafwv-nVgzzzBlU2kwRrcHc8Q");

BOOST_REQUIRE( !!if_extension.new_proposer_policy );
BOOST_REQUIRE_EQUAL(if_extension.new_proposer_policy->schema_version, 1u);
fc::time_point t = (fc::time_point)(if_extension.new_proposer_policy->active_time);
BOOST_REQUIRE( !!if_extension.new_proposer_policy_diff );
fc::time_point t = (fc::time_point)(if_extension.new_proposer_policy_diff->active_time);
BOOST_REQUIRE_EQUAL(t.time_since_epoch().to_seconds(), 946684900ll);
}

Expand Down
Loading

0 comments on commit 5ce056a

Please sign in to comment.