中文字幕在线观看,亚洲а∨天堂久久精品9966,亚洲成a人片在线观看你懂的,亚洲av成人片无码网站,亚洲国产精品无码久久久五月天

使用 Python 從零開始開發(fā)區(qū)塊鏈應(yīng)用程序

2018-07-20    來(lái)源:編程學(xué)習(xí)網(wǎng)

容器云強(qiáng)勢(shì)上線!快速搭建集群,上萬(wàn)Linux鏡像隨意使用

本教程將向具有任何編程技能水平的 Python 開發(fā)人員介紹區(qū)塊鏈。通過(guò)從零開始實(shí)現(xiàn)一個(gè) 公有區(qū)塊鏈 并構(gòu)建一個(gè)簡(jiǎn)單應(yīng)用程序來(lái)利用它,您將了解區(qū)塊鏈到底是什么。

您將能夠使用 Flask 微框架為區(qū)塊鏈的不同功能創(chuàng)建端點(diǎn),比如添加事務(wù),然后在多個(gè)機(jī)器上運(yùn)行腳本來(lái)創(chuàng)建一個(gè)去中心化網(wǎng)絡(luò)。您還將了解如何構(gòu)建一個(gè)簡(jiǎn)單的用戶界面,以便與區(qū)塊鏈進(jìn)行交互,并存儲(chǔ)任何用例的信息,比如對(duì)等支付、聊天或電子商務(wù)。

Python 是一種容易理解的編程語(yǔ)言,這是我在本教程中選擇它的原因。通過(guò)學(xué)習(xí)本教程,您將實(shí)現(xiàn)一個(gè)公有區(qū)塊鏈并了解它的實(shí)際應(yīng)用。GitHub 上提供了一個(gè)完整的樣本應(yīng)用程序代碼,該應(yīng)用程序完全是用 Python 編寫的。

獲取代碼

主要邏輯包含在 views.py 文件中。讓我們一起分析一下該邏輯,以便真正全面了解區(qū)塊鏈。

前提條件

  • Python 的基礎(chǔ)編程知識(shí)
  • Flask 微框架(用于創(chuàng)建區(qū)塊鏈服務(wù)器的端點(diǎn))

背景

公有區(qū)塊鏈與私有區(qū)塊鏈

公有區(qū)塊鏈網(wǎng)絡(luò) (比如比特幣網(wǎng)絡(luò))完全對(duì)公眾開放,任何人都能加入和參與其中。

另一方面,如果企業(yè)對(duì)事務(wù)的隱私性、安全性和速度有更高的要求,可以選擇采用 私有區(qū)塊鏈網(wǎng)絡(luò) ,參與者需要邀請(qǐng)才能加入該網(wǎng)絡(luò)。了解更多信息。

2008 年,一個(gè)名叫 Satoshi Nakamoto 的人(或者可能是一個(gè)小組)發(fā)表了一篇名為《比特幣:一種對(duì)等電子現(xiàn)金系統(tǒng)》的白皮書。該文章結(jié)合了密碼學(xué)技術(shù)和對(duì)等網(wǎng)絡(luò),不需要依靠中心化權(quán)威機(jī)構(gòu)(比如銀行)就能在人們之間實(shí)現(xiàn)付款。比特幣應(yīng)運(yùn)而生。除了比特幣之外,這篇文章還介紹了一種存儲(chǔ)數(shù)據(jù)的分布式系統(tǒng)(即現(xiàn)在廣為人知的“區(qū)塊鏈”),該系統(tǒng)的適用范圍遠(yuǎn)不只是付款或加密貨幣。

從那時(shí)起,幾乎每個(gè)行業(yè)都對(duì)區(qū)塊鏈產(chǎn)生了濃厚的興趣。無(wú)論是像比特幣這樣的完全數(shù)字化的貨幣、像以太坊這樣的分布式計(jì)算技術(shù),還是像 IBM Blockchain Platform 所基于的Hyperledger Fabric 這樣的開源框架,現(xiàn)在都以區(qū)塊鏈作為其背后的基礎(chǔ)技術(shù)。

