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

1
+----------+----------+-------------------------+
2
| asset_id : [32]byte | 32 bytes |
3
+----------+----------+-------------------------+
4
| output : Output | size(output) bytes |
5
+----------+----------+-------------------------+
6
| 32 + size(output) bytes |
7
+-------------------------+
Copied!

Proto Transferable Output Specification

1
message TransferableOutput {
2
bytes asset_id = 1; // 32 bytes
3
Output output = 2; // size(output)
4
}
Copied!

Transferable Output Example

Let’s make a transferable output:
    AssetID: 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
    Output: "Example SECP256K1 Transfer Output from below"
1
[
2
AssetID <- 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
3
Output <- 0x000000070000000000003039000000000000d431000000010000000251025c61fbcfc078f69334f834be6dd26d55a955c3344128e060128ede3523a24a461c8943ab0859,
4
]
5
=
6
[
7
// assetID:
8
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
9
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
10
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
11
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
12
// output:
13
0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00,
14
0x00, 0x00, 0x30, 0x39, 0x00, 0x00, 0x00, 0x00,
15
0x00, 0x00, 0xd4, 0x31, 0x00, 0x00, 0x00, 0x01,
16
0x00, 0x00, 0x00, 0x02, 0x51, 0x02, 0x5c, 0x61,
17
0xfb, 0xcf, 0xc0, 0x78, 0xf6, 0x93, 0x34, 0xf8,
18
0x34, 0xbe, 0x6d, 0xd2, 0x6d, 0x55, 0xa9, 0x55,
19
0xc3, 0x34, 0x41, 0x28, 0xe0, 0x60, 0x12, 0x8e,
20
0xde, 0x35, 0x23, 0xa2, 0x4a, 0x46, 0x1c, 0x89,
21
0x43, 0xab, 0x08, 0x59,
22
]
Copied!

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

1
+------------+----------+------------------------+
2
| tx_id : [32]byte | 32 bytes |
3
+------------+----------+------------------------+
4
| utxo_index : int | 04 bytes |
5
+------------+----------+------------------------+
6
| asset_id : [32]byte | 32 bytes |
7
+------------+----------+------------------------+
8
| input : Input | size(input) bytes |
9
+------------+----------+------------------------+
10
| 68 + size(input) bytes |
11
+------------------------+
Copied!

Proto Transferable Input Specification

1
message TransferableInput {
2
bytes tx_id = 1; // 32 bytes
3
uint32 utxo_index = 2; // 04 bytes
4
bytes asset_id = 3; // 32 bytes
5
Input input = 4; // size(input)
6
}
Copied!

Transferable Input Example

Let’s make a transferable input:
    TxID: 0xf1e1d1c1b1a191817161514131211101f0e0d0c0b0a090807060504030201000
    UTXOIndex: 5
    AssetID: 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
    Input: "Example SECP256K1 Transfer Input from below"
1
[
2
TxID <- 0xf1e1d1c1b1a191817161514131211101f0e0d0c0b0a090807060504030201000
3
UTXOIndex <- 0x00000005
4
AssetID <- 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
5
Input <- 0x0000000500000000075bcd15000000020000000700000003
6
]
7
=
8
[
9
// txID:
10
0xf1, 0xe1, 0xd1, 0xc1, 0xb1, 0xa1, 0x91, 0x81,
11
0x71, 0x61, 0x51, 0x41, 0x31, 0x21, 0x11, 0x01,
12
0xf0, 0xe0, 0xd0, 0xc0, 0xb0, 0xa0, 0x90, 0x80,
13
0x70, 0x60, 0x50, 0x40, 0x30, 0x20, 0x10, 0x00,
14
// utxoIndex:
15
0x00, 0x00, 0x00, 0x05,
16
// assetID:
17
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
18
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
19
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
20
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
21
// input:
22
0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00,
23
0x07, 0x5b, 0xcd, 0x15, 0x00, 0x00, 0x00, 0x02,
24
0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07
25
]
Copied!

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.

Gantt Transferable Op Specification

1
+-------------+------------+------------------------------+
2
| asset_id : [32]byte | 32 bytes |
3
+-------------+------------+------------------------------+
4
| utxo_ids : []UTXOID | 4 + 36 * len(utxo_ids) bytes |
5
+-------------+------------+------------------------------+
6
| transfer_op : TransferOp | size(transfer_op) bytes |
7
+-------------+------------+------------------------------+
8
| 36 + 36 * len(utxo_ids) |
9
| + size(transfer_op) bytes |
10
+------------------------------+
Copied!

Proto Transferable Op Specification

