-
Notifications
You must be signed in to change notification settings - Fork 707
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
relax XcmFeeToAccount
trait bound on AccountId
#4959
Conversation
XcmFeeToAccount
generic over account typeXcmFeeToAccount
trait bound on AccountId
Review required! Latest push from author must always be reviewed |
|
||
/// Try to deposit the given fee in the specified account. | ||
/// Burns the fee in case of a failure. | ||
pub fn deposit_or_burn_xcm_fee<AssetTransactor: TransactAsset>( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this needs to be public?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also the old implementation should call this one internally.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just copy pasted the old one. Didn't change the visibility settings, assuming there was a reason behind them. I can make both of them (the new and the old one) private, no worries
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like this function (the old one) is exported in xcm-builder/src/lib.rs
. It is also used in polkadot-sdk/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs
.
So, I think we should keep both of them public, I'll export the new one, and put deprecated on the old one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed the old function. Also replaced XcmFeeToAcocunt
with SendXcmFeeToAccount
across the repo. If these changes are not meant to be done by now, I can revert them.
You need to put |
Hi @franciscoaguirre, what are the next steps for this PR? |
Just some clippy errors but the PR is fine |
Co-authored-by: Branislav Kontur <[email protected]>
The CI pipeline was cancelled due to failure one of the required jobs. |
You still have this failing compilation ^ |
You should be able to reproduce locally: |
Yes, sorry, I was just running The issue was due to Note: now |
@acatangiu clippy problem is fixed, also reverted the fmt changes introduced by format on save so that |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changes are good, you just have to make the CI happy - you can check the failed checks on their details
button to find out what/why's failing.
Yep, I know. As I explained, my bad for previously thinking that About
this error seems a bit cryptic. It refers to |
this failure is unrelated probably coming from some upstream serde change - it is currently failing on all PRs... you can ignore this one, we'll fix it at CI level. you can check the others |
Fixed the |
f8f70b3
Fixes paritytech#4960 Configuring `FeeManager` enforces the boundary `Into<[u8; 32]>` for the `AccountId` type. Here is how it works currently: Configuration: ```rust type FeeManager = XcmFeeManagerFromComponents< IsChildSystemParachain<primitives::Id>, XcmFeeToAccount<Self::AssetTransactor, AccountId, TreasuryAccount>, >; ``` `XcmToFeeAccount` struct: ```rust /// A `HandleFee` implementation that simply deposits the fees into a specific on-chain /// `ReceiverAccount`. /// /// It reuses the `AssetTransactor` configured on the XCM executor to deposit fee assets. If /// the `AssetTransactor` returns an error while calling `deposit_asset`, then a warning will be /// logged and the fee burned. pub struct XcmFeeToAccount<AssetTransactor, AccountId, ReceiverAccount>( PhantomData<(AssetTransactor, AccountId, ReceiverAccount)>, ); impl< AssetTransactor: TransactAsset, AccountId: Clone + Into<[u8; 32]>, ReceiverAccount: Get<AccountId>, > HandleFee for XcmFeeToAccount<AssetTransactor, AccountId, ReceiverAccount> { fn handle_fee(fee: Assets, context: Option<&XcmContext>, _reason: FeeReason) -> Assets { deposit_or_burn_fee::<AssetTransactor, _>(fee, context, ReceiverAccount::get()); Assets::new() } } ``` `deposit_or_burn_fee()` function: ```rust /// Try to deposit the given fee in the specified account. /// Burns the fee in case of a failure. pub fn deposit_or_burn_fee<AssetTransactor: TransactAsset, AccountId: Clone + Into<[u8; 32]>>( fee: Assets, context: Option<&XcmContext>, receiver: AccountId, ) { let dest = AccountId32 { network: None, id: receiver.into() }.into(); for asset in fee.into_inner() { if let Err(e) = AssetTransactor::deposit_asset(&asset, &dest, context) { log::trace!( target: "xcm::fees", "`AssetTransactor::deposit_asset` returned error: {:?}. Burning fee: {:?}. \ They might be burned.", e, asset, ); } } } ``` --- In order to use **another** `AccountId` type (for example, 20 byte addresses for compatibility with Ethereum or Bitcoin), one has to duplicate the code as the following (roughly changing every `32` to `20`): ```rust /// A `HandleFee` implementation that simply deposits the fees into a specific on-chain /// `ReceiverAccount`. /// /// It reuses the `AssetTransactor` configured on the XCM executor to deposit fee assets. If /// the `AssetTransactor` returns an error while calling `deposit_asset`, then a warning will be /// logged and the fee burned. pub struct XcmFeeToAccount<AssetTransactor, AccountId, ReceiverAccount>( PhantomData<(AssetTransactor, AccountId, ReceiverAccount)>, ); impl< AssetTransactor: TransactAsset, AccountId: Clone + Into<[u8; 20]>, ReceiverAccount: Get<AccountId>, > HandleFee for XcmFeeToAccount<AssetTransactor, AccountId, ReceiverAccount> { fn handle_fee(fee: XcmAssets, context: Option<&XcmContext>, _reason: FeeReason) -> XcmAssets { deposit_or_burn_fee::<AssetTransactor, _>(fee, context, ReceiverAccount::get()); XcmAssets::new() } } pub fn deposit_or_burn_fee<AssetTransactor: TransactAsset, AccountId: Clone + Into<[u8; 20]>>( fee: XcmAssets, context: Option<&XcmContext>, receiver: AccountId, ) { let dest = AccountKey20 { network: None, key: receiver.into() }.into(); for asset in fee.into_inner() { if let Err(e) = AssetTransactor::deposit_asset(&asset, &dest, context) { log::trace!( target: "xcm::fees", "`AssetTransactor::deposit_asset` returned error: {:?}. Burning fee: {:?}. \ They might be burned.", e, asset, ); } } } ``` --- This results in code duplication, which can be avoided simply by relaxing the trait enforced by `XcmFeeToAccount`. In this PR, I propose to introduce a new trait called `IntoLocation` to be able to express both `Into<[u8; 32]>` and `Into<[u8; 20]>` should be accepted (and every other `AccountId` type as long as they implement this trait). Currently, `deposit_or_burn_fee()` function converts the `receiver: AccountId` to a location. I think converting an account to `Location` should not be the responsibility of `deposit_or_burn_fee()` function. This trait also decouples the conversion of `AccountId` to `Location`, from `deposit_or_burn_fee()` function. And exposes `IntoLocation` trait. Thus, allowing everyone to come up with their `AccountId` type and make it compatible for configuring `FeeManager`. --- Note 1: if there is a better file/location to put `IntoLocation`, I'm all ears Note 2: making `deposit_or_burn_fee` or `XcmToFeeAccount` generic was not possible from what I understood, due to Rust currently do not support a way to express the generic should implement either `trait A` or `trait B` (since the compiler cannot guarantee they won't overlap). In this case, they are `Into<[u8; 32]>` and `Into<[u8; 20]>`. See [this](rust-lang/rust#20400) and [this](rust-lang/rfcs#1672 (comment)). Note 3: I should also submit a PR to `frontier` that implements `IntoLocation` for `AccountId20` if this PR gets accepted. ### Summary this new trait: - decouples the conversion of `AccountId` to `Location`, from `deposit_or_burn_fee()` function - makes `XcmFeeToAccount` accept every possible `AccountId` type as long as they they implement `IntoLocation` - backwards compatible - keeps the API simple and clean while making it less restrictive @franciscoaguirre and @gupnik are already aware of the issue, so tagging them here for visibility. --------- Co-authored-by: Francisco Aguirre <[email protected]> Co-authored-by: Branislav Kontur <[email protected]> Co-authored-by: Adrian Catangiu <[email protected]> Co-authored-by: command-bot <>
Fixes #4960
Configuring
FeeManager
enforces the boundaryInto<[u8; 32]>
for theAccountId
type.Here is how it works currently:
Configuration:
XcmToFeeAccount
struct:deposit_or_burn_fee()
function:In order to use another
AccountId
type (for example, 20 byte addresses for compatibility with Ethereum or Bitcoin), one has to duplicate the code as the following (roughly changing every32
to20
):This results in code duplication, which can be avoided simply by relaxing the trait enforced by
XcmFeeToAccount
.In this PR, I propose to introduce a new trait called
IntoLocation
to be able to express bothInto<[u8; 32]>
andInto<[u8; 20]>
should be accepted (and every otherAccountId
type as long as they implement this trait).Currently,
deposit_or_burn_fee()
function converts thereceiver: AccountId
to a location. I think converting an account toLocation
should not be the responsibility ofdeposit_or_burn_fee()
function.This trait also decouples the conversion of
AccountId
toLocation
, fromdeposit_or_burn_fee()
function. And exposesIntoLocation
trait. Thus, allowing everyone to come up with theirAccountId
type and make it compatible for configuringFeeManager
.Note 1: if there is a better file/location to put
IntoLocation
, I'm all earsNote 2: making
deposit_or_burn_fee
orXcmToFeeAccount
generic was not possible from what I understood, due to Rust currently do not support a way to express the generic should implement eithertrait A
ortrait B
(since the compiler cannot guarantee they won't overlap). In this case, they areInto<[u8; 32]>
andInto<[u8; 20]>
.See this and this.
Note 3: I should also submit a PR to
frontier
that implementsIntoLocation
forAccountId20
if this PR gets accepted.Summary
this new trait:
AccountId
toLocation
, fromdeposit_or_burn_fee()
functionXcmFeeToAccount
accept every possibleAccountId
type as long as they they implementIntoLocation
@franciscoaguirre and @gupnik are already aware of the issue, so tagging them here for visibility.