블록체인 플랫폼 중 하나인 Ethereum을 설치하고 Private Network를 구축해보았습니다.
Ubuntu 18.04 LTS(ubuntu-18.04-desktop-amd64)
에서 진행되었습니다.
Geth 설치
geth
는 이더리움 노드 실행을 위한 CLI(Command Line Interface)입니다.
golang
Go를 이용해 빌드하기 때문에 golang을 설치해야 합니다.
# 패키지를 이용한 설치
$ sudo apt-get install golang-go
# 바이너리를 이용한 설치
$ wget https://dl.google.com/go/go1.10.3.linux-amd64.tar.gz
$ tar zxvf go1.10.3.linux-amd64.tar.gz
$ cd go
$ export GOROOT = $( pwd )
$ export PATH = $PATH :$GOROOT /bin
$ go version
go version go1.10.3 linux/amd64
Building geth
$ git clone https://github.com/ethereum/go-ethereum.git
$ cd go-ethereum
$ make
$ sudo cp build/bin/geth /usr/local/bin/
$ geth version
Geth
Version: 1.8.14-unstable
Git Commit: 45eaef24319897f5b1679c9d1aa7d88702cce905
Architecture: amd64
Protocol Versions: [ 63 62]
Network Id: 1
Go Version: go1.10.3
Operating System: linux
GOPATH =
GOROOT = /home/jbshin/ehtereum-workspace/go
Private Network
위의 과정으로 geth가 설치되고 설치된 geth를 이용해 Private Network를 구축해보겠습니다.
우선 편의를 위해 privnet
이라는 폴더를 만들게요.
편하신 경로에 편하신 폴더명으로 작명하셔도 됩니다!
$ mkdir -p ~/ethereum-workspace/privnet
$ cd ~/ethereum-workspace/privnet
Genesis Block
제네시스 블록을 생성하기 위해 genesis.json
파일을 작성합니다.
편하신 에디터를 이용해 아래의 내용을 입력해주세요.
{
"config" : {
"chainId" : 2018 ,
"homesteadBlock" : 0 ,
"eip155Block" : 0 ,
"eip158Block" : 0
},
"nonce" : "0x0000000000000033" ,
"timestamp" : "0x0" ,
"parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000" ,
"gasLimit" : "0x8000000" ,
"difficulty" : "0x100" ,
"mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000" ,
"coinbase" : "0x3333333333333333333333333333333333333333" ,
"alloc" : {}
}
Initialize
$ geth --datadir ./data init genesis.json
Node
제네시스 블록 생성까지 했으니 모든 준비가 완료된 것 같네요.
이제 노드를 실행해볼까요?
$ geth --rpc --datadir ./data --nodiscover --rpcapi db,eth,net,web3,admin.personal console
RPC address와 port는 각각 --rpcaddr
, --rpcport
옵션을 이용해 지정할 수 있으며 default로 127.0.0.1:8545
를 사용합니다.
--networkid
를 이용해 네트워크ID를 지정할 수 있습니다.
--nodiscover
옵션은 같은 제네시스 블록과 네트워크ID에 있는 노드들이 연결하는 것을 방지해줍니다.
Geth 사용하기
geth로 Private Network의 노드로 참여하는 것에 성공했습니다!
그렇다면 account를 만들고 mining을 하고 송금하는 등 간단한 사용법 몇가지를 알아볼까요?
account 목록을 조회해볼게요.
> eth.accounts
[]
명령어를 입력하니 빈 배열이 나오네요.
account가 없으니 하나 새로 만들어보죠.
> personal.newAccount( 'jb' )
"0x260bf32fc4529a3167c73f02f06201c02f028205" # 출력되는 값이 다를거에요!
personal.newAccount()
의 파라미터에 passphrase가 입력됩니다.
0x260bf32fc4529a3167c73f02f06201c02f028205
의 passphrase는 jb
에요.
> eth.accounts
[ "0x260bf32fc4529a3167c73f02f06201c02f028205" ]
account 목록에 정상적으로 추가되었네요.
이 account에는 얼마의 ether가 있을까요?
> eth.getBalance( eth.accounts[0]) # eth.getBalance('0x260bf32fc4529a3167c73f02f06201c02f028205')
0
0이네요… 당연한거겠죠?
블록을 마이닝하고 보상을 받는 과정을 해보겠습니다.
> miner.start()
INFO [ 08-10|17:35:09.128] Updated mining threads threads = 0
INFO [ 08-10|17:35:09.128] Transaction pool price threshold updated price = 18000000000
INFO [ 08-10|17:35:09.128] Etherbase automatically configured address = 0x260BF32FC4529a3167c73f02F06201C02F028205
null
INFO [ 08-10|17:35:09.128] Commit new empty mining work number = 1 uncles = 0
INFO [ 08-10|17:35:09.128] Commit new full mining work number = 1 txs = 0 uncles = 0 elapsed = 261.395µs
INFO [ 08-10|17:35:12.791] Generating DAG in progress epoch = 0 percentage = 0 elapsed = 2.844s
INFO [ 08-10|17:35:15.767] Generating DAG in progress epoch = 0 percentage = 1 elapsed = 5.819s
...
INFO [ 08-10|17:39:54.978] Successfully sealed new block number = 1 hash = 5a2077…0eb665
INFO [ 08-10|17:39:54.979] 🔨 mined potential block number = 1 hash = 5a2077…0eb665
INFO [ 08-10|17:39:54.979] Commit new empty mining work number = 2 uncles = 0
INFO [ 08-10|17:39:54.979] Commit new full mining work number = 2 txs = 0 uncles = 0 elapsed = 316.197µs
마이닝까지의 시간이 꽤 걸릴거에요~
🔨 표시와 함께 1번 블록이 마이닝되었습니다!
(참고) account가 여러 개 있는데 그 중 하나를 지정해 보상을 받고 싶으시다면 miner.setEtherbase()
를 활용해보세요!
> miner.setEtherbase( eth.accounts[1])
> eth.getBalance( eth.accounts[0])
5000000000000000000
5ether(5,000,000,000,000,000,000wei)를 보상으로 받은 것을 확인할 수 있습니다.
이번엔 송금을 해봐야겠죠?
송금을 위해 account를 하나 더 생성합시다!
> personal.newAccount( 'foo' )
"0xc07f222c6312473fc5694fd2ae1cf1e78410b58c"
처음 만들었던 account에서 1ether를 새로 만든 account로 송금해보죠!
트랜잭션을 발생하기 위해서는 account unlock 과정이 필요합니다.
> personal.unlockAccount( eth.accounts[0])
Unlock account 0x260bf32fc4529a3167c73f02f06201c02f028205
Passphrase:
true
> eth.sendTransaction({ from: eth.accounts[0], to: eth.accounts[1], value: web3.toWei( 1, 'ether' )})
INFO [ 08-10|19:59:50.985] Submitted transaction fullhash = 0x1a5fa277634a504a10ff4f33a6a29c208e90c113d54b40c5b4bcc99e84fd1a63 recipient = 0xc07f222C6312473FC5694fD2ae1cf1E78410b58C
"0x1a5fa277634a504a10ff4f33a6a29c208e90c113d54b40c5b4bcc99e84fd1a63"
accounts의 0번(jb)에서 1번(foo)로 1ether를 송금하는 트랜잭션이 발생하였습니다.
이 트랜잭션의 정보를 볼까요?
eth.pendingTransactions
과 eth.getBlock('pending').transactions
는 현재 마이닝 중인 블록에 있는 트랜잭션을 볼 수 있습니다.
> eth.pendingTransactions
[{
blockHash: null,
blockNumber: null,
from: "0x260bf32fc4529a3167c73f02f06201c02f028205" ,
gas: 90000,
gasPrice: 18000000000,
hash : "0x1a5fa277634a504a10ff4f33a6a29c208e90c113d54b40c5b4bcc99e84fd1a63" ,
input: "0x" ,
nonce: 0,
r: "0xfee8ec5ab640f3a37c27b569966f9ec8a43199b2c8ef197ee49cf3cf67aa6df8" ,
s: "0x6ca469673ec1e00d1e00d0954b0d8db49285b0dac418c8582d0dbb7b9237bad" ,
to: "0xc07f222c6312473fc5694fd2ae1cf1e78410b58c" ,
transactionIndex: 0,
v: "0xfe8" ,
value: 1000000000000000000
}]
> eth.getBlock( 'pending' ) .transactions
[ "0x1a5fa277634a504a10ff4f33a6a29c208e90c113d54b40c5b4bcc99e84fd1a63" ]
트랜잭션이 발생되고 블록이 마이닝 된 후 ether를 확인해봅니다.
> eth.getBalance( eth.accounts[1])
1000000000000000000
1ether(1,000,000,000,000,000,000wei)가 입금되었습니다!
Private Network
다시 Private Network입니다.
이름이 Network인데 노드가 하나만 있다면 아쉽겠죠?
노드의 정보를 확인해볼게요.
> admin.nodeInfo
{
enode: "enode://9bb90c172175f636faa6d1670607c88d23524080ee38f63a6d9347f5fa8d1e931a4a9e0423e7fab9f7816883d4a818474118aa41039e495f7f172d285d7a4df7@[::]:30303?discport=0" ,
id : "9bb90c172175f636faa6d1670607c88d23524080ee38f63a6d9347f5fa8d1e931a4a9e0423e7fab9f7816883d4a818474118aa41039e495f7f172d285d7a4df7" ,
ip: "::" ,
listenAddr: "[::]:30303" ,
name: "Geth/v1.8.14-unstable-45eaef24/linux-amd64/go1.10.3" ,
ports: {
discovery: 0,
listener: 30303
} ,
protocols: {
eth: {
config: {
chainId: 2018,
eip150Hash: "0x0000000000000000000000000000000000000000000000000000000000000000" ,
eip155Block: 0,
eip158Block: 0,
homesteadBlock: 0
} ,
difficulty: 918208,
genesis: "0x5704d029fe80f4fb605c0cb5e31d591511f10a46a0cb8166f97d8d559f9bc5b0" ,
head : "0xe74d827b527f35d9de71bd113ccdbc8498e36cedd9db9cb1b0ebc1c0390456b1" ,
network: 1
}
}
}
이 데이터의 enode
를 이용해 다른 노드에서 이 노드를 네트워크에 추가 할 수 있습니다.
기존 노드를 종료하고 rpcaddr을 지정해서 다시 실행시켜볼게요.
> exit
$ geth --rpc --rpcaddr 0.0.0.0 --datadir ./data --nodiscover --rpcapi db,eth,net,web3,admin.personal console
다른 PC에서 노드를 하나 더 실행해 준 후 아래처럼 node를 추가할 수 있습니다.
# 위와 다른 PC의 노드입니다.
> admin.addPeer( 'enode://9bb90c172175f636faa6d1670607c88d23524080ee38f63a6d9347f5fa8d1e931a4a9e0423e7fab9f7816883d4a818474118aa41039e495f7f172d285d7a4df7@[::]:30303?discport=0' )
true
> admin.peers
[{
caps: [ "eth/62" , "eth/63" ] ,
id : "9bb90c172175f636faa6d1670607c88d23524080ee38f63a6d9347f5fa8d1e931a4a9e0423e7fab9f7816883d4a818474118aa41039e495f7f172d285d7a4df7" ,
name: "Geth/v1.8.14-unstable-45eaef24/linux-amd64/go1.10.3" ,
network: {
inbound: false ,
localAddress: "[::1]:52530" ,
remoteAddress: "[::1]:30303" ,
static: true ,
trusted: false
} ,
protocols: {
eth: {
difficulty: 918208,
head : "0xe74d827b527f35d9de71bd113ccdbc8498e36cedd9db9cb1b0ebc1c0390456b1" ,
version: 63
}
}
}]
> INFO [ 08-10|20:23:19.741] Block synchronisation started
블록 동기화가 이루어지고 피어가 2개인 PrivateNetwork가 만들어졌습니다. 더 추가도 되겠죠?
댓글남기기