Cross Supernet Virtual Machine (XSVM)
Cross Supernet Asset Transfers README Overview
Background
Introduction
Usage
Running
Demo
Avalanche Supernets and Custom VMs
Avalanche is a network composed of multiple sub-networks (called supernets) that each contain any number of blockchains. Each blockchain is an instance of a Virtual Machine (VM), much like an object in an object-oriented language is an instance of a class. That is, the VM defines the behavior of the blockchain where it is instantiated. For example, Coreth (EVM) is a VM that is instantiated by the C-Chain. Likewise, one could deploy another instance of the EVM as their own blockchain (to take this to its logical conclusion).
Introduction
Just as Coreth powers the C-Chain, XSVM can be used to power its own blockchain in an Avalanche Supernet. Instead of providing a place to execute Solidity smart contracts, however, XSVM enables asset transfers for assets originating on its own chain or other XSVM chains on other supernets.
How it Works
XSVM utilizes AvalancheGo's teleporter package to create and authenticate Supernet Messages.
Transfer
If you want to send an asset to someone, you can use a tx.Transfer
to send to any address.
Export
If you want to send this chain's native asset to a different supernet, you can use a tx.Export
to send to any address on a destination chain. You may also use a tx.Export
to return the destination chain's native asset.
Import
To receive assets from another chain's tx.Export
, you must issue a tx.Import
. Note that, similarly to a bridge, the security of the other chain's native asset is tied to the other chain. The security of all other assets on this chain are unrelated to the other chain.
Fees
Currently there are no fees enforced in the XSVM.
xsvm
Install
git clone https://github.com/ava-labs/avalanchego.git;
cd avalanchego;
go install -v ./vms/example/xsvm/cmd/xsvm;
Usage
Runs an XSVM plugin
Usage:
xsvm [flags]
xsvm [command]
Available Commands:
account Displays the state of the requested account
chain Manages XS chains
completion Generate the autocompletion script for the specified shell
help Help about any command
issue Issues transactions
version Prints out the version
Flags:
-h, --help help for xsvm
Use "xsvm [command] --help" for more information about a command.
// Client defines xsvm client operations.
type Client interface {
Network(
ctx context.Context,
options ...rpc.Option,
) (uint32, ids.ID, ids.ID, error)
Genesis(
ctx context.Context,
options ...rpc.Option,
) (*genesis.Genesis, error)
Nonce(
ctx context.Context,
address ids.ShortID,
options ...rpc.Option,
) (uint64, error)
Balance(
ctx context.Context,
address ids.ShortID,
assetID ids.ID,
options ...rpc.Option,
) (uint64, error)
Loan(
ctx context.Context,
chainID ids.ID,
options ...rpc.Option,
) (uint64, error)
IssueTx(
ctx context.Context,
tx *tx.Tx,
options ...rpc.Option,
) (ids.ID, error)
LastAccepted(
ctx context.Context,
options ...rpc.Option,
) (ids.ID, *block.Stateless, error)
Block(
ctx context.Context,
blkID ids.ID,
options ...rpc.Option,
(*block.Stateless, error)
Message(
ctx context.Context,
txID ids.ID,
options ...rpc.Option,
) (*teleporter.UnsignedMessage, []byte, error)
}
Public Endpoints
xsvm.network
<<< POST
{
"jsonrpc": "2.0",
"method": "xsvm.network",
"params":{},
"id": 1
}
>>> {"networkID":<uint32>, "supernetID":<ID>, "chainID":<ID>}
For example:
curl --location --request POST 'http://34.235.54.228:9650/ext/bc/28iioW2fYMBnKv24VG5nw9ifY2PsFuwuhxhyzxZB5MmxDd3rnT' \
--header 'Content-Type: application/json' \
--data-raw '{
"jsonrpc": "2.0",
"method": "xsvm.network",
"params":{},
"id": 1
}'
{"jsonrpc":"2.0","result":{"networkID":1000000,"supernetID":"2gToFoYXURMQ6y4ZApFuRZN1HurGcDkwmtvkcMHNHcYarvsJN1","chainID":"28iioW2fYMBnKv24VG5nw9ifY2PsFuwuhxhyzxZB5MmxDd3rnT"},"id":1}
xsvm.genesis
<<< POST
{
"jsonrpc": "2.0",
"method": "xsvm.genesis",
"params":{},
"id": 1
}
>>> {"genesis":<genesis file>}
xsvm.nonce
<<< POST
{
"jsonrpc": "2.0",
"method": "xsvm.nonce",
"params":{
"address":<cb58 encoded>
},
"id": 1
}
>>> {"nonce":<uint64>}
xsvm.balance
<<< POST
{
"jsonrpc": "2.0",
"method": "xsvm.balance",
"params":{
"address":<cb58 encoded>,
"assetID":<cb58 encoded>
},
"id": 1
}
>>> {"balance":<uint64>}
xsvm.loan
<<< POST
{
"jsonrpc": "2.0",
"method": "xsvm.loan",
"params":{
"chainID":<cb58 encoded>
},
"id": 1
}
>>> {"amount":<uint64>}
xsvm.issueTx
<<< POST
{
"jsonrpc": "2.0",
"method": "xsvm.issueTx",
"params":{
"tx":<bytes>
},
"id": 1
}
>>> {"txID":<cb58 encoded>}
xsvm.lastAccepted
<<< POST
{
"jsonrpc": "2.0",
"method": "xsvm.lastAccepted",
"params":{},
"id": 1
}
>>> {"blockID":<cb58 encoded>, "block":<json>}
xsvm.block
<<< POST
{
"jsonrpc": "2.0",
"method": "xsvm.block",
"params":{
"blockID":<cb58 encoded>
},
"id": 1
}
>>> {"block":<json>}
xsvm.message
<<< POST
{
"jsonrpc": "2.0",
"method": "xsvm.message",
"params":{
"txID":<cb58 encoded>
},
"id": 1
}
>>> {"message":<json>, "signature":<bytes>}
Running the VM
To build the VM, run ./scripts/build_xsvm.sh
.
Deploying Your Own Network
Anyone can deploy their own instance of the XSVM as a supernet on Avalanche. All you need to do is compile it, create a genesis, and send a few txs to the
P-Chain.
You can do this by following the supernet tutorial or by using the supernet-cli.
Cross Supernet Transaction Example
The following example shows how to interact with the XSVM to send and receive native assets across supernets.
Overview of Steps
- Create & deploy Supernet A
- Create & deploy Supernet B
- Issue an export Tx on Supernet A
- Issue an import Tx on Supernet B
- Confirm Txs processed correctly
Note: This demo requires avalanche-cli version > 1.0.5, xsvm version > 1.0.2 and avalanche-network-runner v1.3.5.
Create and Deploy Supernet A, Supernet B
Using the avalanche-cli, this step deploys two supernets running the XSVM. Supernet A will act as the sender in this demo, and Supernet B will act as the receiver.
Steps
Build the XSVM
Create a genesis file
xsvm chain genesis --encoding binary > xsvm.genesis
Create Supernet A and Supernet B
avalanche supernet create supernetA --custom --genesis <path_to_genesis> --vm <path_to_vm_binary>
avalanche supernet create supernetB --custom --genesis <path_to_genesis> --vm <path_to_vm_binary>
Deploy Supernet A and Supernet B
avalanche supernet deploy supernetA --local
avalanche supernet deploy supernetB --local
Issue Export Tx from Supernet A
The SupernetID and ChainIDs are stored in the sidecar.json files in your avalanche-cli directory. Typically this is located at $HOME/.avalanche/supernets/
xsvm issue export --source-chain-id <SupernetA.BlockchainID> --amount <export_amount> --destination-chain-id <SupernetB.BlockchainID>
Save the TxID printed out by running the export command.
Issue Import Tx from Supernet B
Note: The import tx requires snowman++ consensus to be activated on the importing chain. A chain requires ~3 blocks to be produced for snowman++ to start.
Run xsvm issue transfer --chain-id <SupernetB.BlockchainID> --amount 1000
to issue simple Txs on SupernetB
xsvm issue import --source-chain-id <SupernetA.BlockchainID> --destination-chain-id <SupernetB.BlockchainID> --tx-id <exportTxID> --source-uris <source_uris>
The <source_uris> can be found by running avalanche network status
. The default URIs are
"http://localhost:9650,http://localhost:9652,http://localhost:9654,http://localhost:9656,http://localhost:9658"
Account Values
To check proper execution, use the xsvm account
command to check balances.
Verify the balance on SupernetA decreased by your export amount using
xsvm account --chain-id <SupernetA.BlockchainID>
Now verify chain A's assets were successfully imported to SupernetB
xsvm account --chain-id <SupernetB.BlockchainID> --asset-id <SupernetA.BlockchainID>