進(jìn)一步了解 IBM Blockchain Platform Starter Plan(免費(fèi)使用測(cè)試版。

“區(qū)塊鏈”是什么?

區(qū)塊鏈?zhǔn)且环N存儲(chǔ)數(shù)字?jǐn)?shù)據(jù)的方式。數(shù)據(jù)可以是任何內(nèi)容。對(duì)于比特幣,它是事務(wù)(在帳戶之間轉(zhuǎn)移比特幣),它甚至可以是文件;這都無(wú)關(guān)緊要。數(shù)據(jù)是以區(qū)塊形式進(jìn)行存儲(chǔ)的,區(qū)塊使用哈希值鏈接在一起。因此得名“區(qū)塊鏈”。

區(qū)塊鏈的神奇之處是在其中添加和存儲(chǔ)此類數(shù)據(jù)的方式,該方式造就了一些非常理想的特征:

  • 歷史記錄無(wú)法更改
  • 系統(tǒng)無(wú)法攻破
  • 數(shù)據(jù)的持久保存
  • 沒(méi)有單點(diǎn)故障

那么區(qū)塊鏈如何能夠?qū)崿F(xiàn)這些特征呢?我們將通過(guò)實(shí)現(xiàn)一個(gè)區(qū)塊鏈來(lái)深入剖析它。讓我們開始吧。

關(guān)于該應(yīng)用程序

首先定義一下我們將要構(gòu)建的應(yīng)用程序的用途。我們的目的是構(gòu)建一個(gè)允許用戶共享信息的簡(jiǎn)單網(wǎng)站。因?yàn)閮?nèi)容將存儲(chǔ)在區(qū)塊鏈中,所以它無(wú)法更改且會(huì)永遠(yuǎn)存在。

我們將采用自下而上的實(shí)現(xiàn)方式。首先定義我們將存儲(chǔ)在區(qū)塊鏈中的數(shù)據(jù)的結(jié)構(gòu)。 一篇帖子(任何用戶在我們的應(yīng)用程序上發(fā)布的一條消息)將由 3 個(gè)基本要素來(lái)標(biāo)識(shí):

  1. 內(nèi)容
  2. 作者
  3. 時(shí)間戳

1

將事務(wù)存儲(chǔ)到區(qū)塊中

我們將采用一種廣泛使用的格式來(lái)將數(shù)據(jù)存儲(chǔ)在區(qū)塊鏈中:JSON。以下是一篇存儲(chǔ)在區(qū)塊鏈中的帖子的格式:

{
    "author": "some_author_name", 
    "content": "Some thoughts that author wants to share", 
    "timestamp": "The time at which the content was created"
}

術(shù)語(yǔ)“數(shù)據(jù)”通常在互聯(lián)網(wǎng)上被“事務(wù)”一詞所取代。所以,為了避免混淆并保持一致,我們將使用術(shù)語(yǔ)“事務(wù)”來(lái)表示在我們的示例應(yīng)用程序中發(fā)布的數(shù)據(jù)。

事務(wù)被打包到區(qū)塊中。一個(gè)區(qū)塊可以包含一個(gè)或許多個(gè)事務(wù)。包含事務(wù)的區(qū)塊頻繁地生成并添加到區(qū)塊鏈中。因?yàn)榭赡苡卸鄠(gè)區(qū)塊,所以每個(gè)區(qū)塊都應(yīng)有一個(gè)唯一 ID:

class Block: 
    def __init__(self, index, transactions, timestamp): 
        self.index = [] 
        self.transactions = transactions 
        self.timestamp = timestamp

2

讓區(qū)塊不可更改

我們希望檢測(cè)出對(duì)區(qū)塊內(nèi)存儲(chǔ)的數(shù)據(jù)的任何篡改。在區(qū)塊鏈中,這是使用一個(gè)哈希函數(shù)來(lái)實(shí)現(xiàn)的。

哈希函數(shù) 接受任何大小的數(shù)據(jù)并生成固定大小的數(shù)據(jù),該結(jié)果通常用于識(shí)別輸入。下面是 Python 中的一個(gè)使用 sha256 哈希函數(shù)的示例:

>>> from hashlib import sha256
>>> data = "Some variable length data"
>>> sha256(data).hexdigest()
'b919fbbcae38e2bdaebb6c04ed4098e5c70563d2dc51e085f784c058ff208516'
>>> sha256(data).hexdigest() # no matter how many times you run it, the
 result is going to be the same 256 character string
