Как работают кроссчейн мосты | 1
Сегодня мы будем разбираться с работой кроссчейн мостов, а поможет нам в этом данная статья ТЫК
Начнем!
Возможно вас удивит тот факт, что в 2022 году в результате взломов было украдено более 3 млрд долларов США, и большая часть этих потерь пришлась на кроссчейн мосты (например, Ronin Network, Wormhole, Nomad, BNB Token Hub, Horizon, Qubit)
Почему кроссчейн мосты так уязвимы? Почему они так плохо реализованы, если над ними работают самые светлые умы?. Настоящая причина заключается в том, что кроссчейн мосты просто слишком сложны, чтобы их правильно реализовать, и включают в себя слишком много технических тонкостей
В этой серии статей мы подробно рассмотрим внутреннее устройство кроссчейн мостов, как они реализуются и в чём их недостатки с точки зрения пользователя. В качестве примера мы будем использовать популярный мост Wormhole
На высоком уровне, что такое кроссчейн мост?
Кроссчейн мост — это просто (виртуальная) связь между двумя блокчейнами для передачи сообщений. По сути, сообщение может быть любой битовой последовательностью (например, передача токена или NFT из цепи A в цепь B)
Предположим, вы хотите перевести биткоин из Ethereum в Solana, вам нужно выполнить как минимум две операции:
1. Списать биткоин с исходного счета на Ethereum
2. Зачислить биткоин на целевой счет на Solana
Однако, поскольку эти две цепочки напрямую не взаимодействуют (в техническом смысле: нет возможности затронуть обе цепочки в одной транзакции), вам нужен посредник, который владеет биткоинами в обеих цепочках и может помочь вам выполнить оба шага:
1. Получить биткойн с вашего исходного счета на свой счет на Ethereum
2. Отправить биткоин (или его эквивалент) на ваш целевой счет с их счета на Solana
Кроссчейн мост — это такой "посредник". Здесь существует несколько проблем:
- Как мост гарантирует, что эти два шага происходят атомарно (т.е. либо оба успешны, либо оба неудачны)? Если хоть один из них будет успешным, а другой неудачным, то либо вы, либо мост потеряет деньги
- Как мост обеспечивает доставку одного и того же сообщения (т.е. только одного биткоина, а не одного Dogecoin или любой другой монеты, или двух биткоинов, и на ваш целевой счет, а не на чей-либо еще)?
- Как мост гарантирует, что одно и то же сообщение будет доставлено ровно один раз (например, его счет на Solana никогда не отправит средства дважды на ваш целевой счет)?
Исследователи Web3 разработали множество различных решений для решения этих проблем (с различными компромиссами). Например, multisig валидаторы, многосторонние вычисления (multi-party computation, MPC), rollup и optimistic мосты и т.д.
Мы сосредоточимся на объяснении показательного решения на основе опекунов (т.е. такого типа валидаторов с несколькими подписями (multisig)), используемых в Wormhole
// далее guardians = опекуны, можно переводить также как хранители, охранники, сторожи и т.д.
На высоком уровне, как работает Wormhole?
По состоянию на январь 2023 года Wormhole соединяет 20 различных цепочек, включая Ethereum, Solana, Binance Smart Chain, Polygon, Aptos и так далее
Это достигается за счет сети из 19 нод, называемых опекунами (см. все адреса 19 опекунов), и ряда смарт-контрактов, развернутых на каждой цепи (включая основной (core) мостовой контракт, мостовой контракт для токенов и мостовой контракт для NFT). Основной мостовой контракт предоставляет функции для отправки сообщений, проверки подписей опекунов и так далее. Мостовые контракты токенов и NFT отвечают за передачу токенов и NFT, соответственно
Каждый из 19 опекунов постоянно наблюдает за сообщениями, передаваемыми основными мостовыми контрактами Wormhole, и подписывает их (например, сообщение типа "Алиса только что отправила биткоин в Wormhole на Ethereum, и она хочет, чтобы Wormhole отправил биткоин Бобу на Solana)
Каждый из опекунов имеет равный вес. Когда большинство (2/3) из них подписывают сообщение, сеть опекунов создает Validator Action Approval (VAA), который служит доказательством для Wormhole доставить то же сообщение на целевую цепочку (например, отправить биткоин Бобу на Solana)
VAA: основной технический компонент Wormhole
VAA лежат в основе всех технических деталей Wormhole. Есть ряд вопросов по VAA, которые могут возникнуть у внимательных читателей:
- Какую информацию содержит VAA? Каков формат VAA?
- Как используются VAA? Где они хранятся? Как их получить?
- Каков сквозной (end-to-end) рабочий процесс кроссчейн сообщения с точки зрения пользователя? Сколько транзакций необходимо для завершения сообщения (т.е. от отправки на исходной цепи до получения на целевой цепи)?
- Как проверяются подписи опекунов (для предотвращения поддельных VAA)? Что если (злонамеренный) опекун подпишет одно и то же сообщение несколько раз и создаст несколько подписей?
- Как убедиться, что токены одинаковы (или эквивалентны) на двух соединенных цепочках? Что, если у Wormhole нет такого же токена (или достаточного количества) на целевой цепочке, как у пользователя, отправившего исходный токен?
- Кто будет выполнять действия по доставке сообщений на целевой цепи (поскольку это требует оплаты транзакций)?
- Как предотвратить двойное использование одного и того же VAA на целевой цепочке?
Далее мы ответим на эти вопросы один за другим (при необходимости с примерами кода)
Формат VAA и внутренности
Каждый VAA кодируется как массив байтов, состоящий из двух частей — заголовка и тела
Заголовок содержит информацию об опекунах и их подписях:
Body содержит подробную информацию о сообщении (например, таймстэмп исходной транзакции, emitter_chain, emitter_address, sequence и пэйлоэд):
В частности, sequence — важная часть информации для обеспечения уникальности каждого VAA (т.е. любые два разных сообщения будут иметь разные VAA, даже если они имеют одинаковое содержание сообщения).
Sequence увеличивается на 1 в функции useSequence при каждом вызове publishMessage:
Очень важно гарантировать, что одно и то же сообщение никогда не будет доставлено дважды. Мы подробнее остановимся на этом моменте в следующем разделе
Массив байтов полезной нагрузки (payload) содержит содержимое сообщения. Например, для токена Transfer он включает сумму перевода, адрес токена, цепочку токенов, адрес получателя, ID целевой цепочки, комиссию за перевод и т.д:
Как используются VAA? Где они хранятся?
После создания VAA (т.е. сообщения, которое было подписано 2/3 опекунами), оно будет храниться в сети опекунов (вероятно, в течение длительного времени или даже всегда)
Каждый VAA уникально индексируется по его emitterChain, emittedAddress и последовательности, и может быть получен путем запроса ноды опекуна (через RPC API) с этой информацией:
"EmitterChain": "ethereum", "EmitterAddress": "0000000000000000000000003ee18b2214aff97000d974cf647e7c347e8fa585", "Sequence": "99139",
https://wormhole-v2-mainnet-api.certus.one/v1/signed_vaa/2/0000000000000000000000003ee18b2214aff97000d974cf647e7c347e8fa585/99139
возвращает следующие байты VAA:
{"vaaBytes":"AQAAAAINAAOuz9Ep03HIS1T2ypAoahT/BO2UBHpRWxiA1CfnlUUKVvMnPyR+E4Eusb1JkHivpoi6mBcEUvDkGW/bOThL7hoAArNvvcthq87MTGsQHjReeIIL0o3G0Epg/kT438O3GzDtZki5wlZ5YpRbuISJlT3nB7x8fYsxNUpJFAhO1DOyHj8BA3XfOUc2I0oIbQF8waRjl27BQQJsexBmNvXyT9XWJEwoXqq5hSQ+tf/0AUuGwHQ9ae84ENBpxyQhgfLxjqm3YAoBBAlFk8Rj/3Am5ULZUZGpGuoghigwNpCH8/OQLq9KEpxYXgTVecr9yznjvlw8PeerhjSUvgjjEuoT6bMV9WWHhPYBBaJOC3wrK3Lp6fbTcLlkRxJqjLPWeu6I33a3BKSAbJtcRAdm40CWwX5t0Kgt5EadmrvIRLIiKu0w037ok9nZUdIABocfns7u1MOoYaUdozFdyd2yJauIXNtAHrhHWE7QXq2XCITt6LK3qSGex9kwZhVeQVxfbplphKDS4ecDEo3l7/UBDLx+py+3KJWOByFPE5ZSBvimJ3GL3KOARgXM13+FvZxDL4tbeil+im9nVEb2J0J7dFBSPAnIP6+6QXkGtMK2Tx8BDTItV66QzmT4wQ9Io6Is+X7xjjhWIThkoPkUVHxqcLQjId1fOs69sd1KuXRt7Fi7TTVb7+OcPh15Uwkx1U5gAH8BDkJ4qZNL3y0gd7hFBLs57NxUPMljmdgbADS2uv5M7i0icdW9AUYxkY3mJXhUlKeS40VFMBAONKnwiIxfAgO/MXsAD/U/vytJGBHNrXO/OSC/Kkc8rH9h57pzUD2gBRULRjTUW4hL9iOULd6HbjYTW9F/U+jqh1SLktILvXS70c+gQnUAEB6M8654Oi/bCoChGFc1/vfDed0n5e9geecJvXz9fIHgMQG561i9aYmhoYtaAPrwW0NV0WweUJBZr3sgD9Yxm0YBEekZvilyWm03vf1/1WiOU6HO15FBQGb8xKyUIEp9BtuWTHAEy3rRe7KfC2grX8XvxBiUK8RDw2kc3M3udKt6nv4AEjivx2qzCoyUcvDJ2GaotcyiWRbZSYfd67PdeNDtlQhyOtD3eGxqKDC8UfxdS/LiTpLVY6sTG7P3TmXm6RBzko0BY7o2y1grAQAAAgAAAAAAAAAAAAAAAD7hiyIUr/lwANl0z2R+fDR+j6WFAAAAAAABg0MBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmwGdAAAAAAAAAAAAAAAAwCqqObIj/o0KDlxPJ+rZCDx1bMIAAv3Kt+tcG5vAryvnKh9emBXjIeGPLemctNwQfsx3bVQvAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJrHQ=="}что соответствует переводу 0,1 WETH из Ethereum в Solana ($128,15):
Сквозной рабочий процесс кроссчейн сообщения
Любой человек может отправить запрос в ноду-опекун, и полученные в ответ байты VAA могут быть переданы любым человеком в целевую цепочку для завершения сообщения (например, минт биткоина на адрес получателя, закодированный в VAA)
Рассмотрим сообщение на скриншоте #1 (выше). С точки зрения пользователя, на самом деле происходит пять внутрицепочечных транзакций (одна на Ethereum и четыре на Solana) в следующем порядке:
Tx1 (0x6539 wrapAndTransferETH на Ethereum): пользователь 0x4f98 отправляет 0,1 WETH на Wormhole Token Bridge 0x3ee1, вызывая wrapAndTransferETH с параметрами, указывающими цепочку получателя (Solana 0x01), получателя (0xfdca, base58 кодируется как 7vfC на Solana), arbiterFee (т. е. плату ретранслятора, если он используется) и nonce:
Tx1 вызывает внутренний мост Wormhole Core Bridge 0x98f3 и передает сообщение, содержащее sequence, nonce, payload и consistencyLevel, как показано ниже:
- Опекуны наблюдают за сообщением, показанным выше, и создают VAA (AQAA...)
- Далее, VAA извлекается из сети опекунов и используется для вызова основного мостового контракта Wormhole на Солане
Tx2 (5CVY VerifySignatures на Solana): функция VerifySignatures на Solana Wormhole core bridge вызывается подписывающим HZBb с VAA для создания SignatureSet 58Ui:
- Эта транзакция также вызывает предварительно скомпилированную программу Secp256k1 SigVerify для проверки подписей опекунов в VAA.
- Всего в VAA содержится 13 подписей. Из-за ограничения вычислений на Solana, Wormhole разделяет проверку этих подписей на две транзакции. Tx2 (5CVY) проверяет семь подписей:
00 ff 01 02 03 04 05 ff ff ff ff ff 06 ff ff ff ff ff ff
Tx3 (46tG VerifySignatures на Solana): обновление SignatureSet 58Ui, проверив остальные шесть подписей:
ff ff ff ff ff ff ff ff ff ff ff ff ff 00 01 02 03 04 05
Tx4 (5AoD PostVAA на Solana): после проверки всех подписей в VAA, функция PostVAA может быть вызвана для создания message account 31Np, которое уникально идентифицирует переданное сообщение:
pub message: Mut<PostedVAA<’b, { AccountState::MaybeInitialized }>>,- Две другие транзакции 3goi и ZpYN также успешно вызывают PostVAA, однако, поскольку message account — это PDA, он инициализируется только один раз в Tx4 (5AoD)
- Кворум 2/3 проверяется в функции PostVAA:
signature_count > 2/3 guardian_set.keys.size
Tx5 (4p4q CompleteWrapped на Solana ): Наконец, для завершения трансфера вызывается функция CompleteWrapped на мосте Wormhole Token Bridge (wormDTUJ)
- Получатель 0xfdca для получения соответствующего токена WETH (ETH - Ether (Portal) 7vfC) на самом деле является связанным счетом токена (PDA) на Solana, принадлежащим 4Kt8. Если получатель еще не существует, то он должен быть создан, чтобы можно было выполнить Tx5. Счет 0xfdca был создан в Tx (sSjG на Solana)
Как проверяются подписи опекунов (для предотвращения подделки VAA)?
Проверка подписей опекунов очень важна для безопасности любых кроссчейн мостов, и неудивительно, что это сложная задача. Мы подробно остановимся на ней в следующей статье
Кто выполняет последующие операции в целевой цепочке?
Любой человек может извлечь VAA и выполнить последующие транзакции. Для отправителя сообщения это было бы просто (например, пользователи, инициирующие передачу токенов на исходной цепочке). Однако что делать, если у пользователя нет ни одного счета на целевой цепочке или у пользователя недостаточно средств для оплаты комиссии за транзакции?
Чтобы решить эту проблему, Wormhole позволяет мостовым ретрансляторам доставлять сообщения и получать за это плату. Плата может быть указана в исходной транзакции и закодирована в полезной нагрузке (payload) VAA:
Как обеспечить правильность перенесённого через мост токена и суммы?
Перенесённый токен на целевой цепочке должен быть таким же или эквивалентным токену, переданному на исходной цепочке. Например, либо оба являются USDC, либо один — обернутый Ether (WETH) на Ethereum, а другой — ETH — Ether (Portal) на Solana. Но это не может быть WETH на Ethereum и USDC на Solana. Мы обсудим эту деталь в будущих статьях
Как предотвратить двойную доставку одного и того же сообщения (VAA replay)?
Это тонкий момент, который требует тщательной разработки в целевом блокчейне. По сути, требуется глобальное состояние, чтобы отмечать каждое доставленное сообщение и отклонять транзакции, которые пытаются повторно доставить одно и то же сообщение. Подробнее об этом мы расскажем в будущих статьях
Надеюсь статья была интересной и понятной!