Beginner’s guide to blockchain/Ethereum (1) — Build a smart contract on a private network

Overview & Incentive

Since many tutorials, including the official tutorial on ethereum.org, have some errs(ex. the updated version of geth removed the solidity compiling function) which make it harder for beginners like me to get started, I decided to write this tutorial in the hope of expanding the Ethereum community.

I’m using mac. If you encounter any problem, please kindly let me know in the comments so I can update it accordingly:)

Open source tools & language used:

  1. Solidity: smart contract programming language
  2. geth (version 1.5.9): CLI for running ethereum node
  3. brew: package manager for MacOS.

Install it by typing this command in terminal:

/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

Start coding!

As starting from geth version 1.6.0, compiling solidity is no longer available, we cannot install it directly using brew(only the newest version package is provided there). Here we use geth version 1.5.9 and build it from source code.

  1. Download Source code (tar.gz)

In terminal:

cd “path of the file you just downloaded”
// in Mac, you can simply drag the folder to console to get the path
make geth

This will generate an executable file in the “your current directory”/build/bin folder which can be moved to wherever you want to run it from. The binary is stand alone and doesn’t require any additional files.(Reference: https://github.com/ethereum/go-ethereum/wiki/Installing-Geth#build-it-from-source-code )

2. Then, create alias:

echo "alias geth159='your_folder_path/build/bin/geth'" >> ~/.bashrc

In my case, it is /Users/tina/Desktop/go-ethereum-1.5.9/build/bin/geth

To make the changes affected immediately:

source ~/.bashrc

To make what you editted in ~/.bashrc available upon every login

echo "source ~/.bashrc" >> ~/.profile

Now you can type geth159 whenever you want to launch geth :)

3. Install Solidity compiler

brew install solidity

4. launch your private net

First create a folder to store your blockchain data

mkdir privchain

Use geth to launch it

geth159 --rpc --rpcaddr 127.0.0.1 --rpcport 8545 --dev --datadir privchain