1
message UTXOID {
2
bytes tx_id = 1; // 32 bytes
3
uint32 utxo_index = 2; // 04 bytes
4
}
5
message TransferableOp {
6
bytes asset_id = 1; // 32 bytes
7
repeated UTXOID utxo_ids = 2; // 4 + 36 * len(utxo_ids) bytes
8
TransferOp transfer_op = 3; // size(transfer_op)
9
}
Copied!

Transferable Op Example

Let’s make a transferable operation:
    AssetID: 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
    UTXOIDs:
      UTXOID:
        TxID: 0xf1e1d1c1b1a191817161514131211101f0e0d0c0b0a090807060504030201000
        UTXOIndex: 5
    Op: "Example Transfer Op from below"
1
[
2
AssetID <- 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
3
UTXOIDs <- [
4
{
5
TxID:0xf1e1d1c1b1a191817161514131211101f0e0d0c0b0a090807060504030201000
6
UTXOIndex:5
7
}
8
]
9
Op <- 0x0000000d0000000200000003000000070000303900000003431100000000010000000251025c61fbcfc078f69334f834be6dd26d55a955c3344128e060128ede3523a24a461c8943ab0859
10
]
11
=
12
[
13
// assetID:
14
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
15
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
16
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
17
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
18
// number of utxoIDs:
19
0x00, 0x00, 0x00, 0x01,
20
// txID:
21
0xf1, 0xe1, 0xd1, 0xc1, 0xb1, 0xa1, 0x91, 0x81,
22
0x71, 0x61, 0x51, 0x41, 0x31, 0x21, 0x11, 0x01,
23
0xf0, 0xe0, 0xd0, 0xc0, 0xb0, 0xa0, 0x90, 0x80,
24
0x70, 0x60, 0x50, 0x40, 0x30, 0x20, 0x10, 0x00,
25
// utxoIndex:
26
0x00, 0x00, 0x00, 0x05,
27
// op:
28
0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x02,
29
0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07,
30
0x00, 0x00, 0x30, 0x39, 0x00, 0x00, 0x00, 0x03,
31
0x43, 0x11, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
32
0x00, 0x00, 0x02, 0x51, 0x02, 0x5c, 0x61, 0xfb,
33
0xcf, 0xc0, 0x78, 0xf6, 0x93, 0x34, 0xf8, 0x34,
34
0xbe, 0x6d, 0xd2, 0x6d, 0x55, 0xa9, 0x55, 0xc3,
35
0x34, 0x41, 0x28, 0xe0, 0x60, 0x12, 0x8e, 0xde,
36
0x35, 0x23, 0xa2, 0x4a, 0x46, 0x1c, 0x89, 0x43,
37
0xab, 0x08, 0x59,
38
]
Copied!

Outputs

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 is 0x00000007.
    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 of Addresses. If Addresses 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

1
+-----------+------------+--------------------------------+
2
| type_id : int | 4 bytes |
3
+-----------+------------+--------------------------------+
4
| amount : long | 8 bytes |
5
+-----------+------------+--------------------------------+
6
| locktime : long | 8 bytes |
7
+-----------+------------+--------------------------------+
8
| threshold : int | 4 bytes |
9
+-----------+------------+--------------------------------+
10
| addresses : [][20]byte | 4 + 20 * len(addresses) bytes |
11
+-----------+------------+--------------------------------+
12
| 28 + 20 * len(addresses) bytes |
13
+--------------------------------+
Copied!

Proto SECP256K1 Transfer Output Specification

1
message SECP256K1TransferOutput {
2
uint32 typeID = 1; // 04 bytes
3
uint64 amount = 2; // 08 bytes
4
uint64 locktime = 3; // 08 bytes
5
uint32 threshold = 4; // 04 bytes
6
repeated bytes addresses = 5; // 04 bytes + 20 bytes * len(addresses)
7
}
Copied!

SECP256K1 Transfer Output Example

Let’s make a secp256k1 transfer output with:
    TypeID: 7
    Amount: 12345
    Locktime: 54321
    Threshold: 1
    Addresses:
    0x51025c61fbcfc078f69334f834be6dd26d55a955
    0xc3344128e060128ede3523a24a461c8943ab0859
