Transaction analysis¶
The transaction in FISCO BCOS is the request data toward blockchain system to deploy contract, call contract API, maintain contract lifecycle and manage assets, value exchange, etc. There will be transaction receipt after it is confirmed: Transaction receipt and Transaction are all stored in block to record the information generated during transaction execution, like result code, log, consumed gas amount, etc. User can use transaction hash to retrieve transaction receipt and know whether the transaction is accomplished.
Transaction receipt contains three key fields: input (currently fisco bcos compiled by dev branch includes this field), output, logs.
| field | type | description |
|---|---|---|
| input | String | ABI coded hexadecimal string input by transaction |
| output | String | ABI coded hexadecimal string returned by transaction |
| logs | List |
event log list storing event information of transaction |
Transaction analysis can help user to analyze the 3 fields as json data and java object.
Important
code - fisco bcos
- web3sdk
branch:https://github.com/FISCO-BCOS/web3sdk/tree/dev
maven version:2.0.34-SNAPSHOT
Import jar packet¶
Analysis tool class is in web3sdk. First, add the following configurations in build.gradle config file and import web3sdk jar packet.
repositories {
maven { url "http://maven.aliyun.com/nexus/content/groups/public/" }
maven { url "https://dl.bintray.com/ethereum/maven/" }
maven { url "https://oss.sonatype.org/content/repositories/snapshots" }
mavenCentral()
}
compile group: "org.fisco-bcos", name: "web3sdk", version: "2.0.34-SNAPSHOT"
API description¶
Code packet route org.fisco.bcos.web3j.tx.txdecode, use TransactionDecoderFactory factory class to build transaction decoder TransactionDecoder. There are 2 ways:
TransactionDecoder buildTransactionDecoder(String abi, String bin);abi:contract ABI
bin:contract bin, can import empty string “” when not available
TransactionDecoder buildTransactionDecoder(String contractName);contractName:contract name, create
soliditydirectory under root directory of the application, put the contract undersoliditydirectory and get transaction decoder through contract name.
Transaction decoder TransactionDecoder API list:
String decodeInputReturnJson(String input)Analyze input, seal the result as json character string in json format
{"data":[{"name":"","type":"","data":} ... ],"function":"","methodID":""}function : function signature string methodID : function selector
List<ResultEntity> decodeInputReturnObject(String input)Analyze input, return java List object, ResultEntity structure
public class ResultEntity { private String name; // field name, analyze output and return with empty string private String type; // field type private Object data; // field value }
String decodeOutputReturnJson(String input, String output)Analyze output, seal the result as json string, the same format with
decodeInputReturnJsonList<ResultEntity> decodeOutputReturnObject(String input, String output)Analyze output, return java List object
String decodeEventReturnJson(List<Log> logList)Analyze event list, seal the result as json string with json format
{"event1 signature":[[{"name":"_u","type":"","data":}...]...],"event2 signature":[[{"name":"_u","type":"","data":}...]...]...}Map<String, List<List<ResultEntity>>> decodeEventReturnObject(List<Log> logList)Analyze event list, return java Map object, key is event signature string, List<List
> is all the event parameter information in the transaction.
TransactionDecoder provides methods of returning json string and java object respectively to input, output and event logs. Json string helps client end to easily deal data. Java object helps to easily deal data for server.
Example¶
Here is an example of TxDecodeSample contract to describe the use of API:
pragma solidity ^0.4.24;
contract TxDecodeSample
{
event Event1(uint256 _u,int256 _i,bool _b,address _addr,bytes32 _bs32, string _s,bytes _bs);
event Event2(uint256 _u,int256 _i,bool _b,address _addr,bytes32 _bs32, string _s,bytes _bs);
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)
{
Event1(_u, _i, _b, _addr, _bs32, _s, _bs);
return (_u, _i, _b, _addr, _bs32, _s, _bs);
}
function do_event(uint256 _u,int256 _i,bool _b,address _addr,bytes32 _bs32, string _s,bytes _bs) public
{
Event1(_u, _i, _b, _addr, _bs32, _s, _bs);
Event2(_u, _i, _b, _addr, _bs32, _s, _bs);
}
}
Use buildTransactionDecoder to build the transaction decoder of TxDecodeSample contract.
// TxDecodeSample合约ABI
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\"}]";
String bin = "";
TransactionDecoder txDecodeSampleDecoder = TransactionDecoder.buildTransactionDecoder(abi, bin);
Analyze input¶
Call function echo(uint256 _u,int256 _i,bool _b,address _addr,bytes32 _bs32, string _s,bytes _bs) API, input parameter [ 111111 -1111111 false 0x692a70d2e424a56d2c6c27aa97d1a86395877b3a abcdefghiabcdefghiabcdefghiabhji 章鱼小丸子ljjkl;adjsfkljlkjl sadfljkjkljkl ]
// function echo(uint256 _u,int256 _i,bool _b,address _addr,bytes32 _bs32, string _s,bytes _bs)
String input = “0x406d373b000000000000000000000000000000000000000000000000000000000001b207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffef0bb90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000692a70d2e424a56d2c6c27aa97d1a86395877b3a6162636465666768696162636465666768696162636465666768696162686a6900000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000021e7aba0e9b1bce5b08fe4b8b8e5ad906c6a6a6b6c3b61646a73666b6c6a6c6b6a6c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d736164666c6a6b6a6b6c6a6b6c00000000000000000000000000000000000000”;
String jsonResult = txDecodeSampleDecoder.decodeInputReturnJson(input);
List<ResultEntity> listResult = txDecodeSampleDecoder.decodeInputReturnObject(input);
System.out.println("json => \n" + jsonResult);
System.out.println("list => \n" + listResult);
Output:
json =>
{
"data": [
{
"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"
}
],
"function": "echo(uint256,int256,bool,address,bytes32,string,bytes)",
"methodID": "0x406d373b"
}
list =>
[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]]
Analyze output¶
Call function echo(uint256 _u,int256 _i,bool _b,address _addr,bytes32 _bs32, string _s,bytes _bs) API, input parameter [ 111111 -1111111 false 0x692a70d2e424a56d2c6c27aa97d1a86395877b3a abcdefghiabcdefghiabcdefghiabhji 章鱼小丸子ljjkl;adjsfkljlkjl sadfljkjkljkl ], echo API returns what is input.
// 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)
String input = “0x406d373b000000000000000000000000000000000000000000000000000000000001b207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffef0bb90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000692a70d2e424a56d2c6c27aa97d1a86395877b3a6162636465666768696162636465666768696162636465666768696162686a6900000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000021e7aba0e9b1bce5b08fe4b8b8e5ad906c6a6a6b6c3b61646a73666b6c6a6c6b6a6c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d736164666c6a6b6a6b6c6a6b6c00000000000000000000000000000000000000”;
String output = "000000000000000000000000000000000000000000000000000000000001b207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffef0bb90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000692a70d2e424a56d2c6c27aa97d1a86395877b3a6162636465666768696162636465666768696162636465666768696162686a6900000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000021e7aba0e9b1bce5b08fe4b8b8e5ad906c6a6a6b6c3b61646a73666b6c6a6c6b6a6c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d736164666c6a6b6a6b6c6a6b6c00000000000000000000000000000000000000";
String jsonResult = txDecodeSampleDecoder.decodeOutputReturnJson(input, output);
List<ResultEntity> listResult = txDecodeSampleDecoder.decodeOutputReturnObject(input, output);
System.out.println("json => \n" + jsonResult);
System.out.println("list => \n" + listResult);
Result:
json =>
[
{
"name": "",
"type": "uint256",
"data": 111111
},
{
"name": "",
"type": "int256",
"data": -1111111
},
{
"name": "",
"type": "bool",
"data": false
},
{
"name": "",
"type": "address",
"data": "0x692a70d2e424a56d2c6c27aa97d1a86395877b3a"
},
{
"name": "",
"type": "bytes32",
"data": "abcdefghiabcdefghiabcdefghiabhji"
},
{
"name": "",
"type": "string",
"data": "章鱼小丸子ljjkl;adjsfkljlkjl"
},
{
"name": "",
"type": "bytes",
"data": "sadfljkjkljkl"
}
]
list =>
[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]]
Analyze event logs¶
Call function do_event(uint256 _u,int256 _i,bool _b,address _addr,bytes32 _bs32, string _s,bytes _bs) API, input parameter [ 111111 -1111111 false 0x692a70d2e424a56d2c6c27aa97d1a86395877b3a abcdefghiabcdefghiabcdefghiabhji 章鱼小丸子ljjkl;adjsfkljlkjl sadfljkjkljkl ], analyze transaction logs
// transactionReceipt is the transaction receipt of calling do_event API
String jsonResult = txDecodeSampleDecoder.decodeEventReturnJson(transactionReceipt.getLogs());
String mapResult = txDecodeSampleDecoder.decodeEventReturnJson(transactionReceipt.getLogs());
System.out.println("json => \n" + jsonResult);
System.out.println("map => \n" + mapResult);
Result:
jsonResult =>
{
"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"
}
]
]
}
map =>
{"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"}]]}