Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cache milagro g1 pubkeys #811

Merged
merged 18 commits into from
May 4, 2023
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions .github/workflows/parachain.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -99,8 +99,10 @@ 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 }}
toolchain: nightly-2022-11-15
toolchain: nightly-2023-04-22
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
@@ -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
Expand Down
12 changes: 9 additions & 3 deletions parachain/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 1 addition & 4 deletions parachain/pallets/ethereum-beacon-client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
Expand All @@ -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"]
Expand All @@ -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",
Expand Down
57 changes: 31 additions & 26 deletions parachain/pallets/ethereum-beacon-client/src/benchmarking/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,12 @@ 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,
prepare_aggregate_signature,
};
use util::*;

benchmarks! {
Expand All @@ -18,24 +23,23 @@ benchmarks! {

}: sync_committee_period_update(RawOrigin::Signed(caller.clone()), sync_committee_update.clone())
verify {
assert!(<SyncCommittees<T>>::get(sync_committee_update.sync_committee_period+1).unwrap().pubkeys.len() > 0);
EthereumBeaconClient::<T>::sync_committee_for_period(sync_committee_update.sync_committee_period+1).unwrap();
}

import_finalized_header {
let caller: T::AccountId = whitelisted_caller();

let initial_sync_data = initial_sync();

EthereumBeaconClient::<T>::initial_sync(initial_sync_data.clone())?;
EthereumBeaconClient::<T>::initial_sync(&initial_sync_data)?;

let finalized_header_update = finalized_header_update();

SyncCommittees::<T>::insert(
EthereumBeaconClient::<T>::compute_current_sync_period(
let current_period = EthereumBeaconClient::<T>::compute_current_sync_period(
finalized_header_update.attested_header.slot,
),
initial_sync_data.current_sync_committee,
);
);

EthereumBeaconClient::<T>::store_sync_committee(current_period, &initial_sync_data.current_sync_committee)?;

//initialize LatestFinalizedHeaderState with parent slot of finalized_header_update
LatestFinalizedHeaderState::<T>::set(FinalizedHeaderState {
Expand All @@ -56,13 +60,15 @@ benchmarks! {

let initial_sync_data = initial_sync();

EthereumBeaconClient::<T>::initial_sync(initial_sync_data.clone())?;
EthereumBeaconClient::<T>::initial_sync(&initial_sync_data)?;

let header_update = header_update();

SyncCommittees::<T>::insert(EthereumBeaconClient::<T>::compute_current_sync_period(
let current_period = EthereumBeaconClient::<T>::compute_current_sync_period(
header_update.beacon_header.slot,
), initial_sync_data.current_sync_committee);
);

EthereumBeaconClient::<T>::store_sync_committee(current_period, &initial_sync_data.current_sync_committee)?;

let finalized_update: FinalizedHeaderUpdate<> = finalized_header_update();

Expand Down Expand Up @@ -90,32 +96,31 @@ benchmarks! {
assert_eq!(<Blocked<T>>::get(),false);
}

bls_fast_aggregate_verify {
bls_fast_aggregate_verify_pre_aggregated {
let update = initialize_sync_committee::<T>()?;
let participant_pubkeys = get_participant_pubkeys::<T>(&update)?;
let signing_root = get_signing_message::<T>(&update)?;
let participant_pubkeys = participant_pubkeys::<T>(&update)?;
let signing_root = signing_root::<T>(&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::<T>::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::<T>()?;
let participant_pubkeys = get_participant_pubkeys::<T>(&update)?;
let participant_pubkeys = participant_pubkeys::<T>(&update)?;
let signing_root = signing_root::<T>(&update)?;
}:{
participant_pubkeys
.iter()
.map(|bytes| milagro_bls::PublicKey::from_bytes_unchecked(&bytes.0))
.collect::<Result<Vec<milagro_bls::PublicKey>, _>>().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::<T>()?;
let participant_pubkeys = get_participant_pubkeys::<T>(&update)?;
let signing_root = get_signing_message::<T>(&update)?;
let agg_sig = get_aggregate_signature::<T>(update.sync_aggregate.sync_committee_signature).unwrap();
let agg_pub_key = get_aggregate_pubkey::<T>(participant_pubkeys).unwrap();
let current_sync_committee = sync_committee::<T>(&update)?;
let absent_pubkeys = absent_pubkeys::<T>(&update)?;
let signing_root = signing_root::<T>(&update)?;
}:{
agg_sig.fast_aggregate_verify_pre_aggregated(&signing_root.as_bytes(), &agg_pub_key)
fast_aggregate_verify(&current_sync_committee.aggregate_pubkey, &absent_pubkeys, signing_root, &update.sync_aggregate.sync_committee_signature).unwrap();
}
}

Expand Down
102 changes: 46 additions & 56 deletions parachain/pallets/ethereum-beacon-client/src/benchmarking/util.rs
Original file line number Diff line number Diff line change
@@ -1,87 +1,77 @@
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 primitives::{PublicKeyPrepared, SyncCommitteePrepared};
use sp_core::H256;

use super::{initial_sync, sync_committee_update};
use crate::{decompress_sync_committee_bits, Error};

pub fn initialize_sync_committee<T: Config>() -> Result<SyncCommitteeUpdate, &'static str> {
let initial_sync_data = initial_sync();

EthereumBeaconClient::<T>::initial_sync(initial_sync_data.clone())?;
EthereumBeaconClient::<T>::initial_sync(&initial_sync_data)?;

let sync_committee_update = sync_committee_update();

//initialize SyncCommittees with period in sync_committee_update
LatestSyncCommitteePeriod::<T>::set(EthereumBeaconClient::<T>::compute_current_sync_period(
sync_committee_update.attested_header.slot,
));
SyncCommittees::<T>::insert(
EthereumBeaconClient::<T>::compute_current_sync_period(
sync_committee_update.attested_header.slot,
),
initial_sync_data.current_sync_committee,
let current_period = EthereumBeaconClient::<T>::compute_current_sync_period(
sync_committee_update.attested_header.slot,
);
EthereumBeaconClient::<T>::store_sync_committee(
current_period,
&initial_sync_data.current_sync_committee,
)?;
Ok(sync_committee_update)
}

pub fn get_participant_pubkeys<T: Config>(
pub fn sync_committee<T: Config>(
update: &SyncCommitteeUpdate,
) -> Result<Vec<PublicKey>, &'static str> {
let sync_committee_bits =
decompress_sync_committee_bits(update.sync_aggregate.sync_committee_bits.clone());
) -> Result<SyncCommitteePrepared<SYNC_COMMITTEE_SIZE>, &'static str> {
let current_period =
EthereumBeaconClient::<T>::compute_current_sync_period(update.attested_header.slot);
let current_sync_committee =
SyncCommittees::<T>::get(current_period).ok_or("no sync committee")?;
let sync_committee_pubkeys = current_sync_committee.pubkeys;
let mut participant_pubkeys: Vec<PublicKey> = 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::<T>::get(current_period).ok_or("no sync committee")?;
Ok(sync_committee)
}

pub fn get_signing_message<T: Config>(update: &SyncCommitteeUpdate) -> Result<H256, &'static str> {
let validators_root = <ValidatorsRoot<T>>::get();
let fork_version = EthereumBeaconClient::<T>::compute_fork_version(
EthereumBeaconClient::<T>::compute_epoch_at_slot(
update.signature_slot,
crate::config::SLOTS_PER_EPOCH,
),
pub fn participant_pubkeys<T: Config>(
update: &SyncCommitteeUpdate,
) -> Result<Vec<PublicKeyPrepared>, &'static str> {
let sync_committee_bits =
decompress_sync_committee_bits(update.sync_aggregate.sync_committee_bits.clone());
let current_sync_committee = sync_committee::<T>(update)?;
let pubkeys = EthereumBeaconClient::<T>::find_pubkeys(
&sync_committee_bits,
&current_sync_committee.pubkeys.to_vec(),
true,
);
let domain_type = crate::config::DOMAIN_SYNC_COMMITTEE.to_vec();
let domain =
EthereumBeaconClient::<T>::compute_domain(domain_type, fork_version, validators_root)?;
let signing_root =
EthereumBeaconClient::<T>::compute_signing_root(update.attested_header.clone(), domain)?;
Ok(signing_root)
Ok(pubkeys)
}

pub fn get_aggregate_signature<T: Config>(
signature: Signature,
) -> Result<AggregateSignature, Error<T>> {
let sig =
MilagroSignature::from_bytes(&signature.0[..]).map_err(|_| Error::<T>::InvalidSignature)?;
let agg_sig = AggregateSignature::from_signature(&sig);
Ok(agg_sig)
pub fn absent_pubkeys<T: Config>(
update: &SyncCommitteeUpdate,
) -> Result<Vec<PublicKeyPrepared>, &'static str> {
let sync_committee_bits =
decompress_sync_committee_bits(update.sync_aggregate.sync_committee_bits.clone());
let current_sync_committee = sync_committee::<T>(update)?;
let pubkeys = EthereumBeaconClient::<T>::find_pubkeys(
&sync_committee_bits,
&current_sync_committee.pubkeys.to_vec(),
false,
);
Ok(pubkeys)
}

pub fn get_aggregate_pubkey<T: Config>(
pubkeys: Vec<PublicKey>,
) -> Result<AggregatePublicKey, Error<T>> {
let milagro_public_keys = pubkeys
.iter()
.map(|bytes| milagro_bls::PublicKey::from_bytes_unchecked(&bytes.0))
.collect::<Result<Vec<milagro_bls::PublicKey>, _>>()
.map_err(|_| Error::<T>::InvalidSignaturePoint)?;
let agg_pub_key = AggregatePublicKey::into_aggregate(&milagro_public_keys)
.map_err(|_| Error::<T>::InvalidAggregatePublicKeys)?;
Ok(agg_pub_key)
pub fn signing_root<T: Config>(update: &SyncCommitteeUpdate) -> Result<H256, &'static str> {
let validators_root = <ValidatorsRoot<T>>::get();
let signing_root = EthereumBeaconClient::<T>::signing_root(
update.attested_header.clone(),
validators_root,
update.signature_slot,
)?;
Ok(signing_root)
}
Loading