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

Commit

Permalink
Delivery fee should cover cost of local processing (paritytech#975)
Browse files Browse the repository at this point in the history
* Submit outbound message without MessageQueue

* Priority control

* Update priority

* Update cumulus

* Reserve space for high priority messages

* Fix compile error & More refactor

* Improve processing high priority messages

* Some polish

* Add priority back

* Improve comments

* Rename priority to normal

* Refactor submit logic

* Refactor process message

* Add type HighPriorityCommands

* Fix clippy

* Rename priority with BridgeHub

* Update parachain/primitives/core/src/outbound.rs

Co-authored-by: Vincent Geddes <vincent@snowfork.com>

* Update parachain/pallets/outbound-queue/src/lib.rs

Co-authored-by: Vincent Geddes <vincent@snowfork.com>

* Update parachain/pallets/outbound-queue/src/lib.rs

Co-authored-by: Vincent Geddes <vincent@snowfork.com>

* Revamp with ExportOrigin

* Fix format

* Some polish

* Check weight before processing message (paritytech#974)

* update cumulus submodule

* Include base_fee

* Redeem vouchers for delivery fee

* Estimate fee upon commit_one_message

* Balance type as u128

* Improve comments

* Runtime api for estimate_fee

* Remove all voucher&redeem stuff

* Fix for clippy

* Benchmark for do_submit_message

* Add delivery_fee

* Improve fee test

* Remove benchmark for submit

* Add comments

* Rename to calculate_fee

* Comments

* Add method for total fee

* Short name

* Rename to commit_messages

* Use Balance generic for the api

* Update parachain/pallets/outbound-queue/runtime-api/src/lib.rs

Co-authored-by: Vincent Geddes <vincent@snowfork.com>

* Rename generic Runtime to T

* Remove fee from OutboundQueueTicket

* Rename to fees

---------

Co-authored-by: Vincent Geddes <vincent.geddes@hey.com>
Co-authored-by: Vincent Geddes <vincent@snowfork.com>
  • Loading branch information
3 people authored Oct 27, 2023
1 parent 1adc5e0 commit 187c3ff
Show file tree
Hide file tree
Showing 17 changed files with 273 additions and 88 deletions.
4 changes: 4 additions & 0 deletions parachain/Cargo.lock

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

6 changes: 4 additions & 2 deletions parachain/pallets/control/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,10 @@ ethabi = { git = "https://github.com/Snowfork/ethabi-decode.git", package = "eth
hex = "0.4.1"
hex-literal = { version = "0.4.1" }
pallet-balances = { git = "https://github.com/paritytech/substrate.git", branch = "master" }
sp-keyring = { git = "https://github.com/paritytech/substrate.git", branch = "master"}
sp-keyring = { git = "https://github.com/paritytech/substrate.git", branch = "master" }
polkadot-parachain = { git = "https://github.com/paritytech/polkadot.git", branch = "master" }
pallet-message-queue = { git = "https://github.com/paritytech/substrate.git", branch = "master" }
snowbridge-outbound-queue = { path = "../outbound-queue" }

[features]
default = ["std"]
Expand All @@ -60,6 +62,6 @@ std = [
runtime-benchmarks = [
"frame-benchmarking/runtime-benchmarks",
"xcm-builder/runtime-benchmarks",
"xcm-executor/runtime-benchmarks"
"xcm-executor/runtime-benchmarks",
]
try-runtime = ["frame-support/try-runtime"]
3 changes: 2 additions & 1 deletion parachain/pallets/control/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ use crate::Pallet as SnowbridgeControl;
use frame_benchmarking::v2::*;
use frame_system::RawOrigin;
use snowbridge_core::outbound::OperatingMode;
use sp_runtime::SaturatedConversion;
use xcm::prelude::*;

fn fund_sovereign_account<T: Config>(para_id: ParaId) -> Result<(), BenchmarkError> {
let amount: BalanceOf<T> = u16::MAX.into();
let amount: BalanceOf<T> = (1_000_000_000_000_u64).saturated_into::<u128>().saturated_into();
let sovereign_account = sibling_sovereign_account::<T>(para_id);
T::Token::mint_into(&sovereign_account, amount)?;
Ok(())
Expand Down
45 changes: 31 additions & 14 deletions parachain/pallets/control/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,18 @@ use sp_std::prelude::*;
use xcm::prelude::*;
use xcm_executor::traits::ConvertLocation;

use frame_support::{
pallet_prelude::*,
traits::{tokens::Preservation, EnsureOrigin},
};
use frame_system::pallet_prelude::*;
use snowbridge_core::{
outbound::{
Command, Initializer, Message, OperatingMode, OutboundQueue as OutboundQueueTrait, ParaId,
},
sibling_sovereign_account, AgentId,
};
use sp_runtime::Saturating;

#[cfg(feature = "runtime-benchmarks")]
use frame_support::traits::OriginTrait;
Expand Down Expand Up @@ -82,22 +88,21 @@ where

/// Whether a fee should be withdrawn to an account for sending an outbound message
#[derive(Clone, PartialEq, RuntimeDebug)]
enum PaysFee<T>
pub enum PaysFee<T>
where
T: Config,
{
/// Fully charge includes (base_fee + delivery_fee)
Yes(AccountIdOf<T>),
/// Partially charge includes base_fee only
Partial(AccountIdOf<T>),
/// No charge
No,
}

#[frame_support::pallet]
pub mod pallet {
use super::*;
use frame_support::{
pallet_prelude::*,
traits::{tokens::Preservation, EnsureOrigin},
};
use frame_system::pallet_prelude::*;

#[pallet::pallet]
pub struct Pallet<T>(_);
Expand Down Expand Up @@ -289,7 +294,8 @@ pub mod pallet {
ensure!(Channels::<T>::contains_key(para_id), Error::<T>::NoChannel);

let command = Command::UpdateChannel { para_id, mode, fee };
Self::send(para_id, command, PaysFee::<T>::No)?;
let pays_fee = PaysFee::<T>::Partial(sibling_sovereign_account::<T>(para_id));
Self::send(para_id, command, pays_fee)?;

Self::deposit_event(Event::<T>::UpdateChannel { para_id, mode, fee });
Ok(())
Expand Down Expand Up @@ -361,7 +367,9 @@ pub mod pallet {
// Ensure that origin location is some consensus system on a sibling parachain
let (para_id, agent_id) = ensure_sibling::<T>(&origin_location)?;

Self::do_transfer_native_from_agent(agent_id, para_id, recipient, amount)
let pays_fee = PaysFee::<T>::Partial(sibling_sovereign_account::<T>(para_id));

Self::do_transfer_native_from_agent(agent_id, para_id, recipient, amount, pays_fee)
}

/// Sends a message to the Gateway contract to transfer ether from an agent to `recipient`.
Expand Down Expand Up @@ -390,22 +398,30 @@ pub mod pallet {
let (para_id, agent_id) =
ensure_sibling::<T>(&location).map_err(|_| Error::<T>::InvalidLocation)?;

Self::do_transfer_native_from_agent(agent_id, para_id, recipient, amount)
let pays_fee = PaysFee::<T>::No;

Self::do_transfer_native_from_agent(agent_id, para_id, recipient, amount, pays_fee)
}
}

impl<T: Config> Pallet<T> {
/// Send `command` to the Gateway on the channel identified by `origin`.
fn send(origin: ParaId, command: Command, pays_fee: PaysFee<T>) -> DispatchResult {
let message = Message { origin, command };
let (ticket, delivery_fee) =
let (ticket, fee) =
T::OutboundQueue::validate(&message).map_err(|_| Error::<T>::SubmissionFailed)?;

if let PaysFee::Yes(sovereign_account) = pays_fee {
let payment = match pays_fee {
PaysFee::Yes(account) => Some((account, fee.base.saturating_add(fee.delivery))),
PaysFee::Partial(account) => Some((account, fee.base)),
PaysFee::No => None,
};

if let Some((payer, fee)) = payment {
T::Token::transfer(
&sovereign_account,
&payer,
&T::TreasuryAccount::get(),
delivery_fee,
fee,
Preservation::Preserve,
)?;
}
Expand All @@ -421,11 +437,12 @@ pub mod pallet {
para_id: ParaId,
recipient: H160,
amount: u128,
pays_fee: PaysFee<T>,
) -> DispatchResult {
ensure!(Agents::<T>::contains_key(agent_id), Error::<T>::NoAgent);

let command = Command::TransferNativeFromAgent { agent_id, recipient, amount };
Self::send(para_id, command, PaysFee::<T>::No)?;
Self::send(para_id, command, pays_fee)?;

Self::deposit_event(Event::<T>::TransferNativeFromAgent {
agent_id,
Expand Down
73 changes: 54 additions & 19 deletions parachain/pallets/control/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,19 @@ use crate as snowbridge_control;
use frame_support::{
parameter_types,
traits::{tokens::fungible::Mutate, ConstU128, ConstU16, ConstU64, Contains},
weights::IdentityFee,
PalletId,
};
use sp_core::H256;
use xcm_executor::traits::ConvertLocation;

use snowbridge_core::{
outbound::{Message, MessageHash, ParaId, SubmitError},
AgentId,
outbound::{ConstantGasMeter, ParaId},
sibling_sovereign_account, AgentId,
};
use sp_runtime::{
testing::Header,
traits::{AccountIdConversion, BlakeTwo256, IdentityLookup},
traits::{AccountIdConversion, BlakeTwo256, IdentityLookup, Keccak256},
AccountId32,
};
use xcm::prelude::*;
Expand Down Expand Up @@ -94,7 +95,9 @@ frame_support::construct_runtime!(
System: frame_system,
Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>},
XcmOrigin: pallet_xcm_origin::{Pallet, Origin},
OutboundQueue: snowbridge_outbound_queue::{Pallet, Call, Storage, Event<T>},
EthereumControl: snowbridge_control,
MessageQueue: pallet_message_queue::{Pallet, Call, Storage, Event<T>}
}
);

Expand Down Expand Up @@ -146,7 +149,45 @@ impl pallet_xcm_origin::Config for Test {
}

parameter_types! {
pub const HeapSize: u32 = 32 * 1024;
pub const MaxStale: u32 = 32;
pub static ServiceWeight: Option<Weight> = Some(Weight::from_parts(100, 100));
}

impl pallet_message_queue::Config for Test {
type RuntimeEvent = RuntimeEvent;
type WeightInfo = ();
type MessageProcessor = OutboundQueue;
type Size = u32;
type QueueChangeHandler = ();
type HeapSize = HeapSize;
type MaxStale = MaxStale;
type ServiceWeight = ServiceWeight;
}

parameter_types! {
pub const MaxMessagePayloadSize: u32 = 1024;
pub const MaxMessagesPerBlock: u32 = 20;
pub const OwnParaId: ParaId = ParaId::new(1013);
}

impl snowbridge_outbound_queue::Config for Test {
type RuntimeEvent = RuntimeEvent;
type Hashing = Keccak256;
type MessageQueue = MessageQueue;
type MaxMessagePayloadSize = MaxMessagePayloadSize;
type MaxMessagesPerBlock = MaxMessagesPerBlock;
type OwnParaId = OwnParaId;
type GasMeter = ConstantGasMeter;
type Balance = u128;
type DeliveryFeePerGas = ConstU128<1>;
type DeliveryRefundPerGas = ConstU128<1>;
type DeliveryReward = ConstU128<1>;
type WeightToFee = IdentityFee<u128>;
type WeightInfo = ();
}

parameter_types! {
pub const SS58Prefix: u8 = 42;
pub const AnyNetwork: Option<NetworkId> = None;
pub const RelayNetwork: Option<NetworkId> = Some(NetworkId::Kusama);
Expand All @@ -155,24 +196,12 @@ parameter_types! {
X2(GlobalConsensus(RelayNetwork::get().unwrap()), Parachain(1013));
}

pub struct MockOutboundQueue;
impl snowbridge_control::OutboundQueueTrait for MockOutboundQueue {
type Ticket = Message;
type Balance = Balance;

fn validate(message: &Message) -> Result<(Self::Ticket, Self::Balance), SubmitError> {
Ok((message.clone(), 10))
}

fn submit(_ticket: Self::Ticket) -> Result<MessageHash, SubmitError> {
Ok(MessageHash::zero())
}
}

parameter_types! {
pub TreasuryAccount: AccountId = PalletId(*b"py/trsry").into_account_truncating();
pub Fee: u64 = 1000;
pub const RococoNetwork: NetworkId = NetworkId::Rococo;
pub const InitialFunding: u128 = 1_000_000_000_000;
pub TestParaId: u32 = 2000;
}

#[cfg(feature = "runtime-benchmarks")]
Expand All @@ -196,7 +225,7 @@ impl Contains<MultiLocation> for AllowSiblingsOnly {
impl crate::Config for Test {
type RuntimeEvent = RuntimeEvent;
type OwnParaId = OwnParaId;
type OutboundQueue = MockOutboundQueue;
type OutboundQueue = OutboundQueue;
type MessageHasher = BlakeTwo256;
type SiblingOrigin = pallet_xcm_origin::EnsureXcm<AllowSiblingsOnly>;
type AgentIdOf = HashedDescription<AgentId, DescribeFamily<DescribeAllTerminal>>;
Expand All @@ -211,9 +240,15 @@ impl crate::Config for Test {
pub fn new_test_ext() -> sp_io::TestExternalities {
let storage = frame_system::GenesisConfig::default().build_storage::<Test>().unwrap();
let mut ext: sp_io::TestExternalities = storage.into();
let initial_amount = InitialFunding::get().into();
let test_para_id = TestParaId::get();
let sovereign_account = sibling_sovereign_account::<Test>(test_para_id.into());
let treasury_account = TreasuryAccount::get();
ext.execute_with(|| {
System::set_block_number(1);
let _ = Balances::mint_into(&AccountId32::from([0; 32]), 1_000_000_000_000);
Balances::mint_into(&AccountId32::from([0; 32]), initial_amount).unwrap();
Balances::mint_into(&sovereign_account, initial_amount).unwrap();
Balances::mint_into(&treasury_account, initial_amount).unwrap();
});
ext
}
Expand Down
Loading

0 comments on commit 187c3ff

Please sign in to comment.