IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 区块链 -> 通过创建一条链来学习区块链 (1) -> 正文阅读

[区块链]通过创建一条链来学习区块链 (1)

通过创建区块链来学习区块链(1)

主要内容:

  1. Block的数据结构
  2. 挖矿的过程
  3. 工作量证明机制
  4. 工作量证明的简单实现
  5. 建立一条简单的测试链

环境:

  • python 3.7

区块链本质上是一个共享数据库,存储于其中的数据或信息,具有如下特点:

  • 数据仅可通过共识算法以块的形式增加,不可修改或删除,以防止篡改。
  • 每个区块至少会包含一个块生成时间和出块签名。
  • 所有的交易数据都会被双方签名,以防止抵赖。
  • 传统区块链中,新增区块中储存上一个区块的hash,并通过此hash与上一个区块相连。

区块(Block)长什么样

Block 包含下面几个要素:

  • index : 索引
  • timestamp :时间戳
  • transactions : 交易列表
  • proof : 证明(工作量证明)通过工作量证明算法计算
  • previous_hash :上一个区块的哈希值,保证了区块链的不变性
block = {
    'index': 1,
    'timestamp': 1626857298.6391933,
    'transactions': [
        {
            'sender': "147FA8527",
            'recipient': "DA5DF1FD8",
            'amount': 50,
        }
    ],
    'proof': 32740,
    'previous_hash': "06e825e27e52f558e92f7be2f679caf101fbfe227e9cd8d80845029911a0f2d4"
}

class Blockchain

创建一个Blockchain类用来初始化区块链实例。

class Blockchain :

  • 属性:
    • chain : 列表记录Block
    • transaction : 列表记录交易
  • 方法:
    • new_block() : 创建新的区块(Block)并加入链中(chain)
    • new_transaction() : 添加新的交易(transaction)到交易记录中,并返回下一个区块的索引
    • hash() : 生成区块的哈希值
    • last_block() : 返回区块链中的最后一个块

方法的具体实现:

class Blockchain(object):
    def __init__(self):
        self.chain = []
        self.current_transactions = []
        # 初始化实例时,同时也创建一个头节点
        self.new_block(previous_hash = 666, proof = 888)

    def new_block(self, previous_hash, proof):
        # 创建一个新的block并添加到chain中
        """
        previous_hash : <int>/<str> 前一个block的哈希值
        proof :<int> 工作量证明
        return -> <dict> New Block
        """
        block = {}
        block['index'] = len(self.chain) + 1
        block['timestamp'] = time()
        block['transactions'] = self.current_transactions
        block['proof'] = proof
        block['previous_hash'] = previous_hash or self.hash(self.chain[-1])
        self.chain.append(block)
        ## clean current_transactions
        self.current_transactions = []
        return block
        

    def new_transaction(self, sender, recipient, amount):
        # 添加新的transaction到交易列表中
        """
        sender : <str> sender的地址
        recipient : <str> recipient的地址
        amount : <int> 数量
        return -> <int> 索引,是当前block的后续block的索引
        """
        transaction = {}
        transaction['sender'] = sender
        transaction['recipient'] = recipient
        transaction['amount'] = amount
        self.current_transactions.append(transaction)
        return self.last_block['index'] + 1
        
    @staticmethod
    def hash(block):
        # 生成block的哈希值
        """
        block : <dict> block
        return -> <str> 哈希值
        """
        block_string = json.dumps(block, sort_keys=True).encode()
        hash_val = hashlib.sha256(block_string).hexdigest()
        return hash_val
    
    @property
    def last_block(self):
        # 返回chain中的最后一个block
        return self.chain[-1]

? ??Blockchain类已经实现了创建区块链的大部分功能,但是还差一个很重要的功能,那就是工作量计算和验证。从new_block()可以看出,每创建一个新的区块除了要记录一个不定长的交易列表外,还要提供一个工作量证明。了解工作量证明之前先简单说一下挖矿。

矿是怎么挖的

???挖矿就是创建新的区块并添加到链上的一个过程,每当一个矿工成功创建一个区块就会获得一些加密货币作为奖励。但是在整个网络中同时有成千上万甚至几十万的矿工在挖矿,奖励有限,给谁?为了公平起见,采用了一种工作量证明机制,每个矿工在创建新区块的时候,要提供工作量证明,工作量被认可,矿工创建的区块才会被认可,并获得奖励。同时会立刻向全网广播该区块。其他矿工在收到新区块后,会对新区块进行验证,如果有效,就把它添加到区块链的尾部。在本轮工作量证明的竞争中,这个矿工胜出,而其他矿工都失败了。失败的矿工会抛弃自己当前正在计算还没有算完的区块,转而开始计算下一个区块,进行下一轮工作量证明的竞争。

工作量怎么证明的

