Avalanche VMs deep-dive #2: Warp Messages in Subnet-EVM

Avalanche VMs deep-dive #2: Warp Messages in Subnet-EVM

In this technical series, we experiment with Avalanche Subnets VMs. Issue #2 is focused on decoding the Warp messages sent between Subnet-EVM chains!

Before we start

This series assumes that you have basic knowledge of Avalanche and Subnets. If “P-Chain” or “Warp Messaging” don’t ring a bell, you should probably read those first:

What is a Warp message?

🤓
For a more in-depth explanation of Avalanche Warp Messaging, see warp/README.md

Avalanche Warp Messaging enables native cross-chain communication within the Avalanche network. It allows users to send messages from one Subnet to another without trusting a third party. Only the validator nodes of the source Subnet can validate the message by signing it with their BLS keys.

Warp message structure

But what is a Warp message technically? It is a very basic and flexible data structure composed of:

  • The NetworkID: the unique ID of an Avalanche Network (Mainnet/Testnet) and provides replay protection for BLS Signers across different Avalanche Networks

  • The SourceChainID: the unique identifier for the blockchain across the Avalanche Network so that each blockchain can only sign a message with its own ID

  • The Payload: an arbitrary byte array containing the contents of the message. VMs define their own message types to include in the payload

All the VM/application-specific data will be encoded in the message Payload.

The message also has an ID that is determined by computing a SHA256 hash of its bytes.

Warp message signature

Once a message has been registered (written to a block) on its source Subnet, the validator nodes of this Subnet can be asked for their signature of the message.

Each Avalanche validator node has a BLS key that is registered on the P-Chain. Because all nodes validate the P-Chain, they know the BLS public keys of their peers and can verify that a significant number of validator has signed the message (using BLS multi-signatures). Each Subnet can have its own rules on what is the threshold to accept a message.

Warp messages in Subnet-EVM

🤓
For a more in-depth explanation of Avalanche Warp Messaging within the Subnet-EVM, see x/warp/README.md

As previously mentioned, each VM has its own way of encoding data within the Warp message Payload. Let’s see what it looks like in the Subnet-EVM!

WarpMessenger precompile

The WarpMessenger precompile is located at the address 0x0200000000000000000000000000000000000005 and exposes 3 functions (see IWarpMessenger.sol):

  • sendWarpMessage to send a Warp message from the current chain

  • getVerifiedWarpMessage to deserialize a Warp message that was sent from another chain and signed by its validator nodes

  • getBlockchainID to get the byte-32 encoded ID of the current chain

The precompile can be called by other smart contracts that might implement advanced logic on top of AWM. Ava Labs recently released Teleporter: an EVM cross-chain messaging protocol built on top of Avalanche Warp Messaging, that brings features like relayer incentives, replay protection, message delivery and execution retries, etc.

SendWarpMessage events

To ease the tracking of Warp messages, the WarpMessenger precompile emits an event log at each sendWarpMessage call. This event is composed of:

  • The destinationChainID: the blockchain ID on the Avalanche P-Chain that should receive the message

  • The destinationAddress: 32-byte value that represents the destination address that should receive the message (on the EVM this is the 20-byte address left zero-extended)

  • The sender: address that initiated the transaction

  • The event data: The whole underlying Warp message (as described above) that was written to the chain, including the NetworkID, SourceChainID, and the Payload (of the Warp message this time).

Subnet-EVM AddressedPayload

The actual data being sent to another Subnet-EVM chain is an AddressedPayload composed of the SourceAddress, the DestinationChainID, the DestinationAddress and the Payload: arbitrary ABI-encoded data.

This AddressedPayload will be the Payload of the Warp message.

Verified Warp Message

By combining the information from the Warp message itself (NetworkID, SourceChainID) and the AddressedPayload, the WarpMessenger precompile can deserialize “verified” messages on the destination chain and those can be used by other smart contracts. Those messages are defined in a Solidity struct:

struct WarpMessage {
    bytes32 originChainID;
    address originSenderAddress;
    bytes32 destinationChainID;
    address destinationAddress;
    bytes payload;
}

Avalanche Warp Navigator

The Ash team has been working on Avalanche Warp Navigator, a new feature of the Ash CLI that allows to monitor and decode Warp messages sent between Subnet-EVM chains!

The name of this feature is inspired by the Warhammer 40k lore:

A Navigator is a [...] Human mutant who possesses the Navigator Gene. This gives a Navigator the unique ability to navigate a faster-than-light starship accurately through [the Warp]. - Warhammer 40k Wiki

Ash CLI installation and configuration

To use Avalanche Warp Navigator, you need to install the Ash CLI in version 0.3.0-alpha. The easiest way to do that is to download it for your platform:

