Blockchain

[Blockchain] 파이썬으로 만드는 비트코인 (PoW) - 노드 구축 및 운영해보기

여백 :: 2024. 9. 29. 22:57

** 파이썬으로 공부하는 블록체인 (일등박사) 서적 기반으로 작성 **

 

 

앞서 배운 내용들을 기반으로 다음 단계를 진행해볼 것이다.

1) PoW(Proof of Work) 기반의 블록체인 노드를 구현하고, 해당 노드가 블록체인의 원리에 의해 작동하는지 확인한 뒤 노드에 거래 내역을 저장

2) 블록체인 네트워크의 거래 내역을 확인할 수 있는 Block scan 사이트를 구현하여 채굴될 때마다 저장되는 거래 내역과 previous hash 값을 확인

3) 사용자가 생성된 코인을 거래할 수 있는 거래 지갑 사이트를 구축

 

- 여기서 구축할 블록체인 네트워크의 코인 명칭은 pyBTC

- 해당 지갑 사이트를 통해 사용자는 자신의 지갑의 잔액을 확인할 수 있으며, 다른 지갑으로 py BTC 코인을 전송할 수 있을 것

- 또한 단일 노드에서 진행되었던 작업을 여러 노드에서 진행하여, 각 노드가 경쟁적으로 채굴을 하며 거래 내역 데이터가 분산원장에 모두 저장되는 탈중앙화 원리를 이해해보자.

 

 

 

1. 블록체인 노드 구축 (one_code.ipynb)

1) 파이썬 패키지 import

기존에 갖고 있던 주피터 노트북 환경에서 아나콘다 기반의 파이썬으로 진행

패키지명 패키지 설명
json JSON은 XML, YAML과 함께 효율적으로 데이터를 저장하고 교환하는 데 사용하는 텍스트 데이터 포맷 중 하나로 블록체인상 데이터는 json 상태로 저장됨
flask 파이썬의 web flask로 블록체인 API를 운영하고, 블록스캔 사이트, 지갑 사이트를 운영 
(flask, request, jsonify 활용)
time 기본 파이썬에 내장된 모듈로 컴퓨터 친화적인 timestamp를 인간 친화적 시간 타입으로 바꿔줌
hashlib 블록체인 운영의 핵심인 해시암호를 파이썬에서 적용할 수 있게 하는 모듈로 블록의 내용을 해당 라이브러리를 통하여 해시 처리
requests 파이썬에서 HTTP 요청을 보낼 때 사용되는 모듈로 flask로 구축된 블록체인 API와 소통할 때 사용됨
random 임의의 난수를 생성하는 모듈로 채굴 시 알맞은 nonce 값을 찾기 위하여 활용됨 

 

import hashlib
import json
from time import time
import random
import requests
from flask import Flask, request, jsonify

 

2) 블록체인 객체 만들기

1. 객체 생성

# 블록체인 객체 선언
class Blockchain(object):
    def __init__(self):
        self.chain = [] # 블록을 연결하는 체인
        self.current_transaction = [] # 블록 내에 기록되는 거래 내역 리스트
        self.nodes = set() # 블록체인을 운영하는 노드들의 정보
        self.new_block(previous_hash=1, proof=100) # 블록체인 첫 생성 시 자동으로 첫 블록(genesis block)을 생성하는 코드

 

 

2. 해시화

: 거래 내역 블록에 저장할 때, 암호 해시의 원리에 의해 json 형식의 거래 내역들이 SHA-256 방식으로 해시암호화 된다.

이 로직이 객체 내에서 아래와 같이 함수화되어 사용됨 

    @staticmethod
    def hash(block):
        block_string = json.dumps(block, sort_keys = True).encode()
        return hashlib.sha256(block_string).hexdigest()

 

<참고>

@staticmethod

- 클래스 바깥에 정의된 일반 함수와 완전히 동일하게 동작함

- 정적 메소드이지만 다른 언어와는 달리 인스턴스에서도 접근 가능! 

- 특정 클래스와 보다 밀접한 관계에 있다는 것을 나타내거나 코드를 간단하게 만들기 위해 사용

 

접근 제어자

- public : 접두사에 아무 밑줄이 없음

- protected : 접두사에 한 개의 밑줄을 적용

- __private : 접두사에 두 개의 밑줄을 적용

- private을 이용한 속성값을 가져오기 위한 접근자와 설정자로 get, set 메소드를 사용 

 

@property

- 위의 get 메소드를 직관적으로 표현하는 역할

 

