首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

学习区块链的最好方法是构建一个(上)

前言:深入理解区块链最好的方式莫过于亲手搭建一个,在这个过程中理解它背后的逻辑和原理。本文作者是Danielvan Flymen ,文章来源于hackernoon.com,由蓝狐笔记社群“iGreenMind”翻译。

你来这里是因为和我一样,你对加密货币的崛起感到兴奋。你想了解区块链是如何工作的,它们背后的基本技术原理是怎样的。

但了解区块链并不容易,至少对我来说不是很容易的。我喜欢边干边学。它迫使我在代码级别上处理问题,这种方法可以让我坚持学习下去。

记住,区块链是一个不可变的、有顺序的链记录,我们称之为区块。它们可以包含交易、文件或任何你想要的数据。但重要的是它们是用哈希链接在一起。

这个指南最适合的阅读对象的要求是什么?至少你轻松地阅读和编写一些基本的Python,并了解HTTP请求是如何工作的,因为我们将通过HTTP协议与我们的 Blockchain 进行交互。

需要什么工具和环境?确保安装了Python 3.6+(以及 pip ),还需要安装Flask和Requests库:

你还需要一个HTTP客户端,比如Postman或cURL。可用的源代码请点击:https://github.com/dvf/blockchain

第一步:构建Blockchain

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

区块链蓝图

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

1.classBlockchain(object):

2.def__init__(self):

3.self.chain = []

4.self.current_transactions = []

5.

6.defnew_block(self):

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

8.pass

9.

10.defnew_transaction(self):

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

12.pass

13.

14.@staticmethod

15.defhash(block):

16.# Hashes a Block

17.pass

18.

19.@property

20.deflast_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.],

13.}

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

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

在区块中添加交易

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

1.classBlockchain(object):

2....

3.

4.defnew_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.returnself.last_block['index'] + 1

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

创建新区块

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

除了在我们的构造函数中创建创世区块之外,我们还将为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.# Create the genesis block

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

13.

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

29.}

30.

31.# Reset the current list of transactions

32.self.current_transactions = []

33.

34.self.chain.append(block)

35.returnblock

36.

37.defnew_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.returnself.last_block['index'] + 1

53.

54.@property

55.deflast_block(self):

56.returnself.chain[-1]

57.

58.@staticmethod

