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

IF: Calculate IF Genesis Block finality digest correctly #2353

Merged
merged 6 commits into from
Mar 29, 2024
Merged
Show file tree
Hide file tree
Changes from 4 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
45 changes: 28 additions & 17 deletions libraries/chain/block_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,45 +60,56 @@ block_state_ptr block_state::create_if_genesis_block(const block_state_legacy& b
auto result_ptr = std::make_shared<block_state>();
auto &result = *result_ptr;

// set block_header_state data ----
result.block_id = bsp.id();
result.header = bsp.header;
result.header_exts = bsp.header_exts;
result.block = bsp.block;
result.activated_protocol_features = bsp.activated_protocol_features;
result.core = finality_core::create_core_for_genesis_block(bsp.block_num());

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); // required by transition mechanism
result.active_finalizer_policy = std::make_shared<finalizer_policy>(*if_ext.new_finalizer_policy);
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;
result.proposer_policies = {}; // none pending at IF genesis block
result.finalizer_policies = {}; // none pending at IF genesis block
greg7mdp marked this conversation as resolved.
Show resolved Hide resolved
result.header_exts = bsp.header_exts;

// set block_state data ----
result.block = bsp.block;
result.strong_digest = result.compute_finality_digest(); // all block_header_state data populated in result at this point
result.weak_digest = create_weak_digest(result.strong_digest);

// TODO: https://github.com/AntelopeIO/leap/issues/2057
// TODO: Do not aggregate votes on blocks created from block_state_legacy. This can be removed when #2057 complete.
result.pending_qc = pending_quorum_certificate{result.active_finalizer_policy->finalizers.size(), result.active_finalizer_policy->threshold, result.active_finalizer_policy->max_weak_sum_before_weak_final()};
result.valid_qc = {}; // best qc received from the network inside block extension, empty until first savanna proper IF block
greg7mdp marked this conversation as resolved.
Show resolved Hide resolved

// Calculate Merkle tree root in Savanna way so that it is stored in Leaf Node when building block_state.
auto digests = *bsp.action_receipt_digests_savanna;
auto action_mroot_svnn = calculate_merkle(std::move(digests));

// built leaf_node and validation_tree
greg7mdp marked this conversation as resolved.
Show resolved Hide resolved
valid_t::finality_leaf_node_t leaf_node {
.block_num = bsp.block_num(),
.finality_digest = digest_type{},
.finality_digest = result.strong_digest,
.action_mroot = action_mroot_svnn
};
// construct valid structure
incremental_merkle_tree validation_tree;
validation_tree.append(fc::sha256::hash(leaf_node));

// construct valid structure
result.valid = valid_t {
.validation_tree = validation_tree,
.validation_mroots = { validation_tree.get_root() }
};

assert(result.block->contains_header_extension(instant_finality_extension::extension_id())); // required by transition mechanism
instant_finality_extension if_ext = result.block->extract_header_extension<instant_finality_extension>();
assert(if_ext.new_finalizer_policy); // required by transition mechanism
result.active_finalizer_policy = std::make_shared<finalizer_policy>(*if_ext.new_finalizer_policy);
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;
// TODO: https://github.com/AntelopeIO/leap/issues/2057
// TODO: Do not aggregate votes on blocks created from block_state_legacy. This can be removed when #2057 complete.
result.pending_qc = pending_quorum_certificate{result.active_finalizer_policy->finalizers.size(), result.active_finalizer_policy->threshold, result.active_finalizer_policy->max_weak_sum_before_weak_final()};
result.validated = bsp.is_valid();
result.pub_keys_recovered = bsp._pub_keys_recovered;
result.cached_trxs = bsp._cached_trxs;
result.action_mroot = action_mroot_svnn;
result.base_digest = {}; // calculated on demand in get_finality_data()
greg7mdp marked this conversation as resolved.
Show resolved Hide resolved

return result_ptr;
}
Expand Down Expand Up @@ -255,7 +266,7 @@ std::optional<quorum_certificate> block_state::get_best_qc() const {
return quorum_certificate{ block_num(), best_qc };
}

