Giter VIP home page Giter VIP logo

ethereum-tutorial's Introduction

Introduction

As you probably know, a blockchain is a sort of ledger, maintained and updated over time through a peer-to-peer consensus algorithm. The key innovation of the Ethereum blockchain is the ability to do more than just make financial transactions, effectively throwing value from one 'account' to another. Instead, through the use of the Etheruem virtual machine, peers can have their programs executed on the Ethereum network, enabling automatic peer to peer interactions without the overhead of an intermediary. Without the absence of the intermediary, this would just be another paradigm for fault-tolerant distributed computing.

There is a lot of hype (and money) being thrown around in Ethereum land right now. But from what I've observed, very few people seem to understand the technology. Nevertheless, many people advocate its utility, with little more than speculative and esoteric visions of a 'blockchain economy'. I don't mean to discourage any visionaries or theoreticians among us. Rather, I hope to, at a minumum, encourage and help facilitate experiment in blockchain applications in a setting that is not too complicated.

The aim is to set up an environment for writing smart contracts in Ethereum, while sticking with a text editor and the command-line. We will set up a private blockchain and look into some simple applications, so we can get a real, tangible sense of what this is good for, how it performs, and where we stand in the realm of practical application (not far).

I am therefore going to be asking myself a lot of questions that may seem very basic to some. I may, as well, be doing some programming that may seem complex, or, at least, contrived. The hope is that by reading along and mimicing the keystrokes, you can get some sense of what is going on.

That being said, I make no guarantee whatsoever that this will provide you with any form of satisfaction, enlightenment, or understanding - I am probably not much less confused than you.

Installation

Ubuntu

To install geth from PPA, run:

sudo apt-get install software-properties-common
sudo add-apt-repository -y ppa:ethereum/ethereum
sudo apt-get update
sudo apt-get install ethereum

Mac

If you don't have brew, install it:

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

To install geth, run:

brew tap ethereum/ethereum
brew install ethereum

Starting a private node

To keeps things simple for now, we will start by running a single node on a private network. This will allow us to inspect the basic data structures, objects, and procedures without the delay and complications of hopping onto an existing large-scale blockchain. To do this, we will use a custom genesis block. This is done by specifying the following key block details as a JSON file.

  • nonce: 64-bit hash used with mixhash for proof-of-work
  • timestamp: Unix-time value
  • parentHash: Keccak 256-bit hash of parent block header
  • gasLimit: Maximum amount of gas that can be expended in a single block
  • difficulty: Determines the difficulty of mining this block
  • mixhash: 256-bit hash used with nonce for proof-of-work
  • coinbase: The address of the account in which mining rewards are deposited
  • alloc: A specification of initial Ether allocations among accounts on the network
  • extraData: Additional relevant block data, up to a maximum of 32 bytes

Save the following into a file called 'genesis.json'.

{
	"nonce": "0x0000000000000123",
	"timestamp": "0x0",
	"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
	"extraData": "0x0",
	"gasLimit": "0x8000000",
	"difficulty": "0x400",
	"mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
	"coinbase": "0x3333333333333333333333333333333333333333",
	"alloc": {}
}	

To start a node, run

geth --genesis genesis.json

This will use the above json file to write block 0 of the blockchain, the genesis block. You will see some networking logs indicating the server starting. Open another terminal and run

geth attach

This will launch the Javascript Runtime Environment included in geth. Here, you have access to a variety of management APIs, and you can write ordinary JavaScript code. It is instructive to keep an eye on both terminal windows simultaneously, as the first provides immediate insights for debugging and understanding.

Start by inspecting the state of the network.

> web3.eth.accounts
[]
> web3.eth.coinbase
null
> web3.eth.blockNumber
0
> web3.eth.getBlock(0)
{
  difficulty: 1024,
  extraData: "0x00",
  gasLimit: 134217728,
  gasUsed: 0,
  hash: "0x8b1f2271ac3d51f7ca371b8e633e8f1625b64fb4bad3a158cc3da8157dfdaa14",
  logsBloom: "0x00000000000000000000000000...",
  miner: "0x3333333333333333333333333333333333333333",
  nonce: "0x0000000000000123",
  number: 0,
  parentHash: "0x0000000000000000000000000000000000000000000000000000000000000000",
  receiptRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
  sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
  size: 507,
  stateRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
  timestamp: 0,
  totalDifficulty: 1024,
  transactions: [],
  transactionsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
  uncles: []
}
> web3.eth.getBlock(1)
null

