From 4e92feb6c0a629eb5cf3d3429514ae755272a5a2 Mon Sep 17 00:00:00 2001 From: ron Date: Tue, 2 May 2023 16:06:42 +0800 Subject: [PATCH 01/16] Cache milagro G1 pubkeys --- cumulus | 2 +- parachain/Cargo.lock | 12 +- .../pallets/ethereum-beacon-client/Cargo.toml | 5 +- .../src/benchmarking/mod.rs | 52 +++-- .../src/benchmarking/util.rs | 101 ++++---- .../pallets/ethereum-beacon-client/src/lib.rs | 216 ++++++++++-------- .../ethereum-beacon-client/src/mock.rs | 10 +- .../ethereum-beacon-client/src/tests.rs | 65 +++--- .../src/tests_mainnet.rs | 75 +++--- .../src/tests_minimal.rs | 62 +++-- .../ethereum-beacon-client/src/weights.rs | 16 +- parachain/primitives/beacon/Cargo.toml | 2 + parachain/primitives/beacon/src/bls.rs | 100 ++++++++ parachain/primitives/beacon/src/lib.rs | 10 +- parachain/primitives/beacon/src/types.rs | 29 ++- parachain/rustfmt.toml | 1 + 16 files changed, 470 insertions(+), 288 deletions(-) create mode 100644 parachain/primitives/beacon/src/bls.rs diff --git a/cumulus b/cumulus index 9fdbaf6bd4..7a8220c7fc 160000 --- a/cumulus +++ b/cumulus @@ -1 +1 @@ -Subproject commit 9fdbaf6bd4e77f48cca6a3c33a2c52d6db6b7d69 +Subproject commit 7a8220c7fcea968f2f35c46755cfd4c3dafab0f2 diff --git a/parachain/Cargo.lock b/parachain/Cargo.lock index e6340b85d9..2c29f7289a 100644 --- a/parachain/Cargo.lock +++ b/parachain/Cargo.lock @@ -71,7 +71,11 @@ dependencies = [ [[package]] name = "amcl" version = "0.3.0" -source = "git+https://github.com/Snowfork/milagro_bls#2c9e8b383981308a8b4cbbc19e0b897dcf14534b" +source = "git+https://github.com/snowfork/milagro_bls?rev=b95ca5be05e3c6e5b865b7e1f4a768dfa97f27f8#b95ca5be05e3c6e5b865b7e1f4a768dfa97f27f8" +dependencies = [ + "parity-scale-codec", + "scale-info", +] [[package]] name = "android_system_properties" @@ -2238,12 +2242,14 @@ dependencies = [ [[package]] name = "milagro_bls" version = "1.5.0" -source = "git+https://github.com/Snowfork/milagro_bls#2c9e8b383981308a8b4cbbc19e0b897dcf14534b" +source = "git+https://github.com/snowfork/milagro_bls?rev=b95ca5be05e3c6e5b865b7e1f4a768dfa97f27f8#b95ca5be05e3c6e5b865b7e1f4a768dfa97f27f8" dependencies = [ "amcl", "hex", "lazy_static", + "parity-scale-codec", "rand 0.8.5", + "scale-info", "zeroize", ] @@ -3499,6 +3505,7 @@ dependencies = [ "frame-system", "hex", "hex-literal", + "milagro_bls", "parity-scale-codec", "rlp", "scale-info", @@ -3563,7 +3570,6 @@ dependencies = [ "frame-support", "frame-system", "hex-literal", - "milagro_bls", "pallet-timestamp", "parity-scale-codec", "rlp", diff --git a/parachain/pallets/ethereum-beacon-client/Cargo.toml b/parachain/pallets/ethereum-beacon-client/Cargo.toml index 5e9bd0c65f..ab0dc85406 100644 --- a/parachain/pallets/ethereum-beacon-client/Cargo.toml +++ b/parachain/pallets/ethereum-beacon-client/Cargo.toml @@ -14,7 +14,6 @@ targets = ["x86_64-unknown-linux-gnu"] serde = { version = "1.0.160", optional = true } codec = { version = "3.1.5", package = "parity-scale-codec", default-features = false, features = [ "derive" ] } scale-info = { version = "2.5.0", default-features = false, features = [ "derive" ] } -milagro_bls = { git = "https://github.com/Snowfork/milagro_bls", default-features = false } ssz-rs = { git = "https://github.com/ralexstokes/ssz-rs", default-features = false, rev="d18af912abacbf84219be37ab3b42a9abcf10d2a" } ssz-rs-derive = { git = "https://github.com/ralexstokes/ssz-rs", default-features = false, rev="d18af912abacbf84219be37ab3b42a9abcf10d2a" } byte-slice-cast = { version = "1.2.1", default-features = false } @@ -39,7 +38,7 @@ sp-io = { git = "https://github.com/paritytech/substrate.git", branch = "master" snowbridge-testutils = { path = "../../primitives/testutils" } serde_json = "1.0.96" hex-literal = { version = "0.4.1" } -pallet-timestamp = { git = "https://github.com/paritytech/substrate.git", branch = "master", default-features = false } +pallet-timestamp = { git = "https://github.com/paritytech/substrate.git", branch = "master" } [features] default = ["std"] @@ -56,10 +55,8 @@ std = [ "snowbridge-core/std", "snowbridge-ethereum/std", "primitives/std", - "milagro_bls/std", "ssz-rs/std", "byte-slice-cast/std", - "pallet-timestamp/std" ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", diff --git a/parachain/pallets/ethereum-beacon-client/src/benchmarking/mod.rs b/parachain/pallets/ethereum-beacon-client/src/benchmarking/mod.rs index 9d350477f9..10fb3790cf 100644 --- a/parachain/pallets/ethereum-beacon-client/src/benchmarking/mod.rs +++ b/parachain/pallets/ethereum-beacon-client/src/benchmarking/mod.rs @@ -8,6 +8,10 @@ use frame_system::RawOrigin; mod data_mainnet; use data_mainnet::*; mod util; +use primitives::{ + fast_aggregate_verify, fast_aggregate_verify_legacy, prepare_aggregate_pubkey, + prepare_aggregate_signature, +}; use util::*; benchmarks! { @@ -18,7 +22,7 @@ benchmarks! { }: sync_committee_period_update(RawOrigin::Signed(caller.clone()), sync_committee_update.clone()) verify { - assert!(>::get(sync_committee_update.sync_committee_period+1).unwrap().pubkeys.len() > 0); + EthereumBeaconClient::::sync_committee_for_period(sync_committee_update.sync_committee_period+1).unwrap(); } import_finalized_header { @@ -30,12 +34,11 @@ benchmarks! { let finalized_header_update = finalized_header_update(); - SyncCommittees::::insert( - EthereumBeaconClient::::compute_current_sync_period( + let current_period = EthereumBeaconClient::::compute_current_sync_period( finalized_header_update.attested_header.slot, - ), - initial_sync_data.current_sync_committee, - ); + ); + + EthereumBeaconClient::::store_sync_committee(current_period, &initial_sync_data.current_sync_committee)?; //initialize LatestFinalizedHeaderState with parent slot of finalized_header_update LatestFinalizedHeaderState::::set(FinalizedHeaderState { @@ -60,9 +63,11 @@ benchmarks! { let header_update = header_update(); - SyncCommittees::::insert(EthereumBeaconClient::::compute_current_sync_period( + let current_period = EthereumBeaconClient::::compute_current_sync_period( header_update.beacon_header.slot, - ), initial_sync_data.current_sync_committee); + ); + + EthereumBeaconClient::::store_sync_committee(current_period, &initial_sync_data.current_sync_committee)?; let finalized_update: FinalizedHeaderUpdate<> = finalized_header_update(); @@ -90,32 +95,31 @@ benchmarks! { assert_eq!(>::get(),false); } - bls_fast_aggregate_verify { + bls_fast_aggregate_verify_pre_aggregated { let update = initialize_sync_committee::()?; - let participant_pubkeys = get_participant_pubkeys::(&update)?; - let signing_root = get_signing_message::(&update)?; + let participant_pubkeys = participant_pubkeys::(&update)?; + let signing_root = signing_root::(&update)?; + let agg_sig = prepare_aggregate_signature(&update.sync_aggregate.sync_committee_signature).unwrap(); + let agg_pub_key = prepare_aggregate_pubkey(&participant_pubkeys).unwrap(); }:{ - EthereumBeaconClient::::bls_fast_aggregate_verify(&participant_pubkeys,signing_root,&update.sync_aggregate.sync_committee_signature)?; + agg_sig.fast_aggregate_verify_pre_aggregated(&signing_root.as_bytes(), &agg_pub_key) } - bls_aggregate_pubkey { + bls_fast_aggregate_verify_legacy { let update = initialize_sync_committee::()?; - let participant_pubkeys = get_participant_pubkeys::(&update)?; + let participant_pubkeys = participant_pubkeys::(&update)?; + let signing_root = signing_root::(&update)?; }:{ - participant_pubkeys - .iter() - .map(|bytes| milagro_bls::PublicKey::from_bytes_unchecked(&bytes.0)) - .collect::, _>>().unwrap() + fast_aggregate_verify_legacy(&participant_pubkeys, signing_root, &update.sync_aggregate.sync_committee_signature).unwrap(); } - bls_verify_message { + bls_fast_aggregate_verify { let update = initialize_sync_committee::()?; - let participant_pubkeys = get_participant_pubkeys::(&update)?; - let signing_root = get_signing_message::(&update)?; - let agg_sig = get_aggregate_signature::(update.sync_aggregate.sync_committee_signature).unwrap(); - let agg_pub_key = get_aggregate_pubkey::(participant_pubkeys).unwrap(); + let current_sync_committee = sync_committee::(&update)?; + let absent_pubkeys = absent_pubkeys::(&update)?; + let signing_root = signing_root::(&update)?; }:{ - agg_sig.fast_aggregate_verify_pre_aggregated(&signing_root.as_bytes(), &agg_pub_key) + fast_aggregate_verify(¤t_sync_committee.aggregate_pubkey, &absent_pubkeys, signing_root, &update.sync_aggregate.sync_committee_signature).unwrap(); } } diff --git a/parachain/pallets/ethereum-beacon-client/src/benchmarking/util.rs b/parachain/pallets/ethereum-beacon-client/src/benchmarking/util.rs index e48077ad10..69b343a80d 100644 --- a/parachain/pallets/ethereum-beacon-client/src/benchmarking/util.rs +++ b/parachain/pallets/ethereum-beacon-client/src/benchmarking/util.rs @@ -1,12 +1,13 @@ use crate::{ - Config, LatestSyncCommitteePeriod, Pallet as EthereumBeaconClient, PublicKey, Signature, - SyncCommitteeUpdate, SyncCommittees, ValidatorsRoot, Vec, + decompress_sync_committee_bits, Config, LatestSyncCommitteePeriod, + Pallet as EthereumBeaconClient, SyncCommitteeUpdate, SyncCommittees, ValidatorsRoot, Vec, + SYNC_COMMITTEE_SIZE, }; -use milagro_bls::{AggregatePublicKey, AggregateSignature, Signature as MilagroSignature}; +use frame_support::traits::ConstU32; +use primitives::{PreparedSyncCommittee, PublicKeyPrepared}; use sp_core::H256; use super::{initial_sync, sync_committee_update}; -use crate::{decompress_sync_committee_bits, Error}; pub fn initialize_sync_committee() -> Result { let initial_sync_data = initial_sync(); @@ -19,69 +20,57 @@ pub fn initialize_sync_committee() -> Result::set(EthereumBeaconClient::::compute_current_sync_period( sync_committee_update.attested_header.slot, )); - SyncCommittees::::insert( - EthereumBeaconClient::::compute_current_sync_period( - sync_committee_update.attested_header.slot, - ), - initial_sync_data.current_sync_committee, + let current_period = EthereumBeaconClient::::compute_current_sync_period( + sync_committee_update.attested_header.slot, ); + EthereumBeaconClient::::store_sync_committee( + current_period, + &initial_sync_data.current_sync_committee, + )?; Ok(sync_committee_update) } -pub fn get_participant_pubkeys( +pub fn sync_committee( update: &SyncCommitteeUpdate, -) -> Result, &'static str> { - let sync_committee_bits = - decompress_sync_committee_bits(update.sync_aggregate.sync_committee_bits.clone()); +) -> Result>, &'static str> { let current_period = EthereumBeaconClient::::compute_current_sync_period(update.attested_header.slot); - let current_sync_committee = - SyncCommittees::::get(current_period).ok_or("no sync committee")?; - let sync_committee_pubkeys = current_sync_committee.pubkeys; - let mut participant_pubkeys: Vec = Vec::new(); - for (bit, pubkey) in sync_committee_bits.iter().zip(sync_committee_pubkeys.iter()) { - if *bit == 1 as u8 { - let pubk = pubkey.clone(); - participant_pubkeys.push(pubk); - } - } - Ok(participant_pubkeys) + let sync_committee = SyncCommittees::::get(current_period).ok_or("no sync committee")?; + Ok(sync_committee) } -pub fn get_signing_message(update: &SyncCommitteeUpdate) -> Result { - let validators_root = >::get(); - let fork_version = EthereumBeaconClient::::compute_fork_version( - EthereumBeaconClient::::compute_epoch_at_slot( - update.signature_slot, - crate::config::SLOTS_PER_EPOCH, - ), - ); - let domain_type = crate::config::DOMAIN_SYNC_COMMITTEE.to_vec(); - let domain = - EthereumBeaconClient::::compute_domain(domain_type, fork_version, validators_root)?; - let signing_root = - EthereumBeaconClient::::compute_signing_root(update.attested_header.clone(), domain)?; - Ok(signing_root) +pub fn participant_pubkeys( + update: &SyncCommitteeUpdate, +) -> Result, &'static str> { + let sync_committee_bits = + decompress_sync_committee_bits(update.sync_aggregate.sync_committee_bits.clone()); + let current_sync_committee = sync_committee::(update)?; + let pubkeys = EthereumBeaconClient::::participant_pubkeys( + &sync_committee_bits, + ¤t_sync_committee.pubkeys, + )?; + Ok(pubkeys) } -pub fn get_aggregate_signature( - signature: Signature, -) -> Result> { - let sig = - MilagroSignature::from_bytes(&signature.0[..]).map_err(|_| Error::::InvalidSignature)?; - let agg_sig = AggregateSignature::from_signature(&sig); - Ok(agg_sig) +pub fn absent_pubkeys( + update: &SyncCommitteeUpdate, +) -> Result, &'static str> { + let sync_committee_bits = + decompress_sync_committee_bits(update.sync_aggregate.sync_committee_bits.clone()); + let current_sync_committee = sync_committee::(update)?; + let pubkeys = EthereumBeaconClient::::absent_pubkeys( + &sync_committee_bits, + ¤t_sync_committee.pubkeys, + )?; + Ok(pubkeys) } -pub fn get_aggregate_pubkey( - pubkeys: Vec, -) -> Result> { - let milagro_public_keys = pubkeys - .iter() - .map(|bytes| milagro_bls::PublicKey::from_bytes_unchecked(&bytes.0)) - .collect::, _>>() - .map_err(|_| Error::::InvalidSignaturePoint)?; - let agg_pub_key = AggregatePublicKey::into_aggregate(&milagro_public_keys) - .map_err(|_| Error::::InvalidAggregatePublicKeys)?; - Ok(agg_pub_key) +pub fn signing_root(update: &SyncCommitteeUpdate) -> Result { + let validators_root = >::get(); + let signing_root = EthereumBeaconClient::::signing_root( + update.attested_header.clone(), + validators_root, + update.signature_slot, + )?; + Ok(signing_root) } diff --git a/parachain/pallets/ethereum-beacon-client/src/lib.rs b/parachain/pallets/ethereum-beacon-client/src/lib.rs index e3e0eda21d..c64bd7d9e3 100644 --- a/parachain/pallets/ethereum-beacon-client/src/lib.rs +++ b/parachain/pallets/ethereum-beacon-client/src/lib.rs @@ -20,28 +20,29 @@ mod benchmarking; pub use weights::WeightInfo; -use frame_support::{dispatch::DispatchResult, log, traits::UnixTime, transactional}; +use frame_support::{ + dispatch::DispatchResult, + log, + traits::{ConstU32, Get, UnixTime}, + transactional, BoundedVec, +}; use frame_system::ensure_signed; use primitives::{ - verify_merkle_proof, verify_receipt_proof, BeaconHeader, CompactExecutionHeader, - ExecutionHeaderState, FinalizedHeaderState, ForkData, ForkVersion, PublicKey, Signature, - SigningData, + fast_aggregate_verify, verify_merkle_proof, verify_receipt_proof, BeaconHeader, BlsError, + CompactExecutionHeader, ExecutionHeaderState, FinalizedHeaderState, ForkData, ForkVersion, + ForkVersions, PreparedSyncCommittee, PublicKeyPrepared, Signature, SigningData, }; use snowbridge_core::{Message, Verifier}; use sp_core::H256; use sp_std::prelude::*; -use milagro_bls::{AggregatePublicKey, AggregateSignature, AmclError}; -use primitives::ForkVersions; use snowbridge_core::Proof; use snowbridge_ethereum::{Header as EthereumHeader, Log, Receipt}; use sp_core::U256; -use frame_support::{traits::Get, BoundedVec}; - pub use pallet::*; -use config::{ +pub use config::{ MAX_FINALIZED_HEADER_SLOT_ARRAY, SLOTS_PER_HISTORICAL_ROOT, SYNC_COMMITTEE_BITS_SIZE, SYNC_COMMITTEE_SIZE, }; @@ -53,6 +54,7 @@ pub type SyncCommitteeUpdate = pub type FinalizedHeaderUpdate = primitives::FinalizedHeaderUpdate; pub type SyncCommittee = primitives::SyncCommittee; +pub type PreparedSyncCommitteeOf = PreparedSyncCommittee>; fn decompress_sync_committee_bits( input: [u8; SYNC_COMMITTEE_BITS_SIZE], @@ -78,8 +80,9 @@ pub mod pallet { type TimeProvider: UnixTime; #[pallet::constant] type ForkVersions: Get; - type WeightInfo: WeightInfo; + #[pallet::constant] type WeakSubjectivityPeriodSeconds: Get; + type WeightInfo: WeightInfo; } #[pallet::event] @@ -91,6 +94,7 @@ pub mod pallet { } #[pallet::error] + #[cfg_attr(test, derive(PartialEq))] pub enum Error { AncientHeader, SkippedSyncCommitteePeriod, @@ -101,9 +105,6 @@ pub mod pallet { InvalidSyncCommitteeMerkleProof, InvalidExecutionHeaderProof, InvalidAncestryMerkleProof, - InvalidSignature, - InvalidSignaturePoint, - InvalidAggregatePublicKeys, InvalidHash, InvalidSyncCommitteeBits, SignatureVerificationFailed, @@ -133,6 +134,20 @@ pub mod pallet { InvalidExecutionHeaderUpdate, FinalizedBeaconHeaderSlotsExceeded, ExecutionHeaderMappingFailed, + BLSPreparePublicKeysFailed, + BLSVerificationFailed(#[codec(skip)] &'static str), + } + + impl From for Error { + fn from(e: BlsError) -> Self { + match e { + BlsError::InvalidPublicKey | BlsError::InvalidAggregatePublicKeys => + Error::BLSVerificationFailed("InvalidPublicKey"), + BlsError::InvalidSignature => Error::BLSVerificationFailed("InvalidSignature"), + BlsError::SignatureVerificationFailed => + Error::BLSVerificationFailed("SignatureVerificationFailed"), + } + } } #[pallet::hooks] @@ -154,12 +169,6 @@ pub mod pallet { pub(super) type ExecutionHeaders = StorageMap<_, Identity, H256, CompactExecutionHeader, OptionQuery>; - /// Current sync committee corresponding to the active header. - /// TODO prune older sync committees than xxx - #[pallet::storage] - pub(super) type SyncCommittees = - StorageMap<_, Identity, u64, SyncCommittee, OptionQuery>; - #[pallet::storage] pub(super) type ValidatorsRoot = StorageValue<_, H256, ValueQuery>; @@ -177,6 +186,10 @@ pub mod pallet { #[pallet::storage] pub(super) type Blocked = StorageValue<_, bool, ValueQuery>; + #[pallet::storage] + pub(super) type SyncCommittees = + StorageMap<_, Identity, u64, PreparedSyncCommitteeOf, OptionQuery>; + #[pallet::genesis_config] pub struct GenesisConfig { pub initial_sync: Option, @@ -348,7 +361,7 @@ pub mod pallet { .hash_tree_root() .map_err(|_| Error::::HeaderHashTreeRootFailed)?; - Self::store_sync_committee(period, &update.current_sync_committee); + Self::store_sync_committee(period, &update.current_sync_committee)?; Self::store_validators_root(update.validators_root); let slot = update.header.slot; @@ -405,8 +418,6 @@ pub mod pallet { signature_slot_period ); - let current_sync_committee = - >::get(current_period).ok_or(Error::::SyncCommitteeMissing)?; let next_period = current_period + 1; ensure!( !>::contains_key(next_period), @@ -418,10 +429,11 @@ pub mod pallet { ); let validators_root = >::get(); + let sync_committee = Self::sync_committee_for_period(current_period)?; Self::verify_signed_header( &participation, &update.sync_aggregate.sync_committee_signature, - ¤t_sync_committee.pubkeys, + &sync_committee, update.attested_header.clone(), validators_root, update.signature_slot, @@ -438,7 +450,7 @@ pub mod pallet { ); Self::store_block_root(update.block_roots_root, block_root); - Self::store_sync_committee(next_period, &update.next_sync_committee); + Self::store_sync_committee(next_period, &update.next_sync_committee)?; Self::store_finalized_header(block_root, update.finalized_header.clone())?; Ok(()) @@ -502,14 +514,12 @@ pub mod pallet { Error::::InvalidFinalizedPeriodUpdate ); - let sync_committee = - >::get(current_period).ok_or(Error::::SyncCommitteeMissing)?; - let validators_root = >::get(); + let sync_committee = Self::sync_committee_for_period(current_period)?; Self::verify_signed_header( &participation, &update.sync_aggregate.sync_committee_signature, - &sync_committee.pubkeys, + &sync_committee, update.attested_header, validators_root, update.signature_slot, @@ -581,8 +591,7 @@ pub mod pallet { )?; let current_period = Self::compute_current_sync_period(update.beacon_header.slot); - let sync_committee = - >::get(current_period).ok_or(Error::::SyncCommitteeMissing)?; + let sync_committee = Self::sync_committee_for_period(current_period)?; let validators_root = >::get(); let participation = @@ -591,7 +600,7 @@ pub mod pallet { Self::verify_signed_header( &participation, &update.sync_aggregate.sync_committee_signature, - &sync_committee.pubkeys, + &sync_committee, update.beacon_header, validators_root, update.signature_slot, @@ -682,36 +691,26 @@ pub mod pallet { pub(super) fn verify_signed_header( sync_committee_bits: &[u8], sync_committee_signature: &Signature, - sync_committee_pubkeys: &[PublicKey], + sync_committee: &PreparedSyncCommitteeOf, header: BeaconHeader, validators_root: H256, signature_slot: u64, ) -> DispatchResult { - let mut participant_pubkeys: Vec = Vec::new(); - // Gathers all the pubkeys of the sync committee members that participated in signing - // the header. - for (bit, pubkey) in sync_committee_bits.iter().zip(sync_committee_pubkeys.iter()) { - if *bit == 1_u8 { - participant_pubkeys.push(*pubkey); - } - } + // Gathers milagro pubkeys absent to participate + let absent_pubkeys = + Self::absent_pubkeys(sync_committee_bits, &sync_committee.pubkeys)?; - let fork_version = Self::compute_fork_version(Self::compute_epoch_at_slot( - signature_slot, - config::SLOTS_PER_EPOCH, - )); - let domain_type = config::DOMAIN_SYNC_COMMITTEE.to_vec(); - // Domains are used for for seeds, for signatures, and for selecting aggregators. - let domain = Self::compute_domain(domain_type, fork_version, validators_root)?; - // Hash tree root of SigningData - object root + domain - let signing_root = Self::compute_signing_root(header, domain)?; + // Get signing root for BeaconHeader + let signing_root = Self::signing_root(header, validators_root, signature_slot)?; // Verify sync committee aggregate signature. - Self::bls_fast_aggregate_verify( - &participant_pubkeys, + fast_aggregate_verify( + &sync_committee.aggregate_pubkey, + &absent_pubkeys, signing_root, sync_committee_signature, - )?; + ) + .map_err(|e| Error::::from(e))?; Ok(()) } @@ -720,50 +719,10 @@ pub mod pallet { signature_slot / slots_per_epoch } - pub(super) fn bls_fast_aggregate_verify( - pubkeys: &[PublicKey], - message: H256, - signature: &Signature, - ) -> DispatchResult { - let sig = milagro_bls::Signature::from_bytes(&signature.0[..]); - if let Err(_e) = sig { - return Err(Error::::InvalidSignature.into()) - } - - let agg_sig = AggregateSignature::from_signature(&sig.unwrap()); - - let public_keys_res: Result, _> = pubkeys - .iter() - .map(|bytes| milagro_bls::PublicKey::from_bytes_unchecked(&bytes.0)) - .collect(); - if let Err(e) = public_keys_res { - match e { - AmclError::InvalidPoint => return Err(Error::::InvalidSignaturePoint.into()), - _ => return Err(Error::::InvalidSignature.into()), - }; - } - - let agg_pub_key_res = AggregatePublicKey::into_aggregate(&public_keys_res.unwrap()); - if let Err(e) = agg_pub_key_res { - log::error!(target: "ethereum-beacon-client", "💫 invalid public keys: {:?}.", e); - return Err(Error::::InvalidAggregatePublicKeys.into()) - } - - ensure!( - agg_sig.fast_aggregate_verify_pre_aggregated( - message.as_bytes(), - &agg_pub_key_res.unwrap() - ), - Error::::SignatureVerificationFailed - ); - - Ok(()) - } - pub(super) fn compute_signing_root( beacon_header: BeaconHeader, domain: H256, - ) -> Result { + ) -> Result> { let beacon_header_root = beacon_header .hash_tree_root() .map_err(|_| Error::::HeaderHashTreeRootFailed)?; @@ -818,18 +777,21 @@ pub mod pallet { Ok(()) } - fn store_sync_committee(period: u64, sync_committee: &SyncCommittee) { - >::insert(period, sync_committee); + pub fn store_sync_committee(period: u64, sync_committee: &SyncCommittee) -> DispatchResult { + let prepare_sync_committee: PreparedSyncCommitteeOf = + sync_committee.try_into().map_err(|_| >::BLSPreparePublicKeysFailed)?; + >::insert(period, prepare_sync_committee); - log::trace!( + >::set(period); + + log::debug!( target: "ethereum-beacon-client", "💫 Updated latest sync committee period stored to {}.", period ); - >::set(period); - Self::deposit_event(Event::SyncCommitteeUpdated { period }); + Ok(()) } fn store_finalized_header(block_root: H256, header: BeaconHeader) -> DispatchResult { @@ -919,7 +881,7 @@ pub mod pallet { domain_type: Vec, fork_version: ForkVersion, genesis_validators_root: H256, - ) -> Result { + ) -> Result> { let fork_data_root = Self::compute_fork_data_root(fork_version, genesis_validators_root)?; @@ -933,7 +895,7 @@ pub mod pallet { fn compute_fork_data_root( current_version: ForkVersion, genesis_validators_root: H256, - ) -> Result { + ) -> Result> { let hash_root = ForkData { current_version, genesis_validators_root: genesis_validators_root.into(), @@ -956,6 +918,14 @@ pub mod pallet { Ok(()) } + pub(super) fn sync_committee_for_period( + period: u64, + ) -> Result> { + let pub_keys = + >::get(period).ok_or(Error::::SyncCommitteeMissing)?; + Ok(pub_keys) + } + pub(super) fn compute_fork_version(epoch: u64) -> ForkVersion { let fork_versions = T::ForkVersions::get(); @@ -1017,6 +987,52 @@ pub mod pallet { }, } } + + pub fn participant_pubkeys( + sync_committee_bits: &[u8], + sync_committee_pubkeys: &Vec, + ) -> Result, Error> { + let mut pubkeys: Vec = Vec::new(); + for (bit, pubkey) in sync_committee_bits.iter().zip(sync_committee_pubkeys.iter()) { + if *bit == 1 as u8 { + let pubk = pubkey.clone(); + pubkeys.push(pubk); + } + } + Ok(pubkeys) + } + + pub fn absent_pubkeys( + sync_committee_bits: &[u8], + sync_committee_pubkeys: &Vec, + ) -> Result, Error> { + let mut pubkeys: Vec = Vec::new(); + for (bit, pubkey) in sync_committee_bits.iter().zip(sync_committee_pubkeys.iter()) { + if *bit == 0 as u8 { + let pubk = pubkey.clone(); + pubkeys.push(pubk); + } + } + Ok(pubkeys) + } + + // Calculate signing root for BeaconHeader + pub fn signing_root( + header: BeaconHeader, + validators_root: H256, + signature_slot: u64, + ) -> Result> { + let fork_version = Self::compute_fork_version(Self::compute_epoch_at_slot( + signature_slot, + config::SLOTS_PER_EPOCH, + )); + let domain_type = config::DOMAIN_SYNC_COMMITTEE.to_vec(); + // Domains are used for for seeds, for signatures, and for selecting aggregators. + let domain = Self::compute_domain(domain_type, fork_version, validators_root)?; + // Hash tree root of SigningData - object root + domain + let signing_root = Self::compute_signing_root(header, domain)?; + Ok(signing_root) + } } impl Verifier for Pallet { diff --git a/parachain/pallets/ethereum-beacon-client/src/mock.rs b/parachain/pallets/ethereum-beacon-client/src/mock.rs index bb83a5a2ef..ae22dcd636 100644 --- a/parachain/pallets/ethereum-beacon-client/src/mock.rs +++ b/parachain/pallets/ethereum-beacon-client/src/mock.rs @@ -4,7 +4,6 @@ use crate::config; use crate as ethereum_beacon_client; use frame_support::parameter_types; -use frame_system as system; use pallet_timestamp; use primitives::{BeaconHeader, Fork, ForkVersions, PublicKey, Signature}; use sp_core::H256; @@ -192,7 +191,14 @@ pub mod mock_mainnet { // Build genesis storage according to the mock runtime. pub fn new_tester() -> sp_io::TestExternalities { - system::GenesisConfig::default().build_storage::().unwrap().into() + #[cfg(not(feature = "minimal"))] + use crate::mock::mock_mainnet::Timestamp; + #[cfg(feature = "minimal")] + use crate::mock::mock_minimal::Timestamp; + let t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + let mut ext = sp_io::TestExternalities::new(t); + ext.execute_with(|| Timestamp::set_timestamp(30_000)); + ext } pub struct BLSSignatureVerifyTest< diff --git a/parachain/pallets/ethereum-beacon-client/src/tests.rs b/parachain/pallets/ethereum-beacon-client/src/tests.rs index 289d357c42..f76a41faac 100644 --- a/parachain/pallets/ethereum-beacon-client/src/tests.rs +++ b/parachain/pallets/ethereum-beacon-client/src/tests.rs @@ -1,6 +1,20 @@ use crate::{mock::*, verify_merkle_proof, BeaconHeader, Error}; use frame_support::{assert_err, assert_ok}; use hex_literal::hex; +use primitives::{ + fast_aggregate_verify_legacy, prepare_g1_pubkeys, BlsError, PublicKey, PublicKeyPrepared, +}; + +pub fn prepare_milagro_pubkeys() -> Result, &'static str> { + let pubkeys = vec![ + PublicKey(hex!("a73eb991aa22cdb794da6fcde55a427f0a4df5a4a70de23a988b5e5fc8c4d844f66d990273267a54dd21579b7ba6a086").into()), + PublicKey(hex!("b29043a7273d0a2dbc2b747dcf6a5eccbd7ccb44b2d72e985537b117929bc3fd3a99001481327788ad040b4077c47c0d").into()), + PublicKey(hex!("b928f3beb93519eecf0145da903b40a4c97dca00b21f12ac0df3be9116ef2ef27b2ae6bcd4c5bc2d54ef5a70627efcb7").into()), + PublicKey(hex!("9446407bcd8e5efe9f2ac0efbfa9e07d136e68b03c5ebc5bde43db3b94773de8605c30419eb2596513707e4e7448bb50").into()), + ]; + let milagro_pubkeys = prepare_g1_pubkeys(&pubkeys).unwrap(); + Ok(milagro_pubkeys) +} #[test] pub fn test_get_sync_committee_sum() { @@ -196,13 +210,9 @@ pub fn test_merkle_proof_fails_if_depth_and_branch_dont_match() { #[test] pub fn test_bls_fast_aggregate_verify_minimal() { new_tester::().execute_with(|| { - assert_ok!(mock_minimal::EthereumBeaconClient::bls_fast_aggregate_verify( - &[ - hex!("a73eb991aa22cdb794da6fcde55a427f0a4df5a4a70de23a988b5e5fc8c4d844f66d990273267a54dd21579b7ba6a086").into(), - hex!("b29043a7273d0a2dbc2b747dcf6a5eccbd7ccb44b2d72e985537b117929bc3fd3a99001481327788ad040b4077c47c0d").into(), - hex!("b928f3beb93519eecf0145da903b40a4c97dca00b21f12ac0df3be9116ef2ef27b2ae6bcd4c5bc2d54ef5a70627efcb7").into(), - hex!("9446407bcd8e5efe9f2ac0efbfa9e07d136e68b03c5ebc5bde43db3b94773de8605c30419eb2596513707e4e7448bb50").into(), - ], + let milagro_pubkeys = prepare_milagro_pubkeys().unwrap(); + assert_ok!(fast_aggregate_verify_legacy( + &milagro_pubkeys, hex!("69241e7146cdcc5a5ddc9a60bab8f378c0271e548065a38bcc60624e1dbed97f").into(), &hex!("b204e9656cbeb79a9a8e397920fd8e60c5f5d9443f58d42186f773c6ade2bd263e2fe6dbdc47f148f871ed9a00b8ac8b17a40d65c8d02120c00dca77495888366b4ccc10f1c6daa02db6a7516555ca0665bca92a647b5f3a514fa083fdc53b6e").into() )); @@ -212,48 +222,37 @@ pub fn test_bls_fast_aggregate_verify_minimal() { #[test] pub fn test_bls_fast_aggregate_verify_invalid_point() { new_tester::().execute_with(|| { - assert_err!(mock_minimal::EthereumBeaconClient::bls_fast_aggregate_verify( - &[ - hex!("973eb991aa22cdb794da6fcde55a427f0a4df5a4a70de23a988b5e5fc8c4d844f66d990273267a54dd21579b7ba6a086").into(), - hex!("b29043a7273d0a2dbc2b747dcf6a5eccbd7ccb44b2d72e985537b117929bc3fd3a99001481327788ad040b4077c47c0d").into(), - hex!("b928f3beb93519eecf0145da903b40a4c97dca00b21f12ac0df3be9116ef2ef27b2ae6bcd4c5bc2d54ef5a70627efcb7").into(), - hex!("9446407bcd8e5efe9f2ac0efbfa9e07d136e68b03c5ebc5bde43db3b94773de8605c30419eb2596513707e4e7448bb50").into(), - ], - hex!("69241e7146cdcc5a5ddc9a60bab8f378c0271e548065a38bcc60624e1dbed97f").into(), - &hex!("b204e9656cbeb79a9a8e397920fd8e60c5f5d9443f58d42186f773c6ade2bd263e2fe6dbdc47f148f871ed9a00b8ac8b17a40d65c8d02120c00dca77495888366b4ccc10f1c6daa02db6a7516555ca0665bca92a647b5f3a514fa083fdc53b6e").into() - ), Error::::InvalidSignaturePoint); + let pubkeys = vec![ + PublicKey(hex!("973eb991aa22cdb794da6fcde55a427f0a4df5a4a70de23a988b5e5fc8c4d844f66d990273267a54dd21579b7ba6a086").into()), + PublicKey(hex!("b29043a7273d0a2dbc2b747dcf6a5eccbd7ccb44b2d72e985537b117929bc3fd3a99001481327788ad040b4077c47c0d").into()), + PublicKey(hex!("b928f3beb93519eecf0145da903b40a4c97dca00b21f12ac0df3be9116ef2ef27b2ae6bcd4c5bc2d54ef5a70627efcb7").into()), + PublicKey(hex!("9446407bcd8e5efe9f2ac0efbfa9e07d136e68b03c5ebc5bde43db3b94773de8605c30419eb2596513707e4e7448bb50").into()), + ]; + assert_err!(prepare_g1_pubkeys(&pubkeys), BlsError::InvalidPublicKey); }); } #[test] pub fn test_bls_fast_aggregate_verify_invalid_message() { new_tester::().execute_with(|| { - assert_err!(mock_minimal::EthereumBeaconClient::bls_fast_aggregate_verify( - &[ - hex!("a73eb991aa22cdb794da6fcde55a427f0a4df5a4a70de23a988b5e5fc8c4d844f66d990273267a54dd21579b7ba6a086").into(), - hex!("b29043a7273d0a2dbc2b747dcf6a5eccbd7ccb44b2d72e985537b117929bc3fd3a99001481327788ad040b4077c47c0d").into(), - hex!("b928f3beb93519eecf0145da903b40a4c97dca00b21f12ac0df3be9116ef2ef27b2ae6bcd4c5bc2d54ef5a70627efcb7").into(), - hex!("9446407bcd8e5efe9f2ac0efbfa9e07d136e68b03c5ebc5bde43db3b94773de8605c30419eb2596513707e4e7448bb50").into(), - ], + let milagro_pubkeys = prepare_milagro_pubkeys().unwrap(); + assert_err!(fast_aggregate_verify_legacy( + &milagro_pubkeys, hex!("99241e7146cdcc5a5ddc9a60bab8f378c0271e548065a38bcc60624e1dbed97f").into(), &hex!("b204e9656cbeb79a9a8e397920fd8e60c5f5d9443f58d42186f773c6ade2bd263e2fe6dbdc47f148f871ed9a00b8ac8b17a40d65c8d02120c00dca77495888366b4ccc10f1c6daa02db6a7516555ca0665bca92a647b5f3a514fa083fdc53b6e").into() - ), Error::::SignatureVerificationFailed); + ), BlsError::SignatureVerificationFailed); }); } #[test] pub fn test_bls_fast_aggregate_verify_invalid_signature() { new_tester::().execute_with(|| { - assert_err!(mock_minimal::EthereumBeaconClient::bls_fast_aggregate_verify( - &[ - hex!("a73eb991aa22cdb794da6fcde55a427f0a4df5a4a70de23a988b5e5fc8c4d844f66d990273267a54dd21579b7ba6a086").into(), - hex!("b29043a7273d0a2dbc2b747dcf6a5eccbd7ccb44b2d72e985537b117929bc3fd3a99001481327788ad040b4077c47c0d").into(), - hex!("b928f3beb93519eecf0145da903b40a4c97dca00b21f12ac0df3be9116ef2ef27b2ae6bcd4c5bc2d54ef5a70627efcb7").into(), - hex!("9446407bcd8e5efe9f2ac0efbfa9e07d136e68b03c5ebc5bde43db3b94773de8605c30419eb2596513707e4e7448bb50").into(), - ], + let milagro_pubkeys = prepare_milagro_pubkeys().unwrap(); + assert_err!(fast_aggregate_verify_legacy( + &milagro_pubkeys, hex!("69241e7146cdcc5a5ddc9a60bab8f378c0271e548065a38bcc60624e1dbed97f").into(), &hex!("c204e9656cbeb79a9a8e397920fd8e60c5f5d9443f58d42186f773c6ade2bd263e2fe6dbdc47f148f871ed9a00b8ac8b17a40d65c8d02120c00dca77495888366b4ccc10f1c6daa02db6a7516555ca0665bca92a647b5f3a514fa083fdc53b6e").into() - ), Error::::InvalidSignature); + ), BlsError::InvalidSignature); }); } diff --git a/parachain/pallets/ethereum-beacon-client/src/tests_mainnet.rs b/parachain/pallets/ethereum-beacon-client/src/tests_mainnet.rs index 0f38d9e817..8b6f1ef6b3 100644 --- a/parachain/pallets/ethereum-beacon-client/src/tests_mainnet.rs +++ b/parachain/pallets/ethereum-beacon-client/src/tests_mainnet.rs @@ -4,12 +4,13 @@ use crate::{ config::{SYNC_COMMITTEE_BITS_SIZE, SYNC_COMMITTEE_SIZE}, mock::*, Error, ExecutionHeaders, FinalizedBeaconHeaders, FinalizedBeaconHeadersBlockRoot, - FinalizedHeaderState, LatestFinalizedHeaderState, LatestSyncCommitteePeriod, SyncCommittees, - ValidatorsRoot, + FinalizedHeaderState, LatestFinalizedHeaderState, LatestSyncCommitteePeriod, ValidatorsRoot, }; use frame_support::{assert_err, assert_ok}; use hex_literal::hex; -use primitives::decompress_sync_committee_bits; +use primitives::{ + decompress_sync_committee_bits, fast_aggregate_verify_legacy, prepare_g1_pubkeys, +}; use sp_core::H256; #[test] @@ -29,18 +30,19 @@ fn it_syncs_from_an_initial_checkpoint() { fn it_updates_a_committee_period_sync_update() { let update = get_committee_sync_period_update::(); - let genesis = get_initial_sync::(); + let current_sync_committee = + get_initial_sync::<{ SYNC_COMMITTEE_SIZE }>().current_sync_committee; let current_period = mock_mainnet::EthereumBeaconClient::compute_current_sync_period( update.attested_header.slot, ); new_tester::().execute_with(|| { - SyncCommittees::::insert( - current_period, - genesis.current_sync_committee, - ); LatestSyncCommitteePeriod::::set(current_period); - ValidatorsRoot::::set(genesis.validators_root); + ValidatorsRoot::::set(get_validators_root::<{ SYNC_COMMITTEE_SIZE }>()); + assert_ok!(mock_mainnet::EthereumBeaconClient::store_sync_committee( + current_period, + ¤t_sync_committee, + )); let block_root: H256 = update.finalized_header.hash_tree_root().unwrap(); @@ -56,7 +58,8 @@ fn it_updates_a_committee_period_sync_update() { #[test] fn it_processes_a_finalized_header_update() { let update = get_finalized_header_update::(); - let genesis = get_initial_sync::(); + let current_sync_committee = + get_initial_sync::<{ SYNC_COMMITTEE_SIZE }>().current_sync_committee; let current_period = mock_mainnet::EthereumBeaconClient::compute_current_sync_period( update.attested_header.slot, ); @@ -67,16 +70,16 @@ fn it_processes_a_finalized_header_update() { new_tester::().execute_with(|| { mock_mainnet::Timestamp::set_timestamp(mock_pallet_time * 1000); // needs to be in milliseconds - SyncCommittees::::insert( + assert_ok!(mock_mainnet::EthereumBeaconClient::store_sync_committee( current_period, - genesis.current_sync_committee, - ); + ¤t_sync_committee, + )); LatestFinalizedHeaderState::::set(FinalizedHeaderState { beacon_block_root: Default::default(), import_time, beacon_slot: slot - 1, }); - ValidatorsRoot::::set(genesis.validators_root); + ValidatorsRoot::::set(get_validators_root::<{ SYNC_COMMITTEE_SIZE }>()); assert_ok!(mock_mainnet::EthereumBeaconClient::import_finalized_header( mock_mainnet::RuntimeOrigin::signed(1), @@ -92,7 +95,8 @@ fn it_processes_a_finalized_header_update() { #[test] fn it_errors_when_weak_subjectivity_period_exceeded_for_a_finalized_header_update() { let update = get_finalized_header_update::(); - let genesis = get_initial_sync::(); + let current_sync_committee = + get_initial_sync::<{ SYNC_COMMITTEE_SIZE }>().current_sync_committee; let current_period = mock_mainnet::EthereumBeaconClient::compute_current_sync_period( update.attested_header.slot, @@ -104,16 +108,16 @@ fn it_errors_when_weak_subjectivity_period_exceeded_for_a_finalized_header_updat new_tester::().execute_with(|| { mock_mainnet::Timestamp::set_timestamp(mock_pallet_time * 1000); // needs to be in milliseconds - SyncCommittees::::insert( + assert_ok!(mock_mainnet::EthereumBeaconClient::store_sync_committee( current_period, - genesis.current_sync_committee, - ); + ¤t_sync_committee, + )); LatestFinalizedHeaderState::::set(FinalizedHeaderState { beacon_block_root: Default::default(), import_time, beacon_slot: slot - 1, }); - ValidatorsRoot::::set(genesis.validators_root); + ValidatorsRoot::::set(get_validators_root::<{ SYNC_COMMITTEE_SIZE }>()); assert_err!( mock_mainnet::EthereumBeaconClient::import_finalized_header( @@ -128,7 +132,8 @@ fn it_errors_when_weak_subjectivity_period_exceeded_for_a_finalized_header_updat #[test] fn it_processes_a_header_update() { let update = get_header_update::(); - let genesis = get_initial_sync::(); + let current_sync_committee = + get_initial_sync::<{ config::SYNC_COMMITTEE_SIZE }>().current_sync_committee; let current_period = mock_mainnet::EthereumBeaconClient::compute_current_sync_period(update.beacon_header.slot); @@ -138,11 +143,11 @@ fn it_processes_a_header_update() { let finalized_block_root: H256 = finalized_update.finalized_header.hash_tree_root().unwrap(); new_tester::().execute_with(|| { - SyncCommittees::::insert( + assert_ok!(mock_mainnet::EthereumBeaconClient::store_sync_committee( current_period, - genesis.current_sync_committee, - ); - ValidatorsRoot::::set(genesis.validators_root); + ¤t_sync_committee, + )); + ValidatorsRoot::::set(get_validators_root::<{ SYNC_COMMITTEE_SIZE }>()); LatestFinalizedHeaderState::::set(FinalizedHeaderState { beacon_block_root: finalized_block_root, beacon_slot: finalized_slot, @@ -182,17 +187,29 @@ pub fn test_bls_fast_aggregate_verify() { let test_data = get_bls_signature_verify_test_data::(); - let participation = decompress_sync_committee_bits::< + let milagro_pubkeys = prepare_g1_pubkeys(&test_data.pubkeys.to_vec()).unwrap(); + + let participant_bits = decompress_sync_committee_bits::< SYNC_COMMITTEE_SIZE, SYNC_COMMITTEE_BITS_SIZE, >(test_data.sync_committee_bits); - assert_ok!(mock_mainnet::EthereumBeaconClient::verify_signed_header( - &participation, - &test_data.sync_committee_signature, - &test_data.pubkeys, + let participant_pubkeys = mock_mainnet::EthereumBeaconClient::participant_pubkeys( + &participant_bits, + &milagro_pubkeys, + ) + .unwrap(); + + let signing_root = mock_mainnet::EthereumBeaconClient::signing_root( test_data.header, test_data.validators_root, test_data.signature_slot, + ) + .unwrap(); + + assert_ok!(fast_aggregate_verify_legacy( + &participant_pubkeys, + signing_root, + &test_data.sync_committee_signature, )); } diff --git a/parachain/pallets/ethereum-beacon-client/src/tests_minimal.rs b/parachain/pallets/ethereum-beacon-client/src/tests_minimal.rs index f3774b2b95..b016963e77 100644 --- a/parachain/pallets/ethereum-beacon-client/src/tests_minimal.rs +++ b/parachain/pallets/ethereum-beacon-client/src/tests_minimal.rs @@ -4,12 +4,13 @@ use crate::{ mock::*, pallet::FinalizedBeaconHeadersBlockRoot, Error, ExecutionHeaderState, ExecutionHeaders, FinalizedBeaconHeaders, FinalizedHeaderState, - LatestExecutionHeaderState, LatestFinalizedHeaderState, LatestSyncCommitteePeriod, - SyncCommittees, ValidatorsRoot, + LatestExecutionHeaderState, LatestFinalizedHeaderState, ValidatorsRoot, }; use frame_support::{assert_err, assert_ok}; use hex_literal::hex; -use primitives::decompress_sync_committee_bits; +use primitives::{ + decompress_sync_committee_bits, fast_aggregate_verify_legacy, prepare_g1_pubkeys, +}; use sp_core::H256; use std::time::{SystemTime, UNIX_EPOCH}; @@ -40,12 +41,10 @@ fn it_updates_a_committee_period_sync_update() { update.attested_header.slot, ); - SyncCommittees::::insert( + assert_ok!(mock_minimal::EthereumBeaconClient::store_sync_committee( current_period, - initial_sync.current_sync_committee, - ); - - LatestSyncCommitteePeriod::::set(current_period); + &initial_sync.current_sync_committee, + )); assert_ok!(mock_minimal::EthereumBeaconClient::sync_committee_period_update( mock_minimal::RuntimeOrigin::signed(1), @@ -125,18 +124,16 @@ fn it_updates_a_invalid_committee_period_sync_update_with_duplicate_entry() { update.attested_header.slot, ); - SyncCommittees::::insert( + assert_ok!(mock_minimal::EthereumBeaconClient::store_sync_committee( current_period, - initial_sync.current_sync_committee.clone(), - ); + &initial_sync.current_sync_committee, + )); // initialize with period of the next update - SyncCommittees::::insert( + assert_ok!(mock_minimal::EthereumBeaconClient::store_sync_committee( current_period + 1, - initial_sync.current_sync_committee, - ); - - LatestSyncCommitteePeriod::::set(current_period + 1); + &initial_sync.current_sync_committee, + )); assert_err!( mock_minimal::EthereumBeaconClient::sync_committee_period_update( @@ -152,7 +149,6 @@ fn it_updates_a_invalid_committee_period_sync_update_with_duplicate_entry() { fn it_processes_a_finalized_header_update() { let update = get_finalized_header_update::(); let initial_sync = get_initial_sync::(); - let current_sync_committee = initial_sync.current_sync_committee; let current_period = mock_minimal::EthereumBeaconClient::compute_current_sync_period( update.attested_header.slot, @@ -176,8 +172,11 @@ fn it_processes_a_finalized_header_update() { // been imported already. beacon_slot: update.finalized_header.slot - 1, }); - SyncCommittees::::insert(current_period, current_sync_committee); ValidatorsRoot::::set(get_validators_root::()); + assert_ok!(mock_minimal::EthereumBeaconClient::store_sync_committee( + current_period, + &initial_sync.current_sync_committee, + )); assert_ok!(mock_minimal::EthereumBeaconClient::import_finalized_header( mock_minimal::RuntimeOrigin::signed(1), @@ -255,7 +254,6 @@ fn it_processes_a_header_update() { mock_minimal::EthereumBeaconClient::compute_current_sync_period(update.beacon_header.slot); new_tester::().execute_with(|| { - SyncCommittees::::insert(current_period, current_sync_committee); ValidatorsRoot::::set(get_validators_root::()); LatestFinalizedHeaderState::::set(FinalizedHeaderState { beacon_block_root: finalized_block_root, @@ -266,6 +264,10 @@ fn it_processes_a_header_update() { finalized_block_root, finalized_update.block_roots_root, ); + assert_ok!(mock_minimal::EthereumBeaconClient::store_sync_committee( + current_period, + ¤t_sync_committee, + )); assert_ok!(mock_minimal::EthereumBeaconClient::import_execution_header( mock_minimal::RuntimeOrigin::signed(1), @@ -372,17 +374,29 @@ pub fn test_bls_fast_aggregate_verify() { let test_data = get_bls_signature_verify_test_data::(); - let participation = decompress_sync_committee_bits::< + let milagro_pubkeys = prepare_g1_pubkeys(&test_data.pubkeys.to_vec()).unwrap(); + + let participant_bits = decompress_sync_committee_bits::< SYNC_COMMITTEE_SIZE, SYNC_COMMITTEE_BITS_SIZE, >(test_data.sync_committee_bits); - assert_ok!(mock_minimal::EthereumBeaconClient::verify_signed_header( - &participation, - &test_data.sync_committee_signature, - &test_data.pubkeys, + let participant_pubkeys = mock_minimal::EthereumBeaconClient::participant_pubkeys( + &participant_bits, + &milagro_pubkeys, + ) + .unwrap(); + + let signing_root = mock_minimal::EthereumBeaconClient::signing_root( test_data.header, test_data.validators_root, test_data.signature_slot, + ) + .unwrap(); + + assert_ok!(fast_aggregate_verify_legacy( + &participant_pubkeys, + signing_root, + &test_data.sync_committee_signature, )); } diff --git a/parachain/pallets/ethereum-beacon-client/src/weights.rs b/parachain/pallets/ethereum-beacon-client/src/weights.rs index a05bc4c641..fdcad77533 100644 --- a/parachain/pallets/ethereum-beacon-client/src/weights.rs +++ b/parachain/pallets/ethereum-beacon-client/src/weights.rs @@ -37,9 +37,9 @@ pub trait WeightInfo { fn import_finalized_header() -> Weight; fn import_execution_header() -> Weight; fn unblock_bridge() -> Weight; + fn bls_fast_aggregate_verify_pre_aggregated() -> Weight; fn bls_fast_aggregate_verify() -> Weight; - fn bls_aggregate_pubkey() -> Weight; - fn bls_verify_message() -> Weight; + fn bls_fast_aggregate_verify_legacy() -> Weight; } // For backwards compatibility and tests @@ -63,16 +63,16 @@ impl WeightInfo for () { Weight::from_parts(13_941_000, 0) .saturating_add(RocksDbWeight::get().writes(1)) } - fn bls_fast_aggregate_verify() -> Weight { - Weight::from_parts(123_459_134_000, 0) + fn bls_fast_aggregate_verify_pre_aggregated() -> Weight { + Weight::from_parts(28_368_043_000, 0) .saturating_add(Weight::from_parts(0, 0)) } - fn bls_aggregate_pubkey() -> Weight { - Weight::from_parts(94_487_034_000, 0) + fn bls_fast_aggregate_verify() -> Weight { + Weight::from_parts(123_459_134_000, 0) .saturating_add(Weight::from_parts(0, 0)) } - fn bls_verify_message() -> Weight { - Weight::from_parts(28_368_043_000, 0) + fn bls_fast_aggregate_verify_legacy() -> Weight { + Weight::from_parts(123_459_134_000, 0) .saturating_add(Weight::from_parts(0, 0)) } } diff --git a/parachain/primitives/beacon/Cargo.toml b/parachain/primitives/beacon/Cargo.toml index ba4698a4c9..2645bc808c 100644 --- a/parachain/primitives/beacon/Cargo.toml +++ b/parachain/primitives/beacon/Cargo.toml @@ -26,6 +26,7 @@ byte-slice-cast = { version = "1.2.1", default-features = false } snowbridge-ethereum = { path = "../../primitives/ethereum", default-features = false } static_assertions = { version = "1.1.0" } +milagro_bls = { git = "https://github.com/snowfork/milagro_bls", default-features = false, rev="b95ca5be05e3c6e5b865b7e1f4a768dfa97f27f8"} [dev-dependencies] hex-literal = { version = "0.4.1" } @@ -46,4 +47,5 @@ std = [ "snowbridge-ethereum/std", "ssz-rs/std", "byte-slice-cast/std", + "milagro_bls/std", ] diff --git a/parachain/primitives/beacon/src/bls.rs b/parachain/primitives/beacon/src/bls.rs new file mode 100644 index 0000000000..d5e40a024a --- /dev/null +++ b/parachain/primitives/beacon/src/bls.rs @@ -0,0 +1,100 @@ +use crate::{PublicKey, Signature}; +use codec::{Decode, Encode}; +use frame_support::ensure; +pub use milagro_bls::{ + AggregatePublicKey, AggregateSignature, PublicKey as PublicKeyPrepared, + Signature as SignaturePrepared, +}; +use scale_info::TypeInfo; +use sp_core::H256; +use sp_runtime::RuntimeDebug; +use sp_std::prelude::*; + +#[derive(Copy, Clone, Encode, Decode, Eq, PartialEq, TypeInfo, RuntimeDebug)] +pub enum BlsError { + InvalidSignature, + InvalidPublicKey, + InvalidAggregatePublicKeys, + SignatureVerificationFailed, +} + +// legacy fast_aggregate_verify from all participant keys +pub fn fast_aggregate_verify_legacy( + pubkeys: &Vec, + message: H256, + signature: &Signature, +) -> Result<(), BlsError> { + let agg_sig = prepare_aggregate_signature(signature)?; + let agg_key = prepare_aggregate_pubkey(&pubkeys)?; + // major bottleneck which consumes more than 90% of weight in the entire call + fast_aggregate_verify_pre_aggregated(agg_sig, agg_key, message) +} + +// fast_aggregate_verify optimized with aggregate key subtracting absent ones +pub fn fast_aggregate_verify( + aggregate_pubkey: &PublicKeyPrepared, + absent_pubkeys: &Vec, + message: H256, + signature: &Signature, +) -> Result<(), BlsError> { + let agg_sig = prepare_aggregate_signature(signature)?; + let agg_key = prepare_aggregate_pubkey_from_absent(aggregate_pubkey, &absent_pubkeys)?; + fast_aggregate_verify_pre_aggregated(agg_sig, agg_key, message) +} + +// Decompress one public key into a point in G1 +pub fn prepare_milagro_pubkey(pubkey: &PublicKey) -> Result { + PublicKeyPrepared::from_bytes_unchecked(&pubkey.0).map_err(|_| BlsError::InvalidPublicKey) +} + +// Prepare for G1 public keys +pub fn prepare_g1_pubkeys(pubkeys: &Vec) -> Result, BlsError> { + pubkeys + .iter() + // Deserialize one public key from compressed bytes + .map(|pubkey| prepare_milagro_pubkey(pubkey)) + .collect::, BlsError>>() +} + +// Prepare for G1 AggregatePublicKey +pub fn prepare_aggregate_pubkey( + pubkeys: &Vec, +) -> Result { + let agg_pub_key = + AggregatePublicKey::into_aggregate(pubkeys).map_err(|_| BlsError::InvalidPublicKey)?; + Ok(agg_pub_key) +} + +// Prepare for G1 AggregatePublicKey +pub fn prepare_aggregate_pubkey_from_absent( + aggregate_key: &PublicKeyPrepared, + absent_pubkeys: &Vec, +) -> Result { + let mut aggregate_pubkey = AggregatePublicKey::from_public_key(aggregate_key); + if !absent_pubkeys.is_empty() { + let absent_aggregate_key = prepare_aggregate_pubkey(absent_pubkeys)?; + aggregate_pubkey.point.sub(&absent_aggregate_key.point); + } + Ok(AggregatePublicKey { point: aggregate_pubkey.point }) +} + +// Prepare for G2 AggregateSignature, normally more expensive than G1 operation +pub fn prepare_aggregate_signature(signature: &Signature) -> Result { + let sig = + SignaturePrepared::from_bytes(&signature.0).map_err(|_| BlsError::InvalidSignature)?; + let agg_sig = AggregateSignature::from_signature(&sig); + Ok(agg_sig) +} + +// fast_aggregate_verify_pre_aggregated which is the most expensive call in beacon light client +pub fn fast_aggregate_verify_pre_aggregated( + agg_sig: AggregateSignature, + aggregate_key: AggregatePublicKey, + message: H256, +) -> Result<(), BlsError> { + ensure!( + agg_sig.fast_aggregate_verify_pre_aggregated(&message[..], &aggregate_key), + BlsError::SignatureVerificationFailed + ); + Ok(()) +} diff --git a/parachain/primitives/beacon/src/lib.rs b/parachain/primitives/beacon/src/lib.rs index e3810bd079..fa41aee55f 100644 --- a/parachain/primitives/beacon/src/lib.rs +++ b/parachain/primitives/beacon/src/lib.rs @@ -1,6 +1,7 @@ #![cfg_attr(not(feature = "std"), no_std)] pub mod bits; +pub mod bls; pub mod config; pub mod merkle_proof; pub mod receipt; @@ -13,11 +14,16 @@ mod serde_utils; pub use types::{ BeaconHeader, CompactExecutionHeader, ExecutionHeaderState, ExecutionPayloadHeader, - FinalizedHeaderState, Fork, ForkData, ForkVersion, ForkVersions, PublicKey, Signature, - SigningData, SyncAggregate, SyncCommittee, + FinalizedHeaderState, Fork, ForkData, ForkVersion, ForkVersions, PreparedSyncCommittee, + PublicKey, Signature, SigningData, SyncAggregate, SyncCommittee, }; pub use updates::{FinalizedHeaderUpdate, HeaderUpdate, InitialUpdate, SyncCommitteeUpdate}; pub use bits::decompress_sync_committee_bits; +pub use bls::{ + fast_aggregate_verify, fast_aggregate_verify_legacy, prepare_aggregate_pubkey, + prepare_aggregate_pubkey_from_absent, prepare_aggregate_signature, prepare_g1_pubkeys, + AggregatePublicKey, AggregateSignature, BlsError, PublicKeyPrepared, SignaturePrepared, +}; pub use merkle_proof::verify_merkle_proof; pub use receipt::verify_receipt_proof; diff --git a/parachain/primitives/beacon/src/types.rs b/parachain/primitives/beacon/src/types.rs index 8ed1531d31..c33af41fe5 100644 --- a/parachain/primitives/beacon/src/types.rs +++ b/parachain/primitives/beacon/src/types.rs @@ -1,8 +1,8 @@ use codec::{Decode, Encode, MaxEncodedLen}; -use frame_support::{CloneNoBound, PartialEqNoBound, RuntimeDebugNoBound}; +use frame_support::{traits::Get, CloneNoBound, PartialEqNoBound, RuntimeDebugNoBound}; use scale_info::TypeInfo; use sp_core::{H160, H256, U256}; -use sp_runtime::RuntimeDebug; +use sp_runtime::{BoundedVec, RuntimeDebug}; use sp_std::prelude::*; use crate::config::{PUBKEY_SIZE, SIGNATURE_SIZE}; @@ -21,6 +21,9 @@ use ssz_rs::MerkleizationError; pub use crate::bits::decompress_sync_committee_bits; +use crate::bls::{prepare_g1_pubkeys, prepare_milagro_pubkey, BlsError}; +use milagro_bls::PublicKey as PublicKeyPrepared; + pub type ValidatorIndex = u64; pub type ForkVersion = [u8; 4]; @@ -176,6 +179,28 @@ impl SyncCommittee { } } +/// Prepared G1 public key of sync committee as it is stored in the runtime storage. +#[derive(Clone, PartialEq, Eq, Encode, Decode, TypeInfo, MaxEncodedLen)] +#[scale_info(skip_type_params(MaxCommitteeSize))] +pub struct PreparedSyncCommittee> { + pub pubkeys: BoundedVec, + pub aggregate_pubkey: PublicKeyPrepared, +} + +impl> + TryFrom<&SyncCommittee> for PreparedSyncCommittee +{ + type Error = BlsError; + + fn try_from(sync_committee: &SyncCommittee) -> Result { + let g1_pubkeys = prepare_g1_pubkeys(&sync_committee.pubkeys.to_vec())?; + let pubkeys = BoundedVec::::try_from(g1_pubkeys) + .map_err(|_| BlsError::InvalidPublicKey)?; + let aggregate_pubkey = prepare_milagro_pubkey(&sync_committee.aggregate_pubkey)?; + Ok(PreparedSyncCommittee:: { pubkeys, aggregate_pubkey }) + } +} + /// Beacon block header as it is stored in the runtime storage. The block root is the /// Merklization of a BeaconHeader. #[derive(Clone, Default, Encode, Decode, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen)] diff --git a/parachain/rustfmt.toml b/parachain/rustfmt.toml index 441913f619..f6fbe80064 100644 --- a/parachain/rustfmt.toml +++ b/parachain/rustfmt.toml @@ -21,3 +21,4 @@ match_block_trailing_comma = true trailing_comma = "Vertical" trailing_semicolon = false use_field_init_shorthand = true +edition = "2021" From 8eb2d9aaf164215e5c3e54a6b7f68b7b5bf8a1ab Mon Sep 17 00:00:00 2001 From: ron Date: Tue, 2 May 2023 08:33:21 +0000 Subject: [PATCH 02/16] Update cumulus --- cumulus | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cumulus b/cumulus index 7a8220c7fc..262f554226 160000 --- a/cumulus +++ b/cumulus @@ -1 +1 @@ -Subproject commit 7a8220c7fcea968f2f35c46755cfd4c3dafab0f2 +Subproject commit 262f554226f9b6efa8f1ecb4770625d35ccb85c0 From 849e218b17597a11cd7e43b78b52ee14d1c936b2 Mon Sep 17 00:00:00 2001 From: ron Date: Tue, 2 May 2023 21:51:19 +0800 Subject: [PATCH 03/16] More refactoring --- .../src/benchmarking/util.rs | 19 +++--- .../pallets/ethereum-beacon-client/src/lib.rs | 58 +++++-------------- .../ethereum-beacon-client/src/tests.rs | 4 +- .../src/tests_mainnet.rs | 9 +-- .../src/tests_minimal.rs | 7 +-- parachain/primitives/beacon/src/bls.rs | 14 ++--- parachain/primitives/beacon/src/lib.rs | 4 +- parachain/primitives/beacon/src/types.rs | 26 +++++---- 8 files changed, 58 insertions(+), 83 deletions(-) diff --git a/parachain/pallets/ethereum-beacon-client/src/benchmarking/util.rs b/parachain/pallets/ethereum-beacon-client/src/benchmarking/util.rs index 69b343a80d..eb4df6f44e 100644 --- a/parachain/pallets/ethereum-beacon-client/src/benchmarking/util.rs +++ b/parachain/pallets/ethereum-beacon-client/src/benchmarking/util.rs @@ -3,8 +3,7 @@ use crate::{ Pallet as EthereumBeaconClient, SyncCommitteeUpdate, SyncCommittees, ValidatorsRoot, Vec, SYNC_COMMITTEE_SIZE, }; -use frame_support::traits::ConstU32; -use primitives::{PreparedSyncCommittee, PublicKeyPrepared}; +use primitives::{PublicKeyPrepared, SyncCommitteePrepared}; use sp_core::H256; use super::{initial_sync, sync_committee_update}; @@ -32,7 +31,7 @@ pub fn initialize_sync_committee() -> Result( update: &SyncCommitteeUpdate, -) -> Result>, &'static str> { +) -> Result, &'static str> { let current_period = EthereumBeaconClient::::compute_current_sync_period(update.attested_header.slot); let sync_committee = SyncCommittees::::get(current_period).ok_or("no sync committee")?; @@ -45,10 +44,11 @@ pub fn participant_pubkeys( let sync_committee_bits = decompress_sync_committee_bits(update.sync_aggregate.sync_committee_bits.clone()); let current_sync_committee = sync_committee::(update)?; - let pubkeys = EthereumBeaconClient::::participant_pubkeys( + let pubkeys = EthereumBeaconClient::::find_pubkeys( &sync_committee_bits, - ¤t_sync_committee.pubkeys, - )?; + ¤t_sync_committee.pubkeys.to_vec(), + true, + ); Ok(pubkeys) } @@ -58,10 +58,11 @@ pub fn absent_pubkeys( let sync_committee_bits = decompress_sync_committee_bits(update.sync_aggregate.sync_committee_bits.clone()); let current_sync_committee = sync_committee::(update)?; - let pubkeys = EthereumBeaconClient::::absent_pubkeys( + let pubkeys = EthereumBeaconClient::::find_pubkeys( &sync_committee_bits, - ¤t_sync_committee.pubkeys, - )?; + ¤t_sync_committee.pubkeys.to_vec(), + false, + ); Ok(pubkeys) } diff --git a/parachain/pallets/ethereum-beacon-client/src/lib.rs b/parachain/pallets/ethereum-beacon-client/src/lib.rs index c64bd7d9e3..bcae5c2d55 100644 --- a/parachain/pallets/ethereum-beacon-client/src/lib.rs +++ b/parachain/pallets/ethereum-beacon-client/src/lib.rs @@ -30,7 +30,7 @@ use frame_system::ensure_signed; use primitives::{ fast_aggregate_verify, verify_merkle_proof, verify_receipt_proof, BeaconHeader, BlsError, CompactExecutionHeader, ExecutionHeaderState, FinalizedHeaderState, ForkData, ForkVersion, - ForkVersions, PreparedSyncCommittee, PublicKeyPrepared, Signature, SigningData, + ForkVersions, PublicKeyPrepared, Signature, SigningData, }; use snowbridge_core::{Message, Verifier}; use sp_core::H256; @@ -54,7 +54,7 @@ pub type SyncCommitteeUpdate = pub type FinalizedHeaderUpdate = primitives::FinalizedHeaderUpdate; pub type SyncCommittee = primitives::SyncCommittee; -pub type PreparedSyncCommitteeOf = PreparedSyncCommittee>; +pub type SyncCommitteePrepared = primitives::SyncCommitteePrepared; fn decompress_sync_committee_bits( input: [u8; SYNC_COMMITTEE_BITS_SIZE], @@ -135,19 +135,7 @@ pub mod pallet { FinalizedBeaconHeaderSlotsExceeded, ExecutionHeaderMappingFailed, BLSPreparePublicKeysFailed, - BLSVerificationFailed(#[codec(skip)] &'static str), - } - - impl From for Error { - fn from(e: BlsError) -> Self { - match e { - BlsError::InvalidPublicKey | BlsError::InvalidAggregatePublicKeys => - Error::BLSVerificationFailed("InvalidPublicKey"), - BlsError::InvalidSignature => Error::BLSVerificationFailed("InvalidSignature"), - BlsError::SignatureVerificationFailed => - Error::BLSVerificationFailed("SignatureVerificationFailed"), - } - } + BLSVerificationFailed(BlsError), } #[pallet::hooks] @@ -188,7 +176,7 @@ pub mod pallet { #[pallet::storage] pub(super) type SyncCommittees = - StorageMap<_, Identity, u64, PreparedSyncCommitteeOf, OptionQuery>; + StorageMap<_, Identity, u64, SyncCommitteePrepared, OptionQuery>; #[pallet::genesis_config] pub struct GenesisConfig { @@ -691,14 +679,14 @@ pub mod pallet { pub(super) fn verify_signed_header( sync_committee_bits: &[u8], sync_committee_signature: &Signature, - sync_committee: &PreparedSyncCommitteeOf, + sync_committee: &SyncCommitteePrepared, header: BeaconHeader, validators_root: H256, signature_slot: u64, ) -> DispatchResult { // Gathers milagro pubkeys absent to participate let absent_pubkeys = - Self::absent_pubkeys(sync_committee_bits, &sync_committee.pubkeys)?; + Self::find_pubkeys(sync_committee_bits, &sync_committee.pubkeys, false); // Get signing root for BeaconHeader let signing_root = Self::signing_root(header, validators_root, signature_slot)?; @@ -710,7 +698,7 @@ pub mod pallet { signing_root, sync_committee_signature, ) - .map_err(|e| Error::::from(e))?; + .map_err(|e| Error::::BLSVerificationFailed(e))?; Ok(()) } @@ -778,7 +766,7 @@ pub mod pallet { } pub fn store_sync_committee(period: u64, sync_committee: &SyncCommittee) -> DispatchResult { - let prepare_sync_committee: PreparedSyncCommitteeOf = + let prepare_sync_committee: SyncCommitteePrepared = sync_committee.try_into().map_err(|_| >::BLSPreparePublicKeysFailed)?; >::insert(period, prepare_sync_committee); @@ -920,7 +908,7 @@ pub mod pallet { pub(super) fn sync_committee_for_period( period: u64, - ) -> Result> { + ) -> Result> { let pub_keys = >::get(period).ok_or(Error::::SyncCommitteeMissing)?; Ok(pub_keys) @@ -988,32 +976,18 @@ pub mod pallet { } } - pub fn participant_pubkeys( - sync_committee_bits: &[u8], - sync_committee_pubkeys: &Vec, - ) -> Result, Error> { - let mut pubkeys: Vec = Vec::new(); - for (bit, pubkey) in sync_committee_bits.iter().zip(sync_committee_pubkeys.iter()) { - if *bit == 1 as u8 { - let pubk = pubkey.clone(); - pubkeys.push(pubk); - } - } - Ok(pubkeys) - } - - pub fn absent_pubkeys( + pub fn find_pubkeys( sync_committee_bits: &[u8], - sync_committee_pubkeys: &Vec, - ) -> Result, Error> { + sync_committee_pubkeys: &[PublicKeyPrepared], + participant: bool, + ) -> Vec { let mut pubkeys: Vec = Vec::new(); for (bit, pubkey) in sync_committee_bits.iter().zip(sync_committee_pubkeys.iter()) { - if *bit == 0 as u8 { - let pubk = pubkey.clone(); - pubkeys.push(pubk); + if *bit == u8::from(participant) { + pubkeys.push(pubkey.clone()); } } - Ok(pubkeys) + pubkeys } // Calculate signing root for BeaconHeader diff --git a/parachain/pallets/ethereum-beacon-client/src/tests.rs b/parachain/pallets/ethereum-beacon-client/src/tests.rs index f76a41faac..1221425599 100644 --- a/parachain/pallets/ethereum-beacon-client/src/tests.rs +++ b/parachain/pallets/ethereum-beacon-client/src/tests.rs @@ -258,7 +258,9 @@ pub fn test_bls_fast_aggregate_verify_invalid_signature() { #[test] pub fn test_sync_committee_participation_is_supermajority() { - let bits = hex!("bffffffff7f1ffdfcfeffeffbfdffffbfffffdffffefefffdffff7f7ffff77fffdf7bff77ffdf7fffafffffff77fefffeff7effffffff5f7fedfffdfb6ddff7b"); + let bits = +hex!("bffffffff7f1ffdfcfeffeffbfdffffbfffffdffffefefffdffff7f7ffff77fffdf7bff77ffdf7fffafffffff77fefffeff7effffffff5f7fedfffdfb6ddff7b" +); let participation = primitives::decompress_sync_committee_bits::<512, 64>(bits); assert_ok!(mock_minimal::EthereumBeaconClient::sync_committee_participation_is_supermajority( &participation diff --git a/parachain/pallets/ethereum-beacon-client/src/tests_mainnet.rs b/parachain/pallets/ethereum-beacon-client/src/tests_mainnet.rs index 8b6f1ef6b3..51c7d159b3 100644 --- a/parachain/pallets/ethereum-beacon-client/src/tests_mainnet.rs +++ b/parachain/pallets/ethereum-beacon-client/src/tests_mainnet.rs @@ -65,7 +65,7 @@ fn it_processes_a_finalized_header_update() { ); let slot = update.finalized_header.slot; - let import_time = 1616508000u64 + (slot * config::SECONDS_PER_SLOT); // Goerli genesis time + finalized header update time + let import_time = 1616508000u64 + (slot * config::SECONDS_PER_SLOT); // Goerli genesis time + let mock_pallet_time = import_time + 3600; // plus one hour new_tester::().execute_with(|| { @@ -194,11 +194,8 @@ pub fn test_bls_fast_aggregate_verify() { SYNC_COMMITTEE_BITS_SIZE, >(test_data.sync_committee_bits); - let participant_pubkeys = mock_mainnet::EthereumBeaconClient::participant_pubkeys( - &participant_bits, - &milagro_pubkeys, - ) - .unwrap(); + let participant_pubkeys = + mock_mainnet::EthereumBeaconClient::find_pubkeys(&participant_bits, &milagro_pubkeys, true); let signing_root = mock_mainnet::EthereumBeaconClient::signing_root( test_data.header, diff --git a/parachain/pallets/ethereum-beacon-client/src/tests_minimal.rs b/parachain/pallets/ethereum-beacon-client/src/tests_minimal.rs index b016963e77..eb41ccc0ea 100644 --- a/parachain/pallets/ethereum-beacon-client/src/tests_minimal.rs +++ b/parachain/pallets/ethereum-beacon-client/src/tests_minimal.rs @@ -381,11 +381,8 @@ pub fn test_bls_fast_aggregate_verify() { SYNC_COMMITTEE_BITS_SIZE, >(test_data.sync_committee_bits); - let participant_pubkeys = mock_minimal::EthereumBeaconClient::participant_pubkeys( - &participant_bits, - &milagro_pubkeys, - ) - .unwrap(); + let participant_pubkeys = + mock_minimal::EthereumBeaconClient::find_pubkeys(&participant_bits, &milagro_pubkeys, true); let signing_root = mock_minimal::EthereumBeaconClient::signing_root( test_data.header, diff --git a/parachain/primitives/beacon/src/bls.rs b/parachain/primitives/beacon/src/bls.rs index d5e40a024a..f25ab560c7 100644 --- a/parachain/primitives/beacon/src/bls.rs +++ b/parachain/primitives/beacon/src/bls.rs @@ -1,6 +1,6 @@ use crate::{PublicKey, Signature}; use codec::{Decode, Encode}; -use frame_support::ensure; +use frame_support::{ensure, PalletError}; pub use milagro_bls::{ AggregatePublicKey, AggregateSignature, PublicKey as PublicKeyPrepared, Signature as SignaturePrepared, @@ -10,7 +10,7 @@ use sp_core::H256; use sp_runtime::RuntimeDebug; use sp_std::prelude::*; -#[derive(Copy, Clone, Encode, Decode, Eq, PartialEq, TypeInfo, RuntimeDebug)] +#[derive(Copy, Clone, Encode, Decode, Eq, PartialEq, TypeInfo, RuntimeDebug, PalletError)] pub enum BlsError { InvalidSignature, InvalidPublicKey, @@ -25,7 +25,7 @@ pub fn fast_aggregate_verify_legacy( signature: &Signature, ) -> Result<(), BlsError> { let agg_sig = prepare_aggregate_signature(signature)?; - let agg_key = prepare_aggregate_pubkey(&pubkeys)?; + let agg_key = prepare_aggregate_pubkey(pubkeys)?; // major bottleneck which consumes more than 90% of weight in the entire call fast_aggregate_verify_pre_aggregated(agg_sig, agg_key, message) } @@ -38,7 +38,7 @@ pub fn fast_aggregate_verify( signature: &Signature, ) -> Result<(), BlsError> { let agg_sig = prepare_aggregate_signature(signature)?; - let agg_key = prepare_aggregate_pubkey_from_absent(aggregate_pubkey, &absent_pubkeys)?; + let agg_key = prepare_aggregate_pubkey_from_absent(aggregate_pubkey, absent_pubkeys)?; fast_aggregate_verify_pre_aggregated(agg_sig, agg_key, message) } @@ -48,17 +48,17 @@ pub fn prepare_milagro_pubkey(pubkey: &PublicKey) -> Result) -> Result, BlsError> { +pub fn prepare_g1_pubkeys(pubkeys: &[PublicKey]) -> Result, BlsError> { pubkeys .iter() // Deserialize one public key from compressed bytes - .map(|pubkey| prepare_milagro_pubkey(pubkey)) + .map(prepare_milagro_pubkey) .collect::, BlsError>>() } // Prepare for G1 AggregatePublicKey pub fn prepare_aggregate_pubkey( - pubkeys: &Vec, + pubkeys: &[PublicKeyPrepared], ) -> Result { let agg_pub_key = AggregatePublicKey::into_aggregate(pubkeys).map_err(|_| BlsError::InvalidPublicKey)?; diff --git a/parachain/primitives/beacon/src/lib.rs b/parachain/primitives/beacon/src/lib.rs index fa41aee55f..205185d620 100644 --- a/parachain/primitives/beacon/src/lib.rs +++ b/parachain/primitives/beacon/src/lib.rs @@ -14,8 +14,8 @@ mod serde_utils; pub use types::{ BeaconHeader, CompactExecutionHeader, ExecutionHeaderState, ExecutionPayloadHeader, - FinalizedHeaderState, Fork, ForkData, ForkVersion, ForkVersions, PreparedSyncCommittee, - PublicKey, Signature, SigningData, SyncAggregate, SyncCommittee, + FinalizedHeaderState, Fork, ForkData, ForkVersion, ForkVersions, PublicKey, Signature, + SigningData, SyncAggregate, SyncCommittee, SyncCommitteePrepared, }; pub use updates::{FinalizedHeaderUpdate, HeaderUpdate, InitialUpdate, SyncCommitteeUpdate}; diff --git a/parachain/primitives/beacon/src/types.rs b/parachain/primitives/beacon/src/types.rs index c33af41fe5..47d8e8e3f1 100644 --- a/parachain/primitives/beacon/src/types.rs +++ b/parachain/primitives/beacon/src/types.rs @@ -1,8 +1,8 @@ use codec::{Decode, Encode, MaxEncodedLen}; -use frame_support::{traits::Get, CloneNoBound, PartialEqNoBound, RuntimeDebugNoBound}; +use frame_support::{CloneNoBound, PartialEqNoBound, RuntimeDebugNoBound}; use scale_info::TypeInfo; use sp_core::{H160, H256, U256}; -use sp_runtime::{BoundedVec, RuntimeDebug}; +use sp_runtime::RuntimeDebug; use sp_std::prelude::*; use crate::config::{PUBKEY_SIZE, SIGNATURE_SIZE}; @@ -156,7 +156,6 @@ impl SigningData { derive(Serialize, Deserialize), serde(deny_unknown_fields, bound(serialize = ""), bound(deserialize = "")) )] -#[scale_info(skip_type_params(SyncCommitteeSize))] #[codec(mel_bound())] pub struct SyncCommittee { #[cfg_attr(feature = "std", serde(with = "crate::serde_utils::arrays"))] @@ -181,23 +180,28 @@ impl SyncCommittee { /// Prepared G1 public key of sync committee as it is stored in the runtime storage. #[derive(Clone, PartialEq, Eq, Encode, Decode, TypeInfo, MaxEncodedLen)] -#[scale_info(skip_type_params(MaxCommitteeSize))] -pub struct PreparedSyncCommittee> { - pub pubkeys: BoundedVec, +pub struct SyncCommitteePrepared { + pub pubkeys: [PublicKeyPrepared; COMMITTEE_SIZE], pub aggregate_pubkey: PublicKeyPrepared, } -impl> - TryFrom<&SyncCommittee> for PreparedSyncCommittee +impl TryFrom<&SyncCommittee> + for SyncCommitteePrepared { type Error = BlsError; fn try_from(sync_committee: &SyncCommittee) -> Result { let g1_pubkeys = prepare_g1_pubkeys(&sync_committee.pubkeys.to_vec())?; - let pubkeys = BoundedVec::::try_from(g1_pubkeys) - .map_err(|_| BlsError::InvalidPublicKey)?; + let pubkeys: [PublicKeyPrepared; COMMITTEE_SIZE] = + g1_pubkeys.try_into().unwrap_or_else(|v: Vec| { + panic!( + "Expected Vec length of pubkeys as {} but actually it was {}", + COMMITTEE_SIZE, + v.len() + ) + }); let aggregate_pubkey = prepare_milagro_pubkey(&sync_committee.aggregate_pubkey)?; - Ok(PreparedSyncCommittee:: { pubkeys, aggregate_pubkey }) + Ok(SyncCommitteePrepared:: { pubkeys, aggregate_pubkey }) } } From b63b1ac1b36ebd7c48524df39deaf7b6614317d1 Mon Sep 17 00:00:00 2001 From: ron Date: Tue, 2 May 2023 22:06:17 +0800 Subject: [PATCH 04/16] Fix parachain test in CI --- .github/workflows/parachain.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/parachain.yml b/.github/workflows/parachain.yml index 0226cdc4b0..89723d2765 100644 --- a/.github/workflows/parachain.yml +++ b/.github/workflows/parachain.yml @@ -99,7 +99,9 @@ jobs: command: tarpaulin args: >- --manifest-path parachain/Cargo.toml - --verbose --workspace + --release + --verbose + --workspace --features runtime-benchmarks --avoid-cfg-tarpaulin --coveralls ${{ secrets.COVERALLS_REPO_TOKEN }} From 22274fad4e604152a347fc03cfb9eefea28fbc6b Mon Sep 17 00:00:00 2001 From: ron Date: Wed, 3 May 2023 10:25:23 +0800 Subject: [PATCH 05/16] Revert to use BoundedVec for SyncCommitteePrepared --- .github/workflows/parachain.yml | 3 +-- .../src/benchmarking/util.rs | 8 +++--- .../pallets/ethereum-beacon-client/src/lib.rs | 3 ++- parachain/primitives/beacon/src/types.rs | 25 ++++++++----------- 4 files changed, 17 insertions(+), 22 deletions(-) diff --git a/.github/workflows/parachain.yml b/.github/workflows/parachain.yml index 89723d2765..70fe5b9bc8 100644 --- a/.github/workflows/parachain.yml +++ b/.github/workflows/parachain.yml @@ -99,8 +99,7 @@ jobs: command: tarpaulin args: >- --manifest-path parachain/Cargo.toml - --release - --verbose + --verbose --workspace --features runtime-benchmarks --avoid-cfg-tarpaulin diff --git a/parachain/pallets/ethereum-beacon-client/src/benchmarking/util.rs b/parachain/pallets/ethereum-beacon-client/src/benchmarking/util.rs index eb4df6f44e..30d85a9683 100644 --- a/parachain/pallets/ethereum-beacon-client/src/benchmarking/util.rs +++ b/parachain/pallets/ethereum-beacon-client/src/benchmarking/util.rs @@ -1,9 +1,9 @@ use crate::{ decompress_sync_committee_bits, Config, LatestSyncCommitteePeriod, - Pallet as EthereumBeaconClient, SyncCommitteeUpdate, SyncCommittees, ValidatorsRoot, Vec, - SYNC_COMMITTEE_SIZE, + Pallet as EthereumBeaconClient, SyncCommitteePrepared, SyncCommitteeUpdate, SyncCommittees, + ValidatorsRoot, Vec, }; -use primitives::{PublicKeyPrepared, SyncCommitteePrepared}; +use primitives::PublicKeyPrepared; use sp_core::H256; use super::{initial_sync, sync_committee_update}; @@ -31,7 +31,7 @@ pub fn initialize_sync_committee() -> Result( update: &SyncCommitteeUpdate, -) -> Result, &'static str> { +) -> Result { let current_period = EthereumBeaconClient::::compute_current_sync_period(update.attested_header.slot); let sync_committee = SyncCommittees::::get(current_period).ok_or("no sync committee")?; diff --git a/parachain/pallets/ethereum-beacon-client/src/lib.rs b/parachain/pallets/ethereum-beacon-client/src/lib.rs index bcae5c2d55..779fbc25f4 100644 --- a/parachain/pallets/ethereum-beacon-client/src/lib.rs +++ b/parachain/pallets/ethereum-beacon-client/src/lib.rs @@ -54,7 +54,8 @@ pub type SyncCommitteeUpdate = pub type FinalizedHeaderUpdate = primitives::FinalizedHeaderUpdate; pub type SyncCommittee = primitives::SyncCommittee; -pub type SyncCommitteePrepared = primitives::SyncCommitteePrepared; +pub type SyncCommitteePrepared = + primitives::SyncCommitteePrepared>; fn decompress_sync_committee_bits( input: [u8; SYNC_COMMITTEE_BITS_SIZE], diff --git a/parachain/primitives/beacon/src/types.rs b/parachain/primitives/beacon/src/types.rs index 47d8e8e3f1..8b734e3e75 100644 --- a/parachain/primitives/beacon/src/types.rs +++ b/parachain/primitives/beacon/src/types.rs @@ -1,8 +1,8 @@ use codec::{Decode, Encode, MaxEncodedLen}; -use frame_support::{CloneNoBound, PartialEqNoBound, RuntimeDebugNoBound}; +use frame_support::{traits::Get, CloneNoBound, PartialEqNoBound, RuntimeDebugNoBound}; use scale_info::TypeInfo; use sp_core::{H160, H256, U256}; -use sp_runtime::RuntimeDebug; +use sp_runtime::{BoundedVec, RuntimeDebug}; use sp_std::prelude::*; use crate::config::{PUBKEY_SIZE, SIGNATURE_SIZE}; @@ -180,28 +180,23 @@ impl SyncCommittee { /// Prepared G1 public key of sync committee as it is stored in the runtime storage. #[derive(Clone, PartialEq, Eq, Encode, Decode, TypeInfo, MaxEncodedLen)] -pub struct SyncCommitteePrepared { - pub pubkeys: [PublicKeyPrepared; COMMITTEE_SIZE], +#[scale_info(skip_type_params(MaxCommitteeSize))] +pub struct SyncCommitteePrepared> { + pub pubkeys: BoundedVec, pub aggregate_pubkey: PublicKeyPrepared, } -impl TryFrom<&SyncCommittee> - for SyncCommitteePrepared +impl> + TryFrom<&SyncCommittee> for SyncCommitteePrepared { type Error = BlsError; fn try_from(sync_committee: &SyncCommittee) -> Result { let g1_pubkeys = prepare_g1_pubkeys(&sync_committee.pubkeys.to_vec())?; - let pubkeys: [PublicKeyPrepared; COMMITTEE_SIZE] = - g1_pubkeys.try_into().unwrap_or_else(|v: Vec| { - panic!( - "Expected Vec length of pubkeys as {} but actually it was {}", - COMMITTEE_SIZE, - v.len() - ) - }); + let pubkeys = BoundedVec::::try_from(g1_pubkeys) + .map_err(|_| BlsError::InvalidPublicKey)?; let aggregate_pubkey = prepare_milagro_pubkey(&sync_committee.aggregate_pubkey)?; - Ok(SyncCommitteePrepared:: { pubkeys, aggregate_pubkey }) + Ok(SyncCommitteePrepared:: { pubkeys, aggregate_pubkey }) } } From 2ef76013524305f742247b34b62b680835674164 Mon Sep 17 00:00:00 2001 From: ron Date: Wed, 3 May 2023 10:36:18 +0800 Subject: [PATCH 06/16] Use DispatchError --- parachain/pallets/ethereum-beacon-client/src/lib.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/parachain/pallets/ethereum-beacon-client/src/lib.rs b/parachain/pallets/ethereum-beacon-client/src/lib.rs index 779fbc25f4..89fa8f1296 100644 --- a/parachain/pallets/ethereum-beacon-client/src/lib.rs +++ b/parachain/pallets/ethereum-beacon-client/src/lib.rs @@ -711,7 +711,7 @@ pub mod pallet { pub(super) fn compute_signing_root( beacon_header: BeaconHeader, domain: H256, - ) -> Result> { + ) -> Result { let beacon_header_root = beacon_header .hash_tree_root() .map_err(|_| Error::::HeaderHashTreeRootFailed)?; @@ -870,7 +870,7 @@ pub mod pallet { domain_type: Vec, fork_version: ForkVersion, genesis_validators_root: H256, - ) -> Result> { + ) -> Result { let fork_data_root = Self::compute_fork_data_root(fork_version, genesis_validators_root)?; @@ -884,7 +884,7 @@ pub mod pallet { fn compute_fork_data_root( current_version: ForkVersion, genesis_validators_root: H256, - ) -> Result> { + ) -> Result { let hash_root = ForkData { current_version, genesis_validators_root: genesis_validators_root.into(), @@ -909,7 +909,7 @@ pub mod pallet { pub(super) fn sync_committee_for_period( period: u64, - ) -> Result> { + ) -> Result { let pub_keys = >::get(period).ok_or(Error::::SyncCommitteeMissing)?; Ok(pub_keys) @@ -996,7 +996,7 @@ pub mod pallet { header: BeaconHeader, validators_root: H256, signature_slot: u64, - ) -> Result> { + ) -> Result { let fork_version = Self::compute_fork_version(Self::compute_epoch_at_slot( signature_slot, config::SLOTS_PER_EPOCH, From 2051c411dd500ad89898a3906237eee55a841f5e Mon Sep 17 00:00:00 2001 From: Vincent Geddes Date: Wed, 3 May 2023 13:43:25 +0200 Subject: [PATCH 07/16] Revert "Revert to use BoundedVec for SyncCommitteePrepared" This reverts commit 22274fad4e604152a347fc03cfb9eefea28fbc6b. --- .github/workflows/parachain.yml | 3 ++- .../src/benchmarking/util.rs | 8 +++--- .../pallets/ethereum-beacon-client/src/lib.rs | 3 +-- parachain/primitives/beacon/src/types.rs | 25 +++++++++++-------- 4 files changed, 22 insertions(+), 17 deletions(-) diff --git a/.github/workflows/parachain.yml b/.github/workflows/parachain.yml index 70fe5b9bc8..89723d2765 100644 --- a/.github/workflows/parachain.yml +++ b/.github/workflows/parachain.yml @@ -99,7 +99,8 @@ jobs: command: tarpaulin args: >- --manifest-path parachain/Cargo.toml - --verbose + --release + --verbose --workspace --features runtime-benchmarks --avoid-cfg-tarpaulin diff --git a/parachain/pallets/ethereum-beacon-client/src/benchmarking/util.rs b/parachain/pallets/ethereum-beacon-client/src/benchmarking/util.rs index 30d85a9683..eb4df6f44e 100644 --- a/parachain/pallets/ethereum-beacon-client/src/benchmarking/util.rs +++ b/parachain/pallets/ethereum-beacon-client/src/benchmarking/util.rs @@ -1,9 +1,9 @@ use crate::{ decompress_sync_committee_bits, Config, LatestSyncCommitteePeriod, - Pallet as EthereumBeaconClient, SyncCommitteePrepared, SyncCommitteeUpdate, SyncCommittees, - ValidatorsRoot, Vec, + Pallet as EthereumBeaconClient, SyncCommitteeUpdate, SyncCommittees, ValidatorsRoot, Vec, + SYNC_COMMITTEE_SIZE, }; -use primitives::PublicKeyPrepared; +use primitives::{PublicKeyPrepared, SyncCommitteePrepared}; use sp_core::H256; use super::{initial_sync, sync_committee_update}; @@ -31,7 +31,7 @@ pub fn initialize_sync_committee() -> Result( update: &SyncCommitteeUpdate, -) -> Result { +) -> Result, &'static str> { let current_period = EthereumBeaconClient::::compute_current_sync_period(update.attested_header.slot); let sync_committee = SyncCommittees::::get(current_period).ok_or("no sync committee")?; diff --git a/parachain/pallets/ethereum-beacon-client/src/lib.rs b/parachain/pallets/ethereum-beacon-client/src/lib.rs index 89fa8f1296..ca11f54a59 100644 --- a/parachain/pallets/ethereum-beacon-client/src/lib.rs +++ b/parachain/pallets/ethereum-beacon-client/src/lib.rs @@ -54,8 +54,7 @@ pub type SyncCommitteeUpdate = pub type FinalizedHeaderUpdate = primitives::FinalizedHeaderUpdate; pub type SyncCommittee = primitives::SyncCommittee; -pub type SyncCommitteePrepared = - primitives::SyncCommitteePrepared>; +pub type SyncCommitteePrepared = primitives::SyncCommitteePrepared; fn decompress_sync_committee_bits( input: [u8; SYNC_COMMITTEE_BITS_SIZE], diff --git a/parachain/primitives/beacon/src/types.rs b/parachain/primitives/beacon/src/types.rs index 8b734e3e75..47d8e8e3f1 100644 --- a/parachain/primitives/beacon/src/types.rs +++ b/parachain/primitives/beacon/src/types.rs @@ -1,8 +1,8 @@ use codec::{Decode, Encode, MaxEncodedLen}; -use frame_support::{traits::Get, CloneNoBound, PartialEqNoBound, RuntimeDebugNoBound}; +use frame_support::{CloneNoBound, PartialEqNoBound, RuntimeDebugNoBound}; use scale_info::TypeInfo; use sp_core::{H160, H256, U256}; -use sp_runtime::{BoundedVec, RuntimeDebug}; +use sp_runtime::RuntimeDebug; use sp_std::prelude::*; use crate::config::{PUBKEY_SIZE, SIGNATURE_SIZE}; @@ -180,23 +180,28 @@ impl SyncCommittee { /// Prepared G1 public key of sync committee as it is stored in the runtime storage. #[derive(Clone, PartialEq, Eq, Encode, Decode, TypeInfo, MaxEncodedLen)] -#[scale_info(skip_type_params(MaxCommitteeSize))] -pub struct SyncCommitteePrepared> { - pub pubkeys: BoundedVec, +pub struct SyncCommitteePrepared { + pub pubkeys: [PublicKeyPrepared; COMMITTEE_SIZE], pub aggregate_pubkey: PublicKeyPrepared, } -impl> - TryFrom<&SyncCommittee> for SyncCommitteePrepared +impl TryFrom<&SyncCommittee> + for SyncCommitteePrepared { type Error = BlsError; fn try_from(sync_committee: &SyncCommittee) -> Result { let g1_pubkeys = prepare_g1_pubkeys(&sync_committee.pubkeys.to_vec())?; - let pubkeys = BoundedVec::::try_from(g1_pubkeys) - .map_err(|_| BlsError::InvalidPublicKey)?; + let pubkeys: [PublicKeyPrepared; COMMITTEE_SIZE] = + g1_pubkeys.try_into().unwrap_or_else(|v: Vec| { + panic!( + "Expected Vec length of pubkeys as {} but actually it was {}", + COMMITTEE_SIZE, + v.len() + ) + }); let aggregate_pubkey = prepare_milagro_pubkey(&sync_committee.aggregate_pubkey)?; - Ok(SyncCommitteePrepared:: { pubkeys, aggregate_pubkey }) + Ok(SyncCommitteePrepared:: { pubkeys, aggregate_pubkey }) } } From dd16453caa5a34c0a41d6fc3484086af2ddf8897 Mon Sep 17 00:00:00 2001 From: ron Date: Wed, 3 May 2023 20:54:35 +0800 Subject: [PATCH 08/16] Revert "Revert to use BoundedVec for SyncCommitteePrepared" This reverts commit 22274fad4e604152a347fc03cfb9eefea28fbc6b. --- .github/workflows/parachain.yml | 3 ++- .../src/benchmarking/util.rs | 8 +++--- .../pallets/ethereum-beacon-client/src/lib.rs | 3 +-- parachain/primitives/beacon/src/types.rs | 25 +++++++++++-------- 4 files changed, 22 insertions(+), 17 deletions(-) diff --git a/.github/workflows/parachain.yml b/.github/workflows/parachain.yml index 70fe5b9bc8..89723d2765 100644 --- a/.github/workflows/parachain.yml +++ b/.github/workflows/parachain.yml @@ -99,7 +99,8 @@ jobs: command: tarpaulin args: >- --manifest-path parachain/Cargo.toml - --verbose + --release + --verbose --workspace --features runtime-benchmarks --avoid-cfg-tarpaulin diff --git a/parachain/pallets/ethereum-beacon-client/src/benchmarking/util.rs b/parachain/pallets/ethereum-beacon-client/src/benchmarking/util.rs index 30d85a9683..eb4df6f44e 100644 --- a/parachain/pallets/ethereum-beacon-client/src/benchmarking/util.rs +++ b/parachain/pallets/ethereum-beacon-client/src/benchmarking/util.rs @@ -1,9 +1,9 @@ use crate::{ decompress_sync_committee_bits, Config, LatestSyncCommitteePeriod, - Pallet as EthereumBeaconClient, SyncCommitteePrepared, SyncCommitteeUpdate, SyncCommittees, - ValidatorsRoot, Vec, + Pallet as EthereumBeaconClient, SyncCommitteeUpdate, SyncCommittees, ValidatorsRoot, Vec, + SYNC_COMMITTEE_SIZE, }; -use primitives::PublicKeyPrepared; +use primitives::{PublicKeyPrepared, SyncCommitteePrepared}; use sp_core::H256; use super::{initial_sync, sync_committee_update}; @@ -31,7 +31,7 @@ pub fn initialize_sync_committee() -> Result( update: &SyncCommitteeUpdate, -) -> Result { +) -> Result, &'static str> { let current_period = EthereumBeaconClient::::compute_current_sync_period(update.attested_header.slot); let sync_committee = SyncCommittees::::get(current_period).ok_or("no sync committee")?; diff --git a/parachain/pallets/ethereum-beacon-client/src/lib.rs b/parachain/pallets/ethereum-beacon-client/src/lib.rs index 89fa8f1296..ca11f54a59 100644 --- a/parachain/pallets/ethereum-beacon-client/src/lib.rs +++ b/parachain/pallets/ethereum-beacon-client/src/lib.rs @@ -54,8 +54,7 @@ pub type SyncCommitteeUpdate = pub type FinalizedHeaderUpdate = primitives::FinalizedHeaderUpdate; pub type SyncCommittee = primitives::SyncCommittee; -pub type SyncCommitteePrepared = - primitives::SyncCommitteePrepared>; +pub type SyncCommitteePrepared = primitives::SyncCommitteePrepared; fn decompress_sync_committee_bits( input: [u8; SYNC_COMMITTEE_BITS_SIZE], diff --git a/parachain/primitives/beacon/src/types.rs b/parachain/primitives/beacon/src/types.rs index 8b734e3e75..47d8e8e3f1 100644 --- a/parachain/primitives/beacon/src/types.rs +++ b/parachain/primitives/beacon/src/types.rs @@ -1,8 +1,8 @@ use codec::{Decode, Encode, MaxEncodedLen}; -use frame_support::{traits::Get, CloneNoBound, PartialEqNoBound, RuntimeDebugNoBound}; +use frame_support::{CloneNoBound, PartialEqNoBound, RuntimeDebugNoBound}; use scale_info::TypeInfo; use sp_core::{H160, H256, U256}; -use sp_runtime::{BoundedVec, RuntimeDebug}; +use sp_runtime::RuntimeDebug; use sp_std::prelude::*; use crate::config::{PUBKEY_SIZE, SIGNATURE_SIZE}; @@ -180,23 +180,28 @@ impl SyncCommittee { /// Prepared G1 public key of sync committee as it is stored in the runtime storage. #[derive(Clone, PartialEq, Eq, Encode, Decode, TypeInfo, MaxEncodedLen)] -#[scale_info(skip_type_params(MaxCommitteeSize))] -pub struct SyncCommitteePrepared> { - pub pubkeys: BoundedVec, +pub struct SyncCommitteePrepared { + pub pubkeys: [PublicKeyPrepared; COMMITTEE_SIZE], pub aggregate_pubkey: PublicKeyPrepared, } -impl> - TryFrom<&SyncCommittee> for SyncCommitteePrepared +impl TryFrom<&SyncCommittee> + for SyncCommitteePrepared { type Error = BlsError; fn try_from(sync_committee: &SyncCommittee) -> Result { let g1_pubkeys = prepare_g1_pubkeys(&sync_committee.pubkeys.to_vec())?; - let pubkeys = BoundedVec::::try_from(g1_pubkeys) - .map_err(|_| BlsError::InvalidPublicKey)?; + let pubkeys: [PublicKeyPrepared; COMMITTEE_SIZE] = + g1_pubkeys.try_into().unwrap_or_else(|v: Vec| { + panic!( + "Expected Vec length of pubkeys as {} but actually it was {}", + COMMITTEE_SIZE, + v.len() + ) + }); let aggregate_pubkey = prepare_milagro_pubkey(&sync_committee.aggregate_pubkey)?; - Ok(SyncCommitteePrepared:: { pubkeys, aggregate_pubkey }) + Ok(SyncCommitteePrepared:: { pubkeys, aggregate_pubkey }) } } From af53adc5656068c78f9c58729c4589618e0a067d Mon Sep 17 00:00:00 2001 From: Vincent Geddes Date: Wed, 3 May 2023 21:07:39 +0200 Subject: [PATCH 09/16] optimize things --- .../src/benchmarking/mod.rs | 5 +++-- .../src/benchmarking/util.rs | 2 +- .../pallets/ethereum-beacon-client/src/lib.rs | 11 +++++------ .../ethereum-beacon-client/src/tests_mainnet.rs | 9 ++++----- parachain/primitives/beacon/src/types.rs | 17 ++++++----------- 5 files changed, 19 insertions(+), 25 deletions(-) diff --git a/parachain/pallets/ethereum-beacon-client/src/benchmarking/mod.rs b/parachain/pallets/ethereum-beacon-client/src/benchmarking/mod.rs index 10fb3790cf..caeaa8f9b5 100644 --- a/parachain/pallets/ethereum-beacon-client/src/benchmarking/mod.rs +++ b/parachain/pallets/ethereum-beacon-client/src/benchmarking/mod.rs @@ -7,6 +7,7 @@ use frame_system::RawOrigin; // For benchmark focus on main spec only mod data_mainnet; use data_mainnet::*; + mod util; use primitives::{ fast_aggregate_verify, fast_aggregate_verify_legacy, prepare_aggregate_pubkey, @@ -30,7 +31,7 @@ benchmarks! { let initial_sync_data = initial_sync(); - EthereumBeaconClient::::initial_sync(initial_sync_data.clone())?; + EthereumBeaconClient::::initial_sync(&initial_sync_data)?; let finalized_header_update = finalized_header_update(); @@ -59,7 +60,7 @@ benchmarks! { let initial_sync_data = initial_sync(); - EthereumBeaconClient::::initial_sync(initial_sync_data.clone())?; + EthereumBeaconClient::::initial_sync(&initial_sync_data)?; let header_update = header_update(); diff --git a/parachain/pallets/ethereum-beacon-client/src/benchmarking/util.rs b/parachain/pallets/ethereum-beacon-client/src/benchmarking/util.rs index eb4df6f44e..1e044540e6 100644 --- a/parachain/pallets/ethereum-beacon-client/src/benchmarking/util.rs +++ b/parachain/pallets/ethereum-beacon-client/src/benchmarking/util.rs @@ -11,7 +11,7 @@ use super::{initial_sync, sync_committee_update}; pub fn initialize_sync_committee() -> Result { let initial_sync_data = initial_sync(); - EthereumBeaconClient::::initial_sync(initial_sync_data.clone())?; + EthereumBeaconClient::::initial_sync(&initial_sync_data)?; let sync_committee_update = sync_committee_update(); diff --git a/parachain/pallets/ethereum-beacon-client/src/lib.rs b/parachain/pallets/ethereum-beacon-client/src/lib.rs index ca11f54a59..a98c005ef0 100644 --- a/parachain/pallets/ethereum-beacon-client/src/lib.rs +++ b/parachain/pallets/ethereum-beacon-client/src/lib.rs @@ -11,11 +11,12 @@ mod tests; #[cfg(test)] #[cfg(not(feature = "minimal"))] mod tests_mainnet; + #[cfg(test)] #[cfg(feature = "minimal")] mod tests_minimal; -#[cfg(feature = "runtime-benchmarks")] +//// [cfg(feature = "runtime-benchmarks")] mod benchmarking; pub use weights::WeightInfo; @@ -200,7 +201,7 @@ pub mod pallet { ); if let Some(initial_sync) = self.initial_sync.clone() { - Pallet::::initial_sync(initial_sync).unwrap(); + Pallet::::initial_sync(&initial_sync).unwrap(); } } } @@ -909,9 +910,7 @@ pub mod pallet { pub(super) fn sync_committee_for_period( period: u64, ) -> Result { - let pub_keys = - >::get(period).ok_or(Error::::SyncCommitteeMissing)?; - Ok(pub_keys) + >::get(period).ok_or(Error::::SyncCommitteeMissing.into()) } pub(super) fn compute_fork_version(epoch: u64) -> ForkVersion { @@ -930,7 +929,7 @@ pub mod pallet { fork_versions.genesis.version } - pub(super) fn initial_sync(update: InitialUpdate) -> Result<(), &'static str> { + pub(super) fn initial_sync(update: &InitialUpdate) -> Result<(), &'static str> { log::info!( target: "ethereum-beacon-client", "💫 Received initial sync, starting processing.", diff --git a/parachain/pallets/ethereum-beacon-client/src/tests_mainnet.rs b/parachain/pallets/ethereum-beacon-client/src/tests_mainnet.rs index 51c7d159b3..71d7ed6469 100644 --- a/parachain/pallets/ethereum-beacon-client/src/tests_mainnet.rs +++ b/parachain/pallets/ethereum-beacon-client/src/tests_mainnet.rs @@ -18,7 +18,7 @@ fn it_syncs_from_an_initial_checkpoint() { let initial_sync = get_initial_sync::(); new_tester::().execute_with(|| { - assert_ok!(mock_mainnet::EthereumBeaconClient::initial_sync(initial_sync.clone())); + assert_ok!(mock_mainnet::EthereumBeaconClient::initial_sync(&initial_sync)); let block_root: H256 = initial_sync.header.hash_tree_root().unwrap(); @@ -95,8 +95,7 @@ fn it_processes_a_finalized_header_update() { #[test] fn it_errors_when_weak_subjectivity_period_exceeded_for_a_finalized_header_update() { let update = get_finalized_header_update::(); - let current_sync_committee = - get_initial_sync::<{ SYNC_COMMITTEE_SIZE }>().current_sync_committee; + let current_sync_committee = get_initial_sync::().current_sync_committee; let current_period = mock_mainnet::EthereumBeaconClient::compute_current_sync_period( update.attested_header.slot, @@ -117,7 +116,7 @@ fn it_errors_when_weak_subjectivity_period_exceeded_for_a_finalized_header_updat import_time, beacon_slot: slot - 1, }); - ValidatorsRoot::::set(get_validators_root::<{ SYNC_COMMITTEE_SIZE }>()); + ValidatorsRoot::::set(get_validators_root::()); assert_err!( mock_mainnet::EthereumBeaconClient::import_finalized_header( @@ -147,7 +146,7 @@ fn it_processes_a_header_update() { current_period, ¤t_sync_committee, )); - ValidatorsRoot::::set(get_validators_root::<{ SYNC_COMMITTEE_SIZE }>()); + ValidatorsRoot::::set(get_validators_root::()); LatestFinalizedHeaderState::::set(FinalizedHeaderState { beacon_block_root: finalized_block_root, beacon_slot: finalized_slot, diff --git a/parachain/primitives/beacon/src/types.rs b/parachain/primitives/beacon/src/types.rs index 47d8e8e3f1..a269a60c74 100644 --- a/parachain/primitives/beacon/src/types.rs +++ b/parachain/primitives/beacon/src/types.rs @@ -191,17 +191,12 @@ impl TryFrom<&SyncCommittee> type Error = BlsError; fn try_from(sync_committee: &SyncCommittee) -> Result { - let g1_pubkeys = prepare_g1_pubkeys(&sync_committee.pubkeys.to_vec())?; - let pubkeys: [PublicKeyPrepared; COMMITTEE_SIZE] = - g1_pubkeys.try_into().unwrap_or_else(|v: Vec| { - panic!( - "Expected Vec length of pubkeys as {} but actually it was {}", - COMMITTEE_SIZE, - v.len() - ) - }); - let aggregate_pubkey = prepare_milagro_pubkey(&sync_committee.aggregate_pubkey)?; - Ok(SyncCommitteePrepared:: { pubkeys, aggregate_pubkey }) + let g1_pubkeys = prepare_g1_pubkeys(&sync_committee.pubkeys)?; + + Ok(SyncCommitteePrepared:: { + pubkeys: g1_pubkeys.try_into().unwrap_or_else(|_| panic!("checked statically; qed")), + aggregate_pubkey: prepare_milagro_pubkey(&sync_committee.aggregate_pubkey)?, + }) } } From 600c1b887678bb887febfcd289bbdbd2622923f8 Mon Sep 17 00:00:00 2001 From: ron Date: Thu, 4 May 2023 08:54:27 +0800 Subject: [PATCH 10/16] Update Milagro --- cumulus | 2 +- parachain/Cargo.lock | 4 ++-- parachain/primitives/beacon/Cargo.toml | 3 ++- parachain/primitives/beacon/src/types.rs | 8 +------- 4 files changed, 6 insertions(+), 11 deletions(-) diff --git a/cumulus b/cumulus index 262f554226..d45182d8fc 160000 --- a/cumulus +++ b/cumulus @@ -1 +1 @@ -Subproject commit 262f554226f9b6efa8f1ecb4770625d35ccb85c0 +Subproject commit d45182d8fcb681899bf30b0c89a9a5d1caa3d6d9 diff --git a/parachain/Cargo.lock b/parachain/Cargo.lock index 2c29f7289a..1d50fc99de 100644 --- a/parachain/Cargo.lock +++ b/parachain/Cargo.lock @@ -71,7 +71,7 @@ dependencies = [ [[package]] name = "amcl" version = "0.3.0" -source = "git+https://github.com/snowfork/milagro_bls?rev=b95ca5be05e3c6e5b865b7e1f4a768dfa97f27f8#b95ca5be05e3c6e5b865b7e1f4a768dfa97f27f8" +source = "git+https://github.com/snowfork/milagro_bls?rev=a6d66e4eb89015e352fb1c9f7b661ecdbb5b2176#a6d66e4eb89015e352fb1c9f7b661ecdbb5b2176" dependencies = [ "parity-scale-codec", "scale-info", @@ -2242,7 +2242,7 @@ dependencies = [ [[package]] name = "milagro_bls" version = "1.5.0" -source = "git+https://github.com/snowfork/milagro_bls?rev=b95ca5be05e3c6e5b865b7e1f4a768dfa97f27f8#b95ca5be05e3c6e5b865b7e1f4a768dfa97f27f8" +source = "git+https://github.com/snowfork/milagro_bls?rev=a6d66e4eb89015e352fb1c9f7b661ecdbb5b2176#a6d66e4eb89015e352fb1c9f7b661ecdbb5b2176" dependencies = [ "amcl", "hex", diff --git a/parachain/primitives/beacon/Cargo.toml b/parachain/primitives/beacon/Cargo.toml index 2645bc808c..be85bcb477 100644 --- a/parachain/primitives/beacon/Cargo.toml +++ b/parachain/primitives/beacon/Cargo.toml @@ -26,7 +26,8 @@ byte-slice-cast = { version = "1.2.1", default-features = false } snowbridge-ethereum = { path = "../../primitives/ethereum", default-features = false } static_assertions = { version = "1.1.0" } -milagro_bls = { git = "https://github.com/snowfork/milagro_bls", default-features = false, rev="b95ca5be05e3c6e5b865b7e1f4a768dfa97f27f8"} +# milagro_bls = { path = "../../../../milagro_bls", default-features = false } +milagro_bls = { git = "https://github.com/snowfork/milagro_bls", default-features = false, rev="a6d66e4eb89015e352fb1c9f7b661ecdbb5b2176"} [dev-dependencies] hex-literal = { version = "0.4.1" } diff --git a/parachain/primitives/beacon/src/types.rs b/parachain/primitives/beacon/src/types.rs index 47d8e8e3f1..462cf18a94 100644 --- a/parachain/primitives/beacon/src/types.rs +++ b/parachain/primitives/beacon/src/types.rs @@ -193,13 +193,7 @@ impl TryFrom<&SyncCommittee> fn try_from(sync_committee: &SyncCommittee) -> Result { let g1_pubkeys = prepare_g1_pubkeys(&sync_committee.pubkeys.to_vec())?; let pubkeys: [PublicKeyPrepared; COMMITTEE_SIZE] = - g1_pubkeys.try_into().unwrap_or_else(|v: Vec| { - panic!( - "Expected Vec length of pubkeys as {} but actually it was {}", - COMMITTEE_SIZE, - v.len() - ) - }); + g1_pubkeys.try_into().expect("checked statically; qed"); let aggregate_pubkey = prepare_milagro_pubkey(&sync_committee.aggregate_pubkey)?; Ok(SyncCommitteePrepared:: { pubkeys, aggregate_pubkey }) } From 3cf3151fccbe3d1ee5e451c7393aa1df4be7de48 Mon Sep 17 00:00:00 2001 From: ron Date: Thu, 4 May 2023 09:33:40 +0800 Subject: [PATCH 11/16] More refactoring --- cumulus | 2 +- parachain/Cargo.lock | 4 ++-- .../ethereum-beacon-client/src/benchmarking/mod.rs | 4 ++-- .../ethereum-beacon-client/src/benchmarking/util.rs | 2 +- parachain/pallets/ethereum-beacon-client/src/lib.rs | 10 ++++------ .../ethereum-beacon-client/src/tests_mainnet.rs | 2 +- .../ethereum-beacon-client/src/tests_minimal.rs | 8 ++++---- parachain/primitives/beacon/Cargo.toml | 2 +- parachain/primitives/beacon/src/types.rs | 4 ++-- 9 files changed, 18 insertions(+), 20 deletions(-) diff --git a/cumulus b/cumulus index 262f554226..d45182d8fc 160000 --- a/cumulus +++ b/cumulus @@ -1 +1 @@ -Subproject commit 262f554226f9b6efa8f1ecb4770625d35ccb85c0 +Subproject commit d45182d8fcb681899bf30b0c89a9a5d1caa3d6d9 diff --git a/parachain/Cargo.lock b/parachain/Cargo.lock index 2c29f7289a..1d50fc99de 100644 --- a/parachain/Cargo.lock +++ b/parachain/Cargo.lock @@ -71,7 +71,7 @@ dependencies = [ [[package]] name = "amcl" version = "0.3.0" -source = "git+https://github.com/snowfork/milagro_bls?rev=b95ca5be05e3c6e5b865b7e1f4a768dfa97f27f8#b95ca5be05e3c6e5b865b7e1f4a768dfa97f27f8" +source = "git+https://github.com/snowfork/milagro_bls?rev=a6d66e4eb89015e352fb1c9f7b661ecdbb5b2176#a6d66e4eb89015e352fb1c9f7b661ecdbb5b2176" dependencies = [ "parity-scale-codec", "scale-info", @@ -2242,7 +2242,7 @@ dependencies = [ [[package]] name = "milagro_bls" version = "1.5.0" -source = "git+https://github.com/snowfork/milagro_bls?rev=b95ca5be05e3c6e5b865b7e1f4a768dfa97f27f8#b95ca5be05e3c6e5b865b7e1f4a768dfa97f27f8" +source = "git+https://github.com/snowfork/milagro_bls?rev=a6d66e4eb89015e352fb1c9f7b661ecdbb5b2176#a6d66e4eb89015e352fb1c9f7b661ecdbb5b2176" dependencies = [ "amcl", "hex", diff --git a/parachain/pallets/ethereum-beacon-client/src/benchmarking/mod.rs b/parachain/pallets/ethereum-beacon-client/src/benchmarking/mod.rs index 10fb3790cf..49ae1495d2 100644 --- a/parachain/pallets/ethereum-beacon-client/src/benchmarking/mod.rs +++ b/parachain/pallets/ethereum-beacon-client/src/benchmarking/mod.rs @@ -30,7 +30,7 @@ benchmarks! { let initial_sync_data = initial_sync(); - EthereumBeaconClient::::initial_sync(initial_sync_data.clone())?; + EthereumBeaconClient::::initial_sync(&initial_sync_data)?; let finalized_header_update = finalized_header_update(); @@ -59,7 +59,7 @@ benchmarks! { let initial_sync_data = initial_sync(); - EthereumBeaconClient::::initial_sync(initial_sync_data.clone())?; + EthereumBeaconClient::::initial_sync(&initial_sync_data)?; let header_update = header_update(); diff --git a/parachain/pallets/ethereum-beacon-client/src/benchmarking/util.rs b/parachain/pallets/ethereum-beacon-client/src/benchmarking/util.rs index 30d85a9683..2e62cdfb3e 100644 --- a/parachain/pallets/ethereum-beacon-client/src/benchmarking/util.rs +++ b/parachain/pallets/ethereum-beacon-client/src/benchmarking/util.rs @@ -11,7 +11,7 @@ use super::{initial_sync, sync_committee_update}; pub fn initialize_sync_committee() -> Result { let initial_sync_data = initial_sync(); - EthereumBeaconClient::::initial_sync(initial_sync_data.clone())?; + EthereumBeaconClient::::initial_sync(&initial_sync_data)?; let sync_committee_update = sync_committee_update(); diff --git a/parachain/pallets/ethereum-beacon-client/src/lib.rs b/parachain/pallets/ethereum-beacon-client/src/lib.rs index 89fa8f1296..f8ee00287e 100644 --- a/parachain/pallets/ethereum-beacon-client/src/lib.rs +++ b/parachain/pallets/ethereum-beacon-client/src/lib.rs @@ -201,7 +201,7 @@ pub mod pallet { ); if let Some(initial_sync) = self.initial_sync.clone() { - Pallet::::initial_sync(initial_sync).unwrap(); + Pallet::::initial_sync(&initial_sync).unwrap(); } } } @@ -910,9 +910,7 @@ pub mod pallet { pub(super) fn sync_committee_for_period( period: u64, ) -> Result { - let pub_keys = - >::get(period).ok_or(Error::::SyncCommitteeMissing)?; - Ok(pub_keys) + >::get(period).ok_or(Error::::SyncCommitteeMissing.into()) } pub(super) fn compute_fork_version(epoch: u64) -> ForkVersion { @@ -931,13 +929,13 @@ pub mod pallet { fork_versions.genesis.version } - pub(super) fn initial_sync(update: InitialUpdate) -> Result<(), &'static str> { + pub(super) fn initial_sync(update: &InitialUpdate) -> Result<(), &'static str> { log::info!( target: "ethereum-beacon-client", "💫 Received initial sync, starting processing.", ); - if let Err(err) = Self::process_initial_sync(&update) { + if let Err(err) = Self::process_initial_sync(update) { log::error!( target: "ethereum-beacon-client", "Initial sync failed with error {:?}", diff --git a/parachain/pallets/ethereum-beacon-client/src/tests_mainnet.rs b/parachain/pallets/ethereum-beacon-client/src/tests_mainnet.rs index 51c7d159b3..5a731d786c 100644 --- a/parachain/pallets/ethereum-beacon-client/src/tests_mainnet.rs +++ b/parachain/pallets/ethereum-beacon-client/src/tests_mainnet.rs @@ -18,7 +18,7 @@ fn it_syncs_from_an_initial_checkpoint() { let initial_sync = get_initial_sync::(); new_tester::().execute_with(|| { - assert_ok!(mock_mainnet::EthereumBeaconClient::initial_sync(initial_sync.clone())); + assert_ok!(mock_mainnet::EthereumBeaconClient::initial_sync(&initial_sync)); let block_root: H256 = initial_sync.header.hash_tree_root().unwrap(); diff --git a/parachain/pallets/ethereum-beacon-client/src/tests_minimal.rs b/parachain/pallets/ethereum-beacon-client/src/tests_minimal.rs index eb41ccc0ea..c76cd15890 100644 --- a/parachain/pallets/ethereum-beacon-client/src/tests_minimal.rs +++ b/parachain/pallets/ethereum-beacon-client/src/tests_minimal.rs @@ -19,7 +19,7 @@ fn it_syncs_from_an_initial_checkpoint() { let initial_sync = get_initial_sync::(); new_tester::().execute_with(|| { - assert_ok!(mock_minimal::EthereumBeaconClient::initial_sync(initial_sync.clone())); + assert_ok!(mock_minimal::EthereumBeaconClient::initial_sync(&initial_sync)); let block_root: H256 = initial_sync.header.hash_tree_root().unwrap(); @@ -35,7 +35,7 @@ fn it_updates_a_committee_period_sync_update() { get_committee_sync_period_update::(); new_tester::().execute_with(|| { - assert_ok!(mock_minimal::EthereumBeaconClient::initial_sync(initial_sync.clone())); + assert_ok!(mock_minimal::EthereumBeaconClient::initial_sync(&initial_sync)); let current_period = mock_minimal::EthereumBeaconClient::compute_current_sync_period( update.attested_header.slot, @@ -65,7 +65,7 @@ fn it_updates_a_committee_period_sync_update_with_invalid_header() { get_committee_sync_period_update::(); new_tester::().execute_with(|| { - assert_ok!(mock_minimal::EthereumBeaconClient::initial_sync(initial_sync.clone())); + assert_ok!(mock_minimal::EthereumBeaconClient::initial_sync(&initial_sync)); // makes a invalid update with signature_slot should be more than attested_slot update.signature_slot = update.attested_header.slot; @@ -118,7 +118,7 @@ fn it_updates_a_invalid_committee_period_sync_update_with_duplicate_entry() { get_committee_sync_period_update::(); new_tester::().execute_with(|| { - assert_ok!(mock_minimal::EthereumBeaconClient::initial_sync(initial_sync.clone())); + assert_ok!(mock_minimal::EthereumBeaconClient::initial_sync(&initial_sync)); let current_period = mock_minimal::EthereumBeaconClient::compute_current_sync_period( update.attested_header.slot, diff --git a/parachain/primitives/beacon/Cargo.toml b/parachain/primitives/beacon/Cargo.toml index 2645bc808c..bf027e1812 100644 --- a/parachain/primitives/beacon/Cargo.toml +++ b/parachain/primitives/beacon/Cargo.toml @@ -26,7 +26,7 @@ byte-slice-cast = { version = "1.2.1", default-features = false } snowbridge-ethereum = { path = "../../primitives/ethereum", default-features = false } static_assertions = { version = "1.1.0" } -milagro_bls = { git = "https://github.com/snowfork/milagro_bls", default-features = false, rev="b95ca5be05e3c6e5b865b7e1f4a768dfa97f27f8"} +milagro_bls = { git = "https://github.com/snowfork/milagro_bls", default-features = false, rev="a6d66e4eb89015e352fb1c9f7b661ecdbb5b2176"} [dev-dependencies] hex-literal = { version = "0.4.1" } diff --git a/parachain/primitives/beacon/src/types.rs b/parachain/primitives/beacon/src/types.rs index 8b734e3e75..ccf4604adc 100644 --- a/parachain/primitives/beacon/src/types.rs +++ b/parachain/primitives/beacon/src/types.rs @@ -192,9 +192,9 @@ impl> type Error = BlsError; fn try_from(sync_committee: &SyncCommittee) -> Result { - let g1_pubkeys = prepare_g1_pubkeys(&sync_committee.pubkeys.to_vec())?; + let g1_pubkeys = prepare_g1_pubkeys(&sync_committee.pubkeys)?; let pubkeys = BoundedVec::::try_from(g1_pubkeys) - .map_err(|_| BlsError::InvalidPublicKey)?; + .expect("checked statically; qed"); let aggregate_pubkey = prepare_milagro_pubkey(&sync_committee.aggregate_pubkey)?; Ok(SyncCommitteePrepared:: { pubkeys, aggregate_pubkey }) } From 8c2791afa1bbe9589052406eb28d5513d74b66b2 Mon Sep 17 00:00:00 2001 From: ron Date: Thu, 4 May 2023 09:42:57 +0800 Subject: [PATCH 12/16] Uncomment benchmark --- parachain/pallets/ethereum-beacon-client/src/lib.rs | 2 +- parachain/primitives/beacon/src/types.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/parachain/pallets/ethereum-beacon-client/src/lib.rs b/parachain/pallets/ethereum-beacon-client/src/lib.rs index a98c005ef0..2274bc85d4 100644 --- a/parachain/pallets/ethereum-beacon-client/src/lib.rs +++ b/parachain/pallets/ethereum-beacon-client/src/lib.rs @@ -16,7 +16,7 @@ mod tests_mainnet; #[cfg(feature = "minimal")] mod tests_minimal; -//// [cfg(feature = "runtime-benchmarks")] +#[cfg(feature = "runtime-benchmarks")] mod benchmarking; pub use weights::WeightInfo; diff --git a/parachain/primitives/beacon/src/types.rs b/parachain/primitives/beacon/src/types.rs index a269a60c74..14594994d3 100644 --- a/parachain/primitives/beacon/src/types.rs +++ b/parachain/primitives/beacon/src/types.rs @@ -194,7 +194,7 @@ impl TryFrom<&SyncCommittee> let g1_pubkeys = prepare_g1_pubkeys(&sync_committee.pubkeys)?; Ok(SyncCommitteePrepared:: { - pubkeys: g1_pubkeys.try_into().unwrap_or_else(|_| panic!("checked statically; qed")), + pubkeys: g1_pubkeys.try_into().expect("checked statically; qed"), aggregate_pubkey: prepare_milagro_pubkey(&sync_committee.aggregate_pubkey)?, }) } From 0a50935f71d686cf97531b4bafb2c01aa7826744 Mon Sep 17 00:00:00 2001 From: ron Date: Thu, 4 May 2023 10:29:36 +0800 Subject: [PATCH 13/16] Pin cumulus branch --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index b408ff5487..016d5bf848 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,7 +1,7 @@ [submodule "cumulus"] path = cumulus url = https://github.com/Snowfork/cumulus - branch = snowbridge + branch = ron/cache-milagro-g1-pubkeys [submodule "core/packages/contracts/lib/forge-std"] path = core/packages/contracts/lib/forge-std url = https://github.com/foundry-rs/forge-std From 912de31bd6cbff60fa4550226b43f5f9f2b61e82 Mon Sep 17 00:00:00 2001 From: ron Date: Thu, 4 May 2023 18:06:10 +0800 Subject: [PATCH 14/16] Update rust toolchain & More polish --- .github/workflows/parachain.yml | 10 +++++----- .github/workflows/release.yml | 2 +- .../ethereum-beacon-client/src/tests.rs | 20 +++++++++---------- parachain/primitives/beacon/src/bls.rs | 12 ++++------- parachain/rust-toolchain.toml | 2 +- 5 files changed, 21 insertions(+), 25 deletions(-) diff --git a/.github/workflows/parachain.yml b/.github/workflows/parachain.yml index 89723d2765..aebf366742 100644 --- a/.github/workflows/parachain.yml +++ b/.github/workflows/parachain.yml @@ -40,13 +40,13 @@ jobs: - uses: actions-rs/toolchain@v1 with: profile: minimal - toolchain: nightly-2022-11-15 + toolchain: nightly-2023-04-22 target: wasm32-unknown-unknown - name: cargo check uses: actions-rs/cargo@v1 with: command: check - toolchain: nightly-2022-11-15 + toolchain: nightly-2023-04-22 args: >- --manifest-path parachain/Cargo.toml --workspace @@ -76,7 +76,7 @@ jobs: - uses: actions-rs/toolchain@v1 with: profile: minimal - toolchain: nightly-2022-11-15 + toolchain: nightly-2023-04-22 target: wasm32-unknown-unknown - name: test beacon client with minimal feature uses: actions-rs/cargo@v1 @@ -87,7 +87,7 @@ jobs: --verbose --package snowbridge-ethereum-beacon-client --features minimal - toolchain: nightly-2022-11-15 + toolchain: nightly-2023-04-22 - uses: actions-rs/install@v0.1.2 with: crate: cargo-tarpaulin @@ -105,4 +105,4 @@ jobs: --features runtime-benchmarks --avoid-cfg-tarpaulin --coveralls ${{ secrets.COVERALLS_REPO_TOKEN }} - toolchain: nightly-2022-11-15 + toolchain: nightly-2023-04-22 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9a8b1c91e1..599016c954 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -25,7 +25,7 @@ jobs: - uses: actions-rs/toolchain@v1 with: profile: minimal - toolchain: nightly-2022-11-15 + toolchain: nightly-2023-04-22 target: wasm32-unknown-unknown - name: build uses: actions-rs/cargo@v1 diff --git a/parachain/pallets/ethereum-beacon-client/src/tests.rs b/parachain/pallets/ethereum-beacon-client/src/tests.rs index 1221425599..62e4714126 100644 --- a/parachain/pallets/ethereum-beacon-client/src/tests.rs +++ b/parachain/pallets/ethereum-beacon-client/src/tests.rs @@ -6,11 +6,11 @@ use primitives::{ }; pub fn prepare_milagro_pubkeys() -> Result, &'static str> { - let pubkeys = vec![ - PublicKey(hex!("a73eb991aa22cdb794da6fcde55a427f0a4df5a4a70de23a988b5e5fc8c4d844f66d990273267a54dd21579b7ba6a086").into()), - PublicKey(hex!("b29043a7273d0a2dbc2b747dcf6a5eccbd7ccb44b2d72e985537b117929bc3fd3a99001481327788ad040b4077c47c0d").into()), - PublicKey(hex!("b928f3beb93519eecf0145da903b40a4c97dca00b21f12ac0df3be9116ef2ef27b2ae6bcd4c5bc2d54ef5a70627efcb7").into()), - PublicKey(hex!("9446407bcd8e5efe9f2ac0efbfa9e07d136e68b03c5ebc5bde43db3b94773de8605c30419eb2596513707e4e7448bb50").into()), + let pubkeys: Vec = vec![ + hex!("a73eb991aa22cdb794da6fcde55a427f0a4df5a4a70de23a988b5e5fc8c4d844f66d990273267a54dd21579b7ba6a086").into(), + hex!("b29043a7273d0a2dbc2b747dcf6a5eccbd7ccb44b2d72e985537b117929bc3fd3a99001481327788ad040b4077c47c0d").into(), + hex!("b928f3beb93519eecf0145da903b40a4c97dca00b21f12ac0df3be9116ef2ef27b2ae6bcd4c5bc2d54ef5a70627efcb7").into(), + hex!("9446407bcd8e5efe9f2ac0efbfa9e07d136e68b03c5ebc5bde43db3b94773de8605c30419eb2596513707e4e7448bb50").into(), ]; let milagro_pubkeys = prepare_g1_pubkeys(&pubkeys).unwrap(); Ok(milagro_pubkeys) @@ -222,11 +222,11 @@ pub fn test_bls_fast_aggregate_verify_minimal() { #[test] pub fn test_bls_fast_aggregate_verify_invalid_point() { new_tester::().execute_with(|| { - let pubkeys = vec![ - PublicKey(hex!("973eb991aa22cdb794da6fcde55a427f0a4df5a4a70de23a988b5e5fc8c4d844f66d990273267a54dd21579b7ba6a086").into()), - PublicKey(hex!("b29043a7273d0a2dbc2b747dcf6a5eccbd7ccb44b2d72e985537b117929bc3fd3a99001481327788ad040b4077c47c0d").into()), - PublicKey(hex!("b928f3beb93519eecf0145da903b40a4c97dca00b21f12ac0df3be9116ef2ef27b2ae6bcd4c5bc2d54ef5a70627efcb7").into()), - PublicKey(hex!("9446407bcd8e5efe9f2ac0efbfa9e07d136e68b03c5ebc5bde43db3b94773de8605c30419eb2596513707e4e7448bb50").into()), + let pubkeys: Vec = vec![ + hex!("973eb991aa22cdb794da6fcde55a427f0a4df5a4a70de23a988b5e5fc8c4d844f66d990273267a54dd21579b7ba6a086").into(), + hex!("b29043a7273d0a2dbc2b747dcf6a5eccbd7ccb44b2d72e985537b117929bc3fd3a99001481327788ad040b4077c47c0d").into(), + hex!("b928f3beb93519eecf0145da903b40a4c97dca00b21f12ac0df3be9116ef2ef27b2ae6bcd4c5bc2d54ef5a70627efcb7").into(), + hex!("9446407bcd8e5efe9f2ac0efbfa9e07d136e68b03c5ebc5bde43db3b94773de8605c30419eb2596513707e4e7448bb50").into(), ]; assert_err!(prepare_g1_pubkeys(&pubkeys), BlsError::InvalidPublicKey); }); diff --git a/parachain/primitives/beacon/src/bls.rs b/parachain/primitives/beacon/src/bls.rs index f25ab560c7..d09e30645d 100644 --- a/parachain/primitives/beacon/src/bls.rs +++ b/parachain/primitives/beacon/src/bls.rs @@ -8,7 +8,6 @@ pub use milagro_bls::{ use scale_info::TypeInfo; use sp_core::H256; use sp_runtime::RuntimeDebug; -use sp_std::prelude::*; #[derive(Copy, Clone, Encode, Decode, Eq, PartialEq, TypeInfo, RuntimeDebug, PalletError)] pub enum BlsError { @@ -60,9 +59,7 @@ pub fn prepare_g1_pubkeys(pubkeys: &[PublicKey]) -> Result Result { - let agg_pub_key = - AggregatePublicKey::into_aggregate(pubkeys).map_err(|_| BlsError::InvalidPublicKey)?; - Ok(agg_pub_key) + AggregatePublicKey::into_aggregate(pubkeys).map_err(|_| BlsError::InvalidPublicKey) } // Prepare for G1 AggregatePublicKey @@ -80,10 +77,9 @@ pub fn prepare_aggregate_pubkey_from_absent( // Prepare for G2 AggregateSignature, normally more expensive than G1 operation pub fn prepare_aggregate_signature(signature: &Signature) -> Result { - let sig = - SignaturePrepared::from_bytes(&signature.0).map_err(|_| BlsError::InvalidSignature)?; - let agg_sig = AggregateSignature::from_signature(&sig); - Ok(agg_sig) + Ok(AggregateSignature::from_signature( + &SignaturePrepared::from_bytes(&signature.0).map_err(|_| BlsError::InvalidSignature)?, + )) } // fast_aggregate_verify_pre_aggregated which is the most expensive call in beacon light client diff --git a/parachain/rust-toolchain.toml b/parachain/rust-toolchain.toml index 3a2fd35a96..8f31405e52 100644 --- a/parachain/rust-toolchain.toml +++ b/parachain/rust-toolchain.toml @@ -6,7 +6,7 @@ # - update `channel = "nightly-OLD_DATE"` below # - update nightly-OLD_DATE in .github/workflows/parachain.yml -channel = "nightly-2023-04-22" # 1.67.0 nightly for unstable features, matching polkadot v0.9.38 +channel = "nightly-2023-04-22" # 1.71.0 nightly for unstable features targets = [ "wasm32-unknown-unknown", ] From f990a4b86689a3f557d2a102f8bb33b296787b2a Mon Sep 17 00:00:00 2001 From: ron Date: Thu, 4 May 2023 19:44:20 +0800 Subject: [PATCH 15/16] Fix build --- parachain/primitives/beacon/src/bls.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/parachain/primitives/beacon/src/bls.rs b/parachain/primitives/beacon/src/bls.rs index d09e30645d..4612b82dba 100644 --- a/parachain/primitives/beacon/src/bls.rs +++ b/parachain/primitives/beacon/src/bls.rs @@ -8,6 +8,7 @@ pub use milagro_bls::{ use scale_info::TypeInfo; use sp_core::H256; use sp_runtime::RuntimeDebug; +use sp_std::prelude::*; #[derive(Copy, Clone, Encode, Decode, Eq, PartialEq, TypeInfo, RuntimeDebug, PalletError)] pub enum BlsError { From 21b3809df1639e8b8c8a264ba5f609dbd836434f Mon Sep 17 00:00:00 2001 From: ron Date: Thu, 4 May 2023 22:27:58 +0800 Subject: [PATCH 16/16] Update cumulus --- .gitmodules | 2 +- cumulus | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index 016d5bf848..b408ff5487 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,7 +1,7 @@ [submodule "cumulus"] path = cumulus url = https://github.com/Snowfork/cumulus - branch = ron/cache-milagro-g1-pubkeys + branch = snowbridge [submodule "core/packages/contracts/lib/forge-std"] path = core/packages/contracts/lib/forge-std url = https://github.com/foundry-rs/forge-std diff --git a/cumulus b/cumulus index d45182d8fc..84043ce642 160000 --- a/cumulus +++ b/cumulus @@ -1 +1 @@ -Subproject commit d45182d8fcb681899bf30b0c89a9a5d1caa3d6d9 +Subproject commit 84043ce642831105ef0384f9e2f19ef38f8e074d