This article explains how we write, deploy, and invoke Ethereum smart contracts used in the benchmark.
Use Solidity to. For example, the key-value smart contract is written as follows:
pragma solidity ^0.4.0;
contract KVstore {
mapping(string=>string) store;
function get(string key) constant returns(string) {
return store[key];
}
function set(string key, string value) {
store[key] = value;
}
}
The contract must first be compiled into EVM bytecode and send to the blockchain as data of a transaction.
At the end, a unique contractAddress
is generated, which is a hash of the following:
- The uploading address, i.e. address of the account that invoke the transaction.
- The contract bytecode.
Thus, the same contract (bytecode) uploaded from two different addresses results in two distinct
contractAddress
. In other words, two independent contracts are deployed. This is an important distinction
to Hyperledger: in this example, only one Hyperledger will be deployed.
-
Compilation: use the online Solidity browser
https://ethereum.github.io/browser-solidity
- Copy and paste the code
- See the compiled bytecode
-
Upload to the blockchain using
eth_sendTransaction
RPCcurl -X POST <endpoint> -d {"jsonrpc": "2.0", "method": "eth_sendTransaction", "params": [{"gas": <gas>, "from": "<from address>", "data": "<bytecode>"}], "id": 1}
Once the contract is deploy at contractAddress
, its method is invoked by sending transactions to it. Content
of the transaction, its data
field contains encoded input: a string of the following format:
`<method singature><padded param>..`
For instance, the encoding for the method call set("hello", "world")
is as follows:
- Method signature, generated by the same Solidity browser during compilation, i.e.
0x0xe942b516
- Off-set to the encoded first parameter (excluding the signature), padded to 32 bytes. Say this is X
- Off-set to the encoded second parameter (excluding the signature), padded to 32 bytes. Say this is Y
- Encoded first parameter, padded to 32-byte units. In this case, the encoding is 64 bytes (32 byte for length, and 32 bytes for "hello")
- Encoded second parameter, padded to 32-byte units. In this case, the encoding is 64 bytes (32 bytes for length, and 32 bytes for "world")
Thus, X=00..040
because the encoded first parameter starts at byte 64 after the signature. Y=00..80
because the encoded second parameter starts at byte 128 after the signature. Suppose the first string is
longer than 32 bytes, say it's 48 bytes (padded to 64), then Y=00..a0
because the encoded second parameter
now starts at byte 160.
Finally, the transaction is sent via RPC
curl -X POST <endpoint> {"jsonrpc": "2.0", "method": "eth_sendTransaction", "params": [{"gas": <gas>, "from": "<from_address>", "to": "<contractAddress>", "data": "<encodedMethod>"}], "id": 1}