附录 A Solidity与Java的编码解码

类型对应

当使用LiteSDK编译solidity合约时,由于java和solidity本身类型的不兼容,所以在调用solidity方法传参数的时候需要对java类型进行相应的编码解码,LiteSDK内部的Abi类,与solidity的abi文件对应,用来提供solidity合约的函数入参、返回值等信息,方便我们对solidity类型和java类型做转换,目前Litesdk支持的对应类型如下:

JAVASOLIDITY
boolean/Booleanbool
BigIntegerint、int8、int16……int256
BigIntegeruint、uint8、uint16……uint256
Stringstring
byte[]/Byte[]bytes、bytes1、bytes2……bytes32
stringaddress
Array/Listarray

编码

编码时需要提供以下信息:

  • solidity合约对应的abi对象,
  • 调用方法名
  • 封装后的java参数

实现java与solidity之间的类型转换。(注:如果是部署需要提供bin文件,具体参照部署合约一节)

Abi对象

通过LiteSDK提供的FileUtil工具类读取文件内容得到abi字符串,并利用Abi类的fromJson方法生成封装的Abi对象,使用方法如下:

  1. InputStream abiIs = Thread.currentThread().getContextClassLoader().getResourceAsStream("xxx.abi");
  2. String abiStr = FileUtil.readFile(abiIs);
  3. Abi abi = Abi.fromJson(abiStr);
调用方法名

调用方法名需要按格式$(method_name)(type1[,type2…])填,假如solidity的函数签名为

  1. function TestUint(uint8 a) returns (uint8) {
  2. return a;
  3. }

则我们提供的调用方法名为TestUint(uint8),如果函数多个参数,则调用方法名的类型之间用,分隔。

封装的java参数

LiteSDK提供了FuncParams工具类封装需要转换成solidity类型的java参数,使用方法如下:

  1. FuncParams params = new FuncParams();
  2. // param 是类型对应表里对应的java参数
  3. params.addParams(param1);
  4. params.addParams(param2);
  5. // 构造交易时将构造好的FuncParams对象传进去
  6. Transaction transaction = new Transaction.EVMBuilder(account.getAddress()).invoke(contractAddress, <method_name>, abi, params).build();

解码

解码与编码类似,需要提供Abi对象、方法名和编码的solidity结果,具体可见编码一节。

调用evm合约得到交易回执ReceiptResponse后,需要对solidity合约的返回值进行解析,使用方法如下:

  1. String ret = receiptResponse.getRet();
  2. byte[] fromHex = ByteUtil.fromHex(ret);
  3. // 通过abi的方法名解码,由于返回值可能有多个,所以解码得到的其实是一个List<?>,当中的每个对象
  4. // 对应一个返回值。如该例子返回值为 int256,在java中对应的是BigInter,所以对返回的decodeResult
  5. // 遍历强转为BigInteger
  6. List<?> decodeResult = abi.getFunction("TestInt(int256)").decodeResult(fromHex);
  7. for (Object result : decodeResult) {
  8. System.out.println(result.getClass());
  9. System.out.println(((BigInteger) result).toString());
  10. }