工作量证明的本质就是计算,通过计算证明矿工的工作量,工作量证明有两个特点:

  1. 计算过程十分复杂
  2. 工作量的验证过程简单

? ??哈希算法常被用来进行工作量证明计算,矿工就是通过不断的尝试哈希计算,直到找到了一个满足要求的哈希值,此时就算是挖矿成功了。具体的工作量证明不同的区块链略有不同,但本质都是进行哈希计算。

下面通过一个简单的例子来说明一下:

? ??假设:当前网络中对创建新区块的要求是:哈希值的首位必须为0。为了尝试不同的哈希值,在挖矿过程中,我们采用一个变量 P P P,跟前一个区块一起进行哈希计算(为了简单起见,我们只用上一个区块中的工作量证明参与哈希计算),直到得到特定的哈希值,此时那个 P P P就可以作为矿工的工作量证明,否则不停的尝试新的 P P P。验证的方法就是,将矿工提供工作量证明 P P P跟前一个区块的工作量证明组合在一起进行哈希计算,检验哈希值是否满足要求。

举个例子,当前链中最后一个Block的工作量证明 proof = 888,下一个区块的工作量证明过程如下:

from hashlib import sha256


prev_proof = 888
new_proof = 0    # ? P
count = 0        # 记录hash的次数
while sha256(f'{prev_proof}{new_proof}'.encode()).hexdigest()[0] != "0":  # 哈希值的首字符为0
    new_proof = new_proof + 2
    count += 1
print("count : %d, new_proof : %d"%(count, new_proof))
count : 13, new_proof : 26

经过13次的计算,就找到的满足的哈希值和新的工作量证明,下面验证工作量是否有效:

new_proof = 26

sha256(f'{prev_proof}{new_proof}'.encode()).hexdigest()
>>>'06e825e27e52f558e92f7be2f679caf101fbfe227e9cd8d80845029911a0f2d4'

经过验证,工作量有效。下面继续模拟上面的过程,假设当前的要求是前两位哈希值为00:

prev_proof = 26
new_proof = 0    # ? P
count = 0        # 记录hash的次数
while sha256(f'{prev_proof}{new_proof}'.encode()).hexdigest()[:2] != "00":
    new_proof = new_proof + 2
    count += 1
print("count : %d, new_proof : %d"%(count, new_proof))
count : 25, new_proof : 50

前三位哈希值为000:

prev_proof = 50
new_proof = 0    # ? P
count = 0        # 记录hash的次数
while sha256(f'{prev_proof}{new_proof}'.encode()).hexdigest()[:3] != "000":
    new_proof = new_proof + 2
    count += 1
print("count : %d, new_proof : %d"%(count, new_proof))
count : 1266, new_proof : 2532

前四位哈希值为0000:

prev_proof = 2532
new_proof = 0    # ? P
count = 0        # 记录hash的次数
while sha256(f'{prev_proof}{new_proof}'.encode()).hexdigest()[:4] != "0000":
    new_proof = new_proof + 2
    count += 1
print("count : %d, new_proof : %d"%(count, new_proof))
count : 6280, new_proof : 12560

前五位哈希值为00000

prev_proof = 12560
new_proof = 0    # ? P
count = 0        # 记录hash的次数
while sha256(f'{prev_proof}{new_proof}'.encode()).hexdigest()[:5] != "00000":
    new_proof = new_proof + 2
    count += 1
print("count : %d, new_proof : %d"%(count, new_proof))
count : 356128, new_proof : 712256

前六位哈希值为000000:

prev_proof = 712256
new_proof = 0    # ? P
count = 0        # 记录hash的次数
while sha256(f'{prev_proof}{new_proof}'.encode()).hexdigest()[:6] != "000000":
    new_proof = new_proof + 2
    count += 1
print("count : %d, new_proof : %d"%(count, new_proof))
count : 1552855, new_proof : 3105710

在这里插入图片描述

???从上面的模拟结果可以发现,随着网络对创建新区块的哈希值要求的变化,矿工要进行哈希计算的次数也在迅速增加,这意味着挖矿的成本也在增加。实际挖矿中,这个挖矿的难度,即哈希值前几位为0的个数会动态的调整,来保证新区块生成的效率。全网算力减少(矿工减少),难度值就会减少,反之算力增加,挖矿难度也随之增加。

工作量证明实现和验证

class Blockchain(object):
    def __init__(self): ...
        
    def new_block(self, previous_hash, proof): ...
        
    def new_transaction(self, sender, recipient, amount): ...
        
    @staticmethod
    def hash(block):...
    
    @property
    def last_block(self): ...
    
    def proof_of_work(self, last_proof):
        """
        POW : hash(pp')
        p : previous_proof, p': new_proof
        last_proof: <int> 上一个区块中的proof
        return -> <int> new_proof 满足哈希条件的工作量证明
        """
        proof = 0
        while self.valid_proof(last_proof, proof) is False:
            proof += 1
        return proof

    @staticmethod
    def valid_proof(last_proof, proof):
        """
        验证POW,hash(pp')是否满足条件0000
        """
        guess = f'{last_proof}{proof}'.encode()
        hash_val = hashlib.sha256(guess).hexdigest()
        return hash_val[:4] == "0000"

