Python實(shí)現(xiàn)類似比特幣的加密貨幣區(qū)塊鏈的創(chuàng)建與交易實(shí)例
雖然有些人認(rèn)為區(qū)塊鏈?zhǔn)且粋€(gè)早晚會(huì)出現(xiàn)問(wèn)題的解決方案,但是毫無(wú)疑問(wèn),這個(gè)創(chuàng)新技術(shù)是一個(gè)計(jì)算機(jī)技術(shù)上的奇跡。那么,究竟什么是區(qū)塊鏈呢?
區(qū)塊鏈
以比特幣(Bitcoin)或其它加密貨幣按時(shí)間順序公開(kāi)地記錄交易的數(shù)字賬本。
更通俗的說(shuō),它是一個(gè)公開(kāi)的數(shù)據(jù)庫(kù),新的數(shù)據(jù)存儲(chǔ)在被稱之為區(qū)塊(block)的容器中,并被添加到一個(gè)不可變的鏈(chain)中(因此被稱為區(qū)塊鏈(blockchain)),之前添加的數(shù)據(jù)也在該鏈中。對(duì)于比特幣或其它加密貨幣來(lái)說(shuō),這些數(shù)據(jù)就是一組組交易,不過(guò),也可以是其它任何類型的數(shù)據(jù)。
區(qū)塊鏈技術(shù)帶來(lái)了全新的、完全數(shù)字化的貨幣,如比特幣和萊特幣(Litecoin),它們并不由任何中心機(jī)構(gòu)管理。這給那些認(rèn)為當(dāng)今的銀行系統(tǒng)是騙局并將最終走向失敗的人帶來(lái)了自由。區(qū)塊鏈也革命性地改變了分布式計(jì)算的技術(shù)形式,如以太坊(Ethereum)就引入了一種有趣的概念:智能合約(smart contract)。
在這篇文章中,我將用不到 50 行的 Python 2.x 代碼實(shí)現(xiàn)一個(gè)簡(jiǎn)單的區(qū)塊鏈,我把它叫做 SnakeCoin。
不到 50 行代碼的區(qū)塊鏈
我們首先將從定義我們的區(qū)塊是什么開(kāi)始。在區(qū)塊鏈中,每個(gè)區(qū)塊隨同時(shí)間戳及可選的索引一同存儲(chǔ)。在 SnakeCoin 中,我們會(huì)存儲(chǔ)這兩者。為了確保整個(gè)區(qū)塊鏈的完整性,每個(gè)區(qū)塊都會(huì)有一個(gè)自識(shí)別的哈希值。如在比特幣中,每個(gè)區(qū)塊的哈希是該塊的索引、時(shí)間戳、數(shù)據(jù)和前一個(gè)區(qū)塊的哈希值等數(shù)據(jù)的加密哈希值。這里提及的“數(shù)據(jù)”可以是任何你想要的數(shù)據(jù)。
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()
現(xiàn)在我們有了區(qū)塊的結(jié)構(gòu)了,不過(guò)我們需要?jiǎng)?chuàng)建的是一個(gè)區(qū)塊鏈。我們需要把區(qū)塊添加到一個(gè)實(shí)際的鏈中。如我們之前提到過(guò)的,每個(gè)區(qū)塊都需要前一個(gè)區(qū)塊的信息。但問(wèn)題是,該區(qū)塊鏈中的第一個(gè)區(qū)塊在哪里?好吧,這個(gè)第一個(gè)區(qū)塊,也稱之為創(chuàng)世區(qū)塊,是一個(gè)特別的區(qū)塊。在很多情況下,它是手工添加的,或通過(guò)獨(dú)特的邏輯添加的。
我們將創(chuàng)建一個(gè)函數(shù)來(lái)簡(jiǎn)單地返回一個(gè)創(chuàng)世區(qū)塊解決這個(gè)問(wèn)題。這個(gè)區(qū)塊的索引為 0 ,其包含一些任意的數(shù)據(jù)值,其“前一哈希值”參數(shù)也是任意值。
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")
現(xiàn)在我們可以創(chuàng)建創(chuàng)世區(qū)塊了,我們需要一個(gè)函數(shù)來(lái)生成該區(qū)塊鏈中的后繼區(qū)塊。該函數(shù)將獲取鏈中的前一個(gè)區(qū)塊作為參數(shù),為要生成的區(qū)塊創(chuàng)建數(shù)據(jù),并用相應(yīng)的數(shù)據(jù)返回新的區(qū)塊。新的區(qū)塊的哈希值來(lái)自于之前的區(qū)塊,這樣每個(gè)新的區(qū)塊都提升了該區(qū)塊鏈的完整性。如果我們不這樣做,外部參與者就很容易“改變過(guò)去”,把我們的鏈替換為他們的新鏈了。這個(gè)哈希鏈起到了加密的證明作用,并有助于確保一旦一個(gè)區(qū)塊被添加到鏈中,就不能被替換或移除。
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)
這就是主要的部分。
現(xiàn)在我們能創(chuàng)建自己的區(qū)塊鏈了!在這里,這個(gè)區(qū)塊鏈?zhǔn)且粋€(gè)簡(jiǎn)單的 Python 列表。其第一個(gè)的元素是我們的創(chuàng)世區(qū)塊,我們會(huì)添加后繼區(qū)塊。因?yàn)?SnakeCoin 是一個(gè)極小的區(qū)塊鏈,我們僅僅添加了 20 個(gè)區(qū)塊。我們通過(guò)循環(huán)來(lái)完成它。
# 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)
讓我們看看我們的成果:

別擔(dān)心,它將一直添加到 20 個(gè)區(qū)塊
很好,我們的區(qū)塊鏈可以工作了。如果你想要在主控臺(tái)查看更多的信息,你可以編輯其完整的源代碼并輸出每個(gè)區(qū)塊的時(shí)間戳或數(shù)據(jù)。
這就是 SnakeCoin 所具有的功能。要使 SnakeCoin 達(dá)到現(xiàn)今的產(chǎn)品級(jí)的區(qū)塊鏈的高度,我們需要添加更多的功能,如服務(wù)器層,以在多臺(tái)機(jī)器上跟蹤鏈的改變,并通過(guò)工作量證明算法(POW)來(lái)限制給定時(shí)間周期內(nèi)可以添加的區(qū)塊數(shù)量。
如果你想了解更多技術(shù)細(xì)節(jié),你可以在這里查看最初的比特幣白皮書。
讓這個(gè)極小區(qū)塊鏈稍微變大些
這個(gè)極小的區(qū)塊鏈及其簡(jiǎn)單,自然也相對(duì)容易完成。但是因其簡(jiǎn)單也帶來(lái)了一些缺陷。首先,SnakeCoin 僅能運(yùn)行在單一的一臺(tái)機(jī)器上,所以它相距分布式甚遠(yuǎn),更別提去中心化了。其次,區(qū)塊添加到區(qū)塊鏈中的速度同在主機(jī)上創(chuàng)建一個(gè) Python 對(duì)象并添加到列表中一樣快。在我們的這個(gè)簡(jiǎn)單的區(qū)塊鏈中,這不是問(wèn)題,但是如果我們想讓 SnakeCoin 成為一個(gè)實(shí)際的加密貨幣,我們就需要控制在給定時(shí)間內(nèi)能創(chuàng)建的區(qū)塊(和幣)的數(shù)量。
從現(xiàn)在開(kāi)始,SnakeCoin 中的“數(shù)據(jù)”將是交易數(shù)據(jù),每個(gè)區(qū)塊的“數(shù)據(jù)”字段都將是一些交易信息的列表。接著我們來(lái)定義“交易”。每個(gè)“交易”是一個(gè) JSON 對(duì)象,其記錄了幣的發(fā)送者、接收者和轉(zhuǎn)移的 SnakeCoin 數(shù)量。注:交易信息是 JSON 格式,原因我很快就會(huì)說(shuō)明。
{
"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
}
現(xiàn)在我們知道了交易信息看起來(lái)的樣子了,我們需要一個(gè)辦法來(lái)將其加到我們的區(qū)塊鏈網(wǎng)絡(luò)中的一臺(tái)計(jì)算機(jī)(稱之為節(jié)點(diǎn))中。要做這個(gè)事情,我們會(huì)創(chuàng)建一個(gè)簡(jiǎn)單的 HTTP 服務(wù)器,以便每個(gè)用戶都可以讓我們的節(jié)點(diǎn)知道發(fā)生了新的交易。節(jié)點(diǎn)可以接受 POST 請(qǐng)求,請(qǐng)求數(shù)據(jù)為如上的交易信息。這就是為什么交易信息是 JSON 格式的:我們需要它們可以放在請(qǐng)求信息中傳遞給服務(wù)器。
$ pip install flask # 首先安裝 Web 服務(wù)器框架
1
$ pip install flask # 首先安裝 Web 服務(wù)器框架
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()
現(xiàn)在我們有了一種保存用戶彼此發(fā)送 SnakeCoin 的記錄的方式。這就是為什么人們將區(qū)塊鏈稱之為公共的、分布式賬本:所有的交易信息存儲(chǔ)給所有人看,并被存儲(chǔ)在該網(wǎng)絡(luò)的每個(gè)節(jié)點(diǎn)上。
但是,有個(gè)問(wèn)題:人們從哪里得到 SnakeCoin 呢?現(xiàn)在還沒(méi)有辦法得到,還沒(méi)有一個(gè)稱之為 SnakeCoin 這樣的東西,因?yàn)槲覀冞€沒(méi)有創(chuàng)建和分發(fā)任何一個(gè)幣。要?jiǎng)?chuàng)建新的幣,人們需要“挖”一個(gè)新的 SnakeCoin 區(qū)塊。當(dāng)他們成功地挖到了新區(qū)塊,就會(huì)創(chuàng)建出一個(gè)新的 SnakeCoin ,并獎(jiǎng)勵(lì)給挖出該區(qū)塊的人(礦工)。一旦挖礦的礦工將 SnakeCoin 發(fā)送給別人,這個(gè)幣就流通起來(lái)了。
我們不想讓挖新的 SnakeCoin 區(qū)塊太容易,因?yàn)檫@將導(dǎo)致 SnakeCoin 太多了,其價(jià)值就變低了;同樣,我們也不想讓它變得太難,因?yàn)槿绻麤](méi)有足夠的幣供每個(gè)人使用,它們對(duì)于我們來(lái)說(shuō)就太昂貴了。為了控制挖新的 SnakeCoin 區(qū)塊的難度,我們會(huì)實(shí)現(xiàn)一個(gè)工作量證明(Proof-of-Work)(PoW)算法。工作量證明基本上就是一個(gè)生成某個(gè)項(xiàng)目比較難,但是容易驗(yàn)證(其正確性)的算法。這個(gè)項(xiàng)目被稱之為“證明”,聽(tīng)起來(lái)就像是它證明了計(jì)算機(jī)執(zhí)行了特定的工作量。
在 SnakeCoin 中,我們創(chuàng)建了一個(gè)簡(jiǎn)單的 PoW 算法。要?jiǎng)?chuàng)建一個(gè)新區(qū)塊,礦工的計(jì)算機(jī)需要遞增一個(gè)數(shù)字,當(dāng)該數(shù)字能被 9 (“SnakeCoin” 這個(gè)單詞的字母數(shù))整除時(shí),這就是最后這個(gè)區(qū)塊的證明數(shù)字,就會(huì)挖出一個(gè)新的 SnakeCoin 區(qū)塊,而該礦工就會(huì)得到一個(gè)新的 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"
現(xiàn)在,我們能控制特定的時(shí)間段內(nèi)挖到的區(qū)塊數(shù)量,并且我們給了網(wǎng)絡(luò)中的人新的幣,讓他們彼此發(fā)送。但是如我們說(shuō)的,我們只是在一臺(tái)計(jì)算機(jī)上做的。如果區(qū)塊鏈?zhǔn)侨ブ行幕模覀冊(cè)鯓硬拍艽_保每個(gè)節(jié)點(diǎn)都有相同的鏈呢?要做到這一點(diǎn),我們會(huì)使每個(gè)節(jié)點(diǎn)都廣播其(保存的)鏈的版本,并允許它們接受其它節(jié)點(diǎn)的鏈。然后,每個(gè)節(jié)點(diǎn)會(huì)校驗(yàn)其它節(jié)點(diǎn)的鏈,以便網(wǎng)絡(luò)中每個(gè)節(jié)點(diǎn)都能夠達(dá)成最終的鏈的共識(shí)。這稱之為共識(shí)算法(consensus algorithm)。
我們的共識(shí)算法很簡(jiǎn)單:如果一個(gè)節(jié)點(diǎn)的鏈與其它的節(jié)點(diǎn)的不同(例如有沖突),那么最長(zhǎng)的鏈保留,更短的鏈會(huì)被刪除。如果我們網(wǎng)絡(luò)上的鏈沒(méi)有了沖突,那么就可以繼續(xù)了。
@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
我們差不多就要完成了。在運(yùn)行了完整的 SnakeCoin 服務(wù)器代碼之后,在你的終端可以運(yùn)行如下代碼。(假設(shè)你已經(jīng)安裝了 cCUL)。
1、創(chuàng)建交易
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、挖一個(gè)新區(qū)塊
curl localhost:5000/mine curl localhost:5000/mine
3、 查看結(jié)果。從客戶端窗口,我們可以看到。
對(duì)代碼做下美化處理,我們看到挖礦后我們得到的新區(qū)塊的信息:
{
"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"
}
大功告成!現(xiàn)在 SnakeCoin 可以運(yùn)行在多個(gè)機(jī)器上,從而創(chuàng)建了一個(gè)網(wǎng)絡(luò),而且真實(shí)的 SnakeCoin 也能被挖到了。
你可以根據(jù)你的喜好去修改 SnakeCoin 服務(wù)器代碼,并問(wèn)各種問(wèn)題了,好了本文暫時(shí)講解一下Python實(shí)現(xiàn)類似比特幣的加密貨幣區(qū)塊鏈的創(chuàng)建與交易實(shí)例。
下一篇我們將討論創(chuàng)建一個(gè) SnakeCoin 錢包,這樣用戶就可以發(fā)送、接收和存儲(chǔ)他們的 SnakeCoin 了
相關(guān)文章
python字典各式各樣操作從基礎(chǔ)到高級(jí)全面示例詳解
在Python中,字典(Dictionary)是一種強(qiáng)大而靈活的數(shù)據(jù)結(jié)構(gòu),它允許你存儲(chǔ)和檢索鍵值對(duì),本文將深入探討Python中各式各樣的字典操作,包括基本操作、高級(jí)操作以及一些實(shí)用的技巧,通過(guò)全面的示例代碼,將展示如何充分發(fā)揮字典在Python編程中的優(yōu)勢(shì)2023-12-12
python3用PIL把圖片轉(zhuǎn)換為RGB圖片的實(shí)例
今天小編就為大家分享一篇python3用PIL把圖片轉(zhuǎn)換為RGB圖片的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-07-07
python函數(shù)超時(shí)自動(dòng)退出的實(shí)操方法
在本篇文章里小編給大家整理的是一篇關(guān)于python函數(shù)超時(shí)自動(dòng)退出的實(shí)操方法,有需要的朋友們可以學(xué)習(xí)下。2020-12-12
python安裝模塊如何通過(guò)setup.py安裝(超簡(jiǎn)單)
這篇文章主要介紹了python安裝模塊如何通過(guò)setup.py安裝,安裝方法其實(shí)很簡(jiǎn)單,感興趣的朋友跟隨腳本之家小編一起看看吧2018-05-05
淺談matplotlib中FigureCanvasXAgg的用法
這篇文章主要介紹了淺談matplotlib中FigureCanvasXAgg的用法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-06-06
python開(kāi)發(fā)之str.format()用法實(shí)例分析
這篇文章主要介紹了python開(kāi)發(fā)之str.format()用法,結(jié)合實(shí)例形式較為詳細(xì)的分析了str.format()函數(shù)的功能,使用方法與相關(guān)注意事項(xiàng),代碼包含詳盡的注釋說(shuō)明,需要的朋友可以參考下2016-02-02
linux環(huán)境下安裝python虛擬環(huán)境及注意事項(xiàng)
這篇文章主要介紹了linux環(huán)境下安裝python虛擬環(huán)境,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-01-01
Python3實(shí)現(xiàn)簡(jiǎn)單可學(xué)習(xí)的手寫體識(shí)別(實(shí)例講解)
下面小編就為大家?guī)?lái)一篇Python3實(shí)現(xiàn)簡(jiǎn)單可學(xué)習(xí)的手寫體識(shí)別(實(shí)例講解)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-10-10