valid_t block_state::new_valid(const block_header_state& next_bhs, const digest_type& action_mroot) const {
valid_t block_state::new_valid(const block_header_state& next_bhs, const digest_type& action_mroot, const digest_type& strong_digest) const {
assert(valid);
assert(next_bhs.core.last_final_block_num() >= core.last_final_block_num());

Expand All @@ -270,7 +281,7 @@ valid_t block_state::new_valid(const block_header_state& next_bhs, const digest_
// construct block's finality leaf node.
valid_t::finality_leaf_node_t leaf_node{
.block_num = next_bhs.block_num(),
.finality_digest = next_bhs.compute_finality_digest(),
.finality_digest = strong_digest,
.action_mroot = action_mroot
};
auto leaf_node_digest = fc::sha256::hash(leaf_node);
Expand Down
8 changes: 4 additions & 4 deletions libraries/chain/controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -763,12 +763,12 @@ struct building_block {
// Create the valid structure for validating_bsp if it does not
// have one.
if (!validating_bsp->valid) {
validating_bsp->valid = bb.parent.new_valid(bhs, action_mroot);
validating_bsp->valid = bb.parent.new_valid(bhs, action_mroot, bb.parent.strong_digest);
linh2931 marked this conversation as resolved.
Show resolved Hide resolved
validating_bsp->action_mroot = action_mroot; // caching for constructing finality_data. Only needed when block is commited.
}
} else {
// Create the valid structure for producing
valid = bb.parent.new_valid(bhs, action_mroot);
valid = bb.parent.new_valid(bhs, action_mroot, bb.parent.strong_digest);
}

assembled_block::assembled_block_if ab{
Expand Down Expand Up @@ -1311,7 +1311,7 @@ struct controller_impl {
auto digests = *legacy->action_receipt_digests_savanna;
auto action_mroot = calculate_merkle(std::move(digests));
// Create the valid structure for producing
new_bsp->valid = prev->new_valid(*new_bsp, action_mroot);
new_bsp->valid = prev->new_valid(*new_bsp, action_mroot, new_bsp->strong_digest);
}
forkdb.add(new_bsp, legacy->is_valid() ? mark_valid_t::yes : mark_valid_t::no, ignore_duplicate_t::yes);
}
Expand Down Expand Up @@ -1525,7 +1525,7 @@ struct controller_impl {
auto digests = *bspl->action_receipt_digests_savanna;
auto action_mroot = calculate_merkle(std::move(digests));
// Create the valid structure for producing
new_bsp->valid = prev->new_valid(*new_bsp, action_mroot);
new_bsp->valid = prev->new_valid(*new_bsp, action_mroot, new_bsp->strong_digest);
prev = new_bsp;
}
}
Expand Down
5 changes: 2 additions & 3 deletions libraries/chain/include/eosio/chain/block_state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ struct block_state : public block_header_state { // block_header_state provi
bool pub_keys_recovered = false;
deque<transaction_metadata_ptr> cached_trxs;
digest_type action_mroot; // For finality_data sent to SHiP
std::optional<digest_type> base_digest; // For finality_data sent to SHiP
std::optional<digest_type> base_digest; // For finality_data sent to SHiP, computed on demand in get_finality_data()

// ------ private methods -----------------------------------------------------------
bool is_valid() const { return validated; }
Expand Down Expand Up @@ -109,8 +109,7 @@ struct block_state : public block_header_state { // block_header_state provi
uint32_t final_on_strong_qc_block_num() const { return core.final_on_strong_qc_block_num; }

// build next valid structure from current one with input of next
// header state and action_mroot
valid_t new_valid(const block_header_state& bhs, const digest_type& action_mroot) const;
valid_t new_valid(const block_header_state& bhs, const digest_type& action_mroot, const digest_type& strong_digest) const;

// Returns the root digest of the finality tree associated with the target_block_num
// [core.last_final_block_num, block_num]
Expand Down
Loading