'b919fbbcae38e2bdaebb6c04ed4098e5c70563d2dc51e085f784c058ff208516'

一個(gè)理想的哈希函數(shù)包括以下特征:

  • 它應(yīng)該很容易計(jì)算。
  • 哪怕只更改數(shù)據(jù)中的一個(gè)位,哈希值也應(yīng)該完全發(fā)生變化。
  • 應(yīng)該無(wú)法根據(jù)輸出哈希值猜出輸入。

您現(xiàn)在知道哈希函數(shù)是什么了吧。我們將每個(gè)區(qū)塊的哈希值都存儲(chǔ)在 Block 對(duì)象內(nèi)的一個(gè)字段中,其作用類似于它所包含的數(shù)據(jù)的數(shù)字指紋:

from hashlib import sha256
import json

def compute_hash(block):  
     """ 
    A function that creates the hash of the block. 
    """ 
    block_string = json.dumps(self.__dict__, sort_keys=True) 
    return sha256(block_string.encode()).hexdigest()

備注:在大多數(shù)加密貨幣中,甚至對(duì)區(qū)塊中的各個(gè)事務(wù)也進(jìn)行了哈希運(yùn)算,從而形成一棵哈希樹(也稱為 二進(jìn)制哈希樹 ),這棵樹的根可以用作區(qū)塊的哈希值。它不是區(qū)塊鏈正常運(yùn)作的必要條件,所以我們將省略它,以保持代碼簡(jiǎn)潔。

3

鏈接區(qū)塊

我們已設(shè)置了區(qū)塊。區(qū)塊鏈應(yīng)該是一個(gè)區(qū)塊集合。我們可以將所有區(qū)塊都存儲(chǔ)在 Python 列表中(等效于數(shù)組)。但這還不夠,因?yàn)槿绻腥斯室馓鎿Q了集合中的一個(gè)區(qū)塊該怎么辦?用修改過(guò)的事務(wù)創(chuàng)建一個(gè)新的區(qū)塊,計(jì)算哈希值,然后替換任何舊區(qū)塊,這在我們的當(dāng)前實(shí)現(xiàn)中并不是什么難事,因?yàn)槲覀儠?huì)保持區(qū)塊的不可更改性和順序。

我們需要采用某種途徑來(lái)確保對(duì)過(guò)去的區(qū)塊的任何更改都會(huì)造成整個(gè)鏈的失效。一種方法是通過(guò)哈希值將區(qū)塊鏈接起來(lái)。談到鏈接,我們指的是將前一個(gè)區(qū)塊的哈希值包含在當(dāng)前區(qū)塊中。所以,如果任何以前的區(qū)塊的內(nèi)容發(fā)生更改,該區(qū)塊的哈希值也會(huì)發(fā)生更改,導(dǎo)致與下一個(gè)區(qū)塊中的 previous_hash 字段不匹配。

每個(gè)區(qū)塊都通過(guò) previous_hash 字段鏈接到前一個(gè)區(qū)塊,但是第一個(gè)區(qū)塊該如何處理?第一個(gè)區(qū)塊稱為 創(chuàng)始區(qū)塊 ,大多數(shù)情況下,它是手動(dòng)生成或通過(guò)某種獨(dú)特邏輯生成的。讓我們將 previous_hash 字段添加到 Block 類中,并實(shí)現(xiàn)我們的 Blockchain 類的初始結(jié)構(gòu)(參見清單 1)。

清單 1. 我們的 Blockchain 類的初始結(jié)構(gòu)

from hashlib import sha256
import json
import time
class Block:  
    def__init__(self, index, transactions, timestamp, previous_hash):  
        self.index = index 
        self.transactions = transactions 
        self.timestamp = timestamp
        self.previous_hash = previous_hash 

    def compute_hash(self):  
        block_string = json.dumps(self.__dict__, sort_keys=True) 
        return sha256(block_string.encode()).hexdigest()

這是我們的 Blockchain 類:

