學(xué)習(xí)區(qū)塊鏈的最好方法是構(gòu)建一個(gè)(下)

2 評論 3585 瀏覽 12 收藏 19 分鐘

深入理解區(qū)塊鏈最好的方式莫過于親手搭建一個(gè),在這個(gè)過程中理解它背后的邏輯和原理。

接上一篇《學(xué)習(xí)區(qū)塊鏈的最好方法是構(gòu)建一個(gè)(上)

第三步:與我們的區(qū)塊鏈交互

你可以使用普通的cURL或Postman工具,通過網(wǎng)絡(luò)與我們的API進(jìn)行交互。

啟動(dòng)服務(wù)器:

1.? ??$?python?blockchain.py

2.? ? ?*?Running?on?http://127.0.0.1:5000/?(Press?CTRL+C?to?quit)

讓我們嘗試通過向http://localhost:5000/mine發(fā)出GET請求來挖掘一個(gè)區(qū)塊:

UsingPostman to make a GET?request

讓我們通過向http://localhost:5000/transactions/new? 發(fā)出一個(gè)POST請求來創(chuàng)建一個(gè)新的交易,這個(gè)交易包含了交易結(jié)構(gòu)的主體:

UsingPostman to make a POST?request

如果你不使用 Postman 工具,同樣可以使用cURL這個(gè)工具來實(shí)現(xiàn)同樣的目的:

1.?????????????$?curl?-X?POST?-H?“Content-Type:?application/json”?-d?‘{

2.??????????????“sender”:?“d4ee26eee15148ee92c6cd394edd974e”,

3.??????????????“recipient”:?“someone-other-address”,

4.??????????????“amount”:?5

5.?????????????}’?“http://localhost:5000/transactions/new”

重啟了我的服務(wù)器,并挖掘了兩個(gè)區(qū)塊,總共給出了3個(gè)區(qū)塊。讓我們通過請求http://localhost:5000/chain檢查整個(gè)鏈:

1.?????????????{

2.???????????????“chain”:?[

3.?????????????????{

4.???????????????????“index”:?1,

5.???????????????????“previous_hash”:?1,

6.???????????????????“proof”:?100,

7.???????????????????“timestamp”:?1506280650.770839,

8.???????????????????“transactions”:?[]

9.?????????????????},

10.??????????????{

11.?????????????????“index”:?2,

12.????????????????“previous_hash”:?“c099bc…bfb7”,

13.????????????????“proof”:?35293,

14.????????????????“timestamp”:?1506280664.717925,

15.????????????????“transactions”:?[

16.??????????????????{

17.????????????????????“amount”:?1,

18.????????????????????“recipient”:?“8bbcb347e0634905b0cac7955bae152b”,

19.????????????????????“sender”:?“0”

20.??????????????????}

21.????????????????]

22.??????????????},

23.??????????????{

24.????????????????“index”:?3,

25.????????????????“previous_hash”:?“eff91a…10f2”,

26.????????????????“proof”:?35089,

27.????????????????“timestamp”:?1506280666.1086972,

28.????????????????“transactions”:?[

29.??????????????????{

30.????????????????????“amount”:?1,

31.????????????????????“recipient”:?“8bbcb347e0634905b0cac7955bae152b”,

32.????????????????????“sender”:?“0”

33.??????????????????}

34.????????????????]

35.??????????????}

36.????????????],

37.????????????“length”:?3

38.??????????}

第四步:共識(shí)

這非???。我們有一個(gè)基本的 Blockchain 接受交易,它允許我們挖掘新的區(qū)塊。但 Blockchain 的關(guān)鍵在于,它們應(yīng)該是分布式的。如果它們是分布式的,我們?nèi)绾未_保它們都在一條鏈?這被稱為共識(shí)的問題,如果我們想要在我們的網(wǎng)絡(luò)中有多個(gè)節(jié)點(diǎn),我們就必須實(shí)現(xiàn)一個(gè)共識(shí)的算法。

注冊新節(jié)點(diǎn)

在實(shí)現(xiàn)共識(shí)算法之前,我們需要一種方法讓節(jié)點(diǎn)知道網(wǎng)絡(luò)上的相鄰節(jié)點(diǎn)。我們網(wǎng)絡(luò)上的每個(gè)節(jié)點(diǎn)都應(yīng)該保留網(wǎng)絡(luò)上其他節(jié)點(diǎn)的注冊表。因此,我們需要更多的端點(diǎn):

1.?/nodes/register?以url的形式接受新的節(jié)點(diǎn)列表。

2.??/nodes/resolve?? 來實(shí)現(xiàn)我們的共識(shí)算法,它可以解決任何沖突——以確保一個(gè)節(jié)點(diǎn)擁有正確的鏈。

