找回密码
 立即注册

扫一扫,登录网站

首页 百科 查看内容
  • 2157
  • 0
  • 分享到

【编程技术】构建Blockchain的代码

2020-4-1 08:49

构建Blockchain

打开你喜欢的文本编辑器或IDE,我比较喜欢使用 PyCharm。然后创建一个名为blockchain.py的新文件。只使用这一个文件,但是如果搞丢了此文件,你可以一直引用源代码:https://github.com/dvf/blockchain

(1)区块链蓝图

我们将创建一个区块链 类,它的构造函数会创建一个初始空列表用于存储区块链,另一个用于存储交易。这是我们创建的区块链class 的源码:

1.             class Blockchain(object):

2.                 def __init__(self):

3.                     self.chain = []

4.                     self.current_transactions = []

5.

6.                 def new_block(self):

7.                     # Creates a new Block and adds it to the chain

8.                     pass

9.

10.              def new_transaction(self):

11.                   # Adds a new transaction to the list of transactions

12.                  pass

13.

14.              @staticmethod

15.              def hash(block):

16.                  # Hashes a Block

17.                  pass

18.

19.              @property

20.              def last_block(self):

21.                  # Returns the last Block in the chain

22.                  pass

Blueprint of our Blockchain Class

区块链 class 负责管理链。它将存储交易,并有一些辅助方法来为链添加新的区块。让我们开始充实一些方法。

一个区块会是什么样子?

每个块都有一个索引、一个时间戳(Unix时间)、一个交易列表、一个证明和前一个块的哈希值。

区块源码例子:

1.             block = {

2.                 ‘index’: 1,

3.                 ‘timestamp’: 1506057125.900785,

4.                 ‘transactions’: [

5.                     {

6.                         ‘sender’: “8527147fe1f5426f9dd545de4b27ee00”,

7.                         ‘recipient’: “a77f5cdfa2934df3954a5c7c7da5df1f”,

8.                         ‘amount’: 5,

9.                     }

10.              ],

11.               ‘proof’: 324984774000,

12.              ‘previous_hash’: “2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824”

13.          }

链的概念应该很明显:每个新块都包含在其内部的前一个块的哈希。这点是至关重要的,因为它使 Blockchain 不可篡改:如果攻击者破坏了链中较早的区块,那么随后所有的块都将包含不正确的哈希值。

请花一些时间好好去理解它——这是区块链设计的的核心理念。

(2)在区块中添加交易

我们需要一种将交易添加到块中的方法。new_transaction() 方法可以实现这个功能,而且非常简单:

1.             class Blockchain(object):

2.                 …

3.

4.                 def new_transaction(self, sender, recipient, amount):

5.                     “””

6.                     Creates a new transaction to go into the next mined Block

7.

8.                     :param sender:  Address of the Sender

9.                     :param recipient:  Address of the Recipient

10.                  :param amount:  Amount

11.                   :return:  The index of the Block that will hold this transaction

12.                  “””

13.

14.                  self.current_transactions.append({

15.                      ‘sender’: sender,

16.                      ‘recipient’: recipient,

17.                      ‘amount’: amount,

18.                  })

19.

20.                  return self.last_block[‘index’] + 1

在new_transaction()将交易添加到列表之后,它将返回这个交易会被添加到下一个块的索引。这对稍后提交交易的用户有用。

(3)创建新区块

当 区块链被实例化时,需要将它与一个没有前辈的创世区块一起连接起来。我们还需要向我们的创世区块添加一个“证明”,这是挖矿的结果。

除了在我们的构造函数中创建创世区块之外,我们还将为new_block()、new_transaction()和hash()添加方法:

1.             import hashlib

2.             import json

3.             from time import time

4.

5.

6.             class Blockchain(object):

7.                 def __init__(self):

8.                     self.current_transactions = []

9.                     self.chain = []

10.

11.                   # Create the genesis block

12.                  self.new_block(previous_hash=1, proof=100)

13.

14.              def new_block(self, proof, previous_hash=None):

15.                  “””

16.                  Create a new Block in the Blockchain

17.

18.                  :param proof:  The proof given by the Proof of Work algorithm

19.                  :param previous_hash: (Optional)  Hash of previous Block

20.                  :return:  New Block

21.                  “””

22.

23.                  block = {

24.                      ‘index’: len(self.chain) + 1,

25.                      ‘timestamp’: time(),

26.                      ‘transactions’: self.current_transactions,

27.                      ‘proof’: proof,

28.                      ‘previous_hash’: previous_hash or self.hash(self.chain[-1]),

29.                  }

30.

31.                  # Reset the current list of transactions

32.                  self.current_transactions = []