1
[
2
TypeID <- 0x00000007
3
Amount <- 0x0000000000003039
4
Locktime <- 0x000000000000d431
5
Threshold <- 0x00000001
6
Addresses <- [
7
0x51025c61fbcfc078f69334f834be6dd26d55a955,
8
0xc3344128e060128ede3523a24a461c8943ab0859,
9
]
10
]
11
=
12
[
13
// typeID:
14
0x00, 0x00, 0x00, 0x07,
15
// amount:
16
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x39,
17
// locktime:
18
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x31,
19
// threshold:
20
0x00, 0x00, 0x00, 0x01,
21
// number of addresses:
22
0x00, 0x00, 0x00, 0x02,
23
// addrs[0]:
24
0x51, 0x02, 0x5c, 0x61, 0xfb, 0xcf, 0xc0, 0x78,
25
0xf6, 0x93, 0x34, 0xf8, 0x34, 0xbe, 0x6d, 0xd2,
26
0x6d, 0x55, 0xa9, 0x55,
27
// addrs[1]:
28
0xc3, 0x34, 0x41, 0x28, 0xe0, 0x60, 0x12, 0x8e,
29
0xde, 0x35, 0x23, 0xa2, 0x4a, 0x46, 0x1c, 0x89,
30
0x43, 0xab, 0x08, 0x59,
31
]
Copied!

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 is 0x00000006.
    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 of Addresses. If Addresses 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

1
+-----------+------------+--------------------------------+
2
| type_id : int | 4 bytes |
3
+-----------+------------+--------------------------------+
4
| locktime : long | 8 bytes |
5
+-----------+------------+--------------------------------+
6
| threshold : int | 4 bytes |
7
+-----------+------------+--------------------------------+
8
| addresses : [][20]byte | 4 + 20 * len(addresses) bytes |
9
+-----------+------------+--------------------------------+
10
| 20 + 20 * len(addresses) bytes |
11
+--------------------------------+
Copied!

Proto SECP256K1 Mint Output Specification

1
message SECP256K1MintOutput {
2
uint32 typeID = 1; // 04 bytes
3
uint64 locktime = 2; // 08 bytes
4
uint32 threshold = 3; // 04 bytes
5
repeated bytes addresses = 4; // 04 bytes + 20 bytes * len(addresses)
6
}
Copied!

SECP256K1 Mint Output Example

Let’s make a SECP256K1 mint output with:
    TypeID: 6
    Locktime: 54321
    Threshold: 1
    Addresses:
    0x51025c61fbcfc078f69334f834be6dd26d55a955
    0xc3344128e060128ede3523a24a461c8943ab0859
1
[
2
TypeID <- 0x00000006
3
Locktime <- 0x000000000000d431
4
Threshold <- 0x00000001
5
Addresses <- [
6
0x51025c61fbcfc078f69334f834be6dd26d55a955,
7
0xc3344128e060128ede3523a24a461c8943ab0859,
8
]
9
]
10
=
11
[
12
// typeID:
13
0x00, 0x00, 0x00, 0x06,
14
// locktime:
15
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x31,
16
// threshold:
17
0x00, 0x00, 0x00, 0x01,
18
// number of addresses:
19
0x00, 0x00, 0x00, 0x02,
20
// addrs[0]:
21
0x51, 0x02, 0x5c, 0x61, 0xfb, 0xcf, 0xc0, 0x78,
22
0xf6, 0x93, 0x34, 0xf8, 0x34, 0xbe, 0x6d, 0xd2,
23
0x6d, 0x55, 0xa9, 0x55,
24
// addrs[1]:
25
0xc3, 0x34, 0x41, 0x28, 0xe0, 0x60, 0x12, 0x8e,
26
0xde, 0x35, 0x23, 0xa2, 0x4a, 0x46, 0x1c, 0x89,
27
0x43, 0xab, 0x08, 0x59,
28
]
Copied!

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 is 0x0000000b.
    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 of Addresses. If Addresses 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

1
+-----------+------------+-------------------------------+
2
| type_id : int | 4 bytes |
3
+-----------+------------+-------------------------------+
4
| group_id : int | 4 bytes |
5
+-----------+------------+-------------------------------+
6
| payload : []byte | 4 + len(payload) bytes |
7
+-----------+------------+-------------------------------+
8
| locktime : long | 8 bytes |
9
+-----------+------------+-------------------------------+
10
| threshold : int | 4 bytes |
11
+-----------+------------+-------------------------------+
12
| addresses : [][20]byte | 4 + 20 * len(addresses) bytes |
13
+-----------+------------+-------------------------------+
14
| 28 + len(payload) |
15
| + 20 * len(addresses) bytes |
16
+-------------------------------+
Copied!

Proto NFT Transfer Output Specification

