编译自:3359 medium.com/crypto-current/let-build-the-TiNi est-区块链-e70965a248b作者:Gerald Nash
译者:星宇。王
尽管有些人认为区块链是迟早问题的解决方案,但毫无疑问,这项创新技术是计算机技术的奇迹。那么,区块链到底是什么?
00-1010用比特币或其他加密货币按时间顺序公开记录交易的数字账本。
更通俗的说,它是一个开放的数据库。新数据存储在一个称为块的容器中,并添加到一个不可变的链中(因此称为区块链)。先前添加的数据也在链中。对于比特币或其他加密货币,这些数据是交易组,但它们也可以是任何其他类型的数据。
区块链技术带来了全新的、完全数字化的货币,比如比特币和莱特币,它们不受任何一个中心机构的管理。这给那些认为今天的银行系统是一个骗局并最终会失败的人带来了自由。区块链也彻底改变了分布式计算的技术形式。比如以太坊就推出了一个有趣的概念:智能合约。
在本文中,我将使用不到50行的Python 2.x代码实现一个简单的区块链,我称之为SnakeCoin。
区块链
我们将首先定义我们的块是什么。在区块链中,每个块都与时间戳和可选索引一起存储。在SnakeCoin中,我们将存储这两者。为了保证整个区块链的完整性,每个块将有一个自我识别的哈希值。比如在比特币中,每个块的hash是该块的索引、时间戳、数据和前一个块的hash值的加密hash值。这里说的“数据”可以是你想要的任何数据。
将hashlib作为hasher类块导入:
def __init__(自身,索引,时间戳,数据,previous_hash):
self.index=索引
self.timestamp=时间戳
self.data=数据
self.previous _ hash=previous _哈希
self.hash=self.hash_block()
def hash_block(自身):
sha=hasher.sha256()
sha.update(str(self.index)
str(自身时间戳)
str(自我数据)
str(self.previous_hash))
返回sha.hexdigest()
很好,现在我们有了一个块结构,但是我们需要创建一个区块链。我们需要向实际的链中添加块。正如我们之前提到的,每个块都需要前一个块的信息。但问题是,区块链的第一个街区在哪里?嗯,这第一块,也被称为创造块,是一个特殊的块。在许多情况下,它是手动添加的或者通过独特的逻辑添加的。
我们将创建一个函数来简单地返回一个创建块来解决这个问题。这个块的索引是0,包含了一些任意的数据值,它的“上一个哈希值”参数也是任意的。
将日期时间作为日期定义create_genesis_block():导入
#手动构造一个块
#索引零和任意先前散列
返回块(0,date.datetime.now(),\'创世纪块\',\' 0 \')
既然我们可以创建创建块,我们需要一个函数来生成这个区块链中的后续块。该函数将采集链中的前一个块作为参数,为要生成的块创建数据,并返回带有相应数据的新块。新块的散列值来自前一个块,因此每个新块都提高了区块链的完整性。如果我们不这样做,外部参与者很容易“改变过去”,用他们的新链条替换我们的链条。该散列链用作加密的证明,并且有助于确保一旦块被添加到链中,它就不能被替换或移除。
def next _ block(last _ block): this _ index=last _ block . index 1
this _ timestamp=date . datetime . now()
this_data=\'嘿!我是block \' str(this_index)
this_hash=last_block .哈希
返回块(this_index,this_timestamp,this_data,this_hash)
这是主要部分。
现在我们可以创造我们自己的区块链了!在这里,这个区块链是一个简单的Python列表。第一个元素是我们的创建块,我们将添加后续的块。因为SnakeCoin是一个很小的区块链,我们只增加了20个街区。我们通过流通来做。
#创建区块链并添加创世纪块区块链=[create_genesis_block()]
上一个区块=区块链[0]
#我们应该向链中添加多少块
#在创世纪街区之后
要添加的块数=20
#向链中添加块
对于范围(0,要添加的块数):内的I
块添加=下一个块(上一个块)
区块链.追加(block_to_add)
前一个块=块添加
#告诉所有人吧!
print \'Block #{}已添加到区块链!\'。格式(块添加索引)
打印“Hash: {}\\n”。格式(块添加.散列)
别担心,会一直加到20块。
很好,我们的区块链可以工作。如果想在主控制台查看更多信息,可以编辑其完整的源代码[2]并输出每个块的时间戳或数据。
这就是蛇币的功能。要让SnakeCoin达到今天产品级区块链的高度,我们需要增加更多的功能,比如服务器层,跟踪多台机器上的链变化,通过工作负载证明算法(POW)[3]限制给定时间段内可以增加的块数。
如果想了解更多技术细节,可以查看比特币白皮书原文[5]这里[4]。
00-1010这个小小的区块链极其简单,自然也相对容易完成。但是它的简单也带来了一些缺陷。首先,SnakeCoin只能在单机上运行,所以远谈不上分布式,更谈不上去中心化。其次,可以像在主机上创建Python对象并将其添加到列表中一样快速地将块添加到区块链中。在我们简单的区块链中,这不是问题,但如果我们希望SnakeCoin成为真正的加密货币,我们需要控制在给定时间内可以创建的块(和硬币)的数量。
从现在开始,SnakeCoin中的“数据”将是交易数据,每个区块的“数据”字段将是一些交易信息的列表。那么我们来定义一下“交易”。每个“交易”都是一个JSON对象,它记录了硬币的发送者和接收者以及被转移的SnakeCoin的数量。注意:交易信息是JSON格式的,我很快会解释原因。
{ \' from \' : \' 71238 uqirbfh 894-random-public-key-a-alkjdflakjfewn 204 ij \',
到\' : \' 93j 4 ivnqiopvh 43-random-public-key-b-qjrgvnoeirbnferinfo \',
金额\' : 3
}
现在我们知道了交易信息的样子,我们需要一种方法将它添加到我们区块链网络中的一台计算机(称为节点)上。为此,我们将创建一个简单的HTTP服务器,以便每个用户都可以让我们的节点知道发生了新的事务。节点可以接受POST请求,请求数据就是上面的事务信息。这就是事务信息采用JSON格式的原因:我们需要将它们放在请求信息中并传输到服务器。
$ pip安装flask #首先从flash安装Web服务器框架从flash导入flash从flash导入请求。
node=Flask(__name__)
#存储以下交易
#此节点在列表中有
this_nodes_transactions=[]
@node.route(\'/txion \',methods=[\'POST\'])
定义交易():
if request.method==\'POST\':
#对于每个新的发布请求,
#我们提取交易数据
new_txion=request.get_json()
#然后我们将交易添加到我们的列表中
this_nodes_transactions.append(新事务)
#因为交易成功
#已提交,我们将其记录到控制台
打印“新交易记录”
打印“从: {}”。格式(new_txion[\'from\'])
打印“收件人: {}”。格式(new_txion[\'to\'])
打印\"金额: {}\\n .格式(new_txion[\'amount\'])
#然后我们让客户知道它成功了
返回\"交易提交成功\\n \"
node.run()
真棒!现在我们有了一种保存用户彼此发送蛇币的记录的方式。这就是为什么人们将区块链称之为公共的、分布式账本:所有的交易信息存储给所有人看,并被存储在该网络的每个节点上。
但是,有个问题:人们从哪里得到蛇币呢?现在还没有办法得到,还没有一个称之为蛇币这样的东西,因为我们还没有创建和分发任何一个币。要创建新的币,人们需要\"挖\"一个新的蛇币区块。当他们成功地挖到了新区块,就会创建出一个新的蛇币,并奖励给挖出该区块的人(矿工)。一旦挖矿的矿工将蛇币发送给别人,这个币就流通起来了。
我们不想让挖新的蛇币区块太容易,因为这将导致蛇币太多了,其价值就变低了;同样,我们也不想让它变得太难,因为如果没有足够的币供每个人使用,它们对于我们来说就太昂贵了。为了控制挖新的蛇币区块的难度,我们会实现一个工作量证明[6](功效证明)算法。工作量证明基本上就是一个生成某个项目比较难,但是容易验证(其正确性)的算法。这个项目被称之为\"证明\",听起来就像是它证明了计算机执行了特定的工作量。
在蛇币中,我们创建了一个简单的啪算法。要创建一个新区块,矿工的计算机需要递增一个数字,当该数字能被9(\"蛇币\"这个单词的字母数)整除时,这就是最后这个区块的证明数字,就会挖出一个新的蛇币区块,而该矿工就会得到一个新的蛇币。
# .区块链#.块类定义
miner _ address=\' q3nf 394 hjg-random-miner-address-34nf 3 i4 NFL kn 3 oi \'
极好的工作证明(最后证明):
#创建一个变量,我们将使用它来查找
#我们的下一个工作证明
incrementor=last_proof 1
#保持递增增量,直到
#它等于一个可被9整除的数
#以及之前工作的证明
#链条中的块
而不是(incrementor % 9==0且增量或% last _ proof==0):
incrementor=1
#一旦找到那个号码,
#我们可以把它作为证据退回去
#我们的工作
返回增量
@node.route(\'/mine \',methods=[\'GET\'])
def mine():
#获得工作的最后证明
last_block=区块链[伦(区块链)- 1]
last_proof=last_block.data[\'工作证明]
#找到工作的证明
#当前正在开采的区块
#找到工作证明
证明=工作证明(最后证明)
#一旦我们找到有效的工作证明,
#我们知道我们可以开采一个街区
#我们通过添加交易来奖励矿工
this_nodes_transactions.append(
{ \'从\' : \'网络\',\'到:矿工_地址,\'金额\' : 1 }
)
#现在我们可以收集所需的数据了
#创建新块
新块数据={
工作证明:证明,
事务\' :列表(这_节点_事务)
}
新块索引=最后块索引一
新块时间戳=此时间戳=日期。日期时间。现在()
最后一个块哈希=最后一个块哈希
#空交易列表
this _ nodes _ transactions[:]=[]
#现在创建
#新街区!
mined_block=Block(
新块索引,
新块时间戳,
新块数据,
最后一个块散列
)
blockchain.append(mined_block)
#让客户知道我们开采了一个区块
返回json.dumps({
索引\' :新块索引,
时间戳:字符串(新块时间戳),
数据\' :新块数据,
哈希\' :最后一个块哈希
})\"\\ n \"
现在,我们可以控制在特定时间段内挖出的块数,我们给网络中的人新的硬币来互相发送。但是我们说过,我们只在电脑上做。如果区块链是分散的,我们如何确保每个节点都有相同的链?为此,我们将让每个节点广播其(保存的)链的版本,并允许它们接受其他节点的链。然后,每个节点会检查其他节点的链,使网络中的每个节点达到最终链的共识。这叫做[7](共识算法[7])。
我们的共识算法很简单:如果一个节点的链与其他节点的链不同(比如有冲突),那么将保留最长的链,删除较短的链。如果我们网络上的链没有冲突,那么我们可以继续。
@node.route(\'/blocks \',methods=[\' GET \'])def GET _ blocks():
连锁发送=区块链
#将我们的积木转换成字典
#所以我们可以稍后将它们作为json对象发送
对于chain_to_send:中的块
block_index=str(block.index)
block _时间戳=str(block.timestamp)
块数据=字符串(块数据)
block_hash=block .哈希
block={
索引\' : block_index,
时间戳\' :块_时间戳,
数据\' :块_数据,
哈希\' :块_哈希
}
#把我们的项链送给任何需要它的人
chain _ to _ send=JSON . dump(chain _ to _ send)
返回链发送
def find_new_chains():
#获得每个人的区块链
#其他节点
other_chains=[]
对于对等节点中的节点URL 3360
#使用Get请求获取它们的链
block=requests . get(node _ URL \'/blocks \')。内容
#将JSON对象转换为Python字典
block=json.loads(block)
#添加到我们的列表中
other_chains.append(块)
返回其他_链
def共识():
#从其他节点获取块
other_chains=find_new_chains()
#如果我们的链条不是最长的,
#然后我们存储最长的链
最长_链=区块链
用于其他链中的链_链:
if len(最长链)len(链):
最长链=链
#如果最长的链条不是我们的,
#然后我们把链条设到最长
区块链=最长_链
我们快完成了。在运行完整的SnakeCoin服务器代码[8]之后,您可以在您的终端上运行以下代码。(假设你已经安装了cCUL)。
不到 50 行代码的区块链
curl \' localhost :5000/txion \' \\-H \' Content-type : application/JSON \' \\
-d \'{\'from\': \'akjflw \',\' to\':\'fjlakdj \',\' amount\': 3} \'
让这个极小区块链稍微变大些
卷曲localhost :5000/mine
1、创建交易
美化代码,我们看到挖掘后得到的新块的信息:
{\'index\': 2,
数据\' : {
交易\' : [
{
至\' : \'fjlakdj \':
金额\' : 3,
从\' : \'akjflw \'
},
{
到\' : \' q3nf 394 hjg-random-miner-address-34 nf3 i4 nflkn 3 oi \',
金额\' : 1,
来自“:”网络
}
],
工作证明\' : 36
},
哈希\' : \' 151 edd 3 ef 6 af 2e 7 EB 8272245 cb8ea 91 B4 ecfc 3 e 60 af 22d 8518 ef 0 BBA 8 B4 a6b 18 \',
时间戳\' : \' 2017-07-23 11:23:10.140996
}
你完了!现在SnakeCoin可以在多台机器上运行,这样就形成了一个网络,真正的SnakeCoin就可以挖出来了。
可以根据喜好修改SnakeCoin服务器代码,问各种问题。
在下一篇文章中(LCTT翻译:截至本文翻译时,作者尚未撰写下一篇文章),我们将讨论创建一个SnakeCoin钱包,以便用户可以发送、接收和存储他们的snake coin。