我們需要修改 Blockchain 的構(gòu)造函數(shù),并提供注冊節(jié)點(diǎn)的方法:

1.?????????????…

2.?????????????from?urllib.parse?import?urlparse

3.?????????????…

4.

5.

6.?????????????class?Blockchain(object):

7.?????????????????def?__init__(self):

8.?????????????????????…

9.?????????????????????self.nodes?=?set()

10.??????????????????…

11.

12.??????????????def?register_node(self,?address):

13.??????????????????“””

14.??????????????????Add?a?new?node?to?the?list?of?nodes

15.

16.??????????????????:param?address:?<str>?Address?of?node.?Eg.?‘http://192.168.0.5:5000’

17.??????????????????:return:?None

18.??????????????????“””

19.

20.??????????????????parsed_url?=?urlparse(address)

21.??????????????????self.nodes.add(parsed_url.netloc)

Amethod for adding neighbouring nodes to our Network

使用set()來保存節(jié)點(diǎn)列表。這是確保新節(jié)點(diǎn)的添加具有冪等性的廉價(jià)方式,這意味著無論我們添加多少次特定節(jié)點(diǎn),它都只會(huì)出現(xiàn)一次。

實(shí)現(xiàn)算法的共識(shí)

如前所述,當(dāng)一個(gè)節(jié)點(diǎn)與另一個(gè)節(jié)點(diǎn)具有不同鏈時(shí)就有了沖突。為了解決這個(gè)問題,我們制定一條規(guī)則:最長的并且有效的鏈才是權(quán)威的。換句話說,網(wǎng)絡(luò)上最長的鏈?zhǔn)鞘聦?shí)上的鏈。利用該算法,我們在網(wǎng)絡(luò)節(jié)點(diǎn)之間達(dá)成了一致。

1.?????????????…

2.?????????????import?requests

3.

4.

5.?????????????class?Blockchain(object)

6.?????????????????…

7.

8.?????????????????def?valid_chain(self,?chain):

9.?????????????????????“””

10.??????????????????Determine?if?a?given?blockchain?is?valid

11.

12.??????????????????:param?chain:?<list>?A?blockchain

13.??????????????????:return:?<bool>?True?if?valid,?False?if?not

14.??????????????????“””

15.

16.??????????????????last_block?=?chain[0]

17.??????????????????current_index?=?1

18.

19.??????????????????while?current_index?<?len(chain):

20.??????????????????????block?=?chain[current_index]

