solidity 以太坊智能合约语言(三)

ABI(Contract Application Binary Interface)详解

ABI是以太坊合约间相互调用的一种消息格式,包括从链外部调用链,或者合约之间的相互调用,类似于常见的rpc协议一样,也就是定义操作函数签名,参数编码,返回结果编码等。

1、函数

使用ABI协议的时候,必须要求在编译的时候知道类型,不支持动态类型编译。同时,协议假设编译期间知道另一个合约的接口定义,所以协议返回没有明确定义内容类型。

函数选择器:调用一个函数时,前四个字节指定了要调用函数的签名,计算方式是使用函数签名的keccak256的哈希,取4个字节。e.g.:

bytes4(keccak256("fuc(uint32,bool)"))

 参数编码:因为函数签名占用了4个字节,参数编码从第五个字节开始。

编码方式:区分了动态内容和固定大小类型,动态内容类型有:

  • bytes
  • string
  • T[]不定长数组
  • T[k]定长数组

初次之外的都是固定大小代的类型。固定大小的类型按原位置存储在当前块中,动态类型的数据独立存储在其他数据块中。

2、Events事件

Events是从以太坊日志/事件监听机制的一个抽象。日志实体包含合约地址,最多4个的主体topic和任意长度的二进制数据内容。Events依赖ABI函数来解析,日志实体被当做一个自定义的数据结构。

事件有事件名称和参数,我们将他们分为两个系列:需要索引和不需要索引。需要索引的,最多不超过3个,和事件签名的hash一起组成日志实体的topic。那些不需要索引的内容组成了事件的字节数组内容。

日志实体使用的ABI描述如下:

  • address,合约地址,由以太坊内部提供
  • topics[0],keccak(EVENT_NAME+"("+EVENT_ARGS.map(canonical_type_of).join(",")+")"),其中的canonical_type_of是返回函数的规范型(Canonical form),如,uint indexed foo,返回的应该是uint256。如果事件本身是匿名定义的,那么Topic[0]将不会自动生成。
  • topics[n],EVENT_INDEXED_ARGS[n-1],其中的EVENT_INDEXED_ARGS表示指定成要索引的事件参数。
  • data,abi_serialise(EVENT_NON_INDEXED_ARGS)使用ABI协议序列化的没有指定为索引的其它的参数。abi_serialise()是ABI序列函数,用来返回一系列的函数定义的类型值。

3、JSON 格式

JSON格式的合约接口,可以描述为:

  • type: 可取值有functionconstructorfallback(无名称的默认函数)
  • name: 函数的名字
  • inputs: 一系列的对象,每个对象包含下述属性:
    • name: 参数名称
    • type: 参数的规范型(Canonical Type)
  • outputs: 一系列的类似inputs的对象,如果无返回值时,可以省略
  • constanttrue表示函数声明自己不会改变区块链的状态。
  • payabletrue表示函数可以接收ether,否则表示不能。

type字段可以省略,默认取值function,payable和constant也可以省略,默认都是false。构造器函数和回退函数,没有name或者outputs,回退函数也没有inputs。

事件的json描述非常类似:

  • type: 取值都是"event"
  • name: 事件名字
  • inputs: 一系列的输入参数,每个参数包括:
    • name: 参数名字
    • type: 参数类型
    • components: used for tuple types (more below).
    • indexed: 如果是日志的topic,取值是true,否则是false
  • anonymoustrue 表示事件是匿名的

详情可参考:https://solidity.readthedocs.io/en/develop/abi-spec.html?highlight=abi

你可能感兴趣的:(区块链——智能合约)