-
Notifications
You must be signed in to change notification settings - Fork 1.1k
relax XcmFeeToAccount trait bound on AccountId
#4959
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
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]>
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 |
acatangiu
left a comment
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 |
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
FeeManagerenforces the boundaryInto<[u8; 32]>for theAccountIdtype.Here is how it works currently:
Configuration:
XcmToFeeAccountstruct:deposit_or_burn_fee()function:In order to use another
AccountIdtype (for example, 20 byte addresses for compatibility with Ethereum or Bitcoin), one has to duplicate the code as the following (roughly changing every32to20):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
IntoLocationto be able to express bothInto<[u8; 32]>andInto<[u8; 20]>should be accepted (and every otherAccountIdtype as long as they implement this trait).Currently,
deposit_or_burn_fee()function converts thereceiver: AccountIdto a location. I think converting an account toLocationshould not be the responsibility ofdeposit_or_burn_fee()function.This trait also decouples the conversion of
AccountIdtoLocation, fromdeposit_or_burn_fee()function. And exposesIntoLocationtrait. Thus, allowing everyone to come up with theirAccountIdtype 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_feeorXcmToFeeAccountgeneric was not possible from what I understood, due to Rust currently do not support a way to express the generic should implement eithertrait Aortrait 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
frontierthat implementsIntoLocationforAccountId20if this PR gets accepted.Summary
this new trait:
AccountIdtoLocation, fromdeposit_or_burn_fee()functionXcmFeeToAccountaccept every possibleAccountIdtype as long as they they implementIntoLocation@franciscoaguirre and @gupnik are already aware of the issue, so tagging them here for visibility.