5 분 소요

Geth


실행 환경 : Docker Ubuntu

Geth Version : 1.10.24 - stable

Docker로 Ubuntu Geth 실행

로컬 테스트넷에서 Geth 실행

먼저 로컬 테스트넷에서 Geth를 실행하기 위해

  • 데이터 디렉터리 생성 : 송수신한 블록 데이터와 계정 정보 저장
  • genesis.json : 제네시스 블록 정보가 저장된 json 형태의 텍스트 파일

을 생성한다. 여기서는 먼저 계정을 생성한 후, 제네시스 블록을 정의할 때, 해당 계정에 Eth를 할당해 줄 것이기 genesis.json에는 내용이 들어가지 않아도 된다.

$ cd ~/go-ethereum
$ mkdir test_data # 데이터 디렉터리 생성
$ vim genesis.json # genesis.json 생성

i1

계정 생성


$ geth --datadir test_data account new

i2

이 때, 위 그림과 같이 주소값이 나오는데, 위에서 말했던 것과 같이 해당 계정에 Eth를 미리 할당하기 위해 genesis.json에서 사용할 것이다.

생성된 계정은

$ geth --datadir test_data account list

로 확인 가능하다.

i3

GenesisBlock 생성


제네시스 블록은 위에 생성했던 genesis.json에서 정의한다. (여기서 alloc 주소는 위에 생성한 계정 주소로 설정한다.)

i4

  • config : 이더리움 관련 설정
  • config.chainId : 현재 chain을 구별하는 값이며, Chainlist.org에 들어가면 확인 가능하다. 또한, 유효한 데이터 전송을 악의적으로 반복시키거나 지연시키는 replay attack으로부터 보호해주는 역할을 한다.
  • config.homesteadBlock : homestead는 이더리움의 프론티어, 홈스테드, 메트로폴리스, 세레니티 중 두 번째 단계로, 0일 경우 true를 뜻한다.
  • config.eip155Block : EIP155는 chainId와 마찬가지로 replay attack을 막기 위한 설정이다.
  • config.eip150Block: IO가 많은 작업에 대한 가스 변경 비용을 위한 설정이다.
  • config.eip158Block : EIP158은 계정의 상태가 변경되고, 변경된 결과값으로 인해 계정의 nonce와 balance 값이 0이 되고 code와 storage가 빈 값이 되는 경우 해당 계정을 삭제한다.
  • difficulty : 채굴 난이도로, 값이 클수록 난이도가 상승하며, 낮을수록 난이도가 낮아진다.
  • gasLimit : 블록당 담을 수 있는 가스의 한도를 설정한다. 하나의 블록 안에 담을 트랜잭션 개수를 결정하는데 사용하는 옵션이다. 따라서 값이 클수록 트랜잭션을 많이 보낼 수 있다.
  • alloc : 제네시스 블록이 생성됨과 동시에, alloc에 등록된 주소로 이더를 할당한다.

그 외 속성값

  • parentHash : 부모 블록의 해시값을 넣는다. 제네시스 블록은 부모 블록이 없기 때문에 사용하지 않는다.
  • coinbase : 제네시스 블록 채굴 시 주어지는 보상과 보상을 받을 어카운트 주소이다. 마이너가 coinbase값을 설정하기 때문에 제네시스 블록에서는 상관없다.
  • nonce, mixhash : 블록체인 작업 증명을 위한 값이다.
  • timestamp : 해당 블록이 취득된 시점을 의미하는 값으로, 제네시스 블록은 0으로 설정해도 된다. timestamp 값은 블록 간의 순서와 난이도를 조절하는 데 사용된다. 예를 들어 두 블록의 생성 시간이 짧다면 난이도가 쉬운 것이고,간격이 길다면 어려운 것이다.
  • extraData : 옵션 항목으로 최대 32바이트 공간이다.

Genesis Block 생성 및 초기화


앞서 정의한 제네시스 블록을 생성 및 초기화 한다.

$ geth --datadir test_data init ./genesis.json

i5

+ geth 디렉터리 구조

먼저 디렉터리 구조를 보기 위해 tree 모듈을 설치하고 tree를 통해 디렉터리 구조를 확인한다.

$ apt-get install tree -y
$ tree test_data

