-
Notifications
You must be signed in to change notification settings - Fork 337
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
Girazoki avoid statemine prefix breaking change #1159
Girazoki avoid statemine prefix breaking change #1159
Conversation
…atemine-prefix-breaking-change
…atemine-prefix-breaking-change
|
||
}: _(RawOrigin::Root, asset_id, asset_type.clone()) | ||
verify { | ||
assert_eq!(Pallet::<T>::asset_id_type(asset_id), Some(asset_type)); |
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.
This looks like it's (1) changing from one asset type to the same asset type, and (2) expecting the implementation of change_existing_asset_type()
to not short-circuit this case.
This works for now because that is actually how change_existing_asset_type()
is implemented, but it's probably more future-proof to write this test so that it actually changes the type (that way a future "optimization" or similar won't cause the benchmark to become ineffective).
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 wanted to write this benchmark like you described, but I have two associated types (assetId, assetType) that I need to generate and in order to be generic (over the mock runtime and over the proper runtime where this is included) I can only generate the default one. Still I think the benchmarking is correct
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.
One option is to require that AssetType: From<MultiLocation>
in the config, and in that case I can generate several. But to be honest the pallet is so simple that I did not even bother requiring this. Let me know if this is something we think we should add
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.
Agreed, I don't think my concern is worth a lot of effort...
pallets/asset-manager/src/weights.rs
Outdated
} | ||
|
||
/// Weights for pallet_asset_manager using the Substrate node and recommended hardware. | ||
pub struct SubstrateWeight<T>(PhantomData<T>); | ||
impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> { | ||
fn register_asset() -> Weight { | ||
(52_572_000 as Weight) | ||
(50_651_000 as Weight) |
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.
Needs proper benchmark. Let me know when you want me to run this.
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 actually run it on the target machine, but feel free to redo it
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 don't understand this well enough to approve it, but I have looked through it. I'll try to go back through it again soon.
fn get_asset_id(asset_type: T::AssetType) -> Option<T::AssetId> { | ||
AssetTypeId::<T>::get(asset_type) | ||
} |
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.
This implies a 1:1 mapping between an AssetId
and an AssetType
(instead of a many-to-one). I previously thought it made sense to support multiple AssetId
s mapping to a single AssetType
, is this categorically wrong? Or is it not the AssetManager
s responsibility to handle this?
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 think this is wrong. We need the asset-manager to provide one specific multiLocation when a user says: "I want to transact asset X".
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.
The assetType exists mainly to be able to reference distinct type of tokens in the future. Right now its an enum containing XCM(MultiLocation) but in the future we might want to distinguish between, e.g., fungible and non-fungible tokens, which should probably go into different pallets. But since our approach is to retrieve the Id through a hash, there is low risk of collision
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.
Oh, that's right. This constraint is about communicating back to another chain, right?
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.
yes
parents: 1, | ||
interior: X3( | ||
Parachain(id), | ||
PalletInstance(StatemintAssetPalletInstance::get()), |
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.
This seems safe for now. If Kusama were to change their pallet instance (very unlikely) or add a second instance of Statemint (unlikely), this would do bad things, but we will be able to remove this before then anyway -- right?
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.
Yes, the idea is that we remove this once Statemine has upgraded
CouncilCollective, | ||
TechCommitteeCollective, | ||
>, | ||
runtime_common::migrations::XcmMigrations< |
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.
Just to be pedantic, this means we can order CommonMigrations
and XcmMigrations
independently, and that all XcmMigrations
come after all CommonMigrations
.
This is possible because of the impl GetMigrations for Tuple
.
I believe this will cause a lot of allocation and copies every time get_migrations()
is called, but that shouldn't happen outside of runtime upgrades.
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.
Agree. I think in the near future this will dissappear though, just because xcm is now reaching moonbeam. That means xcm migrations will be moved to common.
pub struct PopulateAssetTypeIdStorage<T>(PhantomData<T>); | ||
impl<T: Config> OnRuntimeUpgrade for PopulateAssetTypeIdStorage<T> { | ||
fn on_runtime_upgrade() -> Weight { | ||
log::info!(target: "PopulateAssetTypeIdStorage", "actually running it"); |
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 think log statements like this are fine to leave in, but I might change it so that it will have enough context to make sense in the real world
let location: Option<MultiLocation> = asset_type.into(); | ||
|
||
match location { | ||
Some(MultiLocation { |
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.
You could also throw in an assert here that makes sure the From
impl can be used as expected with respect to this conversion
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.
Not entirely sure about what you mean by this. Can you elaborate more?
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.
This looks good to me. I have some nits which I'll leave to your discretion. I'm asking for changes over just one thing: the assert in on_runtime_upgrade()
as I feel pretty strongly that it should go in post_runtime_upgrade()
.
…atemine-prefix-breaking-change
"version": "7.16.3", | ||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.16.3.tgz", | ||
"integrity": "sha512-WBwekcqacdY2e9AF/Q7WLFUWmdJGJTkbjqTjoMDgXkVZ3ZRUvOPsLb5KdwISoQVsbP+DQzVZW4Zhci0DvpbNTQ==", | ||
"version": "7.16.7", |
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.
Please revert those changes if not intended
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.
The package-lock changes were needed. The reason is that I needed version 6.12.1 to be able to decode and insert a message as if it was coming from statemine (in typescript). I will revisit, but I struggled with this file to be able to do that
pallets/asset-manager/src/lib.rs
Outdated
} | ||
|
||
/// Stores the asset TYPE | ||
/// Stores the asset Type with assetId as key |
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.
/// Stores the asset Type with assetId as key | |
/// Mapping from an asset id to asset type. This is mostly used when receiving transaction specifying an asset directly, like transferring an asset from this chain to another. |
(We should provide a bit more explanation for our storage variable... I wrote an exemple but feel free to rewrite matching what correspond the best to it)
pallets/asset-manager/src/lib.rs
Outdated
#[pallet::storage] | ||
#[pallet::getter(fn asset_id_type)] | ||
pub type AssetIdType<T: Config> = StorageMap<_, Blake2_128Concat, T::AssetId, T::AssetType>; | ||
|
||
/// Stores the asset Id with Asset Type as key |
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.
/// Stores the asset Id with Asset Type as key | |
/// Reverse mapping of AssetIdType. Mapping from an asset type to an asset id. This is mostly used when receiving a multilocation XCM message to retrieve the corresponding asset. |
(another exemple)
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.
will do, thanks alan
// There are no entries in the old storage afterward | ||
|
||
// Assert new storage is empty | ||
assert!(AssetTypeUnitsPerSecond::<T>::iter().next().is_none()); |
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.
Out of curiosity what happens if this is failing? Will it break the chain ?
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.
this is only in pre_upgrade. So this only applies for the try-runtime tests. This does not get executed on_runtime()
What does it do?
It performs three migrations to avoid breaking when statemine changes to its new way of representing assets.
In particular, three new migrations have been added to asset-manager:
AssetType
instead of byassetId
. This allows us to decoupleassetIds
andAssetTypes
, and therefore, avoid migrating pallet-assets whenever we have a breaking change like we do in statemineAssetTypeId
, which holds the AssetType->AssetId mapping. This new storage item is needed if we decoupleassetIds
andAssetTypes
, as now one cannot be calculated hashing the other.The Runtime has been modified so that when we receive X2(Parachain(id), GeneralIndex(index)), we transalate it to X3(Parachain(id), PalletInstance(instance), GeneralIndex(index)) so that the correct assetId is minted. This wont be necessary once we are sure Statemine has updated, but has been added to avoid interruption of service.
All tests have been adapted to these changes, and new tests have been added to prove that both prefixes mint the same assetId.
This should avoid interrumption from the upgrade that statemine is planning to do including
paritytech/cumulus#831. In a future upgrade, we can remove this hack and migrate our storage item.
I have also added a new extrinsic in pallet-asset-manager to support changing the multilocation associated to an assetId, so that in the future we can adaptively change associations between
assetTypes
andassetIds
What important points reviewers should know?
Is there something left for follow-up PRs?
What alternative implementations were considered?
Are there relevant PRs or issues in other repositories (Substrate, Polkadot, Frontier, Cumulus)?
What value does it bring to the blockchain users?