1
message NFTTransferOutput {
2
uint32 typeID = 1; // 04 bytes
3
uint32 group_id = 2; // 04 bytes
4
bytes payload = 3; // 04 bytes + len(payload)
5
uint64 locktime = 4 // 08 bytes
6
uint32 threshold = 5; // 04 bytes
7
repeated bytes addresses = 6; // 04 bytes + 20 bytes * len(addresses)
8
}
Copied!

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
1
[
2
TypeID <- 0x0000000b
3
GroupID <- 0x00003039
4
Payload <- 0x431100
5
Locktime <- 0x000000000000d431
6
Threshold <- 0x00000001
7
Addresses <- [
8
0x51025c61fbcfc078f69334f834be6dd26d55a955,
9
0xc3344128e060128ede3523a24a461c8943ab0859,
10
]
11
]
12
=
13
[
14
// TypeID:
15
0x00, 0x00, 0x00, 0x0b,
16
// groupID:
17
0x00, 0x00, 0x30, 0x39,
18
// length of payload:
19
0x00, 0x00, 0x00, 0x03,
20
// payload:
21
0x43, 0x11, 0x00,
22
// locktime:
23
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x31,
24
// threshold:
25
0x00, 0x00, 0x00, 0x01,
26
// number of addresses:
27
0x00, 0x00, 0x00, 0x02,
28
// addrs[0]:
29
0x51, 0x02, 0x5c, 0x61, 0xfb, 0xcf, 0xc0, 0x78,
30
0xf6, 0x93, 0x34, 0xf8, 0x34, 0xbe, 0x6d, 0xd2,
31
0x6d, 0x55, 0xa9, 0x55,
32
// addrs[1]:
33
0xc3, 0x34, 0x41, 0x28, 0xe0, 0x60, 0x12, 0x8e,
34
0xde, 0x35, 0x23, 0xa2, 0x4a, 0x46, 0x1c, 0x89,
35
0x43, 0xab, 0x08, 0x59,
36
]
Copied!

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 is 0x0000000a.
    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 of Addresses. If Addresses 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

1
+-----------+------------+--------------------------------+
2
| type_id : int | 4 bytes |
3
+-----------+------------+--------------------------------+
4
| group_id : int | 4 bytes |
5
+-----------+------------+--------------------------------+
6
| locktime : long | 8 bytes |
7
+-----------+------------+--------------------------------+
8
| threshold : int | 4 bytes |
9
+-----------+------------+--------------------------------+
10
| addresses : [][20]byte | 4 + 20 * len(addresses) bytes |
11
+-----------+------------+--------------------------------+
12
| 24 + 20 * len(addresses) bytes |
13
+--------------------------------+
Copied!

Proto NFT Mint Output Specification

1
message NFTMintOutput {
2
uint32 typeID = 1; // 04 bytes
3
uint32 group_id = 2; // 04 bytes
4
uint64 locktime = 3; // 08 bytes
5
uint32 threshold = 4; // 04 bytes
6
repeated bytes addresses = 5; // 04 bytes + 20 bytes * len(addresses)
7
}
Copied!

NFT Mint Output Example

Let’s make an NFT mint output with:
    TypeID: 10
    GroupID: 12345
    Locktime: 54321
    Threshold: 1
    Addresses:
    0x51025c61fbcfc078f69334f834be6dd26d55a955
    0xc3344128e060128ede3523a24a461c8943ab0859
1
[
2
TypeID <- 0x0000000a
3
GroupID <- 0x00003039
4
Locktime <- 0x000000000000d431
5
Threshold <- 0x00000001
6
Addresses <- [
7
0x51025c61fbcfc078f69334f834be6dd26d55a955,
8
0xc3344128e060128ede3523a24a461c8943ab0859,
9
]
10
]
11
=
12
[
13
// TypeID
14
0x00, 0x00, 0x00, 0x0a,
15
// groupID:
16
0x00, 0x00, 0x30, 0x39,
17
// locktime:
18
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x31,
19
// threshold:
20
0x00, 0x00, 0x00, 0x01,
21
// number of addresses:
22
0x00, 0x00, 0x00, 0x02,
23
// addrs[0]:
24
0x51, 0x02, 0x5c, 0x61, 0xfb, 0xcf, 0xc0, 0x78,
25
0xf6, 0x93, 0x34, 0xf8, 0x34, 0xbe, 0x6d, 0xd2,
26
0x6d, 0x55, 0xa9, 0x55,
27
// addrs[1]:
28
0xc3, 0x34, 0x41, 0x28, 0xe0, 0x60, 0x12, 0x8e,
29
0xde, 0x35, 0x23, 0xa2, 0x4a, 0x46, 0x1c, 0x89,
30
0x43, 0xab, 0x08, 0x59,
31
]
Copied!

Inputs

Inputs have one possible type: SECP256K1TransferInput.

SECP256K1 Transfer Input

A secp256k1 transfer input allows for spending an unspent secp256k1 transfer output.

What SECP256K1 Transfer Input Contains

