EOS智能合约ABI文件结构

2020.07.01 04:12

之前的文章使用编译好的eosio.token.abi和eosio.token.wasm文件部署了eosio.token合约,这篇文章介绍ABI是如何和eosio.token合约相关联的。

可以使用eosio.cdt提供的eosio-cpp工具生成ABI文件,然而在某些情况下可能会出现ABI生成失败, 因此必须了解ABI文件的工作原理,以便在必要时进行调试和修复。


什么是ABI?

ABI全称是应用程序二进制接口(Application Binary Interface),它是基于JSON的文本文件,用于说明智能合约的Action如何在JSON和二进制格式之间互相转换。

ABI还描述了如何将数据库状态数据与JSON互相转换,合约通过ABI描述后,开发人员和用户可以通过JSON与合约进行无缝交互。

要注意,智能合约执行的是二进制的WebAssembly(WASM)代码,ABI只是指导,执行交易时可以绕过ABI,传递给合约的消息和操作也不需要完全符合ABI。


创建ABI文件

下面是一个简略的eosio.token.abi文件

{
   "___comment" : "",
   "version": "eosio::abi/1.0",
   "types": [],
   "structs": [],
   "actions": [],
   "tables": [],
   "ricardian_clauses": [],
   "variants": []
}

types

ABI可以使任何客户端程序或接口为合约生成GUI(图形用户界面),在公共Action或结构类型中用做参数的自定义类型需要在types字段中进行描述。

{
   "new_type_name": "name",
   "type": "name"
}

另外,EOSIO为智能合约实现了许多内置类型(Built-in Types),内置类型无需在types字段中进行描述,EOSIO的内置类型定义在eos/libraries/chain/abi_serializer.cpp的configure_built_in_types函数中,这些内置数据类型可以分为8大类:整数、浮点数、时间、名称、字符、哈希算法、密钥和签名、资产,具体可看上一篇文章。


structs

structs用于描述ABI的结构,包括合约类的Action和Multi-index数据表成员,每个成员都有name、base、fields几个字段,描述了这个Action或数据表的结构,如eosio.token合约的issue Action的结构如下

{
    "name": "issue",
    "base": "",
    "fields": [
        {
            "name": "to",
            "type": "name"
        },
        {
            "name": "quantity",
            "type": "asset"
        },
        {
            "name": "memo",
            "type": "string"
        }
    ]
},

Action本质上是一个可公开访问的函数,fields字段描述了这个函数的参数个数、参数名称和参数类型。

base字段用于描述继承关系,在eosio.token合约中没有使用,但在eosio.system合约中使用到了

struct eosio_global_state : eosio::blockchain_parameters {
    //...
}

actions

actions字段下的一个数据是这样定义的

{
    "name": "issue",
    "type": "issue",
    "ricardian_contract": ""
},

name字段表示此Action在合约中的名称;

type字段表示此Action在ABI的structs字段中定义的名称;

ricardian_contract字段是一个可选的李嘉图合约条款,用于描述此Action的预期功能。

一般情况下,name和type字段值相同,但这不是必须的。


tables

tables字段用于描述合约中的Multi-index表,tables字段下的一个数据是这样定义的

{
    "name": "accounts",
    "type": "account",
    "index_type": "i64",
    "key_names": [],
    "key_types": []
},

这是eosio.token合约的accounts数据表,

name字段表示在合约中声明的数据表名称;

type字段表示此数据表在ABI的structs字段中定义的名称;

index_type表示数据表主键数据类型(i64为64位无符号整型uint64_t);

key_names和key_types字段表示二级索引的名称和类型,二级索引可以有多个,因此这两个字段是数组类型,且元素个数需要保持一致。


ricardian_clauses

ricardian_clauses字段表示李嘉图合约条款,描述特定Action的预期操作结果和在发送方与合约之间建立条款。


注意事项

修改EOS合约源码后,需要重新编译源文件,生成新的ABI和WASM文件,并使用cleos set contract命令更新主网的链上合约。虽然忘记更新ABI不会报错,但可能会造成业务逻辑上的问题,导致数据表不返回正确的数据。


新闻资讯