그러면 공통적으로 이더리움에서는 chaindata, lightchaindata, keystore등을 볼 수 있는데 각 디렉터리가 저장되는 데이터는 다음과 같다.

  • chaindata : 블록체인 데이터가 저장된다. 별도의 옵션 없이 콘솔 모드 작동 시 이더리움 메인 네트워크에 풀노드 동기화 모드로 연결하기 때문에 저장된다.
  • lightchaindata : 블록체인 데이터가 저장된다. geth syncmode를 light로 지정하면 라이트 노드로 블록 헤더에서 중요한 데이터만 저장한다.
  • keystore : 어카운트의 개인 키를 저장한다.
  • build/bin : Geth 실행 파일이 저장된다.
  • ethash : DAG 파일이 저장된다. 마이너를 구동시키면 작업 증명을 위한 해시 문제를 해결하기 위해 최대 2GB 사이즈의 DAG 파일을 만들어 메모리를 할당한다.
  • nodes : 노드에 관한 정보가 저장된다.
  • triecache : 트리의 캐시를 저장한다.

Geth 실행


Geth를 실행한다.

$ geth --networkid 8484 --nodiscover --datadir test_data -allow-insecure-unlock --http.addr 0.0.0.0 --http --http.port 8545 --http.corsdomain "*" --http.api="db,eth,net,web3,personal,web3,miner,admin" --miner.threads 1 console 2>> test_data/geth.log

i6

  • –datadir test_data : 데이터 디렉터리를 지정한다.
  • –networkid 8484 : 네트워크 식별자이다.
  • http 관련 : IP, Port, Cors, API를 지정한다. “*“의 경우 전체 허용이다.
  • –nodiscover : 생성자의 노드를 다른 노드에서 검색할 수 없게 한다. 즉 같은 제네시스 블록과 네트워크 ID에 있는 블록들이 연결되는 것을 방지한다.
  • -allow-insecure-unlock : 보안상의 이유로 외부에서 계정을 unlock하는 것을 금지하지만, 허용하도록 한다.
  • –miner.threads 1 : mining을 할 때 사용할 threads 수를 1로 지정한다.
  • console : 콘솔을 구동한다.
  • 2» test_data/geth.log : 해당 로그 파일에 에러를 저장한다.

Geth : 계정 생성 및 채굴

EOA 계정 생성 및 계정 확인


계정 생성

> personal.newAccount('아무값')

i7

계정 확인

> eth.accounts

i8

그러면 위와 같이 처음 생성했던 계정과 방금 생성된 계정이 확인된다.

채굴


채굴 계정 설정 및 확인

먼저 채굴을 하고 보상을 받을 계정을 설정한다. 기본적으로 eth.account[0]이 설정된다.

> miner.setEtherbase(personal.listAccounts[0])

i9

이후 채굴 계정을 확인한다.

> eth.coinbase

I10

채굴 계정 설정이 완료되면, 채굴 여부를 확인하기 위해 잔액을 확인한다.

> web3.fromWei(eth.getBalance(eth.coinbase), 'ether') # web3를 통해서 ether단위로 확인(기본 단위는 Wei이다.)

img11

블록 확인

먼저 현재 생성된 블록 수를 확인한다.

> eth.blockNumber

img12

현재 제네시스 블록 이후로 채굴을 하지 않았기 때문에 생성된 블록은 0개이다.

또한, 블록의 정보도 확인할 수 있다.

> eth.getBlock(blockNumber)

i13

위 그림과 같이 이전에 정의했던 제네시스 블록 정보 등을 확인할 수 있다.

채굴

채굴을 위해 우선 기본적으로 계정 잠금 상태를 풀어야 한다. 따라서 먼저 coinbase 계정의 잠금 상태를 확인한다.

> personal.listWallets[0].status

img14

현재 coinbase 계정이 잠금되어 있어 채굴을 하려면 잠금 해제가 필요하다. 따라서 계정 잠금 해제를 진행한다.

> personal.unlockAccount(eth.coinbase)

img15

위 그림과 같이 coinbase 계정 잠금해제가 완료되면, 채굴을 시작한다.

> miner.start(1) # 여기서 ()안은 스레드 개수이다.

img16

위와 같이 진행되면 성공이다. 이후 명령어를 통해 마이닝이 정상적으로 진행되는지 확인한다.

> eth.mining # 채굴을 진행하고 있는지 확인
> eth.blockNumber # 가장 최근에 추가된 블록의 숫자

