如何理解以太坊ABI – 应用程序二进制接口

很多同学不是很明白以太坊ABI是什么,他的作用是什么,读完本文就明白了。

很多同学不是很明白以太坊ABI是什么,他的作用是什么,读完本文就明白了。 ## 写在前面 阅读本文前,你应该对以太坊、[智能合约](https://learnblockchain.cn/2018/01/04/understanding-smart-contracts/)有所了解, 如果你还不了解,建议你先看[以太坊是什么](https://learnblockchain.cn/2017/11/20/whatiseth/),也可以观看我们的视频:[零基础搞懂区块链](https://ke.qq.com/course/318230?flowToken=1010388 )和[深入详解以太坊智能合约语言Solidity](https://ke.qq.com/course/326528?flowToken=1010387), 可以系统全面学习理解以太坊、智能合约。 ## ABI 是什么 ABI 全称是 Application Binary Interface,翻译过来就是:应用程序二进制接口,简单来说就是 以太坊的调用合约时的接口说明。还不是很理解,没关系。 ## 调用合约函数发生了什么 从外部施加给以太坊的行为都称之为向以太坊网络提交了一个交易, 调用合约函数其实是向合约地址(账户)提交了一个交易,这个交易有一个附加数据,这个附加的数据就是ABI的编码数据。 ![](https://img.learnblockchain.cn/2018/abi1.jpg!wl) > 比特币的交易也可以附加数据,以太坊革命性的地方就是能把附加数据转化为都函数的执行。 因此要想和合约交互,就离不开ABI数据。 ### 演示调用函数 以下面以个最简单的合约为例,我们看看用参数 1 调用`set(uint x)`,这个交易附带的数据是什么。 ```js pragma solidity ^0.4.0; contract SimpleStorage { uint storedData; function set(uint x) public { storedData = x; } function get() public constant returns (uint) { return storedData; } } ``` 当然第一步需要先把合约部署到以太坊网络(其实部署也是一个)上,然后用 “1” 作为参数调用set,如下图: ![](https://img.learnblockchain.cn/2018/abi2.jpg!wl) 然后我们打开etherscan查看[交易详情数据](https://ropsten.etherscan.io/tx/0xd773a6909808f99c5a26c0c890af8b0bb6d784f29a3af55e04fa35d44d7716e2), 可以看到其附加数据如下图: ![](https://img.learnblockchain.cn/2018/abi3.jpg!wl) 这个数据就是ABI的编码数据: ``` 0x60fe47b10000000000000000000000000000000000000000000000000000000000000001 ``` ## ABI 编码分析 我把上面交易的附加数据拷贝出来分析一下,这个数据可以分成两个子部分: * 函数选择器(4字节) 0x60fe47b1 * 第一个参数(32字节) 00000000000000000000000000000000000000000000000000000000000000001 函数选择器值 实际是对函数签名字符串进行sha3(keccak256)哈希运算之后,取前4个字节,用代码表示就是: ```js bytes4(sha3(“set(uint256)”)) == 0x60fe47b1 ``` 参数部分则是使用对应的16进制数。 现在就好理解 附加数据怎么转化为对应的函数调用。 ## ABI 编码函数 那么怎么获得函数对应的ABI 数据呢, 有两种方法: ### Solidity ABI 编码函数 一个是 solidity 提供了ABI的相关[API](https://learnblockchain.cn/2018/03/14/solidity-api/), 用来直接得到ABI编码信息,这些函数有: * abi.encode(...) returns (bytes):计算参数的ABI编码。 * abi.encodePacked(...) returns (bytes):计算参数的紧密打包编码 * abi. encodeWithSelector(bytes4 selector, ...) returns (bytes): 计算函数选择器和参数的ABI编码 * abi.encodeWithSignature(string signature, ...) returns (bytes): 等价于* abi.encodeWithSelector(bytes4(keccak256(signature), ...) 通过ABI编码函数可以在不用调用函数的情况下,获得ABI编码值,下面通过一段代码来看看这些方法的使用: ```js pragma solidity ^0.4.24; contract testABI { uint storedData; function set(uint x) public { storedData = x; } function abiEncode() public constant returns (bytes) { abi.encode(1); // 计算1的ABI编码 return abi.encodeWithSignature("set(uint256)", 1); //计算函数set(uint256) 及参数1 的ABI 编码 } } ``` 大家可以运行运行下`abiEncode`函数,它的输出其实就是前面调用的附加数据。 ### Web3 ABI 编码函数 另一个web3提供相应的API,例如使用web3计算函数选择器的方式如下: ```js web3.eth.abi.encodeFunctionSignature('myMethod(uint256,string)'); ``` 其完整的文档在[这里](http://web3js.readthedocs.io/en/1.0/web3-eth-abi.html),这里不一一演示。 另外安利两门视频课程给大家: * [深入详解以太坊智能合约语言Solidity](https://ke.qq.com/course/326528?flowToken=1010387) - Solidity 语言面面俱到 * [以太坊DAPP开发实战](https://ke.qq.com/course/335169?flowToken=1010386) - 轻轻松松学会DAPP开发 *学习中如遇问题,欢迎到[区块链技术问答](https://learnblockchain.cn/questions)提问,这里有专家为你解惑。 [深入浅出区块链](https://learnblockchain.cn/) - 高质量的区块链技术博客+问答社区,为区块链学习双重助力*