class Blockchain: 

    def __init__(self): 
        self.unconfirmed_transactions = [] # data yet to get into blockchain
        self.chain = []
        self.create_genesis_block()

    def create_genesis_block(self): 
        """
        A function to generate genesis block and appends it to
        the chain.The block has index 0, previous_hash as 0, and
        a valid hash.
        """
        genesis_block = Block(0, [], time.time(), "0")
        genesis_block.hash = genesis_block.compute_hash()
        self.chain.append(genesis_block)

    @property
    def last_block(self): 
        return self.chain[-1]

4

實(shí)現(xiàn)工作量證明算法

選擇性背書與工作量證明

IBM Blockchain Platform 支持的業(yè)務(wù)區(qū)塊鏈中的共識(shí)性不是通過(guò)挖礦實(shí)現(xiàn)的,而是通過(guò)一個(gè)稱為 選擇性背書 的流程來(lái)實(shí)現(xiàn)的。網(wǎng)絡(luò)成員準(zhǔn)確控制由誰(shuí)來(lái)驗(yàn)證事務(wù),與目前的業(yè)務(wù)實(shí)現(xiàn)方式大致相同。進(jìn)一步了解業(yè)務(wù)區(qū)塊鏈。

但這里存在一個(gè)問(wèn)題。如果我們更改前一個(gè)區(qū)塊,我們可以非常輕松地重新計(jì)算所有后續(xù)區(qū)塊的哈希值,并創(chuàng)建一個(gè)不同的有效區(qū)塊鏈。為了預(yù)防這種情況,我們必須讓計(jì)算哈希值的任務(wù)變得困難和隨機(jī)化。

以下是我們實(shí)現(xiàn)此操作的方式。我們不會(huì)接受任何區(qū)塊哈希值,而是對(duì)它添加某種約束。讓我們來(lái)添加一種約束:哈希值應(yīng)以兩個(gè)前導(dǎo)零開始。另外我們知道,除非更改區(qū)塊的內(nèi)容,否則哈希值不會(huì)發(fā)生更改。

所以我們將在區(qū)塊中引入一個(gè)稱為 隨機(jī)數(shù) 的新字段。隨機(jī)數(shù)會(huì)不斷變化,直到我們獲得滿足約束條件的哈希值。前導(dǎo)零的數(shù)量(在我們的例子中為值 2)決定了工作量證明算法的“難度”。您可能還注意到,我們的工作量證明很難計(jì)算,但在我們確定隨機(jī)數(shù)后很容易驗(yàn)證(對(duì)于驗(yàn)證,您只需要再次運(yùn)行哈希函數(shù)即可):

class Blockchain: 
    # difficulty of PoW algorithm
    difficulty = 2

    """
    Previous code contd..
    """

    def proof_of_work(self, block): 
        """
        Function that tries different values of nonce to get a hash
        that satisfies our difficulty criteria.
        """
        block.nonce = 0

        computed_hash = block.compute_hash()
        while not computed_hash.startswith('0' * Blockchain.difficulty): 
            block.nonce += 1
            computed_hash = block.compute_hash()

        return computed_hash

請(qǐng)注意,沒(méi)有明確的邏輯來(lái)快速確定隨機(jī)數(shù);只能通過(guò)暴力破解。

5

將區(qū)塊添加到鏈中

要將區(qū)塊添加到鏈中,首先需要驗(yàn)證所提供的工作量證明是否正確,以及要添加的區(qū)塊的 previous_hash 字段是否指向鏈中的最新區(qū)塊的哈希值。

讓我們看看將區(qū)塊添加到鏈中的代碼:

class Blockchain: 
    """
    Previous code contd..
    """
    def add_block(self, block, proof): 
        """
        A function that adds the block to the chain after verification.
        """
        previous_hash = self.last_block.hash

        if previous_hash != block.previous_hash: 
            return False

        if not self.is_valid_proof(block, proof): 
            return False

        block.hash = proof
        self.chain.append(block)
        return True

    def is_valid_proof(self, block, block_hash): 
        """
        Check if block_hash is valid hash of block and satisfies
        the difficulty criteria.
        """
        return (block_hash.startswith('0' * Blockchain.difficulty) and
                block_hash == block.compute_hash())

挖礦

