引用“50行python代码的区块链SnakeCoin”,Gerald NashJul 16, 2017 原文见底
一年前的老文章。比起大量的概念炒作文章,这短短的五十行代码更贴切地展示了区块链的核心概念。
轻定义
区块链在更通用的术语中,是指一个公共数据库。在这个数据库中,新数据存储在一个名为 Block 的容器中,并将其添加到一个不可变链中。
数据也可以是任何类型。对于比特币和其他加密货币,这些数据是一组交易。
- 定义一个 Block区块 class
每个块都存储五个数据:一个时间戳time stamp,一个索引 index(不必要),数据data(可以是任何内容),前一个block的hash值和自己的hash值。自己的hash值是通过对 Block 的索引、时间戳、数据做哈希加密得到的。
本例中由hashlib包完成:产生一个sha256()初始值,然后产生一个超长的字符串(index+timestamp+data+prev_hash),最后用这个字符串来更新初始值。
比特币也是如此,
# Python 2
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()
# Python 3: need encode for sha.update
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)).encode())
return sha.hexdigest()
注意!由于区块链的第一个区块没有“前一个区块”。所以创世块(genesis block)是一个特殊的块。在很多情况下,它是手动添加的,或者有独特的逻辑允许添加。
- 生成创世块的方法
这里使用手动方法生成第一个区块。
其索引index为0,时间戳为方法被使用时的时间,包含的数据为字符串“Genesis Block”(可以为任何内容,比如“Hello World :D”),前一个区块的hash值为“0”(可以为任何内容,比如“3.1415926”)。
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")
有了这段代码,我们就得到创世块了。其后的每一个block都可以通过之前的定义取得。
- 区块链中生成后续的块
将链中的前一个 Block 作为参数,创建一个新Block的数据(新的 Block 的 hash 值依赖于前一个 Block 的哈希值),然后生成并返回新块。
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)
last_block意指链尾块。取得其数据后,新的block数据依赖其index
和Hash。
#觉得很奇怪,应该把数据当做参数输入才对吧。不然数据越来越多。
def next_block(last_block, new_data):
this_index = last_block.index + 1
this_timestamp = date.datetime.now()
this_data = str(new_data)
return Block(this_index, this_timestamp, this_data, last_block.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)
# 所有网站贴的结果图都一样,没意思不贴了。
本例子中,区块链本身就是一个简单的 Python 列表(单向链表?)。
列表的第一个元素是创世块(genesis block)。 接着添加后续的块。例子中添加了 20 个新的块。 用 for 循环实现。
这里只是实现了区块链最最基础部分的代码, 如果想让 SnakeCoin 运作起来 ,我们必须添加更多的功能,如服务器层,以跟踪多台机器上链的变化,并提供工作证明算法,以限制在限定时间内允许添加 Block 的数量。
(作为偷懒,暂时跳过第二部分,有兴趣回头看吧)
原文:(Gerald NashJul 16, 2017)
第一部分:https://medium.com/crypto-currently/lets-build-the-tiniest-blockchain-e70965a248b
第二部分:https://medium.com/crypto-currently/lets-make-the-tiniest-blockchain-bigger-ac360a328f4d
参考翻译:
https://www.jianshu.com/p/c805e4b955ca (部分翻译不充分)
http://www.gongxiangcj.com/posts/39301