A secp256k1 transfer input contains an Amount and AddressIndices.
    TypeID is the ID for this input type. It is 0x00000005.
    Amount is a long that specifies the quantity that this input should be consuming from the UTXO. Must be positive. Must be equal to the amount specified in the UTXO.
    AddressIndices is a list of unique ints that define the private keys that are being used to spend the UTXO. Each UTXO has an array of addresses that can spend the UTXO. Each int represents the index in this address array that will sign this transaction. The array must be sorted low to high.

Gantt SECP256K1 Transfer Input Specification

1
+-------------------------+-------------------------------------+
2
| type_id : int | 4 bytes |
3
+-----------------+-------+-------------------------------------+
4
| amount : long | 8 bytes |
5
+-----------------+-------+-------------------------------------+
6
| address_indices : []int | 4 + 4 * len(address_indices) bytes |
7
+-----------------+-------+-------------------------------------+
8
| 16 + 4 * len(address_indices) bytes |
9
+-------------------------------------+
Copied!

Proto SECP256K1 Transfer Input Specification

1
message SECP256K1TransferInput {
2
uint32 typeID = 1; // 04 bytes
3
uint64 amount = 2; // 08 bytes
4
repeated uint32 address_indices = 3; // 04 bytes + 04 bytes * len(address_indices)
5
}
Copied!

SECP256K1 Transfer Input Example

Let’s make a payment input with:
    TypeId: 5
    Amount: 123456789
    AddressIndices: [3,7]
1
[
2
TypeID <- 0x00000005
3
Amount <- 123456789 = 0x00000000075bcd15,
4
AddressIndices <- [0x00000003, 0x00000007]
5
]
6
=
7
[
8
// type id:
9
0x00, 0x00, 0x00, 0x05,
10
// amount:
11
0x00, 0x00, 0x00, 0x00, 0x07, 0x5b, 0xcd, 0x15,
12
// length:
13
0x00, 0x00, 0x00, 0x02,
14
// sig[0]
15
0x00, 0x00, 0x00, 0x03,
16
// sig[1]
17
0x00, 0x00, 0x00, 0x07,
18
]
Copied!

Operations

Operations have three possible types: SECP256K1MintOperation, NFTMintOp, and NFTTransferOp.

SECP256K1 Mint Operation

A secp256k1 mint operation consumes a SECP256K1 mint output, creates a new mint output and sends a transfer output to a new set of owners.

What SECP256K1 Mint Operation Contains

A secp256k1 Mint operation contains a TypeID, AddressIndices, MintOutput, and TransferOutput.
    TypeID is the ID for this output type. It is 0x00000008.
    AddressIndices is a list of unique ints that define the private keys that are being used to spend the UTXO. Each UTXO has an array of addresses that can spend the UTXO. Each int represents the index in this address array that will sign this transaction. The array must be sorted low to high.
    MintOutput is a SECP256K1 Mint output.
    TransferOutput is a SECP256K1 Transfer output.

Gantt SECP256K1 Mint Operation Specification

1
+----------------------------------+------------------------------------+
2
| type_id : int | 4 bytes |
3
+----------------------------------+------------------------------------+
4
| address_indices : []int | 4 + 4 * len(address_indices) bytes |
5
+----------------------------------+------------------------------------+
6
| mint_output : MintOutput | size(mint_output) bytes |
7
+----------------------------------+------------------------------------+
8
| transfer_output : TransferOutput | size(transfer_output) bytes |
9
+----------------------------------+------------------------------------+
10
| 8 + 4 * len(address_indices) |
11
| + size(mint_output) |
12
| + size(transfer_output) bytes |
13
+------------------------------------+
Copied!

Proto SECP256K1 Mint Operation Specification

1
message SECP256K1MintOperation {
2
uint32 typeID = 1; // 4 bytes
3
repeated uint32 address_indices = 2; // 04 bytes + 04 bytes * len(address_indices)
4
MintOutput mint_output = 3; // size(mint_output
5
TransferOutput transfer_output = 4; // size(transfer_output)
6
}
Copied!

SECP256K1 Mint Operation Example

Let’s make a secp256k1 mint operation with:
    TypeId: 8
    AddressIndices:
    0x00000003
    0x00000007
    MintOutput: "Example SECP256K1 Mint Output from above"
    TransferOutput: "Example SECP256K1 Transfer Output from above"
