이더리움 가상 머신Ethereum Virtual Machine(EVM)은 이더리움 네트워크상의 모든 참여자가 합의하는 상태를 담고 있는 가상의 컴퓨터이다. 어떤 참여자든 트랜잭션의 처리를 위해 EVM에 임의의 코드를 실행하도록 요청할 수 있으며, 이는 EVM의 상태를 바꾼다.
이더리움 노드는 EVM 상태를 저장하고 있는 실제 머신을 말한다. 네트워크상에서 블록체인 데이터를 읽거나 트랜잭션을 보내기 위해서는 노드와 연결되어야만 한다. 노드는 다른 노드와 EVM 상태 및 상태 변화 정보를 주고받으며, 모든 노드의 집합은 곧 이더리움 네트워크가 된다.
이더리움 노드를 컴퓨터에서 실행하기 위해서는 이더리움 클라이언트 애플리케이션이 필요하다. 이 글에서는 GethGo Ethereum를 이용해 프라이빗 네트워크를 구축해본다.
⚙️ VERSION/ geth=1.10.18-stable
💡️ 이더리움의 프라이빗 네트워크란 허가를 받은 조직이나 개인만이 참여할 수 있으며, 메인 체인과 분리되어 있는 블록체인 네트워크를 말한다.
$ git clone https://github.com/ethereum/go-ethereum.git
$ cd go-ethereum
$ make geth
$ mkdir {토큰명}
$ cd {토큰명}
$ vi genesis.json
모든 블록체인에는 “제네시스 블록genesis block(최초의 블록)”이 존재하며, 서로 다른 네트워크는 제네시스 블록을 공유하지 않는다. 따라서 메인 체인이 아닌 새로운 체인을 생성하고 싶다면 genesis.json
파일을 만들어 제네시스 블록을 따로 설정해주어야 한다. 다음은 예시 파일이다.
{
"config": {
"chainId": 21,
"homesteadBlock": 0,
"eip150Block": 0,
"eip155Block": 0,
"eip158Block": 0,
"byzantiumBlock": 0,
"constantinopleBlock": 0,
"petersburgBlock": 0,
"ethash": {}
},
"difficulty": "0x40000",
"gasLimit": "0x8000000",
"alloc": {}
}
주요 필드를 살펴보자면 다음과 같지만, 이해하지 않아도 따라오는 데 문제는 없다.
config
블록체인 설정chainId
네트워크 ID. 0~3이 아닌 값을 선택한다. 이더리움에서는 두 노드의 제네시스 블록과 체인 ID가 동일하면 같은 네트워크상에 있는 것으로 간주한다. ethash
PoW 방식의 컨센서스 알고리즘 (default). PoA 방식의 clique을 사용할 수도 있다.difficulty
채굴 난이도. 클수록 블록이 채굴되는 평균 시간이 길어진다.gasLimit
블록당 소모될 수 있는 가스의 최대치. 블록당 실행 가능한 연산의 총량을 결정한다.alloc
블록체인을 시작하기 전에 미리 돈을 넣어둘 계정의 목록.alloc
필드에 계정을 리스팅해둔다고 해서 자동으로 계정을 생성해주지는 않는다. 따라서 돈을 가지고 시작할 계정을 만들고 싶다면 네트워크를 구축하기 전에 계정을 직접 만들어주어야 한다. 이런 계정이 필요 없다면 아래 과정을 거칠 것 없이 3번으로 넘어가면 된다.
$ geth account new --datadir .
Your new key was generated
Public address of the key: {만들어진 계정 주소}
계정이 생성되었다. 이 값을 alloc
필드에 원하는 잔고와 함께 넣어준다.
{
"config": {
"chainId": 21,
"homesteadBlock": 0,
"eip150Block": 0,
"eip155Block": 0,
"eip158Block": 0,
"byzantiumBlock": 0,
"constantinopleBlock": 0,
"petersburgBlock": 0,
"ethash": {}
},
"difficulty": "0x40000",
"gasLimit": "0x8000000",
"alloc": {
"{만들어진 계정 주소}": {
"balance": "{넣어줄 돈의 양}"
}
}
}
$ geth --datadir . init genesis.json
$ geth --networkid {네트워크 ID} --datadir . --http --http.port {포트 주소} --http.api "admin,db,eth,miner,net,txpool,personal,web3" --allow-insecure-unlock --nodiscover --snapshot=false
genesis.json
에 설정해둔 네트워크 ID와 포트 주소를 아무거나 넣어서 위 커맨드를 입력하면 구축된 네트워크를 가동할 수 있다. 여기서 다른 쉘을 열어서 아래 커맨드를 입력하면 Geth 자바스크립트 콘솔이 열리면서 네트워크를 직접 사용해볼 수 있게 된다!
$ geth attach http://localhost:<포트 주소>
> personal.newAccount("{sender 비밀번호}")
"{sender 주소}"
> miner.start()
> miner.stop()
송금을 할 계정(sender)을 만든 뒤, 채굴로 보상을 받아 계정이 운용할 수 있는 돈을 번다. 2번에서 계정을 미리 만들어두었고, 일정 금액을 넣어두었다면 이 커맨드는 굳이 수행하지 않아도 괜찮다.
💡️ 최초로 채굴을 시작할 때에는 PoW 알고리즘을 위한 1GB 데이터셋을 생성할 시간이 필요하다. (네트워크를 가동 중인 터미널에서 “generating DAG in Progess”라는 메시지가 보일 것이다.) 그러므로
miner.start()
와miner.stop()
사이에 충분히 시간을 두고 기다리도록 하자. 채굴이 시작되면 아래와 같은 메시지가 출력된다.
> personal.newAccount("{receiver 비밀번호}")
"{receiver 주소}"
> personal.unlockAccount("{sender 주소}", "{sender 비밀번호}", 0)
> eth.sendTransaction({from: "{sender 주소}", to: "{receiver 주소}", value: web3.toWei({송금액}, "ether")})
"{트랜잭션 해시}"
송금을 받을 계정(receiver)을 만든다. sender 계정 잠금을 풀어준 뒤, receiver 계정으로 설정한 액수만큼의 이더를 송금한다. 실제 예시는 아래와 같다.
> miner.start()
> miner.stop()
> eth.getBalance("{receiver 주소}")
{receiver 잔액}
트랜잭션을 블록체인에 넣어주기 위해 한 번 더 채굴을 해준 다음 receiver의 잔액을 확인해보면 송금이 잘 이루어진 것을 확인할 수 있다. 이때 환율(?)은 1이더 = 1000000000000000000웨이이고, 잔액은 웨이 단위로 표시되므로 갑자기 큰 금액이 송금되었다고 놀라지 말자.
Private Networks | Go Ethereum
Geth를 활용한 프라이빗 블록체인 구축 & 마이닝 실습