事務(wù)最初存儲(chǔ)在一個(gè)未確認(rèn)事務(wù)池中。將未確認(rèn)事務(wù)放入?yún)^(qū)塊中并計(jì)算工作量證明的過(guò)程被稱為區(qū)塊 挖礦 。一旦找到滿足我們的約束條件的隨機(jī)數(shù),我們就可以說(shuō)挖到了一個(gè)區(qū)塊,這個(gè)區(qū)塊就會(huì)放入?yún)^(qū)塊鏈中。

在大多數(shù)加密貨幣(包括比特幣)中,作為對(duì)耗費(fèi)算力來(lái)計(jì)算工作量證明的獎(jiǎng)勵(lì),礦工可以獲得一些加密貨幣。以下是我們的挖礦函數(shù)的格式:

class Blockchain: 
    """
    Previous code contd...
    """

    def add_new_transaction(self, transaction): 
            self.unconfirmed_transactions.append(transaction)

    def mine(self): 
        """
        This function serves as an interface to add the pending
        transactions to the blockchain by adding them to the block
        and figuring out Proof of Work.
        """
        if not self.unconfirmed_transactions: 
            return False

        last_block = self.last_block

        new_block = Block(index=last_block.index + 1,
                          transactions=self.unconfirmed_transactions,
                          timestamp=time.time(),
                          previous_hash=last_block.hash)

        proof = self.proof_of_work(new_block)
        self.add_block(new_block, proof)
        self.unconfirmed_transactions = []
        return new_block.index

好了,我們的工作差不多完成了。您可以 在 GitHub 上查看截至目前的合并代碼 。

6

創(chuàng)建接口

現(xiàn)在為我們的節(jié)點(diǎn)創(chuàng)建接口,以便與其他對(duì)等節(jié)點(diǎn)以及我們將要構(gòu)建的應(yīng)用程序進(jìn)行交互。我們將使用 Flask 創(chuàng)建一個(gè) REST-API 來(lái)與我們的節(jié)點(diǎn)進(jìn)行交互。以下是它的代碼:

from flask import Flask, request
import requests

app =  Flask(__name__)

# the node's copy of blockchain
blockchain = Blockchain()

我們的應(yīng)用程序需要一個(gè)端點(diǎn)來(lái)提交新事務(wù)。我們的應(yīng)用程序?qū)⑹褂么硕它c(diǎn)將新數(shù)據(jù)(帖子)添加到區(qū)塊鏈中:

@app.route('/new_transaction', methods=['POST'])
def new_transaction(): 
    tx_data = request.get_json()
    required_fields = ["author", "content"]

    for field in required_fields: 
        if not tx_data.get(field): 
            return "Invlaid transaction data", 404

    tx_data["timestamp"] = time.time()

    blockchain.add_new_transaction(tx_data)

    return "Success", 201

下面是返回節(jié)點(diǎn)的鏈副本的端點(diǎn)。我們的應(yīng)用程序?qū)⑹褂么硕它c(diǎn)來(lái)查詢要顯示的所有帖子:

@app.route('/chain', methods=['GET'])
def get_chain(): 
    chain_data = []
    for block in blockchain.chain: 
        chain_data.append(block.__dict__)
    return json.dumps({"length": len(chain_data),
                       "chain": chain_data})

下面是請(qǐng)求節(jié)點(diǎn)挖掘未確認(rèn)事務(wù)(如果有)的端點(diǎn)。我們將使用此端點(diǎn)從我們的應(yīng)用程序自身發(fā)起一個(gè)挖礦命令:

@app.route('/mine', methods=['GET'])
def mine_unconfirmed_transactions(): 
    result = blockchain.mine()
    if not result: 
        return "No transactions to mine"
    return "Block #{} is mined.".format(result)


# endpoint to query unconfirmed transactions
@app.route('/pending_tx')
def get_pending_tx(): 
    return json.dumps(blockchain.unconfirmed_transactions)


app.run(debug=True, port=8000)

現(xiàn)在,您可以體驗(yàn)一下我們的區(qū)塊鏈,創(chuàng)建一些事務(wù),然后使用諸如 cURL 或 Postman 之類的工具來(lái)挖掘它們。

7

建立共識(shí)和去中心化