# loads() 함수: JSON 문자열을 python 객체로 변환

import json

json_string = '''{
    "id": 1,
    "username": "James",
    "email": "abc@email.com",
    "address": {
        "street": "Cheongpa",
        "suite": "Apt. 516",
        "city": "seoul",
    },
    "admin": false,
    "hobbies": null
}'''

json_object = json.loads(json_string)

assert json_object['id'] == 1
assert json_object['email'] == 'abc@email.com'
assert json_object['address']['city'] == 'seoul'
assert json_object['admin'] is False
assert json_object['hobbies'] is None
# dumps() 함수 : python 객체를 JSON 문자열로 변환

import json

json_object = {
    "id": 1,
    "username": "James",
    "email": "abc@email.com",
    "address": {
        "street": "Cheongpa",
        "suite": "Apt. 516",
        "city": "seoul",
    },
    "admin": false,
    "hobbies": null
}

json_string = json.dumps(json_object)
print(json_string)

 

 

3. 블록체인의 마지막 블록 호출

: 블록의 최근 nonce 값을 기반으로 새로운 nonce 값을 찾기 위해, 블록체인의 가장 최근(마지막) 블록을 호출하는 함수가 필요

    @property
    def last_block(self):
        return self.chain[-1]

 

 

4. 검증(valid_proof)

- 블록체인 채굴 시 작업으로 산출된 nonce 값이 조건에 맞는 알맞은 값인지 검증이 필요

- 검증 함수에서는 마지막 블록의 nonce 값과 신규 nonce 후보 값을 결합하여 해시화한 뒤 첫 4개의 단어가 '0000'일 때 해당 nonce 값이 유효(valid)하다고 판단

    @staticmethod
    def valid_proof(last_proof, proof):
        guess = str(last_proof + proof).encode()
        guess_hash = hashlib.sha256(guess).hexdigest()
        return guess_hash[:4] == "0000"

 

 

5. PoW(Proof of Work) 채굴

- 블록체인 내에 거래 내역이 저장되기 위해서는 유효(valid) nonce 값이 확인되어야 함

- 이에 지속적으로 proof에 난수값을 생성하여 가장 최근 블록의 nonce 값(last_proof)과 비교하며 작업 증명(PoW)이 성공할 때까지 반복됨

    def pow(self, last_proof):
        proof = random.randint(-1000000, 1000000)
        while self.valid_proof(last_proof, proof) is False:
            proof = random.randint(-1000000, 1000000)
        return proof

 

 

6. 거래 내역 추가(new_transaction)

- 매번 블록이 생성되기 전 (채굴되기 전)까지 지속적으로 예비 블록 내에 거래 내역이 추가됨

- 이 블록체인의 거래 내역에는 발신자, 수신자, 보내는 금액, 시간 4가지 요소를 저장할 것임

    def new_transaction(self, sender, recipient, amount):
        self.current_transaction.append(
            {
                'sender' : sender, # 송신자
                'recipient' : recipient, # 수신자
                'amount' : amount, # 금액
                'timestamp' : time()
            }
        )
        return self.last_block['index'] + 1

 

 

7. 블록 추가 (new_block)

- current_transaction에 거래 내역이 추가되며, PoW 작업을 통해 유효한 nonce 값이 찾아졌을 때 신규 블록이 생성됨

- 신규 블록이 생성될 때 필요한 인자는 5가지 (블록 번호, 생성 시간, 거래 내역, nonce 값, 전 블록의 해시값)

- 기존 거래 내역이 블록에 저장된 후에는 현 거래 내역 리스트는 초기화 되어야 하며 (self.current_transaction = []) 생성된 블록은 객체의 체인 리스트에 추가됨 

    def new_block(self, proof, previous_hash = None):
        block = {
            'index' : len(self.chain) + 1,
            'timestamp' : time(),
            'transaction' : self.current_transaction,
            'nonce' : proof,
            'previous_hash' : previous_hash or self.hash(self.chain[-1]),
        }
        self.current_transaction = []
        self.chain.append(block)
        return block

 

 

8. 블록 검증 (valid_chain)

- 블록 생성 후 알맞은 블록이 생성되었는지 검증이 필요

- 마지막 블록의 해시값과 그 전 블록을 직접 해시한 값을 비교하여 과거 거래 내역에 변동된 것은 없는지 체크

