全部版块 我的主页
论坛 金融投资论坛 六区 金融实务版 比特币、区块链与元宇宙
1777 2
2018-01-30
边构建区块链边学习(Jupyter notebook)
  • 构建区块链的同时进行学习|编程|使用在POSTD中发布的解释和代码逐步进行测试。

  • 直接由Jupyter实施,因为觉得在Flask中的实现很多余。

  • 阅读文本是假定您对于块链本身的机制已经有所理解。






代码的实现1.创建一个区块链类


In [1]:
复制代码

2.挖矿代码


In [2]:
复制代码





3.添加示例并返回整个链


In [3]:
复制代码




尝试移动块链

使用pprint使显示更容易看到。




In [4]:
复制代码

自身节点的标识符如下。




In [5]:
复制代码
Out[5]:
'7d10057a10364156aa9ac7b92ce3c34e'





一旦实例化,将创建第一个区块

  • index:索引为1
  • previous_hash:初始的hash值1
  • length:链条的长度显然是1



In [6]:
复制代码

开始创建第一个街区

复制代码

In [7]:
复制代码
复制代码

在交易环节中,只描述了采矿挖掘交易

  • sender:发件人为0
  • recipient:收件人标识符
  • amount:金额是1

记录为交易。 现在我们来看看整个区块链的内容




In [8]:
复制代码
复制代码





作为一个新的交易(交易),有的区块只包含挖掘结果。

我们在这里添加一个新的事务。

  • 添加发件人到'foo'
  • 将收件人设置为'bar'
  • amount 设置为10

并达成交易。




In [9]:
复制代码


此时index(块的索引)是3。 上述交易存储在这个块中。




In [10]:
复制代码
3

此时,从整个链条来看,上面添加的交易还没有在链上注册。




In [11]:
复制代码
复制代码





挖矿并添加一个新的块。


In [12]:
复制代码

创建第3个区块,保存之前创建的事务信息和挖掘信息。




In [13]:

pp.pprint(newblock)
{ 'index': 3,  'message': 'New Block Forged',  'previous_hash': '635b05a6a3d32c78f3d23fa9ab44222616ba073cac93f064fedeafb6684ad645',  'proof': 35089,  'transactions': [ {'amount': 10, 'recipient': 'bar', 'sender': 'foo'},                    { 'amount': 1,                      'recipient': '7d10057a10364156aa9ac7b92ce3c34e',                      'sender': '0'}]}


此时整个链条的状态如下。




In [14]:
pp.pprint(full_chain(b)){ 'chain': [ { 'index': 1,               'previous_hash': 1,               'proof': 100,               'timestamp': 1516245610.8226993,               'transactions': []},             { 'index': 2,               'previous_hash': 'b0879b53a4230c49e23d3c4715034e732bc07ab54f3ba16dbd0fa73860d8faee',               'proof': 35293,               'timestamp': 1516245625.9124067,               'transactions': [ { 'amount': 1,                                   'recipient': '7d10057a10364156aa9ac7b92ce3c34e',                                   'sender': '0'}]},             { 'index': 3,               'previous_hash': '635b05a6a3d32c78f3d23fa9ab44222616ba073cac93f064fedeafb6684ad645',               'proof': 35089,               'timestamp': 1516245688.0261838,               'transactions': [ { 'amount': 10,                                   'recipient': 'bar',                                   'sender': 'foo'},                                 { 'amount': 1,                                   'recipient': '7d10057a10364156aa9ac7b92ce3c34e',                                   'sender': '0'}]}],  'length': 3}



智能合约(分布式)class Blockchain2()类的实现

实现Blcokchain 2类包含共识算法。

另外,节点标识符被保存为一个类成员,并且在挖掘它时被修改为使用它。 (为了能够处理多个节点的块链)

