如何与以太坊区块链交互并用Python和SQL创建数据库

关于区块链介绍性的研讨会通常以易于理解的点对点网络和银行分类账这类故事开头,然后直接跳到编写智能合约,这显得非常突兀。因此,想象自己走进丛林,想象以太坊区块链是一个你即将研究的奇怪生物。今天我们将观察该生物,并与其进行交互然后将有关它的所有数据收集到一个集中存储中供自己使用。

进行第一次设置

首先,你需要安装web3py。Web3py是一个用于连接以太坊区块链的Python库。你需要事先知道的是,没有可以从中下载数据的中央管理系统。彼此共享资源的内连节点(“对等体”)存储经验证的数据副本(或其一部分)。网络执行以太坊协议,该协议定义节点彼此之间的交互规则及网络上的智能合约。

如果要访问有关交易,余额,区块或其他任何被写入区块链的信息,协议需要你连接到节点。节点不断地相互共享新数据并验证数据,因此这样你就可以确定那些是未被篡改的数据,那些是最新的数据。

你可以在第一次接触以太坊的方法中使用两种基本类型的节点:本地或托管。本地节点可以在你的计算机上运行,这意味着你首先需要下载像geth这样的客户端,它会将区块链同步到你的设备,要占用存储空间并花费大量时间来完成。对于第一次学习,托管节点是更好的选择——它由其他人控制,但你可以轻松连接到它并自己玩区块链。

去Infura并创建自己的免费帐户以访问此类托管节点。当你完成后,你可以看到mainnet主网(即以太坊区块链)和一堆testnets测试网,它们基本上可以测试你的智能合约,这样你就可以在将昂贵的代码部署到mainnet之前犯错误,并纠正它们。

这第一次我们先导入Web3对象并建立HTTP连接。

1
2
from web3 import Web3 
web3 = Web3(Web3.HTTPProvider("https://mainnet.infura.io/your-own-personal-number"))

现在你已经完成了!你可以使用web3 API浏览查询数据结构了。

查询特定区块信息

1
2
3
4
5
#current block number
>>> web3.eth.blockNumber
5658173
#get the content of the most recently mined block
>>> web3.eth.getBlock('latest')

此命令返回AttributeDict数据结构,该结构是key-value键值对的字典,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
AttributeDict({'difficulty': 3297284143124448,
'extraData': HexBytes('0x65746865726d696e652d6177732d61736961312d34'),
'gasLimit': 7999992,
'gasUsed': 7990111,
'hash': HexBytes('0x8c09ba67123601c08ef5d292acaffd36798ca178b7d6fecd5e1144ce8e3b9e50'),
'logsBloom': HexBytes('0x348000240b40620836308460180004415000c8ccb260021402420721c22801ca847c625c0a89030482044001523a4d100050100250d100858381260a186312088006c154010000491216446840888200c1812088c12b06000809a808530014160000812c2ac20008a201c83380314d02242338400c0500c2a028005010988c44b0608a020400201032e10e16142b931115469824248066100b082224200222140a41a20aa2006224d608210f1a22811d03969423e8c08058100388c0800402002a000802130c40d289201900c38142a1cc0380a4010f0201040d4022200022018c5801346c168502841906940485ea1d9864044060a00000a00616004d006090'),
'miner': '0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8',
'mixHash': HexBytes('0x84320fd71345778b48e437f3403e9021575520ba23aaac48dd7a352c9ce31f75'),
'nonce': HexBytes('0x98a0b1e00bfabac6'),
'number': 5658173,
'parentHash': HexBytes('0x01eda8a47a0151533d1afacf9b9108606d4d89a86e269dddaac9698b6fb12930'),
'receiptsRoot': HexBytes('0xc40f774ad10ad443457c3a5a0db96b539af3007f8d351b198ca7bf2ef196b7e0'),
'sha3Uncles': HexBytes('0x55725ec296c6c64257ed6a88d7d8c66160abe7b672f5d89bbad5487779b1d5fe'),
'size': 27161,
'stateRoot': HexBytes('0x5bfc7a9a87fb9991f2760807d56319154f1dab91d3cfc9530a597b6c5d064aba'),
'timestamp': 1527002893,
'totalDifficulty': 4339832462578780814928,
'transactions': [HexBytes('0x1ce6bca99701c4e8acae986b10e7649d628d70ec62b7a8314bbb13726a312225'),
HexBytes('0x6ba5e657243aea5f95afb40090313d10bb9443db41ed1216fbf7e7e60a16749a'),
loooooots_of_transactions_here],
'transactionsRoot': HexBytes('0x67e1e1f2f4b1d33791a0fba2d5ebf039bd6c331c665cb8020ff41d0e0eade46e'),
'uncles': [HexBytes('0x3df1bffa62d73b3847b434e9ea459c10cfdc3e212a2e78ebbf0db58adbef30b5'),
HexBytes('0x74bdcd4b88427854ae18f9c7ada28d46f26411bed09af6b040cbede66fdb1853')]})

