精华内容
下载资源
问答
  • 简单区块链Python实现

    2019-11-04 16:31:39
    什么是区块链 区块链是一种数据结构,也是一个分布式数据库。 从技术上来看:区块是一种记录交易的数据结构,反映了一笔交易的资金流向。系统中已经达成的交易的区块连接在一起形成了一条主链,所有参与计算的节点都...

    什么是区块链

    区块链是一种数据结构,也是一个分布式数据库。

    从技术上来看:区块是一种记录交易的数据结构,反映了一笔交易的资金流向。系统中已经达成的交易的区块连接在一起形成了一条主链,所有参与计算的节点都记录了主链或主链的一部分。
    在这里插入图片描述

    组成

    区块头

    区块头主要包含的三组元数据分别是:(1)用于连接前面的区块、索引自父区块哈希值的数据;(2)挖矿难度、时间戳、Nonce(随机数,用于工作量证明算法的计数器,也可理解为记录解密该区块相关数学题的答案的值);(3)能够总结并快速归纳校验区块中所有交易数据的Merkle(默克尔)树根数据。当然区块头不仅仅包含这些元数据,还有其他比如:版本号、难度值等。
    从这个结构来看,区块链的大部分功能都由区块头实现。

    区块主体

    区块主体所记录的交易信息是区块所承载的任务数据,具体包括交易双方的私钥、交易的数量、电子货币的数字签名等。

    比特币系统大约每10分钟会创建一个区块,这个区块包含了这段时间里全网范围内发生的所有交易。每一个区块都保存了上一个区块的哈希值,使得每个区块都能找到其前一个区块,这样就将这些区块连接起来,形成了一个链式的结构。
    在这里插入图片描述

    区块字段

    • Difficulty 此区块的难度级别
    • ExtraData 与此区块相关的附加数据 在区块链早期使用比较多,现在用的很少
    • gasLimit 当前区块允许使用的最大gas, gas表示一种计算量, 使用的算力单位
    • gasUsed 当前区块已经使用的gas
    • Hash 当前区块的哈希值。如果区块没有被确认,这个字段会是null值
    • LogsBloom 由日志信息组成的一个Bloom过滤器 (数据结构),区块没被确认- 是值为null
    • Miner 取得该区块记账权的矿工
    • mixHash 一个Hash值,当与nonce组合时,证明此区块已经执行了足够的计算
    • nonce 一个Hash值,当与mixHash组合时,证明此区块已经执行了足够的计算
    • Number 当前区块的计数(创世纪块的区块序号为0,对于每个后续区块,区块序号都增加1)
    • parentHash 父区块头的Hash值(这也是使得区块变成区块链的原因)
    • receiptsRoot 包含此区块所列的所有交易收据的树的根节点Hash值
    • Sha3Uncles 数据块的哈希值
    • Size 当前区块的字节大小
    • stateRoot 区块状态树的根哈希
    • Timestamp 区块打包时的unix时间戳
    • totalDifficulty 区块链到当前区块的总难度
    • Transactions 交易的对象
    • transactionsRoot 区块的交易树的根哈希
    • Uncles 叔哈希数组 树区块详见 https://blog.csdn.net/weixin_42874184/article/details/81735695

    在这里插入图片描述

    Python实现

    实现了工作量证明,难度计算,哈希部分

    import hashlib
    import datetime
    import random
     
    class Block:
        def __init__(self, index, transaction, pre_hash, difficulty, nonce):
            self.index = index
            self._timestamp = datetime.datetime.now()
            self._transaction = transaction
            self._pre_hash = pre_hash
            self._nonce = nonce
            self._difficulty = difficulty
            self.hash = self.gen_hash()
     
        @property
        def get_hash(self):
            return self.hash
     
        @property
        def get_index(self):
            return self.index
     
        @property
        def get_transaction(self):
            return self._transaction
     
        @property
        def get_difficulty(self):
            return self._difficulty
     
        @property
        def get_timestamp(self):
            return self._timestamp
     
        @property
        def get_pre_hash(self):
            return self._pre_hash
     
        @property
        def get_nonce(self):
            return self._nonce
     
        def gen_hash(self):
            sha = hashlib.sha256()
            data = str(self.index) + str(self._timestamp) + str(self._transaction) + str(self._pre_hash) + str(self._nonce) + str(self._difficulty)
            sha.update(data.encode("utf8"))
            return sha.hexdigest()
     
     
    class Blockchain:
        def __init__(self, max_blocks):
            self._chain_list = [Block(0, "The First Block", '0', '1', random.randrange(0, 99999))]
            self._previous_block = self._chain_list[0]
            self._current_block = 1
            self.max_blocks = max_blocks
     
        @staticmethod
        def create_next_block(self):
            last_block = self._chain_list[self._current_block - 1]
            last_difficulty = last_block.get_difficulty
            this_index = last_block.index + 1
            this_transaction = "New Block " + str(this_index) + " has been generated successfully."
            nonce = random.randrange(0, 99999)
            this_difficulty = self.proof_of_work(nonce)
            pre_hash = last_block.hash
            self._chain_list.append(Block(this_index, this_transaction, pre_hash, this_difficulty, nonce))
            self._current_block += 1
     
        def last_block(self):
            return self._chain_list[-1]
     
        def proof_of_work(self, nonce):
            proof = 0
            while self.valid_proof(self, proof, nonce) is False:
                proof += 1
            return proof
     
        @staticmethod
        def valid_proof(self, proof, nonce):
            guess = f'{proof}{nonce}'.encode()
            guess_hash = hashlib.sha256(guess).hexdigest()
            pattern = "0000"
            return guess_hash[:len(pattern)] == pattern
     
        def run(self):
            for i in range(self.max_blocks):
                self.create_next_block(self)
     
        def show_block(self, index):
            print("----------------------------------------")
            print("ID: ", self._chain_list[index].get_index)
            print("Time", self._chain_list[index].get_transaction)
            print("Cur Hash", self._chain_list[index].get_hash)
            print("Pre Hash", self._chain_list[index].get_pre_hash)
            print("Difficulty", self._chain_list[index].get_difficulty)
            print("Trans", self._chain_list[index].get_transaction)
            print("Nonce", self._chain_list[index].get_nonce)
            print("----------------------------------------")
     
     
    myBlockChain = Blockchain(100)
    myBlockChain.run()
    for i in range(myBlockChain.max_blocks):
        myBlockChain.show_block(i)
    

    在这里插入图片描述

    参考文献

    https://segmentfault.com/a/1190000014483104
    https://blog.csdn.net/qq874455953/article/details/83718022

    更多内容访问 omegaxyz.com
    网站所有代码采用Apache 2.0授权
    网站文章采用知识共享许可协议BY-NC-SA4.0授权
    © 2020 • OmegaXYZ-版权所有 转载请注明出处

    展开全文
  • Chia是一种从头开始构建的现代加密货币,旨在高效,分散和安全。 chia-blockchain当前版本/主开发部门/ dev Chia是一种从头开始构建的现代加密货币,旨在高效,分散和安全。 这里有一些功能和好处:基于时空共识的...
  • 通过键入python3确保您的默认python版本> = 3.7。 如果您使用的是NAT,则子网外的对等点启动时可能很难到达您。 您可以在路由器上启用或添加NAT(针对IPv4,但不针对IPv6)和防火墙规则,以允许TCP端口8444访问...
  • Python实现的简单BlockChain 这是我在[在Python中构建简单的区块链]中的帖子的源代码。 要求 Python3.5 烧瓶 python请求 贡献 请随时提出拉取请求:)
  • 不到 200 行代码的区块链 Python 实现 一个简单区块链Python 实现。 不到 200 行代码。 描述 Pysimplechain实现几乎完全集中在哈希分类帐功能上。 它不包括任何高级功能,如分布式账本或通过工作证明的共识协议。...
  • 区块链 这是一个Pythonimlementation 制备 安装 安装该项目的依赖项 pipenv install 激活该项目的virtualenv pipenv shell 用法 创建一个钱包 $ python cli.py createwallet Your new address: 17Y288D5DnFwU6cj5...
  • 区块链blockchain_go的python实现
  • QuarkChain区块链协议的Python 实现
  • # 区块链的其他块 last_block 上一个区块 this_index = last_block.index + 1 this_timestamp = datetime.datetime.now() this_data = "taotao coin" + str(this_index) # 模拟交易数据 last_hash = last...
    import hashlib
    import datetime
    
    
    class TTBlockCoin:
        def __init__(self,
                     index,  # 索引
                     timeStamp,  # 时间戳
                     data,  # 交易数据
                     lastHash):  # 上一个块的hash值
            self.index = index
            self.timeStamp = timeStamp
            self.data = data
            self.lastHash = lastHash
            self.selfHash = self.hash_TTBlockCoin()
    
        # 产生加密串,产生一个加密串就是产生一个币
        def hash_TTBlockCoin(self):
            # sha = hashlib.sha256()
            # sha = hashlib.sha512()
            sha = hashlib.md5()
            datastr = str(self.index) + str(self.timeStamp) + str(self.data) + str(self.lastHash)
            sha.update(datastr.encode("utf-8"))
            return sha.hexdigest()
    
    
    def create_first_TTBlock():  # 创造一个创世区块
        return TTBlockCoin(0, datetime.datetime.now(), "TT COIN", "tt001")
    
    
    def create_money_TTBlock(last_block):  # 区块链的其他块  last_block 上一个区块
        this_index = last_block.index + 1
        this_timestamp = datetime.datetime.now()
        this_data = "taotao coin" + str(this_index)  # 模拟交易数据
        last_hash = last_block.selfHash    #lastHash =上一个block的selfHash
        return TTBlockCoin(this_index,
                             this_timestamp,
                             this_data,
                             last_hash)
    
    
    TTBlockCoins = [create_first_TTBlock()]  # 区块链链表
    nums = 100
    head_block = TTBlockCoins[0]
    print("创世区块TT币来啦")
    print(head_block.index, head_block.data, head_block.timeStamp, 
          head_block.lastHash, head_block.selfHash)
    for i in range(nums):
        ttBlock_another = create_money_TTBlock(head_block)  # 根据第一个区块创造下一个区块
        TTBlockCoins.append(ttBlock_another)  # 区块加入链
        head_block = ttBlock_another
        print(ttBlock_another.index, ttBlock_another.data, 
              ttBlock_another.timeStamp, ttBlock_another.lastHash,
              ttBlock_another.selfHash)
    
    
    展开全文
  • 区块链系列·python实现区块链

    千次阅读 2019-07-04 07:00:00
    听说现在会点区块链技术的工资都高破天了,抱着对高工资的幻想,我决定也开始学一学区块链吧。那么我想接触区块链的第一步必须得是去交易平台注册个帐号,然后充点钱买0.000...
        


      听说现在会点区块链技术的工资都高破天了,抱着对高工资的幻想,我决定也开始学一学区块链吧。那么我想接触区块链的第一步必须得是去交易平台注册个帐号,然后充点钱买0.00001个BTC了。(2333,~!~现在我穷得只剩下币了)

      老实说区块链技术还是有点难理解的,为此我搜了搜区块链的实现代码,想着结合代码看获许会简单一点,于是我发现有人用python实现了简单的区块链,于是再原作者基础上,我稍微修改了点内容,在此粘贴一下,以供学习。原项目地址:https://github.com/xilibi2003/blockchain

    从本篇开始,我将继续学习一些区块链的技术以及区块链安全相关的技术,并会总结成系列文章在博客发布,技术有限请多包涵!






    640?wx_fmt=gif更多原创文章,请扫描下方二维码




    640?wx_fmt=jpeg      



    展开全文
  • Python区块链仿真实现教程及源码

    千次阅读 2020-04-02 09:33:12
    区块链或数字货币领域,Python并不是主流的开发语言。但是如果你的目的是研究区块链技术的原理,或者需要在自己的笔记本上仿真一个区块链网络并进行一些研究性的实验,比如完成自己的毕业设计项目或科研课题,那么...

    在区块链或数字货币领域,Python并不是主流的开发语言。但是如果你的目的是研究区块链技术的原理,或者需要在自己的笔记本上仿真一个区块链网络并进行一些研究性的实验,比如完成自己的毕业设计项目或科研课题,那么Python就是合适的。在这个教程里,我们将学习如何使用Python从零开发一个多节点的区块链网络,并基于这个仿真区块链网络,开发一个去中心化的数据分享应用。

    相关教程链接:区块链毕业论文 | 以太坊 | 比特币 | EOS | Tendermint | Hyperledger Fabric | Omni/USDT | Ripple

    本教程中的完整源代码可以在这里下载:https://github.com/ezpod/python-blockchain-sim。如果你需要仿真大规模区块链网络,可以使用这个区块链仿真开发包

    1、Python仿真区块链:用区块分批保存交易

    我们首先要把数据以JSON格式存入区块链。JSON是一种常用的跨语言的数据交换格式,例如一篇博客的JSON表示看起来就像这样:

    { 
      "author": "some_author_name", 
      "content": "Some thoughts that author wants to share", 
      "timestamp": "The time at which the content was created"
    }
    

    在区块链领域,我们经常使用 交易 来代替上面说到的数据。因此,为了避免引起混乱并保持一致,在这个教程里我们将使用 交易 这个术语来表示要存入区块链的数据。

    交易被分批打包进区块,一个区块可以包含一个或多个交易。包含交易的区块会定期生成并加入区块链。因为会有很多区块,所以每个区块都应当有一个唯一的ID。下面是我们的Python仿真区块链的Block类定义代码:

    class Block:
        def __init__(self, index, transactions, timestamp):
            """
            Constructor for the `Block` class.
            :param index: Unique ID of the block.
            :param transactions: List of transactions.
            :param timestamp: Time of generation of the block.
            """
            self.index = index 
            self.transactions = transactions 
            self.timestamp = timestamp
    

    2、Python仿真区块链:为区块添加抗篡改的数字指纹

    区块链的一个特点就是存储在区块中的交易不可篡改,为了实现这个特性,首先需要能够检测出区块数据被篡改。为此目的,我们需要使用密码学中的哈希(Hash)函数。

    哈希函数可以把任意大小的输入数据转换为固定大小的输出数据,也就是数据的哈希,而且不同的输入数据(基本上)会得到不同的输出数据,因此可以使用输出的哈希作为输入数据的标识。一个理想的哈希函数具有如下特点:

    • 应当易于计算
    • 应当是确定性的,对于相同的输入数据总是生成相同的哈希
    • 应当具有均匀随机性,输入数据的一点变化也会导致输出哈希的显著改变

    这样我们就可以保证:

    • 从哈希猜测出输入数据是什么基本是不可能的,唯一的办法是尝试所有可能的组合
    • 如果同时知道输入和输出,那么你可以通过简单地重算来验证哈希是否正确

    显然,从输入数据推导出哈希很简单,然而从哈希推导出输入数据则是几乎不可能的,这一非对称性值就是区块链用来获取期望的抗篡改能力的关键。

    目前有很多流行的哈希函数,下面是一个使用SHA-256哈希函数的Python示例:

    >>> from hashlib import sha256
    >>> data = b"Some variable length data"
    >>> sha256(data).hexdigest()
    'b919fbbcae38e2bdaebb6c04ed4098e5c70563d2dc51e085f784c058ff208516'
    >>> sha256(data).hexdigest() # no matter how many times you run it, the result is going to be the same 256 character string
    'b919fbbcae38e2bdaebb6c04ed4098e5c70563d2dc51e085f784c058ff208516'
    >>>  data = b"Some variable length data2" # Added one character at the end.
    '9fcaab521baf8e83f07512a7de7a0f567f6eef2688e8b9490694ada0a3ddeec8'
    

    注意在上面的示例中,输入数据的一点变化就得到完全不同的哈希!

    在教程的Python仿真区块链项目中,我们将把区块哈希保存为区块的一个字段,用它作为区块数据的数字指纹(Digital Fingerprint),或者说签名(Signature)。

    下面是计算区块哈希的Python实现代码:

    from hashlib import sha256
    import json
    
    def compute_hash(block):
        """
        Returns the hash of the block instance by first converting it
        into JSON string.
        """
        block_string = json.dumps(self.__dict__, sort_keys=True)
        return sha256(block_string.encode()).hexdigest()
    

    注意:在大多数数字加密货币实现中,区块中的每个交易也需要计算哈希并利用一个树形结构(merkle树)来计算一组交易的根哈希。不过这对于区块链来说并不是必需的,因此我们暂时忽略这一特性。

    3、Python仿真区块链:将区块一个个链接起来

    好了,现在我们已经搞定区块类Block的Python实现了,现在来看看如何用Ptyhon实现区块链结构。

    区块链就是区块的集合,我们可以使用Python列表来保存所有的区块。不过这还不够,因为如果有人故意用一个较早的区块替换掉集合中的新区块还会导致数据被篡改。

    我们需要一个办法来保证对较早的区块的修改会导致整条区块链的无效。比特币使用的办法是让后面区块的哈希依赖于前面较早的区块。为将区块链接起来,我们需要在区块结构中增加一个新的字段来保存前一个区块的哈希:previous_hash。

    好了,如果每个区块都通过previous_hash字段链接到前一个区块,那么第一个区块怎么办?在区块链领域,第一个区块被称为创世区块(Genesis Block),可以手工生成创世区块或者使用一些特定的逻辑。现在让我们为Block类添加previous_hash字段并实现区块链结构定义,下面是Blockchain类的
    Python实现代码:

    from hashlib import sha256
    import json
    import time
    
    
    class Block:
        def__init__(self, index, transactions, timestamp, previous_hash):
            """
            Constructor for the `Block` class.
            :param index:         Unique ID of the block.
            :param transactions:  List of transactions.
            :param timestamp:     Time of generation of the block.
            :param previous_hash: Hash of the previous block in the chain which this block is part of.                                        
            """
            self.index = index
            self.transactions = transactions
            self.timestamp = timestamp
            self.previous_hash = previous_hash # Adding the previous hash field
    
        def compute_hash(self):
            """
            Returns the hash of the block instance by first converting it
            into JSON string.
            """
            block_string = json.dumps(self.__dict__, sort_keys=True) # The string equivalent also considers the previous_hash field now
            return sha256(block_string.encode()).hexdigest()
    
    class Blockchain:
    
        def __init__(self):
            """
            Constructor for the `Blockchain` class.
            """
            self.chain = []
            self.create_genesis_block()
    
        def create_genesis_block(self):
            """
            A function to generate genesis block and appends it to
            the chain. The block has index 0, previous_hash as 0, and
            a valid hash.
            """
            genesis_block = Block(0, [], time.time(), "0")
            genesis_block.hash = genesis_block.compute_hash()
            self.chain.append(genesis_block)
    
        @property
        def last_block(self):
            """
            A quick pythonic way to retrieve the most recent block in the chain. Note that
            the chain will always consist of at least one block (i.e., genesis block)
            """
            return self.chain[-1]
    

    现在,如果任何较早的区块被修改,那么:

    • 该较早区块的哈希会变化
    • 这会导致与后面区块的previous_hash字段记录的内容不一致
    • 由于计算区块哈希的输入数据包含了previous_hash字段的内容,因此下一个区块的哈希也会变化

    最终,从被替换掉的区块开始的整条链都失效了,修复这一问题的唯一办法是重算整条链。

    4、Python仿真区块链:实现工作量证明算法

    不过还有一个问题。如果我们修改了之前的区块,如果重算后面的其他区块非常简单的话,那么篡改区块链也不是什么难事了。为了避免这一问题,我们可以利用前面提到的哈希函数的非对称性来加大区块哈希计算工作的难度和随机性。我们要做的是:只接受符合特定约束条件的区块哈希。现在让我们增加一个约束条件,要求区块哈希的开始部分至少有n个0,其中n是一个正整数。

    我们知道,除非改变区块数据的内容,否则区块哈希不会变化,当然我们也不希望修改已有的数据。那么我们该怎么做?很简单!我们再增加一些我们可以随便修改的数据就是了。因此我们需要为Block类增加一个新的字段nonce,我们可以通过改变这个字段的值来得到不同的区块哈希,直到满足指定的约束条件,而这时的nonce值就是我们工作量的证明。

    上面的这一过程就是比特币使用的hashcash算法的简化版本。约束条件中指定的前导0的数量决定了我们的工作量证明算法的难度:前导0的数量越多,就越难找到合适的nonce。

    同时,由于哈希函数的非对称性,工作量证明不容易计算,但是容易进行验证。

    下面是工作量证明算法(PoW:Proof of Work)的Python实现代码:

    class Blockchain:
        # difficulty of PoW algorithm
        difficulty = 2
    
        """
        Previous code contd..
        """
    
        def proof_of_work(self, block):
            """
            Function that tries different values of the nonce to get a hash
            that satisfies our difficulty criteria.
            """
            block.nonce = 0
    
            computed_hash = block.compute_hash()
            while not computed_hash.startswith('0' * Blockchain.difficulty):
                block.nonce += 1
                computed_hash = block.compute_hash()
    
            return computed_hash
    

    需要指出的是,没有简单的逻辑可以快速找到满足约束条件的nonce值,因此只能进行暴力计算。

    5、Python仿真区块链:将区块加入区块链

    要将区块加入区块链,我们首先需要验证:

    • 区块中的数据没有被篡改,所提供的工作量证明是正确的
    • 交易的顺序是正确的,previous_hash字段指向我们链上最新区块的哈希

    现在让我们看一下将区块上链的Python实现代码:

    class Blockchain:
        """
        Previous code contd..
        """
    
        def add_block(self, block, proof):
            """
            A function that adds the block to the chain after verification.
            Verification includes:
            * Checking if the proof is valid.
            * The previous_hash referred in the block and the hash of a latest block
              in the chain match.
            """
            previous_hash = self.last_block.hash
    
            if previous_hash != block.previous_hash:
                return False
    
            if not Blockchain.is_valid_proof(block, proof):
                return False
    
            block.hash = proof
            self.chain.append(block)
            return True
    
        def is_valid_proof(self, block, block_hash):
            """
            Check if block_hash is valid hash of block and satisfies
            the difficulty criteria.
            """
            return (block_hash.startswith('0' * Blockchain.difficulty) and
                    block_hash == block.compute_hash())
    

    6、Python仿真区块链:挖矿

    交易一开始是保存在未确认交易池中的。将未确认交易放入区块并计算工作量证明的过程,就是广为人知的挖矿。一旦找出了满足指定约束条件的nonce,我们就可以说挖出了一个可以上链的区块。

    在大多数数字加密货币中,包括比特币,矿工都会得到加密货币奖励,以回报其为计算工作量证明所投入的算力。下面是我们的挖矿函数的Python实现代码:

    class Blockchain:
    
        def __init__(self):
            self.unconfirmed_transactions = [] # data yet to get into blockchain
            self.chain = []
            self.create_genesis_block()
    
        """
        Previous code contd...
        """
    
        def add_new_transaction(self, transaction):
            self.unconfirmed_transactions.append(transaction)
    
        def mine(self):
            """
            This function serves as an interface to add the pending
            transactions to the blockchain by adding them to the block
            and figuring out proof of work.
            """
            if not self.unconfirmed_transactions:
                return False
    
            last_block = self.last_block
    
            new_block = Block(index=last_block.index + 1,
                              transactions=self.unconfirmed_transactions,
                              timestamp=time.time(),
                              previous_hash=last_block.hash)
    
            proof = self.proof_of_work(new_block)
            self.add_block(new_block, proof)
            self.unconfirmed_transactions = []
            return new_block.index
    

    好了,我们就快要完成这个Python仿真区块链项目了!

    7、Python仿真区块链:为节点添加API接口

    现在该为我们的仿真区块链节点添加API接口了,这样应用程序就可以利用这些API开发具体的应用。我们将使用流行的Python微框架Flask来创建REST API。如果你以前使用过其他web框架,那么下面的代码应当不难理解,如果没有接触过web框架的话也别担心,这里有一个非常棒的Flask教程

    from flask import Flask, request
    import requests
    
    # Initialize flask application
    app =  Flask(__name__)
    
    # Initialize a blockchain object.
    blockchain = Blockchain()
    

    我们需要一个可以提交新交易的访问端节点,这样我们的应用就可以利用这个API来将新数据添加到区块链中。下面是节点的/new_transaction访问端节点的Python实现代码:

    # Flask's way of declaring end-points
    @app.route('/new_transaction', methods=['POST'])
    def new_transaction():
        tx_data = request.get_json()
        required_fields = ["author", "content"]
    
        for field in required_fields:
            if not tx_data.get(field):
                return "Invalid transaction data", 404
    
        tx_data["timestamp"] = time.time()
    
        blockchain.add_new_transaction(tx_data)
    
        return "Success", 201
    

    另一个端节点/chain可以返回区块链的数据。我们的应用将利用这个API来查询要显示的数据。下面是这个端节点的Python实现代码:

    @app.route('/chain', methods=['GET'])
    def get_chain():
        chain_data = []
        for block in blockchain.chain:
            chain_data.append(block.__dict__)
        return json.dumps({"length": len(chain_data),
                           "chain": chain_data})
    

    挖矿很费CPU,因此我们不希望让节点一直挖矿,而是提供一个访问端节点/mine来提供按需挖矿服务。 下面是Python实现代码:

    @app.route('/mine', methods=['GET'])
    def mine_unconfirmed_transactions():
        result = blockchain.mine()
        if not result:
            return "No transactions to mine"
        return "Block #{} is mined.".format(result)
    
    @app.route('/pending_tx')
    def get_pending_tx():
        return json.dumps(blockchain.unconfirmed_transactions)
    

    这些REST访问端节点可以用来操作我们的区块链,比如提交一些交易,然后通过挖矿确认这些交易等等。

    8、Python仿真区块链:实现最长链共识与去中心化计算

    到目前为止,我们用Python从零实现的仿真区块链是运行在一台计算机上的。即使我们已经利用哈希将区块前后链接起来,并应用了工作量证明约束,我们还是不能只信任单一的节点。我们需要实现分布式数据存储,我们需要多个节点来维护区块链。因此,为了从单一节点转向P2P网络,让我们先
    创建一个机制来让网络上的节点彼此了解。

    首先定义一个新的访问端节点/register_node用来在网络中注册新节点。下面是Python实现代码:

    # Contains the host addresses of other participating members of the network
    peers = set()
    
    # Endpoint to add new peers to the network
    @app.route('/register_node', methods=['POST'])
    def register_new_peers():
        # The host address to the peer node 
        node_address = request.get_json()["node_address"]
        if not node_address:
            return "Invalid data", 400
    
        # Add the node to the peer list
        peers.add(node_address)
    
        # Return the blockchain to the newly registered node so that it can sync
        return get_chain()
    
    @app.route('/register_with', methods=['POST'])
    def register_with_existing_node():
        """
        Internally calls the `register_node` endpoint to
        register current node with the remote node specified in the
        request, and sync the blockchain as well with the remote node.
        """
        node_address = request.get_json()["node_address"]
        if not node_address:
            return "Invalid data", 400
    
        data = {"node_address": request.host_url}
        headers = {'Content-Type': "application/json"}
    
        # Make a request to register with remote node and obtain information
        response = requests.post(node_address + "/register_node",
                                 data=json.dumps(data), headers=headers)
    
        if response.status_code == 200:
            global blockchain
            global peers
            # update chain and the peers
            chain_dump = response.json()['chain']
            blockchain = create_chain_from_dump(chain_dump)
            peers.update(response.json()['peers'])
            return "Registration successful", 200
        else:
            # if something goes wrong, pass it on to the API response
            return response.content, response.status_code
    
    
    def create_chain_from_dump(chain_dump):
        blockchain = Blockchain()
        for idx, block_data in enumerate(chain_dump):
            block = Block(block_data["index"],
                          block_data["transactions"],
                          block_data["timestamp"],
                          block_data["previous_hash"])
            proof = block_data['hash']
            if idx > 0:
                added = blockchain.add_block(block, proof)
                if not added:
                    raise Exception("The chain dump is tampered!!")
            else:  # the block is a genesis block, no verification needed
                blockchain.chain.append(block)
        return blockchain
    

    新加入网络的节点可以利用/register_with endpoint端节点调用register_with_existing_node方法进行注册。这有助于解决以下问题:

    • 要求远端节点在其已知邻节点中添加一个新的条目
    • 使用远端节点的数据初始化新节点上的区块链
    • 如果节点中途有下线,而可以重新从网络同步区块链

    然而,当存在多个区块链节点时有一个问题需要解决:不管有意或无意(例如网络延迟),不同节点上的区块链可能彼此不同。在这种情况下,节点之间需要就区块链的版本达成一致,以便维护整个系统的一致性。换句话说,我们需要达成共识。

    当不同节点上的区块链出现分化时,一个简单的共识算法是选择最长有效链。这一方法背后的合理性在于,最长的链包含了最多的已经投入的工作量证明计算。下面是最长链共识算法的Python实现代码:

    class Blockchain
        """
        previous code continued...
        """
        def check_chain_validity(cls, chain):
            """
            A helper method to check if the entire blockchain is valid.            
            """
            result = True
            previous_hash = "0"
    
            # Iterate through every block
            for block in chain:
                block_hash = block.hash
                # remove the hash field to recompute the hash again
                # using `compute_hash` method.
                delattr(block, "hash")
    
                if not cls.is_valid_proof(block, block.hash) or \
                        previous_hash != block.previous_hash:
                    result = False
                    break
    
                block.hash, previous_hash = block_hash, block_hash
    
            return result
    
    def consensus():
        """
        Our simple consensus algorithm. If a longer valid chain is
        found, our chain is replaced with it.
        """
        global blockchain
    
        longest_chain = None
        current_len = len(blockchain.chain)
    
        for node in peers:
            response = requests.get('{}/chain'.format(node))
            length = response.json()['length']
            chain = response.json()['chain']
            if length > current_len and blockchain.check_chain_validity(chain):
                  # Longer valid chain found!
                current_len = length
                longest_chain = chain
    
        if longest_chain:
            blockchain = longest_chain
            return True
    
        return False
    

    现在,我们需要提供一个Python方法让节点在挖出区块时可以将这一消息广播给其他节点,这样我们的仿真区块链网络中的每个参与者都可以更新其本地区块链,然后接着挖下一个区块。收到区块广播的节点很简单就可以验证工作量证明,然后将收到区块加入到自己的本地链上。

    下面是节点的/add_block访问端节点的Python实现代码:

    # endpoint to add a block mined by someone else to
    # the node's chain. The node first verifies the block
    # and then adds it to the chain.
    @app.route('/add_block', methods=['POST'])
    def verify_and_add_block():
        block_data = request.get_json()
        block = Block(block_data["index"],
                      block_data["transactions"],
                      block_data["timestamp"],
                      block_data["previous_hash"])
    
        proof = block_data['hash']
        added = blockchain.add_block(block, proof)
    
        if not added:
            return "The block was discarded by the node", 400
    
        return "Block added to the chain", 201
    
    
    def announce_new_block(block):
        """
        A function to announce to the network once a block has been mined.
        Other blocks can simply verify the proof of work and add it to their
        respective chains.
        """
        for peer in peers:
            url = "{}add_block".format(peer)
            requests.post(url, data=json.dumps(block.__dict__, sort_keys=True))
    

    announce_new_block方法应当在区块被挖出的时候调用,这样其他节点就可以更新自己本地保存的区块链副本:

    @app.route('/mine', methods=['GET'])
    def mine_unconfirmed_transactions():
        result = blockchain.mine()
        if not result:
            return "No transactions to mine"
        else:
            # Making sure we have the longest chain before announcing to the network
            chain_length = len(blockchain.chain)
            consensus()
            if chain_length == len(blockchain.chain):
                # announce the recently mined block to the network
                announce_new_block(blockchain.last_block)
            return "Block #{} is mined.".format(blockchain.last_block.index
    

    9、Python仿真区块链:开发去中心化应用程序

    好了,现在我们的仿真区块链的节点软件已经开发完了。现在需要开发应用程序的用户界面了。我们使用Jinja2模板来渲染网页,并使用一些CSS来让网页看起来美观一些。

    我们的应用需要连接到这个仿真区块链网络中的某个节点以便获取数据或者提交新数据。下面是应用的初始化部分的Python代码:

    import datetime
    import json
    
    import requests
    from flask import render_template, redirect, request
    
    from app import app
    
    # Node in the blockchain network that our application will communicate with
    # to fetch and add data.
    CONNECTED_NODE_ADDRESS = "http://127.0.0.1:8000"
    
    posts = []
    

    fetch_posts方法利用节点的/chain端节点获取数据、解析数据并保存在本地:

    def fetch_posts():
        """
        Function to fetch the chain from a blockchain node, parse the
        data, and store it locally.
        """
        get_chain_address = "{}/chain".format(CONNECTED_NODE_ADDRESS)
        response = requests.get(get_chain_address)
        if response.status_code == 200:
            content = []
            chain = json.loads(response.content)
            for block in chain["chain"]:
                for tx in block["transactions"]:
                    tx["index"] = block["index"]
                    tx["hash"] = block["previous_hash"]
                    content.append(tx)
    
            global posts
            posts = sorted(content,
                           key=lambda k: k['timestamp'],
                           reverse=True)
    

    应用程序使用一个HTML表单来接收用户输入然后利用一个POST请求将交易添加到所连接节点的未确认交易池中。然后交易会被我们的仿真区块链网络确认并最终当刷新网页时被再次读取:

    @app.route('/submit', methods=['POST'])
    def submit_textarea():
        """
        Endpoint to create a new transaction via our application
        """
        post_content = request.form["content"]
        author = request.form["author"]
    
        post_object = {
            'author': author,
            'content': post_content,
        }
    
        # Submit a transaction
        new_tx_address = "{}/new_transaction".format(CONNECTED_NODE_ADDRESS)
    

    10、Python仿真区块链:如何运行应用

    终于完成了!你可以在github上查看这个Python仿真区块链的完整源代码。

    首先克隆项目仓库:

    $ git clone https://github.com/ezpod/python-blockchain-sim.git
    

    安装必要的Python项目依赖:

    $ cd python_blockchain_app
    $ pip install -r requirements.txt
    

    启动我们的仿真区块链节点:

    $ export FLASK_APP=node_server.py
    $ flask run --port 8000
    

    现在我们的一个仿真区块链节点实例已经启动并在8000端口监听。

    开启另一个终端运行我们的去中心化应用:

    $ python run_app.py
    

    现在应用已经启动,可以通过这个网址访问: http://localhost:5000.

    下图展示了如何利用web界面向我们的仿真区块链提交内容:

    在这里插入图片描述

    下图展示了如何利用web界面启动节点挖矿:

    在这里插入图片描述

    下图展示了如何利用web界面重新同步区块链数据:

    在这里插入图片描述

    11、Python仿真区块链:运行多个节点

    要运行包含多个节点的仿真区块链网络,可以使用register_with/端节点在网络中注册新节点。

    下面是一个多节点的示例场景,我们启动了3个仿真节点,分别在8000、8001和8002端口监听:

    # already running
    $ flask run --port 8000 &
    # spinning up new nodes
    $ flask run --port 8001 &
    $ flask run --port 8002 &
    

    可以使用下面的cURL请求注册在8001和8002端口监听的两个新节点:

    $ curl -X POST \
      http://127.0.0.1:8001/register_with \
      -H 'Content-Type: application/json' \
      -d '{"node_address": "http://127.0.0.1:8000"}'
    
    $ curl -X POST \
      http://127.0.0.1:8002/register_with \
      -H 'Content-Type: application/json' \
      -d '{"node_address": "http://127.0.0.1:8000"}'
    

    这样在端口8000监听的节点就可以知道还有8001和8002监听的节点,反之亦然。新加入的节点也会从原来的在网节点同步区块链数据,这样新节点就可以参与后续的挖矿过程了。

    要修改前端应用同步的区块链节点,可以修改views.py文件中的CONNECTED_NODE_ADDRESS字段。

    一旦完成上面的操作,你就可以运行应用(python run_app.py)并通过web界面创建交易了。当你挖矿后,网络中的所有节点都会更新自己的本地区块链。也可以使用cURL或Postman利用/chain端节点查看区块链。例如:

    $ curl -X GET http://localhost:8001/chain
    $ curl -X GET http://localhost:8002/chain
    

    12、Python仿真区块链:如何验证交易

    你可能注意到我们的基于仿真区块链的去中心化应用还有一点瑕疵:任何人在任何时间都可以提交任何内容。解决这一问题的一个办法,就是使用非对称密钥技术创建用户账户。每一个新用户都需要一个公钥(对应账户名)和一个私钥才能在我们的应用中提交数据。私钥用来创建数据的签名,而公钥用来验证数据的签名,下面是其工作机制:

    • 每一个提交的新交易都使用用户的私钥进行签名。这个签名与用户信息一起 添加到交易数据中
    • 在验证阶段,当挖矿时,我们可以使用公钥和签名验证数据中生成的发送方 和签名是否相符,以及验证消息是否被修改。

    13、Python仿真区块链:教程总结

    在这个教程中,我们学习了一个公链的基本概念,并利用Python实现了一个仿真区块链以及基于这个仿真区块链的Flask应用。如果你走完了整个教程,相信应该可以使用Python从零实现一个区块链,并基于这个仿真的区块链开发自己的去中心化应用,或者利用这个仿真区块链网络进行一些研究性的实验。教程中的区块链实现没有比特币或以太坊那么复杂,但相信会有助于理解区块链技术的核心问题和解决思路。


    原文链接:Python仿真区块链 — 汇智网

    展开全文
  • Python实现自己的分布式区块链视频培训教程:区块链技术近非常的火,去中心化,挖矿各种概念层出不穷。本课程的目标便是通过Python区块链技术实现自己的区块链,课程中会讲到Python3实现区块链的数据结构,Python3...
  • 利用PBFT共识算法的区块链python概念验证实现。 此特定实现专为IoT配置更新而设计。 在本地运行 在本地运行容器之前,请将manageChain.py中的'localIP'变量更改为您的本地IP地址。 然后,只需运行“ docker-...
  • python实现区块链

    千次阅读 2020-07-04 11:54:49
    return "区块内容:%s\n哈希值:%s" % (self.transaction, self.hash) 区块链结构: # 区块链结构 class BlockChain: ''' blocks:包含的区块列表 ''' def __init__(self): self.blocks = [] # 添加区块 def add...
  • python实现简单区块链

    2020-10-10 09:41:20
    python实现简单区块链 import hashlib import json from time import time from typing import Any, Dict, List, Optional from urllib.parse import urlparse from uuid import uuid4 import requests from flask ...
  • python实现分布式区块链 import hashlib import json from time import time from urllib.parse import urlparse from uuid import uuid4 import requests from flask import Flask, jsonify, request import math ...
  • 区块链的本质及原理:5分半钟; 区块链Python实现:7分24秒。 两个都是FLV文件。 代码 https://github.com/makelove/Blockchain_Study
  • 3.1 python 实现区块链环境准备 安装 postman 安装 python 创建文件目录 lesson1 安装 pip 命令:pip install pipenv pipenv --python=python 安装 flask 命令 pipenv install flask0.12.2 安装 requests 命令 ...
  • 使用python实现的简单的区块链。 设备登入登出,添加区块,查询等等。 无智能合约等等。
  • 但对于程序员,代码对于加深理解有着非常大的作用,以下代码为python实现的一个区块链货币,用来帮助理解。代码中配有注释,copy下来可以直接run,测试代码在最后。 理解前提:理解区块链的“账本”的比喻,基于...
  • Python作为一种面向对象的解释型计算机程序设计语言,因其具有丰富和强大的库,常被称为“胶水语言”,简单、易上手,是区块链技术爱好者快速学习区块链的首选之一。   本文作者Adil Moujahid 是世界IT服务企业...
  • 比特币的python实现,主要介绍比特币底层技术。如Base58编码、椭圆加密算法、MerkleTree、P2P对等网络、RPC通信、UTXO、虚拟机、DHT、DAG、链上数据的持久化存储等。
  • Simcoin - 使用Docker和Python实现区块链模拟框架
  • 文章目录区块链一、比特币内部结构二、实现的比特币结构三、代码实现1.定义区块的结构2.创世区块构造3.挖矿函数定义4.定义区块链结构四、代码运行 一、比特币内部结构 比特币内部结构有四部分: previous hash: ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 639
精华内容 255
关键字:

区块链python实现

python 订阅