python实现简单的区块链

运用datetime和hashlib模拟实现区块链
区块函数
包含区块高度标识:blockNo
交易数据:data
nonce值
preious_hash:上一个区块哈希
timestamp:当前时间
在这里插入图片描述
链函数
在这里插入图片描述
分别包括三个方法,添加块的方法、挖矿功能、以及打包交易
添加块的方法:
在这里插入图片描述
挖矿功能(采用的是工作量证明共识机制)
在这里插入图片描述
打包交易:模拟简单的打包交易的功能,哈希加密了最后的返回值
在这里插入图片描述
最后运行部分设置了20个区块上链
在这里插入图片描述
运行结果:
在这里插入图片描述
全部代码:

import datetime
import hashlib
import random


class Block:
    blockNo = 0
    data = None
    next = None
    hash = None
    nonce = 0
    previous_hash = 0x0
    timestamp = datetime.datetime.now()

    def __init__(self, data):
        self.data = data

    # 添加哈希函数,计算区块的哈希值--将nonce、data、前一个 hash、timestamp和块号放入一个字符串并通过 SHA-256 函数运行
    def hash(self):
        h = hashlib.sha256()
        h.update(
            str(self.nonce).encode('utf-8') +
            str(self.data).encode('utf-8') +
            str(self.previous_hash).encode('utf-8') +
            str(self.timestamp).encode('utf-8') +
            str(self.blockNo).encode('utf-8')
        )
        return h.hexdigest()

    def __str__(self):
        return "Block Hash: " + str(self.hash()) + "nBlockNo: " + str(self.blockNo) + "nBlock Data: " + str(
            self.data) + "nHashes: " + str(self.nonce) + "n---------"


# 区块链类
class Blockchain:
    # 难度
    diff = 20
    # 最大随机数--设置为 2 的 32 次方,即 32 位数字中可以存储的最大数。随机数必须小于要接受的目标数
    maxNonce = 2 ** 32
    # 目标数--设置为 2 的 256 次方减去难度。在这种情况下,难度为 20
    target = 2 ** (256 - diff)
    # 区块链中的第一个块是创世块
    block = Block("Genesis")
    dummy = head = block

    # 添加块
    def add(self, block):
        # 前一个哈希设置为等于当前位于列表顶部的块
        block.previous_hash = self.block.hash()
        block.blockNo = self.block.blockNo + 1

        self.block.next = block
        self.block = self.block.next

    # 添加了一个挖矿功能。我使用了工作量证明共识机制
    def mine(self, block):
        # 首先设置一些猜测准则(范围),从 0 到最大随机数
        for n in range(self.maxNonce):
            if int(block.hash(), 16) <= self.target:
                self.add(block)
                print(block)
                break
            else:
                block.nonce += 1

    # 打包交易
    def pack(self):
        data = ""
        transaction = {
            1: "A转账B 1bit n",
            2: "A转账B 2bit n",
            3: "A转账B 3bit n",
            4: "A转账B 4bit n",
            5: "A转账B 5bit n",
            6: "A转账B 6bit n",
            7: "A转账B 7bit n",
            8: "A转账B 8bit n",
            9: "A转账B 9bit n",
            10: "A转账B 10bit n",
            11: "A转账B 11bit n",
            12: "A转账B 12bit n",
            13: "A转账B 13bit n",
            14: "A转账B 14bit n",
            15: "A转账B 15bit n",
            16: "A转账B 16bit n",
            17: "A转账B 17bit n",
            18: "A转账B 18bit n",
            19: "A转账B 19bit n",
            20: "A转账B 20bit n",
            21: "A转账B 21bit n",
            22: "A转账B 22bit n",
            23: "A转账B 23bit n",
            24: "A转账B 24bit n",
            25: "A转账B 25bit n",
            26: "A转账B 26bit n",
            27: "A转账B 27bit n",
            28: "A转账B 28bit n",
            29: "A转账B 29bit n",
            30: "A转账B 30bit n",
        }
        for i in range(1, 6):
            index = random.randint(1, 30)
            data += transaction[index]
        hash_object = hashlib.sha256()
        hash_object.update(data.encode('utf-8'))
        hash_value = hash_object.hexdigest()
        return hash_value


if __name__ == '__main__':
    start = datetime.datetime.now()
    blockchain = Blockchain()
    num_of_blocks_to_add = 20
    # 它计算 num_of_blocks_to_add 个随机块
    for n in range(num_of_blocks_to_add):
        data = blockchain.pack()
        blockchain.mine(Block("Block " + str(n + 1) + data))
    while blockchain.head is not None:
        print(blockchain.head)
        blockchain.head = blockchain.head.next
    end = datetime.datetime.now()
    print('Running time: %s Seconds' % (end - start))