- 이상이 있을 경우 False 값을 반환하고 모든 값이 정상일 경우 True 값을 반환

    def valid_chain(self, chain):
        last_block = chain[0]
        current_index = 1
        while current_index < len(chain):
            block = chain[current_index]
            print('%s' % last_block)
            print('%s' % block)
            print("\n--------\n")
            if block['previous_hash'] != self.hash(last_block):
                return False
            last_block = block
            current_index += 1
        return True

 

 

9. 최종 코드 

import hashlib
import json
from time import time
import random
import requests
from flask import Flask, request, jsonify

# 블록체인 객체 선언
class Blockchain(object):
    def __init__(self):
        self.chain = [] # 블록을 연결하는 체인
        self.current_transaction = [] # 블록 내에 기록되는 거래 내역 리스트
        self.nodes = set() # 블록체인을 운영하는 노드들의 정보
        self.new_block(previous_hash=1, proof=100) # 블록체인 첫 생성 시 자동으로 첫 블록을 생성하는 코드
        
    @staticmethod
    def hash(block):
        block_string = json.dumps(block, sort_keys = True).encode()
        return hashlib.sha256(block_string).hexdigest()

    @property
    def last_block(self):
        return self.chain[-1]

    @staticmethod
    def valid_proof(last_proof, proof):
        guess = str(last_proof + proof).encode()
        guess_hash = hashlib.sha256(guess).hexdigest()
        return guess_hash[:4] == "0000"

    def pow(self, last_proof):
        proof = random.randint(-1000000, 1000000)
        while self.valid_proof(last_proof, proof) is False:
            proof = random.randint(-1000000, 1000000)
        return proof

    def new_transaction(self, sender, recipient, amount):
        self.current_transaction.append(
            {
                'sender' : sender, # 송신자
                'recipient' : recipient, # 수신자
                'amount' : amount, # 금액
                'timestamp' : time()
            }
        )
        return self.last_block['index'] + 1

    def new_block(self, proof, previous_hash = None):
        block = {
            'index' : len(self.chain) + 1,
            'timestamp' : time(),
            'transaction' : self.current_transaction,
            'nonce' : proof,
            'previous_hash' : previous_hash or self.hash(self.chain[-1]),
        }
        self.current_transaction = []
        self.chain.append(block)
        return block

    def valid_chain(self, chain):
        last_block = chain[0]
        current_index = 1
        while current_index < len(chain):
            block = chain[current_index]
            print('%s' % last_block)
            print('%s' % block)
            print("\n--------\n")
            if block['previous_hash'] != self.hash(last_block):
                return False
            last_block = block
            current_index += 1
        return True

 

 

3) 블록체인 객체 기반으로 노드 만들기

1. 노드 기본 정보 설정

- 위의 블록체인 객체를 호출한 뒤, 운영할 노드의 IP주소와 포트 주소를 선언

- 이를 통해 노드의 key 값(node_identifier, 노드 IP + 포트 번호)을 생성하고, 노드의 채굴 결과 발생하는 수익을 보낼 지갑의 주소(mine_owner)와 채굴 보상값(mine_profit)을 선언

blockchain = Blockchain()
my_ip = '0.0.0.0'
my_port = '5000'
node_identifier = 'node_' + my_port
mine_owner = 'master'
mine_profit = 0.1

 

 

2. 블록 정보 호출 (full_chain)

- 블록체인 기술의 큰 장점 : 모든 거래 내역이 투명하게 공개됨

- 임의의 사용자가 블록체인 정보 호출 시 블록체인 내의 블록의 길이와 블록의 모든 정보를 json 양식으로 리턴

@app.route('/chain', methods=['GET'])
def full_chain():
    print("chain info requested!")
    response = {
        'chain' : blockchain.chain,
        'length' : len(blockchain.chain),
    }
    return jsonify(response), 200

 

 

3. 신규 거래 추가(new_transaction)

- 사용자 간의 거래가 발생할 경우 해당 거래 내역은 json 형식으로 요청되며, 이때 요청 사항 내에 거래 내역의 3가지 요소 (발신자, 수신자, 보내는 금액)가 있는지 확인한 뒤 없을 경우에는 400 에러를 배출

- 에러가 없을 경우에는 블록체인 객체의 new_transaction 함수를 활용하여 블록 거래 내역 내에 신규 거래 내역을 추가

# 신규 거래 추가
@app.route('/transactions/new', methods=['POST'])
def new_transaction():
    values = request.get_json()
    print("transactions_new!!! : ", values)
    required = ['sender', 'recipient', 'amount']
    if not all(k in values for k in required):
        return 'missing values', 400

    index = blockchain.new_transaction(values['sender'], values['recipient'], values['amount'])
    response = {'message' : 'Transaction will be added to Block {%s}' % index}
    return jsonify(response), 201

 

 

