-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Optimize multilocation reanchoring logic in XCM #6301
base: master
Are you sure you want to change the base?
Conversation
@tonyalaribe I see two not covered edge cases, here the failing tests #6307 |
xcm/src/v1/multilocation.rs
Outdated
id.parents = id | ||
.parent_count() | ||
.saturating_add(target.parent_count().saturating_add(target.interior().len() as u8)); |
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.
id.parents = id | |
.parent_count() | |
.saturating_add(target.parent_count().saturating_add(target.interior().len() as u8)); | |
let final_parents = (id.parent_count() as usize).saturating_add( | |
(target.parent_count() as usize).saturating_add(target.interior().len()), | |
); | |
if final_parents > 255 { | |
return Err(()) | |
} | |
id.parents = final_parents as u8; |
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, I see. The idea is to return an error if there's an overflow and not just saturate it to fail silently? In that case I've switched to using a checked_add
instead of saturating_add
. That should give us the behaviour we want.
bot rebase |
…cation-reanchoring
Rebased |
bot merge |
Waiting for commit status. |
bot rebase |
…cation-reanchoring
Rebased |
bot rebase |
…cation-reanchoring
Rebased |
bot rebase |
…cation-reanchoring
Rebased |
bot rebase |
…cation-reanchoring
Rebased |
I took tests from fn account20() -> Junction {
AccountKey20 { network: Any, key: Default::default() }
}
fn account32() -> Junction {
AccountId32 { network: Any, id: Default::default() }
}
#[test]
fn inverter_works_in_tree() {
let ancestry: MultiLocation = X3(Parachain(1), account20(), account20()).into();
let target = MultiLocation::new(3, X2(Parachain(2), account32()));
let inverted = ancestry.inverted(&target).unwrap();
let expected = MultiLocation::new(2, X3(Parachain(1), account20(), account20()));
assert_eq!(inverted, expected);
}
#[test]
fn inverter_uses_ancestry_as_inverted_location() {
let ancestry: MultiLocation = X2(account20(), account20()).into();
let target = MultiLocation::grandparent();
let inverted = ancestry.inverted(&target).unwrap();
let expected = X2(account20(), account20()).into();
assert_eq!(inverted, expected);
}
#[test]
fn inverter_uses_only_child_on_missing_ancestry() {
let ancestry: MultiLocation = X1(PalletInstance(5)).into();
let target = MultiLocation::grandparent();
let inverted = ancestry.inverted(&target).unwrap();
let expected = X2(PalletInstance(5), OnlyChild).into();
assert_eq!(inverted, expected);
}
#[test]
fn inverter_errors_when_location_is_too_large() {
let ancestry: MultiLocation = Here.into();
let target = MultiLocation { parents: 99, interior: X1(Parachain(88)) };
let inverted = ancestry.inverted(&target);
assert_eq!(inverted, Err(()));
} Only one test is failing:
May be useful to ensure that no regression happened. |
This PR improves the algorithm for reanchor - see paritytech/polkadot-sdk#897 for more details.
Approach:
This gives us the path to go from target to id, without any superflous nodes, or the need for post simplification.
Question:
The
simplify()
method which was used previously is public. Does it make sense to leave it or should it be removed if it's not used anywhere else in the polkadot codebase (except tests)? This also applies with theinverted()
method on Multilocation