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

构建Blockchain

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

(1)区块链蓝图

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

1.classBlockchain(object):

2.def__init__(self):

3.self.chain=[]

4.self.current_transactions=[]

5.

6.defnew_block(self):

7.#CreatesanewBlockandaddsittothechain

8.pass

9.

10.defnew_transaction(self):

11.#Addsanewtransactiontothelistoftransactions

12.pass

13.

14.@staticmethod

15.defhash(block):

16.#HashesaBlock

17.pass

18.

19.@property

20.deflast_block(self):

21.#ReturnsthelastBlockinthechain

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.classBlockchain(object):

2.…

3.

4.defnew_transaction(self,sender,recipient,amount):

5.“””

6.CreatesanewtransactiontogointothenextminedBlock

7.

8.:paramsender:AddressoftheSender

9.:paramrecipient:AddressoftheRecipient

10.:paramamount:Amount

11.:return:TheindexoftheBlockthatwillholdthistransaction

12.“””

13.

14.self.current_transactions.append({

15.‘sender’:sender,

16.‘recipient’:recipient,

17.‘amount’:amount,

18.})

19.

20.returnself.last_block[‘index’]+1

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

(3)创建新区块

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

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

1.importhashlib

2.importjson

3.fromtimeimporttime

4.

5.

6.classBlockchain(object):

7.def__init__(self):

8.self.current_transactions=[]

9.self.chain=[]

10.

11.#Createthegenesisblock

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

13.

14.defnew_block(self,proof,previous_hash=None):

15.“””

16.CreateanewBlockintheBlockchain

17.

18.:paramproof:TheproofgivenbytheProofofWorkalgorithm

19.:paramprevious_hash:(Optional)HashofpreviousBlock

20.:return:NewBlock

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_hashorself.hash(self.chain[-1]),

29.}

30.

31.#Resetthecurrentlistoftransactions

32.self.current_transactions=[]

33.

34.self.chain.append(block)

35.returnblock

36.

37.defnew_transaction(self,sender,recipient,amount):

38.“””

39.CreatesanewtransactiontogointothenextminedBlock

40.

41.:paramsender:AddressoftheSender

42.:paramrecipient:AddressoftheRecipient

43.:paramamount:Amount

44.:return:TheindexoftheBlockthatwillholdthistransaction

45.“””

46.self.current_transactions.append({

47.‘sender’:sender,

48.‘recipient’:recipient,

49.‘amount’:amount,

50.})

51.

52.returnself.last_block[‘index’]+1

53.

54.@property

55.deflast_block(self):

56.returnself.chain[-1]

57.

58.@staticmethod

59.defhash(block):

60.“””

61.CreatesaSHA-256hashofaBlock

62.

63.:paramblock:Block

64.:return:

65.“””

66.

67.#WemustmakesurethattheDictionaryisOrdered,orwe’llhaveinconsistenthashes

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

69.returnhashlib.sha256(block_string).hexdigest()

70.

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

(4)理解PoW工作量证明

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

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

hash(x * y) = ac23dc…0

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

1.fromhashlibimportsha256

2.x=5

3.y=0#Wedon’tknowwhatyshouldbeyet…

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

5.y+=1

6.print(f’Thesolutionisy={y}’)

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

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

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

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

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

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

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

1.importhashlib

2.importjson

3.

4.fromtimeimporttime

5.fromuuidimportuuid4

6.

7.

8.classBlockchain(object):

9.…

10.

11.defproof_of_work(self,last_proof):

12.“””

13.SimpleProofofWorkAlgorithm:

14.–Findanumberp’suchthathash(pp’)containsleading4zeroes,wherepisthepreviousp’

15.–pisthepreviousproof,andp’isthenewproof

16.

17.:paramlast_proof:

18.:return:

19.“””

20.

21.proof=0

22.whileself.valid_proof(last_proof,proof)isFalse:

23.proof+=1

24.

25.returnproof

26.

27.@staticmethod

28.defvalid_proof(last_proof,proof):

29.“””

30.ValidatestheProof:Doeshash(last_proof,proof)contain4leadingzeroes?

31.

32.:paramlast_proof:PreviousProof

33.:paramproof:CurrentProof

34.:return:Trueifcorrect,Falseifnot.

35.“””

36.

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

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

39.returnguess_hash[:4]==“0000”

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

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

扫一扫手机访问

发表评论