交易解析

FISCO BCOS的交易是一段发往区块链系统的请求数据,用于部署合约,调用合约接口,维护合约的生命周期以及管理资产,进行价值交换等。当交易确认后会产生交易回执,交易回执交易均保存在区块里,用于记录交易执行过程生成的信息,如结果码、日志、消耗的gas量等。用户可以使用交易哈希查询交易回执,判定交易是否完成。

交易回执包含三个关键字段,分别是input(目前dev分支编译的fisco bcos包含该字段,后续合入2.0.0版本), output , logs:

字段类型描述
inputString交易输入的ABI编码十六进制字符串
outputString交易返回的ABI编码十六进制字符串
logsListevent log列表,保存交易的event信息

交易解析功能帮助用户解析这三个字段为json数据和java对象。

重要

代码- fisco bcos

  • web3sdk

分支:https://github.com/FISCO-BCOS/web3sdk/tree/dev

maven版本:2.0.34-SNAPSHOT

引入jar包

解析工具类在web3sdk中,应用需要首先在build.gradle配置文件中增加如下配置,引入web3sdk jar包。

  1. repositories {
  2. maven { url "http://maven.aliyun.com/nexus/content/groups/public/" }
  3. maven { url "https://dl.bintray.com/ethereum/maven/" }
  4. maven { url "https://oss.sonatype.org/content/repositories/snapshots" }
  5. mavenCentral()
  6. }
  7. compile group: "org.fisco-bcos", name: "web3sdk", version: "2.0.34-SNAPSHOT"

接口说明

代码包路径org.fisco.bcos.web3j.tx.txdecode,使用TransactionDecoderFactory工厂类建立交易解析对象TransactionDecoder,有两种方式:

  • TransactionDecoder buildTransactionDecoder(String abi, String bin);

abi:合约的ABI

bin:合约bin,暂无使用,可以直接传入空字符串””

  • TransactionDecoder buildTransactionDecoder(String contractName);

contractName:合约名称,在应用的根目录下创建solidity目录,将交易相关的合约放在solidity目录,通过指定合约名获取交易解析对象

交易解析对象TransactionDecoder接口列表:

  • String decodeInputReturnJson(String input)

解析input,将结果封装为json字符串,json格式

  1. {"data":[{"name":"","type":"","data":} ... ],"function":"","methodID":""}

function : 函数签名字符串methodID : 函数选择器

  • List<ResultEntity> decodeInputReturnObject(String input)

解析input,返回java List对象,ResultEntity结构

  1. public class ResultEntity {
  2. private String name; // 字段名称, 解析output返回时,值为空字符串
  3. private String type; // 字段类型
  4. private Object data; // 字段值
  5. }
  • String decodeOutputReturnJson(String input, String output)

解析output,将结果封装为json字符串,格式同decodeInputReturnJson

  • List<ResultEntity> decodeOutputReturnObject(String input, String output)

解析output,返回java List对象

  • String decodeEventReturnJson(List<Log> logList)

解析event列表,将结果封装为json字符串,json格式

  1. {"event1签名":[[{"name":"_u","type":"","data":}...]...],"event2签名":[[{"name":"_u","type":"","data":}...]...]...}
  • Map<String, List<List<ResultEntity>>> decodeEventReturnObject(List<Log> logList)

解析event列表,返回java Map对象,key为event签名字符串,List为交易中所有的event参数信息TransactionDecoder对input,output和event logs均分别提供返回json字符串和java对象的方法。json字符串方便客户端处理数据,java对象方便服务端处理数据。

示例

TxDecodeSample合约为例说明接口的使用:

  1. pragma solidity ^0.4.24;
  2. contract TxDecodeSample
  3. {
  4. event Event1(uint256 _u,int256 _i,bool _b,address _addr,bytes32 _bs32, string _s,bytes _bs);
  5. event Event2(uint256 _u,int256 _i,bool _b,address _addr,bytes32 _bs32, string _s,bytes _bs);
  6.  
  7.  
  8. function echo(uint256 _u,int256 _i,bool _b,address _addr,bytes32 _bs32, string _s,bytes _bs) public constant returns (uint256,int256,bool,address,bytes32,string,bytes)
  9. {
  10. Event1(_u, _i, _b, _addr, _bs32, _s, _bs);
  11. return (_u, _i, _b, _addr, _bs32, _s, _bs);
  12. }
  13.  
  14. function do_event(uint256 _u,int256 _i,bool _b,address _addr,bytes32 _bs32, string _s,bytes _bs) public
  15. {
  16. Event1(_u, _i, _b, _addr, _bs32, _s, _bs);
  17. Event2(_u, _i, _b, _addr, _bs32, _s, _bs);
  18. }
  19. }

