HRMP: основа

HRMP — Horizontal Relay Message Passing — это облегченная версия XCMP — Cross-Chain Message Passing, которая не позволяет парасейнам напрямую посылать сообщения друг другу, а использует релейную цепочку для облегчения передачи сообщений между парасейнами посредством комбинации протоколов UMP — Upward Message Passing & DMP — Downward Message Passing.

Что это за сообщения?

Polkadot определяет общий формат сообщений кросс-консенсуса под названием XCM, который разработан так, чтобы быть платформонезависимым, что означает, что вы можете отправлять сообщения не только с блокчейна на блокчейн, но и на смарт-контракты других цепочек.

XCM определяется как

pub struct Xcm<Call>(pub Vec<Instruction<Call>>);
Вход в полноэкранный режим Выход из полноэкранного режима

Здесь вы видите кортеж struct с публичным полем vec и общим типом Call.

Внутри Vec находится набор инструкций, которые конкретная система консенсуса должна определить, чтобы система консенсуса-получателя выполняла их пошагово, что означает, что этот набор инструкций, т.е. Instruction<Call> — это перечисление с вариантами стандартных инструкций/отправляемых вызовов, которые существуют в большинстве цепочек на основе субстрата (например, TransferAsset) и нестандартной инструкции Transact, которая позволяет вызовы, специфичные для цепочки получателя.

Вопросы

  • Что происходит при изменении форматирования цепочки получателей в случае обновления среды выполнения?

XCM действует как слой перед реальным временем выполнения вашей цепочки, если у вас есть инструкция WithdrawAsset/TransferAsset, то вы можете просто запрограммировать абстракцию, позволяющую XCM оставаться последовательным между этими общими сообщениями, но под капотом реализовать любые изменения, которые вы хотите, это относится только к стандартным инструкциям, для инструкции Transact вы должны убедиться, что формат транзакции (т.е. формат отправляемой функции). т.е. формат диспетчеризируемой функции) цепочки-получателя остается неизменным во время межцепочечной коммуникации.

  • Что представляет собой процесс отправки XCM

Для этого мы собираемся смоделировать простую передачу активов по релейной цепи, инициированную парачайном, мы будем использовать xcm-симулятор, разработанный Шоном из Acala.

Шаг 1

Клонирование репо Polkadot и сборка

Я обычно переключаюсь на новую ветку на этом этапе, просто чтобы ничего не переносить в master 🙂

Шаг 2

Перейдите к файлу библиотеки xcm-executor и добавьте эти логи в функцию process_instruction, просто чтобы мы могли увидеть, что происходит, когда мы делаем простой перенос.

...
    /// Process a single XCM instruction, mutating the state of the XCM virtual machine.
    fn process_instruction(&mut self, instr: Instruction<Config::Call>) -> Result<(), XcmError> {
        println!("instruction: {:?}", instr);
        println!("origin: {:?}", self.origin);
        println!("holding before: {:?}", self.holding);
        let result = match instr {
            WithdrawAsset(assets) => {
                // Take `assets` from the origin account (on-chain) and place in holding.
                let origin = self.origin.as_ref().ok_or(XcmError::BadOrigin)?;
                for asset in assets.drain().into_iter() {
                    Config::AssetTransactor::withdraw_asset(&asset, origin)?;
                    self.holding.subsume(asset);
                }
                Ok(())
            },
        ...
        };
        println!("holding after: {:?}", self.holding);
        result
...

Вход в полноэкранный режим Выход из полноэкранного режима

Шаг 3

Выполните эту команду в терминале

cargo test --package xcm-simulator-example --lib -- tests::withdraw_and_deposit --exact --nocapture
Войти в полноэкранный режим Выйти из полноэкранного режима
running 1 test
instruction: WithdrawAsset(MultiAssets([MultiAsset { id: Concrete(MultiLocation { parents: 0, interior: Here }), fun: Fungible(10) }]))
origin: Some(MultiLocation { parents: 0, interior: X1(Parachain(1)) })
holding before: Assets { fungible: {}, non_fungible: {} }
holding after: Assets { fungible: {Concrete(MultiLocation { parents: 0, interior: Here }): 10}, non_fungible: {} }
instruction: BuyExecution { fees: MultiAsset { id: Concrete(MultiLocation { parents: 0, interior: Here }), fun: Fungible(10) }, weight_limit: Unlimited }
origin: Some(MultiLocation { parents: 0, interior: X1(Parachain(1)) })
holding before: Assets { fungible: {Concrete(MultiLocation { parents: 0, interior: Here }): 10}, non_fungible: {} }
holding after: Assets { fungible: {Concrete(MultiLocation { parents: 0, interior: Here }): 10}, non_fungible: {} }
instruction: DepositAsset { assets: Wild(All), max_assets: 1, beneficiary: MultiLocation { parents: 0, interior: X1(Parachain(2)) } }
origin: Some(MultiLocation { parents: 0, interior: X1(Parachain(1)) })
holding before: Assets { fungible: {Concrete(MultiLocation { parents: 0, interior: Here }): 10}, non_fungible: {} }
holding after: Assets { fungible: {}, non_fungible: {} }
test tests::withdraw_and_deposit ... ok

Войти в полноэкранный режим Выйти из полноэкранного режима

дополнительные вопросы

  • что такое xcm executor и что он из себя представляет?

  • как работает пример xcm simulator crate?

  • можно ли увидеть этот пример, когда цепочке на основе субстрата может понадобиться изменить реализацию общих вызовов под свои нужды и принять xcm-сообщение для выполнения вызова?

  • где происходит фактическое выполнение? в месте отправления или в месте назначения?

  • какой механизм используется для того, чтобы сеть знала, какие сообщения принимать? в этом примере сообщение отправляется с помощью ParachainPalletXcm::send_xcm(Here, Parent, message.clone())) как мы узнаем используемый механизм отправки или как сеть узнает, чтобы определить получателей?

Оцените статью
Procodings.ru
Добавить комментарий