img17

위와 같이 eth.mining이 진행되고, eth.blockNumber가 증가하면 성공적으로 채굴이 진행되는 것이다.

이후 채굴을 종료하고 coinbase 계정 잔액을 확인하면 잔액이 늘어난 것을 확인할 수 있다.

> miner.stop() # 채굴 종료
> web3.fromWei(eth.getBalance(eth.accounts[0]),'ether')

i18

Geth : 트랜잭션 생성 및 채굴

트랜잭션 생성

먼저 계정 0으로부터 계정 1로 2Eth를 송금하는 트랜잭션을 전송한다. (이 때, 채굴과 마찬가지로 계정은 unlock상태여야 한다.)

> eth.sendTransaction({
    	from:eth.accounts[0],
    	to:eth.accounts[1],
    	value:web3.toWei(2,’ether’), 
    	data:web3.toHex(”send message”)
    })

i19

트랜잭션 Pending 확인

정상적인 트랜잭션이 생성되면 위 그림과 같이 트랜잭션 해시가 출력된다. 하지만 해당 트랜잭션은 현재 네트워크의 채굴을 통해 블록에 저장하는 역할을 하는 채굴자가 없기 때문에 pending상태일 것이다. 따라서 pending된 트랜잭션을 확인한다.

> eth.pendingTransactions

i21

위와 같이 위에서 생성한 트랜잭션은 pending 상태이고 계정 1로 송금 또한, 당연히 이루어지지 않는다.

트랜잭션 처리를 위한 채굴 및 트랜잭션 확인

따라서 송금을 위해 채굴을 진행하고 계정 1의 잔액을 확인한다.

img22

위와 같이 채굴을 통해 트랜잭션이 성공적으로 블록에 저장되면, 트랜잭션 해시값을 사용해, 트랜잭션에 대한 정보를 확인할 수 있다.

> eth.getTransaction("TxHash")

i23

트랜잭션에 대한 정보는 blockNumber를 통해서도 확인할 수 있다.

> eth.getTransactionFromBlock(blockNumber)

i24

트랜잭션 수수료

i25

계정 0의 잔액을 보면 트랜잭션 수수료가 빠져나가지 않는다.(만약 빠져나갔다면 소수점자리에 변화) 이 이유는 간단하게 계정 0이 coinbase, 즉 채굴자였기 때문에 자신이 발생한 트랜잭션에 대해 보상인 수수료를 자신이 받아왔기 때문이다.

따라서 트랜잭션 수수료를 테스트해보기 위해 계정 2를 생성하여 coinbase로 지정하고 트랜잭션 채결 후, 잔액을 확인한다.

i26

i27

i28

그러면 위와 같이 계정 0은 수수료를 지불하고 채굴자인 계정 2는 수수료0.000021Ether를 받아온 것을 확인할 수 있다. 이는 트랜잭션 정보를 보면

i29

  • gas : 지불할 수 있는 최대 gas
  • gasPrice : 1gas 가격

이고 마찬가지로 채굴자에게 지급되는 수수료는 gas*gasPrice로

i30

위와 같이 확인할 수 있고, 이는 블록에서 역시 확인 가능하다.(여기서 gasLimit는 블록당 현재 지급 가능한 최대 가스 총합을 말하며, gasUsed는 현재 블록 내에 트랜잭션에 의해 사용된 가스 총합을 말한다.)

i31

-> 이더리움에서는 트랜잭션에 gasLimit(트랜잭션 수행 시 지급 가능한 최대 범위)와 gasPrice(트랜잭션 발신자가 각 실행 단계에서 지급하는 비용인 가스 가격)를 명시하여 실제 트랜잭션 발행 비용은 gasPrice * gasLimit를 통해 계산한다.

-> 이 때, gasPrice가 높을 수록 채굴자들이 우선적으로 처리하여 빨리 처리되며, gasLimit는 해당 트랜잭션이 최대 몇 가스가 소요되는지 예상치를 사용자가 추정하여 적고 트랜잭션을 수행하고도 남는다면 돌려받고 부족하다면 트랜잭션은 취소되고 사용한 가스도 돌려받지 못한다.

본 포스팅은 코드스테이츠 BEB 과정을 수강하며 작성한 글입니다.

Reference
코어 이더리움 프로그래밍 p55,56,61,64,82,83,144