Update Apr 23 2017
geth
1.6.0 has a breaking change to remove access to the Solidity compiler from within geth
.
The workaround is detailed in How to compile Solidity contracts within geth with the v1.6.0 **BREAKING CHANGE**?
Update Feb 04 2017
Solidity 0.4.9 has a breaking change. The workaround is detailed in Unable to define greeterContract in the Greeter tutorial. Breaking change in Solidity 0.4.9! where you have to use refer to variable like greeterCompiled.<stdin>:greeter
with greeterCompiled["<stdin>:greeter"]
.
Here's a step-by-step guide to get this contract deployed to a dev blockchain.
Create A Coinbase Account
user@Kumquat:~/ESE/Deploy$ geth --datadir "./data" --dev account new
Your new account is locked with a password. Please give a password. Do not forget this password.
Passphrase:
Repeat Passphrase:
Address: {730b87e78b07fb2bf1b1e8b127b3353d08d72706}
Window #1 - Run Geth Mining Instance With Unlocked Account
This geth instance will mine the blockchain. We will unlock the coinbase account so this instance will be able to execute transactions, and run the mining on one CPU thread. Enter your password created in the previous step at the Passphrase:
prompt.
user@Kumquat:~/ESE/Deploy$ geth --datadir "./data" --dev --unlock 0 --mine --minerthreads 1
I0409 01:02:10.427513 32675 database.go:71] Alloted 16MB cache to data/chaindata
I0409 01:02:10.429602 32675 database.go:71] Alloted 16MB cache to data/dapp
I0409 01:02:10.431573 32675 backend.go:314] Protocol Versions: [63 62 61], Network Id: 1
I0409 01:02:10.431686 32675 backend.go:362] Blockchain DB Version: 3
I0409 01:02:10.432078 32675 blockchain.go:214] Last header: #0 [e5be9214…] TD=131072
I0409 01:02:10.432118 32675 blockchain.go:215] Last block: #0 [e5be9214…] TD=131072
I0409 01:02:10.432153 32675 blockchain.go:216] Fast block: #0 [e5be9214…] TD=131072
I0409 01:02:10.439890 32675 cmd.go:115] Starting Geth/v1.3.6/linux/go1.5.1
I0409 01:02:10.440240 32675 server.go:311] Starting Server
I0409 01:02:12.543810 32675 udp.go:212] Listening, enode://ef1eb6acad7a816bcc8debe0b078e0d8433225ca5d57622687aea13fee389e2ef064e7f01b5f8bf1d003d4722032597f2688917ca13133bd872fb90ba6872bce@[::]:30303
I0409 01:02:12.544021 32675 backend.go:526] Server started
Unlocking account 0 | Attempt 1/3
I0409 01:02:12.544151 32675 backend.go:584] Automatic pregeneration of ethash DAG ON (ethash dir: /home/user/.ethash)
I0409 01:02:12.544180 32675 server.go:552] Listening on [::]:30303
I0409 01:02:12.544217 32675 backend.go:591] checking DAG (ethash dir: /home/user/.ethash)
Passphrase:
Account '0' (0x730b87e78b07fb2bf1b1e8b127b3353d08d72706) unlocked.
I0409 01:02:18.255806 32675 miner.go:119] Starting mining operation (CPU=1 TOT=1)
I0409 01:02:18.255950 32675 ipc.go:112] IPC service started (data/geth.ipc)
I0409 01:02:18.256684 32675 worker.go:569] commit new work on block 1 with 0 txs & 0 uncles. Took 829.143µs
I0409 01:02:18.256853 32675 ethash.go:220] Generating DAG for epoch 0 (size 1073739904) (0000000000000000000000000000000000000000000000000000000000000000)
I0409 01:02:19.852771 32675 ethash.go:237] Done generating DAG for epoch 0, it took 1.595912996s
I0409 01:02:34.225955 32675 worker.go:348] 🔨 Mined block (#1 / bf23cf06). Wait 5 blocks for confirmation
I0409 01:02:34.226385 32675 worker.go:569] commit new work on block 2 with 0 txs & 0 uncles. Took 357.68µs
I0409 01:02:34.226734 32675 worker.go:569] commit new work on block 2 with 0 txs & 0 uncles. Took 286.72µs
Window #2 - Run Second Geth Instance Attaching To The First
EDIT 30/05/2016 - Updated command as IPC path behaviour has changed between geth
v1.3.6 and 1.4.5-stable.
Open a second terminal and run a second geth instance that attaches to the first geth instance. Checking the balance of the coinbase account (eth.accounts[0]) will show an increasing balance as the first geth instance continues mining.
user@Kumquat:~/ESE/Deploy$ geth --datadir "./data" --dev attach ipc:data/geth.ipc
instance: Geth/v1.4.5-stable/linux/go1.5.1
datadir: data
coinbase: 0x730b87e78b07fb2bf1b1e8b127b3353d08d72706
at block: 71 (Sat, 09 Apr 2016 01:07:42 AEST)
modules: admin:1.0 db:1.0 debug:1.0 eth:1.0 miner:1.0 net:1.0 personal:1.0 shh:1.0 txpool:1.0 web3:1.0
> web3.fromWei(eth.getBalance(eth.accounts[0]).toNumber(), "ether")
"360"
> web3.fromWei(eth.getBalance(eth.accounts[0]).toNumber(), "ether")
"390"
>
Compile the code in the question and display the compiled code.
> var greeterSource = 'contract mortal { address owner; function mortal() { owner = msg.sender; } function kill() { if (msg.sender == owner) suicide(owner); } } contract greeter is mortal { string greeting; function greeter(string _greeting) public { greeting = _greeting; } function greet() constant returns (string) { return greeting; } }'
undefined
> var greeterCompiled = web3.eth.compile.solidity(greeterSource)
undefined
> greeterCompiled
{
greeter: {
code: "0x606060405260405161023e38038061023e8339810160405280510160008054600160a060020a031916331790558060016000509080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10609f57805160ff19168380011785555b50608e9291505b8082111560cc57600081558301607d565b50505061016e806100d06000396000f35b828001600101855582156076579182015b82811115607657825182600050559160200191906001019060b0565b509056606060405260e060020a600035046341c0e1b58114610026578063cfae321714610068575b005b6100246000543373ffffffffffffffffffffffffffffffffffffffff908116911614156101375760005473ffffffffffffffffffffffffffffffffffffffff16ff5b6100c9600060609081526001805460a06020601f6002600019610100868816150201909416939093049283018190040281016040526080828152929190828280156101645780601f1061013957610100808354040283529160200191610164565b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156101295780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b565b820191906000526020600020905b81548152906001019060200180831161014757829003601f168201915b505050505090509056",
info: {
abiDefinition: [{...}, {...}, {...}],
compilerOptions: "--bin --abi --userdoc --devdoc --add-std --optimize -o /tmp/solc163112865",
compilerVersion: "0.3.1",
developerDoc: {
methods: {}
},
language: "Solidity",
languageVersion: "0.3.1",
source: "contract mortal { address owner; function mortal() { owner = msg.sender; } function kill() { if (msg.sender == owner) suicide(owner); } } contract greeter is mortal { string greeting; function greeter(string _greeting) public { greeting = _greeting; } function greet() constant returns (string) { return greeting; } }",
userDoc: {
methods: {}
}
}
},
mortal: {
code: "0x606060405260008054600160a060020a03191633179055605c8060226000396000f3606060405260e060020a600035046341c0e1b58114601a575b005b60186000543373ffffffffffffffffffffffffffffffffffffffff90811691161415605a5760005473ffffffffffffffffffffffffffffffffffffffff16ff5b56",
info: {
abiDefinition: [{...}, {...}],
compilerOptions: "--bin --abi --userdoc --devdoc --add-std --optimize -o /tmp/solc163112865",
compilerVersion: "0.3.1",
developerDoc: {
methods: {}
},
language: "Solidity",
languageVersion: "0.3.1",
source: "contract mortal { address owner; function mortal() { owner = msg.sender; } function kill() { if (msg.sender == owner) suicide(owner); } } contract greeter is mortal { string greeting; function greeter(string _greeting) public { greeting = _greeting; } function greet() constant returns (string) { return greeting; } }",
userDoc: {
methods: {}
}
}
}
}
>
Send the transaction to insert the contract code into the blockchain. You will see that the contract transaction has been successfully mined.
> var _greeting = "Hello World!"
undefined
> var greeterContract = web3.eth.contract(greeterCompiled.greeter.info.abiDefinition);
undefined
> var greeter = greeterContract.new(_greeting, {from: eth.accounts[0], data: greeterCompiled.greeter.code, gas: 4000000},
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);
}
}
})
Contract transaction send: TransactionHash: 0x90d201388971770036898a7a22ab252cb0bf3c556f988a7b87583315cdaf58bc waiting to be mined...
undefined
> Contract mined! Address: 0x083628160c1cf218d14f2f0998c7a8dc72aec180
[object Object]
You will see in window #1 the following message that shows the transaction being included into a mined block #352. Your greeter contract is now in the blockchain:
I0409 01:22:16.060791 32675 worker.go:447] 🔨 🔗 Mined 5 blocks back: block #345
I0409 01:22:16.061344 32675 worker.go:569] commit new work on block 351 with 0 txs & 0 uncles. Took 437.176µs
I0409 01:22:17.021781 32675 xeth.go:1026] Tx(0x90d201388971770036898a7a22ab252cb0bf3c556f988a7b87583315cdaf58bc) created: 0x083628160c1cf218d14f2f0998c7a8dc72aec180
I0409 01:22:25.759727 32675 worker.go:348] 🔨 Mined block (#351 / 6d35d834). Wait 5 blocks for confirmation
I0409 01:22:25.763740 32675 worker.go:569] commit new work on block 352 with 1 txs & 0 uncles. Took 3.937696ms
I0409 01:22:25.763820 32675 worker.go:447] 🔨 🔗 Mined 5 blocks back: block #346
I0409 01:22:25.764723 32675 worker.go:569] commit new work on block 352 with 1 txs & 0 uncles. Took 816.878µs
I0409 01:22:27.864884 32675 worker.go:348] 🔨 Mined block (#352 / f44a6a52). Wait 5 blocks for confirmation
I0409 01:22:27.865448 32675 worker.go:569] commit new work on block 353 with 0 txs & 0 uncles. Took 485.587µs
In window #2, call the greeter.greet() method that will extract the message from the blockchain and display it:
> greeter.greet();
"Hello World!"
>
If you exit from your window #2 geth instance and want to re-run the contract inserted in the steps above, start up the geth instance again (window #2 attach version) and run the following commands. Replace the address at the at(...)
function with your contract address:
> var greeter2 = eth.contract([{constant:false,inputs:[],name:'kill',outputs:[],type:'function'},{constant:true,inputs:[],name:'greet',outputs:[{name:'',type:'string'}],type:'function'},{inputs:[{name:'_greeting',type:'string'}],type:'constructor'}]).at('0x083628160c1cf218d14f2f0998c7a8dc72aec180');
undefined
> greeter2
{
address: "0x083628160c1cf218d14f2f0998c7a8dc72aec180",
allEvents: function(),
greet: function(),
kill: function()
}
> greeter2.greet()
"Hello World!"
>
EDIT 30/05/2016
If You Are Not Getting The Results Above
- Don't worry about setting up Window #2
- Run all the commands from the Window #2 sections above beginning with
var greeterSource = 'contract mortal { address ow...
to greeter2.greet()
in Window #1.
If you are not getting the Contract mined! Address: 0x083628160c1...
message:
a. Check that geth
is mining successfully. You should see the message 🔨 Mined block (#...
in your Window #1.
b. If you are not getting the 🔨 Mined block (#...
message, try running the command miner.start(1)
. This will start the CPU mining on one thread.
c. Check your account balance using web3.fromWei(eth.getBalance(eth.accounts[0]).toNumber(), "ether")
as you will need some ethers to send the transaction.
d. If all fails, try setting debug.verbosity(4)
and see if you can work out what is happening. You can try 5 or 6 as well, but there will be more message flashing past your screen.