Block Chain Python

【Python】ブロックチェーンの実装方法_5 マイニングの実装

Block Chain

どうも、月見(@Suzuka14144156)です。

私は、ブロックチェーンに関する研究をしており、本ブログでは仮想通貨/暗号資産の情報を整理して発信しています。

今回は、Pythonでブロックチェーンを実際に実装していきたいと思います。

参考にした講座は以下のUdemyの講座です。

現役シリコンバレーエンジニアが教えるPythonで始めるスクラッチからのブロックチェーン開発入門
Facebookの仮想通貨LibraによりAmazon、Microsfot、IBMなどがブロックチェーン事業に参入し、その技術が再び脚光を浴びています。IoT、医療、不動産の分野でも期待される次世代の技術を学びましょう。

こちらの講座は、Pythonでスクラッチでブロックチェーンを実装するというものです。

Pythonの中級者以上の向けの講座となっています。

ブロックチェーンだけでなく、クラスを使ったコーディングを覚えたい方にもオススメの講座だと思います。

前回までの私の記事は、こちらです。

今回は、前回からの続きですので、お読みでない方は、ぜひ参考にしてみてください。

今回は、マイニングの実装です。

マイニングとは?

  • 対象期間に発生したすべての取引のデータの整合性を取りながら正確に記録する作業
  • マイニングの対価として、暗号資産を得ることができる

マイニングを行ったものに対し、ブロックチェーンから仮想通貨が送られる仕組みを実装します。

マイニングの実際の動作としては、それまでの取引情報をトランザクションに格納し、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の順序を整列かさせるための関数です。

詳細は、以下の記事を参考にしてみてください。

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
*************************

コメント

タイトルとURLをコピーしました