github.com/MetalBlockchain/metalgo@v1.11.9/vms/example/xsvm/README.md (about) 1 # Cross Subnet Virtual Machine (XSVM) 2 3 Cross Subnet Asset Transfers README Overview 4 5 [Background](#avalanche-subnets-and-custom-vms) 6 7 [Introduction](#introduction) 8 9 [Usage](#how-it-works) 10 11 [Running](#running-the-vm) 12 13 [Demo](#cross-subnet-transaction-example) 14 15 ## Avalanche Subnets and Custom VMs 16 17 Avalanche is a network composed of multiple sub-networks (called [subnets][Subnet]) that each contain any number of blockchains. Each blockchain is an instance of a [Virtual Machine (VM)](https://docs.avax.network/learn/platform-overview#virtual-machines), 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)][Coreth] 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). 18 19 ## Introduction 20 21 Just as [Coreth] powers the [C-Chain], XSVM can be used to power its own blockchain in an Avalanche [Subnet]. 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 subnets. 22 23 ## How it Works 24 25 XSVM utilizes AvalancheGo's [teleporter] package to create and authenticate Subnet Messages. 26 27 ### Transfer 28 29 If you want to send an asset to someone, you can use a `tx.Transfer` to send to any address. 30 31 ### Export 32 33 If you want to send this chain's native asset to a different subnet, 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. 34 35 ### Import 36 37 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. 38 39 ### Fees 40 41 Currently there are no fees enforced in the XSVM. 42 43 ### xsvm 44 45 #### Install 46 47 ```bash 48 git clone https://github.com/ava-labs/avalanchego.git; 49 cd avalanchego; 50 go install -v ./vms/example/xsvm/cmd/xsvm; 51 ``` 52 53 #### Usage 54 55 ``` 56 Runs an XSVM plugin 57 58 Usage: 59 xsvm [flags] 60 xsvm [command] 61 62 Available Commands: 63 account Displays the state of the requested account 64 chain Manages XS chains 65 completion Generate the autocompletion script for the specified shell 66 help Help about any command 67 issue Issues transactions 68 version Prints out the version 69 70 Flags: 71 -h, --help help for xsvm 72 73 Use "xsvm [command] --help" for more information about a command. 74 ``` 75 76 ### [Golang SDK](https://github.com/ava-labs/avalanchego/blob/master/vms/example/xsvm/client/client.go) 77 78 ```golang 79 // Client defines xsvm client operations. 80 type Client interface { 81 Network( 82 ctx context.Context, 83 options ...rpc.Option, 84 ) (uint32, ids.ID, ids.ID, error) 85 Genesis( 86 ctx context.Context, 87 options ...rpc.Option, 88 ) (*genesis.Genesis, error) 89 Nonce( 90 ctx context.Context, 91 address ids.ShortID, 92 options ...rpc.Option, 93 ) (uint64, error) 94 Balance( 95 ctx context.Context, 96 address ids.ShortID, 97 assetID ids.ID, 98 options ...rpc.Option, 99 ) (uint64, error) 100 Loan( 101 ctx context.Context, 102 chainID ids.ID, 103 options ...rpc.Option, 104 ) (uint64, error) 105 IssueTx( 106 ctx context.Context, 107 tx *tx.Tx, 108 options ...rpc.Option, 109 ) (ids.ID, error) 110 LastAccepted( 111 ctx context.Context, 112 options ...rpc.Option, 113 ) (ids.ID, *block.Stateless, error) 114 Block( 115 ctx context.Context, 116 blkID ids.ID, 117 options ...rpc.Option, 118 (*block.Stateless, error) 119 Message( 120 ctx context.Context, 121 txID ids.ID, 122 options ...rpc.Option, 123 ) (*teleporter.UnsignedMessage, []byte, error) 124 } 125 ``` 126 127 ### Public Endpoints 128 129 #### xsvm.network 130 131 ``` 132 <<< POST 133 { 134 "jsonrpc": "2.0", 135 "method": "xsvm.network", 136 "params":{}, 137 "id": 1 138 } 139 >>> {"networkID":<uint32>, "subnetID":<ID>, "chainID":<ID>} 140 ``` 141 142 For example: 143 144 ```bash 145 curl --location --request POST 'http://34.235.54.228:9650/ext/bc/28iioW2fYMBnKv24VG5nw9ifY2PsFuwuhxhyzxZB5MmxDd3rnT' \ 146 --header 'Content-Type: application/json' \ 147 --data-raw '{ 148 "jsonrpc": "2.0", 149 "method": "xsvm.network", 150 "params":{}, 151 "id": 1 152 }' 153 ``` 154 155 > `{"jsonrpc":"2.0","result":{"networkID":1000000,"subnetID":"2gToFoYXURMQ6y4ZApFuRZN1HurGcDkwmtvkcMHNHcYarvsJN1","chainID":"28iioW2fYMBnKv24VG5nw9ifY2PsFuwuhxhyzxZB5MmxDd3rnT"},"id":1}` 156 157 #### xsvm.genesis 158 159 ``` 160 <<< POST 161 { 162 "jsonrpc": "2.0", 163 "method": "xsvm.genesis", 164 "params":{}, 165 "id": 1 166 } 167 >>> {"genesis":<genesis file>} 168 ``` 169 170 #### xsvm.nonce 171 172 ``` 173 <<< POST 174 { 175 "jsonrpc": "2.0", 176 "method": "xsvm.nonce", 177 "params":{ 178 "address":<cb58 encoded> 179 }, 180 "id": 1 181 } 182 >>> {"nonce":<uint64>} 183 ``` 184 185 #### xsvm.balance 186 187 ``` 188 <<< POST 189 { 190 "jsonrpc": "2.0", 191 "method": "xsvm.balance", 192 "params":{ 193 "address":<cb58 encoded>, 194 "assetID":<cb58 encoded> 195 }, 196 "id": 1 197 } 198 >>> {"balance":<uint64>} 199 ``` 200 201 #### xsvm.loan 202 203 ``` 204 <<< POST 205 { 206 "jsonrpc": "2.0", 207 "method": "xsvm.loan", 208 "params":{ 209 "chainID":<cb58 encoded> 210 }, 211 "id": 1 212 } 213 >>> {"amount":<uint64>} 214 ``` 215 216 #### xsvm.issueTx 217 218 ``` 219 <<< POST 220 { 221 "jsonrpc": "2.0", 222 "method": "xsvm.issueTx", 223 "params":{ 224 "tx":<bytes> 225 }, 226 "id": 1 227 } 228 >>> {"txID":<cb58 encoded>} 229 ``` 230 231 #### xsvm.lastAccepted 232 233 ``` 234 <<< POST 235 { 236 "jsonrpc": "2.0", 237 "method": "xsvm.lastAccepted", 238 "params":{}, 239 "id": 1 240 } 241 >>> {"blockID":<cb58 encoded>, "block":<json>} 242 ``` 243 244 #### xsvm.block 245 246 ``` 247 <<< POST 248 { 249 "jsonrpc": "2.0", 250 "method": "xsvm.block", 251 "params":{ 252 "blockID":<cb58 encoded> 253 }, 254 "id": 1 255 } 256 >>> {"block":<json>} 257 ``` 258 259 #### xsvm.message 260 261 ``` 262 <<< POST 263 { 264 "jsonrpc": "2.0", 265 "method": "xsvm.message", 266 "params":{ 267 "txID":<cb58 encoded> 268 }, 269 "id": 1 270 } 271 >>> {"message":<json>, "signature":<bytes>} 272 ``` 273 274 ## Running the VM 275 276 To build the VM, run `./scripts/build_xsvm.sh`. 277 278 ### Deploying Your Own Network 279 280 Anyone can deploy their own instance of the XSVM as a subnet on Avalanche. All you need to do is compile it, create a genesis, and send a few txs to the 281 P-Chain. 282 283 You can do this by following the [subnet tutorial] or by using the [subnet-cli]. 284 285 [teleporter]: https://github.com/ava-labs/avalanchego/tree/master/vms/platformvm/teleporter 286 [subnet tutorial]: https://docs.avax.network/build/tutorials/platform/subnets/create-a-subnet 287 [subnet-cli]: https://github.com/ava-labs/subnet-cli 288 [Coreth]: https://github.com/ava-labs/coreth 289 [C-Chain]: https://docs.avax.network/learn/platform-overview/#contract-chain-c-chain 290 [Subnet]: https://docs.avax.network/learn/platform-overview/#subnets 291 292 ## Cross Subnet Transaction Example 293 294 The following example shows how to interact with the XSVM to send and receive native assets across subnets. 295 296 ### Overview of Steps 297 298 1. Create & deploy Subnet A 299 2. Create & deploy Subnet B 300 3. Issue an **export** Tx on Subnet A 301 4. Issue an **import** Tx on Subnet B 302 5. Confirm Txs processed correctly 303 304 > **Note:** This demo requires [avalanche-cli](https://github.com/ava-labs/avalanche-cli) version > 1.0.5, [xsvm](https://github.com/ava-labs/xsvm) version > 1.0.2 and [avalanche-network-runner](https://github.com/ava-labs/avalanche-network-runner) v1.3.5. 305 306 ### Create and Deploy Subnet A, Subnet B 307 308 Using the avalanche-cli, this step deploys two subnets running the XSVM. Subnet A will act as the sender in this demo, and Subnet B will act as the receiver. 309 310 Steps 311 312 Build the [XSVM](https://github.com/ava-labs/xsvm) 313 314 ### Create a genesis file 315 316 ```bash 317 xsvm chain genesis --encoding binary > xsvm.genesis 318 ``` 319 320 ### Create Subnet A and Subnet B 321 322 ```bash 323 avalanche subnet create subnetA --custom --genesis <path_to_genesis> --vm <path_to_vm_binary> 324 avalanche subnet create subnetB --custom --genesis <path_to_genesis> --vm <path_to_vm_binary> 325 ``` 326 327 ### Deploy Subnet A and Subnet B 328 329 ```bash 330 avalanche subnet deploy subnetA --local 331 avalanche subnet deploy subnetB --local 332 ``` 333 334 ### Issue Export Tx from Subnet A 335 336 The SubnetID and ChainIDs are stored in the sidecar.json files in your avalanche-cli directory. Typically this is located at $HOME/.avalanche/subnets/ 337 338 ```bash 339 xsvm issue export --source-chain-id <SubnetA.BlockchainID> --amount <export_amount> --destination-chain-id <SubnetB.BlockchainID> 340 ``` 341 342 Save the TxID printed out by running the export command. 343 344 ### Issue Import Tx from Subnet B 345 346 > 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. 347 > Run `xsvm issue transfer --chain-id <SubnetB.BlockchainID> --amount 1000` to issue simple Txs on SubnetB 348 349 ```bash 350 xsvm issue import --source-chain-id <SubnetA.BlockchainID> --destination-chain-id <SubnetB.BlockchainID> --tx-id <exportTxID> --source-uris <source_uris> 351 ``` 352 353 > The <source_uris> can be found by running `avalanche network status`. The default URIs are 354 "http://localhost:9650,http://localhost:9652,http://localhost:9654,http://localhost:9656,http://localhost:9658" 355 356 **Account Values** 357 To check proper execution, use the `xsvm account` command to check balances. 358 359 Verify the balance on SubnetA decreased by your export amount using 360 361 ```bash 362 xsvm account --chain-id <SubnetA.BlockchainID> 363 ``` 364 365 Now verify chain A's assets were successfully imported to SubnetB 366 367 ```bash 368 xsvm account --chain-id <SubnetB.BlockchainID> --asset-id <SubnetA.BlockchainID> 369 ```