21.??????????????????????print(f'{last_block}’)

22.??????????????????????print(f'{block}’)

23.??????????????????????print(“\n———–\n”)

24.??????????????????????#?Check?that?the?hash?of?the?block?is?correct

25.??????????????????????if?block[‘previous_hash’]?!=?self.hash(last_block):

26.??????????????????????????return?False

27.

28.??????????????????????#?Check?that?the?Proof?of?Work?is?correct

29.??????????????????????if?not?self.valid_proof(last_block[‘proof’],?block[‘proof’]):

30.??????????????????????????return?False

31.

32.??????????????????????last_block?=?block

33.??????????????????????current_index?+=?1

34.

35.??????????????????return?True

36.

37.??????????????def?resolve_conflicts(self):

38.??????????????????“””

39.??????????????????This?is?our?Consensus?Algorithm,?it?resolves?conflicts

40.??????????????????by?replacing?our?chain?with?the?longest?one?in?the?network.

41.

42.??????????????????:return:?<bool>?True?if?our?chain?was?replaced,?False?if?not

43.??????????????????“””

44.

45.??????????????????neighbours?=?self.nodes

46.??????????????????new_chain?=?None

47.

48.??????????????????#?We’re?only?looking?for?chains?longer?than?ours

49.??????????????????max_length?=?len(self.chain)

50.

51.??????????????????#?Grab?and?verify?the?chains?from?all?the?nodes?in?our?network

52.??????????????????for?node?in?neighbours:

53.??????????????????????response?=?requests.get(f’http://{node}/chain’)

54.

55.??????????????????????if?response.status_code?==?200:

56.??????????????????????????length?=?response.json()[‘length’]

57.??????????????????????????chain?=?response.json()[‘chain’]

58.

59.??????????????????????????#?Check?if?the?length?is?longer?and?the?chain?is?valid

60.??????????????????????????if?length?>?max_length?and?self.valid_chain(chain):

61.??????????????????????????????max_length?=?length

62.??????????????????????????????new_chain?=?chain

63.

64.??????????????????#?Replace?our?chain?if?we?discovered?a?new,?valid?chain?longer?than?ours

65.??????????????????if?new_chain:

66.??????????????????????self.chain?=?new_chain

67.??????????????????????return?True

68.

69.??????????????????return?False

第一個(gè)方法valid_chain() 負(fù)責(zé)檢查鏈?zhǔn)欠裼行?,通過循環(huán)遍歷每個(gè)區(qū)塊并驗(yàn)證哈希和證明。

resolve_conflicts() 是這么一個(gè)方法:它遍歷我們所有的鄰近節(jié)點(diǎn),下載它們的鏈并使用上面的方法驗(yàn)證它們。如果一個(gè)有效的鏈被發(fā)現(xiàn),它的長度大于我們的,我們就替換掉我們當(dāng)前所使用的鏈。

讓我們將兩個(gè)端點(diǎn)注冊到API中,一個(gè)用于添加相鄰節(jié)點(diǎn),另一個(gè)用于解決沖突:

1.?????????????@app.route(‘/nodes/register’,?methods=[‘POST’])

2.?????????????def?register_nodes():

3.?????????????????values?=?request.get_json()

4.

5.?????????????????nodes?=?values.get(‘nodes’)

6.?????????????????if?nodes?is?None:

7.?????????????????????return?“Error:?Please?supply?a?valid?list?of?nodes”,?400

8.

9.?????????????????for?node?in?nodes:

10.??????????????????blockchain.register_node(node)

11.

12.??????????????response?=?{

13.??????????????????‘message’:?‘New?nodes?have?been?added’,

14.??????????????????‘total_nodes’:?list(blockchain.nodes),

15.??????????????}

16.??????????????return?jsonify(response),?201

17.

18.

19.??????????@app.route(‘/nodes/resolve’,?methods=[‘GET’])

20.??????????def?consensus():

21.??????????????replaced?=?blockchain.resolve_conflicts()

22.

23.??????????????if?replaced:

24.??????????????????response?=?{

25.??????????????????????‘message’:?‘Our?chain?was?replaced’,

26.??????????????????????‘new_chain’:?blockchain.chain

27.??????????????????}

28.??????????????else:

29.??????????????????response?=?{

30.??????????????????????‘message’:?‘Our?chain?is?authoritative’,

31.??????????????????????‘chain’:?blockchain.chain

32.??????????????????}

33.

34.??????????????return?jsonify(response),?200

此時(shí),你可以使用不同的機(jī)器,并在網(wǎng)絡(luò)上創(chuàng)建不同的節(jié)點(diǎn)?;蛘咴谕慌_(tái)機(jī)器上使用不同的端口來啟動(dòng)進(jìn)程。我在我的機(jī)器上的另一個(gè)端口上啟動(dòng)了另一個(gè)節(jié)點(diǎn),并將它注冊到我當(dāng)前的節(jié)點(diǎn)上。因此,我有兩個(gè)節(jié)點(diǎn):? http://localhost:5000? 和 http://localhost:5001? 。

Registeringa new?Node

然后我在節(jié)點(diǎn)2上挖掘了一些新的區(qū)塊,以確保鏈更長。之后,我在節(jié)點(diǎn)1上調(diào)用 GET /nodes/resolve? ,在節(jié)點(diǎn)1上的鏈被共識(shí)算法所取代:

ConsensusAlgorithm at?Work

去找?guī)讉€(gè)朋友測試一下你的Blockchain吧。

我希望這能激勵(lì)你去創(chuàng)造一些新的東西。我對加密貨幣感到興奮,因?yàn)槲蚁嘈艆^(qū)塊鏈會(huì)迅速改變我們對經(jīng)濟(jì)、政府和記錄保存的看法。

風(fēng)險(xiǎn)警示:藍(lán)狐所有文章都不構(gòu)成投資推薦,投資有風(fēng)險(xiǎn),建議對項(xiàng)目進(jìn)行深入考察,慎重做好自己的投資決策。

相關(guān)閱讀

學(xué)習(xí)區(qū)塊鏈的最好方法是構(gòu)建一個(gè)(上)

原文作者:Danielvan Flymen

原文地址:hackernoon.com

譯者:由藍(lán)狐筆記社群“iGreenMind”翻譯

本文由 @藍(lán)狐筆記社群“iGreenMind” 翻譯發(fā)布于人人都是產(chǎn)品經(jīng)理。未經(jīng)許可,禁止轉(zhuǎn)載。

題圖來自 Pexels,基于 CC0 協(xié)議

更多精彩內(nèi)容,請關(guān)注人人都是產(chǎn)品經(jīng)理微信公眾號(hào)或下載App
評論
評論請登錄
  1. 很不錯(cuò),我一個(gè)開發(fā)的看了都覺得蠻清楚的

    來自廣東 回復(fù)