区块链五层架构python_Python从零开始构建区块链之数据层理解

前言

比特币在2017可谓是十足地火爆了,那他背后依赖的区块链技术又是如何实现的呢?当下对区块链人才的需求更是迫切中的迫切,或许在2018将火爆各个行业。

本次系列文章将从实际代码出发,来构建你对区块链技术的认知。

写代码之前

基础技能要求

1.简单的Python基础

2.对HTTP请求有基本的认知

3.面向对象编程思维

4.区块链基本定义

开发环境准备

1.Python3.6

Mac自带的Python为2.7,这里我们需要重新安装Python3.6

1.1确保电脑安装了套件管理工具 Homebrew,如果没有请在命令行执行以下命令安装:

/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

1.2 验证是否安装成功,该命令也可以检验电脑是否安装了Homebrew

brew doctor

1.3安装Python3.6

brew install python3

1.4查看Python路径

// 系统自带的python2.7,目录为/usr/bin/python

which python

//brew安装的python3.4,目录为/usr/local/bin/python3

which python3

1.4查看Python路径.png

1.5使用

// 系统自带的

python a.py

//brew安装的

python3 a.py

2.python包管理工具:Pip

一般我们安装python3时自带了Pip,如果没有在命令行用HomeBrew安装:

brew install pip

2.1 配置pipenv:

//安装 pipenv

pip install pipenv

//创建virtual env

pipenv --python=python3.6

//安装依赖

pipenv install

3.Python IDE

这一项不是必须的,我们可以在命令行vi或记事本里写python代码。当然习惯使用IDE的童鞋也可以选择使用IDE,笔者这里使用的Python IDE为Pycharm专业版(自行百度PoJie教程)

4.flask网络框架

我们后期理解了区块链的底层数据结构后,在网络层实现节点同步和网络共识时会使用到flask网络框架。这里,暂且提一下,本文内容暂时不会用到。

5.接口调试工具

同时后期进行区块链网络编程时还需要一个HTTP客户端,比如Postman,cURL或其它客户端。这里我使用的是Postman

)

废话少说撸代码

我们知道区块链是有一个个区块构成,而区块内又包含了基本的区块信息和若干个交易信息,一个交易信息就是对一笔交易的结构封装(附带了哈希值等值以防止交易被篡改)。我们今天就从区块链的最下层数据结构交易开始层层分析,直到构成一个完整的区块链。

打开Pycharm新建一个Python项目并新建一个文件:blockchain.py(使用Vi或记事本开发的直接新建该文件)

交易类

Transaction用来简单描述一笔交易的主要信息

class Transaction: #交易类

def __init__(self,

payer, #付款方

recer, #收款方

count): #金额

self.payer = payer

self.recer = recer

self.count = count

self.timestamp = datetime.datetime.now()

def __repr__(self):

return str(self.payer) + " pay" + str(self.recer) + " " + str(self.count) + " in " + str(self.timestamp)

交易记录类

ChaorsMessage类用来封装一笔交易,并引入哈希加密机制防止交易数据与时间或者交易链被篡改。

#交易链的简单实现

ChaorsMessage

import datetime #获取时间的库

import hashlib #哈希函数库

from Transaction import Transaction #引入交易类

class ChaorsMessage: #交易记录类

def __init__(self, data):

self.data = data # 交易信息

self.hash = None #自身哈希

self.prev_hash = None #上一个交易记录的哈希

self.timestamp = datetime.datetime.now()

self.payload_hash = self._hash_payload() #锁定哈希

def _hash_payload(self): #交易哈希

return hashlib.sha256((str(self.timestamp) + str(self.data)).encode("utf-8")).hexdigest()

def _hash_message(self): #交易记录哈希,锁定交易(哈希再哈希)

return hashlib.sha256((str(self.prev_hash) + str(self.payload_hash)).encode("utf-8")).hexdigest()

#密封,相当于将交易信息封装为一个带哈希验证值的数据结构 使得交易信息(包括交易数据和时间,交易链接的顺序)不能被修改

def seal(self):

self.hash = self._hash_message() #对应数据锁定

def validate(self): #验证交易记录是否合法

if self.payload_hash != self._hash_payload():

raise InvalidMessage("交易数据与时间被修改" + str(self))

if self.hash != self._hash_message(): #判断消息链

raise InvalidMessage("交易的哈希链接被修改" + str(self))

return "data ok" + str(self)

def __repr__(self): #返回对象基本信息

mystr = "hash:{}, prev_hash:{}, data:{}".format(self.hash, self.prev_hash, self.data)

return mystr

def link(self, message): #链接

self.prev_hash = message.hash

class InvalidMessage(Exception): #异常处理类

def __init__(self, *args, **kwargs):

Exception.__init__(self, *args, **kwargs)

f __name__ == '__main__': #单独模块测试

try:

t1 = Transaction("chaors", "yajun", 999999999)

t2 = Transaction("chaors2", "yajun2", 999999999)

m1 = ChaorsMessage(t1)

m2 = ChaorsMessage(t2)

#交易密封

m1.seal()

#交易哈希只有密封之后才能link

m2.link(m1)

m2.seal()

m1.validate()

m2.validate()

#篡改数据 篡改数据后会捕获到异常

# m2.data = "hahahaha"

# m2.validate()

#

m2.prev_hash = "kkkkk"

# print(m2)

m2.validate()

except InvalidMessage as e:

print(e)

Block类

每个区块包含属性:索引(index),Unix时间戳(timestamp),交易列表(transactions),工作量证明(下次讲这个,这里暂时搁置)以及前一个区块的Hash值。

以下是一个区块的结构:

block = {

'index': 1,

'timestamp': 1506057125.900785,

'transactions': [

{

'sender': "8527147fe1f5426f9dd545de4b27ee00",

'recipient': "a77f5cdfa2934df3954a5c7c7da5df1f",

'amount': 5,

}

],

'proof': 324984774000,

'previous_hash': "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824"

}

到这里,区块链的概念就清楚了,每个新的区块都包含上一个区块的Hash,这是关键的一点,它保障了区块链不可变性。如果攻击者破坏了前面的某个区块,那么后面所有区块的Hash都会变得不正确。

import datetime

import hashlib

from Message import ChaorsMessage

from Message import InvalidMessage

from Transaction import Transaction

class Block:

def __init__(self, *args):

self.messagelist = [] #存储多个交易记录

self.timestamp = None #当前时间戳

self.hash = None;

self.prev_hash = None

#遍历交易参数,将所有交易加入到交易列表内

if args:

for arg in args:

self.add_message(arg)

def add_message(self, msg): #增加交易信息

#区分第一条和后面的 判断是否需要链接

if len(self.messagelist) > 0:

msg.link(self.messagelist[-1])

msg.seal()

msg.validate()

self.messagelist.append(msg)

def link(self, block): #链接

#当前区块的上个哈希值为上个区块哈希值,将区块连接起来

block.hash = self.prev_hash

def seal(self): #区块封装,带有时间戳和哈希值的数据结构

self.timestamp = datetime.datetime.now()

self.hash = self._hash_block()

#求区块的哈希值

def _hash_block(self):

return hashlib.sha256((str(self.prev_hash) +

str(self.timestamp) +

str(self.messagelist[-1].hash)).encode("utf-8")).hexdigest()

def validate(self): #区块合法性验证

for i, msg in enumerate(self.messagelist):

msg.validate()

if i > 0 and msg.prev_hash != self.messagelist[i-1].hash:

raise InvalidBlock("无效block,第{}条交易记录被修改".format(i)+ str(self))

return str(self) + "block ok..."

def __repr__(self):

return "block = hash:{}, prehash:{}, len:{}, time:{}".format(self.hash,

self.prev_hash,

len(self.messagelist),

self.timestamp)

class InvalidBlock(Exception): #异常处理类

def __init__(self, *args, **kwargs):

Exception.__init__(self, *args, **kwargs)

if __name__ == '__main__':

try:

t1 = Transaction("chaors", "yajun", 999999999)

t2 = Transaction("chaors2", "yajun2", 999999999)

t3 = Transaction("chaors4", "yajun4", 999999999)

m1 = ChaorsMessage(t1)

m2 = ChaorsMessage(t2)

m3 = ChaorsMessage(t3)

block = Block(m1, m2, m3)

block.seal()

print(block)

# m1.data = "kkkk"

block.messagelist[1] = m3

block.validate()

except InvalidMessage as e:

print(e)

except InvalidBlock as e:

print(e)

Blockchain类

Blockchain类用来管理链条,它能存储交易,加入新块等。它就是一个完整的区块链

import datetime

import hashlib

from Block import Block

from Block import InvalidBlock

from Message import ChaorsMessage

from Message import InvalidMessage

from Transaction import Transaction

class BlockChain:

def __init__(self):

self.blocklist = []

def add_block(self, block):

if len(self.blocklist) > 0:

block.prev_hash = self.blocklist[-1].hash

block.seal() #区块封装

block.validate() #区块链接

self.blocklist.append(block)

def validate(self): #区块验证

for i, block in enumerate(self.blocklist):

try:

block.validate()

except InvalidBlock as e:

print(e)

raise InvalidBlockChain("第{}区块校验错误".format(i))

def __repr__(self):

return "BlockChain:{}".format(len(self.blocklist))

class InvalidBlockChain(Exception): # 异常处理类

def __init__(self, *args, **kwargs):

Exception.__init__(self, *args, **kwargs)

if __name__ == '__main__':

try:

t1 = Transaction("chaors", "yajun", 999999999)

t2 = Transaction("chaors2", "yajun2", 999999999)

t3 = Transaction("chaors4", "yajun4", 999999999)

m1 = ChaorsMessage(t1)

m2 = ChaorsMessage(t2)

m3 = ChaorsMessage(t3)

block1 = Block(m1, m2, m3)

block1.seal()

t21 = Transaction("chaors", "yajun", 999999999)

t22 = Transaction("chaors2", "yajun2", 999999999)

m21 = ChaorsMessage(t21)

m22 = ChaorsMessage(t22)

block2 = Block(m21, m22)

block2.seal()

t31 = Transaction("chaors", "yajun", 999999999)

t32 = Transaction("chaors2", "yajun2", 999999999)

t33 = Transaction("chaors4", "yajun4", 999999999)

t34 = Transaction("chaors8", "yajun8", 999999999)

m31 = ChaorsMessage(t31)

m32 = ChaorsMessage(t32)

m33 = ChaorsMessage(t33)

m34 = ChaorsMessage(t34)

block3 = Block(m31, m32, m33, m34)

block3.seal()

mychain = BlockChain()

mychain.add_block(block1)

mychain.add_block(block2)

mychain.add_block(block3)

print(mychain)

#篡改区块

block3.messagelist[1] = m33

# m31.data = "lkjioh"

mychain.validate()

except InvalidBlockChain as e:

print(e)

通过上面的代码,可以对区块链区块的产生和交易有一个更深刻的了解。交易和存储交易的区块因为哈希值都会具有不可篡改的特性。

当然真正的区块链远不止这么简单,这里只是大概搭建一个简单的区块链Demo,用于理解区块链的不可篡改原理和基本数据结构。本文代码也只实现了区块链的数据层,至于网络层,共识层等,以后有机会再写一写。

互联网颠覆世界,区块链颠覆互联网!

---------------------------------------------------------20180405夜

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值