1
[
2
TypeID <- 0x00000008
3
AddressIndices <- [0x00000003, 0x00000007]
4
MintOutput <- 0x00000006000000000000d431000000010000000251025c61fbcfc078f69334f834be6dd26d55a955c3344128e060128ede3523a24a461c89
5
TransferOutput <- 0x000000070000000000003039000000000000d431000000010000000251025c61fbcfc078f69334f834be6dd26d55a955c3344128e060128ede3523a24a461c8943ab0859
6
]
7
=
8
[
9
// typeID
10
0x00, 0x00, 0x00, 0x08,
11
// number of address_indices:
12
0x00, 0x00, 0x00, 0x02,
13
// address_indices[0]:
14
0x00, 0x00, 0x00, 0x03,
15
// address_indices[1]:
16
0x00, 0x00, 0x00, 0x07,
17
// mint output
18
0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00,
19
0x00, 0x00, 0xd4, 0x31, 0x00, 0x00, 0x00, 0x01,
20
0x00, 0x00, 0x00, 0x02, 0x51, 0x02, 0x5c, 0x61,
21
0xfb, 0xcf, 0xc0, 0x78, 0xf6, 0x93, 0x34, 0xf8,
22
0x34, 0xbe, 0x6d, 0xd2, 0x6d, 0x55, 0xa9, 0x55,
23
0xc3, 0x34, 0x41, 0x28, 0xe0, 0x60, 0x12, 0x8e,
24
0xde, 0x35, 0x23, 0xa2, 0x4a, 0x46, 0x1c, 0x89,
25
0x43, 0xab, 0x08, 0x59,
26
// transfer output
27
0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00,
28
0x00, 0x00, 0x30, 0x39, 0x00, 0x00, 0x00, 0x00,
29
0x00, 0x00, 0xd4, 0x31, 0x00, 0x00, 0x00, 0x01,
30
0x00, 0x00, 0x00, 0x02, 0x51, 0x02, 0x5c, 0x61,
31
0xfb, 0xcf, 0xc0, 0x78, 0xf6, 0x93, 0x34, 0xf8,
32
0x34, 0xbe, 0x6d, 0xd2, 0x6d, 0x55, 0xa9, 0x55,
33
0xc3, 0x34, 0x41, 0x28, 0xe0, 0x60, 0x12, 0x8e,
34
0xde, 0x35, 0x23, 0xa2, 0x4a, 0x46, 0x1c, 0x89,
35
0x43, 0xab, 0x08, 0x59,
36
]
Copied!

NFT Mint Op

An NFT mint operation consumes an NFT mint output and sends an unspent output to a new set of owners.

What NFT Mint Op Contains

An NFT mint operation contains a TypeID, AddressIndices, GroupID, Payload, and Output of addresses.
    TypeID is the ID for this operation type. It is 0x0000000c.
    AddressIndices is a list of unique ints that define the private keys that are being used to spend the UTXO. Each UTXO has an array of addresses that can spend the UTXO. Each int represents the index in this address array that will sign this transaction. The array must be sorted low to high.
    GroupID is an int that specifies the group this NFT is issued to.
    Payload is an arbitrary string of bytes no longer than 1024 bytes.
    Output is not a TransferableOutput, but rather is a locktime, threshold, and an array 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 Op Specification

1
+------------------------------+------------------------------------+
2
| type_id : int | 4 bytes |
3
+-----------------+------------+------------------------------------+
4
| address_indices : []int | 4 + 4 * len(address_indices) bytes |
5
+-----------------+------------+------------------------------------+
6
| group_id : int | 4 bytes |
7
+-----------------+------------+------------------------------------+
8
| payload : []byte | 4 + len(payload) bytes |
9
+-----------------+------------+------------------------------------+
10
| outputs : []Output | 4 + size(outputs) bytes |
11
+-----------------+------------+------------------------------------+
12
| 20 + |
13
| 4 * len(address_indices) + |
14
| len(payload) + |
15
| size(outputs) bytes |
16
+------------------------------------+
Copied!

Proto NFT Mint Op Specification

1
message NFTMintOp {
2
uint32 typeID = 1; // 04 bytes
3
repeated uint32 address_indices = 2; // 04 bytes + 04 bytes * len(address_indices)
4
uint32 group_id = 3; // 04 bytes
5
bytes payload = 4; // 04 bytes + len(payload)
6
repeated bytes outputs = 5; // 04 bytes + size(outputs)
7
}
Copied!

NFT Mint Op Example

Let’s make an NFT mint operation with:
    TypeId: 12
    AddressIndices:
      0x00000003
      0x00000007
    GroupID: 12345
    Payload: 0x431100
    Locktime: 54321
    Threshold: 1
    Addresses:
    0xc3344128e060128ede3523a24a461c8943ab0859
