B8 m5 y; l: I/ z. _* L! F
的一个奇迹。但是,到底区块链是什么呢? 我们将通过动手实现一个迷你的区块链来帮你
+ z8 i6 E$ Q) q+ s
真正理解区块链技术的核心原理。python源代码保存在Github。
1 z/ \& Z \8 Z' H% f0 ~. K
区块链
% k/ P, \# c5 p- a. W0 W1 t
区块链是一个公开的数字账本,它按时间顺序记录比特币或其他加密货币发生的交易。. _4 M: U; G. Z; x% g' v
" ~+ p2 ^( A+ p9 k& D$ [
更一般的讲,区块链是一个公共数据库,新的数据将存储在一个被称为”块“的容器中,然后0 t& T# A' H8 X+ |/ k ]7 [) T' {
5 v- P, q7 Y) Z, Z
块会被添加到一个不可篡改的链,因此被称为”区块链“。当我们谈到比特币或其他加密货币时,这些数据指的是交易记录。当然,你可以将任何类型的数据存入区块链。
区块链技术已经催生了全新的、完全数字化的货币,如比特币和莱特币,这些货币并不是由
; g/ D0 K( i' c( P! @3 d3 O
中央政府发行或管理的。这一技术给那些不认可当前银行系统人带来了新的自由。. r! h: L0 G$ g" a
6 U8 F$ u p9 \( _ z' {5 A
区块链同时也为分布式计算带来了革命性的创新,例如,以太坊区块链引入了一些有趣的概念,比如智能合约。- b; l p/ \) h% s( C
# ]9 R$ m! [1 d# V, V8 k: |: D/ o
在本文中,我将用不到50行的Python 2代码来做一个简单的区块链。我称它为SnakeCoin。7 m0 ]6 |9 H& u/ J
: p& j. q% B6 F+ z2 V
我们首先将定义“块”的数据结构。在区块链中,每个块都存储一个时间戳和一个可选地索引。在SnakeCoin中,我们将把两者都存储起来。为了确保整个区块链的完整性,每个块都有一个用于自我标识的哈希。1 l9 @' j1 z+ G8 l) n9 U
与比特币一样,每个块的哈希将是对块索引、时间戳、数据和前块哈希计算出的加密哈希值。其中你可以在数据中保存任何内容。( l% R+ e( l4 s0 @
- import hashlib as hasher
- class Block:
- def __init__(self, index, timestamp, data, previous_hash):
- self.index = index
- self.timestamp = timestamp
- self.data = data8 @! k! W+ B1 d2 n5 I- t
- self.previous_hash = previous_hash
- self.hash = self.hash_block()* K% `( e$ a. K
- def hash_block(self):
- sha = hasher.sha256()
- sha.update(str(self.index) +' G* R! _! E: u" c, O! m7 j$ h( ^% J
- str(self.timestamp) + }, \' R8 m' Y- Q1 Y; Y
- str(self.data) +! S3 u1 f1 l* b; C
- str(self.previous_hash))
- return sha.hexdigest()
太棒了!现在有了块的数据结构,不过我们的目的是实现一个区块链,所以需要将块添加到一个链中。
如前所述,每个块都需要前一个块的信息。但是按照这个说法就会有一个问题,如何添加区块链的第一个块?2 e z: e* p8 {7 h O
嗯,链中的第一个块,或者说创世块,是一个特殊的块。在很多情况下需要手动添加或者采用单独的处理逻辑。
( L" g# W* i2 p( R4 x- G/ e7 f
下面将创建一个函数,它的作用就是简单地返回一个创世块。这个块的索引为0:8 e# \1 Q- C% F8 q, Q: v
/ r2 ^; n! c$ e; E+ F, q4 j
- import datetime as date3 [' A M% y* ?0 T6 _# `( p1 r* s G
- def create_genesis_block():
- # Manually construct a block with
- # index zero and arbitrary previous hash
- return Block(0, date.datetime.now(), "Genesis Block", "0")
现在已经创建好了创世块,接下来需要一个函数,以便在区块链中生成后续的块。这个函数将: w8 [ ]. h2 I+ z M) ^. \
" D2 b: G6 g: I) `5 Q
以链中的前一个块为参数,生成并返回新块。当新块的哈希值计算利用了来自前面块的信息时,区块链的完整性就会随着每个新块而增加。如果不这样的话,外部组织就更容易“改变过去”,用他们伪造的块来取代链中的块。这一系列的块哈希可以作为加密的证据,有助于确保一旦将块添加到区块链,它就不能被替换或删除。% i" m0 c; T, H T
- def next_block(last_block):
- this_index = last_block.index + 1
- this_timestamp = date.datetime.now()3 |8 R4 E' L) | B9 S
- this_data = "Hey! I'm block " + str(this_index)) |% Z* R" T" W5 r2 c
- this_hash = last_block.hash# v7 S! x3 g" B' Z
- return Block(this_index, this_timestamp, this_data, this_hash)
7 L6 a( G1 {( {# _; W( G. x
大部分的重要工作已经完成,现在可以创建区块链了!在我们的实现中,区块链就是一个简单的Python列表。列表的第一个元素是创世块。当然,我们还需要添加后续的块。因为SnakeCoin可以说是世界上最迷你的区块链,我们在这里只添加20个新的块。可以用for循环来生成新块:4 Y' P2 b' \+ z0 m
! r7 @4 q% a3 ~
- # 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 U% Y2 H" X/ a) K9 V$ Q
- # 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)3 E" t7 d. p1 G. l
- blockchain.append(block_to_add)3 s, U/ a% t6 [1 X, j
- previous_block = block_to_add4 M8 g: ^+ k+ l7 y) T
- # Tell everyone about it!
- print "Block #{} has been added to the blockchain!".format(block_to_add.index). L; x1 }1 E# ]
- print "Hash: {}\n".format(block_to_add.hash)
下面来测试一下我们的区块链。% j; c, q" ]$ ~! G# [9 m
跑通了!如果希望在控制台中查看更多信息,可以编辑源文件并打印每个块的时间戳或
块中的数据。
6 h' n* B# r- N2 @) R* U
这就是SnakeCoin的全部内容。为了使SnakeCoin能够达到生产级区块链的规模,还需要添加更多的功能,比如用来跟踪多个节点上区块链变化的P2P服务层,以及限制在一定时间内可以添加到链中的新块数量的工作量证明算法。6 E7 R H# B5 }- W5 S7 K