本文章主要寫調用合約發送交易參數組裝編碼過程;java
在web3j源碼中有一個codegen module模塊,其中有個項功能是將solidity文件轉換成java文件,該文件包含了合約的全部接口與deploy、load,這樣對其餘程序員來講,下降了他們對接區塊鏈與智能合約時的學習成本;但這種方式也存在一些弊端,須要改進,如每編寫一個合約都須要手動的生成一個對應的java文件,若是合約隨着業務的變化一直在變,那麼就須要不停的更新java文件,並附加到項目工程中,致使沒更新一個合約就要從新更新項目版本;程序員
so爲了解決這個問題,只能拋棄web3j的方法,使用輸入參數的形式,也就是部署合約與調用合約接口由專門的統一接口提供; 如:部署合約接口(deploy)、調用合約接口,發送交易(sendContractTransaction)、調用合約接口,不發生交易(callContract)。 下面就對這3個接口作一個詳細的解析;由於每一個鏈都有不一樣的數據結構和標準,因此這裏以eth爲例,其餘以太坊系列的使用solidity語言的相似一次類推;web
這裏不講智能合約具體是啥,幹什麼用,若想了解可參考小編的另外一篇關於solidity的博客;json
這裏講智能合約應用程序二進制接口規範; 主要有如下基本類型:數組
uint<M>: unsigned integer type of M bits, 0 < M <= 256, M % 8 == 0. e.g. uint32, uint8, uint256. int<M>: two’s complement signed integer type of M bits, 0 < M <= 256, M % 8 == 0. address: equivalent to uint160, except for the assumed interpretation and language typing. For computing the function selector, address is used. uint, int: synonyms for uint256, int256 respectively. For computing the function selector, uint256 and int256 have to be used. bool: equivalent to uint8 restricted to the values 0 and 1. For computing the function selector, bool is used. fixed<M>x<N>: signed fixed-point decimal number of M bits, 8 <= M <= 256, M % 8 ==0, and 0 < N <= 80, which denotes the value v as v / (10 ** N). ufixed<M>x<N>: unsigned variant of fixed<M>x<N>. fixed, ufixed: synonyms for fixed128x18, ufixed128x18 respectively. For computing the function selector, fixed128x18 and ufixed128x18 have to be used. bytes<M>: binary type of M bytes, 0 < M <= 32. function: an address (20 bytes) followed by a function selector (4 bytes). Encoded identical to bytes24. The following (fixed-size) array type exists: <type>[M]: a fixed-length array of M elements, M >= 0, of the given type. The following non-fixed-size types exist: bytes: dynamic sized byte sequence. string: dynamic sized unicode string assumed to be UTF-8 encoded. <type>[]: a variable-length array of elements of the given type. Types can be combined to a tuple by enclosing a finite non-negative number of them inside parentheses, separated by commas: (T1,T2,...,Tn): tuple consisting of the types T1, …, Tn, n >= 0 It is possible to form tuples of tuples, arrays of tuples and so on. It is also possible to form zero-tuples (where n == 0).
小編主要講解如何解析合約方法編碼問題,比較常見的2中,靜態類型(static type)與動態類型(dynamic type),其中靜態類型分基本類型與固定數組長度數據結構
這裏寫個合約作講解 來之solidity官方文檔curl
pragma solidity ^0.4.16; contract Foo { // 基本類型 function baz(uint32 x, bool y) public pure returns (bool r) { r = x > 32 || y; } // 固定數組長度 function bar(bytes3[2]) public pure {} // 動態類型 function sam(bytes, bool, uint[]) public pure {} }
例如:調用baz(69,true),可由68字節組成,可細分爲methodId+arg1(uint32 69)+arg2(bool true)ide
0xcdcd77c0
0x0000000000000000000000000000000000000000000000000000000000000045
0x0000000000000000000000000000000000000000000000000000000000000001
得函數
0xcdcd77c000000000000000000000000000000000000000000000000000000000000000450000000000000000000000000000000000000000000000000000000000000001
返回一個bool。由於bool true爲1 false爲0,因此輸出若爲false則 0x0000000000000000000000000000000000000000000000000000000000000000
學習
例如:調用bar(["abc","def"]),則有68字節組成;可細分爲methodId+arg1(bytes3[2])
0xfce353f6
0x6162630000000000000000000000000000000000000000000000000000000000
:第一個參數的第一部分,一個bytes3值"abc"(左對齊)。0x6465660000000000000000000000000000000000000000000000000000000000
:第一個參數的第二部分,一個bytes3值"def"(左對齊)。得
0xfce353f661626300000000000000000000000000000000000000000000000000000000006465660000000000000000000000000000000000000000000000000000000000
若是想調用sam("dave",true,[1,2,3]),注意,uint將被替換成uint256
0xa5643bf2
:方法ID。這來自簽名sam(bytes,bool,uint256[])。請注意,它將uint替換爲其規範表示uint256。0x0000000000000000000000000000000000000000000000000000000000000060
:第一個參數(動態類型)的數據部分的位置,以參數塊開頭的字節爲單位。在這種狀況下,0x60。這裏再補充一遍0x60是怎麼計算出來的,是指從第60個偏移量開始爲該動態類型的內容;下面的xa同理0x0000000000000000000000000000000000000000000000000000000000000001
:第二個參數:布爾值true。0x00000000000000000000000000000000000000000000000000000000000000a0
:第三個參數(動態類型)的數據部分的位置,以字節爲單位。在這種狀況下,0xa0
。0x0000000000000000000000000000000000000000000000000000000000000004
:第一個參數的數據部分,它以元素中字節數組的長度開始,在本例中爲4。0x6461766500000000000000000000000000000000000000000000000000000000
:第一個參數的內容:UTF-8(在本例中等於ASCII)編碼"dave",右邊填充32個字節。 0x0000000000000000000000000000000000000000000000000000000000000003
:第三個參數的數據部分,它以元素中數組的長度開始,在本例中爲3。0x0000000000000000000000000000000000000000000000000000000000000001
:第三個參數的第一個條目。0x0000000000000000000000000000000000000000000000000000000000000002
:第三個參數的第二個條目。0x0000000000000000000000000000000000000000000000000000000000000003
:第三個參數的第三個條目。得
0xa5643bf20000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000464617665000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003
合約事件也是同理,只是對應以太坊的logs中的topics
Creates new message call transaction or a contract creation, if the data field contains code.
Parameters
params: [{ "from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155", "to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567", "gas": "0x76c0", // 30400 "gasPrice": "0x9184e72a000", // 10000000000000 "value": "0x9184e72a", // 2441406250 "data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675" }]
Returns DATA, 32 Bytes - the transaction hash, or the zero hash if the transaction is not yet available.
Example
// Request curl -X POST --data '{"jsonrpc":"2.0","method":"eth_sendTransaction","params":[{see above}],"id":1}' // Result { "id":1, "jsonrpc": "2.0", "result": "0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331" }
Creates new message call transaction or a contract creation for signed transactions.
Parameters
params: ["0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"]
Returns DATA, 32 Bytes - the transaction hash, or the zero hash if the transaction is not yet available.
Use eth_getTransactionReceipt to get the contract address, after the transaction was mined, when you created a contract.
Example
// Request curl -X POST --data '{"jsonrpc":"2.0","method":"eth_sendRawTransaction","params":[{see above}],"id":1}' // Result { "id":1, "jsonrpc": "2.0", "result": "0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331" }
這裏先以調用合約接口,發送交易(sendContractTransaction)爲例,
輸入:合約地址,合約方法名稱,合約參數,合約ABI
sam(bytes,bool,uint256[])
)
""(由於此處是以調用sendContractTransaction因此沒有部署合約時的bin參數,如果調用構造函數則代表是deploy即須要在前面insert 合約二進制編碼bin)
""
其中,6,7步驟根據不一樣的區塊鏈數據結構與編碼要求修改,1~5則是根據solidity語言作修改(通常不會有改動)
輸出:合約十六進制編碼字符串
合約數據結構UML設計;