So, we have no accounts, our coinbase (default recipient of mined Ether) is null, we are on block number 0, and we can see within its information the data from our JSON file.

Creating Accounts

Everything in Ethereum starts with an account. The first type of account is called an externally owned account, and is created like so:

> web3.personal.newAccount("strong password that no one will guess")
"0x7a47376c00308be583e1ea5e7a610d58dce68744"
> web3.personal.newAccount("haha")
"0xd451d8e4cc7392c9a21ac8c0e23c6beac1343691"
> web3.eth.accounts
["0x7a47376c00308be583e1ea5e7a610d58dce68744", "0xd451d8e4cc7392c9a21ac8c0e23c6beac1343691"]
> web3.eth.getBalance(web3.eth.accounts[0])
0

We will see the other type of account, a contract account, when we get to writing smart contracts in Solidity.

🔨 Mining

To do anything, we need Ether.

> miner.start()
	true

In the other window, you will see something like this (the timestamps and program name have been ommitted to save space):

Starting mining operation (CPU=8 TOT=9)
Automatic pregeneration of ethash DAG ON (ethash dir: /home/momo/.ethash)
commit new work on block 1 with 0 txs & 0 uncles. Took 110.399µs
checking DAG (ethash dir: /home/momo/.ethash)
Generating DAG for epoch 0 (size 1073739904) (0000000000000000000000000000000000000000000000000000000000000000)
Generating DAG: 0%
Generating DAG: 1%
Generating DAG: 2%
Generating DAG: 3%
Generating DAG: 4%
Generating DAG: 5%
Generating DAG: 6%
Generating DAG: 7%
Generating DAG: 8%
Generating DAG: 9%
Generating DAG: 10%

Once the DAG is generated, mining will start:

