Skip to content

Latest commit

 

History

History
 
 

abi

ABI Package

Overview

The ABI package provides functionality for marshaling and unmarshaling actions. It is designed to work across different language implementations.

ABI Format

The ABI is defined in JSON format, as shown in the abi.json file:

{
    "actions": [
        {
            "id": 1,
            "action": "MockObjectSingleNumber"
        },
    ],
    "types": [
        {
            "name": "MockObjectSingleNumber",
            "fields": [
                {
                    "name": "Field1",
                    "type": "uint16"
                }
            ]
        },
    ]
}

The ABI consists of two main sections:

  • actions: A list of action definitions, each with a typeID and action name (action name specifies the type)
  • types: A dictionary of types including their name and corresponding fields

The type in each field must either be included in the ABI's types or in the list of Supported Primitive Types.

Test Vectors

This implementation provides testdata/ for implementations in any other language.

To verify correctness, an implementation can implement the following pseudocode:

abi = abi.json

for filename in testdata/*.hex:
    if filename.endswith(".hash.hex"):
        continue
    expectedHex = readFile(filename)
    json = readFile(filename.replace(".hex", ".json"))

    actualHex = Marshal(abi, json)
    if actualHex != expectedHex:
        raise "Hex values do not match"

ABI Verification

Frontends can use the ABI to display proper action and field names. For a wallet to verify it knows what it's signing, it must ensure that a canonical hash of the ABI is included in the message it signs.

A correct VM will verify the signature against the same ABI hash, such that verification fails if the wallet signed an action against a different than expected ABI.

This enables frontends to provide a verifiable display of what they are asking users to sign.

Constraints

  • Actions require an ID, other structs / types do not require one
  • Multiple structs with the same name from different packages are not supported
  • Maps are not supported; use slices or arrays instead
  • Built-in type codec.Address included as a special case

Generating Golang Bindings

Use cmd/abigen to automatically generate Go bindings from an ABI's JSON.

For example, to auto-generate golang bindings for the test ABI provided in ./abi/testdata/abi.json run:

go run ./cmd/abigen/ ./abi/testdata/abi.json ./example.go --package=testpackage

This should generate the same code that is present in ./abi/mockabi_test.go.

Supported Primitive Types

Type Range/Description JSON Serialization Binary Serialization
bool true or false boolean 1 byte
uint8 numbers from 0 to 255 number 1 byte
uint16 numbers from 0 to 65535 number 2 bytes
uint32 numbers from 0 to 4294967295 number 4 bytes
uint64 numbers from 0 to 18446744073709551615 number 8 bytes
int8 numbers from -128 to 127 number 1 byte
int16 numbers from -32768 to 32767 number 2 bytes
int32 numbers from -2147483648 to 2147483647 number 4 bytes
int64 numbers from -9223372036854775808 to 9223372036854775807 number 8 bytes
Address 33 byte array base64 33 bytes
string string string uint16 length + bytes
[]T for any T in the above list, serialized as an array array uint32 length + elements
[x]T for any T in the above list, serialized as an array array uint32 length + elements
[]uint8 byte slice base64 uint32 length + bytes
[x]uint8 byte array array of numbers x bytes