Python区块链教程
Posted wodepingzi
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python区块链教程相关的知识,希望对你有一定的参考价值。
来源 https://zhuanlan.zhihu.com/p/142136802
此区块链教程将详细介绍区块链背后的理论。区块链是数字货币比特币的基本构建块,此教程将讨论比特币的复杂性,全面解释区块链架构,并建立我们自己的区块链。
本教程将介绍如何构建上述系统,并在市场上推出自己的数字货币。整个区块链项目开发包括3个主要部分:客户(Client)、矿工(Miners)、区块链(Blockchain)。
- 客户:从其他卖方(供应商)购买商品。客户本身可能会成为卖方,从其提供的商品中接受买方的钱款。我们假设客户既可以是TPCoins的供应商,也可以是其接收者。因此,我们需要在代码中创建一个具有收付钱款功能的客户类。
- 矿工:从交易池(transaction pool)中提取交易并将其组装成一个块。矿工必须提供有效的工作证明才能获得采矿奖励。矿工收取的所有钱都将由他保留。他可能在网上的其他注册供应商那里通过购买商品或服务而消费这笔钱,就像上述客户一样。
- 区块链:是一种按时间顺序链接所有已开采区块的数据结构。 该链是不可变的,防止被篡改。
2. 创建多交易
多个客户进行的交易在系统中排队; 矿工从此队列中提取交易并将其添加到区块中。 然后他们将开采该区块,获胜的矿工将拥有将该区块添加到区块链中的特权,从而为自己赚钱。
我们将在后续讨论区块链创建时描述此挖掘过程。 在编写多个交易代码之前,添加一个函数用来打印给定交易的内容。
2.1 展示交易
display_transaction
函数接受交易类型的单参数。 接收到交易中的字典对象被复制到一个名为tsdict
的临时变量中,并使用字典键打印对应的值。
def display_transaction(transaction):
tsdict = transaction.to_dict()
print("sender: " + tsdict[\'sender\'])
print(\'-\' * 20)
print("recipient: " + tsdict[\'recipient\'])
print(\'-\' * 20)
print("value: " + str(tsdict[\'value\']))
print(\'-\' * 20)
print("time: " + str(tsdict[\'time\']))
print(\'-\' * 20)
下面我们定义一个交易队列存储交易对象。
2.2 交易队列
为了创建一个队列,我们声明一个名为transactions
的全局列表变量:
transactions = []
我们简单地将每个新创建的交易添加到此队列。 注意:为简单起见,本教程中不实现队列管理逻辑。
2.3 创建多客户
我们将开始创建交易。 首先创建4个客户,他们为从他人那里获得各种服务或商品而互相汇款。
Dinesh = Client()
Ramesh = Client()
Seema = Client()
Vijay = Client()
至此,我们有4个客户,分别是Dinesh,Ramesh,Seema和Vijay。 假设每个客户钱包中都持有一些TPCoin可以用于交易。 这些客户的身份将通过这些对象的identity属性来指定。
2.4 创建第一个交易
现在执行第一个交易:
t1 = Transaction(Dinesh, Ramesh.identity, 5.0)
在这个交易中,Dinesh将5个TPCoins发送给Ramesh。 为了使交易成功,必须确保Dinesh钱包中有足够的钱来进行这次付款。 注意:我们需要一个初始(genesis
)交易来启动系统中TPCoin的流通。
我们使用Dinesh的私钥签署此交易,并将其添加到交易队列中:
t1.sign_transaction()
transactions.append(t1)
Dinesh完成第一个交易后,我们将在不同客户间创建更多的交易。
2.5 添加更多交易
现在创建更多交易,每笔交易都会向对方转移一些TPCoins。 当有人花钱时,他不必检查钱包中是否有足够的余额。在发起交易时,矿工将验证每个交易发送方所拥有的余额。
余额不足时,矿工将此交易标记为无效,并且不会将其添加到该区块中。
以下代码将创建9个交易并将其添加到我们的队列中。
t2 = Transaction(Dinesh, Seema.identity, 6.0)
t2.sign_transaction()
transactions.append(t2)
t3 = Transaction(Ramesh, Vijay.identity, 2.0)
t3.sign_transaction()
transactions.append(t3)
t4 = Transaction(Seema, Ramesh.identity, 4.0)
t4.sign_transaction()
transactions.append(t4)
t5 = Transaction(Vijay, Seema.identity, 7.0)
t5.sign_transaction()
transactions.append(t5)
t6 = Transaction(Ramesh, Seema.identity, 3.0)
t6.sign_transaction()
transactions.append(t6)
t7 = Transaction(Seema, Dinesh.identity, 8.0)
t7.sign_transaction()
transactions.append(t7)
t8 = Transaction(Seema, Ramesh.identity, 1.0)
t8.sign_transaction()
transactions.append(t8)
t9 = Transaction(Vijay, Dinesh.identity, 5.0)
t9.sign_transaction()
transactions.append(t9)
t10 = Transaction(Vijay, Ramesh.identity, 3.0)
t10.sign_transaction()
transactions.append(t10)
2.6 查看交易
作为区块链管理者,你可能喜欢定期查看交易队列的内容。 为此,可以使用display_transaction
函数。 要将所有交易转储到队列中,只需迭代交易列表;然后为每个交易调用display_transaction
函数:
for transaction in transactions:
display_transaction(transaction)
print (\'-\' * 20)
由于交易会定期添加到区块中,因此你通常只希望查看尚未开采的交易清单,需要创建适当的for循环来遍历尚未挖掘的交易。
到目前为止,你已经学习了如何创建客户,允许客户之间进行交易,维护待挖掘的未完成的交易队列。
3. Block类
一个区块由不同数量的交易组成。 为简单起见,假设该块由固定数量的交易组成,示例中为3个交易。 由于该块需要存储3个交易的列表,我们声明一个实例变量authenticated_transactions
:
self.verified_transactions = []
我们将此变量命名为verify_transactions
,表示只有经过验证的有效交易才会被添加到该区块中。 每个块还保留前一个块的哈希值,因此块链变得不可变。
为了存储先前的哈希,声明一个实例变量:
self.previous_block_hash = ""
最后,声明一个变量Nonce
,用于存储矿工在采矿过程中创建的随机数。
self.Nonce = ""
Block类的定义为:
class Block():
def __init__(self):
self.verified_transactions = []
self.previous_block_hash = ""
self.Nonce = ""
由于每个块需要前一个块的哈希值,声明一个last_block_hash
的全局变量:
last_block_hash = ""
3.1 创建初始区块
下面在区块链中创建第一个块。假设TPCoins的发起者最初向一个已知客户Dinesh发送500个TPCoins。 为此创建一个Dinesh实例:
Dinesh = Client()
然后我们创建初始(genesis)交易,并向Dinesh的公共地址发送500 TPCoins。
t0 = Transaction("Genesis", Dinesh.identity, 500.0)
创建一个Block类的实例:
block0 = Block()
将previous_block_hash
和once
实例变量初始化为None,因为这是存储在区块链中的第一笔交易。
block0.previous_block_hash = None
Nonce = None
将t0
交易添加到块中的verified_transactions
列表中。
block0.verified_transactions.append(t0)
此时,该块完成初始化,可以添加到我们的区块链中。 我们将为此创建区块链。 在将区块添加到区块链之前,我们将对区块进行哈希处理并将其值存储在之前声明的last_block_hash
变量中。 该值将由下一个矿工在其区块中使用。
通过如下代码哈希区块并存储其值:
digest = hash(block0)
last_block_hash = digest
3.2 创建区块链
区块链包含彼此链接的区块列表。 为了存储整个列表,创建一个列表变量TPCoins
:
TPCoins = []
dump_blockchain
方法用于转储整个区块链的内容。 首先打印区块链的长度,以便确定当前区块链中存在多少个区块。
def dump_blockchain(self):
print("Number of blocks in the chain: " + str(len(self)))
随着时间的推移,区块链中的块数可能很多。 当打印区块链的内容时,需要确定要检查的范围。 示例中打印了整个区块链,因为在当前示例不会添加太多块。为了遍历整个链,设置了一个for循环:
for x in range (len(TPCoins)):
block_temp = TPCoins[x]
print ("block # " + str(x))
每个引用的块都复制到临时变量block_temp
中。
将块号作为每个块的标题。 注意:数字将从零开始,第1个块是编号为1的初始块。
在每个块中,已经将3个交易(初始块除外)的列表存储在变量verified_transactions
中。 在for循环中迭代此列表,调用display_transaction
显示交易明细。
for transaction in block_temp.verified_transactions:
display_transaction (transaction)
dump_blockchain
方法全部代码为:
def dump_blockchain(self):
print("Number of blocks in the chain: " + str(len(self)))
for x in range(len(TPCoins)):
block_temp = TPCoins[x]
print("block # " + str(x))
for transaction in block_temp.verified_transactions:
display_transaction(transaction)
print(\'-\' * 10)
print(\'=\' * 40)
现在已经创建了一个用于存储块的区块链,一个任务是创建块并将其添加到区块链中。 为此,将添加之前已经创建的初始块。
3.3 添加初始块
向区块链添加一个块涉及到将创建的块追加到TPCoins
列表中。
TPCoins.append(block0)
注意:与系统中其余的块不同,初始块仅包含一个由TPCoins系统的发起者发起的交易。通过调用函数dump_blockchain
转储区块链的内容:
dump_blockchain(TPCoins)
至此,区块链系统就可以使用了。我们将通过为感兴趣的客户提供挖掘功能,使他们成为矿工。
以上是关于Python区块链教程的主要内容,如果未能解决你的问题,请参考以下文章
区块链教程Fabric1.0源代码分析blockfile区块文件存储一