-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Make AssetId
and MultiLocation
non-Copy
; make Instruction
92% smaller
#7236
base: master
Are you sure you want to change the base?
Conversation
} | ||
} | ||
|
||
impl IntoIterator for Junctions { | ||
type Item = Junction; | ||
type IntoIter = JunctionsIterator; | ||
fn into_iter(self) -> Self::IntoIter { | ||
JunctionsIterator(self) | ||
JunctionsIterator { range: 0..self.len(), junctions: self } |
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.
would be nice if arg order was switched: junctions, range so it's the same as JunctionsRefIterator
above
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 deliberate. The arg order must be like this because self
is moved into JunctionsIterator
, and once you move it you can't call self.len()
.
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.
On the whole I really like this.
pub struct OnlyParachains; | ||
impl Contains<MultiLocation> for OnlyParachains { | ||
fn contains(loc: &MultiLocation) -> bool { | ||
matches!(loc.unpack(), (0, [Parachain(_)])) | ||
} | ||
} | ||
|
||
pub struct CollectivesOrFellows; | ||
impl Contains<MultiLocation> for CollectivesOrFellows { | ||
fn contains(loc: &MultiLocation) -> bool { | ||
matches!(loc.unpack(), |(0, [Parachain(COLLECTIVES_ID)])| ( | ||
0, | ||
[Parachain(COLLECTIVES_ID), Plurality { id: BodyId::Technical, .. }] | ||
)) | ||
} |
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'd prefer to keep the declarative syntax. As a rule, top-level runtime files should not contain procedural code.
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.
Generally looks like a reasonable direction (modulo the comment).
This should probably go in XCMv4 though since it's a major API breakage.
@gavofyork Hm... well, although it is a source-level API breakage the ABI will stay the same ( I'm not saying we shouldn't care about API-level backwards compatibility, we definitely should, however in my opinion fixing this is worth the API breakage. Having such huge types is a potential performance trap and risks triggering bugs like these not only in our code but in our users' code. So personally I would suggest landing this and, if we're worried about how it will affect downstream users, I could maybe write a migration guide explaining how to update the code to the new API (which is fairly easy, albeit maybe somewhat tedious) and we'd attach that to the release notes? But it is up to you; if you don't want to break the API then I can update this PR to only include non-breaking changes in preparation for V4, but obviously this won't fix the underlying issue, just make it easier to do this when V4 lands. |
I note that we currently need to box |
This pull request has been mentioned on Polkadot Forum. There might be relevant details there: https://forum.polkadot.network/t/polkadot-release-analysis-v0-9-43/3158/3 |
I think it's best to do this on XCMv4. While it's true the binary interface didn't change, the programming interface did, and it does require some effort by XCM developers to change to the new format. |
We might reasonably make XCMv4 an API-only change (for this) and deliver NOW, rather than waiting around indefinitely for the rest of v4 to materialize. The new instructions can be done as a v5. |
Okay, so just to clarify: release v4 now containing this change, and retarget all existing RFCs to v5? Sounds like we should also pair it with some renaming changes. In any case, this means that this PR needs to create a new folder for v4 and make the changes there, rather than modifying existing v2 and v3 type definitions. |
This PR makes the following changes:
AssetId
,MultiLocation
,Junctions
are notCopy
anymore and need to be explicitlyclone()
'd.The sizes of XCM types are now drastically reduced.
Before:
After:
The
Junctions
type is now internally boxed, or more specificallyArc
'd, and acts in a copy-on-write fashion. This makes it cheaper to clone (now it only has to bump the refcount instead of copying over half a kilobyte).The canonical way of constructing a
Junctions
is now through a conversion from an array.Before:
let xs = Junctions::X2(OnlyChild, OnlyChild)
After:
let xs: Junctions = [OnlyChild, OnlyChild].into()
Since Rust doesn't (yet) support pattern matching of boxed values this makes it not possible to directly match on them, however this can be worked around by converting the internal
Junctions
into a slice and matching on that, for example:Before:
After:
A few of some of the previously
const
functions and statics were made not-const
since anArc
cannot be constructed in aconst
context.Potential open questions
Junctions
type completely opaque? There might not be much of a point in keeping it as an enum now, since you can't directly match on it anyway. (Although this could potentially change in the future when Rust will support matching of boxed values.)Junctions::unpack
returning a tuple, or perhaps introduce aJunctionsRef
type so that the parameters are named when matching?(This still needs a Cumulus companion, which I will add once paritytech/substrate#14158 is merged.)