AVM Transaction Format
This file is meant to be the single source of truth for how we serialize transactions in the Avalanche Virtual Machine (AVM). This document uses the primitive serialization format for packing and secp256k1 for cryptographic user identification.
Codec ID
Some data is prepended with a codec ID (unt16) that denotes how the data should be deserialized. Right now, the only valid codec ID is 0 (0x00 0x00
).
Transferable Output
Transferable outputs wrap an output with an asset ID.
What Transferable Output Contains
A transferable output contains an AssetID
and an Output
.
AssetID
is a 32-byte array that defines which asset this output references.Output
is an output, as defined below. For example, this can be a SECP256K1 transfer output.
Gantt Transferable Output Specification
+----------+----------+-------------------------+
| asset_id : [32]byte | 32 bytes |
+----------+----------+-------------------------+
| output : Output | size(output) bytes |
+----------+----------+-------------------------+
| 32 + size(output) bytes |
+-------------------------+
Proto Transferable Output Specification
message TransferableOutput {
bytes asset_id = 1; // 32 bytes
Output output = 2; // size(output)
}
Transferable Output Example
Let’s make a transferable output:
AssetID
:0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
Output
:"Example SECP256K1 Transfer Output from below"
[
AssetID <- 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
Output <- 0x000000070000000000003039000000000000d431000000010000000251025c61fbcfc078f69334f834be6dd26d55a955c3344128e060128ede3523a24a461c8943ab0859,
]
=
[
// assetID:
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
// output:
0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x30, 0x39, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xd4, 0x31, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x02, 0x51, 0x02, 0x5c, 0x61,
0xfb, 0xcf, 0xc0, 0x78, 0xf6, 0x93, 0x34, 0xf8,
0x34, 0xbe, 0x6d, 0xd2, 0x6d, 0x55, 0xa9, 0x55,
0xc3, 0x34, 0x41, 0x28, 0xe0, 0x60, 0x12, 0x8e,
0xde, 0x35, 0x23, 0xa2, 0x4a, 0x46, 0x1c, 0x89,
0x43, 0xab, 0x08, 0x59,
]
Transferable Input
Transferable inputs describe a specific UTXO with a provided transfer input.
What Transferable Input Contains
A transferable input contains a TxID
, UTXOIndex
AssetID
and an Input
.
TxID
is a 32-byte array that defines which transaction this input is consuming an output from. Transaction IDs are calculated by taking sha256 of the bytes of the signed transaction.UTXOIndex
is an int that defines which utxo this input is consuming in the specified transaction.AssetID
is a 32-byte array that defines which asset this input references.Input
is an input, as defined below. This can currently only be a SECP256K1 transfer input
Gantt Transferable Input Specification
+------------+----------+------------------------+
| tx_id : [32]byte | 32 bytes |
+------------+----------+------------------------+
| utxo_index : int | 04 bytes |
+------------+----------+------------------------+
| asset_id : [32]byte | 32 bytes |
+------------+----------+------------------------+
| input : Input | size(input) bytes |
+------------+----------+------------------------+
| 68 + size(input) bytes |
+------------------------+
Proto Transferable Input Specification
message TransferableInput {
bytes tx_id = 1; // 32 bytes
uint32 utxo_index = 2; // 04 bytes
bytes asset_id = 3; // 32 bytes
Input input = 4; // size(input)
}
Transferable Input Example
Let’s make a transferable input:
TxID
:0xf1e1d1c1b1a191817161514131211101f0e0d0c0b0a090807060504030201000
UTXOIndex
:5
AssetID
:0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
Input
:"Example SECP256K1 Transfer Input from below"
[
TxID <- 0xf1e1d1c1b1a191817161514131211101f0e0d0c0b0a090807060504030201000
UTXOIndex <- 0x00000005
AssetID <- 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
Input <- 0x0000000500000000075bcd15000000020000000700000003
]
=
[
// txID:
0xf1, 0xe1, 0xd1, 0xc1, 0xb1, 0xa1, 0x91, 0x81,
0x71, 0x61, 0x51, 0x41, 0x31, 0x21, 0x11, 0x01,
0xf0, 0xe0, 0xd0, 0xc0, 0xb0, 0xa0, 0x90, 0x80,
0x70, 0x60, 0x50, 0x40, 0x30, 0x20, 0x10, 0x00,
// utxoIndex:
0x00, 0x00, 0x00, 0x05,
// assetID:
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
// input:
0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00,
0x07, 0x5b, 0xcd, 0x15, 0x00, 0x00, 0x00, 0x02,
0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07
]
Transferable Op
Transferable operations describe a set of UTXOs with a provided transfer operation. Only one Asset ID is able to be referenced per operation.
What Transferable Op Contains
A transferable operation contains an AssetID
, UTXOIDs
, and a TransferOp
.
AssetID
is a 32-byte array that defines which asset this operation changes.UTXOIDs
is an array of TxID-OutputIndex tuples. This array must be sorted in lexicographical order.TransferOp
is a transferable operation object.
Gantt Transferable Op Specification
+-------------+------------+------------------------------+
| asset_id : [32]byte | 32 bytes |
+-------------+------------+------------------------------+
| utxo_ids : []UTXOID | 4 + 36 * len(utxo_ids) bytes |
+-------------+------------+------------------------------+
| transfer_op : TransferOp | size(transfer_op) bytes |
+-------------+------------+------------------------------+
| 36 + 36 * len(utxo_ids) |
| + size(transfer_op) bytes |
+------------------------------+
Proto Transferable Op Specification
message UTXOID {
bytes tx_id = 1; // 32 bytes
uint32 utxo_index = 2; // 04 bytes
}
message TransferableOp {
bytes asset_id = 1; // 32 bytes
repeated UTXOID utxo_ids = 2; // 4 + 36 * len(utxo_ids) bytes
TransferOp transfer_op = 3; // size(transfer_op)
}
Transferable Op Example
Let’s make a transferable operation:
AssetID
:0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
UTXOIDs
:UTXOID
:TxID
:0xf1e1d1c1b1a191817161514131211101f0e0d0c0b0a090807060504030201000
UTXOIndex
:5
Op
:"Example Transfer Op from below"
[
AssetID <- 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
UTXOIDs <- [
{
TxID:0xf1e1d1c1b1a191817161514131211101f0e0d0c0b0a090807060504030201000
UTXOIndex:5
}
]
Op <- 0x0000000d0000000200000003000000070000303900000003431100000000010000000251025c61fbcfc078f69334f834be6dd26d55a955c3344128e060128ede3523a24a461c8943ab0859
]
=
[
// assetID:
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
// number of utxoIDs:
0x00, 0x00, 0x00, 0x01,
// txID:
0xf1, 0xe1, 0xd1, 0xc1, 0xb1, 0xa1, 0x91, 0x81,
0x71, 0x61, 0x51, 0x41, 0x31, 0x21, 0x11, 0x01,
0xf0, 0xe0, 0xd0, 0xc0, 0xb0, 0xa0, 0x90, 0x80,
0x70, 0x60, 0x50, 0x40, 0x30, 0x20, 0x10, 0x00,
// utxoIndex:
0x00, 0x00, 0x00, 0x05,
// op:
0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x02,
0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07,
0x00, 0x00, 0x30, 0x39, 0x00, 0x00, 0x00, 0x03,
0x43, 0x11, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
0x00, 0x00, 0x02, 0x51, 0x02, 0x5c, 0x61, 0xfb,
0xcf, 0xc0, 0x78, 0xf6, 0x93, 0x34, 0xf8, 0x34,
0xbe, 0x6d, 0xd2, 0x6d, 0x55, 0xa9, 0x55, 0xc3,
0x34, 0x41, 0x28, 0xe0, 0x60, 0x12, 0x8e, 0xde,
0x35, 0x23, 0xa2, 0x4a, 0x46, 0x1c, 0x89, 0x43,
0xab, 0x08, 0x59,
]
Outputs
Outputs have four possible types: SECP256K1TransferOutput
, SECP256K1MintOutput
, NFTTransferOutput
and NFTMintOutput
.
SECP256K1 Transfer Output
A secp256k1 transfer output allows for sending a quantity of an asset to a collection of addresses after a specified unix time.
What SECP256K1 Transfer Output Contains
A secp256k1 transfer output contains a TypeID
, Amount
, Locktime
, Threshold
, and Addresses
.
TypeID
is the ID for this output type. It is0x00000007
.Amount
is a long that specifies the quantity of the asset that this output owns. Must be positive.Locktime
is a long that contains the unix timestamp that this output can be spent after. The unix timestamp is specific to the second.Threshold
is an int that names the number of unique signatures required to spend the output. Must be less than or equal to the length ofAddresses
. IfAddresses
is empty, must be 0.Addresses
is a list of unique addresses that correspond to the private keys that can be used to spend this output. Addresses must be sorted lexicographically.
Gantt SECP256K1 Transfer Output Specification
+-----------+------------+--------------------------------+
| type_id : int | 4 bytes |
+-----------+------------+--------------------------------+
| amount : long | 8 bytes |
+-----------+------------+--------------------------------+
| locktime : long | 8 bytes |
+-----------+------------+--------------------------------+
| threshold : int | 4 bytes |
+-----------+------------+--------------------------------+
| addresses : [][20]byte | 4 + 20 * len(addresses) bytes |
+-----------+------------+--------------------------------+
| 28 + 20 * len(addresses) bytes |
+--------------------------------+
Proto SECP256K1 Transfer Output Specification
message SECP256K1TransferOutput {
uint32 typeID = 1; // 04 bytes
uint64 amount = 2; // 08 bytes
uint64 locktime = 3; // 08 bytes
uint32 threshold = 4; // 04 bytes
repeated bytes addresses = 5; // 04 bytes + 20 bytes * len(addresses)
}
SECP256K1 Transfer Output Example
Let’s make a secp256k1 transfer output with:
TypeID
:7
Amount
:12345
Locktime
:54321
Threshold
:1
Addresses
:0x51025c61fbcfc078f69334f834be6dd26d55a955
0xc3344128e060128ede3523a24a461c8943ab0859
[
TypeID <- 0x00000007
Amount <- 0x0000000000003039
Locktime <- 0x000000000000d431
Threshold <- 0x00000001
Addresses <- [
0x51025c61fbcfc078f69334f834be6dd26d55a955,
0xc3344128e060128ede3523a24a461c8943ab0859,
]
]
=
[
// typeID:
0x00, 0x00, 0x00, 0x07,
// amount:
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x39,
// locktime:
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x31,
// threshold:
0x00, 0x00, 0x00, 0x01,
// number of addresses:
0x00, 0x00, 0x00, 0x02,
// addrs[0]:
0x51, 0x02, 0x5c, 0x61, 0xfb, 0xcf, 0xc0, 0x78,
0xf6, 0x93, 0x34, 0xf8, 0x34, 0xbe, 0x6d, 0xd2,
0x6d, 0x55, 0xa9, 0x55,
// addrs[1]:
0xc3, 0x34, 0x41, 0x28, 0xe0, 0x60, 0x12, 0x8e,
0xde, 0x35, 0x23, 0xa2, 0x4a, 0x46, 0x1c, 0x89,
0x43, 0xab, 0x08, 0x59,
]
SECP256K1 Mint Output
A secp256k1 mint output is an output that is owned by a collection of addresses.
What SECP256K1 Mint Output Contains
A secp256k1 Mint output contains a TypeID
, Locktime
, Threshold
, and Addresses
.
TypeID
is the ID for this output type. It is0x00000006
.Locktime
is a long that contains the unix timestamp that this output can be spent after. The unix timestamp is specific to the second.Threshold
is an int that names the number of unique signatures required to spend the output. Must be less than or equal to the length ofAddresses
. IfAddresses
is empty, must be 0.Addresses
is a list of unique addresses that correspond to the private keys that can be used to spend this output. Addresses must be sorted lexicographically.
Gantt SECP256K1 Mint Output Specification
+-----------+------------+--------------------------------+
| type_id : int | 4 bytes |
+-----------+------------+--------------------------------+
| locktime : long | 8 bytes |
+-----------+------------+--------------------------------+
| threshold : int | 4 bytes |
+-----------+------------+--------------------------------+
| addresses : [][20]byte | 4 + 20 * len(addresses) bytes |
+-----------+------------+--------------------------------+
| 20 + 20 * len(addresses) bytes |
+--------------------------------+
Proto SECP256K1 Mint Output Specification
message SECP256K1MintOutput {
uint32 typeID = 1; // 04 bytes
uint64 locktime = 2; // 08 bytes
uint32 threshold = 3; // 04 bytes
repeated bytes addresses = 4; // 04 bytes + 20 bytes * len(addresses)
}
SECP256K1 Mint Output Example
Let’s make a SECP256K1 mint output with:
TypeID
:6
Locktime
:54321
Threshold
:1
Addresses
:0x51025c61fbcfc078f69334f834be6dd26d55a955
0xc3344128e060128ede3523a24a461c8943ab0859
[
TypeID <- 0x00000006
Locktime <- 0x000000000000d431
Threshold <- 0x00000001
Addresses <- [
0x51025c61fbcfc078f69334f834be6dd26d55a955,
0xc3344128e060128ede3523a24a461c8943ab0859,
]
]
=
[
// typeID:
0x00, 0x00, 0x00, 0x06,
// locktime:
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x31,
// threshold:
0x00, 0x00, 0x00, 0x01,
// number of addresses:
0x00, 0x00, 0x00, 0x02,
// addrs[0]:
0x51, 0x02, 0x5c, 0x61, 0xfb, 0xcf, 0xc0, 0x78,
0xf6, 0x93, 0x34, 0xf8, 0x34, 0xbe, 0x6d, 0xd2,
0x6d, 0x55, 0xa9, 0x55,
// addrs[1]:
0xc3, 0x34, 0x41, 0x28, 0xe0, 0x60, 0x12, 0x8e,
0xde, 0x35, 0x23, 0xa2, 0x4a, 0x46, 0x1c, 0x89,
0x43, 0xab, 0x08, 0x59,
]
NFT Transfer Output
An NFT transfer output is an NFT that is owned by a collection of addresses.
What NFT Transfer Output Contains
An NFT transfer output contains a TypeID
, GroupID
, Payload
, Locktime
, Threshold
, and Addresses
.
TypeID
is the ID for this output type. It is0x0000000b
.GroupID
is an int that specifies the group this NFT was issued with.Payload
is an arbitrary string of bytes no long longer than 1024 bytes.Locktime
is a long that contains the unix timestamp that this output can be spent after. The unix timestamp is specific to the second.Threshold
is an int that names the number of unique signatures required to spend the output. Must be less than or equal to the length ofAddresses
. IfAddresses
is empty, must be 0.Addresses
is a list of unique addresses that correspond to the private keys that can be used to spend this output. Addresses must be sorted lexicographically.
Gantt NFT Transfer Output Specification
+-----------+------------+-------------------------------+
| type_id : int | 4 bytes |
+-----------+------------+-------------------------------+
| group_id : int | 4 bytes |
+-----------+------------+-------------------------------+
| payload : []byte | 4 + len(payload) bytes |
+-----------+------------+-------------------------------+
| locktime : long | 8 bytes |
+-----------+------------+-------------------------------+
| threshold : int | 4 bytes |
+-----------+------------+-------------------------------+
| addresses : [][20]byte | 4 + 20 * len(addresses) bytes |
+-----------+------------+-------------------------------+
| 28 + len(payload) |
| + 20 * len(addresses) bytes |
+-------------------------------+
Proto NFT Transfer Output Specification
message NFTTransferOutput {
uint32 typeID = 1; // 04 bytes
uint32 group_id = 2; // 04 bytes
bytes payload = 3; // 04 bytes + len(payload)
uint64 locktime = 4 // 08 bytes
uint32 threshold = 5; // 04 bytes
repeated bytes addresses = 6; // 04 bytes + 20 bytes * len(addresses)
}
NFT Transfer Output Example
Let’s make an NFT transfer output with:
TypeID
:11
GroupID
:12345
Payload
:0x431100
Locktime
:54321
Threshold
:1
Addresses
:0x51025c61fbcfc078f69334f834be6dd26d55a955
0xc3344128e060128ede3523a24a461c8943ab0859
[
TypeID <- 0x0000000b
GroupID <- 0x00003039
Payload <- 0x431100
Locktime <- 0x000000000000d431
Threshold <- 0x00000001
Addresses <- [
0x51025c61fbcfc078f69334f834be6dd26d55a955,
0xc3344128e060128ede3523a24a461c8943ab0859,
]
]
=
[
// TypeID:
0x00, 0x00, 0x00, 0x0b,
// groupID:
0x00, 0x00, 0x30, 0x39,
// length of payload:
0x00, 0x00, 0x00, 0x03,
// payload:
0x43, 0x11, 0x00,
// locktime:
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x31,
// threshold:
0x00, 0x00, 0x00, 0x01,
// number of addresses:
0x00, 0x00, 0x00, 0x02,
// addrs[0]:
0x51, 0x02, 0x5c, 0x61, 0xfb, 0xcf, 0xc0, 0x78,
0xf6, 0x93, 0x34, 0xf8, 0x34, 0xbe, 0x6d, 0xd2,
0x6d, 0x55, 0xa9, 0x55,
// addrs[1]:
0xc3, 0x34, 0x41, 0x28, 0xe0, 0x60, 0x12, 0x8e,
0xde, 0x35, 0x23, 0xa2, 0x4a, 0x46, 0x1c, 0x89,
0x43, 0xab, 0x08, 0x59,
]
NFT Mint Output
An NFT mint output is an NFT that is owned by a collection of addresses.
What NFT Mint Output Contains
An NFT Mint output contains a TypeID
, GroupID
, Locktime
, Threshold
, and Addresses
.
TypeID
is the ID for this output type. It is0x0000000a
.GroupID
is an int that specifies the group this NFT is issued to.Locktime
is a long that contains the unix timestamp that this output can be spent after. The unix timestamp is specific to the second.Threshold
is an int that names the number of unique signatures required to spend the output. Must be less than or equal to the length ofAddresses
. IfAddresses
is empty, must be 0.Addresses
is a list of unique addresses that correspond to the private keys that can be used to spend this output. Addresses must be sorted lexicographically.
Gantt NFT Mint Output Specification
+-----------+------------+--------------------------------+
| type_id : int | 4 bytes |
+-----------+------------+--------------------------------+
| group_id : int | 4 bytes |
+-----------+------------+--------------------------------+
| locktime : long | 8 bytes |
+-----------+------------+--------------------------------+
| threshold : int | 4 bytes |
+-----------+------------+--------------------------------+
| addresses : [][20]byte | 4 + 20 * len(addresses) bytes |
+-----------+------------+--------------------------------+
| 24 + 20 * len(addresses) bytes |
+--------------------------------+
Proto NFT Mint Output Specification
message NFTMintOutput {
uint32 typeID = 1; // 04 bytes
uint32 group_id = 2; // 04 bytes
uint64 locktime = 3; // 08 bytes
uint32 threshold = 4; // 04 bytes
repeated bytes addresses = 5; // 04 bytes + 20 bytes * len(addresses)
}
NFT Mint Output Example
Let’s make an NFT mint output with:
TypeID
:10
GroupID
:12345
Locktime
:54321
Threshold
:1
Addresses
:0x51025c61fbcfc078f69334f834be6dd26d55a955
0xc3344128e060128ede3523a24a461c8943ab0859
[
TypeID <- 0x0000000a
GroupID <- 0x00003039
Locktime <- 0x000000000000d431
Threshold <- 0x00000001
Addresses <- [
0x51025c61fbcfc078f69334f834be6dd26d55a955,
0xc3344128e060128ede3523a24a461c8943ab0859,
]
]
=
[
// TypeID
0x00, 0x00, 0x00, 0x0a,
// groupID:
0x00, 0x00, 0x30, 0x39,
// locktime:
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x31,
// threshold:
0x00, 0x00, 0x00, 0x01,
// number of addresses:
0x00, 0x00, 0x00, 0x02,
// addrs[0]:
0x51, 0x02, 0x5c, 0x61, 0xfb, 0xcf, 0xc0, 0x78,
0xf6, 0x93, 0x34, 0xf8, 0x34, 0xbe, 0x6d, 0xd2,
0x6d, 0x55, 0xa9, 0x55,
// addrs[1]:
0xc3, 0x34, 0x41, 0x28, 0xe0, 0x60, 0x12, 0x8e,
0xde, 0x35, 0x23, 0xa2, 0x4a, 0x46, 0x1c, 0x89,
0x43, 0xab, 0x08, 0x59,
]