python写的创世区块
这是篇技术文,我们会用Python一步步搭建一个完整的区块链。不过,在此之前,咱们还是先说说你什么你该学习如何从零搭建一个区块链。
有人认为区块链是一个「等待问题」的解决方案,但毫无疑问,这项新技术是一项计算的奇迹。不过,区块链究竟是什么?
我们可以把区块链看做一个公共数据库,其中新数据存储在一个称为区块的容器中,然后被添加到一条不可更改的链上(也就是区块链),同时,链上保存着之前的数据记录。这些数据是比特币或其他加密货币之前的交易信息,被分门别类地添加到链上
区块链的诞生,引发了以比特币和莱特币为首的加密货币的崛起。由于加密货币的去中心化属性。对于那些本来就不信任银行系统的人来说,简直是带来了新世界。此外,区块链还给分布式计算带来了革新,出现了很多诸如以太坊这样的新平台,也引入了智能合约的概念。
俗话说实践出真知。接下来,我将用不超过50行的 Python 代码创建一个简单的区块链,并给它取了一个名字叫SnakeCoin。以此帮助大家理解区块链。
一起动手创建一个极简的区块链
首先,我们先对区块链进行定义。在区块链中,每个区块上都有一个时间戳,有时还会有一个索引。在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()
完成了!区块链的基本框架就这样搭建出来了。考虑到我们要做的是「区块链」,因此,我们还需要往链上加区块。我之前提到过,其中每一个区块需要包含链上前一个区块的哈希值。你可能会问,区块链的第一个区块是怎么出现的呢??当然,作为第一个区块(也叫创世区块),自然很特殊。在多数情况下,它是手动地被添加到链上,或者通过独特的逻辑将它添加到链上。
下面,我们就简单一点,通过创建一个函数,让它返回一个创世区块。这个区块的索引为0,此外,它所包含的数据以及前一个区块的哈希值都是一个任意的值。创建创世区块的函数代码如下:
import datetime as date
def create_genesis_block():
# Manually construct ablock with
# index zero andarbitrary previous hash
return Block(0, date.datetime.now(), "GenesisBlock", "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
returnBlock(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
# Addblocks to the chain
for iin range(0, num_of_blocks_to_add):
block_to_add= next_block(previous_block)
blockchain.append(block_to_add)
previous_block = block_to_add
# Telleveryone about it!
print "Block #{} has been added to theblockchain!".format(block_to_add.index)
print "Hash:{}\n".format(block_to_add.hash)
跑一下上边的代码,结果如下:
从上面代码可以看出,区块链已经跑起来了,如果你想在控制台看到更多信息,可以修改源代码文件,将每一个区块的时间戳或者数据打印出来。
上面讲到的区块链是非常简洁的,区块的创造也相对简单。但是如果要使SnakeCoin成为一个真正的加密货币,我们需要控制每次产出的区块数量和币的数量。
为“瘦小的”区块链“增肥”
SnakeCoin上的数据从交易中产生,每个区块上的数据均由一系列交易组成。我们将交易定义为:每笔交易均为一个JSON对象,这个JSON对象包括币的发送者、接受者和交易数量。
注意:下文我们会谈到为什么交易是以JSON格式保存的。
{
"from":"71238uqirbfh894-random-public-key-a-alkjdflakjfewn204ij",
"to":"93j4ivnqiopvh43-random-public-key-b-qjrgvnoeirbnferinfo",
"amount": 3
}
在了解了什么是交易之后,我们需要一个方法,将交易添加到之前的区块链网络节点中(这些节点由普通的电脑组成),为此,我们将创造一个简单的HTTP服务器,便于交易用户将交易信息上报节点。一个节点能够接收一个带有交易信息的POST请求来作为请求主体。这就是为什么交易是JSON格式的原因。我们需要将它们传送到服务器的请求主体中。
首先需要安装一个网络服务器框架:
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 submissionsuccessful\n"
node.run()
这样我们就完成了对用户间互相发送SnakeCoin信息的保存。这就是为什么大家将区块链称为公共账本和分布式账本的原因:所有交易存储在网络内的每个节点之中,重要的是,对所有用户是可见的。
但是,问题来了,我们从哪里获取SnakeCoin呢?(目前)哪儿都不行!实际上SnakeCoin是不存在的。我们需要挖掘新的SnakeCoin区块把它创造出来,一个新的区块被挖出后,一个SnakeCoin就会产生出来,作为奖励给与挖矿者。矿工将SnakeCoin转给其他人之后,币就开始流通了。
我们不希望挖出SnakeCoin的过程过于简单,因为会产生太多的SnakeCoin,而且会变得越来越不值钱。同时,我们也不希望这个过程特别难,因为这样的话,SnakeCoin的数量不足,这会导致币价过高,同时流通缓慢。我们通过工作量证明算法控制挖矿的难度。工作证明算法本质上是生成一种难以创建但易于验证的算法。就像字面意思一样,它就是证明一个节点(计算机)完成了多少工作量。
在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 wewill 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 andincrementor % 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 blockso
# we reward the miner by addinga transaction
this_nodes_transactions.append(
{ "from":"network", "to": miner_address, "amount": 1 }
)
# Now we can gather the dataneeded
# 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.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 GETrequest block = requests.get(node_url +"/blocks").content # Convert the JSON object to aPython 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服务器代码,到这里我们离大功告成就只差一步了。运行完snakecoin的代码后,在终端里运行以下命令(假设你用的是cURL)。
1. 创建一个交易。
curl"localhost:5000/txion" \
-H "Content-Type:application/json" \
-d '{"from": "akjflw","to":"fjlakdj", "amount": 3}'
2. 开采新的区块。
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-2311:23:10.140996"
}
大功告成! 我们自己创建了一条完整的区块链!现在 SnakeCoin 可以在多台节点上运行,SnakeCoin也可以被开采了。
怎么样?你的区块链做好了吗?欢迎把反馈写在留言区,跟营长一起讨论。
原文链接:
第一部分:
https://medium.com/crypto-currently/lets-build-the-tiniest-blockchain-e70965a248b第二部分:
https://medium.com/crypto-currently/lets-make-the-tiniest-blockchain-bigger-ac360a328f4d
python写的创世区块相关推荐
- 身价百亿的中本聪是如何打造出“创世区块”的?
点击上方"CSDN",选择"置顶公众号" 关键时刻,第一时间送达! 随着比特币逐渐被主流认识并接受,它的基础安全模型也以"挖矿"的形象出现在 ...
- 教你使用Python从零开始搭建一个区块链项目!
你是否会和我一样,对加密数字货币底层的区块链技术非常感兴趣,特别想了解他们的运行机制. 但是学习区块链技术并非一帆风顺,我看多了大量的视频教程还有各种课程,最终的感觉就是真正可用的实战课程太少. 我喜 ...
- 走进区块链(一):用Python实现第一个区块链小程序
源代码链接:https://github.com/dvf/blockchain 大家好!这是本人踩在巨人的肩膀上,实现的第一个区块链小程序.在实现代码的过程中,我遇到了很多问题,不过,幸好都解决了.在 ...
- 我的世界源代码python_用Python写的游戏《我的世界》 还原初代世界
之前在某音上刷到,有位程序员小哥哥用Python写出了<我的世界>游戏,这个游戏大家都是耳熟能详的 起初是在国外有个叫fogleman的开发者就用Python做了这样的一件事--自制< ...
- 从0到1简易区块链开发手册V0.3-数据持久化与创世区块
Author: brucefeng Email: brucefeng@brucefeng.com 编程语言:Golang 1.BoltDB简介 Bolt是一个纯粹Key/Value模型的程序.该项目的 ...
- 我的世界python写游戏_快来试试Python写的游戏《我的世界》
<我的世界 Minecraft>大家应该都听说过,但你有没有想过自己用Python写一个这样的游戏呢?太难.太复杂了?也许吧,但是不试一试你怎么知道能不能成呢? 国外有位叫fogleman ...
- NFT火了,12岁男孩用 Python 写了一个「表情包」,赚了250万
梦晨 发自 凹非寺 量子位 报道 | 公众号 QbitAI 12岁男孩在暑假里画了一系列画,在区块链上以NFT的形式出售,赚到的虚拟货币价值相当于250万人民币! 这些画倒也不是什么精致的艺术品,只是 ...
- 如何用 Python 快速开发一个区块链数据结构?
作者 | arjuna sky kok 整理 | Aholiab 出品 | 区块链大本营(blockchain_camp) 根据IEEE此前的一项调查,Python已成为最受开发者欢迎的语言之一.由于 ...
- [译] 如何用 Python 写一个 Discord 机器人
原文地址:How to write a Discord bot in Python 原文作者:Junpei Shimotsu 译文出自:掘金翻译计划 本文永久链接:github.com/xitu/go ...
最新文章
- Auto ML自动调参
- MyBatis批量增删改的另外一种思路(推荐)
- setting.xml的mirror、mirrorOf和pom.xml的repositories、repository的关系关联*
- spring_Spring Boot登录选项快速指南
- python每天学习30分钟系列
- 自制服务器语言,修改系统语言,NTF服务器
- 国内第一本项目管理的实践书籍——《IT项目管理那些事儿》
- 做了44年保洁员,一生只会5个字,她却成为香港大学院士
- P1078 文化之旅
- [置顶]理解Linux系统负荷
- conda 升级_jupyter notebook升级体验!笔记本神器—Jupyter Lab
- AOP Aspect Oriented Programming
- python文本框与数据库的关联_Python 基于python+mysql浅谈redis缓存设计与数据库关联数据处理...
- 【动态规划】区间dp: P1063能量项链
- 2021秋招IC验证面经-ARM中国/中科芯/飞腾/地平线/中兴
- java文件内容比较_怎么用JAVA技术编写一个两文件内容比较的程序?
- SwiftUI 7GUIs编程基准之 05 CRUD 增删改查 掌握分离域和表示逻辑,管理变异,构建非平凡的布局。(教程含源码)
- iOS系统自带指纹验证的使用
- DMA工作原理-STM32 DMA和ARM9 DMA,彻底理解DMA
- Web前端jQuery实现监控大屏数字滚动