【发布时间】:2018-03-14 01:47:36
【问题描述】:
我正在努力在 python 中重新创建一个区块链,虽然我的大部分代码都可以正常工作,但我不知道为什么这部分不可用。编码在 3.5 中是如何工作的?
原文:
from flask import Flask
from flask import request
import json
import requests
import hashlib as hasher
import datetime as date
node = Flask(__name__)
# Define what a Snakecoin block is
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()
# Generate genesis block
def create_genesis_block():
# Manually construct a block with
# index zero and arbitrary previous hash
return Block(0, date.datetime.now(), {
"proof-of-work": 9,
"transactions": None
}, "0")
# A completely random address of the owner of this node
miner_address = "q3nf394hjg-random-miner-address-34nf3i4nflkn3oi"
# This node's blockchain copy
blockchain = []
blockchain.append(create_genesis_block())
# Store the transactions that
# this node has in a list
this_nodes_transactions = []
# Store the url data of every
# other node in the network
# so that we can communicate
# with them
peer_nodes = []
# A variable to deciding if we're mining or not
mining = True
@node.route('/txion', methods=['POST'])
def transaction():
# 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'].encode('ascii','replace'))
print "TO: {}".format(new_txion['to'].encode('ascii','replace'))
print "AMOUNT: {}\n".format(new_txion['amount'])
# Then we let the client know it worked out
return "Transaction submission successful\n"
@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 i in range(len(chain_to_send)):
block = chain_to_send[i]
block_index = str(block.index)
block_timestamp = str(block.timestamp)
block_data = str(block.data)
block_hash = block.hash
chain_to_send[i] = {
"index": block_index,
"timestamp": block_timestamp,
"data": block_data,
"hash": block_hash
}
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 isn't ours,
# then we stop mining and set
# our chain to the longest one
blockchain = longest_chain
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"
node.run()
我的版本如下。我收到的错误是:
“文件“davecoin.py”,第 113 行,在我的 last_proof = int(last_block.data['proof-of-work']) TypeError: 字符串索引必须是整数"
from flask import Flask
from flask import request
import json
import requests
import hashlib as hasher
import datetime as date
node = Flask(__name__)
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).encode('utf-8') + str(self.timestamp).encode('utf-8') + str(self.data).encode('utf-8') + str(self.previous_hash).encode('utf-8'))
return sha.hexdigest()
def create_genesis_block():
# Manually create the first block of davecoin. Index = 0.
return Block(0, date.datetime.now(), {
"proof-of-work": 7,
"transactions": None
}, "0")
miner_address = "34h5jk34h5-miner-address-k5j34h5634"
this_nodes_transactions = []
@node.route('/txion', methods=['POST'])
def transaction():
# 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'].encode('ascii','replace')))
print("TO: {}".format(new_txion['to'].encode('ascii','replace')))
print("AMOUNT: {}\n".format(new_txion['amount']))
# Then we let the client know it worked out
return "Transaction sent successfully.\n"
def next_block(last_block):
this_index = last_block.index + 1
this_timestamp = date.datetime.now()
this_data = "Davecoin Block " + str(this_index)
this_hash = last_block.hash
return Block(this_index, this_timestamp, this_data, this_hash)
blockchain = [create_genesis_block()]
previous_block = blockchain[0]
blocks_to_add_after_genesis = 15
for i in range(0, blocks_to_add_after_genesis):
block_to_add = next_block(previous_block)
blockchain.append(block_to_add)
previous_block = block_to_add
print("Block #" + str(block_to_add.index) +" has been added to the blockchain.")
print("Hash: "+ block_to_add.hash)
@node.route('/blocks', methods=['GET'])
def get_blocks():
chain_to_send = blockchain
#Convert blocks to dictionary for json
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
}
chain_to_send = json.dumps(chain_to_send)
return chain_to_send
def find_new_chains():
other_chains = []
for node_url in peer_nodes:
block = requests.get(node_url + "/blocks").content
#convert json to python dictionary
block = json.loads(block)
other_chains.append(block)
return other_chains
def consensus():
# get blocks from other nodes
other_chains = find_new_chains()
longest_chain = blockchain
for chain in other_chains:
if len(longest_chain) < len(chain):
longest_chain = chain
blockchain = longest_chain
def proof_of_work(last_proof):
incrementor = last_proof + 1
while not (incrementor % 7 == 0 and incrementor % last_proof == 0):
incrementor += 1
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
proof = proof_of_work(last_proof)
# Reward miner for finding block
this_nodes_transactions.append(
{ "from": "network", "to": miner_address, "amount": 1 }
)
# Gather data for 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[:] = []
# Create 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"
node.run()
【问题讨论】:
-
这是什么? Python 2 还是 Python 3?不能两者兼有。
-
我的是 Python 3.5。不知道如何找到原始版本,但这里是github code
-
您确定为第二个程序复制了正确的文本吗? 它们完全相同。
-
完全确定。我将两者都与代码差异工具进行了比较,以确保我没有遗漏任何内容。我仍然是 Python 的初学者,但实际上我唯一能想到的是这可能是一个问题,因为它们是不同版本的 python。
-
等一下……你知道代码示例是一样的吗?你有什么问题?
标签: python json python-3.x flask