-
Notifications
You must be signed in to change notification settings - Fork 652
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
[Epoch Sync] EpochSyncProof validation #12020
Conversation
5113cf7
to
f80fc66
Compare
f80fc66
to
00c1851
Compare
chain/client/src/sync/epoch.rs
Outdated
)?; | ||
|
||
store_update.set_ser( | ||
DBCol::BlockOrdinal, | ||
&borsh::to_vec(&proof.current_epoch.merkle_proof_for_first_block.size()).unwrap(), | ||
&index_to_bytes(last_header.block_ordinal()), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Concern: BlockHeader::block_ordinal()
is supported since BlockHeaderV3
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think that's an issue. EpochSync to a block header version below V3 is unsupportable due to also not having epoch_data_hash.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But it will be worth making a test to check that trying to sync to a version below V3 will fail. I'll file an issue.
chain/client/src/sync/epoch.rs
Outdated
let last_epoch_data = &proof.past_epochs[proof.past_epochs.len() - 2]; | ||
let last_epoch_last_final_block_height = last_epoch_data.last_final_block_header.height(); | ||
let first_block_info_in_epoch = | ||
BlockInfo::from_header(&last_header, last_epoch_last_final_block_height); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Concern: there is also from_header_and_endorsements()
method, but from_header
would copy endorsements from the header. cc @tayfunelmas
Looking into failing integration tests. |
} | ||
} | ||
|
||
impl MerkleProofAccess for Store { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very nice design to make it work for both ChainStore and Store!
chain/client/src/sync/epoch.rs
Outdated
)?; | ||
|
||
store_update.set_ser( | ||
DBCol::BlockOrdinal, | ||
&borsh::to_vec(&proof.current_epoch.merkle_proof_for_first_block.size()).unwrap(), | ||
&index_to_bytes(last_header.block_ordinal()), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think that's an issue. EpochSync to a block header version below V3 is unsupportable due to also not having epoch_data_hash.
chain/client/src/sync/epoch.rs
Outdated
)?; | ||
|
||
store_update.set_ser( | ||
DBCol::BlockOrdinal, | ||
&borsh::to_vec(&proof.current_epoch.merkle_proof_for_first_block.size()).unwrap(), | ||
&index_to_bytes(last_header.block_ordinal()), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But it will be worth making a test to check that trying to sync to a version below V3 will fail. I'll file an issue.
epoch_manager: &dyn EpochManagerAdapter, | ||
) -> Result<(), Error> { | ||
// Verify epoch.block_producers | ||
let bp_hash = Chain::compute_bp_hash_from_validator_stakes( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice refactoring for this function. I was worried earlier about the protocol version check in here, but this is good.
@@ -514,6 +508,148 @@ impl EpochSync { | |||
|
|||
Ok(()) | |||
} | |||
|
|||
// Verify EpochSyncProof | |||
fn verify_proof( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we add some tests (can add some to the testloop test) that messing with the proof will result in a failing verification? We could, e.g. check that tweaking every byte of a valid serialized proof will cause a failure one way or another. It doesn't cover all possible attacks but at least makes sure that we aren't forgetting any fields.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Created follow-up issue for tests: #12260.
Might need fixing other issues first.
Great implementation! |
Addressed PR comments here: 76bdb69 |
76bdb69
to
9e2f79d
Compare
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #12020 +/- ##
==========================================
- Coverage 71.62% 71.62% -0.01%
==========================================
Files 837 838 +1
Lines 167105 167319 +214
Branches 167105 167319 +214
==========================================
+ Hits 119696 119842 +146
- Misses 42180 42242 +62
- Partials 5229 5235 +6
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
Issue: #11932
Implements EpochSyncProof validation, according to:
epoch_sync.rs
Summary:
Chain
to a separate trait (MerkleProofAccess
). MakeStore
implements this trait so that we canget_block_proof
while servingEpochSyncRequest
from a separate thread and having no access toChain
.verify_approval
andcompute_bp_hash
so that we can use it for proof validation.first_block_info_in_epoch
from block header.EpochSyncProofPastEpochData::protocol_version
merkle_proof_for_first_block
generated at height of final block of current epoch.merkle_proof_for_first_block
at the bootstrapped node. That will be done as a follow-up issue: [Epoch Sync] Generate merkle proof for the first block of current epoch #12255.epoch_sync_data_hash
infinal_block_header_in_next_epoch
#12258