并非所有这些变量都会立即对你有用,因为有些变量非常技术性,只有当你对区块链的实际工作方式有了更深入的了解时,它们的含义才有意义。你可以在所谓的黄皮书中阅读有关它们的更多信息,或暂时跳过它们并使用易于理解的方法。

简而言之,一个包含区块头部信息的区块,一个写入它的已验证交易列表和一个未确认列表(矿工的块标识符,他们的区块太慢,无法进入主区块链,但仍因其计算工作量而获得以太奖励)。下面你可以看到每个变量的含义,我把它分成子类别。

General常规数据

挖矿相关

uncle相关

技术相关

交易和收据

现在,我们还可以通过其唯一标识符(即交易哈希)查找区块中的单个交易。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
>>> web3.eth.getTransaction('0x1ce6bca99701c4e8acae986b10e7649d628d70ec62b7a8314bbb13726a312225')

AttributeDict({'blockHash': HexBytes('0x8c09ba67123601c08ef5d292acaffd36798ca178b7d6fecd5e1144ce8e3b9e50'),
'blockNumber': 5658173,
'from': '0x390dE26d772D2e2005C6d1d24afC902bae37a4bB',
'gas': 45000,
'gasPrice': 123400000000,
'hash': HexBytes('0x1ce6bca99701c4e8acae986b10e7649d628d70ec62b7a8314bbb13726a312225'),
'input': '0x',
'nonce': 415710,
'r': HexBytes('0x1bb901ad0a3add517504cc459fdb1545d193020ec5c63a566e440ee39dbfe131'),
's': HexBytes('0x4b7ac95eb321b5947948ecb624e1d80b19d9cc876668c69cc2b32670f52b061a'),
'to': '0xBbA2D99C9B3aF394B0d6417b1D58815eE495029D',
'transactionIndex': 0,
'v': 37,
'value': 1000000000000000000})

和以前一样,web3py返回一个属性字典。下表总结了每个键的含义。

最后,我们还可以查看交易收据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
>>> web3.eth.getTransactionReceipt('0x68c70c5ffe54a42ebf7118e7e931aeac018cee4656a816ffe6a01388da50c851')

AttributeDict({'blockHash': HexBytes('0x44338e1f80302037c7213e8f56dd35d8a473b000319bc200f76e910e62d12f98'),
'blockNumber': 5617795,
'contractAddress': None,
'cumulativeGasUsed': 21004,
'from': '0xea6e3e41ebaa09d550d3c3f0d72971b3c5ccc261',
'gasUsed': 21004,
'logs': [],
'logsBloom': HexBytes('0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'),
'status': 1,
'to': '0xd96a6e75d099ce529bbd257cbcb403224cceaebf',
'transactionHash': HexBytes('0x68c70c5ffe54a42ebf7118e7e931aeac018cee4656a816ffe6a01388da50c851'),
'transactionIndex': 0})

交易收据包含一些重复和新条目,新的条目解释如下。

作为参考,除了黄皮书之外,我还包括各种额外资源来编制这些表格2,3,4,5

如你所见,只需几个简单的命令,就可以连接到网络并获得有关原始格式的交易,区块或状态的基本信息。这将为这些数据打开一个新窗口!

数据库管理系统

当计划将数据写入适当的数据库时,你可能会意识到有许多针对Python爱好者的管理系统解决方案,例如无服务器SQLite,或基于服务器的MySQL,PostgreSQL或Hadoop。根据你的意图,必须确定哪个选项最适合你的项目。总的来说,我发现这些要点很有帮助:

  • 数据库的预期大小是什么(即可以在单个机器系统上处理)?
  • 这些条目是经常编辑还是会保持不变?
  • 数据库是否应该由多方/应用程序同时访问和编辑?

随着时间的推移,以太坊区块链正在稳步增长,截止到2018年6月接近1TB,这个很小,因此对于像Hadoop这样的分布式处理系统来说并不是最佳选择。区块链数据库将被写入一次,然后仅使用新条目进行扩展,保留旧条目不变。此数据库的预期用例由一个通道编写,并由其他通道以只读方式访问,因此我们实际上不需要在服务器上运行它。在你的机器上本地保存数据库将导致快速读取,这对于像SQLite这样的无服务器管理系统是可取的和可实现的。Python有一个内置的库sqlite3,因此我们甚至不需要安装新的包。