很多同学不是很明白以太坊ABI是什么,他的作用是什么,读完本文就明白了。

写在前面

阅读本文前,你应该对以太坊、智能合约有所了解, 如果你还不了解,建议你先看以太坊是什么,也可以观看我们的视频:零基础搞懂区块链和深入详解以太坊智能合约语言Solidity, 可以系统全面学习理解以太坊、智能合约。

ABI 是什么

ABI 全称是 Application Binary Interface,翻译过来就是:应用程序二进制接口,简单来说就是 以太坊的调用合约时的接口说明。还不是很理解,没关系。

调用合约函数发生了什么

从外部施加给以太坊的行为都称之为向以太坊网络提交了一个交易, 调用合约函数其实是向合约地址(账户)提交了一个交易,这个交易有一个附加数据,这个附加的数据就是ABI的编码数据。

比特币的交易也可以附加数据,以太坊革命性的地方就是能把附加数据转化为都函数的执行。

因此要想和合约交互,就离不开ABI数据。

演示调用函数

以下面以个最简单的合约为例,我们看看用参数 1 调用set(uint x),这个交易附带的数据是什么。

pragma solidity ^0.4.0;

contract SimpleStorage {

    uint storedData;

    function set(uint x) public {
        storedData = x;
    }

    function get() public constant returns (uint) {
        return storedData;
    }
}

当然第一步需要先把合约部署到以太坊网络(其实部署也是一个)上,然后用 “1” 作为参数调用set,如下图:

然后我们打开etherscan查看交易详情数据, 可以看到其附加数据如下图:

这个数据就是ABI的编码数据:

0x60fe47b10000000000000000000000000000000000000000000000000000000000000001

ABI 编码分析

我把上面交易的附加数据拷贝出来分析一下,这个数据可以分成两个子部分:

  • 函数选择器(4字节) 0x60fe47b1

  • 第一个参数(32字节) 00000000000000000000000000000000000000000000000000000000000000001

函数选择器值 实际是对函数签名字符串进行sha3(keccak256)哈希运算之后,取前4个字节,用代码表示就是:

    bytes4(sha3(“set(uint256)”)) == 0x60fe47b1

参数部分则是使用对应的16进制数。

现在就好理解 附加数据怎么转化为对应的函数调用。

ABI 编码函数

那么怎么获得函数对应的ABI 数据呢, 有两种方法:

Solidity ABI 编码函数

一个是 solidity 提供了ABI的相关API, 用来直接得到ABI编码信息,这些函数有:

  • abi.encode(...) returns (bytes):计算参数的ABI编码。
  • abi.encodePacked(...) returns (bytes):计算参数的紧密打包编码
  • abi. encodeWithSelector(bytes4 selector, ...) returns (bytes): 计算函数选择器和参数的ABI编码
  • abi.encodeWithSignature(string signature, ...) returns (bytes): 等价于* abi.encodeWithSelector(bytes4(keccak256(signature), ...)

通过ABI编码函数可以在不用调用函数的情况下,获得ABI编码值,下面通过一段代码来看看这些方法的使用:

pragma solidity ^0.4.24;

contract testABI {
    uint storedData;

    function set(uint x) public {
        storedData = x;
    }

    function abiEncode() public constant returns (bytes) {
        abi.encode(1);  // 计算1的ABI编码
        return abi.encodeWithSignature("set(uint256)", 1); //计算函数set(uint256) 及参数1 的ABI 编码
    }
}

大家可以运行运行下abiEncode函数,它的输出其实就是前面调用的附加数据。

Web3 ABI 编码函数

另一个web3提供相应的API,例如使用web3计算函数选择器的方式如下:

web3.eth.abi.encodeFunctionSignature('myMethod(uint256,string)');

其完整的文档在这里,这里不一一演示。

另外安利两门视频课程给大家:

  • 深入详解以太坊智能合约语言Solidity - Solidity 语言面面俱到
  • 以太坊DAPP开发实战 - 轻轻松松学会DAPP开发

学习中如遇问题,欢迎到区块链技术问答提问,这里有专家为你解惑。 深入浅出区块链 - 高质量的区块链技术博客+问答社区,为区块链学习双重助力

  • 发表于 2018-08-09 17:08
  • 阅读 ( 20660 )
  • 学分 ( 22 )
  • 分类:以太坊

评论