下一代加密货币网络
项目描述
这是以太坊项目的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_code、set_storage_data,但通常建议避免使用这些方法,而应仅通过apply_transaction和apply_block修改状态。
ethereum.meta
此文件包含两个函数
apply_block(state, block) - 将区块处理到给定状态中
make_head_candidate(chain, txqueue=None, parent=None, timestamp, coinbase, extra_data, min_gasprice=0) - 在给定父区块的顶部为链创建候选区块(默认:链的头部)。从给定的txqueue对象中获取交易,并使用给定的mingasprice(否则不添加交易)。可以使用timestamp、coinbase和extra_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**15,denoms.shannon = 10**9,denoms.gwei = 10**9
ethereum.block
包含Block和BlockHeader类。通常建议避免直接创建块和块头,而是使用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.mixhash 和 header.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 - 如果交易创建了一个合约,则返回合约地址
nonce,gasprice,startgas,to,value,data,v,r,s - 交易中的参数
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') - 为密钥创建加密的密钥存储对象。建议保留 kdf 和 cipher 的默认值。
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