苏铭客

导航

以太坊 方法签名

  最近在工作中使用web3j调用合约,发现一个比较头疼的问题?复杂一点的合约参数多了,函数的方法签名老是出错。在这之前调用合约方法一直都是拼接合约的函数签名以及参数。为了能快速的获取每个合约的函数签名,我在思考是否便捷可行解决方案?而不是使用老套的方法,在remix IDE中编写函数,用其编译获取函数签名。

  通常以太坊合约开发后,需要先进行编译,部署时需要二进制字节编码bytecode,或者是abi文件。其中abi文件是合约函数,变量,事件组成的一组输入输出的json串。而bytecode是根据abi文件生成的二进制字节码。其中bytecode包含了合约中函数签名。那bytecode的函数签名是如何生成的呢?什么又是函数签名?

 

一.以太坊函数签名

  区块链中合约代码执行,需要指定某个合约地址的某个函数,其中这个执行的函数是使用Keccak-256(SHA-3)编码后的散列,取散列的前四个字节作为函数签名。官方定义:"签名被定义为没有数据位置说明符的基本原型规范表达式,即具有带括号的参数类型列表的函数名称"。通俗的说就是:将函数名,带顺序的变量类型以及参数括号进行Keccak-256编码后,取前四个字节的二进制字符串,即以太坊的合约函数签名。

 

二.函数签名生成

  在java中可以使用bcpkix-jdk15on工具类的Keccak.Digest256将合约函数方法名及参数类型做hash计算,转换成16进制后取前8位的四个字节。

代码如下:

Keccak.Digest256 digest256 = new Keccak.Digest256();
System.out.println(Hex.toHexString(digest256.digest("setMap(bytes32,string,address[],bytes32)".getBytes())).substring(0, 8));

可以得到此函数签名为:dc913337

还有一种特殊的签名,叫event事件签名:

Keccak.Digest256 digest256 = new Keccak.Digest256(); 

System.out.println(Hex.toHexString(digest256.digest("LogCreate(address)".getBytes())));

得到的事件签名值:

b8f132fb6526e0405f3ce4f3bab301f1d4409b1e7f2c01c2037d6cf845c831cb

关于合约函数签名文档生成,我在业余时间写了个java小工具,目前已在github上开源,地址已经放在文末。那么为什么需要这个合约签名文档呢?

 

三.开发协调

  以太坊合约函数签名文档,可以理解成接口文档,主要作用有:

第一:由于合约开发者和合约调用者,可能是不同的开发人员。调用合约者需要知道合约的函数签名,同时也可以验证自己拼接的函数签名以及参数是否正确。

第二:调用者需要知道合约原始的方法名以及参数类型,尤其是明确需要知道参数的顺序,否则无法生成正确的函数签名。那么此时就需要合约方法的文档来作为调用者参考媒介。出于此功能的需要,就自己动手丰衣足食做了个规范化的合约函数签名文档生成工具。

  在生成合约函数签名文档之前,需要使用truffle或者solc。truffle是以太坊合约开发的脚手架,使用truffle将完成开发的合约编译成json文件。或者使用solc将合约编译成abi文件。最后使用 ethSignUtil.jar 工具生成函数签名文档以及合约接口文档。简单看下效果图

函数签名:

 

合约接口:

 

 

关于合约函数签名文档生成的具体用法,请移步至github:

https://github.com/zhjgit/Ethereum-util

 

持续关注"刻意链习"公众号,获取更多区块链技术知识。转载请注明文章出处,原创技术贴,侵权必纠。

             

posted on 2018-12-10 18:28  苏铭客  阅读(2006)  评论(0编辑  收藏  举报