Skip to content
maggie edited this page Sep 27, 2020 · 3 revisions

ABI模块

  • 功能

  • 重构目标

  • 模块关联

  • 类图

  • 接口

  • 示例

1.功能

提供Solidity ABI编解码工具集

2.重构目标

  1. 完善类型支持

    • 支持完整ABI类型,完善对ABIEncodeV2 struct类型的支持
  2. 提供友好/完整的ABI工具类

    • 易用性
      • 支持完整类型的ABI编解码
      • JavaSDK其他模块易于集成
    • 特定需求
      • 支持字符串参数
      • 支持函数signature入参描述ABI
    • 其他
      • 国密/非国密hash接口依赖整理

3.模块关联

参考 JavaSDK 重构整体架构

4.类图

image

5. 接口

支持两种参数形式:

  • Java对象参数
  • 字符串参数

我们将ABI Codec和ABICodecJsonWrapper合并成一个类

public class ABICodec {
  // Encode method
  String encodeMethod(String ABI, String methodName, List<Object> params) throws ABICodecException;
  String encodeMethodById(String ABI, String methodId, List<Object> params) throws ABICodecException;
  String encodeMethodByInterface(String methodInterface, List<Object> params) throws ABICodecException;
  String encodeMethodFromString (String ABI, String methodName, List<String> params) throws ABICodecException;
  String encodeMethodByIdFromString(String ABI, String methodId, List<String> params) throws ABICodecException;
  String encodeMethodByInterfaceFromString(String methodInterface, List<String> params) throws ABICodecException;
  // Encode event
  String encodeEvent(String ABI, String eventName, List<Object> params) throws ABICodecException;
  String encodeEventByTopic(String ABI, String eventTopic, List<Object> params) throws ABICodecException;
  String encodeEventByInterface(String eventSignature, List<Object> params) throws ABICodecException;
  String encodeEventFromString(String ABI, String eventName, List<String> params) throws ABICodecException;
  String encodeEventByTopicFromString(String ABI, String eventTopic, List<String> params) throws ABICodecException;
  String encodeEventByInterfaceFromString(String eventSignature, List<String> params) throws ABICodecException;
  // Decode method
  List<Object> decodeMethod(String ABI, String methodName, String output) throws ABICodecException;
  List<Object> decodeMethodById(String ABI, String methodId, String output) throws ABICodecException;
  List<Object> decodeMethodByInterface(String methodSignature, String output) throws ABICodecException;
  List<String> decodeMethodToString(String ABI, String methodName, String output) throws ABICodecException;
  List<String> decodeMethodByIdToString(String ABI, String methodId, String output) throws ABICodecException;
  List<String> decodeMethodByInterfaceToString(String methodSignature, String output) throws ABICodecException;
  // Decode event
  List<Object> decodeEvent(String ABI, String eventName, String output) throws ABICodecException;
  List<Object> decodeEventByTopic(String ABI, String eventTopic, String output) throws ABICodecException;
  List<Object> decodeEventByInterface(String eventSignature, String output) throws ABICodecException;
  List<String> decodeEventToString(String ABI, String eventName, String output) throws ABICodecException;
  List<String> decodeEventByTopicToString(String ABI, String eventTopic, String output) throws ABICodecException;
  List<String> decodeEventByInterfaceToString(String eventSignature, String output) throws ABICodecException;
}

Java Object与solidity类型映射关系:

uint => BigInteger
int => BigInteger
bool => boolean
address => Address
string => String
bytes => byte[]
bytesN => byte[]
tuple => List
T[] => List
T[N] => List

ABI编解码模块可以接受字符串类型的入参数,内部进行类型初始化,对于复杂类型T[] T[N] tuple可以使用JSON字符串表示。

6.示例

示例合约

pragma solidity>=0.5.0 <0.6.11;
pragma experimental ABIEncoderV2;
contract TupleTest {
    
    event SetEvent(int i, Item item, string s);
    
    struct Item {
        int a;
        int b;
        int c;
    }
    
    int i;
    Item item;
    string s;
    
    function set(int _i, Item memory _item, string memory _s) public {
        i = _i;
        item = _item;
        s = _s;
    }

    function get() view public returns(int, Item memory, string memory) {
        return (i, item, s);
    }
}

ABI:

[{"constant":false,"inputs":[{"name":"_i","type":"int256"},{"components":[{"name":"a","type":"int256"},{"name":"b","type":"int256"},{"name":"c","type":"int256"}],"name":"_item","type":"tuple"},{"name":"_s","type":"string"}],"name":"set","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"get","outputs":[{"name":"","type":"int256"},{"components":[{"name":"a","type":"int256"},{"name":"b","type":"int256"},{"name":"c","type":"int256"}],"name":"","type":"tuple"},{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"i","type":"int256"},{"components":[{"name":"a","type":"int256"},{"name":"b","type":"int256"},{"name":"c","type":"int256"}],"indexed":false,"name":"item","type":"tuple"},{"indexed":false,"name":"s","type":"string"}],"name":"SetEvent","type":"event"}]

函数参数编码

  • 接口: set
  • 参数:
    • int i: 1
    • Item item: tuple(2, 3, 4)
    • string s: "Hello World"

Java Object参数

  1. 方式一: 合约ABI + 接口名
String abi = "[{"constant":false,"inputs":[{"name":"_i","type":"int256"},{"components":[{"name":"a","type":"int256"},{"name":"b","type":"int256"},{"name":"c","type":"int256"}],"name":"_item","type":"tuple"},{"name":"_s","type":"string"}],"name":"set","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"get","outputs":[{"name":"","type":"int256"},{"components":[{"name":"a","type":"int256"},{"name":"b","type":"int256"},{"name":"c","type":"int256"}],"name":"","type":"tuple"},{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"i","type":"int256"},{"components":[{"name":"a","type":"int256"},{"name":"b","type":"int256"},{"name":"c","type":"int256"}],"indexed":false,"name":"item","type":"tuple"},{"indexed":false,"name":"s","type":"string"}],"name":"SetEvent","type":"event"}]";

ABICodec abiCodec = new ABICodec();

String abiEncoded = abiCodec.encodeMethod(abi, "set", new Object[]{1, new ArrayList<> {2,3,4}, new String("Hello World")});
  1. 方式二: 接口signature
ABICodec abiCodec = new ABICodec();

String setMethodSignature = "set(int,tuple(int,int,int),string)";
String abiEncoded = abiCodec.encodeMethodByMethodSignature(setMethodSignature, new Object[]{1, new ArrayList<> {2,3,4}, new String("Hello World")});

字符串参数

  1. 方式一: 合约ABI + 接口名 + 字符串入参
ABICodecJsonWrapper abiCodecJsonWrapper = new ABICodecJsonWrapper();

String abi = "";
String abiEncoded = abiCodecJsonWrapper.encodeMethod(abi, "set", new String[]{"1", "\"[1,2,3]\"", "Hello World"});
  1. 方式一: 接口signature + 字符串入参
ABICodecJsonWrapper abiCodecJsonWrapper = new ABICodecJsonWrapper();

String setMethodSignature = "set(int,tuple(int,int,int),string)";
String abiEncoded = abiCodec.encodeMethodByMethodSignature(setMethodSignature, new String[]{"1", "\"[1,2,3]\"", "Hello World"});
Clone this wiki locally