跳转到主要内容

下一代加密货币网络

项目描述

这是以太坊项目的Python核心库。

有关基于Python的命令行客户端,请参阅: https://github.com/ethereum/pyethapp

安装

sudo apt-get install libssl-dev build-essential automake pkg-config libtool libffi-dev libgmp-dev

git clone https://github.com/ethereum/pyethereum/

cd pyethereum

python setup.py install

组件

ethereum.pow.chain

包含Chain类,可以用来管理区块链。主要方法有

  • __init__(genesis=None, env=None, new_head_cb=None, reset_genesis=False, localtime=None) - 使用给定的创世纪初始化。 env指定了环境(包括链配置和数据库),new_head_cb是在添加新头时调用的回调,localtime是链假定的当前时间戳。创世纪可以是

    • 无 - 在这种情况下,它假设已提供 env,并创建一个包含在 env.db 中保存的数据的 Chain 对象。如果设置了 reset_genesis,它将重新初始化链。

    • 一个 State 对象

    • 创世声明

    • 状态快照 (State.snapshot())

    • 一个分配(即字典 {address: {balance: 1, nonce: 2, code: b'\x03\x04\x05', storage: {"0x06": "0x07"}}}

  • add_block(block) - 将块添加到链中

  • process_time_queue(timestamp) - 告诉链当前时间已增加到新的时间戳。然后链将处理任何因为出现得太“早”而未处理的块

  • get_blockhash_by_number(num) - 获取给定块号的块哈希

  • get_block(hash) - 获取具有给定块哈希的块

  • get_block_by_number(num) - 等同于 get_block(get_blockhash_by_number(num))

  • get_parent(block) - 获取块的父块

  • get_children(block) - 获取块的子块

  • head (属性) - 获取链头部的块

  • state (属性) - 获取链头部的状态

  • mk_poststate_of_blockhash(hash) - 在给定的块之后创建一个状态对象

  • has_block(block) - 该块在链中吗?返回 True/False

  • get_chain(from, to) - 大约等同于 [get_block_by_number(i) for i in range(from, to)],但如果达到头部会自动停止。 from 可以省略,从创世开始,to 可以省略,直到头部。

  • get_tx_position(tx) - 如果交易在链中,返回 (blknum, index),其中 blknum 是包含该交易的块的块号,index 是其在块中的位置

ethereum.state

包含用于管理状态的 State 类。主要方法有

  • __init__(root_hash, env, **kwargs) - 使用给定的根哈希、给定的 env(包括配置和数据库)和给定的辅助参数初始化状态。这些包括

    • txindex - 交易索引

    • gas_used - 使用气量

    • gas_limit - 块气量限制

    • block_number - 块号

    • block_coinbase - 块 coinbase 地址

    • block_difficulty - 块难度

    • timestamp - 时间戳

    • logs - 已创建的日志

    • receipts - 已创建的收据(来自当前块中之前的交易)

    • bloom - bloom 过滤器

    • suicides - 自杀(或自我销毁,较新且更政治正确的同义词)

    • recent_uncles - 链中的最近叔叔块

    • prev_headers - 前一个块头部

    • refunds - 自杀/自我销毁退款计数器

Pyethereum采用了一个以状态为中心的最大化模型;处理交易或区块所需的信息全部位于状态内部,这使得实际的状态转换逻辑非常简洁,如apply_transaction(state, tx)apply_block(state, block)

  • get_balance - 获取账户余额

  • get_code - 获取账户代码

  • get_storage_data(addr, k) - 获取指定地址的给定键的存储数据。期望一个键以数字形式(例如,b”cow”或“0x636f77”表示为6516599)。

  • to_snapshot(root_only=False, no_prevblocks=False) - 为当前状态创建快照。如果设置root_only,则只添加状态根,而不是整个状态。如果设置no_prevblocks,则不添加先前头和叔父。设置这两个标志之一意味着需要相同的数据库来从快照中恢复。

  • from_snapshot(snapshot, env)(类方法)- 使用给定的env从给定的快照创建状态。

  • ephemeral_clone() - 创建一个状态的副本,您可以在此工作而不会影响原始状态。

还有许多修改状态的方法,例如set_codeset_storage_data,但通常建议避免使用这些方法,而应仅通过apply_transactionapply_block修改状态。

ethereum.meta

此文件包含两个函数

  • apply_block(state, block) - 将区块处理到给定状态中

  • make_head_candidate(chain, txqueue=None, parent=None, timestamp, coinbase, extra_data, min_gasprice=0) - 在给定父区块的顶部为链创建候选区块(默认:链的头部)。从给定的txqueue对象中获取交易,并使用给定的mingasprice(否则不添加交易)。可以使用timestampcoinbaseextra_data指定这些参数,否则使用默认值。

ethereum.messages

从这里应该调用的主要函数是apply_transaction(state, tx)

ethereum.utils

包含许多实用函数,包括

数值和十六进制转换

  • encode_int(i) - 将整数转换为大端二进制表示

  • zpad(data, length) - 通过在左侧添加零字节将数据填充到所需的长度

  • encode_int32(i) - 等同于zpad(encode_int(i), 32),但速度更快

  • big_endian_to_int(d) - 将二进制数据转换为整数

  • encode_hex(b) - 将字节转换为十六进制

  • decode_hex(h) - 将十六进制转换为字节

  • int_to_addr(i) - 将整数转换为地址

  • is_numeric(i) - 如果值是int或long,则返回True,否则返回False

密码学

  • sha3(data) - 计算SHA3(更确切地说,keccak256)哈希

  • ecrecover_to_pub(hash, v, r, s) - 从签名中恢复公钥,作为64字节二进制blob encode_int32(x) + encode_int32(y)。对该哈希进行哈希处理并取最后20字节,可以得到签名消息的地址

  • ecsign(hash, key) - 返回签名的v、r、s值

  • normalize_key(key) - 将键从多种格式转换为32字节二进制

  • privtoaddr(key) - 将密钥转换为地址

地址

  • normalize_address(addr) - 将地址转换为20字节的二进制形式

  • check_checksum(addr) - 如果地址校验和通过,则返回True,否则返回False

  • checksum_encode(addr) - 将地址转换为带有校验和的十六进制形式

  • mk_contract_address(addr, nonce) - 创建由给定地址和给定nonce创建的合约地址

杂项

  • denoms - 包含以太币的计量单位,例如denoms.finney = 10**15denoms.shannon = 10**9denoms.gwei = 10**9

ethereum.block

包含BlockBlockHeader类。通常建议避免直接创建块和块头,而是使用mk_head_candidate。成员变量简单易懂

  • block.transactions - 块中的交易

  • block.uncles - 块中的叔父

  • block.header - 块的头

在头信息中

  • header.hash - 哈希(也是块哈希)

  • header.mining_hash - 用于工作量证明挖掘的哈希

  • header.to_dict() - 序列化为可读的字典

  • header.prevhash - 前一个块哈希

  • header.uncles_hash - 叔父列表的哈希

  • header.coinbase - coinbase(矿工)地址

  • header.state_root - 后状态根哈希

  • header.tx_list_root - 块中交易的哈希

  • header.receipts_root - 收据trie的哈希

  • header.bloom - bloom过滤器

  • header.difficulty - 块难度

  • header.number - 块号

  • header.gas_limit - 气体限制

  • header.gas_used - 气体使用量

  • header.timestamp - 时间戳

  • header.extra_data - 块额外数据

  • header.mixhashheader.nonce - Ethash工作量证明值

ethereum.transactions

包含Transaction类,具有以下方法和值

  • __init__(nonce, gasprice, startgas, to, value, data, (v, r, s optional)) - 构造函数

  • sign(key, network_id=None) - 使用给定的密钥对交易进行签名,并使用给定的EIP155链ID(留空将创建预EIP155交易,请注意这种做法可能会导致重放攻击!)

  • sender - 交易发送者地址

  • network_id - 交易的EIP155链ID

  • hash - 交易的哈希

  • to_dict() - 序列化为可读的字典

  • intrinsic_gas_used - 交易消耗的气体量,包括交易数据的费用

  • creates - 如果交易创建了一个合约,则返回合约地址

  • noncegaspricestartgastovaluedatavrs - 交易中的参数

ethereum.tools.keys

创建加密的私钥存储

  • decode_keystore_json(jsondata, password) - 从加密的密钥存储对象中返回私钥。注意:如果您从文件中加载,最方便的方法是 import json; key = decode_keystore_json(json.load(open('filename.json')), 'password')

  • make_keystore_json(key, pw, kdf='pbkdf2', cipher='aes-128-ctr') - 为密钥创建加密的密钥存储对象。建议保留 kdfcipher 的默认值。

ethereum.abi

Ethereum上大多数HLL(Solidity、Serpent、Viper等)编译器都有输出程序ABI声明的选项。这是一个类似于下面的JSON对象

[{"name": "ecrecover(uint256,uint256,uint256,uint256)", "type": "function", "constant": false,
 "inputs": [{"name": "h", "type": "uint256"}, {"name": "v", "type": "uint256"}, {"name": "r", "type": "uint256"}, {"name": "s", "type": "uint256"}],
 "outputs": [{"name": "out", "type": "int256[]"}]},
 {"name": "PubkeyTripleLogEvent(uint256,uint256,uint256)", "type": "event",
 "inputs": [{"name": "x", "type": "uint256", "indexed": false}, {"name": "y", "type": "uint256", "indexed": false}, {"name": "z", "type": "uint256", "indexed": false}]}]

您可以使用以下方法初始化 abi.ContractTranslator 对象来为合约编码和解码数据

true, false = True, False
ct = abi.ContractTranslator(<json here>)
txdata = ct.encode('function_name', [arg1, arg2, arg3])

您还可以调用 ct.decode_event([topic1, topic2...], logdata) 来解码日志。

RLP编码和解码

对于任何交易或区块,您可以简单地这样做

import rlp
bindata = rlp.encode(<tx or block>)

为了解码

import rlp
from ethereum.transactions import Transaction
rlp.decode(blob, Transaction)

或者

import rlp
from ethereum.blocks import Block
rlp.decode(blob, Block)

共识抽象

pyethereum代码库旨在最大程度地适用于多种不同的共识算法。如果您想添加新的共识算法,您需要采取以下步骤

  • pow 旁边添加一个目录,并在其中创建一个实现 Chain 模块的 chain.py 类。这可能具有完全不同的工作量证明分叉选择规则(GHOST、签名计数、Casper等)。

  • 将条目添加到 consensus_strategy.py。您需要实现以下内容

    • check_seal - 检查区块是否正确“密封”(挖矿、签名等)

    • validate_uncles(state, block) - 检查叔块是否有效

    • initialize(state, block) - 在处理交易之前在 apply_block 中调用

    • finalize(state, block) - 在处理交易后在 apply_block 中调用

    • get_uncle_candidates(chain, state) - 在 mk_head_candidate 中调用,以在区块中包含叔块

  • 创建一个具有 CONSENSUS_STRATEGY 设置为您的新的共识策略名称的链配置

测试模块

请参阅 https://github.com/ethereum/pyethereum/wiki/Using-pyethereum.tester

测试

运行 python3.6 -m pytest ethereum/tests/<filename> 以运行该目录中的任何.py文件。目前,除了几个Metropolis特定的状态测试和区块测试外,所有测试都通过。

要创建自己的状态测试,请按如下方式使用测试模块

from ethereum.tools import tester as t
import json
c = t.Chain()
x = c.contract(<code>, language=<language>)
pre = t.mk_state_test_prefill(c)
x.foo(<args>)
post = t.mk_state_test_postfill(c, pre)
open('output.json', 'w').write(json.dumps(post, indent=4))

要创建一个测试填充文件,请执行 post = t.mk_state_test_postfill(c, pre, True)

许可证

请参阅 LICENSE

项目详情


下载文件

下载您平台对应的文件。如果您不确定选择哪个,请了解更多关于安装包的信息。

源代码分布

ethereum-2.3.2.tar.gz (155.6 kB 查看哈希)

上传时间 源代码

支持