59.defhash(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.returnhashlib.sha256(block_string).hexdigest()

70.

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

理解PoW工作量证明

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

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

hash(x * y) = ac23dc…0

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

1.fromhashlibimportsha256

2.x = 5

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

4.whilesha256(f''.encode()).hexdigest()[-1] !="0":

5.y += 1

6.print(f'The solution is y = ')

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

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

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

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

实现基本的工作量证明

为区块链实现一个类似的算法,规则与上面类似:找到一个数字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.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.whileself.valid_proof(last_proof, proof)isFalse:

23.proof += 1

24.

25.returnproof

26.

27.@staticmethod

28.defvalid_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''.encode()

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

39.returnguess_hash[:4] =="0000"

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

第二步:将区块链作为API使用起来

使用Python的Flask框架。它是一个微型框架,它可以很容易地将端点映射到Python函数。这让我们使用HTTP请求在web上与 Blockchain 进行交互。

我们将创建三个方法:

/transactions/new 创建一个新的交易到一个区块。

/mine 告诉我们的服务器去挖掘一个新的区块。

/chain 返回完整的 Blockchain 。

设置Flask

我们的“服务器”将在 Blockchain 网络中形成单独节点,创建一些样板代码如下所示:

1.importhashlib

2.importjson

3.fromtextwrapimportdedent

4.fromtimeimporttime

5.fromuuidimportuuid4

6.

7.fromflaskimportFlask

8.

9.

10.classBlockchain(object):

11....

12.

13.

14.# Instantiate our Node

15.app = Flask(__name__)

16.

17.# Generate a globally unique address for this node

18.node_identifier = str(uuid4()).replace('-','')

19.

20.# Instantiate the Blockchain

21.blockchain = Blockchain()

22.

23.

24.@app.route('/mine', methods=['GET'])

25.defmine():

26.return"We'll mine a new Block"

27.

28.@app.route('/transactions/new', methods=['POST'])

29.defnew_transaction():

30.return"We'll add a new transaction"

31.

32.@app.route('/chain', methods=['GET'])

33.deffull_chain():

34.response = {

35.'chain': blockchain.chain,

36.'length': len(blockchain.chain),

37.}

38.returnjsonify(response), 200

39.

40.if__name__ =='__main__':

41.app.run(host='0.0.0.0', port=5000)

关于在上面代码中添加的内容的简要说明如下:

Line 15: 实例化节点。

Line 18: 为我们的节点创建一个随机名称。

Line 21: 实例化我们的Blockchain类。

Line 24–26: 创建/mine 端点,这是一个GET请求。

Line 28–30: 创建 /transactions/new 端点,这是一个POST 请求,因为我们将向它发送数据。

Line 32–38: 创建/chain端点,它返回完整的 Blockchain 。

Line 40–41: 在端口5000上运行服务器。

交易端点

这就是交易请求的样子。这是用户发送给服务器的内容:

1.{

2."sender":"my address",

3."recipient":"someone else's address",

4."amount": 5

5.}

由于已经有了将交易添加到区块的类的方法,其余的都很简单。让我们编写添加交易的函数:

1.importhashlib

2.importjson

3.fromtextwrapimportdedent

4.fromtimeimporttime

5.fromuuidimportuuid4

6.

7.fromflaskimportFlask, jsonify, request

8.

9....

10.

11.@app.route('/transactions/new', methods=['POST'])

12.defnew_transaction():

13.values = request.get_json()

14.

15.# Check that the required fields are in the POST'ed data

16.required = ['sender','recipient','amount']

17.ifnotall(kinvaluesforkinrequired):

18.return'Missing values', 400

19.

20.# Create a new Transaction

21.index = blockchain.new_transaction(values['sender'], values['recipient'], values['amount'])

22.

23.response = {'message': f'Transaction will be added to Block '}

24.returnjsonify(response), 201

Amethod for creating Transactions

挖矿端点

挖矿端点必须做三件事:

1.计算工作量证明。

2.通过增加一笔交易,奖赏给矿工(也就是我们自己)一定量的数字货币。

3.通过将新区块添加到链中来锻造区块。

1.importhashlib

2.importjson

3.

4.fromtimeimporttime

5.fromuuidimportuuid4

6.

7.fromflaskimportFlask, jsonify, request

8.

9....

10.

11.@app.route('/mine', methods=['GET'])

12.defmine():

13.# We run the proof of work algorithm to get the next proof...

14.last_block = blockchain.last_block

15.last_proof = last_block['proof']

16.proof = blockchain.proof_of_work(last_proof)

17.

18.# We must receive a reward for finding the proof.

19.# The sender is "0" to signify that this node has mined a new coin.

20.blockchain.new_transaction(

21.sender="0",

22.recipient=node_identifier,

23.amount=1,

24.)

25.

26.# Forge the new Block by adding it to the chain

27.previous_hash = blockchain.hash(last_block)

28.block = blockchain.new_block(proof, previous_hash)

29.

30.response = {

31.'message':"New Block Forged",

32.'index': block['index'],

33.'transactions': block['transactions'],

34.'proof': block['proof'],

35.'previous_hash': block['previous_hash'],

36.}

37.returnjsonify(response), 200

被挖掘出来的区块的接收者是我们节点的地址。在这里所做的大部分工作只是与Blockchain class中的方法进行交互。在这一点上,我们已经完成了,并且可以开始与我们的 Blockchain 进行交互了。

——未完待续——

风险警示:蓝狐所有文章都不构成投资推荐,投资有风险,建议对项目进行深入考察,慎重做好自己的投资决策。

想要深入了解区块链,长按下面二维码关注“蓝狐笔记”区块链公众号:lanhubiji 或加入知识星球:https://t.zsxq.com/iaQNnIq(6月28日到期,建议6月28号后再加入)

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180605A1WG8300?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券