(实际上,定义Node类并将Blockchain 2类作为has-a作为成员似乎更好,但是因为在Blockchain类的原始版本中引入了register_node()或resolve_conflicts()




In [15]:import copyBlockchainNeighbours = {}class Blockchain2(Blockchain):    def __init__(self, node_identifier):        super().__init__()        self.nodes = set()        self.node_identifier = node_identifier            def register_node(self, node_identifier):        """        Add a new node to the list of nodes        :node_identifier: <str> Node identifier of the neighbour node.        :return: None        """        self.nodes.add(node_identifier)    def valid_chain(self, chain):        """        Determine if a given blockchain is valid        :param chain: <list> A blockchain        :return: <bool> True if valid, False if not        """        last_block = chain[0]        current_index = 1        while current_index < len(chain):            block = chain[current_index]#            print(f'{last_block}')#            print(f'{block}')#            print("\n-----------\n")            # Check that the hash of the block is correct            if block['previous_hash'] != self.hash(last_block):                return False            # Check that the Proof of Work is correct            if not self.valid_proof(last_block['proof'], block['proof']):                return False            last_block = block            current_index += 1        return True    def resolve_conflicts(self):        """        This is our Consensus Algorithm, it resolves conflicts        by replacing our chain with the longest one in the network.        :return: <bool> True if our chain was replaced, False if not        """        neighbours = self.nodes        new_chain = None        # We're only looking for chains longer than ours        max_length = len(self.chain)        # Grab and verify the chains from all the nodes in our network        for node in neighbours:            blockchain = BlockchainNeighbours[node]            print('node id: %s, len: %d' % (blockchain.node_identifier, len(blockchain.chain)))            # Check if the length is longer and the chain is valid            if len(blockchain.chain) > max_length and self.valid_chain(blockchain.chain):                max_length = len(blockchain.chain)                new_chain = blockchain        # Replace our chain if we discovered a new, valid chain longer than ours        if new_chain:            print("Replacing `%s' <- `%s'" % (self.node_identifier, new_chain.node_identifier))            self.chain = copy.copy(new_chain.chain)            return True        return False


In [16]:def mine2(blockchain):    # We run the proof of work algorithm to get the next proof...    last_block = blockchain.last_block    last_proof = last_block['proof']    proof = blockchain.proof_of_work(last_proof)    # We must receive a reward for finding the proof.    # The sender is "0" to signify that this node has mined a new coin.    blockchain.new_transaction(        sender="0",        recipient=blockchain.node_identifier,        amount=1,    )    # Forge the new Block by adding it to the chain    previous_hash = blockchain.hash(last_block)    block = blockchain.new_block(proof, previous_hash)    response = {        'message': "New Block Forged",        'index': block['index'],        'transactions': block['transactions'],        'proof': block['proof'],        'previous_hash': block['previous_hash'],    }    return response


创建多个节点的块链



为三个节点创建一个块链,并注册为一个相邻节点。




In [35]:# 为节点标识符为“foo”,“bar”,“buz”的三个节点创建一个块链。foo = Blockchain2('foo')bar = Blockchain2('bar')buz = Blockchain2('buz')# 注册在相邻节点的列表中BlockchainNeighbours['foo'] = fooBlockchainNeighbours['bar'] = barBlockchainNeighbours['buz'] = buz# 'bar','buz'注册为'foo'节点邻居foo.register_node('bar')foo.register_node('buz')# 为“bar”,“buz”节点注册邻居bar.register_node('foo')bar.register_node('buz')buz.register_node('foo')buz.register_node('bar')



在初始状态下,所有节点的链路长度为1。




In [18]:
print('foo: %d, bar: %d, buz: %d' %(len(foo.chain), len(bar.chain), len(buz.chain)))

foo: 1, bar: 1, buz: 1





即使你试图在初始状态下解决冲突,也没有链节点长于foo节点,所以foo节点链不会改变。




In [19]:
foo.resolve_conflicts()



node id: buz, len: 1node id: bar, len: 1

Out[19]:
False





在一些节点上伸展块

接下来,在bar节点上挖掘并添加一个块。




In [20]:
pp.pprint(mine2(bar))
{ 'index': 2,  'message': 'New Block Forged',  'previous_hash': 'c97740db684709fd7455f413f0ad84f435236e1534caaea7cf744921b59fab3b',  'proof': 35293,  'transactions': [{'amount': 1, 'recipient': 'bar', 'sender': '0'}]}




节点的长度只有2




In [21]:
print('foo: %d, bar: %d, buz: %d' %(len(foo.chain), len(bar.chain), len(buz.chain)))



foo: 1, bar: 2, buz: 1




In [22]:
pp.pprint(foo.chain)



[ { 'index': 1,    'previous_hash': 1,    'proof': 100,    'timestamp': 1516245713.7215648,    'transactions': []}]



In [23]:
pp.pprint(bar.chain)[ { 'index': 1,    'previous_hash': 1,    'proof': 100,    'timestamp': 1516245713.7215648,    'transactions': []},  { 'index': 2,    'previous_hash': 'c97740db684709fd7455f413f0ad84f435236e1534caaea7cf744921b59fab3b',    'proof': 35293,    'timestamp': 1516245772.022711,    'transactions': [{'amount': 1, 'recipient': 'bar', 'sender': '0'}]}]



In [24]:
pp.pprint(buz.chain)
[ { 'index': 1,    'previous_hash': 1,    'proof': 100,    'timestamp': 1516245713.7215648,    'transactions': []}]



消除节点之间的冲突

在这种状态下,当试图解决foo节点处的冲突时,foo节点链被(更长的)节点链覆盖。




In [25]:
foo.resolve_conflicts()node id: buz, len: 1node id: bar, len: 2Replacing `foo' <- `bar'
Out[25]:
True





当冲突的解决完成时,foo节点的链长变为2。




In [26]:

print('foo: %d, bar: %d, buz: %d' %(len(foo.chain), len(bar.chain), len(buz.chain)))foo: 2, bar: 2, buz: 1





如果每个节点链的内容不同



接下来,考虑每个节点链的内容不同的情况。

这里我们看到foo节点和buz节点的内容不同的情况。




In [27]:
# buzノードの内容を揃えるbuz.resolve_conflicts()print('foo: %d, bar: %d, buz: %d' %(len(foo.chain), len(bar.chain), len(buz.chain)))
node id: foo, len: 2node id: bar, len: 2Replacing `buz' <- `foo'foo: 2, bar: 2, buz: 2



在这里,在foo节点添加两个块,一个块在buz节点,并且添加具有不同事务的块。




In [28]:
foo.new_transaction('AAA', 'BBB', 123)mine2(foo)foo.new_transaction('CCC', 'DDD', 456)mine2(foo)buz.new_transaction('EEE', 'FFF', 789)mine2(buz)print('foo: %d, bar: %d, buz: %d' %(len(foo.chain), len(bar.chain), len(buz.chain)))foo: 4, bar: 2, buz: 3




此时foo节点和buz节点链的内容如下。 你可以看到内容与中间不同。




In [29]:
pp.pprint(foo.chain)
[ { 'index': 1,    'previous_hash': 1,    'proof': 100,    'timestamp': 1516245713.7215648,    'transactions': []},  { 'index': 2,    'previous_hash': 'c97740db684709fd7455f413f0ad84f435236e1534caaea7cf744921b59fab3b',    'proof': 35293,    'timestamp': 1516245772.022711,    'transactions': [{'amount': 1, 'recipient': 'bar', 'sender': '0'}]},  { 'index': 3,    'previous_hash': '8791fb38c957761c7af4331d65e834691cd7aa46019faaab3d655deae86d3dbb',    'proof': 35089,    'timestamp': 1516245803.1813366,    'transactions': [ {'amount': 123, 'recipient': 'BBB', 'sender': 'AAA'},                      {'amount': 1, 'recipient': 'foo', 'sender': '0'}]},  { 'index': 4,    'previous_hash': '99e21d9dd699d831803a0ea41d08cf9b2cfa642b94d4ee5ba4a38d1773c1c5c3',    'proof': 119678,    'timestamp': 1516245803.3608067,    'transactions': [ {'amount': 456, 'recipient': 'DDD', 'sender': 'CCC'},                      {'amount': 1, 'recipient': 'foo', 'sender': '0'}]}]
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

全部回复
2018-1-31 14:33:23
不太能理解。
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2018-2-2 18:45:26
pudino 发表于 2018-1-31 14:33
不太能理解。
有什么问题吗?
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

相关推荐
栏目导航
热门文章
推荐文章

说点什么

分享

扫码加好友,拉您进群
各岗位、行业、专业交流群