33.

34.                  self.chain.append(block)

35.                  return block

36.

37.              def new_transaction(self, sender, recipient, amount):

38.                  “””

39.                  Creates a new transaction to go into the next mined Block

40.

41.                  :param sender:  Address of the Sender

42.                  :param recipient:  Address of the Recipient

43.                  :param amount:  Amount

44.                  :return:  The index of the Block that will hold this transaction

45.                  “””

46.                  self.current_transactions.append({

47.                      ‘sender’: sender,

48.                      ‘recipient’: recipient,

49.                      ‘amount’: amount,

50.                  })

51.

52.                  return self.last_block[‘index’] + 1

53.

54.              @property

55.              def last_block(self):

56.                  return self.chain[-1]

57.

58.              @staticmethod

59.              def hash(block):

60.                  “””

61.                  Creates a SHA-256 hash of a Block

62.

63.                  :param block:  Block

64.                  :return: 

65.                  “””

66.

67.                  # We must make sure that the Dictionary is Ordered, or we’ll have inconsistent hashes

68.                  block_string = json.dumps(block, sort_keys=True).encode()

69.                  return hashlib.sha256(block_string).hexdigest()

70.

至此,我们几乎完成了 Blockchain 的代码化表现。但新的区块是如何被创建、挖掘的?

(4)理解PoW工作量证明

工作量证明,也就是新的区块如何在 Blockchain 上被创建或挖掘出来。它的目标是发现一个解决问题的数字,这个数字一定很难找到,但却很容易被验证——在网络上的任何人都可以通过计算来验证,这是工作证明PoW背后的核心思想。

我们来看一个非常简单的例子:我们想找到这样一个数值,将整数x与另一个数值y的乘积进行hash运算,使得运算的结果是一串字符串的结尾必须是数字0 。用数学表达式表示出来就是:

hash(x * y) = ac23dc…0

我们假定x = 5。在Python中实现,代码如下:

1.             from hashlib import sha256

2.             x = 5

3.             y = 0  # We don’t know what y should be yet…

4.             while sha256(f'{x*y}’.encode()).hexdigest()[-1] != “0”:

5.                 y += 1

6.             print(f’The solution is y = {y}’)

这里的解是y = 21。因为,生成的hash值是以0结尾的:

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

比特币中,工作量证明被称为Hashcash 。它和上面举出的简单例子基本没有太大区别。这是为了创建一个新的区块,矿工们竞相解决问题的算法。一般来说,难度取决于字符串中搜索的字符数。

矿工会因为在一个交易中找到了那个难题的解,而获得系统给出的激励:该网络的一定量的数字货币。该网络能够很容易地验证他们的解是否正确。

(5)实现基本的工作量证明

为区块链实现一个类似的算法,规则与上面类似:找到一个数字p,当与上一个区块的解进行哈希运算时,产生一个前4位都是0的哈希值。

为了调整算法的难度,我们可以修改前几位零的个数。但4个0就足够了。你将发现,添加一个前导零就会对找到解所需的时间造成很大的不同。

1.             import hashlib

2.             import json

3.

4.             from time import time

5.             from uuid import uuid4

6.

7.

8.             class Blockchain(object):

9.                 …

10.

11.               def proof_of_work(self, last_proof):

12.                  “””

13.                  Simple Proof of Work Algorithm:

14.                   – Find a number p’ such that hash(pp’) contains leading 4 zeroes, where p is the previous p’

15.                   – p is the previous proof, and p’ is the new proof

16.

17.                  :param last_proof: 

18.                  :return: 

19.                  “””

20.

21.                  proof = 0

22.                  while self.valid_proof(last_proof, proof) is False:

23.                      proof += 1

24.

25.                  return proof

26.

27.              @staticmethod

28.              def valid_proof(last_proof, proof):

29.                  “””

30.                  Validates the Proof: Does hash(last_proof, proof) contain 4 leading zeroes?

31.

32.                  :param last_proof:  Previous Proof

33.                  :param proof:  Current Proof

34.                  :return:  True if correct, False if not.

35.                  “””

36.

37.                  guess = f'{last_proof}{proof}’.encode()

38.                  guess_hash = hashlib.sha256(guess).hexdigest()

39.                  return guess_hash[:4] == “0000”

我们的类接近完成,我们已经准备好使用HTTP请求开始与它交互。

版权申明:本内容来自于互联网,属第三方汇集推荐平台。本文的版权归原作者所有,文章言论不代表链门户的观点,链门户不承担任何法律责任。如有侵权请联系QQ:3341927519进行反馈。
相关新闻
发表评论

请先 注册/登录 后参与评论

    回顶部