目前為止,我們實(shí)現(xiàn)的代碼只能在單個(gè)計(jì)算機(jī)上運(yùn)行。即使通過(guò)哈希值鏈接了區(qū)塊,我們?nèi)匀徊荒苄湃螁蝹(gè)實(shí)體。我們需要多個(gè)節(jié)點(diǎn)來(lái)維護(hù)我們的區(qū)塊鏈。 所以讓我們創(chuàng)建一個(gè)端點(diǎn),以便讓一個(gè)節(jié)點(diǎn)了解網(wǎng)絡(luò)中的其他對(duì)等節(jié)點(diǎn):

# the address to other participating members of the network
peers = set()

# endpoint to add new peers to the network.
@app.route('/add_nodes', methods=['POST'])
def register_new_peers(): 
    nodes = request.get_json()
    if not nodes: 
        return "Invalid data", 400
    for node in nodes: 
        peers.add(node)

    return "Success", 201

您可能已經(jīng)認(rèn)識(shí)到,在多節(jié)點(diǎn)方面存在一個(gè)問(wèn)題。由于故意操縱或意外的原因,一些節(jié)點(diǎn)的鏈副本可能有所不同。在這種情況下,我們需要商定采用鏈的某個(gè)版本,以維持整個(gè)系統(tǒng)的完整性。我們需要達(dá)成共識(shí)。

一種簡(jiǎn)單的共識(shí)算法可能是,在網(wǎng)絡(luò)中的不同參與者構(gòu)成的鏈出現(xiàn)分歧時(shí),商定采用最長(zhǎng)的有效鏈。選擇此方法的理由是,最長(zhǎng)的鏈?zhǔn)菍?duì)已完成的最多工作量的有效估算:

def consensus(): 
    """
    Our simple consensus algorithm.如果找到一個(gè)更長(zhǎng)的有效鏈,則用它替換我們的鏈。
    """
    global blockchain

    longest_chain = None
    current_len = len(blockchain)

    for node in peers: 
        response = requests.get('http://{}/chain'.format(node))
        length = response.json()['length']
        chain = response.json()['chain']
        if length > current_len and blockchain.check_chain_validity(chain): 
            current_len = length
            longest_chain = chain

    if longest_chain: 
        blockchain = longest_chain
        return True

    return False

最后,我們需要開發(fā)一種方法,讓任何節(jié)點(diǎn)向網(wǎng)絡(luò)宣布它已經(jīng)挖到一個(gè)區(qū)塊,以便每個(gè)人都能更新他們的區(qū)塊鏈,并繼續(xù)挖掘其他事務(wù)。其他節(jié)點(diǎn)可以輕松地驗(yàn)證工作量證明,并將它添加到各自的鏈中:

# endpoint to add a block mined by someone else to the node's chain.
@app.route('/add_block', methods=['POST'])
def validate_and_add_block(): 
    block_data = request.get_json()
    block = Block(block_data["index"], block_data["transactions"],
                  block_data["timestamp", block_data["previous_hash"]])

    proof = block_data['hash']
    added = blockchain.add_block(block, proof)

    if not added: 
        return "The block was discarded by the node", 400

    return "Block added to the chain", 201
    
    def announce_new_block(block): 
    for peer in peers: 
        url = "http://{}/add_block".format(peer)
        requests.post(url, data=json.dumps(block.__dict__, sort_keys=True))

announce_new_block 方法應(yīng)在節(jié)點(diǎn)挖到每個(gè)區(qū)塊后調(diào)用,以便對(duì)等節(jié)點(diǎn)能將該區(qū)塊添加到自己的鏈中。

8

構(gòu)建應(yīng)用程序

好了,后端都設(shè)置好了。您可以 在 GitHub 上查看到目前為止的代碼 。

現(xiàn)在,是時(shí)候創(chuàng)建應(yīng)用程序的接口了。我們使用了 Jinja2 模板來(lái)呈現(xiàn)網(wǎng)頁(yè)和一些 CSS,讓頁(yè)面看起來(lái)美觀一些。

我們的應(yīng)用程序需要連接到區(qū)塊鏈網(wǎng)絡(luò)中的某個(gè)節(jié)點(diǎn),以便抓取數(shù)據(jù)和提交新數(shù)據(jù)。也可能存在多個(gè)節(jié)點(diǎn):