# Can be 'linux' or 'macos'
export OS=linux
# Can be 'amd64' or 'arm64'
export ARCH=amd64
# Download the binary archive
curl -sSfL "https://github.com/AshAvalanche/ash-rs/releases/download/v0.3.0-alpha/ash-${OS}-${ARCH}-v0.3.0-alpha.tar.gz" -o "ash-${OS}-${ARCH}-v0.3.0-alpha.tar.gz"
# Verify binary checksum
curl -sSfL "https://github.com/AshAvalanche/ash-rs/releases/download/v0.3.0-alpha/ash-${OS}-${ARCH}-v0.3.0-alpha.tar.gz.sha512" | sha512sum -c
# Extract the binary
tar -xzf "ash-${OS}-${ARCH}-v0.3.0-alpha.tar.gz"
# Make the binary executable
chmod +x ash
# /!\ You will probably need to whitelist the binaries on first use on MacOS /!\

After the download, test the CLI:

./ash avalanche subnet info 27FCSEqR5nE9pu255fqrJZZQDNt5Cg4P2B86ifD97KRunhMgic \
  --network fuji

We also need to configure the CLI to be able to query the Warpspace Subnet:

# Download the configuration file
curl -sSfL https://raw.githubusercontent.com/AshAvalanche/avalanche-warp-navigator/main/ash-conf/fuji.yml -o fuji.yml
# Make this configuration the default
export ASH_CONFIG=fuji.yml
export AVALANCHE_NETWORK=fuji

Warpspace Subnet

To demonstrate Avalanche Warp Navigator, the Ash team has deployed the Warpspace Subnet on Fuji with 2 Warp-enabled Subnet-EVM chains: HolyTerra (in ref. to Terra) and Fenris (in ref. to Fenris). Here is the Subnet information:

Subnet '27FCSEqR5nE9pu255fqrJZZQDNt5Cg4P2B86ifD97KRunhMgic':
  Type: Permissioned
  Control keys: ["P-fuji1eg9uk9nllt8a26s7ynnxkm32mx6t0pyln9tawg"]
  Threshold:    1
  Blockchains list (2):
  - 'HolyTerra':
    ID:      qgchaJrK1YzWZTYbQ4MCcoKUAgga1qU38odx7XA78iae8yQhr
    VM ID:   jvFWMths2qLjsZgbyEKx82PkQv2YWR4rotjQfxV55vLLogjNA
    VM type: SubnetEVM
    RPC URL: https://validator01.ash-test.center/ext/bc/qgchaJrK1YzWZTYbQ4MCcoKUAgga1qU38odx7XA78iae8yQhr/rpc
  - 'Fenris':
    ID:      2VDAzBtDc2Rgzfm3dfu9bjFrJX2b95zcKwBcN426x3wDTz8JeG
    VM ID:   jvFWMths2qLjsZgbyEKx82PkQv2YWR4rotjQfxV55vLLogjNA
    VM type: SubnetEVM
    RPC URL: https://validator01.ash-test.center/ext/bc/2VDAzBtDc2Rgzfm3dfu9bjFrJX2b95zcKwBcN426x3wDTz8JeG/rpc
  Validators list (5):
  - NodeID-FhFWdWodxktJYq884nrJjWD8faLTk9jmp
  - NodeID-QC741RWyWherFvfXhWfB2KttpJEHKxZDS
  - NodeID-23Rau2xyULqtEmCb3CsQa1WhqYK3zG8Z3
  - NodeID-PXmtxGdX1Aab5Rh1yZbeGbkaTVaqmgQvG
  - NodeID-74aTSN8C4dJj1cgwNoK6jMAt4uNhRWHf7

The chains are deployed using a custom build of the Subnet-EVM by the Ash team: Warp-enabled Subnet-EVM.

The HolyTerra chain has been provided with:

Monitor/decode Warp messages from HolyTerra

A handful of Warp messages have already been sent from the HolyTerra chain and we can see them with the Ash CLI:

./ash avalanche warp navigate HolyTerra

The output should look like:

Here you can see all the different data structures that we talked about in the first part of the article!

Going further

If you want to go further and create your own Warp messages on HolyTerra, go to the GitHub repository and follow Use Avalanche Warp Navigator on HolyTerra (Fuji)!

Wrapping up

In this article, I tried to share all the knowledge that I gathered while developing the Avalanche Warp Navigator feature. I hope this will save you some time in your journey navigating through the Warp! 🫡

What's next?

The new Teleporter protocol builds on top of AWM with extra data structures. We will enhance the Warp Navigator to be able to decode Teleporter messages to the deepest level!