1
[
2
TypeID <- 0x0000000c
3
AddressIndices <- [
4
0x00000003,
5
0x00000007,
6
]
7
GroupID <- 0x00003039
8
Payload <- 0x431100
9
Locktime <- 0x000000000000d431
10
Threshold <- 0x00000001
11
Addresses <- [
12
0xc3344128e060128ede3523a24a461c8943ab0859
13
]
14
]
15
=
16
[
17
// Type ID
18
0x00, 0x00, 0x00, 0x0c,
19
// number of address indices:
20
0x00, 0x00, 0x00, 0x02,
21
// address index 0:
22
0x00, 0x00, 0x00, 0x03,
23
// address index 1:
24
0x00, 0x00, 0x00, 0x07,
25
// groupID:
26
0x00, 0x00, 0x30, 0x39,
27
// length of payload:
28
0x00, 0x00, 0x00, 0x03,
29
// payload:
30
0x43, 0x11, 0x00,
31
// number of outputs:
32
0x00, 0x00, 0x00, 0x01,
33
// outputs[0]
34
// locktime:
35
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x31,
36
// threshold:
37
0x00, 0x00, 0x00, 0x01,
38
// number of addresses:
39
0x00, 0x00, 0x00, 0x01,
40
// addrs[0]:
41
0xc3, 0x34, 0x41, 0x28, 0xe0, 0x60, 0x12, 0x8e,
42
0xde, 0x35, 0x23, 0xa2, 0x4a, 0x46, 0x1c, 0x89,
43
0x43, 0xab, 0x08, 0x59,
44
]
Copied!

NFT Transfer Op

An NFT transfer operation sends an unspent NFT transfer output to a new set of owners.

What NFT Transfer Op Contains

An NFT transfer operation contains a TypeID, AddressIndices and an untyped NFTTransferOutput.
    TypeID is the ID for this output type. It is 0x0000000d.
    AddressIndices is a list of unique ints that define the private keys that are being used to spend the UTXO. Each UTXO has an array of addresses that can spend the UTXO. Each int represents the index in this address array that will sign this transaction. The array must be sorted low to high.
    NFTTransferOutput is the output of this operation and must be an NFT Transfer Output. This output doesn’t have the TypeId, because the type is known by the context of being in this operation.

Gantt NFT Transfer Op Specification

1
+------------------------------+------------------------------------+
2
| type_id : int | 4 bytes |
3
+-----------------+------------+------------------------------------+
4
| address_indices : []int | 4 + 4 * len(address_indices) bytes |
5
+-----------------+------------+------------------------------------+
6
| group_id : int | 4 bytes |
7
+-----------------+------------+------------------------------------+
8
| payload : []byte | 4 + len(payload) bytes |
9
+-----------------+------------+------------------------------------+
10
| locktime : long | 8 bytes |
11
+-----------+------------+------------------------------------------+
12
| threshold : int | 4 bytes |
13
+-----------------+------------+------------------------------------+
14
| addresses : [][20]byte | 4 + 20 * len(addresses) bytes |
15
+-----------------+------------+------------------------------------+
16
| 36 + len(payload) |
17
| + 4 * len(address_indices) |
18
| + 20 * len(addresses) bytes |
19
+------------------------------------+
Copied!

Proto NFT Transfer Op Specification

1
message NFTTransferOp {
2
uint32 typeID = 1; // 04 bytes
3
repeated uint32 address_indices = 2; // 04 bytes + 04 bytes * len(address_indices)
4
uint32 group_id = 3; // 04 bytes
5
bytes payload = 4; // 04 bytes + len(payload)
6
uint64 locktime = 5; // 08 bytes
7
uint32 threshold = 6; // 04 bytes
8
repeated bytes addresses = 7; // 04 bytes + 20 bytes * len(addresses)
9
}
Copied!

NFT Transfer Op Example

Let’s make an NFT transfer operation with:
    TypeID: 13
    AddressIndices:
    0x00000007
    0x00000003
    GroupID: 12345
    Payload: 0x431100
    Locktime: 54321
    Threshold: 1
    Addresses:
    0xc3344128e060128ede3523a24a461c8943ab0859
    0x51025c61fbcfc078f69334f834be6dd26d55a955