import datetime
import json

import requests
from flask import render_template, redirect, request

from app import app

.
CONNECTED_NODE_ADDRESS = "http://127.0.0.1:8000"

posts = []

fetch_posts 函數(shù)從節(jié)點(diǎn)的 / chain 端點(diǎn)獲取數(shù)據(jù),解析該數(shù)據(jù)并將它們存儲(chǔ)在本地。

def fetch_posts(): 
    get_chain_address = "{}/chain".format(CONNECTED_NODE_ADDRESS)
    response = requests.get(get_chain_address)
    if response.status_code == 200: 
        content = []
        chain = json.loads(response.content)
        for block in chain["chain"]: 
            for tx in block["transactions"]: 
                tx["index"] = block["index"]
                tx["hash"] = block["previous_hash"]
                content.append(tx)

        global posts
        posts = sorted(content, key=lambda k: k['timestamp'],
                       reverse=True)

該應(yīng)用程序有一個(gè) HTML 表單,用于接受用戶輸入,然后向一個(gè)已連接的節(jié)點(diǎn)發(fā)出一個(gè) POST 請(qǐng)求,以便將該事務(wù)添加到未確認(rèn)事務(wù)池中。然后,通過(guò)網(wǎng)絡(luò)對(duì)該事務(wù)進(jìn)行挖掘,最后在我們刷新網(wǎng)站后抓取該事務(wù):

@app.route('/submit', methods=['POST'])
def submit_textarea(): 
    """
    Endpoint to create a new transaction via our application.
    """
    post_content = request.form["content"]
    author = request.form["author"]

    post_object = {
        'author': author,
        'content': post_content,
    }

    # Submit a transaction
    new_tx_address = "{}/new_transaction".format(CONNECTED_NODE_ADDRESS)

    requests.post(new_tx_address,
                  json=post_object,
                  headers={'Content-type': 'application/json'})

    return redirect('/')

9

運(yùn)行應(yīng)用程序

大功告成!可以 在 GitHub 上找到最終代碼 。

要運(yùn)行該應(yīng)用程序:

  1. 啟動(dòng)一個(gè)區(qū)塊鏈節(jié)點(diǎn)服務(wù)器:
    python node_server.py
  2. 運(yùn)行該應(yīng)用程序:
    python run_app.py

您應(yīng)該能在 http://localhost:5000 上看到正在運(yùn)行的應(yīng)用程序。

  1. 嘗試發(fā)布一些數(shù)據(jù),您會(huì)看到類似下圖的結(jié)果:

    使用 Python 從零開始開發(fā)區(qū)塊鏈應(yīng)用程序

     
  2. 單擊 Request to mine 按鈕,您會(huì)看到類似下圖的結(jié)果:

    使用 Python 從零開始開發(fā)區(qū)塊鏈應(yīng)用程序

     
  3. 單擊 Resync 按鈕,您會(huì)看到應(yīng)用程序與鏈重新同步:

    使用 Python 從零開始開發(fā)區(qū)塊鏈應(yīng)用程序

驗(yàn)證事務(wù)

您可能注意到了應(yīng)用程序中的一個(gè)缺陷:任何人都能更改任何名稱和發(fā)布任何內(nèi)容。解決此問(wèn)題的一種方法是,使用 公私密鑰加密 來(lái)創(chuàng)建帳戶。每個(gè)新用戶都需要一個(gè)公鑰(類似于用戶名)和私鑰,才能在我們的應(yīng)用程序中發(fā)布內(nèi)容。這些密鑰可以充當(dāng)數(shù)字簽名。公鑰只能對(duì)使用相應(yīng)私鑰加密的內(nèi)容進(jìn)行解密。在將事務(wù)添加到任何區(qū)塊之前,會(huì)使用作者的公鑰對(duì)其進(jìn)行驗(yàn)證。這樣,我們就知道是誰(shuí)寫的這條消息。

結(jié)束語(yǔ)

