Skip to content

Commit f314047

Browse files
paritytech-cmd-bot-polkadot-sdk[bot]claravanstadenacatangiu
authored
[stable2503] Backport #7075 (#7681)
Backport #7075 into `stable2503` from claravanstaden. See the [documentation](https://github.com/paritytech/polkadot-sdk/blob/master/docs/BACKPORT.md) on how to use this bot. <!-- # To be used by other automation, do not modify: original-pr-number: #${pull_number} --> --------- Co-authored-by: Clara van Staden <claravanstaden64@gmail.com> Co-authored-by: Adrian Catangiu <adrian@parity.io>
1 parent cc8cbac commit f314047

File tree

22 files changed

+3195
-126
lines changed

22 files changed

+3195
-126
lines changed

bridges/snowbridge/pallets/ethereum-client/src/benchmarking/mod.rs

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@ mod util;
66
use crate::Pallet as EthereumBeaconClient;
77
use frame_benchmarking::v2::*;
88
use frame_system::RawOrigin;
9-
10-
use snowbridge_pallet_ethereum_client_fixtures::*;
11-
9+
use hex_literal::hex;
1210
use snowbridge_beacon_primitives::{
13-
fast_aggregate_verify, prepare_aggregate_pubkey, prepare_aggregate_signature,
14-
verify_merkle_branch,
11+
fast_aggregate_verify,
12+
merkle_proof::{generalized_index_length, subtree_index},
13+
prepare_aggregate_pubkey, prepare_aggregate_signature, verify_merkle_branch, Fork,
1514
};
15+
use snowbridge_pallet_ethereum_client_fixtures::*;
1616
use util::*;
1717

