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: Implement computing finality digest #2282

Merged
merged 71 commits into from
Mar 14, 2024

Conversation

linh2931
Copy link
Member

@linh2931 linh2931 commented Mar 5, 2024

A finality digest is a hash of a series sub-digests required for IBC verification. It is built from a hash of a serialization of light_header_protocol_version, active_finalizer_policy_generation, finality_tree_digest, and a combination of base_digest and active_finalizer_policy_digest. base_digest is a hash of a serialization of deterministic fields of block_header_state, including header, core, finalizer_policies, active_proposer_policy, proposer_policies, and activated_protocol_features.

finality_tree is defined as following:

  1. A Finality Merkle Tree is a Merkle tree over a sequence of Finality Leaf Nodes,
    one for each block starting from the IF Genesis Block and ending at some
    specified descendant block.
  2. The Validation Tree associated with a target block is the Finality Merkle
    Tree over Finality Leaf Nodes starting with the one for the IF Genesis Block
    and ending with the one for the block that is the parent of the the target Block.
  3. The Finality Tree ssociated with a target block is the Validation Tree of the
    block referenced by the target block's final_on_strong_qc_block_num.
    That is, validation_tree(core.final_on_strong_qc_block_num))

A valid structure is introduced into block_state to hold all necessary information.

This PR implemented computing finality digest based on finality merkle tree, validation tree, finality tree, and validated structure.

See #2080 for design details.

Resolved #2080

@arhag arhag linked an issue Mar 5, 2024 that may be closed by this pull request
@ericpassmore
Copy link
Contributor

Note:start
group: IF
category: INTERNALS
summary: Implementation of finality digest, a hash of a series sub-digests, required for IBC verification.
Note:end

@linh2931 linh2931 marked this pull request as draft March 6, 2024 13:47
…shot

IF: Include `block_state::valid` in the snapshot.
finalizer_policy_ptr active_finalizer_policy;
proposer_policy_ptr active_proposer_policy;
flat_map<block_timestamp_type, proposer_policy_ptr> proposer_policies;
flat_map<uint32_t, finalizer_policy_ptr> finalizer_policies;

// from block_state
using valid_t = uint32_t; // snapshot todo
std::optional<valid_t> valid;
std::optional<valid_t> valid;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no need for this to be optional within a snapshot.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I remember you mentioned that it should always be present, and the std::optional was just because the valid_t is not be available when block_state is initially created.

I assume that when the snapshot is initiated, and we save the chain head to the snapshot, we can FC_ASSERT that the valid member is populated, right?

Copy link
Member

@arhag arhag Mar 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, we can assert that the valid structure exists at the time the snapshot is being produced. It must always be the case.

In the snapshot itself, the valid structure must always be present, which is why I say it shouldn't be an optional type within this struct. It should still be optional within block_state. But when loading the root block_state from a snapshot, valid should always end up populated.

libraries/chain/block_header_state.cpp Outdated Show resolved Hide resolved
libraries/chain/include/eosio/chain/block_header_state.hpp Outdated Show resolved Hide resolved
libraries/chain/include/eosio/chain/block_header_state.hpp Outdated Show resolved Hide resolved
libraries/chain/block_header_state.cpp Outdated Show resolved Hide resolved
libraries/chain/controller.cpp Outdated Show resolved Hide resolved
libraries/chain/block_header.cpp Outdated Show resolved Hide resolved
libraries/chain/block_header_state.cpp Show resolved Hide resolved
libraries/chain/block_header_state.cpp Show resolved Hide resolved
libraries/chain/block_header_state.cpp Outdated Show resolved Hide resolved
libraries/chain/block_header_state.cpp Outdated Show resolved Hide resolved
libraries/chain/block_header_state.cpp Outdated Show resolved Hide resolved
libraries/chain/include/eosio/chain/block_header_state.hpp Outdated Show resolved Hide resolved
… the same time as finality extensioni during block header validation; small changes to incor[orate review comments in block_header_state
@linh2931 linh2931 requested a review from arhag March 13, 2024 23:36
libraries/chain/include/eosio/chain/block_header.hpp Outdated Show resolved Hide resolved
libraries/chain/block_header.cpp Outdated Show resolved Hide resolved
libraries/chain/block_header_state.cpp Outdated Show resolved Hide resolved
@@ -59,8 +117,6 @@ block_header_state block_header_state::next(block_header_state_input& input) con
// +1 since this is called after the block is built, this will be the active schedule for the next block
if (it->first.slot <= input.timestamp.slot + 1) {
result.active_proposer_policy = it->second;
result.header.schedule_version = header.schedule_version + 1;
result.active_proposer_policy->proposer_schedule.version = result.header.schedule_version;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this change means it is now possible to skip propser_schedule.version numbers. We should modify the set_proposed_producers logic so we don't skip version numbers. Need a test to cover that case so we don't break it again.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does

return (--parent.proposer_policies.end())->second->proposer_schedule.version + 1;
}
assert(active_proposer_policy);
return active_proposer_policy->proposer_schedule.version + 1;
ensure the version number not being skipped?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, that doesn't help. We need to make sure that if a proposer policy is scheduled for the same proposer_policy.active_time that it replaces the current one there but doesn't increment the schedule version. I think we will need to change controller::set_proposed_producers to check if there is an existing one that would have the same active_time and replace it and use its version. We should return the correct version to the contract.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feel free to create a follow-on issue for this.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#2313

Thanks.

libraries/chain/block_state.cpp Outdated Show resolved Hide resolved
libraries/chain/controller.cpp Outdated Show resolved Hide resolved
unittests/producer_schedule_if_tests.cpp Outdated Show resolved Hide resolved
unittests/producer_schedule_if_tests.cpp Outdated Show resolved Hide resolved
@linh2931 linh2931 merged commit 422dfca into hotstuff_integration Mar 14, 2024
30 checks passed
@linh2931 linh2931 deleted the compute_finality_digest branch March 14, 2024 15:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

IF: Implement correct compute_finality_digest
6 participants