本教程介紹了公有區(qū)塊鏈的基礎(chǔ)知識(shí)。如果您一直在跟隨操作,那么您已經(jīng)從零開始實(shí)現(xiàn)了一個(gè)區(qū)塊鏈,并構(gòu)建了一個(gè)簡(jiǎn)單應(yīng)用程序來(lái)允許用戶在該區(qū)塊鏈上共享信息。

后續(xù)行動(dòng)

您可以在云上創(chuàng)建多個(gè)節(jié)點(diǎn),并完善您構(gòu)建的應(yīng)用程序。您可以 將任何 Flask 應(yīng)用程序部署到 IBM Cloud 。

此外,您還可以使用諸如 ngrok 之類的隧道服務(wù)為您的 localhost 服務(wù)器創(chuàng)建一個(gè)公有 URL,然后您就能與多臺(tái)機(jī)器進(jìn)行交互。

這一領(lǐng)域還有許多值得探索的地方!您可以通過(guò)以下方式繼續(xù)增強(qiáng)您的區(qū)塊鏈技能:

  • 親自體驗(yàn)新的 IBM Blockchain Platform Starter Plan(免費(fèi)測(cè)試版),繼續(xù)探索區(qū)塊鏈技術(shù)。您可以快速建立一個(gè)區(qū)塊鏈預(yù)生產(chǎn)網(wǎng)絡(luò),部署樣本應(yīng)用程序,開發(fā)和部署客戶端應(yīng)用程序。 入門 ! 
  • 訪問(wèn) developerWorks 上的 區(qū)塊鏈開發(fā)人員中心 。可以在這里獲得開發(fā)和部署業(yè)務(wù)區(qū)塊鏈解決方案的工具和教程,以及代碼和社區(qū)支持。 
  • 學(xué)習(xí) 面向開發(fā)人員的區(qū)塊鏈基礎(chǔ)課程 ,了解資產(chǎn)轉(zhuǎn)移的復(fù)雜細(xì)節(jié)。學(xué)完這門持續(xù) 2 小時(shí)的免費(fèi)自學(xué)課程后,參加測(cè)驗(yàn),獲取一枚徽章,并開始為您的業(yè)務(wù)網(wǎng)絡(luò)規(guī)劃有用的區(qū)塊鏈應(yīng)用程序。 
  • 繼續(xù)學(xué)習(xí) IBM Blockchain 開發(fā)人員基礎(chǔ)課程 ,這門持續(xù) 6 小時(shí)的免費(fèi)課程在“區(qū)塊鏈基礎(chǔ)知識(shí)”的基礎(chǔ)上進(jìn)行了擴(kuò)展,更詳細(xì)地介紹了區(qū)塊鏈業(yè)務(wù)網(wǎng)絡(luò)的組件和架構(gòu),以及構(gòu)建網(wǎng)絡(luò)和創(chuàng)建應(yīng)用程序的經(jīng)驗(yàn)。 
  • 查閱許多 區(qū)塊鏈 Code Pattern ,它們提供了解決復(fù)雜問(wèn)題的路線圖,包括概述、架構(gòu)圖、流程、存儲(chǔ)庫(kù)指南和其他閱讀材料。

作者簡(jiǎn)介

Satwik Kansal 是一位擁有區(qū)塊鏈技術(shù)和數(shù)據(jù)科學(xué)經(jīng)驗(yàn)的軟件開發(fā)人員?梢栽 Twitter、 Linkedin 或 他的網(wǎng)站 上聯(lián)系他。

 

來(lái)自:http://www.ibm.com/developerworks/cn/cloud/library/cl-develop-blockchain-app-in-python/index.html?ca=drs-

 

標(biāo)簽: 安全 代碼 電子商務(wù) 服務(wù)器 互聯(lián)網(wǎng) 腳本 網(wǎng)絡(luò)

版權(quán)申明:本站文章部分自網(wǎng)絡(luò),如有侵權(quán),請(qǐng)聯(lián)系:west999com@outlook.com
特別注意:本站所有轉(zhuǎn)載文章言論不代表本站觀點(diǎn)!
本站所提供的圖片等素材,版權(quán)歸原作者所有,如需使用,請(qǐng)與原作者聯(lián)系。

上一篇:RxJS 緩存高級(jí)教程

下一篇:編寫高性能 Java 代碼的最佳實(shí)踐