1818
#[benchmarks]
@@ -111,13 +111,25 @@ mod benchmarks {
111111
let update = make_sync_committee_update();
112112
let block_root: H256 = update.finalized_header.hash_tree_root().unwrap();
113113

114+
let fork_versions = ForkVersions {
115+
genesis: Fork { version: hex!("00000000"), epoch: 0 },
116+
altair: Fork { version: hex!("01000000"), epoch: 0 },
117+
bellatrix: Fork { version: hex!("02000000"), epoch: 0 },
118+
capella: Fork { version: hex!("03000000"), epoch: 0 },
119+
deneb: Fork { version: hex!("04000000"), epoch: 0 },
120+
electra: Fork { version: hex!("05000000"), epoch: 80000000000 },
121+
};
122+
let finalized_root_gindex = EthereumBeaconClient::<T>::finalized_root_gindex_at_slot(
123+
update.attested_header.slot,
124+
fork_versions,
125+
);
114126
#[block]
115127
{
116128
verify_merkle_branch(
117129
block_root,
118130
&update.finality_branch,
119-
config::FINALIZED_ROOT_SUBTREE_INDEX,
120-
config::FINALIZED_ROOT_DEPTH,
131+
subtree_index(finalized_root_gindex),
132+
generalized_index_length(finalized_root_gindex),
121133
update.attested_header.state_root,
122134
);
123135
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
// SPDX-FileCopyrightText: 2023 Snowfork <hello@snowfork.com>
3+
4+
/// Generalized Indices
5+
/// related to Merkle proofs
6+
/// get_generalized_index(BeaconState, 'block_roots')
7+
pub const BLOCK_ROOTS_INDEX: usize = 37;
8+
/// get_generalized_index(BeaconState, 'finalized_checkpoint', 'root')
9+
pub const FINALIZED_ROOT_INDEX: usize = 105;
10+
/// get_generalized_index(BeaconState, 'current_sync_committee')
11+
pub const CURRENT_SYNC_COMMITTEE_INDEX: usize = 54;
12+
/// get_generalized_index(BeaconState, 'next_sync_committee')
13+
pub const NEXT_SYNC_COMMITTEE_INDEX: usize = 55;
14+
/// get_generalized_index(BeaconBlockBody, 'execution_payload')
15+
pub const EXECUTION_HEADER_INDEX: usize = 25;
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
// SPDX-FileCopyrightText: 2023 Snowfork <hello@snowfork.com>
3+
4+
/// Generalized Indices
5+
/// related to Merkle proofs
6+
/// get_generalized_index(BeaconState, 'block_roots')
7+
pub const BLOCK_ROOTS_INDEX: usize = 69;
8+
/// get_generalized_index(BeaconState, 'finalized_checkpoint', 'root')
9+
pub const FINALIZED_ROOT_INDEX: usize = 169;
10+
/// get_generalized_index(BeaconState, 'current_sync_committee')
11+
pub const CURRENT_SYNC_COMMITTEE_INDEX: usize = 86;
12+
/// get_generalized_index(BeaconState, 'next_sync_committee')
13+
pub const NEXT_SYNC_COMMITTEE_INDEX: usize = 87;

bridges/snowbridge/pallets/ethereum-client/src/config/mod.rs

Lines changed: 2 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,9 @@
11
// SPDX-License-Identifier: Apache-2.0
22
// SPDX-FileCopyrightText: 2023 Snowfork <hello@snowfork.com>
3-
use snowbridge_beacon_primitives::merkle_proof::{generalized_index_length, subtree_index};
43
use static_assertions::const_assert;
54

6-
/// Generalized Indices
7-
/// related to Merkle proofs
8-
/// get_generalized_index(BeaconState, 'block_roots')
9-
pub const BLOCK_ROOTS_INDEX: usize = 37;
10-
pub const BLOCK_ROOTS_SUBTREE_INDEX: usize = subtree_index(BLOCK_ROOTS_INDEX);
11-
pub const BLOCK_ROOTS_DEPTH: usize = generalized_index_length(BLOCK_ROOTS_INDEX);
12-
13-
/// get_generalized_index(BeaconState, 'finalized_checkpoint', 'root')
14-
pub const FINALIZED_ROOT_INDEX: usize = 105;
15-
pub const FINALIZED_ROOT_SUBTREE_INDEX: usize = subtree_index(FINALIZED_ROOT_INDEX);
16-
pub const FINALIZED_ROOT_DEPTH: usize = generalized_index_length(FINALIZED_ROOT_INDEX);
17-
18-
/// get_generalized_index(BeaconState, 'current_sync_committee')
19-
pub const CURRENT_SYNC_COMMITTEE_INDEX: usize = 54;
20-
pub const CURRENT_SYNC_COMMITTEE_SUBTREE_INDEX: usize = subtree_index(CURRENT_SYNC_COMMITTEE_INDEX);
21-
pub const CURRENT_SYNC_COMMITTEE_DEPTH: usize =
22-
generalized_index_length(CURRENT_SYNC_COMMITTEE_INDEX);
23-
24-
/// get_generalized_index(BeaconState, 'next_sync_committee')
25-
pub const NEXT_SYNC_COMMITTEE_INDEX: usize = 55;
26-
pub const NEXT_SYNC_COMMITTEE_SUBTREE_INDEX: usize = subtree_index(NEXT_SYNC_COMMITTEE_INDEX);
27-
pub const NEXT_SYNC_COMMITTEE_DEPTH: usize = generalized_index_length(NEXT_SYNC_COMMITTEE_INDEX);
28-
29-
/// get_generalized_index(BeaconBlockBody, 'execution_payload')
30-
pub const EXECUTION_HEADER_INDEX: usize = 25;
31-
pub const EXECUTION_HEADER_SUBTREE_INDEX: usize = subtree_index(EXECUTION_HEADER_INDEX);
32-
pub const EXECUTION_HEADER_DEPTH: usize = generalized_index_length(EXECUTION_HEADER_INDEX);
5+
pub mod altair;
6+
pub mod electra;
337

348
/// Sizes related to SSZ encoding
359
pub const MAX_EXTRA_DATA_BYTES: usize = 32;

bridges/snowbridge/pallets/ethereum-client/src/impls.rs

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use super::*;
44
use frame_support::ensure;
55
use snowbridge_beacon_primitives::ExecutionProof;
66

7+
use snowbridge_beacon_primitives::merkle_proof::{generalized_index_length, subtree_index};
78
use snowbridge_core::inbound::{
89
VerificationError::{self, *},
910
*,
@@ -13,8 +14,9 @@ use snowbridge_ethereum::Receipt;
1314
impl<T: Config> Verifier for Pallet<T> {
1415
/// Verify a message by verifying the existence of the corresponding
1516
/// Ethereum log in a block. Returns the log if successful. The execution header containing
16-
/// the log should be in the beacon client storage, meaning it has been verified and is an
17-
/// ancestor of a finalized beacon block.
17+
/// the log is sent with the message. The beacon header containing the execution header
18+
/// is also sent with the message, to check if the header is an ancestor of a finalized
19+
/// header.
1820
fn verify(event_log: &Log, proof: &Proof) -> Result<(), VerificationError> {
1921
Self::verify_execution_proof(&proof.execution_proof)
2022
.map_err(|e| InvalidExecutionProof(e.into()))?;
@@ -80,25 +82,6 @@ impl<T: Config> Pallet<T> {
8082
Error::<T>::HeaderNotFinalized
8183
);
8284

83-
// Gets the hash tree root of the execution header, in preparation for the execution
84-
// header proof (used to check that the execution header is rooted in the beacon
85-
// header body.
86-
let execution_header_root: H256 = execution_proof
87-
.execution_header
88-
.hash_tree_root()
89-
.map_err(|_| Error::<T>::BlockBodyHashTreeRootFailed)?;
90-
91-
ensure!(
92-
verify_merkle_branch(
93-
execution_header_root,
94-
&execution_proof.execution_branch,
95-
config::EXECUTION_HEADER_SUBTREE_INDEX,
96-
config::EXECUTION_HEADER_DEPTH,
97-
execution_proof.header.body_root
98-
),
99-
Error::<T>::InvalidExecutionHeaderProof
100-
);
101-
10285
let beacon_block_root: H256 = execution_proof
10386
.header
10487
.hash_tree_root()
@@ -125,6 +108,25 @@ impl<T: Config> Pallet<T> {
125108
},
126109
}
127110

111+
// Gets the hash tree root of the execution header, in preparation for the execution
112+
// header proof (used to check that the execution header is rooted in the beacon
113+
// header body.
114+
let execution_header_root: H256 = execution_proof
115+
.execution_header
116+
.hash_tree_root()
117+
.map_err(|_| Error::<T>::BlockBodyHashTreeRootFailed)?;
118+
119+
let execution_header_gindex = Self::execution_header_gindex();
120+
ensure!(
121+
verify_merkle_branch(
122+
execution_header_root,
123+
&execution_proof.execution_branch,
124+
subtree_index(execution_header_gindex),
125+
generalized_index_length(execution_header_gindex),
126+
execution_proof.header.body_root
127+
),
128+
Error::<T>::InvalidExecutionHeaderProof
129+
);
128130
Ok(())
129131
}
130132

bridges/snowbridge/pallets/ethereum-client/src/lib.rs

Lines changed: 90 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,15 @@ pub mod weights;
2626
#[cfg(any(test, feature = "fuzzing"))]
2727
pub mod mock;
2828

29+
#[cfg(test)]
30+
pub mod mock_electra;
31+
2932
#[cfg(test)]
3033
mod tests;
3134

35+
#[cfg(test)]
36+
mod tests_electra;
37+
3238
#[cfg(feature = "runtime-benchmarks")]
3339
mod benchmarking;
3440

@@ -40,8 +46,10 @@ use frame_support::{
4046
};
4147
use frame_system::ensure_signed;
4248
use snowbridge_beacon_primitives::{
43-
fast_aggregate_verify, verify_merkle_branch, verify_receipt_proof, BeaconHeader, BlsError,
44-
CompactBeaconState, ForkData, ForkVersion, ForkVersions, PublicKeyPrepared, SigningData,
49+
fast_aggregate_verify,
50+
merkle_proof::{generalized_index_length, subtree_index},
51+
verify_merkle_branch, verify_receipt_proof, BeaconHeader, BlsError, CompactBeaconState,
52+
ForkData, ForkVersion, ForkVersions, PublicKeyPrepared, SigningData,
4553
};
4654
use snowbridge_core::{BasicOperatingMode, RingBufferMap};
4755
use sp_core::H256;
@@ -245,13 +253,18 @@ pub mod pallet {
245253
.hash_tree_root()
246254
.map_err(|_| Error::<T>::SyncCommitteeHashTreeRootFailed)?;
247255

256+
let fork_versions = T::ForkVersions::get();
257+
let sync_committee_gindex = Self::current_sync_committee_gindex_at_slot(
258+
update.header.slot,
259+
fork_versions.clone(),
260+
);
248261
// Verifies the sync committee in the Beacon state.
249262
ensure!(
250263
verify_merkle_branch(
251264
sync_committee_root,
252265
&update.current_sync_committee_branch,
253-
config::CURRENT_SYNC_COMMITTEE_SUBTREE_INDEX,
254-
config::CURRENT_SYNC_COMMITTEE_DEPTH,
266+
subtree_index(sync_committee_gindex),
267+
generalized_index_length(sync_committee_gindex),
255268
update.header.state_root
256269
),
257270
Error::<T>::InvalidSyncCommitteeMerkleProof
@@ -265,12 +278,14 @@ pub mod pallet {
265278
// This is used for ancestry proofs in ExecutionHeader updates. This verifies the
266279
// BeaconState: the beacon state root is the tree root; the `block_roots` hash is the
267280
// tree leaf.
281+
let block_roots_gindex =
282+
Self::block_roots_gindex_at_slot(update.header.slot, fork_versions);
268283
ensure!(
269284
verify_merkle_branch(
270285
update.block_roots_root,
271286
&update.block_roots_branch,
272-
config::BLOCK_ROOTS_SUBTREE_INDEX,
273-
config::BLOCK_ROOTS_DEPTH,
287+
subtree_index(block_roots_gindex),
288+
generalized_index_length(block_roots_gindex),
274289
update.header.state_root
275290
),
276291
Error::<T>::InvalidBlockRootsRootMerkleProof
@@ -348,6 +363,11 @@ pub mod pallet {
348363
Error::<T>::InvalidFinalizedHeaderGap
349364
);
350365

366+
let fork_versions = T::ForkVersions::get();
367+
let finalized_root_gindex = Self::finalized_root_gindex_at_slot(
368+
update.attested_header.slot,
369+
fork_versions.clone(),
370+
);
351371
// Verify that the `finality_branch`, if present, confirms `finalized_header` to match
352372
// the finalized checkpoint root saved in the state of `attested_header`.
353373
let finalized_block_root: H256 = update
@@ -358,8 +378,8 @@ pub mod pallet {
358378
verify_merkle_branch(
359379
finalized_block_root,
360380
&update.finality_branch,
361-
config::FINALIZED_ROOT_SUBTREE_INDEX,
362-
config::FINALIZED_ROOT_DEPTH,
381+
subtree_index(finalized_root_gindex),
382+
generalized_index_length(finalized_root_gindex),
363383
update.attested_header.state_root
364384
),
365385
Error::<T>::InvalidHeaderMerkleProof
@@ -368,12 +388,16 @@ pub mod pallet {
368388
// Though following check does not belong to ALC spec we verify block_roots_root to
369389
// match the finalized checkpoint root saved in the state of `finalized_header` so to
370390
// cache it for later use in `verify_ancestry_proof`.
391+
let block_roots_gindex = Self::block_roots_gindex_at_slot(
392+
update.finalized_header.slot,
393+
fork_versions.clone(),
394+
);
371395
ensure!(
372396
verify_merkle_branch(
373397
update.block_roots_root,
374398
&update.block_roots_branch,
375-
config::BLOCK_ROOTS_SUBTREE_INDEX,
376-
config::BLOCK_ROOTS_DEPTH,
399+
subtree_index(block_roots_gindex),
400+
generalized_index_length(block_roots_gindex),
377401
update.finalized_header.state_root
378402
),
379403
Error::<T>::InvalidBlockRootsRootMerkleProof
@@ -393,12 +417,16 @@ pub mod pallet {
393417
Error::<T>::InvalidSyncCommitteeUpdate
394418
);
395419
}
420+
let next_sync_committee_gindex = Self::next_sync_committee_gindex_at_slot(
421+
update.attested_header.slot,
422+
fork_versions,
423+
);
396424
ensure!(
397425
verify_merkle_branch(
398426
sync_committee_root,
399427
&next_sync_committee_update.next_sync_committee_branch,
400-
config::NEXT_SYNC_COMMITTEE_SUBTREE_INDEX,
401-
config::NEXT_SYNC_COMMITTEE_DEPTH,
428+
subtree_index(next_sync_committee_gindex),
429+
generalized_index_length(next_sync_committee_gindex),
402430
update.attested_header.state_root
403431
),
404432
Error::<T>::InvalidSyncCommitteeMerkleProof
@@ -604,6 +632,9 @@ pub mod pallet {
604632

605633
/// Returns the fork version based on the current epoch.
606634
pub(super) fn select_fork_version(fork_versions: &ForkVersions, epoch: u64) -> ForkVersion {
635+
if epoch >= fork_versions.electra.epoch {
636+
return fork_versions.electra.version
637+
}
607638
if epoch >= fork_versions.deneb.epoch {
608639
return fork_versions.deneb.version
609640
}
@@ -684,5 +715,52 @@ pub mod pallet {
684715

685716
Pays::Yes
686717
}
718+
719+
pub fn finalized_root_gindex_at_slot(slot: u64, fork_versions: ForkVersions) -> usize {
720+
let epoch = compute_epoch(slot, config::SLOTS_PER_EPOCH as u64);
721+
722+
if epoch >= fork_versions.electra.epoch {
723+
return config::electra::FINALIZED_ROOT_INDEX;
724+
}
725+
726+
config::altair::FINALIZED_ROOT_INDEX
727+
}
728+
729+
pub fn current_sync_committee_gindex_at_slot(
730+
slot: u64,
731+
fork_versions: ForkVersions,
732+
) -> usize {
733+
let epoch = compute_epoch(slot, config::SLOTS_PER_EPOCH as u64);
734+
735+
if epoch >= fork_versions.electra.epoch {
736+
return config::electra::CURRENT_SYNC_COMMITTEE_INDEX;
737+
}
738+
739+
config::altair::CURRENT_SYNC_COMMITTEE_INDEX
740+
}
741+
742+
pub fn next_sync_committee_gindex_at_slot(slot: u64, fork_versions: ForkVersions) -> usize {
743+
let epoch = compute_epoch(slot, config::SLOTS_PER_EPOCH as u64);
744+
745+
if epoch >= fork_versions.electra.epoch {
746+
return config::electra::NEXT_SYNC_COMMITTEE_INDEX;
747+
}
748+
749+
config::altair::NEXT_SYNC_COMMITTEE_INDEX
750+
}
751+
752+
pub fn block_roots_gindex_at_slot(slot: u64, fork_versions: ForkVersions) -> usize {
753+
let epoch = compute_epoch(slot, config::SLOTS_PER_EPOCH as u64);
754+
755+
if epoch >= fork_versions.electra.epoch {
756+
return config::electra::BLOCK_ROOTS_INDEX;
757+
}
758+
759+
config::altair::BLOCK_ROOTS_INDEX
760+
}
761+
762+
pub fn execution_header_gindex() -> usize {
763+
config::altair::EXECUTION_HEADER_INDEX
764+
}
687765
}
688766
}

bridges/snowbridge/pallets/ethereum-client/src/mock.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,8 +130,12 @@ parameter_types! {
130130
epoch: 0,
131131
},
132132
deneb: Fork {
133-
version: [4, 0, 0, 0], // 0x90000073
133+
version: [4, 0, 0, 0], // 0x04000000
134134
epoch: 0,
135+
},
136+
electra: Fork {
137+
version: [5, 0, 0, 0], // 0x05000000
138+
epoch: 80000000000,
135139
}
136140
};
137141
}

0 commit comments

Comments
 (0)