Summary
Your original contract code would not work correctly until I added a constant
to the function definition to indicate that this function does not modify the blockchain.
I had to use the method signature of double(int256)
instead of double(int)
to get the eth_call
JSON-RPC to work.
The Details
Run Your geth
Instance
You can use the Testnet blockchain that is synchronised with other peers over the Internet, or you can use a private Dev blockchain that is only available on your computer and faster to develop with. The --rpc
parameter will allow you to use curl
to communicate with your geth
instance.
Testnet Blockchain
You will need to create an account and mine some coins as you need the coins to insert your code into the blockchain or to send transactions to the blockchain:
geth --testnet account new
Your new account is locked with a password. Please give a password. Do not forget this password.
Passphrase:
Repeat Passphrase:
Address: {aaaa725f2f36a28c01bc47f883534990c9c8bbbb}
Your geth
instance will have to synchronise your Testnet blockchain with other peers on the Internet. This may take and hour or more. Once synchronised, your mining operation will commence and you should mine some coins in 10 or 20 minutes. Start geth
with the mining parameters:
geth --testnet --rpc --mine --minerthreads 1 console
To check if you have coins, run the command:
> web3.fromWei(eth.getBalance(eth.accounts[0]), "ether");
25
If you want to exit from geth
, press Control-D.
If you want to, you can now run your geth
instance without the mining parameters as another geth
instance somewhere on the Internet will mine your transactions. Use the following command to remove the mining option, or just use the previous geth
command:
geth --testnet --rpc console
Dev Blockchain
You will need to create an account and mine some coins:
geth --dev account new
Your new account is locked with a password. Please give a password. Do not forget this password.
Passphrase:
Repeat Passphrase:
Address: {cccc725f2f36a28c01bc47f883534990c9c8dddd}
Start geth
with the --miner
and --minerthreads
parameters as your geth
instance will need to mine your private blockchain:
geth --dev --rpc --mine --minerthreads 1 console
Flatten Your Code And Assign To A Variable
I had to modify your code to get it to run correctly by adding the word constant
to your function definition as this function does not modify the blockchain when it is run.
In your example, your code will normally be formatted for easy reading:
contract Test {
function double(int a) constant returns(int) {
return 2*a;
}
}
You can use a service like Line Break Removal Tool to strip out your line breaks, or see How to load Solidity source file into geth for some alternatives.
Your flattened code will look like the example you posted:
contract Test { function double(int a) constant returns(int) { return 2*a; } }
You will need to assign your code to a string variable:
var testSource='contract Test { function double(int a) constant returns(int) { return 2*a; } }'
Note that //
comments will cause some problems when your code if flattened as all text after the //
comment will be treated as a comment. Use /* ... */
instead if you need to add comments to your code.
Compile Your Code
In your geth
instance, type in your flattened code with the assignment to the variable. Don't worry about the undefined
result as this is a normal response from geth
:
> var testSource='contract Test { function double(int a) constant returns(int) { return 2*a; } }'
undefined
Compile your code:
> var testCompiled = web3.eth.compile.solidity(testSource);
I0503 09:04:15.907715 3190 solidity.go:114] solc, the solidity compiler commandline interface
Version: 0.3.2-0/Release-Linux/g++/Interpreter
path: /usr/bin/solc
undefined
If you want to see the binary form of your code:
testCompiled
{
Test: {
code: "0x6060604052602a8060106000396000f3606060405260e060020a60003504636ffa1caa8114601a575b005b6002600435026060908152602090f3",
info: {
abiDefinition: [{...}],
compilerOptions: "--bin --abi --userdoc --devdoc --add-std --optimize -o /tmp/solc497335011",
compilerVersion: "0.3.2",
developerDoc: {
methods: {}
},
language: "Solidity",
languageVersion: "0.3.2",
source: "contract Test { function double(int a) constant returns(int) { return 2*a; } }",
userDoc: {
methods: {}
}
}
}
}
You will need the Application Binary Interface (ABI) signature for your contract if you want to access run your function outside this geth
session:
> testCompiled.Test.info.abiDefinition
[{
constant: true,
inputs: [{
name: "a",
type: "int256"
}],
name: "double",
outputs: [{
name: "",
type: "int256"
}],
type: "function"
}]
Note: This is the second hint as to why your JSON RPC call did not work - the method signature has int256
for the a
parameter instead of int
.
Insert Your Code Into The Blockchain
Run the following commands to insert your code into the blockchain:
> var testContract = web3.eth.contract(testCompiled.Test.info.abiDefinition);
undefined
> var test = testContract.new({
from:web3.eth.accounts[0],
data: testCompiled.Test.code, gas: 2000000},
function(e, contract) {
if (!e) {
if (!contract.address) {
console.log("Contract transaction send: TransactionHash: " +
contract.transactionHash + " waiting to be mined...");
} else {
console.log("Contract mined! Address: " + contract.address);
console.log(contract);
}
}
})
I0503 09:09:39.632499 3190 xeth.go:1026] Tx(0x8c15e8b8bb593d4a680b084a455ba82b103e60204638a3674ef1fb90ca0ad4f0) created: 0x7a2d8fa11aa28097135eb514f6a23ba12501191e
Contract transaction send: TransactionHash: 0x8c15e8b8bb593d4a680b084a455ba82b103e60204638a3674ef1fb90ca0ad4f0 waiting to be mined...
undefined
Wait up to a few minutes and you will see the following output:
I0503 09:10:34.319772 3190 worker.go:569] commit new work on block 11122 with 0 txs & 0 uncles. Took 431.081µs
Contract mined! Address: 0x7a2d8fa11aa28097135eb514f6a23ba12501191e
[object Object]
You should save the address if you want to run this contract from outside your geth
session.
Use Your Contract Within The Same geth
Session
Before adding the constant
to the double
function, I was getting the following results:
> test.double(5)
invalid address
Note: This is the first hint as to why your JSON RPC call failed.
To use your contract within your geth
session, AFTER adding constant
to the double
function:
> test.double(5)
10
> test.double(55)
110
Use Your Contract Using curl
And JSON-RPC
And now we get to the tricky part.
Your function double(int)
is really double(int256)
. From Solidity - Types:
int• / uint•: Signed and unsigned integers of various sizes. Keywords uint8 to uint256 in steps of 8 (unsigned of 8 up to 256 bits) and int8 to int256. uint and int are aliases for uint256 and int256, respectively.
In geth
, we run the following command to find the signature of the double(...)
function:
> web3.sha3('double(int256)')
"6ffa1caacdbca40c71e3787a33872771f2864c218eaf6f1b2f862d9323ba1640"
And take the first 4 bytest to create the data
parameter
0x6ffa1caa0000000000000000000000000000000000000000000000000000000000000005
And using the address from the "Contract mined! parameter", we build the following curl
command:
curl localhost:8545 -X POST --data '{"jsonrpc":"2.0", "method":"eth_call", "params":[{"from": "eth.accounts[0]", "to": "0x65da172d668fbaeb1f60e206204c2327400665fd", "data": "0x6ffa1caa0000000000000000000000000000000000000000000000000000000000000005"}], "id":1}'
And run this command from the command line:
user@Kumquat:~$ curl localhost:8545 -X POST --data '{"jsonrpc":"2.0", "method":"eth_call", "params":[{"from": "eth.accounts[0]", "to": "0x65da172d668fbaeb1f60e206204c2327400665fd", "data": "0x6ffa1caa0000000000000000000000000000000000000000000000000000000000000005"}], "id":1}'
{"id":1,"jsonrpc":"2.0","result":"0x000000000000000000000000000000000000000000000000000000000000000a"}
The result of 0x0000...000a
is the value 10
.
Update Oct 18 2016
As documented in RPC error "invalid or missing value for params" when calling contract constant void functions, you may have to add a block parameter to the params
list. Your command with the block parameter will be:
user@Kumquat:~$ curl localhost:8545 -X POST --data '{"jsonrpc":"2.0", "method":"eth_call", "params":[{"from": "eth.accounts[0]", "to": "0x65da172d668fbaeb1f60e206204c2327400665fd", "data": "0x6ffa1caa0000000000000000000000000000000000000000000000000000000000000005"}, "latest"], "id":1}'
{"id":1,"jsonrpc":"2.0","result":"0x000000000000000000000000000000000000000000000000000000000000000a"}
You may also have to leave out the from
parameter.
References:
Your Other Question
Also, are there any way to access already-existing methods within the Go Ethereum library that would free me from having to implement for example methods that to the padding myself?
Could you please ask this in another question as this answer is already too long.