MultiLocation-based account derivation

Currently the XCM configuration defines how to convert multilocations to accounts, usually mapping the parachain multilocation to is sovereign account through the SiblingParachainConvertsVia or the ChildParachainConvertsVia

However, this location conversions obviously fail if the multilocation does not represent a parachain. Therefore, we need to add further conversions if we want to map an origin representing, e.g., an account in a parachain (e.g., MultiLocation {parents: 1, interior: X2(Parachain, AccountKey32)}). We have observed the existence of Account32Hash, which allows you to convert a generic multilocation to an accountId by hashing it.

In Moonbeam, we have already started experiment with these kind of location conversions. Should this become the standard way of implementing such usecase? And although I know this clearly depends on the parachain implementing it, maybe it would make sense to provide a RPC method that performs this conversion to help UI tools?

2 Likes

I suppose I’m still not clear on what use-case that deriving an account is supposed to solve. Aside from MultiLocations coming from the relay chain or parachains, is it not enough to simply extract the AccountKey32 from a MultiLocation containing the AccountKey32 junction?

The use case we are trying to achieve:

Parachain A sends a message to Parachain B with DescendOrigin as first instruction, which would convert the origin from *MultiLocation {parents: 1, interior: X1(Parachain(para_a_id))}* to MultiLocation {parents: 1, interior: X2(Parachain(para_a_id), AccountKey32(para_a_account))}. This allows parachain a to have “more sovereign accounts” other than the main one.

The problem I see if parachain B extracts para_a_account from AccountKey32 is that parachain A would be able to control any account it wants in parachain B (or in any other parachain that uses the same multilocation to account conversion). While hashing the multilocation and converting it into an account ensures isolation. We are guaranteed that if one parachain gets compromised, it can only control its sovereign accounts, but not others

The DescendOrigin as first instruction seems to be what pallet-xcm is doing when using the send extrinsic and the origin is not root: polkadot/lib.rs at e2da6e5369b0b1a2dd7524bfef03ec269dbc7ec6 · paritytech/polkadot · GitHub

I don’t believe so? Just by reading what the origin of ../Parachain(para_a_id)/AccountId32(para_a_account) represents, it’s simply a less privileged account than the sovereign account of parachain A (i.e. a less privileged origin than ../Parachain(para_a_id)).

Not really. Recall that DescendOrigin changes the origin, and, if I’m not mistaken, always to a lower privileged one. In other words, DescendOrigin won’t ever allow you to attach an AccountId32 junction to it that contains parachain B’s account ID – it would always be understood as the account ID of parachain A, because parachain is the origin of the XCM.

Sorry, I used the term “sovereign” because I think by definition “sovereign” referts to an account controlled by one consensus system in another consensus system. But yeah I agree these would “less priviledged accounts”, but I dont yet have a name for them (maybe Multilocation-derived accounts?).

Let’s try to go back for a second. Our goal is that a multilocation of the form ../Parachain(para_a_id)/AccountId32(para_a_account) translates to an account (obviously a less-priviledged account than the sovereign account) in parachain B. This account could be used to dispatch Transact operations, Withdraw tokens from it, etc.

The question here is, how do we transform a multilocation of the form ../Parachain(para_a_id)/AccountId32(para_a_account) into a parachain B account? Ideally we want to maintain isolation, meaning ../Parachain(para_a_id)/AccountId32(para_a_account) and ../Parachain(para_c_id)/AccountId32(para_c_account) can never be mapped the same parachain B account. We believe hashing the multilocation as a whole and then converting it into an accountId32 guarantees uniqueness, while dispatching directly from the accountId32 set in the junction does not.

Is there anything I am missing?

@xlc I’d be happy to get your opinion on it too. Is having a standard for managing those multilocation something you would be interested to follow too ?

1 Like

Yeah I had similar thought about this before. This is a must have feature to allow non-signed-origin to use XCM with all the parachains without chain specific modification.

For example, a common use case is for Polkadot Council to be able to control some assets on another parachain, for whatever reason. Right now the dest parachain have to make some additional configuration to support the council origin from relaychain and eventually map it to an Account type to hold the asset. With a standard way to map MultiLocation to Account, then no additional work required to support it. The source parachain can come up whatever MultiLocation as they need, and it just work on all other parachain that supports this standard.

1 Like

Has this discussion continued in some other place perhaps? :slightly_smiling_face:

We’ve had the Account32Hash conversion enabled for some time on our testnet (Shibuya) but are hesitant to put it on the production network yet since it doesn’t seem like future-proof approach.

With the introduction of XCM v3, the derived account will no longer be same as in v2 I guess.

Function looks like this:

fn convert_ref(location: impl Borrow<MultiLocation>) -> Result<AccountId, ()> {
	Ok(("multiloc", location.borrow()).using_encoded(blake2_256).into())
}

And Account32Id has changed between v2 and v3:

  • v2: AccountId32 { network: NetworkId, id: [u8; 32] }
  • v3: AccountId32 { network: Option<NetworkId>, id: [u8; 32] }

Hi Dino, I think it would be OK to just convert from V3 multilocation to V2 multilocation before you do the hashing.

However there is an ongoing new implementation here: XCM: Remote account converter by mustermeiszer · Pull Request #6662 · paritytech/polkadot · GitHub, which should make things easier

1 Like

Hey @girazoki,

Agree, it’s not much work to keep it backwards compatible but I’d like us to avoid having to do that in the future.

Wasn’t aware of the PR you linked, thanks a lot!
Just what I was looking for :slightly_smiling_face: