亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

Python實現類似比特幣的加密貨幣區塊鏈的創建與交易實例

系統 2489 0

雖然有些人認為區塊鏈是一個早晚會出現問題的解決方案,但是毫無疑問,這個創新技術是一個計算機技術上的奇跡。那么,究竟什么是區塊鏈呢?

區塊鏈

以比特幣(Bitcoin)或其它加密貨幣按時間順序公開地記錄交易的數字賬本。

更通俗的說,它是一個公開的數據庫,新的數據存儲在被稱之為區塊(block)的容器中,并被添加到一個不可變的鏈(chain)中(因此被稱為區塊鏈(blockchain)),之前添加的數據也在該鏈中。對于比特幣或其它加密貨幣來說,這些數據就是一組組交易,不過,也可以是其它任何類型的數據。

區塊鏈技術帶來了全新的、完全數字化的貨幣,如比特幣和萊特幣(Litecoin),它們并不由任何中心機構管理。這給那些認為當今的銀行系統是騙局并將最終走向失敗的人帶來了自由。區塊鏈也革命性地改變了分布式計算的技術形式,如以太坊(Ethereum)就引入了一種有趣的概念:智能合約(smart contract)。

在這篇文章中,我將用不到 50 行的 Python 2.x 代碼實現一個簡單的區塊鏈,我把它叫做 SnakeCoin。

不到 50 行代碼的區塊鏈

我們首先將從定義我們的區塊是什么開始。在區塊鏈中,每個區塊隨同時間戳及可選的索引一同存儲。在 SnakeCoin 中,我們會存儲這兩者。為了確保整個區塊鏈的完整性,每個區塊都會有一個自識別的哈希值。如在比特幣中,每個區塊的哈希是該塊的索引、時間戳、數據和前一個區塊的哈希值等數據的加密哈希值。這里提及的“數據”可以是任何你想要的數據。

            
import hashlib as hasher

class Block:
 def __init__(self, index, timestamp, data, previous_hash):
  self.index = index
  self.timestamp = timestamp
  self.data = data
  self.previous_hash = previous_hash
  self.hash = self.hash_block()
 
 def hash_block(self):
  sha = hasher.sha256()
  sha.update(str(self.index) + 
        str(self.timestamp) + 
        str(self.data) + 
        str(self.previous_hash))
  return sha.hexdigest()

import hashlib as hasher
 
class Block:
 def __init__(self, index, timestamp, data, previous_hash):
  self.index = index
  self.timestamp = timestamp
  self.data = data
  self.previous_hash = previous_hash
  self.hash = self.hash_block()
 
 def hash_block(self):
  sha = hasher.sha256()
  sha.update(str(self.index) + 
        str(self.timestamp) + 
        str(self.data) + 
        str(self.previous_hash))
  return sha.hexdigest()


          

現在我們有了區塊的結構了,不過我們需要創建的是一個區塊鏈。我們需要把區塊添加到一個實際的鏈中。如我們之前提到過的,每個區塊都需要前一個區塊的信息。但問題是,該區塊鏈中的第一個區塊在哪里?好吧,這個第一個區塊,也稱之為創世區塊,是一個特別的區塊。在很多情況下,它是手工添加的,或通過獨特的邏輯添加的。

我們將創建一個函數來簡單地返回一個創世區塊解決這個問題。這個區塊的索引為 0 ,其包含一些任意的數據值,其“前一哈希值”參數也是任意值。

            
import datetime as date

def create_genesis_block():
 # Manually construct a block with
 # index zero and arbitrary previous hash
 return Block(0, date.datetime.now(), "Genesis Block", "0")

import datetime as date
 
def create_genesis_block():
 # Manually construct a block with
 # index zero and arbitrary previous hash
 return Block(0, date.datetime.now(), "Genesis Block", "0")


          

現在我們可以創建創世區塊了,我們需要一個函數來生成該區塊鏈中的后繼區塊。該函數將獲取鏈中的前一個區塊作為參數,為要生成的區塊創建數據,并用相應的數據返回新的區塊。新的區塊的哈希值來自于之前的區塊,這樣每個新的區塊都提升了該區塊鏈的完整性。如果我們不這樣做,外部參與者就很容易“改變過去”,把我們的鏈替換為他們的新鏈了。這個哈希鏈起到了加密的證明作用,并有助于確保一旦一個區塊被添加到鏈中,就不能被替換或移除。

            
def next_block(last_block):
 this_index = last_block.index + 1
 this_timestamp = date.datetime.now()
 this_data = "Hey! I'm block " + str(this_index)
 this_hash = last_block.hash
 return Block(this_index, this_timestamp, this_data, this_hash)

def next_block(last_block):
 this_index = last_block.index + 1
 this_timestamp = date.datetime.now()
 this_data = "Hey! I'm block " + str(this_index)
 this_hash = last_block.hash
 return Block(this_index, this_timestamp, this_data, this_hash)

          

這就是主要的部分。

現在我們能創建自己的區塊鏈了!在這里,這個區塊鏈是一個簡單的 Python 列表。其第一個的元素是我們的創世區塊,我們會添加后繼區塊。因為 SnakeCoin 是一個極小的區塊鏈,我們僅僅添加了 20 個區塊。我們通過循環來完成它。

            
# Create the blockchain and add the genesis block
blockchain = [create_genesis_block()]
previous_block = blockchain[0]

# How many blocks should we add to the chain
# after the genesis block
num_of_blocks_to_add = 20

# Add blocks to the chain
for i in range(0, num_of_blocks_to_add):
 block_to_add = next_block(previous_block)
 blockchain.append(block_to_add)
 previous_block = block_to_add
 # Tell everyone about it!
 print "Block #{} has been added to the blockchain!".format(block_to_add.index)
 print "Hash: {}n".format(block_to_add.hash)

# Create the blockchain and add the genesis block
blockchain = [create_genesis_block()]
previous_block = blockchain[0]
 
# How many blocks should we add to the chain
# after the genesis block
num_of_blocks_to_add = 20
 
# Add blocks to the chain
for i in range(0, num_of_blocks_to_add):
 block_to_add = next_block(previous_block)
 blockchain.append(block_to_add)
 previous_block = block_to_add
 # Tell everyone about it!
 print "Block #{} has been added to the blockchain!".format(block_to_add.index)
 print "Hash: {}n".format(block_to_add.hash)


          

讓我們看看我們的成果:

Python實現類似比特幣的加密貨幣區塊鏈的創建與交易實例_第1張圖片

別擔心,它將一直添加到 20 個區塊

很好,我們的區塊鏈可以工作了。如果你想要在主控臺查看更多的信息,你可以編輯其完整的源代碼并輸出每個區塊的時間戳或數據。

這就是 SnakeCoin 所具有的功能。要使 SnakeCoin 達到現今的產品級的區塊鏈的高度,我們需要添加更多的功能,如服務器層,以在多臺機器上跟蹤鏈的改變,并通過工作量證明算法(POW)來限制給定時間周期內可以添加的區塊數量。

如果你想了解更多技術細節,你可以在這里查看最初的比特幣白皮書。

讓這個極小區塊鏈稍微變大些
這個極小的區塊鏈及其簡單,自然也相對容易完成。但是因其簡單也帶來了一些缺陷。首先,SnakeCoin 僅能運行在單一的一臺機器上,所以它相距分布式甚遠,更別提去中心化了。其次,區塊添加到區塊鏈中的速度同在主機上創建一個 Python 對象并添加到列表中一樣快。在我們的這個簡單的區塊鏈中,這不是問題,但是如果我們想讓 SnakeCoin 成為一個實際的加密貨幣,我們就需要控制在給定時間內能創建的區塊(和幣)的數量。

從現在開始,SnakeCoin 中的“數據”將是交易數據,每個區塊的“數據”字段都將是一些交易信息的列表。接著我們來定義“交易”。每個“交易”是一個 JSON 對象,其記錄了幣的發送者、接收者和轉移的 SnakeCoin 數量。注:交易信息是 JSON 格式,原因我很快就會說明。

            
{
 "from": "71238uqirbfh894-random-public-key-a-alkjdflakjfewn204ij",
 "to": "93j4ivnqiopvh43-random-public-key-b-qjrgvnoeirbnferinfo",
 "amount": 3
}


{
 "from": "71238uqirbfh894-random-public-key-a-alkjdflakjfewn204ij",
 "to": "93j4ivnqiopvh43-random-public-key-b-qjrgvnoeirbnferinfo",
 "amount": 3
}

          

現在我們知道了交易信息看起來的樣子了,我們需要一個辦法來將其加到我們的區塊鏈網絡中的一臺計算機(稱之為節點)中。要做這個事情,我們會創建一個簡單的 HTTP 服務器,以便每個用戶都可以讓我們的節點知道發生了新的交易。節點可以接受? POST 請求,請求數據為如上的交易信息。這就是為什么交易信息是 JSON 格式的:我們需要它們可以放在請求信息中傳遞給服務器。

            
$ pip install flask # 首先安裝 Web 服務器框架
1
$ pip install flask # 首先安裝 Web 服務器框架
Python

from flask import Flask
from flask import request
node = Flask(__name__)
# Store the transactions that
# this node has in a list
this_nodes_transactions = []
@node.route('/txion', methods=['POST'])
def transaction():
 if request.method == 'POST':
  # On each new POST request,
  # we extract the transaction data
  new_txion = request.get_json()
  # Then we add the transaction to our list
  this_nodes_transactions.append(new_txion)
  # Because the transaction was successfully
  # submitted, we log it to our console
  print "New transaction"
  print "FROM: {}".format(new_txion['from'])
  print "TO: {}".format(new_txion['to'])
  print "AMOUNT: {}\n".format(new_txion['amount'])
  # Then we let the client know it worked out
  return "Transaction submission successful\n"
node.run()

from flask import Flask
from flask import request
node = Flask(__name__)
# Store the transactions that
# this node has in a list
this_nodes_transactions = []
@node.route('/txion', methods=['POST'])
def transaction():
 if request.method == 'POST':
  # On each new POST request,
  # we extract the transaction data
  new_txion = request.get_json()
  # Then we add the transaction to our list
  this_nodes_transactions.append(new_txion)
  # Because the transaction was successfully
  # submitted, we log it to our console
  print "New transaction"
  print "FROM: {}".format(new_txion['from'])
  print "TO: {}".format(new_txion['to'])
  print "AMOUNT: {}\n".format(new_txion['amount'])
  # Then we let the client know it worked out
  return "Transaction submission successful\n"
node.run()


          

現在我們有了一種保存用戶彼此發送 SnakeCoin 的記錄的方式。這就是為什么人們將區塊鏈稱之為公共的、分布式賬本:所有的交易信息存儲給所有人看,并被存儲在該網絡的每個節點上。

但是,有個問題:人們從哪里得到 SnakeCoin 呢?現在還沒有辦法得到,還沒有一個稱之為 SnakeCoin 這樣的東西,因為我們還沒有創建和分發任何一個幣。要創建新的幣,人們需要“挖”一個新的 SnakeCoin 區塊。當他們成功地挖到了新區塊,就會創建出一個新的 SnakeCoin ,并獎勵給挖出該區塊的人(礦工)。一旦挖礦的礦工將 SnakeCoin 發送給別人,這個幣就流通起來了。

我們不想讓挖新的 SnakeCoin 區塊太容易,因為這將導致 SnakeCoin 太多了,其價值就變低了;同樣,我們也不想讓它變得太難,因為如果沒有足夠的幣供每個人使用,它們對于我們來說就太昂貴了。為了控制挖新的 SnakeCoin 區塊的難度,我們會實現一個工作量證明(Proof-of-Work)(PoW)算法。工作量證明基本上就是一個生成某個項目比較難,但是容易驗證(其正確性)的算法。這個項目被稱之為“證明”,聽起來就像是它證明了計算機執行了特定的工作量。

在 SnakeCoin 中,我們創建了一個簡單的 PoW 算法。要創建一個新區塊,礦工的計算機需要遞增一個數字,當該數字能被 9 (“SnakeCoin” 這個單詞的字母數)整除時,這就是最后這個區塊的證明數字,就會挖出一個新的 SnakeCoin 區塊,而該礦工就會得到一個新的 SnakeCoin。

            
# ...blockchain
# ...Block class definition
miner_address = "q3nf394hjg-random-miner-address-34nf3i4nflkn3oi"
def proof_of_work(last_proof):
 # Create a variable that we will use to find
 # our next proof of work
 incrementor = last_proof + 1
 # Keep incrementing the incrementor until
 # it's equal to a number divisible by 9
 # and the proof of work of the previous
 # block in the chain
 while not (incrementor % 9 == 0 and incrementor % last_proof == 0):
  incrementor += 1
 # Once that number is found,
 # we can return it as a proof
 # of our work
 return incrementor
@node.route('/mine', methods = ['GET'])
def mine():
 # Get the last proof of work
 last_block = blockchain[len(blockchain) - 1]
 last_proof = last_block.data['proof-of-work']
 # Find the proof of work for
 # the current block being mined
 # Note: The program will hang here until a new
 #    proof of work is found
 proof = proof_of_work(last_proof)
 # Once we find a valid proof of work,
 # we know we can mine a block so 
 # we reward the miner by adding a transaction
 this_nodes_transactions.append(
  { "from": "network", "to": miner_address, "amount": 1 }
 )
 # Now we can gather the data needed
 # to create the new block
 new_block_data = {
  "proof-of-work": proof,
  "transactions": list(this_nodes_transactions)
 }
 new_block_index = last_block.index + 1
 new_block_timestamp = this_timestamp = date.datetime.now()
 last_block_hash = last_block.hash
 # Empty transaction list
 this_nodes_transactions[:] = []
 # Now create the
 # new block!
 mined_block = Block(
  new_block_index,
  new_block_timestamp,
  new_block_data,
  last_block_hash
 )
 blockchain.append(mined_block)
 # Let the client know we mined a block
 return json.dumps({
   "index": new_block_index,
   "timestamp": str(new_block_timestamp),
   "data": new_block_data,
   "hash": last_block_hash
 }) + "\n"

# ...blockchain
# ...Block class definition
miner_address = "q3nf394hjg-random-miner-address-34nf3i4nflkn3oi"
def proof_of_work(last_proof):
 # Create a variable that we will use to find
 # our next proof of work
 incrementor = last_proof + 1
 # Keep incrementing the incrementor until
 # it's equal to a number divisible by 9
 # and the proof of work of the previous
 # block in the chain
 while not (incrementor % 9 == 0 and incrementor % last_proof == 0):
  incrementor += 1
 # Once that number is found,
 # we can return it as a proof
 # of our work
 return incrementor
@node.route('/mine', methods = ['GET'])
def mine():
 # Get the last proof of work
 last_block = blockchain[len(blockchain) - 1]
 last_proof = last_block.data['proof-of-work']
 # Find the proof of work for
 # the current block being mined
 # Note: The program will hang here until a new
 #    proof of work is found
 proof = proof_of_work(last_proof)
 # Once we find a valid proof of work,
 # we know we can mine a block so 
 # we reward the miner by adding a transaction
 this_nodes_transactions.append(
  { "from": "network", "to": miner_address, "amount": 1 }
 )
 # Now we can gather the data needed
 # to create the new block
 new_block_data = {
  "proof-of-work": proof,
  "transactions": list(this_nodes_transactions)
 }
 new_block_index = last_block.index + 1
 new_block_timestamp = this_timestamp = date.datetime.now()
 last_block_hash = last_block.hash
 # Empty transaction list
 this_nodes_transactions[:] = []
 # Now create the
 # new block!
 mined_block = Block(
  new_block_index,
  new_block_timestamp,
  new_block_data,
  last_block_hash
 )
 blockchain.append(mined_block)
 # Let the client know we mined a block
 return json.dumps({
   "index": new_block_index,
   "timestamp": str(new_block_timestamp),
   "data": new_block_data,
   "hash": last_block_hash
 }) + "\n"

          

現在,我們能控制特定的時間段內挖到的區塊數量,并且我們給了網絡中的人新的幣,讓他們彼此發送。但是如我們說的,我們只是在一臺計算機上做的。如果區塊鏈是去中心化的,我們怎樣才能確保每個節點都有相同的鏈呢?要做到這一點,我們會使每個節點都廣播其(保存的)鏈的版本,并允許它們接受其它節點的鏈。然后,每個節點會校驗其它節點的鏈,以便網絡中每個節點都能夠達成最終的鏈的共識。這稱之為共識算法(consensus algorithm)。

我們的共識算法很簡單:如果一個節點的鏈與其它的節點的不同(例如有沖突),那么最長的鏈保留,更短的鏈會被刪除。如果我們網絡上的鏈沒有了沖突,那么就可以繼續了。

            
@node.route('/blocks', methods=['GET'])
def get_blocks():
 chain_to_send = blockchain
 # Convert our blocks into dictionaries
 # so we can send them as json objects later
 for block in chain_to_send:
  block_index = str(block.index)
  block_timestamp = str(block.timestamp)
  block_data = str(block.data)
  block_hash = block.hash
  block = {
   "index": block_index,
   "timestamp": block_timestamp,
   "data": block_data,
   "hash": block_hash
  }
 # Send our chain to whomever requested it
 chain_to_send = json.dumps(chain_to_send)
 return chain_to_send
def find_new_chains():
 # Get the blockchains of every
 # other node
 other_chains = []
 for node_url in peer_nodes:
  # Get their chains using a GET request
  block = requests.get(node_url + "/blocks").content
  # Convert the JSON object to a Python dictionary
  block = json.loads(block)
  # Add it to our list
  other_chains.append(block)
 return other_chains
def consensus():
 # Get the blocks from other nodes
 other_chains = find_new_chains()
 # If our chain isn't longest,
 # then we store the longest chain
 longest_chain = blockchain
 for chain in other_chains:
  if len(longest_chain) < len(chain):
   longest_chain = chain
 # If the longest chain wasn't ours,
 # then we set our chain to the longest
 blockchain = longest_chain

@node.route('/blocks', methods=['GET'])
def get_blocks():
 chain_to_send = blockchain
 # Convert our blocks into dictionaries
 # so we can send them as json objects later
 for block in chain_to_send:
  block_index = str(block.index)
  block_timestamp = str(block.timestamp)
  block_data = str(block.data)
  block_hash = block.hash
  block = {
   "index": block_index,
   "timestamp": block_timestamp,
   "data": block_data,
   "hash": block_hash
  }
 # Send our chain to whomever requested it
 chain_to_send = json.dumps(chain_to_send)
 return chain_to_send
def find_new_chains():
 # Get the blockchains of every
 # other node
 other_chains = []
 for node_url in peer_nodes:
  # Get their chains using a GET request
  block = requests.get(node_url + "/blocks").content
  # Convert the JSON object to a Python dictionary
  block = json.loads(block)
  # Add it to our list
  other_chains.append(block)
 return other_chains
def consensus():
 # Get the blocks from other nodes
 other_chains = find_new_chains()
 # If our chain isn't longest,
 # then we store the longest chain
 longest_chain = blockchain
 for chain in other_chains:
  if len(longest_chain) < len(chain):
   longest_chain = chain
 # If the longest chain wasn't ours,
 # then we set our chain to the longest
 blockchain = longest_chain

          

我們差不多就要完成了。在運行了完整的 SnakeCoin 服務器代碼之后,在你的終端可以運行如下代碼。(假設你已經安裝了 cCUL)。

1、創建交易

            
curl "localhost:5000/txion" \
   -H "Content-Type: application/json" \
   -d '{"from": "akjflw", "to":"fjlakdj", "amount": 3}'

curl "localhost:5000/txion" \
   -H "Content-Type: application/json" \
   -d '{"from": "akjflw", "to":"fjlakdj", "amount": 3}'

          

?

2、挖一個新區塊

            
curl localhost:5000/mine

curl localhost:5000/mine

          

3、 查看結果。從客戶端窗口,我們可以看到。

對代碼做下美化處理,我們看到挖礦后我們得到的新區塊的信息:

            
{
 "index": 2,
 "data": {
  "transactions": [
   {
    "to": "fjlakdj",
    "amount": 3,
    "from": "akjflw"
   },
   {
    "to": "q3nf394hjg-random-miner-address-34nf3i4nflkn3oi",
    "amount": 1,
    "from": "network"
   }
  ],
  "proof-of-work": 36
 },
 "hash": "151edd3ef6af2e7eb8272245cb8ea91b4ecfc3e60af22d8518ef0bba8b4a6b18",
 "timestamp": "2017-07-23 11:23:10.140996"
}

{
 "index": 2,
 "data": {
  "transactions": [
   {
    "to": "fjlakdj",
    "amount": 3,
    "from": "akjflw"
   },
   {
    "to": "q3nf394hjg-random-miner-address-34nf3i4nflkn3oi",
    "amount": 1,
    "from": "network"
   }
  ],
  "proof-of-work": 36
 },
 "hash": "151edd3ef6af2e7eb8272245cb8ea91b4ecfc3e60af22d8518ef0bba8b4a6b18",
 "timestamp": "2017-07-23 11:23:10.140996"
}

          

大功告成!現在 SnakeCoin 可以運行在多個機器上,從而創建了一個網絡,而且真實的 SnakeCoin 也能被挖到了。

你可以根據你的喜好去修改 SnakeCoin 服務器代碼,并問各種問題了,好了本文暫時講解一下Python實現類似比特幣的加密貨幣區塊鏈的創建與交易實例。

下一篇我們將討論創建一個 SnakeCoin 錢包,這樣用戶就可以發送、接收和存儲他們的 SnakeCoin 了


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 精品国产调教最大网站女王 | 91久久亚洲最新一本 | 99在线在线视频免费视频观看 | 欧美爱爱片 | 日韩免费观看一级毛片看看 | 欧美91精品久久久久网免费 | 国产成人精品日本亚洲网站 | 四虎新网址 | 人人爱操| 99久久久精品 | 国产精品玖玖玖影院 | 四虎4hutv永久地址公告 | 久久精品亚洲精品一区 | 亚洲综合春色另类久久 | 就操视频| 亚洲欧美日韩国产 | 欧美毛片aaaaa片久久久久 | 国产一区二区在线不卡 | 奇米影视77777 | 天天草夜夜草 | 999精品国产 | 九一视频在线免费观看 | 色一情一乱一伦麻豆 | 午夜国产精品色福利视频 | 青草社区视频 | 999久久久免费精品国产牛牛 | 四虎国产精品免费久久影院 | 国产精品久久久久免费a∨ 国产精品久久久久免费视频 | 成人国产片免费 | 狠狠色成人综合网图片区 | 国产在线观看91 | 中国女人内谢69xxxxx高清 | 手机看片精品高清国产日韩 | 5g影院天天5g天天爽精品 | 婷婷婷色 | 在线观看91精品国产不卡免费 | 久久成人综合 | 在线亚洲 欧美 日本专区 | 99热久热这里只精品 | 天天想夜夜操 | 三上悠亚在线一区 |