2. 이더리움 실습(2)
페이지 정보
작성자 관리자 댓글 3건 조회 2,137회 작성일 21-07-03 23:53본문
2. 이더리움 실습(2)
geth = go + ethereum
geth는 이더리움 클라이언트 소프트웨어로, 이더리움 블록체인 네트워크의 풀노드를 구축하기 위해 사용된다.
Go 언어를 기반으로 이더리움 풀노드를 구현하고 작동시키기 위한 명령어 라인 인터페이스를 제공한다.
클라이언트 소프트웨어 중에서 가장 유명하고 많이 쓰이는게 geth이다.
geth 역할은 다음과 같다.
○ 채굴자나 어플리케이션 개발자들의 프로그램 인터페이스 역할
- geth를 통해 이더리움 블록체인의 노드로써 참여
- 채굴, 암호화폐 전송, 스마트 컨트랙트의 작성, 트랜젝션 브로드캐스팅 가능
○ 풀 블록 데이터 베이스를 다운
- 블록 전체의 거래 내역 탐색 가능
○ 풀 노드로서 블록 검증
- 이더리움 블록체인에 기여 가능
1. git 설치하고 go-ethereum 소스 가져오기
$ sudo apt install git
ethereum 폴더를 먼저 하나 만든다.
$ mkdir ~/ethereum && cd ~/ethereum
앞으로 ethereum 폴더는 실습의 root 폴더라고 생각하면 된다.
git 설치가 끝났으니 git을 통해 원격에 있는 github/ethereum/go-ethereum 의 geth 클라이언트를 다운받는다.
소스버전이고 컴파일 버전 전이다.
$ git clone https://github.com/ethereum/go-ethereum.git
git repository에서 go-ethereum 소스를 내려 받는다.
user@leelab:~/ethereum$ ll
합계 12
drwxrwxr-x 3 user user 4096 7월 3 23:49 ./
drwxr-x--- 14 user user 4096 7월 3 23:49 ../
drwxrwxr-x 36 user user 4096 7월 3 23:50 go-ethereum/
user@leelab:~/ethereum$
go-ethreum 폴더로 이동 후 빌드에 필요한 Go 언어와 컴파일러 등등 필수 라이브러리를 설치한다.
설치가 완료되면 이제 make 로 go 소스를 build 한다.
user@leelab:~/ethereum$ cd go-ethereum
user@leelab:~/ethereum/go-ethereum$ sudo apt-get install -y build-essential golang
user@leelab:~/ethereum/go-ethereum$ make all
빌드된 파일들 확인과 geth 버전을 확인한다.
user@leelab:~/ethereum/go-ethereum$ cd build/bin
user@leelab:~/ethereum/go-ethereum/build/bin$ ./geth version
Geth
Version: 1.10.5-unstable
Git Commit: 3b053185254959b2c52129b8d146d300a78eb1ad
Git Commit Date: 20210702
Architecture: amd64
Go Version: go1.16.2
Operating System: linux
GOPATH=
GOROOT=go
user@leelab:~/ethereum/go-ethereum/build/bin$
우선, 환경변수를 설정해야한다.
user@leelab:~/ethereum/go-ethereum/build/bin$ pwd
/home/user/ethereum/go-ethereum/build/bin
user@leelab:~/ethereum/go-ethereum/build/bin$ cd
$ sudo apt-get install vim
vi 에디터를 설치 후 아래와 같이 .bash_profile 안에 path 내용에 GETH 위치를 추가해준다.
user@leelab:~$ vi .bash_profile
export GETH=/home/user/ethereum/go-ethereum
export PATH="$PATH:$GETH/build/bin"
~
user@leelab:~$ source ~/.bash_profile
user@leelab:~$ env
GETH=/home/user/ethereum/go-ethereum
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/snap/bin:/home/user/ethereum/go-ethereum/build/bin
이렇게 하면 Geth 가 글로벌 환경변수에 등록 되면서 빌드된 파일을 실행할 수 있게 된다.
2. geth 계정 생성하기
geth를 실행하기 전 먼저 geth의 계정을 생성해 보도록 하겠다.
현재 ethereum 폴더 위치에서 test_data 폴더를 하나 만든다.
user@leelab:~$ cd ethereum/
user@leelab:~/ethereum$ mkdir test_data
user@leelab:~/ethereum$ cd test_data && touch password
패스워드 파일을 test_data 폴더에 만들어 놓는다.
user@leelab:~/ethereum/test_data$ cd ~/ethereum
user@leelab:~/ethereum$
이제 geth 명령어 중 account new를 해보도록 하겠다.
실제 geth 옵션은 -h 로 어떤것들이 있는지 확인해 볼 수 있다
user@leelab:~/ethereum$ geth --help
우선 옵션들이 다양하다. 이더리움, 마이닝, 네트워킹, RPC 등 다양한 옵션들이 나오는 것을 확인할 수 있는데 이 모든 것들 다 알아야 하는 것은 아니니 우선 참고만 한다.
user@leelab:~/ethereum$ geth --datadir test_data account new --password test_data/password
INFO [07-04|09:25:00.468] Maximum peer count ETH=50 LES=0 total=50
INFO [07-04|09:25:00.469] Smartcard socket not found, disabling err="stat /run/pcscd/pcscd.comm: no such file or directory"
Your new key was generated
Public address of the key: 0x48A51D5Cf189476d61AC0c9Ca7c930Af16Dee91A
Path of the secret key file: test_data/keystore/UTC--2021-07-04T00-25-00.469292620Z--48a51d5cf189476d61ac0c9ca7c930af16dee91a
- You can share your public address with anyone. Others need it to interact with you.
- You must NEVER share the secret key with anyone! The key controls access to your funds!
- You must BACKUP your key file! Without the key, it's impossible to access account funds!
- You must REMEMBER your password! Without the password, it's impossible to decrypt the key!
user@leelab:~/ethereum$
위의 명령어는 password 파일(실제 내용은 아무것도 없다)을 토대로 account 를 새로 생성하겠다는 의미이다. 패스워드를 따로 설정하지 않기 위해 만들어 놓았다.
10번을 실행하면 10개의 계정 생성된다. 송금 테스트를 위해 여러개 만들어 놓는다.
user@leelab:~/ethereum$ cd test_data/
user@leelab:~/ethereum/test_data$ ls -al
합계 12
drwxrwxr-x 3 user user 4096 7월 4 09:25 .
drwxrwxr-x 4 user user 4096 7월 4 09:21 ..
drwx------ 2 user user 4096 7월 4 09:25 keystore
-rw-rw-r-- 1 user user 0 7월 4 09:21 password
user@leelab:~/ethereum/test_data$
위의 명령어를 치게 되면 못보던 keystore 폴더가 생긴 것을 볼 수 있다.
user@leelab:~/ethereum/test_data$ cd keystore/
user@leelab:~/ethereum/test_data/keystore$ ls
UTC--2021-07-04T00-25-00.469292620Z--48a51d5cf189476d61ac0c9ca7c930af16dee91a
user@leelab:~/ethereum/test_data/keystore$ cat UTC--2021-07-04T00-25-00.469292620Z--48a51d5cf189476d61ac0c9ca7c930af16dee91a
{"address":"48a51d5cf189476d61ac0c9ca7c930af16dee91a","crypto":{"cipher":"aes-128-ctr","ciphertext":"45b123ded7e2ab19b4988f44fd5ff48000eb3c5b1f68db5f1c97504f71be20e6","cipherparams":{"iv":"71c9ce6e2bec37ad80c11bb8ae2cba60"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"25866a0645ac96a01bbdd2ef7d9c269da6889f856cae14a23bcab54caeb2863e"},"mac":"904129bf6e00eb2ac922b60d62cc38ae6fcbe8b6d87ddfc6f5301b8113b67f90"},"id":"df18c2a6-3c5d-4f37-a366-0e5b12c820fb","version":3}user@leelab:~/ethereum/test_data/keystore$
이게 바로 JSON 형태의 Account 계정들의 private key json 파일이다.
아마 거래소는 고객의 EOA 계정을 본인들이 운영하는 Geth 에서 생성하고 위와 같은 Key 파일을 내부망 안에다 두고 관리할 것이다.
JSON 형태이다. 저 안에는 우선 Address 정보와 내부적인 여러 Private key와 관련된 여러 정보들이 존재해 보이는 듯하다.
3. genesis 블록 생성하기
geth 를 띄워서 console 창에 거래를 해보는 실습을 해보겠다.
먼저 geth를 띄우기 전에 블록체인을 설정하는 작업을 해야하는데 test_data 폴더에 genesis.json 파일을 생성하고 파일 안에 다음과 같은 내용을 집어 넣어보겠다.
user@leelab:~/ethereum/test_data/keystore$ cd ~/ethereum
user@leelab:~/ethereum$ cd test_data/
user@leelab:~/ethereum/test_data$ vi genesis.json
{
"config": {
"chainId": 8484,
"homesteadBlock": 0,
"eip150Block": 0,
"eip155Block": 0,
"eip158Block": 0
},
"alloc" : {},
"coinbase" : "0x0000000000000000000000000000000000000000",
"difficulty" : "0x20",
"extraData" : "",
"gasLimit" : "0x47e7c5",
"nonce" : "0x0000000000000042",
"mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"timestamp" : "0x00"
}
user@leelab:~/ethereum/test_data$ cd ~/ethereum
user@leelab:~/ethereum$
이제 init을 한다.
댓글목록
관리자님의 댓글
관리자 작성일
> miner.stop()
null
> eth.pendingTransaction
undefined
> web3.fromWei(eth.getBalance(eth.accounts[1]),'ether')
1
> web3.fromWei(eth.getBalance(eth.coinbase),'ether')
454
> eth.sendTransaction({from : eth.coinbase, to : eth.accounts[1], value : web3.toWei(1,'ether')});
Error: authentication needed: password or unlock
at web3.js:6357:37(47)
at web3.js:5091:62(37)
at <eval>:1:20(19)
> personal.unlockAccount(eth.coinbase,'',0);
true
> eth.sendTransaction({from : eth.coinbase, to : eth.accounts[1], value : web3.toWei(1,'ether')});
"0x7a8d1cbbf4bca5a7f0f9b0f17206bdee6799dd7e0cdecf231ab7364253bf4632"
> eth.sendTransaction({from : eth.coinbase, to : eth.accounts[1], value : web3.toWei(1,'ether')});
"0xd189107498a26841d5964453314ad34f5390ad4450f35836e2b4ab93401d5ac3"
> eth.sendTransaction({from : eth.coinbase, to : eth.accounts[1], value : web3.toWei(1,'ether')});
"0x61c253ca28a2155dc9501a014f1c1f3b5a5e03e5c15bec8bf40e26d729d0bdb4"
> web3.fromWei(eth.getBalance(eth.accounts[1]),'ether')
1
> eth.pendingTransaction
undefined
> eth.pendingTransactions
[{
blockHash: null,
blockNumber: null,
from: "0x48a51d5cf189476d61ac0c9ca7c930af16dee91a",
gas: 21000,
gasPrice: 1000000000,
hash: "0x7a8d1cbbf4bca5a7f0f9b0f17206bdee6799dd7e0cdecf231ab7364253bf4632",
input: "0x",
nonce: 1,
r: "0x70d53125df3680109bdba583235b222d648e57f65696c91ad98062cac5f6eae2",
s: "0x6047e1a0474b32ef3562db7f5d63a49a91e850c1987c5b0198ca9a5e7563d862",
to: "0x34c7d14533c224084fabb7f9add8fe2b3879b3c3",
transactionIndex: null,
type: "0x0",
v: "0x426c",
value: 1000000000000000000
}, {
blockHash: null,
blockNumber: null,
from: "0x48a51d5cf189476d61ac0c9ca7c930af16dee91a",
gas: 21000,
gasPrice: 1000000000,
hash: "0xd189107498a26841d5964453314ad34f5390ad4450f35836e2b4ab93401d5ac3",
input: "0x",
nonce: 2,
r: "0x87b3ace5067ccd0c8501315f2702ded5fc0ae346c93e263b8aa819483082fa1e",
s: "0x7b016c7fdaaf8bf090c451e1bb6309b5ae7db16f244a3fb2b6fcda196011def4",
to: "0x34c7d14533c224084fabb7f9add8fe2b3879b3c3",
transactionIndex: null,
type: "0x0",
v: "0x426b",
value: 1000000000000000000
}, {
blockHash: null,
blockNumber: null,
from: "0x48a51d5cf189476d61ac0c9ca7c930af16dee91a",
gas: 21000,
gasPrice: 1000000000,
hash: "0x61c253ca28a2155dc9501a014f1c1f3b5a5e03e5c15bec8bf40e26d729d0bdb4",
input: "0x",
nonce: 3,
r: "0x689a763bb2b6a41fb4d9e51c4460959d4eed2b593cf723a2fb6b2ae314c33b32",
s: "0x41889a3041c5d4f95599c3173dc13d15a86ec8897893723818d994efce8bb36b",
to: "0x34c7d14533c224084fabb7f9add8fe2b3879b3c3",
transactionIndex: null,
type: "0x0",
v: "0x426b",
value: 1000000000000000000
}]
>
> miner.start()
null
> eth.pendingTransactions
[]
> miner.stop()
null
> web3.fromWei(eth.getBalance(eth.accounts[1]),'ether')
4
> exit
user@leelab:~/ethereum$
관리자님의 댓글
관리자 작성일
트랜잭션들은 다음과 같은 필드로 구성됩니다.
nonce: EOA에 발급되는 트랜잭션 일련번호를 나타냅니다.
gas price: 가스의 가격입니다.
gas limit: 가스의 최대 사용량입니다.
from: 발신자 주소입니다.
to: 수신자 주소입니다.
value: 수신자에게 보내는 이더(ether) 개수입니다.
data: 가변길이의 바이너리 데이터(payload)입니다.
v, r, s: ECDSA 서명 구성 요소 입니다.
관리자님의 댓글
관리자 작성일
거래 영수증 항목들입니다.
blaockHash: 거래를 어떤 블록에 저장했는지 나타냅니다.
blockNumber: 거래를 몇 번째 블록에 저장했는지 나타냅니다.
contractAddress: 컨트랙트에 참여한 트랜잭션이라면 컨트랙트가 나타납니다.
cumulativeGasUsed: 트랜잭션에서 사용한 가스 사용량입니다.
from: 거래 발신자의 주소가 있습니다. 20바이트(160비트) 값입니다.
gasUsed: 사용한 가스 사용량입니다.
logsBloom: 블록 안에서 출력하는 로그 데이터를 블룸필터 형태로 저장한 것입니다
logs: 거래에서 생성된 로그들입니다.
root: 상태 트리를 바꾼 후의 상태 루트 값입니다.
to: 거래 수신자의 주소가 있습니다.
transactionHash: 32바이트의 거래 해시값을 나타냅니다.