使用buildTransactionDecoder 创建TxDecodeSample合约的解析对象:

  1. // TxDecodeSample合约ABI
  2. String abi = "[{\"constant\":false,\"inputs\":[{\"name\":\"_u\",\"type\":\"uint256\"},{\"name\":\"_i\",\"type\":\"int256\"},{\"name\":\"_b\",\"type\":\"bool\"},{\"name\":\"_addr\",\"type\":\"address\"},{\"name\":\"_bs32\",\"type\":\"bytes32\"},{\"name\":\"_s\",\"type\":\"string\"},{\"name\":\"_bs\",\"type\":\"bytes\"}],\"name\":\"do_event\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"_u\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"_i\",\"type\":\"int256\"},{\"indexed\":false,\"name\":\"_b\",\"type\":\"bool\"},{\"indexed\":false,\"name\":\"_addr\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_bs32\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"_s\",\"type\":\"string\"},{\"indexed\":false,\"name\":\"_bs\",\"type\":\"bytes\"}],\"name\":\"Event1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"_u\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"_i\",\"type\":\"int256\"},{\"indexed\":false,\"name\":\"_b\",\"type\":\"bool\"},{\"indexed\":false,\"name\":\"_addr\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_bs32\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"_s\",\"type\":\"string\"},{\"indexed\":false,\"name\":\"_bs\",\"type\":\"bytes\"}],\"name\":\"Event2\",\"type\":\"event\"},{\"constant\":true,\"inputs\":[{\"name\":\"_u\",\"type\":\"uint256\"},{\"name\":\"_i\",\"type\":\"int256\"},{\"name\":\"_b\",\"type\":\"bool\"},{\"name\":\"_addr\",\"type\":\"address\"},{\"name\":\"_bs32\",\"type\":\"bytes32\"},{\"name\":\"_s\",\"type\":\"string\"},{\"name\":\"_bs\",\"type\":\"bytes\"}],\"name\":\"echo\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"},{\"name\":\"\",\"type\":\"int256\"},{\"name\":\"\",\"type\":\"bool\"},{\"name\":\"\",\"type\":\"address\"},{\"name\":\"\",\"type\":\"bytes32\"},{\"name\":\"\",\"type\":\"string\"},{\"name\":\"\",\"type\":\"bytes\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}]";
  3. String bin = "";
  4. TransactionDecoder txDecodeSampleDecoder = TransactionDecoder.buildTransactionDecoder(abi, bin);

解析input

调用function echo(uint256 _u,int256 _i,bool _b,address _addr,bytes32 _bs32, string _s,bytes _bs) 接口,输入参数为[ 111111 -1111111 false 0x692a70d2e424a56d2c6c27aa97d1a86395877b3a abcdefghiabcdefghiabcdefghiabhji 章鱼小丸子ljjkl;adjsfkljlkjl sadfljkjkljkl ]

  1. // function echo(uint256 _u,int256 _i,bool _b,address _addr,bytes32 _bs32, string _s,bytes _bs)
  2. String input = 0x406d373b000000000000000000000000000000000000000000000000000000000001b207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffef0bb90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000692a70d2e424a56d2c6c27aa97d1a86395877b3a6162636465666768696162636465666768696162636465666768696162686a6900000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000021e7aba0e9b1bce5b08fe4b8b8e5ad906c6a6a6b6c3b61646a73666b6c6a6c6b6a6c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d736164666c6a6b6a6b6c6a6b6c00000000000000000000000000000000000000”;
  3. String jsonResult = txDecodeSampleDecoder.decodeInputReturnJson(input);
  4. List<ResultEntity> listResult = txDecodeSampleDecoder.decodeInputReturnObject(input);
  5. System.out.println("json => \n" + jsonResult);
  6. System.out.println("list => \n" + listResult);

输出:

  1. json =>
  2. {
  3. "data": [
  4. {
  5. "name": "_u",
  6. "type": "uint256",
  7. "data": 111111
  8. },
  9. {
  10. "name": "_i",
  11. "type": "int256",
  12. "data": -1111111
  13. },
  14. {
  15. "name": "_b",
  16. "type": "bool",
  17. "data": false
  18. },
  19. {
  20. "name": "_addr",
  21. "type": "address",
  22. "data": "0x692a70d2e424a56d2c6c27aa97d1a86395877b3a"
  23. },
  24. {
  25. "name": "_bs32",
  26. "type": "bytes32",
  27. "data": "abcdefghiabcdefghiabcdefghiabhji"
  28. },
  29. {
  30. "name": "_s",
  31. "type": "string",
  32. "data": "章鱼小丸子ljjkl;adjsfkljlkjl"
  33. },
  34. {
  35. "name": "_bs",
  36. "type": "bytes",
  37. "data": "sadfljkjkljkl"
  38. }
  39. ],
  40. "function": "echo(uint256,int256,bool,address,bytes32,string,bytes)",
  41. "methodID": "0x406d373b"
  42. }
  43.  
  44. list =>
  45. [ResultEntity [name=_u, type=uint256, data=111111], ResultEntity [name=_i, type=int256, data=-1111111], ResultEntity [name=_b, type=bool, data=false], ResultEntity [name=_addr, type=address, data=0x692a70d2e424a56d2c6c27aa97d1a86395877b3a], ResultEntity [name=_bs32, type=bytes32, data=abcdefghiabcdefghiabcdefghiabhji], ResultEntity [name=_s, type=string, data=章鱼小丸子ljjkl;adjsfkljlkjl], ResultEntity [name=_bs, type=bytes, data=sadfljkjkljkl]]

解析output

调用function echo(uint256 _u,int256 _i,bool _b,address _addr,bytes32 _bs32, string _s,bytes _bs) 接口,输入参数为[ 111111 -1111111 false 0x692a70d2e424a56d2c6c27aa97d1a86395877b3a abcdefghiabcdefghiabcdefghiabhji 章鱼小丸子ljjkl;adjsfkljlkjl sadfljkjkljkl ],echo接口直接将输入返回,因此返回与输入相同

  1. // function echo(uint256 _u,int256 _i,bool _b,address _addr,bytes32 _bs32, string _s,bytes _bs) public constant returns (uint256,int256,bool,address,bytes32,string,bytes)
  2. String input = 0x406d373b000000000000000000000000000000000000000000000000000000000001b207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffef0bb90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000692a70d2e424a56d2c6c27aa97d1a86395877b3a6162636465666768696162636465666768696162636465666768696162686a6900000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000021e7aba0e9b1bce5b08fe4b8b8e5ad906c6a6a6b6c3b61646a73666b6c6a6c6b6a6c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d736164666c6a6b6a6b6c6a6b6c00000000000000000000000000000000000000”;
  3.  
  4. String output = "000000000000000000000000000000000000000000000000000000000001b207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffef0bb90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000692a70d2e424a56d2c6c27aa97d1a86395877b3a6162636465666768696162636465666768696162636465666768696162686a6900000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000021e7aba0e9b1bce5b08fe4b8b8e5ad906c6a6a6b6c3b61646a73666b6c6a6c6b6a6c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d736164666c6a6b6a6b6c6a6b6c00000000000000000000000000000000000000";
  5.  
  6. String jsonResult = txDecodeSampleDecoder.decodeOutputReturnJson(input, output);
  7. List<ResultEntity> listResult = txDecodeSampleDecoder.decodeOutputReturnObject(input, output);
  8. System.out.println("json => \n" + jsonResult);
  9. System.out.println("list => \n" + listResult);

结果:

  1. json =>
  2. [
  3. {
  4. "name": "",
  5. "type": "uint256",
  6. "data": 111111
  7. },
  8. {
  9. "name": "",
  10. "type": "int256",
  11. "data": -1111111
  12. },
  13. {
  14. "name": "",
  15. "type": "bool",
  16. "data": false
  17. },
  18. {
  19. "name": "",
  20. "type": "address",
  21. "data": "0x692a70d2e424a56d2c6c27aa97d1a86395877b3a"
  22. },
  23. {
  24. "name": "",
  25. "type": "bytes32",
  26. "data": "abcdefghiabcdefghiabcdefghiabhji"
  27. },
  28. {
  29. "name": "",
  30. "type": "string",
  31. "data": "章鱼小丸子ljjkl;adjsfkljlkjl"
  32. },
  33. {
  34. "name": "",
  35. "type": "bytes",
  36. "data": "sadfljkjkljkl"
  37. }
  38. ]
  39.  
  40. list =>
  41. [ResultEntity [name=, type=uint256, data=111111], ResultEntity [name=, type=int256, data=-1111111], ResultEntity [name=, type=bool, data=false], ResultEntity [name=, type=address, data=0x692a70d2e424a56d2c6c27aa97d1a86395877b3a], ResultEntity [name=, type=bytes32, data=abcdefghiabcdefghiabcdefghiabhji], ResultEntity [name=, type=string, data=章鱼小丸子ljjkl;adjsfkljlkjl], ResultEntity [name=, type=bytes, data=sadfljkjkljkl]]

解析event logs

调用function do_event(uint256 _u,int256 _i,bool _b,address _addr,bytes32 _bs32, string _s,bytes _bs) 接口,输入参数为[ 111111 -1111111 false 0x692a70d2e424a56d2c6c27aa97d1a86395877b3a abcdefghiabcdefghiabcdefghiabhji 章鱼小丸子ljjkl;adjsfkljlkjl sadfljkjkljkl ],解析交易中的logs

  1. // transactionReceipt为调用do_event接口的交易回执
  2. String jsonResult = txDecodeSampleDecoder.decodeEventReturnJson(transactionReceipt.getLogs());
  3. String mapResult = txDecodeSampleDecoder.decodeEventReturnJson(transactionReceipt.getLogs());
  4.  
  5. System.out.println("json => \n" + jsonResult);
  6. System.out.println("map => \n" + mapResult);

结果:

  1. jsonResult =>
  2. {
  3. "Event1(uint256,int256,bool,address,bytes32,string,bytes)": [
  4. [
  5. {
  6. "name": "_u",
  7. "type": "uint256",
  8. "data": 111111
  9. },
  10. {
  11. "name": "_i",
  12. "type": "int256",
  13. "data": -1111111
  14. },
  15. {
  16. "name": "_b",
  17. "type": "bool",
  18. "data": false
  19. },
  20. {
  21. "name": "_addr",
  22. "type": "address",
  23. "data": "0x692a70d2e424a56d2c6c27aa97d1a86395877b3a"
  24. },
  25. {
  26. "name": "_bs32",
  27. "type": "bytes32",
  28. "data": "abcdefghiabcdefghiabcdefghiabhji"
  29. },
  30. {
  31. "name": "_s",
  32. "type": "string",
  33. "data": "章鱼小丸子ljjkl;adjsfkljlkjl"
  34. },
  35. {
  36. "name": "_bs",
  37. "type": "bytes",
  38. "data": "sadfljkjkljkl"
  39. }
  40. ]
  41. ],
  42. "Event2(uint256,int256,bool,address,bytes32,string,bytes)": [
  43. [
  44. {
  45. "name": "_u",
  46. "type": "uint256",
  47. "data": 111111
  48. },
  49. {
  50. "name": "_i",
  51. "type": "int256",
  52. "data": -1111111
  53. },
  54. {
  55. "name": "_b",
  56. "type": "bool",
  57. "data": false
  58. },
  59. {
  60. "name": "_addr",
  61. "type": "address",
  62. "data": "0x692a70d2e424a56d2c6c27aa97d1a86395877b3a"
  63. },
  64. {
  65. "name": "_bs32",
  66. "type": "bytes32",
  67. "data": "abcdefghiabcdefghiabcdefghiabhji"
  68. },
  69. {
  70. "name": "_s",
  71. "type": "string",
  72. "data": "章鱼小丸子ljjkl;adjsfkljlkjl"
  73. },
  74. {
  75. "name": "_bs",
  76. "type": "bytes",
  77. "data": "sadfljkjkljkl"
  78. }
  79. ]
  80. ]
  81. }
  82.  
  83. map =>
  84. {"Event1(uint256,int256,bool,address,bytes32,string,bytes)":[[{"name":"_u","type":"uint256","data":111111},{"name":"_i","type":"int256","data":-1111111},{"name":"_b","type":"bool","data":false},{"name":"_addr","type":"address","data":"0x692a70d2e424a56d2c6c27aa97d1a86395877b3a"},{"name":"_bs32","type":"bytes32","data":"abcdefghiabcdefghiabcdefghiabhji"},{"name":"_s","type":"string","data":"章鱼小丸子ljjkl;adjsfkljlkjl"},{"name":"_bs","type":"bytes","data":"sadfljkjkljkl"}]],"Event2(uint256,int256,bool,address,bytes32,string,bytes)":[[{"name":"_u","type":"uint256","data":111111},{"name":"_i","type":"int256","data":-1111111},{"name":"_b","type":"bool","data":false},{"name":"_addr","type":"address","data":"0x692a70d2e424a56d2c6c27aa97d1a86395877b3a"},{"name":"_bs32","type":"bytes32","data":"abcdefghiabcdefghiabcdefghiabhji"},{"name":"_s","type":"string","data":"章鱼小丸子ljjkl;adjsfkljlkjl"},{"name":"_bs","type":"bytes","data":"sadfljkjkljkl"}]]}