どうも、月見(@Suzuka14144156)です。
私は、ブロックチェーンに関する研究をしており、本ブログでは仮想通貨/暗号資産の情報を整理して発信しています。
今回は、Pythonでブロックチェーンを実際に実装していきたいと思います。
参考にした講座は以下のUdemyの講座です。
こちらの講座は、Pythonでスクラッチでブロックチェーンを実装するというものです。
Pythonの中級者以上の向けの講座となっています。
ブロックチェーンだけでなく、クラスを使ったコーディングを覚えたい方にもオススメの講座だと思います。
前回までの私の記事は、こちらです。
今回は、前回からの続きですので、お読みでない方は、ぜひ参考にしてみてください。
【Python】ブロックチェーンの実装_1 クラスの定義
【Python】ブロックチェーンの実装方法_2 hashの定義
【Python】ブロックチェーンの実装方法_3 トランザクションの定義
【Python】ブロックチェーンの実装方法_4 Proof of Workの定義
今回は、マイニングの実装です。
マイニングとは?
- 対象期間に発生したすべての取引のデータの整合性を取りながら正確に記録する作業
- マイニングの対価として、暗号資産を得ることができる
マイニングを行ったものに対し、ブロックチェーンから仮想通貨が送られる仕組みを実装します。
マイニングの実際の動作としては、それまでの取引情報をトランザクションに格納し、nonceとprev_hashを格納すれば良いです。
そのためコードとしては、以下になります。
マイニングの実装
minningメソッドがコールされるとトランザクションに以下の情報が格納されます。
- sender_blockchain_address=MINING_SENDER,
- recipient_blockchain_address=self.blockchain_address,
- value=MINING_REWARD
MINING_SENDERは、報酬を送るブロックチェーンアドレスです。
recipient_blockchain_addressは、報酬を受け取る人のアドレスです。
MINING_REWARDは、報酬の額です。
def mining(self):
self.add_transaction(
sender_blockchain_address=MINING_SENDER,
recipient_blockchain_address=self.blockchain_address,
value=MINING_REWARD)
nonce = self.proof_of_work()
previous_hash = self.hash(self.chain[-1])
self.create_block(nonce, previous_hash)
logger.info(
トランザクションが生成されるとProof of Workのアルゴリズムより、nonceが算出されます。
そしてそれまでのブロックをhash化しprev_hashに格納します。
utils.py
import collections
def sorted_dict_by_key(unsorted_dict):
return collections.OrderedDict(
sorted(unsorted_dict.items(), key=lambda d: d[0]))
ディクショナリーのitemの順序を整列かさせるための関数です。
詳細は、以下の記事を参考にしてみてください。
【Python】ブロックチェーンの実装方法_2 hashの定義
blockchains.py
import hashlib
import json
import logging
import sys
import time
import utils
MINING_DIFFICULTY = 3
MINING_SENDER = 'THE BLOCKCHAIN'
MINING_REWARD = 1.0
logging.basicConfig(level=logging.INFO, stream=sys.stdout)
logger = logging.getLogger(__name__)
class BlockChain(object):
def __init__(self, blockchain_address=None):
self.transaction_pool = []
self.chain = []
self.create_block(0, self.hash({}))
self.blockchain_address = blockchain_address
def create_block(self, nonce, previous_hash):
block = utils.sorted_dict_by_key({
'timestamp': time.time(),
'transactions': self.transaction_pool,
'nonce': nonce,
'previous_hash': previous_hash
})
self.chain.append(block)
self.transaction_pool = []
return block
def hash(self, block):
sorted_block = json.dumps(block, sort_keys=True)
return hashlib.sha256(sorted_block.encode()).hexdigest()
def add_transaction(self, sender_blockchain_address,
recipient_blockchain_address, value):
transaction = utils.sorted_dict_by_key({
'sender_blockchain_address': sender_blockchain_address,
'recipient_blockchain_address': recipient_blockchain_address,
'value': float(value)
})
self.transaction_pool.append(transaction)
return True
def valid_proof(self, transactions, previous_hash, nonce,
difficulty=MINING_DIFFICULTY):
guess_block = utils.sorted_dict_by_key({
'transactions': transactions,
'nonce': nonce,
'previous_hash': previous_hash
})
guess_hash = self.hash(guess_block)
return guess_hash[:difficulty] == '0'*difficulty
def proof_of_work(self):
transactions = self.transaction_pool.copy()
previous_hash = self.hash(self.chain[-1])
nonce = 0
while self.valid_proof(transactions, previous_hash, nonce) is False:
nonce += 1
return nonce
def mining(self):
self.add_transaction(
sender_blockchain_address=MINING_SENDER,
recipient_blockchain_address=self.blockchain_address,
value=MINING_REWARD)
nonce = self.proof_of_work()
previous_hash = self.hash(self.chain[-1])
self.create_block(nonce, previous_hash)
logger.info({'action': 'mining', 'status': 'success'})
return True
if __name__ == '__main__':
my_blockchain_address = 'my_blockchain_address'
block_chain = BlockChain(blockchain_address=my_blockchain_address)
utils.pprint(block_chain.chain)
block_chain.add_transaction('A','B', 1.0)
block_chain.mining()
utils.pprint(block_chain.chain)
block_chain.add_transaction('C','D', 2.0)
block_chain.add_transaction('X','Y', 3.0)
block_chain.mining()
utils.pprint(block_chain.chain)
実行結果は以下です。
========================= Chain 0 =========================
nonce 0
previous_hash 44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a
timestamp 1631014110.742186
transactions
*************************
INFO:__main__:{'action': 'mining', 'status': 'success'}
========================= Chain 0 =========================
nonce 0
previous_hash 44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a
timestamp 1631014110.742186
transactions
========================= Chain 1 =========================
nonce 1782
previous_hash 71da251581a63fdaeebb54c3382597f638ac9fa7d4e9056df8a511154867316c
timestamp 1631014110.828654
transactions
----------------------------------------
recipient_blockchain_address B
sender_blockchain_address A
value 1.0
----------------------------------------
recipient_blockchain_address my_blockchain_address
sender_blockchain_address THE BLOCKCHAIN
value 1.0
*************************
INFO:__main__:{'action': 'mining', 'status': 'success'}
========================= Chain 0 =========================
nonce 0
previous_hash 44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a
timestamp 1631014110.742186
transactions
========================= Chain 1 =========================
nonce 1782
previous_hash 71da251581a63fdaeebb54c3382597f638ac9fa7d4e9056df8a511154867316c
timestamp 1631014110.828654
transactions
----------------------------------------
recipient_blockchain_address B
sender_blockchain_address A
value 1.0
----------------------------------------
recipient_blockchain_address my_blockchain_address
sender_blockchain_address THE BLOCKCHAIN
value 1.0
========================= Chain 2 =========================
nonce 1733
previous_hash d69587bae0fc98da848ce135ff7918b2abc698f0f0f0a6f156de57d5d6c4429c
timestamp 1631014111.0091379
transactions
----------------------------------------
recipient_blockchain_address D
sender_blockchain_address C
value 2.0
----------------------------------------
recipient_blockchain_address Y
sender_blockchain_address X
value 3.0
----------------------------------------
recipient_blockchain_address my_blockchain_address
sender_blockchain_address THE BLOCKCHAIN
value 1.0
*************************
コメント