python 区块链学习(一) 单链结构实现

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Clannad_niu/article/details/88060320

最近在纠结以后的研究方向,就先看了看云链。即一种云计算+区块链+物联网设备的架构模式。虽然还是雨里雾里,还是决定先把区块链的编程落实一下。

0x00 系统环境

本次使用的为Python3.6.5 需要用到的库包括hashlib,flask(0.12.2),time

0x01 区块链结构

这个部分看了一些的资料,慢慢理清了结构。所谓区块链就是一条链(chain),在python里用一个很长的链表list表示。列表里每一项分别为一个交易记录(transactions)。而每个交易记录里又包括这个交易的各种信息:交易的标号(index),交易创建的时间(timestamp),交易内容(transactions),工作证明/挖矿(proof),前一个块的哈希值(previous_hash)。再其中,交易内容又包括:接收者(recepient),发送者(sender),交易金额(amount)。这样看起来太复杂了,用一个图来呈现一下吧。

0x02 区块链逻辑

 整个区块链根据结构可以大致分为几个模块:

1.区块链的初始化     2.新块(block)的建立      3.新交易的建立(transactions)   4.工作证明算法

①  首先是区块链的建立,之前介绍了区块链在python中就是一个很长的列表,其中存放了一个一个的节点(block)。

初始化区块链很简单,就是申请一个新的列表。

class Blockchain(object):

    def __init__(self):
        self.chain = []

②  有了链以后我们就可以添加节点(block)了。区块链的每个节点是用来记录每次的交易记录的,其中包括了节点序号、时间等参数。在python中节点用一个字典表示,分别记录各个参数。

class Blockchain(object):

    def __init__(self):
        self.chain = []
        self.current_transactions = []

        self.new_block(previous_hash=1, proof=100)   # 创建初始区块

    def new_block(self, proof, previous_hash=None):
        block = {
            'index': len(self.chain) + 1,            # 序号
            'timestamp': time(),
            'transactions': self.current_transactions,
            'proof': proof,                            # 工作证明(挖矿)
            'previous_hash': previous_hash or self.hash(self.chain[-1]),  # 前一个哈希
        }

        self.current_transactions = []

        self.chain.append(block)
        return block

这里注意,创建了新的节点,就要清空当前的交易记录,以方便记录下一个节点的交易记录。这个current_transactions也是一个列表,用来记录当前节点的交易记录。接下来详细介绍。

③  交易记录是一个列表,里面存放一个个的字典,来存放当前块的每笔交易。每个块可以存放多个交易记录。接下来为创建新记录的函数 以及计算哈希值的函数。

扫描二维码关注公众号,回复: 5397714 查看本文章
    def new_transaction(self,recepient,sender,amount):     # 创建新的交易
        self.current_transactions.append({
            'sender':sender,            # 接收者
            'recepient':recepient,      # 发送者
            'amount':amount,            # 金额
        })

        return self.last_block['index'] + 1
    
    @staticmethod
    def hash(block):
        block_string = json.dumps(block, sort_keys=True).encode()
        return hashlib.sha256(block_string).hexdigest()

    @property                                  # 直接获取return的值
    def last_block(self):
        return self.chain[-1]

④ 最后是工作证明,也被称作为挖矿。

使用工作量证明(PoW)算法,来证明是如何在区块链上创建或挖掘新的区块。PoW 的目标是计算出一个符合特定条件的数字,这个数字对于所有人而言必须在计算上非常困难,但易于验证。这是工作证明背后的核心思想。

我们将看到一个简单的例子帮助你理解:

假设一个整数 x 乘以另一个整数 y 的积的 Hash 值必须以 0 结尾,即 hash(x * y) = ac23dc...0。设 x = 5,求 y ?用 Python 实现:

from hashlib import sha256
x = 5
y = 0  # We don't know what y should be yet...
while sha256(f'{x*y}'.encode()).hexdigest()[-1] != "0":
    y += 1
print(f'The solution is y = {y}')

结果是: y = 21。因为,生成的 Hash 值结尾必须为 0。

hash(5 * 21) = 1253e9373e...5e3600155e860

在比特币中,工作量证明算法被称为 Hashcash ,它和上面的问题很相似,只不过计算难度非常大。这就是矿工们为了争夺创建区块的权利而争相计算的问题。 通常,计算难度与目标字符串需要满足的特定字符的数量成正比,矿工算出结果后,就会获得一定数量的比特币奖励(通过交易)。

验证结果,当然非常容易。

让我们来实现一个相似 PoW 算法。规则类似上面的例子:

找到一个数字 P ,使得它与前一个区块的 proof 拼接成的字符串的 Hash 值以 4 个零开头。

    def proof_of_work(self, last_proof):
        proof = 0

        while self.valid_proof(proof, last_proof) is False:
            proof += 1

        return proof

    @staticmethod
    def valid_proof(proof, last_proof):
        guess = f'{last_proof}{proof}'.encode()
        guess_hash = hashlib.sha256(guess).hexdigest()

        return guess_hash[:4] == "0000"

0x03 区块链实验

我们采用python的flask框架,将我们写好的区块链放在服务器上运行。先附上代码

def main():
    app = Flask(__name__)
    node_identifier = str(uuid4()).replace('-', '')
    blockchain = Blockchain()

    @app.route('/mine', methods=['GET'])
    def mine():
        last_block = blockchain.last_block
        last_proof = last_block['proof']
        proof = blockchain.proof_of_work(last_proof)

        blockchain.new_transaction(
            sender = '0',
            recepient = node_identifier,
            amount = 1,
        )

        last_hash = blockchain.hash(last_block)
        block = blockchain.new_block(proof, last_hash)

        response = {
            'message':'New Blcok Forged',
            'index': block['index'],
            'transactions': block['transactions'],
            'proof': block['proof'],
            'previous_hash': block['previous_hash'],
        }

        return jsonify(response), 200


    @app.route('/transactions/new', methods=['POST'])
    def new_transaction():
        values = request.get_json()
        required = ['sender','recepient','amount']

        if not all(k in values for k in required):
            return 'Missing values', 400

        index = blockchain.new_transaction(values['recepient'], values['sender'], values['amount'])

        response = {'message':f'transactions have been added to {index}'}

        return jsonify(response), 201

    @app.route('/chain', methods=['GET'])
    def full_chain():
        response = {
            'chain': blockchain.chain,
            'length': len(blockchain.chain),
        }

        return jsonify(response), 200
       # return f'<h1>{response}</h1>'

    app.run(host = '0.0.0.0', port=5000)

其中,通过访问 http://localhost:5000/mine 新建一个区块的页面,通过请求,创建一个新的区块,其中交易金额为1,即通过挖矿,我们找到了一个新的区块,系统(sender=0)奖励给我们(recepient=node_identifier)一个币。这就是整个挖矿的逻辑实现。如下

然后,http://ocalhost:5000/transactions/new 我们可以添加一笔交易记录。

最后,http://ocalhost:5000/chain 我们可以请求到整个链。

随着创建的节点的增多,我们查看到的链就越长。

关于单条连的学习就到此为止,由于区块链是在整个网络上 各个设备之间都存在的架构。接下来将进入到多台设备的学习中。

猜你喜欢

转载自blog.csdn.net/Clannad_niu/article/details/88060320