数据库设计

下一步是设计数据库。请记住哪些数据字段与你的分析最相关,并且旨在优化搜索和存储。例如,如果你不打算使用stateRoot,则可能需要完全跳过它或将其保存在单独的表中。可以更快地搜索具有较少列的表,如果稍后意识到你实际上具有stateRoot的用例,你仍然可以访问它。你可能还希望将块信息与交易信息分开;如果不这样做,那么区块属性如timestamp将对区块中的所有交易重复N次,浪费大量空间。稍后使用JOIN操作可以轻松地将交易与其块属性进行匹配。

我设计的数据库包含3个表:

  • Quick:最相关的交易信息,用于快速访问和分析。
  • TX:所有剩余的交易信息,
  • Block:指定区块的信息。

变量的命名约定相对于原始的web3py略有改变,以消除歧义,例如将块哈希和交易哈希都称为“哈希”,或使用“from”/“to”作为列名,这在SQL有不同的含义,会使程序崩溃。

交易值,余额和其他大数字需要作为字符串存储在数据库中。原因是SQLite只能处理最多8字节存储的有符号整数,最大值为2的63次方-1大约是9223372036854775807.这通常远低于wei中的交易值(例如,1ETH = 10*18 wei)。

构建你的迷你数据库

完整的代码可以在GitHub上找到。它将根据上层架构组织区块链信息,并输出包含预先指定数量的块数据的blockchain.db文件。要测试它,请转到database.py文件并为要写入的块数选择合理的数字,例如:

1
Nblocks = 10000

默认情况下,你应该将web3对象指向Infura端点。 如果你有IPC提供商(即你的本地节点),也可以切换到IPC提供商,只需取消注释该行:

1
2
# or connection via node on the VM 
#web3 = Web3(Web3.IPCProvider('/path-to-geth.ipc/'))

修改路径,然后只需在命令行python database.py中运行。代码会将最后写入的块的编号转储到lastblock.txt文件中,以防你需要重新启动。

如何使用数据库

一旦将第一个条目写入数据库,就可以通过ipython shell开始与它进行通信。例如,要打印表“Quick”的前5行,你可以运行下面的代码。

1
2
3
4
5
6
7
8
9
import sqlite3 as sq3
conn = sq3.connect("blockchain.db")
cur = conn.cursor()

# some SQL code, e.g. select first five entries of the table Quick
cur.execute("SELECT * FROM Quick LIMIT 5")
a = cur.fetchall() #list of tuples containing all elements of the row
print(a)
conn.close()

本地节点与Infura

如果要构建大型数据库,则应下载geth并同步节点。同步可以在3种基本模式下完成:

如果你不需要过去的帐户状态,则可以在快速模式下同步节点6

下面的图表显示了此代码写入数据库的速度,与本地完全同步的节点(IPC)与Infura(Infura)上的地址进行通信。正如你所看到的,在本地节点上运行此代码是值得的,因为你可以将速度提升近2个数量级(即100x)!

总结

现在你已拥有自己的本地数据库,了解区块链上发生的事情,可以开始探索它。例如,你可以计算自其起源以来的交易数量,查看作为时间函数生成的地址数量——天空是你可以了解的有关区块链的限制。我们为你的数据科学游乐场奠定了基础。因此,请继续探讨,或查看下一篇文章,了解潜在的应用。

python用web3.py库开发以太坊来说非常的方便,有兴趣的用户可以关注我们的python以太坊教程,主要是针对python工程师使用web3.py进行区块链以太坊开发的详解。

另外其他语言可以学习的以太坊教程如下:

  • web3j教程,主要是针对java和android程序员进行区块链以太坊开发的web3j详解。
  • 以太坊教程,主要介绍智能合约与dapp应用开发,适合入门。
  • 以太坊开发,主要是介绍使用node.js、mongodb、区块链、ipfs实现去中心化电商DApp实战,适合进阶。
  • php以太坊,主要是介绍使用php进行智能合约开发交互,进行账号创建、交易、转账、代币开发以及过滤器和事件等内容。
  • C#以太坊,主要讲解如何使用C#开发基于.Net的以太坊应用,包括账户管理、状态与交易、智能合约开发与交互、过滤器和事件等。

汇智网原创翻译,转载请标明出处。这里是原文