4. 채굴(mine)

- 채굴이 시작되면 마지막 블록 내의 nonce 값을 블록 객체의 pow에 넣은 뒤 작업을 시작

- 작업이 완료되고 작업 증명을 위한 nonce 값이 생성되면 mine_owner로부터 노드 운영자에게 채굴 보상이 주어지고 최종적으로 전 블록의 해시값을 포함하여 블록 객체의 new_block 함수로 블록이 생성됨

- 그리고 정상적으로 처리되었음을 json 결과값으로 리턴 

# 채굴
@app.route('/mine', methods = ['GET'])
def mine():
    print("MINING STARTED")
    last_block = blockchain.last_block
    last_proof = last_block['nonce']
    proof = blockchain.pow(last_proof)
    blockchain.new_transaction(
        sender = mine_owner,
        recipient=node_identifier,
        amount=mine_profit # coinbase transaction
    )
    previous_hash = blockchain.hash(last_block)
    block = blockchain.new_block(proof, previous_hash)
    print("MINING FINISHED")

    response = {
        'message' : 'new block found',
        'index' : block['index'],
        'transactions' : block['transactions'],
        'nonce' : block['nonce'],
        'previous_hash' : block['previous_hash']
    }

    return jsonify(response), 200

 

 

5. 노드 운영

- 지금까지 구성된 정보를 바탕으로 노드 운영을 시작 (노드의 IP 정보, port 정보 등)

app = Flask(__name__)
if __name__ == '__main__':
    app.run(host=my_ip, port=my_port)

 

 

6. 최종 실행 코드 

blockchain = Blockchain()
my_ip = '0.0.0.0'
my_port = '5000'
node_identifier = 'node_' + my_port
mine_owner = 'master'
mine_profit = 0.1

# 블록 정보 호출
@app.route('/chain', methods=['GET'])
def full_chain():
    print("chain info requested!")
    response = {
        'chain' : blockchain.chain,
        'length' : len(blockchain.chain),
    }
    return jsonify(response), 200

# 신규 거래 추가
@app.route('/transactions/new', methods=['POST'])
def new_transaction():
    values = request.get_json()
    print("transactions_new!!! : ", values)
    required = ['sender', 'recipient', 'amount']
    if not all(k in values for k in required):
        return 'missing values', 400

    index = blockchain.new_transaction(values['sender'], values['recipient'], values['amount'])
    response = {'message' : 'Transaction will be added to Block {%s}' % index}
    return jsonify(response), 201

# 채굴
@app.route('/mine', methods = ['GET'])
def mine():
    print("MINING STARTED")
    last_block = blockchain.last_block
    last_proof = last_block['nonce']
    proof = blockchain.pow(last_proof)
    blockchain.new_transaction(
        sender = mine_owner,
        recipient=node_identifier,
        amount=mine_profit # coinbase transaction
    )
    previous_hash = blockchain.hash(last_block)
    block = blockchain.new_block(proof, previous_hash)
    print("MINING FINISHED")

    response = {
        'message' : 'new block found',
        'index' : block['index'],
        'transactions' : block['transactions'],
        'nonce' : block['nonce'],
        'previous_hash' : block['previous_hash']
    }

    return jsonify(response), 200

app = Flask(__name__)
if __name__ == '__main__':
    app.run(host=my_ip, port=my_port)

 

 

 

2. 운영 중인 노드에 실행 명령하기 (one_node_command.ipynb)

이제 구성된 노드에 거래 내역을 저장하고, PoW을 통하여 블록을 생성하고, 생성된 데이터를 조회하는 등 블록체인 노드를 운영해보자.

 

1. 모듈 호출 

import requests
import json
import pandas as pd
import hashlib
import random

 

2. 블록 조회