(Reference: https://github.com/ethereum/go-ethereum/wiki/Command-Line-Options, https://stackoverflow.com/questions/33826018/in-ethereum-what-is-a-private-testnet-why-would-i-want-it-and-how-do-i-set-it )

Should see something like

INFO…. IPC endpoint opened: /Users/tina/privchain/geth.ipc
INFO….HTTP endpoint opened: http://127.0.0.1:8545

And if you open a new console and cd privchain then ls , you can see the originally empty dir is now having geth, geth.ipc, and keystore

5. Keep that Ethereum node running and open a new terminal. Use “geth attach” to connect to the node and open geth console

geth159 attach ipc://Users/tina/privchain/geth.ipc 
// use your own ipc url here!

6. Now use the api commands as specified here https://github.com/ethereum/go-ethereum/wiki/JavaScript-Console#personallistaccounts

(In geth console)

personal.listAccounts

output: []

personal.newAccount('') 
// you can enter your password like newAccount(‘password_ya’)

output: [0x…….] // your newly created account address.

  • Note that every time a new account is created, you should see .”..New wallet appeared..” In the console where you opened your private net
personal.listAccounts 
// just to make sure you hv made the account successfully

output: [0x………]

7. Use the ethereum js api as specified here https://ethereumbuilders.gitbooks.io/guide/content/en/ethereum_javascript_api.html

(in geth console)

web3.eth.coinbase 
// This property is read only and returns the coinbase address where the mining rewards go to.

output: [0x………] // the output should be the same as your newly created account address, cause it takes the first account you created as default value

8. Create your smart contract!

source = "contract test { function multiply(uint a) returns(uint d){return a * 7;}}"

9. Make sure your solidity compiler is installed

web3.eth.getCompilers() // the output should be ["Solidity"]

10. Compile your code

code = web3.eth.compile.solidity(source)

The output(the “code” you just created) is like a json object. The highlighted part is your bytecode, which you will need to create a smart contract, and the abi array, respectively.

{
<stdin>:test: {
    code: "0x60606040523415600b57fe5b5b60918061001a6000396000f300606060405263ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663c6888fa181146039575bfe5b3415604057fe5b6049600435605b565b60408051918252519081900360200190f35b600781025b9190505600a165627a7a723058206a8cbef13138690601a279c73e208f9dcf42e4678d860038475fe555599593d60029",
    info: {
        abiDefinition: [{...}],
compilerOptions: "--combined-json bin,abi,userdoc,devdoc -- add-std --optimize",
        compilerVersion: "0.4.11",
        developerDoc: {
            methods: {} 
        },
        language: "Solidity",
        languageVersion: "0.4.11",
        source: "contract test { function multiply(uint a) returns(uint d){return a * 7;}}",
        userDoc: {
            methods: {}
        }
    }
}
}

*What is abi? You can see this as an api for machines as explained here.

When you write source code, you access the library though an API. Once the code is compiled, your application accesses the binary data in the library through the ABI.

11. Create a contract object by its abi

MyContract = web3.eth.contract(code["<stdin>:test"].info.abiDefinition)

(Official document on how to create a contract: https://github.com/ethereum/wiki/wiki/JavaScript-API#web3ethcontract )

12. Check if you have a default coinbase account (to which your mining reward goes) with ether

First set your coinbase address as account1

account1 = web3.eth.coinbase

Then Check its balance

web3.eth.getBalance(account1)

If the output is larger than 0, go on to the next step:

Otherwise, start mining to get some ether in it!

miner.start()

You should see the mining in progress in the other terminal where you opened your private net

Stop when you feel like having sufficient funds ;p

miner.stop()

Check your balance again

web3.eth.getBalance(account1)

13. Unlock account to enable it to send transactions (In this case, we have to pay the gas price for contract deploy). Here we use account1.

personal.unlockAccount(account1, '') 
// you can replace '' with the password you set previously

14. Next, init the contract using the compiled code. In this case, it is code[“<stdin>:test”].code

You can also use other ways (ex. brower-solidity) to compile the contract and get this code. Here, replace the contract code with our “source” contract code, and click “contract details” at the bottom-right corner and you would be able to see the same bytecode.

*Note: browser solidity cannot work on safari. You can use chrome instead.

*Note: you can also set the contract to a previous one using the address of the contract you created before (contractInstance = MyContract.at(“address”);)

bytecode = code["<stdin>:test"].code

Estimate how many gas you will need to deploy this contract

web3.eth.estimateGas({data: bytecode})

15. Deploy contract and set callback function for our better understanding :)

contractInstance = MyContract.new({data: bytecode gas: 1000000, from: account1}, function(e, contract){if(!e){if(!contract.address){console.log("Contract transaction send: Transaction Hash: "+contract.transactionHash+" waiting to be mined...");}else{console.log("Contract mined! Address: "+contract.address);console.log(contract);}}else{console.log(e)}})
  • Note: The value of param “gas” can be anything higher than the estimated gas costs
  • Note: you may have to unlock your account1 again here.

Now you should see

In this console:

Contract transaction send: Transaction Hash: “your_transaction_hash” waiting to be mined…

In the other console for starting the private net:

… created “your_transaction_hash”

16. Your contract is now waiting be mined. You should see ‘Contract mined!` soon after the mining starts. After that, you can stop mining.

miner.start()

After you see

Contract mined! Address: 0xf1bc128edf9d7d4a7d567b50c1d8080cf58ef068

Ctrl+c to go back to geth console and type

miner.stop()
  • Note: Ctrl+C is to interrupt any process return to the simple console mode. Ctrl+D is to exit the console

17. Last, check if your contract is created successfully

eth.getCode(contractInstance.address) // the output should be the same as your bytecode

18. Call our contract function

contractInstance.multiply.call(6) // replace 6 with any unsigned int

Output: 42

  • Note: call() is a local invocation of a contract function that does not broadcast or publish anything on the blockchain. The command “contractInstance.multiply(6)” will not work.

(Reference: https://ethereum.stackexchange.com/questions/765/what-is-the-difference-between-a-transaction-and-a-call)

Learn more through…

  1. Another great guide on the greeter tutorial:

https://samsclass.info/141/proj/pEth1.htm

Covers how to make a contract available to other machines on the same private network and how to delete a contract

2. Blockchain visualization and charts:

https://etherscan.io/

Wrap up

Now you know how to set up a private network, mine ethers, compile and run smart contracts in Solidity.

This is actually my first article and first tutorial. Share it if you like it. I’m open to any suggestions! Thank you:)