Skip to content
This repository has been archived by the owner on Oct 22, 2024. It is now read-only.

Commit

Permalink
Merge commit '64b8cc1acdfe8e4c904844984572f5d84e278a22' into ron/merg…
Browse files Browse the repository at this point in the history
…e-to-upstream
  • Loading branch information
yrong committed Dec 19, 2023
2 parents 61dcbd7 + 64b8cc1 commit cfae585
Show file tree
Hide file tree
Showing 8 changed files with 202 additions and 77 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ pub struct Envelope {
#[derive(Copy, Clone, RuntimeDebug)]
pub struct EnvelopeDecodeError;

impl TryFrom<Log> for Envelope {
impl TryFrom<&Log> for Envelope {
type Error = EnvelopeDecodeError;

fn try_from(log: Log) -> Result<Self, Self::Error> {
fn try_from(log: &Log) -> Result<Self, Self::Error> {
let topics: Vec<B256> = log.topics.iter().map(|x| B256::from_slice(x.as_ref())).collect();

let event = OutboundMessageAccepted::decode_log(topics, &log.data, true)
Expand Down
28 changes: 20 additions & 8 deletions bridges/snowbridge/parachain/pallets/inbound-queue/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ pub const LOG_TARGET: &str = "snowbridge-inbound-queue";

#[frame_support::pallet]
pub mod pallet {

use super::*;

use frame_support::pallet_prelude::*;
Expand All @@ -102,7 +101,7 @@ pub mod pallet {
type Verifier: Verifier;

/// Message relayers are rewarded with this asset
type Token: Mutate<Self::AccountId>;
type Token: Mutate<Self::AccountId> + Inspect<Self::AccountId>;

/// XCM message sender
type XcmSender: SendXcm;
Expand All @@ -128,8 +127,14 @@ pub mod pallet {
#[cfg(feature = "runtime-benchmarks")]
type Helper: BenchmarkHelper<Self>;

/// Convert a weight value into balance type.
/// Convert a weight value into deductible balance type.
type WeightToFee: WeightToFee<Balance = BalanceOf<Self>>;

/// Convert a length value into deductible balance type
type LengthToFee: WeightToFee<Balance = BalanceOf<Self>>;

/// The upper limit here only used to estimate delivery cost
type MaxMessageSize: Get<u32>;
}

#[pallet::hooks]
Expand Down Expand Up @@ -228,7 +233,7 @@ pub mod pallet {

// Decode event log into an Envelope
let envelope =
Envelope::try_from(message.event_log).map_err(|_| Error::<T>::InvalidEnvelope)?;
Envelope::try_from(&message.event_log).map_err(|_| Error::<T>::InvalidEnvelope)?;

// Verify that the message was submitted from the known Gateway contract
ensure!(T::GatewayAddress::get() == envelope.gateway, Error::<T>::InvalidGateway);
Expand All @@ -253,7 +258,7 @@ pub mod pallet {
// Reward relayer from the sovereign account of the destination parachain
// Expected to fail if sovereign account has no funds
let sovereign_account = sibling_sovereign_account::<T>(channel.para_id);
let delivery_cost = Self::get();
let delivery_cost = Self::calculate_delivery_cost(message.encode().len() as u32);
T::Token::transfer(&sovereign_account, &who, delivery_cost, Preservation::Preserve)?;

// Decode message into XCM
Expand Down Expand Up @@ -317,14 +322,21 @@ pub mod pallet {
let (xcm_hash, _) = send_xcm::<T::XcmSender>(dest, xcm).map_err(Error::<T>::from)?;
Ok(xcm_hash)
}

pub fn calculate_delivery_cost(length: u32) -> BalanceOf<T> {
let weight_fee = T::WeightToFee::weight_to_fee(&T::WeightInfo::submit());
let len_fee = T::LengthToFee::weight_to_fee(&Weight::from_parts(length as u64, 0));
weight_fee
.saturating_add(len_fee)
.saturating_add(T::PricingParameters::get().rewards.local)
}
}

/// API for accessing the delivery cost of a message
impl<T: Config> Get<BalanceOf<T>> for Pallet<T> {
fn get() -> BalanceOf<T> {
let pricing_parameters = T::PricingParameters::get();
let refund: BalanceOf<T> = T::WeightToFee::weight_to_fee(&T::WeightInfo::submit());
refund.saturating_add(pricing_parameters.rewards.local)
// Cost here based on MaxMessagePayloadSize(the worst case)
Self::calculate_delivery_cost(T::MaxMessageSize::get())
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use super::*;

use frame_support::{
parameter_types,
traits::{ConstU128, Everything},
traits::{ConstU128, ConstU32, Everything},
weights::IdentityFee,
};
use hex_literal::hex;
Expand Down Expand Up @@ -219,6 +219,8 @@ impl inbound_queue::Config for Test {
#[cfg(feature = "runtime-benchmarks")]
type Helper = Test;
type WeightToFee = IdentityFee<u128>;
type LengthToFee = IdentityFee<u128>;
type MaxMessageSize = ConstU32<1024>;
}

pub fn last_events(n: usize) -> Vec<RuntimeEvent> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,5 +157,9 @@ mod benchmarks {
Ok(())
}

impl_benchmark_test_suite!(SnowbridgeControl, crate::mock::new_test_ext(), crate::mock::Test);
impl_benchmark_test_suite!(
SnowbridgeControl,
crate::mock::new_test_ext(true),
crate::mock::Test
);
}
73 changes: 45 additions & 28 deletions bridges/snowbridge/parachain/pallets/system/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ mod tests;

#[cfg(feature = "runtime-benchmarks")]
mod benchmarking;
pub mod migration;

pub mod api;
pub mod weights;
Expand Down Expand Up @@ -256,34 +257,7 @@ pub mod pallet {
#[pallet::genesis_build]
impl<T: Config> BuildGenesisConfig for GenesisConfig<T> {
fn build(&self) {
let bridge_hub_agent_id =
agent_id_of::<T>(&MultiLocation::here()).expect("infallible; qed");
// Agent for BridgeHub
Agents::<T>::insert(bridge_hub_agent_id, ());

// Primary governance channel
Channels::<T>::insert(
PRIMARY_GOVERNANCE_CHANNEL,
Channel { agent_id: bridge_hub_agent_id, para_id: self.para_id },
);

// Secondary governance channel
Channels::<T>::insert(
SECONDARY_GOVERNANCE_CHANNEL,
Channel { agent_id: bridge_hub_agent_id, para_id: self.para_id },
);

// Asset Hub
let asset_hub_location: MultiLocation =
ParentThen(X1(Parachain(self.asset_hub_para_id.into()))).into();
let asset_hub_agent_id =
agent_id_of::<T>(&asset_hub_location).expect("infallible; qed");
let asset_hub_channel_id: ChannelId = self.asset_hub_para_id.into();
Agents::<T>::insert(asset_hub_agent_id, ());
Channels::<T>::insert(
asset_hub_channel_id,
Channel { agent_id: asset_hub_agent_id, para_id: self.asset_hub_para_id },
);
Pallet::<T>::initialize(self.para_id, self.asset_hub_para_id).expect("infallible; qed");
}
}

Expand Down Expand Up @@ -643,6 +617,49 @@ pub mod pallet {
});
Ok(())
}

/// Checks if the pallet has been initialized.
pub(crate) fn is_initialized() -> bool {
let primary_exists = Channels::<T>::contains_key(PRIMARY_GOVERNANCE_CHANNEL);
let secondary_exists = Channels::<T>::contains_key(SECONDARY_GOVERNANCE_CHANNEL);
primary_exists && secondary_exists
}

/// Initializes agents and channels.
pub(crate) fn initialize(
para_id: ParaId,
asset_hub_para_id: ParaId,
) -> Result<(), DispatchError> {
// Asset Hub
let asset_hub_location: MultiLocation =
ParentThen(X1(Parachain(asset_hub_para_id.into()))).into();
let asset_hub_agent_id = agent_id_of::<T>(&asset_hub_location)?;
let asset_hub_channel_id: ChannelId = asset_hub_para_id.into();
Agents::<T>::insert(asset_hub_agent_id, ());
Channels::<T>::insert(
asset_hub_channel_id,
Channel { agent_id: asset_hub_agent_id, para_id: asset_hub_para_id },
);

// Governance channels
let bridge_hub_agent_id = agent_id_of::<T>(&MultiLocation::here())?;
// Agent for BridgeHub
Agents::<T>::insert(bridge_hub_agent_id, ());

// Primary governance channel
Channels::<T>::insert(
PRIMARY_GOVERNANCE_CHANNEL,
Channel { agent_id: bridge_hub_agent_id, para_id },
);

// Secondary governance channel
Channels::<T>::insert(
SECONDARY_GOVERNANCE_CHANNEL,
Channel { agent_id: bridge_hub_agent_id, para_id },
);

Ok(())
}
}

impl<T: Config> StaticLookup for Pallet<T> {
Expand Down
74 changes: 74 additions & 0 deletions bridges/snowbridge/parachain/pallets/system/src/migration.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2023 Snowfork <[email protected]>
//! Governance API for controlling the Ethereum side of the bridge
use super::*;
use frame_support::traits::OnRuntimeUpgrade;
use log;

#[cfg(feature = "try-runtime")]
use sp_runtime::TryRuntimeError;

pub mod v0 {
use frame_support::{pallet_prelude::*, weights::Weight};

use super::*;

const LOG_TARGET: &str = "ethereum_system::migration";

pub struct InitializeOnUpgrade<T, BridgeHubParaId, AssetHubParaId>(
sp_std::marker::PhantomData<(T, BridgeHubParaId, AssetHubParaId)>,
);
impl<T, BridgeHubParaId, AssetHubParaId> OnRuntimeUpgrade
for InitializeOnUpgrade<T, BridgeHubParaId, AssetHubParaId>
where
T: Config,
BridgeHubParaId: Get<u32>,
AssetHubParaId: Get<u32>,
{
fn on_runtime_upgrade() -> Weight {
if !Pallet::<T>::is_initialized() {
Pallet::<T>::initialize(
BridgeHubParaId::get().into(),
AssetHubParaId::get().into(),
)
.expect("infallible; qed");
log::info!(
target: LOG_TARGET,
"Ethereum system initialized."
);
T::DbWeight::get().reads_writes(2, 5)
} else {
log::info!(
target: LOG_TARGET,
"Ethereum system already initialized. Skipping."
);
T::DbWeight::get().reads(2)
}
}

#[cfg(feature = "try-runtime")]
fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> {
if !Pallet::<T>::is_initialized() {
log::info!(
target: LOG_TARGET,
"Agents and channels not initialized. Initialization will run."
);
} else {
log::info!(
target: LOG_TARGET,
"Agents and channels are initialized. Initialization will not run."
);
}
Ok(vec![])
}

#[cfg(feature = "try-runtime")]
fn post_upgrade(_: Vec<u8>) -> Result<(), TryRuntimeError> {
frame_support::ensure!(
Pallet::<T>::is_initialized(),
"Agents and channels were not initialized."
);
Ok(())
}
}
}
16 changes: 9 additions & 7 deletions bridges/snowbridge/parachain/pallets/system/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,16 +232,18 @@ impl crate::Config for Test {
}

// Build genesis storage according to the mock runtime.
pub fn new_test_ext() -> sp_io::TestExternalities {
pub fn new_test_ext(genesis_build: bool) -> sp_io::TestExternalities {
let mut storage = frame_system::GenesisConfig::<Test>::default().build_storage().unwrap();

crate::GenesisConfig::<Test> {
para_id: OwnParaId::get(),
asset_hub_para_id: AssetHubParaId::get(),
_config: Default::default(),
if genesis_build {
crate::GenesisConfig::<Test> {
para_id: OwnParaId::get(),
asset_hub_para_id: AssetHubParaId::get(),
_config: Default::default(),
}
.assimilate_storage(&mut storage)
.unwrap();
}
.assimilate_storage(&mut storage)
.unwrap();

let mut ext: sp_io::TestExternalities = storage.into();
let initial_amount = InitialFunding::get();
Expand Down
Loading

0 comments on commit cfae585

Please sign in to comment.