Build the private chain
I want to create 3 nodes with accounts. First node is called server, second is miner2, third is light. Server and singer2 are both miner nodes. Light is a node in light client mode, and its server node is as above first node I named.
Light client not synchronize full blocks of ethereum chain, but only have latest 10 Mb header of blocks. So light client mode is really fit the wallet application with mobile. I would like to use geth to develop Android application. And it only support light client mode on mobile. I want to test transaction with light client node on my iMac first.
- make folders for nodes
$ cd Desktop/
$ mkdir privateChain
$ cd privateChain/
$ mkdir server
$ mkdir miner2
$ mkdir light
$ ls
light miner2 server
create accounts
- server node
$ geth --datadir server/data account new
Address: {726794b16f6c5b0be0b78d7713a876ed3da8be1a}
- miner2 node
$ geth --datadir miner2/data account new
Address: {c077f8420d5b6c125897d9c5e21293ff6f77855c}
- light node
$ geth --datadir light/data account new
Address: {52ea0215068f436f837788686aa4b25de1a98f07}
- result file structure
n$ tree
.
├── light
│ └── data
│ └── keystore
│ └── UTC--2017-09-30T08-36-56.356255000Z--52ea0215068f436f837788686aa4b25de1a98f07
├── miner2
│ └── data
│ └── keystore
│ └── UTC--2017-09-30T08-34-11.290564552Z--c077f8420d5b6c125897d9c5e21293ff6f77855c
└── server
└── data
└── keystore
└── UTC--2017-09-30T08-32-37.801304633Z--726794b16f6c5b0be0b78d7713a876ed3da8be1a
9 directories, 3 files
create the genesis block
$ puppeth
+-----------------------------------------------------------+
| Welcome to puppeth, your Ethereum private network manager |
| |
| This tool lets you create a new Ethereum network down to |
| the genesis block, bootnodes, miners and ethstats servers |
| without the hassle that it would normally entail. |
| |
| Puppeth uses SSH to dial in to remote servers, and builds |
| its network components out of Docker containers using the |
| docker-compose toolset. |
+-----------------------------------------------------------+
Please specify a network name to administer (no spaces, please)
> privateChain
Sweet, you can set this via --network=privateChain next time!
INFO [09-30|16:40:23] Administering Ethereum network name=privateChain
WARN [09-30|16:40:23] No previous configurations found path=/Users/yen/.puppeth/privateChain
What would you like to do? (default = stats)
1. Show network stats
2. Configure new genesis
3. Track new remote server
4. Deploy network components
> 2
Which consensus engine to use? (default = clique)
1. Ethash - proof-of-work
2. Clique - proof-of-authority
> 2
How many seconds should blocks take? (default = 15)
> 3
I only set server node to be the singer. This step can lead to a problem that I can deal with later.
Which accounts are allowed to seal? (mandatory at least one)
> 0x726794b16f6c5b0be0b78d7713a876ed3da8be1a
> 0x
I only pre-fund ether to miner2 node. I will use it to send ether to light node and the node on Android application.
Which accounts should be pre-funded? (advisable at least one)
> 0xc077f8420d5b6c125897d9c5e21293ff6f77855c
> 0x
Below is rest.
Specify your chain/network ID if you want an explicit one (default = random)
>
Anything fun to embed into the genesis block? (max 32 bytes)
>
What would you like to do? (default = stats)
1. Show network stats
2. Save existing genesis
3. Track new remote server
4. Deploy network components
> 2
Which file to save the genesis into? (default = privateChain.json)
>
INFO [09-30|16:42:11] Exported existing genesis block
What would you like to do? (default = stats)
1. Show network stats
2. Save existing genesis
3. Track new remote server
4. Deploy network components
> ^C
- genesis block
$ vim privateChain.json
{
"config": {
"chainId": 56821,
"homesteadBlock": 1,
"eip150Block": 2,
"eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"eip155Block": 3,
"eip158Block": 3,
"clique": {
"period": 3,
"epoch": 30000
}
},
"nonce": "0x0",
"timestamp": "0x59cf588f",
"extraData": "0x0000000000000000000000000000000000000000000000000000000000000000726794b16f6c5b0be0b78d7713a876ed3da8be1a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"gasLimit": "0x47b760",
"difficulty": "0x1",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"coinbase": "0x0000000000000000000000000000000000000000",
"alloc": {
"c077f8420d5b6c125897d9c5e21293ff6f77855c": {
"balance": "0x200000000000000000000000000000000000000000000000000000000000000"
}
},
"number": "0x0",
"gasUsed": "0x0",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
}
network id is same as chainId
initialize nodes
- server node
$ geth --datadir server/data init privateChain.json
INFO [09-30|16:52:47] Allocated cache and file handles database=/Users/yen/Desktop/privateChain/server/data/geth/chaindata cache=16 handles=16
INFO [09-30|16:52:47] Writing custom genesis block
INFO [09-30|16:52:47] Successfully wrote genesis state database=chaindata hash=ffaa00…d07f18
INFO [09-30|16:52:47] Allocated cache and file handles database=/Users/yen/Desktop/privateChain/server/data/geth/lightchaindata cache=16 handles=16
INFO [09-30|16:52:47] Writing custom genesis block
INFO [09-30|16:52:47] Successfully wrote genesis state database=lightchaindata hash=ffaa00…d07f18
- miner2 node
$ geth --datadir miner2/data init privateChain.json
INFO [09-30|16:53:45] Allocated cache and file handles database=/Users/yen/Desktop/privateChain/miner2/data/geth/chaindata cache=16 handles=16
INFO [09-30|16:53:45] Writing custom genesis block
INFO [09-30|16:53:45] Successfully wrote genesis state database=chaindata hash=ffaa00…d07f18
INFO [09-30|16:53:45] Allocated cache and file handles database=/Users/yen/Desktop/privateChain/miner2/data/geth/lightchaindata cache=16 handles=16
INFO [09-30|16:53:45] Writing custom genesis block
INFO [09-30|16:53:45] Successfully wrote genesis state database=lightchaindata hash=ffaa00…d07f18
- light node
$ geth --datadir light/data --light init privateChain.json
INFO [09-30|16:55:17] Allocated cache and file handles database=/Users/yen/Desktop/privateChain/light/data/geth/chaindata cache=16 handles=16
INFO [09-30|16:55:17] Writing custom genesis block
INFO [09-30|16:55:17] Successfully wrote genesis state database=chaindata hash=ffaa00…d07f18
INFO [09-30|16:55:17] Allocated cache and file handles database=/Users/yen/Desktop/privateChain/light/data/geth/lightchaindata cache=16 handles=16
INFO [09-30|16:55:17] Writing custom genesis block
INFO [09-30|16:55:17] Successfully wrote genesis state database=lightchaindata hash=ffaa00…d07f18
I am not sure the
--light
option is required or not. I found it from go-ethereum issue #3510.
start up nodes
- server node - miner
$ geth --datadir server/data --networkid 56821 --nodiscover --identity server --lightserv 75 --lightpeers 10 --minerthreads 1 -rpc --rpcapi "db,eth,net,web3,personal,admin,txpool" --rpcport 8485 --rpcaddr "0.0.0.0" --rpccorsdomain "*" --port 30303 --v5disc --unlock "726794b16f6c5b0be0b78d7713a876ed3da8be1a" console
INFO [09-30|17:07:30] Starting peer-to-peer node instance=Geth/server/v1.7.0-stable-6c6c7b2a/darwin-amd64/go1.7.1
INFO [09-30|17:07:30] Allocated cache and file handles database=/Users/yen/Desktop/privateChain/server/data/geth/chaindata cache=128 handles=1024
WARN [09-30|17:07:30] Upgrading database to use lookup entries
INFO [09-30|17:07:30] Database deduplication successful deduped=0
INFO [09-30|17:07:30] Initialised chain configuration config="{ChainID: 56821 Homestead: 1 DAO: <nil> DAOSupport: false EIP150: 2 EIP155: 3 EIP158: 3 Byzantium: <nil> Engine: clique}"
INFO [09-30|17:07:30] Initialising Ethereum protocol versions="[63 62]" network=56821
INFO [09-30|17:07:30] Loaded most recent local header number=0 hash=ffaa00…d07f18 td=1
INFO [09-30|17:07:30] Loaded most recent local full block number=0 hash=ffaa00…d07f18 td=1
INFO [09-30|17:07:30] Loaded most recent local fast block number=0 hash=ffaa00…d07f18 td=1
INFO [09-30|17:07:30] Regenerated local transaction journal transactions=0 accounts=0
INFO [09-30|17:07:30] Starting P2P networking
INFO [09-30|17:07:30] RLPx listener up self="enode://540e892d76e86b3221aed4858613d7a9b96a1199db4c00901803dfc4abb59e1be359bd33281b91abb126aeb048c79a0720f80a5688c07b3ee4e16fcd5f44a83b@[::]:30303?discport=0"
INFO [09-30|17:07:30] Starting topic registration topic=LES@ffaa00ed88c5cdc8
INFO [09-30|17:07:30] IPC endpoint opened: /Users/yen/Desktop/privateChain/server/data/geth.ipc
INFO [09-30|17:07:30] HTTP endpoint opened: http://0.0.0.0:8485
Welcome to the Geth JavaScript console!
instance: Geth/server/v1.7.0-stable-6c6c7b2a/darwin-amd64/go1.7.1
coinbase: 0x726794b16f6c5b0be0b78d7713a876ed3da8be1a
at block: 0 (Sat, 30 Sep 2017 16:40:47 CST)
datadir: /Users/yen/Desktop/privateChain/server/data
modules: admin:1.0 clique:1.0 debug:1.0 eth:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0
I use --lightserv
option to let server node uses LES/1 protocol.
> admin.nodeInfo
{
enode: "enode://540e892d76e86b3221aed4858613d7a9b96a1199db4c00901803dfc4abb59e1be359bd33281b91abb126aeb048c79a0720f80a5688c07b3ee4e16fcd5f44a83b@[::]:30303?discport=0",
id: "540e892d76e86b3221aed4858613d7a9b96a1199db4c00901803dfc4abb59e1be359bd33281b91abb126aeb048c79a0720f80a5688c07b3ee4e16fcd5f44a83b",
ip: "::",
listenAddr: "[::]:30303",
name: "Geth/server/v1.7.0-stable-6c6c7b2a/darwin-amd64/go1.7.1",
ports: {
discovery: 0,
listener: 30303
},
protocols: {
eth: {
difficulty: 1,
genesis: "0xffaa00ed88c5cdc8b510dc5fbf5676d7373e040563c7133c9556eb8d21d07f18",
head: "0xffaa00ed88c5cdc8b510dc5fbf5676d7373e040563c7133c9556eb8d21d07f18",
network: 56821
},
les: {
difficulty: 1,
genesis: "0xffaa00ed88c5cdc8b510dc5fbf5676d7373e040563c7133c9556eb8d21d07f18",
head: "0xffaa00ed88c5cdc8b510dc5fbf5676d7373e040563c7133c9556eb8d21d07f18",
network: 56821
}
}
}
prepare static-node
There is no node connect to the server node now. I do not want to use the admin.addPeer()
on console. I need to prepare the config files for miner2 and light nodes, so that they can join to server node.
> admin.peers
[]
Static nodes are re-connected on disconnects. I have to prepare static-nodes.json
, and put it to the <datadir>/geth/
folder. I use Wi-Fi in my iMac, and the IP address 192.168.200.xxx. And the discport
is UDP port, its value is ${TCP port} +1
.
[
"enode://540e892d76e86b3221aed4858613d7a9b96a1199db4c00901803dfc4abb59e1be359bd33281b91abb126aeb048c79a0720f80a5688c07b3ee4e16fcd5f44a83b@192.168.200.xxx:30303?discport=30304"
]
Static nodes secton of Connecting to the network on go-ethereum GitHub
$ tree
.
├── light
│ └── data
│ ├── geth
│ │ ├── chaindata
│ │ ├── lightchaindata
│ │ └── static-nodes.json
│ └── keystore
│ └── UTC--2017-09-30T08-36-56.356255000Z--52ea0215068f436f837788686aa4b25de1a98f07
├── miner2
│ └── data
│ ├── geth
│ │ ├── chaindata
│ │ ├── lightchaindata
│ │ └── static-nodes.json
│ └── keystore
│ └── UTC--2017-09-30T08-34-11.290564552Z--c077f8420d5b6c125897d9c5e21293ff6f77855c
├── privateChain.json
└── server
└── data
├── geth
│ ├── LOCK
│ ├── chaindata
│ ├── lightchaindata
│ ├── nodekey
│ └── transactions.rlp
├── geth.ipc
└── keystore
└── UTC--2017-09-30T08-32-37.801304633Z--726794b16f6c5b0be0b78d7713a876ed3da8be1a
18 directories, 41 files
- miner2 node - miner
Launch miner2 on the second terminal of OSX.
$ geth --datadir miner2/data --networkid 56821 --nodiscover --identity miner2 --minerthreads 1 -rpc --rpcapi "db,eth,net,web3,personal,admin,txpool" --rpcport 8487 --rpcaddr "0.0.0.0" --rpccorsdomain "*" --port 30305 --unlock "c077f8420d5b6c125897d9c5e21293ff6f77855c" console
INFO [09-30|17:33:06] Starting peer-to-peer node instance=Geth/miner2/v1.7.0-stable-6c6c7b2a/darwin-amd64/go1.7.1
INFO [09-30|17:33:06] Allocated cache and file handles database=/Users/yen/Desktop/privateChain/miner2/data/geth/chaindata cache=128 handles=1024
WARN [09-30|17:33:06] Upgrading database to use lookup entries
INFO [09-30|17:33:06] Database deduplication successful deduped=0
INFO [09-30|17:33:06] Initialised chain configuration config="{ChainID: 56821 Homestead: 1 DAO: <nil> DAOSupport: false EIP150: 2 EIP155: 3 EIP158: 3 Byzantium: <nil> Engine: clique}"
INFO [09-30|17:33:06] Initialising Ethereum protocol versions="[63 62]" network=56821
INFO [09-30|17:33:06] Loaded most recent local header number=0 hash=ffaa00…d07f18 td=1
INFO [09-30|17:33:06] Loaded most recent local full block number=0 hash=ffaa00…d07f18 td=1
INFO [09-30|17:33:06] Loaded most recent local fast block number=0 hash=ffaa00…d07f18 td=1
INFO [09-30|17:33:06] Regenerated local transaction journal transactions=0 accounts=0
INFO [09-30|17:33:06] Starting P2P networking
INFO [09-30|17:33:06] RLPx listener up self="enode://acf05a7cc42e6504ca63e57c7cb70e7c0ec05c45cb38fe4691c9b71ec125b003751fbe00f2a6c6a4868fa1b17c50552687b7ec06677f9a19cca00411994994ac@[::]:30305?discport=0"
INFO [09-30|17:33:06] HTTP endpoint opened: http://0.0.0.0:8487
INFO [09-30|17:33:06] IPC endpoint opened: /Users/yen/Desktop/privateChain/miner2/data/geth.ipc
Unlocking account c077f8420d5b6c125897d9c5e21293ff6f77855c | Attempt 1/3
Passphrase:
INFO [09-30|17:33:14] Unlocked account address=0xc077F8420D5B6c125897D9c5e21293FF6f77855C
Welcome to the Geth JavaScript console!
instance: Geth/miner2/v1.7.0-stable-6c6c7b2a/darwin-amd64/go1.7.1
coinbase: 0xc077f8420d5b6c125897d9c5e21293ff6f77855c
at block: 0 (Sat, 30 Sep 2017 16:40:47 CST)
datadir: /Users/yen/Desktop/privateChain/miner2/data
modules: admin:1.0 clique:1.0 debug:1.0 eth:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0
> admin.peers
[{
caps: ["eth/63", "les/1"],
id: "540e892d76e86b3221aed4858613d7a9b96a1199db4c00901803dfc4abb59e1be359bd33281b91abb126aeb048c79a0720f80a5688c07b3ee4e16fcd5f44a83b",
name: "Geth/server/v1.7.0-stable-6c6c7b2a/darwin-amd64/go1.7.1",
network: {
localAddress: "192.168.200.207:56869",
remoteAddress: "192.168.200.207:30303"
},
protocols: {
eth: {
difficulty: 1,
head: "0xffaa00ed88c5cdc8b510dc5fbf5676d7373e040563c7133c9556eb8d21d07f18",
version: 63
}
}
}]
- light node - light client mode
$ geth --datadir light/data --networkid 56821 --nodiscover --identity light --light -rpc --rpcapi "db,eth,net,web3,personal,admin,txpool" --rpcport 8489 --rpcaddr "0.0.0.0" --rpccorsdomain "*" --port 30307 --unlock "52ea0215068f436f837788686aa4b25de1a98f07" console
INFO [09-30|17:36:04] Starting peer-to-peer node instance=Geth/light/v1.7.0-stable-6c6c7b2a/darwin-amd64/go1.7.1
INFO [09-30|17:36:04] Allocated cache and file handles database=/Users/yen/Desktop/privateChain/light/data/geth/lightchaindata cache=128 handles=1024
INFO [09-30|17:36:04] Initialised chain configuration config="{ChainID: 56821 Homestead: 1 DAO: <nil> DAOSupport: false EIP150: 2 EIP155: 3 EIP158: 3 Byzantium: <nil> Engine: clique}"
INFO [09-30|17:36:04] Loaded most recent local header number=0 hash=ffaa00…d07f18 td=1
INFO [09-30|17:36:04] Starting P2P networking
WARN [09-30|17:36:04] Light client mode is an experimental feature
INFO [09-30|17:36:04] RLPx listener up self="enode://63e1aafadeac420784a034381c4713e7b59494743cf7dcf8a799ff0ae7d8978e862472620b61997584b0e4e85a549234ce8bc0b5dfa15a8e48aeb3c324465b51@[::]:30307?discport=0"
INFO [09-30|17:36:04] IPC endpoint opened: /Users/yen/Desktop/privateChain/light/data/geth.ipc
INFO [09-30|17:36:04] HTTP endpoint opened: http://0.0.0.0:8489
Unlocking account 52ea0215068f436f837788686aa4b25de1a98f07 | Attempt 1/3
Passphrase:
INFO [09-30|17:36:08] Unlocked account address=0x52ea0215068f436f837788686aA4B25De1a98F07
Welcome to the Geth JavaScript console!
instance: Geth/light/v1.7.0-stable-6c6c7b2a/darwin-amd64/go1.7.1
modules: admin:1.0 debug:1.0 eth:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0
> admin.peers
[{
caps: ["eth/63", "les/1"],
id: "540e892d76e86b3221aed4858613d7a9b96a1199db4c00901803dfc4abb59e1be359bd33281b91abb126aeb048c79a0720f80a5688c07b3ee4e16fcd5f44a83b",
name: "Geth/server/v1.7.0-stable-6c6c7b2a/darwin-amd64/go1.7.1",
network: {
localAddress: "192.168.200.207:56877",
remoteAddress: "192.168.200.207:30303"
},
protocols: {
les: {
difficulty: 1,
head: "ffaa00ed88c5cdc8b510dc5fbf5676d7373e040563c7133c9556eb8d21d07f18",
version: 1
}
}
}]
Check the peers on console of server node
> admin.peers
[{
caps: ["les/1"],
id: "63e1aafadeac420784a034381c4713e7b59494743cf7dcf8a799ff0ae7d8978e862472620b61997584b0e4e85a549234ce8bc0b5dfa15a8e48aeb3c324465b51",
name: "Geth/light/v1.7.0-stable-6c6c7b2a/darwin-amd64/go1.7.1",
network: {
localAddress: "192.168.200.207:30303",
remoteAddress: "192.168.200.207:56877"
},
protocols: {
les: {
difficulty: 1,
head: "ffaa00ed88c5cdc8b510dc5fbf5676d7373e040563c7133c9556eb8d21d07f18",
version: 1
}
}
}, {
caps: ["eth/63"],
id: "acf05a7cc42e6504ca63e57c7cb70e7c0ec05c45cb38fe4691c9b71ec125b003751fbe00f2a6c6a4868fa1b17c50552687b7ec06677f9a19cca00411994994ac",
name: "Geth/miner2/v1.7.0-stable-6c6c7b2a/darwin-amd64/go1.7.1",
network: {
localAddress: "192.168.200.207:30303",
remoteAddress: "192.168.200.207:56869"
},
protocols: {
eth: {
difficulty: 1,
head: "0xffaa00ed88c5cdc8b510dc5fbf5676d7373e040563c7133c9556eb8d21d07f18",
version: 63
}
}
}]
Block sealing failed on miner2 node
> miner.start()
INFO [09-30|17:38:36] Transaction pool price threshold updated price=18000000000
INFO [09-30|17:38:36] Starting mining operation
null
> INFO [09-30|17:38:36] Commit new mining work number=1 txs=0 uncles=0 elapsed=1.100ms
WARN [09-30|17:38:36] Block sealing failed err=unauthorized
POA use the Clique API to manages the seal list. And I not allow miner2 to be signer on genesis block. So I got the unauthorized error. I have to ask the authorized node (here is server node) to let miner2 to join the list.
- console of server node
> clique.proposals
{}
> clique.propose("0xc077f8420d5b6c125897d9c5e21293ff6f77855c", true)
true
> clique.proposals
{
0xc077f8420d5b6c125897d9c5e21293ff6f77855c: true
}
> clique.getSnapshot()
{
hash: "0xfbfe67cd638d21f528036130cc703be8f8fdccb934d871f3f8c2eccda1ed4bf5",
number: 11,
recents: {
10: "0xc077f8420d5b6c125897d9c5e21293ff6f77855c",
11: "0x726794b16f6c5b0be0b78d7713a876ed3da8be1a"
},
signers: {
0x726794b16f6c5b0be0b78d7713a876ed3da8be1a: {},
0xc077f8420d5b6c125897d9c5e21293ff6f77855c: {}
},
tally: {},
votes: []
}
Now, server node needs miner2 to start mining.
> miner.start()
INFO [09-30|17:57:52] Transaction pool price threshold updated price=18000000000
INFO [09-30|17:57:52] Starting mining operation
null
> INFO [09-30|17:57:52] Commit new mining work number=10 txs=0 uncles=0 elapsed=69.377µs
INFO [09-30|17:57:52] Signed recently, must wait for others
- console of miner2 node
> miner.start()
INFO [09-30|17:59:17] Transaction pool price threshold updated price=18000000000
INFO [09-30|17:59:17] Starting mining operation
null
> INFO [09-30|17:59:17] Commit new mining work number=10 txs=0 uncles=0 elapsed=66.686µs
INFO [09-30|17:59:17] 🔗 block reached canonical chain number=4 hash=ce0a8a…4d7ba0
INFO [09-30|17:59:17] Successfully sealed new block number=10 hash=a1baee…d76916
INFO [09-30|17:59:17] 🔨 mined potential block number=10 hash=a1baee…d76916
INFO [09-30|17:59:17] Commit new mining work number=11 txs=0 uncles=0 elapsed=452.019µs
INFO [09-30|17:59:17] Signed recently, must wait for others
They can mining together now.
- console of server node
INFO [09-30|17:59:17] Imported new chain segment blocks=1 txs=0 mgas=0.000 elapsed=206.579µs mgasps=0.000 number=10 hash=a1baee…d76916
INFO [09-30|17:59:17] Commit new mining work number=11 txs=0 uncles=0 elapsed=112.383µs
INFO [09-30|17:59:17] 🔗 block reached canonical chain number=5 hash=950031…4d0048
INFO [09-30|17:59:20] Successfully sealed new block number=11 hash=fbfe67…ed4bf5
INFO [09-30|17:59:20] 🔨 mined potential block number=11 hash=fbfe67…ed4bf5