创建一条测试链

test_chain = Blockchain()
# 链中的第一个block
test_chain.chain
[{'index': 1,
  'timestamp': 1626857298.6391933,
  'transactions': [],
  'proof': 888,
  'previous_hash': 666}]
# 记录网络中一段时间里发生的交易
test_chain.new_transaction("APPLES123","BANANA234", 111)
test_chain.new_transaction("JDI83NG0C","BANANA234", 123)
test_chain.new_transaction("APPLES123","BANANA234", 345)
test_chain.new_transaction("JDI83NG0C","BANANA234", 666)

工作量证明

# 当前链中最后一个block的工作量证明
prev_proof = test_chain.last_block['proof']
# 工作量证明的计算,返回验证通过的工作量证明
new_proof = test_chain.proof_of_work(prev_proof)

创建新的区块

# 计算链中最后一个block的哈希值
prev_hash = test_chain.hash(test_chain.last_block)
# 创建新区块并加入链中
test_chain.new_block(prev_hash, new_proof)
{'index': 2,
 'timestamp': 1626857779.4037974,
 'transactions': [{'sender': 'APPLES123',
   'recipient': 'BANANA234',
   'amount': 111},
  {'sender': 'JDI83NG0C', 'recipient': 'BANANA234', 'amount': 123},
  {'sender': 'APPLES123', 'recipient': 'BANANA234', 'amount': 345},
  {'sender': 'JDI83NG0C', 'recipient': 'BANANA234', 'amount': 666}],
 'proof': 124179,
 'previous_hash': '3c339eac60c9a4f1ee84d42a5c70bea4d510a57a80d833a2cbfc849768ec0964'}
继续添加新的区块
# 记录交易
test_chain.new_transaction("TNCSSS256","JWDLH021", 111)
# 工作量证明
prev_proof = test_chain.last_block['proof']
new_proof = test_chain.proof_of_work(prev_proof)
# 创建新区块
prev_hash = test_chain.hash(test_chain.last_block)
test_chain.new_block(prev_hash, new_proof)
{'index': 3,
 'timestamp': 1626858267.9535542,
 'transactions': [{'sender': 'TNCSSS256',
   'recipient': 'JWDLH021',
   'amount': 111}],
 'proof': 39221,
 'previous_hash': '0d411a993912d9e20e1ccdc670ab1b8ae2062973c5c9eddca8c47a4ad3d3c9b0'}
test_chain.chain
[{'index': 1,
  'timestamp': 1626857298.6391933,
  'transactions': [],
  'proof': 888,
  'previous_hash': 666},
 {'index': 2,
  'timestamp': 1626857779.4037974,
  'transactions': [{'sender': 'APPLES123',
    'recipient': 'BANANA234',
    'amount': 111},
   {'sender': 'JDI83NG0C', 'recipient': 'BANANA234', 'amount': 123},
   {'sender': 'APPLES123', 'recipient': 'BANANA234', 'amount': 345},
   {'sender': 'JDI83NG0C', 'recipient': 'BANANA234', 'amount': 666}],
  'proof': 124179,
  'previous_hash': '3c339eac60c9a4f1ee84d42a5c70bea4d510a57a80d833a2cbfc849768ec0964'},
 {'index': 3,
  'timestamp': 1626858267.9535542,
  'transactions': [{'sender': 'TNCSSS256',
    'recipient': 'JWDLH021',
    'amount': 111}],
  'proof': 39221,
  'previous_hash': '0d411a993912d9e20e1ccdc670ab1b8ae2062973c5c9eddca8c47a4ad3d3c9b0'}]

下一步:

  • 创建一个web服务实现矿工节点跟区块链间的通信
  • 模拟矿工跟区块链间的通信过程
  区块链 最新文章
盘点具备盈利潜力的几大加密板块,以及潜在
阅读笔记|让区块空间成为商品,打造Web3云
区块链1.0-比特币的数据结构
Team Finance被黑分析|黑客自建Token“瞒天
区块链≠绿色?波卡或成 Web3“生态环保”标
期货从入门到高深之手动交易系列D1课
以太坊基础---区块验证
进入以太坊合并的五个数字
经典同态加密算法Paillier解读 - 原理、实现
IPFS/Filecoin学习知识科普(四)
上一篇文章      下一篇文章      查看所有文章
加:2021-07-23 10:50:27  更:2021-07-23 10:51:10 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/27 9:52:04-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计