- requests의 GET 방식을 통해 블록을 조회할 수 있는 URL API(http://localhost:5000/chain)에 현재 운영되는 노드의 모든 블록 데이터를 조회

- 정상적으로 조회되었다면 다음과 같이 노드 운영 노트북에 chain info requestes!! 라는 메시지가 프린트 된다.

 

- 현재는 첫 블록이 생성된 이후 채굴이 이루어지지 않았기에 1개의 블록 정보만 저장되어 있는 상태

 

 

3. Transaction 추가

- requests의 POST 방식을 통해 거래를 추가할 수 있는 API URL(http://localhost:5000/transactions/new)에 거래 내역 데이터를 보낸다. 아래 코드에서는 test_from 이라는 지갑으로부터 test_to 라는 지갑으로 3개의 pyBTC를 보냄 

## transaction 입력하기
headers = {'Content-Type' : 'application/json; charset=utf-8'}
data = {
    "sender" : "test_from",
    "recipient" : "test_to",
    "amount" : 3,
}
requests.post("http://localhost:5000/transactions/new", headers=headers, data=json.dumps(data)).content

블록체인 내 거래 내역 추가

 

운영 노트북 (one_node)을 확인해보면 아래와 같이 정상적으로 신규 Transaction이 추가되었다는 로그가 발생하며, 로그 내용을 확인해보면 sender 인 test_from으로부터 recipient인 test_to에게 3개의 pyBTC가 보내졌음을 확인할 수 있음 

 

 

블록에도 거래 내역이 잘 추가 되었을지 확인하기 위해 아래와 같이 블록 정보를 재조회한다.

현재 Transaction이 추가되었지만 추가되기 전인 모습과 차이가 없는데, 그 이유는 아직 블록에서 작업 증명 (PoW, 채굴)이 이루어지지 않았기 때문에 거래 내역이 블록체인 내의 current_transaction 리스트에 존재할 뿐 블록에 추가되지 않았기 때문이다!

 

4. 채굴 시작

- requests의 GET 방식을 통하여 채굴 실시를 명령하는 URL API(http://localhost:5000/mine)에 채굴 시작 신호를 줌

## 채굴 명령
headers = {'Content-Type' : 'application/json; charset=utf-8'}
res = requests.get("http://localhost:5000/mine")
print(res)
print(res.text)

 

그 결과 다음과 같이 정상적으로 블록체인의 채굴이 발생하였음을 확인할 수 있고, 노드 운영 노트북인 one_node.ipynb에서도 MINING STARTED 와 MINING FINISHED로 정상적인 채굴이 발생하였다는 로그를 확인할 수 있다!

노드에서의 채굴 결과

 

이제 다시 한 번 블록의 정보를 조회하면 index 값2의 두 번째 블록이 생긴 것을 확인할 수 있다!

 

- 이렇게 새로 생성된 블록에는 967400 라는 nonce 값이 입력되어 있고 2개의 거래 내역이 저장되어 있다.

- 우리는 1개의 거래 내역만 신청하였지만 블록 채굴에 따른 보상이 지급되어야 하기에 master로부터 채굴 노드인 node_5000에 1개의 거래 내역이 추가되어 총 2개의 거래 내역이 추가 저장되었음

 

- Transaction 1 : test_from으로부터 test_to로 전달된 3개의 pyBTC

- Transaction 2 : master부터 채굴노드(node_5000)에 제공된 채굴 보상

 


 

 

지금까지 나누어서 진행했던 거래 및 채굴을 한 번의 코드로 진행해보자.

이번 코드에서 진행되는 거래 내역은 아래와 같음

From To Amount
test_from test_to2 30
test_from test_to3 300

 

## transaction2 입력하기
headers = {'Content-Type' : 'application/json; charset=utf-8'}
data = {
    "sender" : "test_from",
    "recipient" : "test_to2",
    "amount" : 30,
}
requests.post("http://localhost:5000/transactions/new", headers=headers, data=json.dumps(data)).content

## transaction3 입력하기
headers = {'Content-Type' : 'application/json; charset=utf-8'}
data = {
    "sender" : "test_from",
    "recipient" : "test_to3",
    "amount" : 300,
}
requests.post("http://localhost:5000/transactions/new", headers=headers, data=json.dumps(data)).content

## 채굴하기
headers = {'Content-Type' : 'application/json; charset=utf-8'}
res = requests.get("http://localhost:5000/mine")
print(res)

## 노드의 블록 정보 확인 - 4
headers = {'Content-Type' : 'application/json; charset=utf-8'}
res = requests.get("http://localhost:5000/chain", headers=headers)

 

코드를 실행해보면 위와 같이 여러 거래 내역을 포함한 세 번째 블록이 생성된 것을 확인할 수 있다.

 

거래 transaction이 증가함에 따라 문자열이 나열된 JSON 방식으로는 확인이 어렵다는 단점이 있기에, pandas를 활용하여 지금까지의 거래 내역을 table로 확인해보자.

 

status_json = json.loads(res.text)
status_json['chain']
tx_amount_l = []
tx_sender_l = []
tx_reciv_l = []
tx_time_l = []

for chain_index in range(len(status_json['chain'])):
    chain_tx = status_json['chain'][chain_index]['transactions']
    for each_tx in range(len(chain_tx)):
        tx_amount_l.append(chain_tx[each_tx]['amount'])
        tx_sender_l.append(chain_tx[each_tx]['sender'])
        tx_reciv_l.append(chain_tx[each_tx]['recipient'])
        tx_time_l.append(chain_tx[each_tx]['timestamp'])

df_tx = pd.DataFrame()
df_tx['timestamp'] = tx_time_l
df_tx['sender'] = tx_sender_l
df_tx['recipient'] = tx_reciv_l
df_tx['amount'] = tx_amount_l
df_tx

 

거래 내역 종합

 

- 지금까지 우리가 입력했던 test_from 부터 test_to/test_to2/test_to3 와의 3가지 거래 내역 뿐만 아니라 master로부터 node_5000에 제공된 채굴 보상 내역까지 확인할 수 있음

- 위 거래 내역을 기반으로 지갑별 잔액을 계산하는 아래 코드를 실행해보면 다음과 같다.

df_sended = pd.DataFrame(df_tx.groupby('sender')['amount'].sum()).reset_index()
df_sended.columns = ['user','sended_amount']
df_received= pd.DataFrame(df_tx.groupby('recipient')['amount'].sum()).reset_index()
df_received.columns = ['user','received_amount']
df_received

df_status = pd.merge(df_received,df_sended, on ='user', how= 'outer').fillna(0)
df_status['balance'] = df_status['received_amount'] - df_status['sended_amount']
df_status

 

이렇게 위와 같이 각 계정별 잔고를 조회할 수 있게 된다!

채굴 노드였던 node_5000의 경우 작업 증명에 대한 보상으로 0.2pyBTC를 보유하게 되었고, pyBTC를 송금받았던 test_to, test_to2, test_to3 계정은 각각 3 / 30 / 300 개의 pyBTC를 보유하였음을 확인할 수 있다.

반대로 송금하기만 했던 test_from은 -336pyBTC, 채굴 보상을 제공했던 master는 -0.3pyBTC의 잔고가 있음을 확인할 수 있다.

 


 

 

이렇게 pyBTC 블록체인 운영을 위해 노드 운영 (one_node)과 노드 명령(one_node_command)으로 코드를 분리하여 운영했다. 그리고 실제 이더리움 네트워크도 이렇게 두 가지로 구분되어 운영된다!

 

이더리움 네트워크 운영 방법

 

1) 노드 운영

- 이더리움 네트워크는 모두에게 공개된 오픈 소스 기반의 네트워크

이에 하드웨어를 소유한 누구나 모두 이더리움 네트워크에 참가하여 노드를 운영할 수 있다. 혹은 이더리움 오픈소스를 기반으로 사적 블록체인 네트워크(Private Blockchain Network)를 운영할 수도 있으며 개발 테스트를 목적으로 사적 블록체인 네트워크를 운영해 주는 가나슈(Ganache)를 활용할 수도 있다.

이때 사용자는 이더리움 운영 언어인 Go를 다운받은 뒤 이더리움의 git을 복제하고 환경변수 설정 등 작업환경을 설정한다. (혹은 가나슈를 설치한다.) 이후 geth 명령을 통하여 노드의 운영을 시작한다.

이 과정에서 우리가 노드의 운영(one_node.ipynb)에서 학습했던 블록체인 객체 생성, 환경 세팅 등의 작업이 진행된다.

 

2) 노드에 실행 명령

노드가 운영되고 있다면 노드에 정보 조회/채굴/거래 내역 저장 등 실행 명령을 내려야 한다.

우리는 해당 과정을 one_node_command.ipynb이라는 파일에서 진행했다.

한편 실제 이더리움에서도 이와 동일하게 블록 정보 조회/지갑 리스트 조회/채굴 시작, 종료/거래 내역 조회 등의 명령을 내릴 수 있다. 명령을 내리는 기본 방식은 geth 명령어로 이더리움 네트워크에 접속한 뒤 Go 기반의 명령어로 내리는 것이다.

한편 외부 환경에서 API 방식으로 이 이더리움 네 트워크에 운영 명령을 내릴 수 있다.

이때 대표적으로 JavaScript 기반의 web3.js가 활용되며 그 외에도 위와 같이 파이썬(web3.py), 자바(web3j) 등 프로그래밍 언어가 활용된다.