Generating DAG: 99%
Generating DAG: 100%
Done generating DAG for epoch 0, it took 4m18.16510184s
Starting mining operation (CPU=8 TOT=9)
commit new work on block 1 with 0 txs & 0 uncles. Took 129.44µs
🔨  Mined block (#1 / 44d47c8c). Wait 5 blocks for confirmation
commit new work on block 2 with 0 txs & 0 uncles. Took 150.156µs
🔨  Mined block (#1 / 348b5a21). Wait 5 blocks for confirmation
commit new work on block 2 with 0 txs & 0 uncles. Took 123.073µs
commit new work on block 2 with 0 txs & 0 uncles. Took 977.309µs
🔨  Mined stale block (#1 / 18c10b67). 
commit new work on block 2 with 0 txs & 0 uncles. Took 191.801µs
commit new work on block 2 with 0 txs & 0 uncles. Took 142.205971ms
🔨  Mined block (#1 / d11b9cb6). Wait 5 blocks for confirmation
commit new work on block 2 with 0 txs & 0 uncles. Took 28.898533ms
commit new work on block 2 with 0 txs & 0 uncles. Took 122.455µs
🔨  Mined block (#2 / cfb278cb). Wait 5 blocks for confirmation
commit new work on block 3 with 0 txs & 0 uncles. Took 205.311µs
🔨  Mined stale block (#2 / ac569b95). 
commit new work on block 3 with 0 txs & 0 uncles. Took 146.449742ms
commit new work on block 3 with 0 txs & 0 uncles. Took 156.201µs
🔨  Mined block (#3 / 06152682). Wait 5 blocks for confirmation

By default, all mining rewards are deposited into the account at web3.eth.accounts[0]. In the console, you can verify the increasing balance:

> web3.getBalance(web3.eth.accounts[0]) //units are in wei. 1 ether = 10^18 wei
45000000000000000000
> web3.getBalance(web3.eth.accounts[1]) // still 0
0
> web3.fromWei(web3.getBalance(web3.eth.accounts[0])) // convert from wei to ether
45

To send some Ether, run:

> var sender = web3.eth.accounts[0]; var receiver = web3.eth.accounts[1]
undefined
> web3.personal.unlockAccount(sender, "strong password that no one will guess")
true
> web3.eth.sendTransaction({from: sender, to: receiver, value: 20})
"0xcd2b5724cff9afcf5236a1f49692fbc9082ffac5da6cbe176626c2f8443f07a8"  //transaction hash

In the other window, you will see the transaction hash and destination address, followed by a log of a block mined with 1 txs, a single transaction.

Tx(0x2d4e0ec822f65549116da31cb70d6d04b39d558e031b4927927a75cec87030ff) to: 0xd451d8e4cc7392c9a21ac8c0e23c6beac1343691
 commit new work on block 18 with 1 txs & 0 uncles. Took 793.931µs   // our transaction will be mined in block 18
  🔨  Mined block (#18 / 57a17fa2). Wait 5 blocks for confirmation     // our transaction has been mined
 commit new work on block 19 with 0 txs & 0 uncles. Took 232.13µs
 commit new work on block 19 with 0 txs & 0 uncles. Took 260.54µs
 🔨  Mined block (#19 / 6eae0bae). Wait 5 blocks for confirmation
 commit new work on block 20 with 0 txs & 0 uncles. Took 195.227µs
 commit new work on block 20 with 0 txs & 0 uncles. Took 183.743µs

Confirm the payment has been received:

> web3.eth.getBalance(receiver)
20

Contracts

To make sure the Solidity compiler is installed, run web3.eth.getCompilers(). If this does not return an array containing 'Solidity' as an element, exit the console and run:

sudo apt-get install solc

Restart the console and verify that the compiler is available. If it is not, run:

$ which solc
/usr/bin/solc

The output of this command provides the path to the solc compiler installed. Provide this path in the console like so:

> admin.setSolc('/usr/bin/solc')
"solc, the solidity compiler commandline interface\nVersion: 0.3.2-0/Release-Linux/g++/Interpreter\n\npath: /usr/bin/solc"

Type the following contract directly into a variable called source.

> var source = 'contract adder { function add(uint a, uint b) constant returns (uint c) { return a+b;} }'

Compile this and save the output to a variable:

> var compiled = web3.eth.compile.solidity(source)
undefined
> compiled
{
  adder: {
    code: "0x6060604052602b8060106000396000f3606060405260e060020a6000350463771602f78114601a575b005b602435600435016060908152602090f3",
    info: {
      abiDefinition: [{...}],
      compilerOptions: "--bin --abi --userdoc --devdoc --add-std --optimize -o /tmp/solc171650220",
      compilerVersion: "0.3.2",
      developerDoc: {
        methods: {}
      },
      language: "Solidity",
      languageVersion: "0.3.2",
      source: "contract adder { function add(uint a, uint b) returns (uint c) {return a+b;} }",
      userDoc: {
        methods: {}
      }
    }
  }
}

The code contained in the compiled.adder.code field is the byte code that will be run on the Ethereum Vritual Machine (EVM). The info section contains metadata on the contract, including a field abiDefinition, which serves as an interface for creating contracts. To do this, run:

> var adder_contract = web3.eth.contract(compiled.adder.info.abiDefinition)
undefined
> adder_contract
{
  abi: [{
      constant: false,
      inputs: [{...}, {...}],
      name: "add",
      outputs: [{...}],
      type: "function"
  }],
  at: function(address, callback),
  new: function()
}

Towards the bottom is a function called new. It is this function that is used to deploy the contract to the blockchain. To do this, define the following callback function:

function tx_callback (e, contract) {
	if (!e) {
		if (!contract.address) {
			console.log("Transaction Hash: " + contract.transactionHash + " waiting to be mined.");	
		} else {
			console.log("Transaction mined at address " + contract.address)
		}
	}
}

Then, invoke the new function like so:

> var code = compiled.adder.code
> code
"0x6060604052602b8060106000396000f3606060405260e060020a6000350463771602f78114601a575b005b602435600435016060908152602090f3"
> var primary = web3.eth.accounts[0]
> personal.unlockAccount(primary, 'strong password that no one will guess') //  replace with your password
> var adder = adder_contract.new({from: primary, data: code, gas: 1000000}, tx_callback)
Transaction Hash: 0xe8ac2ba57281a8ec274993c605f44c2b854ce40adb1d3069cf7b5210b01dd0e0 waiting to be mined.

In the logs, you will see a similar set of messages to those obtained from sending Ether between accounts. After some delay, the transaction will be mined, and the resulting adder can be invoked:

> Transaction mined at address 0x783ce9eb8d98cb3554ed34f04751f9665ecb80eb
> parseInt(adder.add(2,3))
5
> parseInt(adder.add(200,3))
203

So, after all of that, we can, with some confidence, asssert that 2+3 and 200+3 are indeed 5 and 203, respectively. As underwhelming as this is, it is not hard to automate essentially everything we did aside from writing the Solidity code, after which the process becomes one of simply building and deploying.

To recreate the environment familiar to us from traditional programming, in which one might program in an external editor, then build and run their program from a shell, we will turn to nodejs.

Install Node.js

sudo apt-get install nodejs
npm install web3

Connecting with Node.js

Run geth with the arguments below. Don't worry about what all the flags mean right now. If you can't go on without understanding them, just read the information provided with `geth --help`. 
$ geth --rpc --rpcapi "eth,web3,personal,net,miner,admin" --networkid 123 console

This will start an Ethereum node, expose the api specified via RPC, and start mining. To connect via Node.js, run nodejs in another terminal, and execute the following comands:

> var web3 = require('web3')
> var web3 = new web3(new web3.providers.HttpProvider("http://localhost:8545"))
> web3.eth.accounts
[ '0x56e9f2fffc8fde5f0419a7c63e15f6d67ddbd228',
  '0x14aaf671e0d9f0dec3555dcf2f572bdb05932319' ]

We now have access to the tools from the geth console. Importantly, though, we can now use Node.js to use more advanced scripting features, interacting with our filesystem. To start, let's automate some of the commands appearing often, and save it in a file called 'startup.js'. I have included this file in the folder js. To use them directly, just clone or download the this repository, then in your nodejs session, run .load js/startup.js.

Before going through the details of each line in the startup.js file, just observe the result. Instead of doing all of that nonsense from before, we can instead just write the solidity code in an ordinary external text editor, then built and deploy it from a nodejs session.

Save the source for the adder contract in a file adder.sol.

contract adder {
	function add(uint a, uint b) constant returns (uint c) { return a + b; }
}

Then, in a nodejs session,

> .load startup.js
> var adder_contract = build('adder.sol', 'adder')
> var adder = deploy(adder_contract, 0, 'strong password that no one will guess')
> Contract transaction send: TransactionHash: 0x6a142fb14216614b6d82e88d19294c870067ea83ec11c769560fa7f867d886f0 waiting to be mined...
Contract mined! Address: 0x67a62d7001cf8e5e75f5bca773b44e52608c63f6
> parseInt(adder.add(1,2))
3

A Simple Token

Now that we finally have some basic setup, let's have a look at a simple token contract [a simplified version of the token contract described here: https://www.ethereum.org/token]. This is actually more powerful than it might seem, since in principal, a token can be used to represent such things as money, property, or voting rights. Importantly, though, is just how distant these applications are from us at the moment. Right now (Spring 2016), we are seeing proof of concepts for applications that do not actually seem anywhere close to practical application. Nevertheless, we are going to try to take this simple notion of a token to build some simple financial services, then get a sense of how a blockchain network handles these.

Save the following in a file called token.sol.

contract  token {
	mapping (address => uint256) public balanceOf;
	
	function token (uint initial_supply) {
		balanceOf[msg.sender] = initial_supply;
	}

	function transfer(address _receiver, uint256 _value) {
		if (balanceOf[msg.sender] < _value) throw;
		if (balanceOf[_receiver] + _value < balanceOf[_receiver]) throw;
		balanceOf[msg.sender] -= _value;
		balanceOf[_receiver] += _value;
	}
}

ethereum-tutorial's People

Contributors

kidwai avatar

Stargazers

 avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.