1
[
2
TypeID <- 0x0000000d
3
AddressIndices <- [
4
0x00000007,
5
0x00000003,
6
]
7
GroupID <- 0x00003039
8
Payload <- 0x431100
9
Locktime <- 0x000000000000d431
10
Threshold <- 00000001
11
Addresses <- [
12
0x51025c61fbcfc078f69334f834be6dd26d55a955,
13
0xc3344128e060128ede3523a24a461c8943ab0859,
14
]
15
]
16
=
17
[
18
// Type ID
19
0x00, 0x00, 0x00, 0x0d,
20
// number of address indices:
21
0x00, 0x00, 0x00, 0x02,
22
// address index 0:
23
0x00, 0x00, 0x00, 0x07,
24
// address index 1:
25
0x00, 0x00, 0x00, 0x03,
26
// groupID:
27
0x00, 0x00, 0x30, 0x39,
28
// length of payload:
29
0x00, 0x00, 0x00, 0x03,
30
// payload:
31
0x43, 0x11, 0x00,
32
// locktime:
33
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x31,
34
// threshold:
35
0x00, 0x00, 0x00, 0x01,
36
// number of addresses:
37
0x00, 0x00, 0x00, 0x02,
38
// addrs[0]:
39
0x51, 0x02, 0x5c, 0x61, 0xfb, 0xcf, 0xc0, 0x78,
40
0xf6, 0x93, 0x34, 0xf8, 0x34, 0xbe, 0x6d, 0xd2,
41
0x6d, 0x55, 0xa9, 0x55,
42
// addrs[1]:
43
0xc3, 0x34, 0x41, 0x28, 0xe0, 0x60, 0x12, 0x8e,
44
0xde, 0x35, 0x23, 0xa2, 0x4a, 0x46, 0x1c, 0x89,
45
0x43, 0xab, 0x08, 0x59,
46
]
Copied!

Initial State

Initial state describes the initial state of an asset when it is created. It contains the ID of the feature extension that the asset uses, and a variable length array of outputs that denote the genesis UTXO set of the asset.

What Initial State Contains

Initial state contains a FxID and an array of Output.
    FxID is an int that defines which feature extension this state is part of. For SECP256K1 assets, this is 0x00000000. For NFT assets, this is 0x00000001.
    Outputs is a variable length array of outputs, as defined above.

Gantt Initial State Specification

1
+---------------+----------+-------------------------------+
2
| fx_id : int | 4 bytes |
3
+---------------+----------+-------------------------------+
4
| outputs : []Output | 4 + size(outputs) bytes |
5
+---------------+----------+-------------------------------+
6
| 8 + size(outputs) bytes |
7
+-------------------------------+
Copied!

Proto Initial State Specification

1
message InitialState {
2
uint32 fx_id = 1; // 04 bytes
3
repeated Output outputs = 2; // 04 + size(outputs) bytes
4
}
Copied!

Initial State Example

Let’s make an initial state:
    FxID: 0x00000000
    InitialState: ["Example SECP256K1 Transfer Output from above"]
1
[
2
FxID <- 0x00000000
3
InitialState <- [
4
0x000000070000000000003039000000000000d431000000010000000251025c61fbcfc078f69334f834be6dd26d55a955c3344128e060128ede3523a24a461c8943ab0859,
5
]
6
]
7
=
8
[
9
// fxID:
10
0x00, 0x00, 0x00, 0x00,
11
// num outputs:
12
0x00, 0x00, 0x00, 0x01,
13
// output:
14
0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00,
15
0x00, 0x00, 0x30, 0x39, 0x00, 0x00, 0x00, 0x00,
16
0x00, 0x00, 0xd4, 0x31, 0x00, 0x00, 0x00, 0x01,
17
0x00, 0x00, 0x00, 0x02, 0x51, 0x02, 0x5c, 0x61,
18
0xfb, 0xcf, 0xc0, 0x78, 0xf6, 0x93, 0x34, 0xf8,
19
0x34, 0xbe, 0x6d, 0xd2, 0x6d, 0x55, 0xa9, 0x55,
20
0xc3, 0x34, 0x41, 0x28, 0xe0, 0x60, 0x12, 0x8e,
21
0xde, 0x35, 0x23, 0xa2, 0x4a, 0x46, 0x1c, 0x89,
22
0x43, 0xab, 0x08, 0x59,
23
]
Copied!

Credentials

Credentials have two possible types: SECP256K1Credential, and NFTCredential. Each credential is paired with an Input or Operation. The order of the credentials match the order of the inputs or operations.

SECP256K1 Credential

A secp256k1 credential contains a list of 65-byte recoverable signatures.

What SECP256K1 Credential Contains

    TypeID is the ID for this type. It is 0x00000009.
    Signatures is an array of 65-byte recoverable signatures. The order of the signatures must match the input’s signature indices.

Gantt SECP256K1 Credential Specification

1
+------------------------------+---------------------------------+
2
| type_id : int | 4 bytes |
3
+-----------------+------------+---------------------------------+
4
| signatures : [][65]byte | 4 + 65 * len(signatures) bytes |
5
+-----------------+------------+---------------------------------+
6
| 8 + 65 * len(signatures) bytes |
7
+---------------------------------+
Copied!

Proto SECP256K1 Credential Specification

1
message SECP256K1Credential {
2
uint32 typeID = 1; // 4 bytes
3
repeated bytes signatures = 2; // 4 bytes + 65 bytes * len(signatures)
4
}
Copied!

SECP256K1 Credential Example