HRMP – Horizontal Relay Message Passing is the sunshine weight model of XCMP – Cross-Chain Message Passing that doesn’t enable parachains to instantly ship messages to one another however as an alternative makes use of the relay chain to facilitate the passing of messages between parachains through a mixture of UMP – Upward Message Passing & DMP – Downward Message Passing protocols.
What are these messages?
Polkadot defines this generic cross-consensus-messages format referred to as XCM which is designed to be platform agnostic, what meaning is you cannot solely ship messages from blockchain to blockchain but in addition to good contracts of different chains.
XCM is outlined as
pub struct Xcm<Name>(pub Vec<Instruction<Name>>);
What you see here’s a tuple struct with a public vec subject and the generic kind Name
Contained in the Vec
is a set of directions {that a} particular consensus system should outline to have the recipient consensus system execute in a step clever method, what meaning is these set of directions a.ok.a Instruction<Name>
is an enum with variants of normal directions/dispatchable calls that exists in most substrate based mostly chains(i.e. TransferAsset
) and a non-standard instruction Transact
which permits calls which might be particular to the recipient chain.
Questions
- What occurs when the formatting of the recipient chain adjustments within the occasion of a runtime improve?
XCM acts as a layer earlier than the precise runtime of your chain, if in case you have an instruction to WithdrawAsset
/TransferAsset
then you may simply program the abstraction permitting XCM keep constant however below the hood implement what ever adjustments to the formatting and/or pallet you want, this solely applies to plain directions, for the Transact
instruction you need to be sure the transaction format(i.e. dispatchable operate format) of the recipient chain stays the identical through the cross-chain-communication.
- What is the means of sending XCM
For this objective we’re going to simulate a easy asset switch on the relay chain initiated by a parachain, we’ll be utilizing the xcm-simulator developed by shawn from Acala
Step 1
Clone the Polkadot repo and construct
i often swap to a brand new department at this level simply so i do not push something to grasp accidentally.
Step 2
Head over to the xcm-executor library file and add these logs within the process_instruction
operate simply so we will see what occurs once we do a easy switch.
...
/// Course of a single XCM instruction, mutating the state of the XCM digital machine.
fn process_instruction(&mut self, instr: Instruction<Config::Name>) -> End result<(), XcmError> {
println!("instruction: {:?}", instr);
println!("origin: {:?}", self.origin);
println!("holding earlier than: {:?}", self.holding);
let consequence = match instr {
WithdrawAsset(property) => {
// Take `property` from the origin account (on-chain) and place in holding.
let origin = self.origin.as_ref().ok_or(XcmError::BadOrigin)?;
for asset in property.drain().into_iter() {
Config::AssetTransactor::withdraw_asset(&asset, origin)?;
self.holding.subsume(asset);
}
Okay(())
},
...
};
println!("holding after: {:?}", self.holding);
consequence
...
Additionally all that’s unfamiliar proper now will turn into clearer within the subsequent half, I imagine giving a excessive stage overview earlier than delving into the nitty gritty helps, so for now simply observe alongside and I hope it is going to be price you time in the long run.
operating 1 take a look at
instruction: WithdrawAsset(MultiAssets([MultiAsset { id: Concrete(MultiLocation { parents: 0, interior: Here }), fun: Fungible(10) }]))
origin: Some(MultiLocation { dad and mom: 0, inside: X1(Parachain(1)) })
holding earlier than: Belongings { fungible: {}, non_fungible: {} }
holding after: Belongings { fungible: {Concrete(MultiLocation { dad and mom: 0, inside: Right here }): 10}, non_fungible: {} }
instruction: BuyExecution { charges: MultiAsset { id: Concrete(MultiLocation { dad and mom: 0, inside: Right here }), enjoyable: Fungible(10) }, weight_limit: Limitless }
origin: Some(MultiLocation { dad and mom: 0, inside: X1(Parachain(1)) })
holding earlier than: Belongings { fungible: {Concrete(MultiLocation { dad and mom: 0, inside: Right here }): 10}, non_fungible: {} }
holding after: Belongings { fungible: {Concrete(MultiLocation { dad and mom: 0, inside: Right here }): 10}, non_fungible: {} }
instruction: DepositAsset { property: Wild(All), max_assets: 1, beneficiary: MultiLocation { dad and mom: 0, inside: X1(Parachain(2)) } }
origin: Some(MultiLocation { dad and mom: 0, inside: X1(Parachain(1)) })
holding earlier than: Belongings { fungible: {Concrete(MultiLocation { dad and mom: 0, inside: Right here }): 10}, non_fungible: {} }
holding after: Belongings { fungible: {}, non_fungible: {} }
take a look at assessments::withdraw_and_deposit ... okay