mygo 编译合约时,会自动生成合约的 ABI 文件,本节将详细介绍 ABI 文件的格式。

在编译合约时,会自动生成文件 hello.abi。ABI 中描述了每一个合约方法的参数和返回值类型,以及合约自定义结构体的信息,便于合约使用者调用合约。接下来,将详细介绍 ABI 的格式。

简介

ABI (Application Binary Interface) 描述了智能合约对外可见的接口,包括合约方法名和参数类型等。使用蚂蚁区块链的合约开发工具可以自动生成合约的 ABI 文件,以 JSON 格式保存。

以下面简单 C++ 合约为例进行介绍,示例代码如下:

#include <mychainlib/contract.h>

using namespace mychain;

struct Name {
    std::string data;
    SERIALIZE(Name, (data));
};
typedef Name name_t;

class Hello : public Contract {
public:
    INTERFACE int hi(name_t name) {
        print("Hello, %s", name.data.c_str());
        return 0;
    }
};

INTERFACE_EXPORT(Hello, (hi))

它对应的 ABI 文件如下:

{
    "____comment": "This file was generated with wasm-abigen. DO NOT EDIT",
    "version": "mychain::abi/1.3",
    "contract_version": 0,
    "structs": [
        {
            "name": "Name",
            "base": "",
            "fields": [
                {
                    "name": "data",
                    "type": "string"
                }
            ],
            "results": []
        },
        {
            "name": "hi",
            "base": "",
            "fields": [
                {
                    "name": "name",
                    "type": "name_t"
                }
            ],
            "results": ["int32"]
        }
    ],
    "types": [
        {
            "new_type_name": "name_t",
            "type": "Name"
        }
    ],
    "interfaces": [
        {
            "name": "hi",
            "type": "hi"
        }
    ],
    "variants": []
}

下文将分别介绍 ABI 中每个字段的含义。

Interfaces

每个 interface 对象描述了一个合约方法的名字和接口类型:name 成员表示该方法的名字,type 成员表示该方法的接口类型,包括各个参数和返回值的类型。具体的接口类型定义可以在 structs 数组中找到。在上面的例子中,合约方法 hi 的接口类型也是 hi,然后根据 hi 这个名字可以在 structs 中找到它的具体接口类型。

说明

注意:合约方法的名字和接口类型名不要求同名,ABI 生成工具只是为了方便而使用了相同的名字。

Structs

struct 对象可能表示两种类型:

  • 合约方法的接口类型

    name 为合约方法类型名(不要求和方法名相同),fields 为每个参数的名字和类型,results 表示合约方法返回值的类型。C++ 合约只有一个返回值,Go 合约可能有多个返回值。

  • 用户自定义结构体类型

    name 为结构体名字,fields 为结构体每个成员的名字和类型,results 字段为空。

如上面的例子中,Name 对象对应用户定义的结构体类型,hi 对象对应合约方法的接口类型。

Types

当合约代码中使用 C++ 的 typedef 等语句定义了类型别名时,这些类型别名会记录到 type 对象中。

数据类型表示

ABI 中合约方法参数/返回值类型的表示方式与合约代码中不一定完全相同。具体的对应关系如下:

C++

源码

ABI

bool

bool

char, int8_t

int8

unsigned char, uint8_t

uint8

short, int16_t

int16

unsigned short, uint16_t

uint16

int, long, int32_t

int32

unsigned int, unsigned long, uint32_t

uint32

long long, int64_t

int64

unsigned long long, uint64_t

uint64

float

float32

double

float64

std::string

string

Identity

Identity

std::vector<AnyType>

AnyType[]

说明

注:AnyType 可以为上面表格中 vector 以外的任意基础类型。

Go

源码

ABI

bool

bool

int8

int8

uint8, byte

uint8

int16

int16

uint16

uint16

int32, int, rune

int32

uint32, uint, uintptr

uint32

int64

int64

uint64

uint64

string

string

Identity

Identity

[]AnyType

AnyType[]

Solidity

源码

ABI

bool

bool

int32

uint32

uint64

uint64

bytes

bytes

bytes1 ~ bytes32

bytes1 ~ bytes32

string

string

identity

identity

int32[]

int32[]

uint64[]

uint64[]

bytes1[] ~ bytes32[]

bytes1[] ~ bytes32[]

bool[]

bool[]

identity[]

identity[]