eth-tester:用于测试以太坊应用的工具。
项目描述
eth-tester
Ethereum 应用程序的测试工具
在下述文档中了解更多信息。查看变更日志。
快速入门
python -m pip install eth-tester
>>> from eth_tester import EthereumTester
>>> t = EthereumTester()
>>> t.get_accounts()
('0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf',
'0x2B5AD5c4795c026514f8317c7a215E218DcCD6cF',
'0x6813Eb9362372EEF6200f3b1dbC3f819671cBA69',
'0x1efF47bc3a10a45D4B230B5d10E37751FE6AA718',
'0xe1AB8145F7E55DC933d51a18c793F901A3A0b276',
'0xE57bFE9F44b819898F47BF37E5AF72a0783e1141',
'0xd41c057fd1c78805AAC12B0A94a405c0461A6FBb',
'0xF1F6619B38A98d6De0800F1DefC0a6399eB6d30C',
'0xF7Edc8FA1eCc32967F827C9043FcAe6ba73afA5c',
'0x4CCeBa2d7D2B4fdcE4304d3e09a1fea9fbEb1528')
>>> t.get_balance('0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf')
1000000000000000000000000
>>> t.send_transaction({
... 'from': '0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf',
... 'to': '0x2B5AD5c4795c026514f8317c7a215E218DcCD6cF',
... 'gas': 30000,
... 'value': 1,
... 'max_fee_per_gas': 1000000000,
... 'max_priority_fee_per_gas': 1000000000,
... 'chain_id': 131277322940537,
... 'access_list': (
... {
... 'address': '0xde0b295669a9fd93d5f28d9ec85e40f4cb697bae',
... 'storage_keys': (
... '0x0000000000000000000000000000000000000000000000000000000000000003',
... '0x0000000000000000000000000000000000000000000000000000000000000007',
... )
... },
... {
... 'address': '0xbb9bc244d798123fde783fcc1c72d3bb8c189413',
... 'storage_keys': ()
... },
... )
... })
'0xc20b90af87bc65c3d748cf0a1fa54f3a86ffc94348e0fd91a70f1c5ba6ef4109'
>>> t.get_transaction_by_hash('0xc20b90af87bc65c3d748cf0a1fa54f3a86ffc94348e0fd91a70f1c5ba6ef4109')
{'type': '0x2',
'hash': '0xc20b90af87bc65c3d748cf0a1fa54f3a86ffc94348e0fd91a70f1c5ba6ef4109',
'nonce': 0,
'block_hash': '0x28b95514984b0abbd91d88f1a542eaeeb810c24e0234e09891b7d6b3f94f47ed',
'block_number': 1,
'transaction_index': 0,
'from': '0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf',
'to': '0x2B5AD5c4795c026514f8317c7a215E218DcCD6cF',
'value': 1,
'gas': 30000,
'data': '0x',
'r': 60071646517429056848243893841817235885102606421189844318110381014348740252962,
's': 55731679314783756278323646144996847004593793888590884914350251538533006990589,
'v': 0,
'chain_id': 131277322940537,
'max_fee_per_gas': 1000000000,
'max_priority_fee_per_gas': 1000000000,
'access_list': ({'address': '0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe',
'storage_keys': ('0x0000000000000000000000000000000000000000000000000000000000000003',
'0x0000000000000000000000000000000000000000000000000000000000000007')},
{'address': '0xBB9bc244D798123fDe783fCc1C72d3Bb8C189413',
'storage_keys': ()}),
'gas_price': 1000000000}
>>> t.get_transaction_receipt('0xc20b90af87bc65c3d748cf0a1fa54f3a86ffc94348e0fd91a70f1c5ba6ef4109')
{'transaction_hash': '0xc20b90af87bc65c3d748cf0a1fa54f3a86ffc94348e0fd91a70f1c5ba6ef4109',
'transaction_index': 0,
'block_number': 1,
'block_hash': '0x28b95514984b0abbd91d88f1a542eaeeb810c24e0234e09891b7d6b3f94f47ed',
'cumulative_gas_used': 29600,
'gas_used': 29600,
'effective_gas_price': 1000000000,
'contract_address': None,
'logs': (),
'type': '0x2',
'status': 1}
文档
输入和输出数据格式
以太坊测试库严格遵循以下输入格式和类型。
- 十六进制值必须是文本(不是字节)字符串。可选的
0x
前缀。 - 包含混合大小写字母的任何地址将根据EIP-55进行校验地址。
- 32字节哈希值必须进行十六进制编码。
- 数值必须以整数表示。
类似地,以太坊测试库确保返回值遵守类似规则。
- 32字节哈希值将以其十六进制编码形式返回。
- 地址将以其十六进制形式返回并经过EIP55校验。
- 数值将以整数形式返回。
区块编号
任何block_number
参数将接受以下字符串值。
'latest'
:对于最新挖掘的区块。'pending'
:对于当前未挖掘的区块。'earliest'
:对于创世区块。'safe'
:对于合并后通过2/3验证的最后一个区块。'finalized'
:对于合并后的最后一个最终区块。
注意:这些必须是文本字符串(不是字节字符串)
eth_tester.EthereumTester
API
实例化
eth_tester.EthereumTester(backend=None, validator=None, normalizer=None, auto_mine_transactions=True, fork_blocks=None)
EthereumTester
对象是唯一的API入口点。实例化此对象接受以下参数。
backend
:正在使用的链后端。参见链后端validator
:正在使用的验证器。参见验证器normalizer
:正在使用的标准化器。参见标准化器auto_mine_transactions
:如果为真,提交时将自动挖掘交易。参见enable_auto_mine_transactions
和disable_auto_mine_transactions
。fork_blocks
:配置各种网络分叉规则将激活的区块编号。参见分叉规则
>>> from eth_tester import EthereumTester
>>> t = EthereumTester()
>>> t
<eth_tester.main.EthereumTester at 0x102255710>
分叉规则
以太坊测试库使用巴黎(PoS)分叉规则,从区块0开始。
时间旅行
链只能向前时间旅行。
EthereumTester.time_travel(timestamp)
timestamp
必须是整数,严格大于最新区块的当前时间戳。
注意:时间旅行将导致挖掘新的区块。
挖掘
可以使用以下API手动挖掘区块。这些方法的coinbase
参数必须是十六进制编码的地址。
EthereumTester.mine_blocks(num_blocks=1, coinbase=ZERO_ADDRESS)
挖掘num_blocks
个新区块,返回新挖掘区块的哈希值的可迭代对象。
EthereumTester.mine_block(coinbase=ZERO_ADDRESS)
挖掘单个新区块,返回挖掘区块的哈希值。
自动挖掘交易
默认情况下,所有交易都会立即挖掘。这意味着您发送的每笔交易都会导致挖掘新的区块,并且所有区块最多只有一个交易。可以使用以下方法控制此行为。
EthereumTester.enable_auto_mine_transactions()
打开交易自动挖掘。
EthereumTester.disable_auto_mine_transactions()
关闭交易自动挖掘。
账户
可以使用以下API与账户数据交互。这些方法中的account
参数必须是十六进制编码的地址。
返回测试者所知的账户的可迭代对象。列表中的所有账户都将进行EIP55校验。
>>> t.get_accounts()
('0x82A978B3f5962A5b0957d9ee9eEf472EE55B42F1',
'0x7d577a597B2742b498Cb5Cf0C26cDCD726d39E6e',
...
'0x90F0B1EBbbA1C1936aFF7AAf20a7878FF9e04B6c')
EthereumTester.add_account(private_key, password=None)
为指定的私钥添加新账户。返回添加账户的十六进制编码地址。
>>> t.add_account('0x58d23b55bc9cdce1f18c2500f40ff4ab7245df9a89505e9b1fa4851f623d241d')
'0xdc544d1aa88ff8bbd2f2aec754b1f1e99e1812fd'
默认情况下,添加的账户是解锁状态且没有密码。如果您想添加一个有密码的账户,可以将密码作为第二个参数提供。
>>> t.add_account('0x58d23b55bc9cdce1f18c2500f40ff4ab7245df9a89505e9b1fa4851f623d241d', 'my-secret')
'0xdc544d1aa88ff8bbd2f2aec754b1f1e99e1812fd'
EthereumTester.unlock_account(account, password, unlock_seconds=None)
如果提供的密码匹配,则解锁指定的账户。
如果
- 账户未知。
- 密码不匹配。
- 账户是在没有密码的情况下创建的。
>>> t.unlock_account('0xdc544d1aa88ff8bbd2f2aec754b1f1e99e1812fd', 'my-secret')
默认情况下,账户将无限期解锁。但是,您可以提供所需的持续时间(以秒为单位)来解锁账户指定的时间。
# unlock for 1 hour.
>>> t.unlock_account('0xdc544d1aa88ff8bbd2f2aec754b1f1e99e1812fd', 'my-secret', 60 * 60)
EthereumTester.lock_account(account)
锁定提供的账户。
如果
- 账户未知
- 账户没有密码。
EthereumTester.get_balance(account) -> 整数
返回指定账户的余额,单位为wei。
>>> t.get_balance('0x82A978B3f5962A5b0957d9ee9eEf472EE55B42F1')
1000004999999999999999999
EthereumTester.get_nonce(account) -> 整数
返回指定账户的nonce。
>>> t.get_nonce('0x82A978B3f5962A5b0957d9ee9eEf472EE55B42F1')
1
EthereumTester.get_code(account) -> 十六进制字符串
返回指定账户的代码。
>>> t.get_code('0x82A978B3f5962A5b0957d9ee9eEf472EE55B42F1')
"0x"
区块、交易和收据
EthereumTester.get_transaction_by_hash(transaction_hash) -> transaction-object
返回给定哈希的交易,如果找不到交易则抛出TransactionNotFound
异常。
>>> t.get_transaction_by_hash('0x21ae665f707e12a5f1bb13ef8c706b65cc5accfd03e7067ce683d831f51122e6')
{'type': '0x2',
'hash': '0x21ae665f707e12a5f1bb13ef8c706b65cc5accfd03e7067ce683d831f51122e6',
'nonce': 0,
'block_hash': '0x810731efeb7498fc0ac3bc7c72a71571b672c9fdbfbfd8b435f483e368e8ef7e',
'block_number': 1,
'transaction_index': 0,
'from': '0x2B5AD5c4795c026514f8317c7a215E218DcCD6cF',
'to': '0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf',
'value': 1337,
'gas': 21000,
'data': '0x',
'r': 1713666669454033023988006960017431058214051587080823768269189498559514600280,
's': 32003859822305799628524852194521134173285969678963273753063458725692016415033,
'v': 0,
'chain_id': 131277322940537,
'max_fee_per_gas': 2000000000,
'max_priority_fee_per_gas': 500000000,
'access_list': (),
'gas_price': 1375000000}
注意:对于未挖矿的交易,
transaction_index
、block_number
和block_hash
都将为None
。
EthereumTester.get_block_by_number(block_number, full_transactions=False) -> block-object
返回给定block_number
的区块。有关可使用的命名区块编号,请参阅区块编号。如果full_transactions
为真值,则事务数组将填充完整的事务对象,而不是它们的哈希。
如果找不到指定编号的区块,则抛出BlockNotFound
。
>>> t.get_block_by_number(1)
{'number': 1,
'hash': '0xd481955268d1f3db58ee61685a899a35e33e8fd35b9cc0812f85b9f06757140e',
'parent_hash': '0x5be984ab842071903ee443a5dee92603bef42de35b4e10928e753f7e88a7163a',
'nonce': '0x0000000000000000',
'sha3_uncles': '0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347',
'logs_bloom': 0,
'transactions_root': '0xef1e11d99f7db22fd93c6a10d44753d4a93e9f6ecb2f1e5030a0a91f1d3b07ac',
'receipts_root': '0x611e48488cf80b4c31f01ad45b6ebea533a68255a6d0240d434d9366a3582010',
'state_root': '0x9ce568dcaa6f130d733b333304f2c26a19334ed328a7eb9bb31707306381ba65',
'coinbase': '0x0000000000000000000000000000000000000000',
'difficulty': 0,
'total_difficulty': 0,
'mix_hash': '0x0000000000000000000000000000000000000000000000000000000000000000',
'size': 751,
'extra_data': '0x0000000000000000000000000000000000000000000000000000000000000000',
'gas_limit': 3141592,
'gas_used': 29600,
'timestamp': 1633669276,
'transactions': ('0xc20b90af87bc65c3d748cf0a1fa54f3a86ffc94348e0fd91a70f1c5ba6ef4109',),
'uncles': (),
'base_fee_per_gas': 875000000}
EthereumTester.get_block_by_hash(block_hash, full_transactions=True) -> block-object
返回给定block_hash
的区块。The full_transactions
参数的行为与get_block_by_number
中的相同。
如果找不到指定哈希的区块,则抛出BlockNotFound
。
>>> t.get_block_by_hash('0x0f50c8ea0f67ce0b7bff51ae866159edc443bde87de2ab26010a15b777244ddd')
{'number': 1,
'hash': '0xd481955268d1f3db58ee61685a899a35e33e8fd35b9cc0812f85b9f06757140e',
'parent_hash': '0x5be984ab842071903ee443a5dee92603bef42de35b4e10928e753f7e88a7163a',
'nonce': '0x0000000000000000',
'sha3_uncles': '0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347',
'logs_bloom': 0,
'transactions_root': '0xef1e11d99f7db22fd93c6a10d44753d4a93e9f6ecb2f1e5030a0a91f1d3b07ac',
'receipts_root': '0x611e48488cf80b4c31f01ad45b6ebea533a68255a6d0240d434d9366a3582010',
'state_root': '0x9ce568dcaa6f130d733b333304f2c26a19334ed328a7eb9bb31707306381ba65',
'coinbase': '0x0000000000000000000000000000000000000000',
'difficulty': 0,
'total_difficulty': 0,
'mix_hash': '0x0000000000000000000000000000000000000000000000000000000000000000',
'size': 751,
'extra_data': '0x0000000000000000000000000000000000000000000000000000000000000000',
'gas_limit': 3141592,
'gas_used': 29600,
'timestamp': 1633669276,
'transactions': ('0xc20b90af87bc65c3d748cf0a1fa54f3a86ffc94348e0fd91a70f1c5ba6ef4109',),
'uncles': (),
'base_fee_per_gas': 875000000}
EthereumTester.get_transaction_receipt(transaction_hash)
返回给定transaction_hash
的收据,如果找不到给定哈希的交易,则抛出TransactionNotFound
。
>>> t.get_transaction_receipt('0x9a7cc8b7accf54ecb1901bf4d0178f28ca457bb9f9c245692c0ca8fabef08d3b')
{'block_hash': '0x878f779d8bb25b25fb78fc16b8d64d70a5961310ef1689571aec632e9424290c',
'block_number': 2,
'contract_address': None,
'cumulative_gas_used': 23154,
'gas_used': 23154,
'logs': ({'address': '0xd6F084Ee15E38c4f7e091f8DD0FE6Fe4a0E203Ef',
'block_hash': '0x878f779d8bb25b25fb78fc16b8d64d70a5961310ef1689571aec632e9424290c',
'block_number': 2,
'data': '0x',
'log_index': 0,
'topics': (
'0xf70fe689e290d8ce2b2a388ac28db36fbb0e16a6d89c6804c461f65a1b40bb15',
'0x0000000000000000000000000000000000000000000000000000000000003039'),
'transaction_hash': '0x9a7cc8b7accf54ecb1901bf4d0178f28ca457bb9f9c245692c0ca8fabef08d3b',
'transaction_index': 0,
'type': 'mined'},),
'transaction_hash': '0x9a7cc8b7accf54ecb1901bf4d0178f28ca457bb9f9c245692c0ca8fabef08d3b',
'transaction_index': 0}
- 未挖矿交易的收据将把
block_hash
、block_number
和transaction_index
都设置为None
。 - 创建合约交易的收据将在
contract_address
字段中包含创建的合约地址。
交易发送
交易格式化为具有以下键和值的字典。
from
:发送交易的账户地址(十六进制字符串)。to
:交易要发送到的账户地址。应使用空字符串来触发合约创建(十六进制字符串)。gas
:设置交易执行期间的gas限制(整数)。value
:交易中应发送的以太币数量(单位为wei)。data
:交易的数据(十六进制字符串)。chain_id
:交易要与之交互的链的整数ID。
除了上述内容外,以下参数根据发送的交易类型而添加
遗留交易
gas_price
:设置每单位gas的wei价格,这将用于支付交易执行(整数)。
访问列表交易(EIP-2930)
gas_price
:设置每单位gas的wei价格,这将用于支付交易执行(整数)。access_list
(可选):根据交易指定预期访问的账户和存储槽位,以便在执行这些操作时获得气费折扣(请参阅快速入门示例以了解用法)。
动态费用交易(EIP-1559)
max_fee_per_gas
:设置每单位气气的最大费用(以wei为单位),用于交易执行(整数)。max_priority_fee_per_gas
:设置每单位气气的费用(以wei为单位),作为将交易包含在内的激励,发送到coinbase地址(整数)。access_list
(可选):根据交易指定预期访问的账户和存储槽位,以便在执行这些操作时获得气费折扣(请参阅快速入门示例以了解用法)。
方法
EthereumTester.send_transaction(transaction) -> transaction_hash
发送提供的 transaction
对象,返回已发送交易的交易哈希。
EthereumTester.call(transaction, block_number='latest')
在由 block_number
参数指定的区块的evm状态中执行提供的 transaction
对象,返回evm的结果字节返回值。
EthereumTester.estimate_gas(transaction, block_number='latest')
在由 block_number
参数指定的区块的evm状态中执行提供的 transaction
对象,测量并返回气消耗量。
EthereumTester.get_fee_history(block_count=1, newest_block='latest', reward_percentiles=[])
返回从 newest_block
开始的指定 block_count
个区块的历史气费信息。注意,指定 reward_percentiles
对响应没有影响,因此 reward
总是返回一个空列表。
日志和过滤器
EthereumTester.create_block_filter() -> integer
为新挖矿的区块创建一个新的过滤器。返回 filter_id
,可以用于检索已挖矿区块的区块哈希。
>>> filter_id = t.create_block_filter()
>>> filter_id = t.create_block_filter()
>>> t.mine_blocks(3)
>>> t.get_only_filter_changes(filter_id)
('0x07004287f82c1a7ab15d7b8baa03ac14d7e9167ab74e47e1dc4bd2213dd18431',
'0x5e3222c506585e1202da08c7231afdc5e472c777c245b822f44f141d335c744a',
'0x4051c3ba3dcca95da5db1be38e44f5b47fd1a855ba522123e3254fe3f8e271ea')
>>> t.mine_blocks(2)
>>> t.get_only_filter_changes(filter_id)
('0x6649c3a7cb3c7ede3a4fd10ae9dd63775eccdafe39ace5f5a9ae81d360089fba',
'0x04890a08bca0ed2f1496eb29c5dc7aa66014c85377c6d9d9c2c315f85204b39c')
>>> t.get_all_filter_logs(filter_id)
('0x07004287f82c1a7ab15d7b8baa03ac14d7e9167ab74e47e1dc4bd2213dd18431',
'0x5e3222c506585e1202da08c7231afdc5e472c777c245b822f44f141d335c744a',
'0x4051c3ba3dcca95da5db1be38e44f5b47fd1a855ba522123e3254fe3f8e271ea',
'0x6649c3a7cb3c7ede3a4fd10ae9dd63775eccdafe39ace5f5a9ae81d360089fba',
'0x04890a08bca0ed2f1496eb29c5dc7aa66014c85377c6d9d9c2c315f85204b39c')
EthereumTester.create_pending_transaction_filter() -> integer
为待处理交易创建一个新的过滤器。返回 filter_id
,可以用于检索待处理交易的交易哈希。
>>> filter_id = t.create_pending_transaction_filter()
>>> t.send_transaction({...})
'0x07f20bf9586e373ac914a40e99119c4932bee343d89ba852ccfc9af1fd541566'
>>> t.send_transaction({...})
'0xff85f7751d132b66c03e548e736f870797b0f24f3ed41dfe5fc628eb2cbc3505'
>>> t.get_only_filter_changes(filter_id)
('0x07f20bf9586e373ac914a40e99119c4932bee343d89ba852ccfc9af1fd541566',
'0xff85f7751d132b66c03e548e736f870797b0f24f3ed41dfe5fc628eb2cbc3505')
>>> t.send_transaction({...})
'0xb07801f7e8b1cfa52b64271fa2673c4b8d64cc21cdbc5fde51d5858c94c2d26a'
>>> t.get_only_filter_changes(filter_id)
('0xb07801f7e8b1cfa52b64271fa2673c4b8d64cc21cdbc5fde51d5858c94c2d26a',)
>>> t.get_all_filter_logs(filter_id)
('0x07f20bf9586e373ac914a40e99119c4932bee343d89ba852ccfc9af1fd541566',
'0xff85f7751d132b66c03e548e736f870797b0f24f3ed41dfe5fc628eb2cbc3505',
'0xb07801f7e8b1cfa52b64271fa2673c4b8d64cc21cdbc5fde51d5858c94c2d26a')
EthereumTester.create_log_filter(from_block=None, to_block=None, address=None, topics=None) -> integer
为由交易产生的日志创建一个新的过滤器。此函数的参数可以用于过滤日志条目。
>>> filter_id = t.create_log_filter()
>>> t.send_transaction({...}) # something that produces a log entry
'0x728bf75fc7d23845f328d2223df7fe9cafc6e7d23792457b625d5b60d2b22b7c'
>>> t.send_transaction({...}) # something that produces a log entry
'0x63f5b381ffd09940ce22c45a3f4e163bd743851cb6b4f43771fbf0b3c14b2f8a'
>>> t.get_only_filter_changes(filter_id)
({'address': '0xd6F084Ee15E38c4f7e091f8DD0FE6Fe4a0E203Ef',
'block_hash': '0x68c0f318388003b652eae334efbed8bd345c469bd0ca77469183fc9693c23e13',
'block_number': 11,
'data': '0x',
'log_index': 0,
'topics': ('0xf70fe689e290d8ce2b2a388ac28db36fbb0e16a6d89c6804c461f65a1b40bb15',
'0x0000000000000000000000000000000000000000000000000000000000003039'),
'transaction_hash': '0x728bf75fc7d23845f328d2223df7fe9cafc6e7d23792457b625d5b60d2b22b7c',
'transaction_index': 0,
'type': 'mined'},
{'address': '0xd6F084Ee15E38c4f7e091f8DD0FE6Fe4a0E203Ef',
'block_hash': '0x07d7e46be6f9ba53ecd4323fb99ec656e652c4b14f4b8e8a244ee7f997464725',
'block_number': 12,
'data': '0x',
'log_index': 0,
'topics': ('0xf70fe689e290d8ce2b2a388ac28db36fbb0e16a6d89c6804c461f65a1b40bb15',
'0x0000000000000000000000000000000000000000000000000000000000010932'),
'transaction_hash': '0x63f5b381ffd09940ce22c45a3f4e163bd743851cb6b4f43771fbf0b3c14b2f8a',
'transaction_index': 0,
'type': 'mined'})
EthereumTester.delete_filter(filter_id)
删除提供的 filter_id
的过滤器。如果找不到指定的 filter_id
的过滤器,则引发 FilterNotFound
。
EthereumTester.get_only_filter_changes(filter_id) -> transaction_hash or block_hash or log_entry
返回提供的 filter_id
的所有新值,这些值尚未通过此API返回。如果找不到指定的 filter_id
的过滤器,则引发 FilterNotFound
。
EthereumTester.get_all_filter_logs(filter_id) -> transaction_hash or block_hash or log_entry
返回提供的 filter_id
的所有值。如果找不到指定的 filter_id
的过滤器,则引发 FilterNotFound
。
快照和重置
EthereumTester.take_snapshot() -> snapshot_id
对当前链状态进行快照并返回快照ID。
EthereumTester.revert_to_snapshot(snapshot_id)
将链重置到与给定的 snapshot_id
关联的链状态。如果找不到给定ID的快照,则引发 SnapshotNotFound
。
错误和异常
eth_tester.exceptions.TransactionNotFound
在找不到提供的事务哈希时引发。
eth_tester.exceptions.BlockNotFound
在找不到提供编号或哈希的区块时引发。
eth_tester.exceptions.FilterNotFound
在找不到提供的过滤器ID的过滤器时引发。
eth_tester.exceptions.SnapshotNotFound
在找不到提供的快照ID的快照时引发。
后端
Ethereum测试器使用可插拔后端系统编写。
后端依赖
Ethereum测试器默认不安装使用各种后端所需的任何依赖项。但是,您可以使用以下方法安装带有必要依赖项的Ethereum测试器。
$ python -m pip install eth-tester[<backend-name>]
您应该将<backend-name>
替换为所需的测试后端名称。可用的后端有
py-evm
: PyEVM (alpha) (实验性)
选择后端
您可以通过几种不同的方式选择后端。
最直接的方式是手动传递您希望使用的后端实例。
>>> from eth_tester import EthereumTester, MockBackend
>>> t = EthereumTester(backend=MockBackend())
Ethereum tester还支持使用环境变量ETHEREUM_TESTER_CHAIN_BACKEND
进行配置。这应设置为要使用的后端类的导入路径。
可用的后端
Ethereum tester可以使用以下后端。
- MockBackend
- PyEVM (实验性)
MockBackend
此后端功能有限。它不能执行任何虚拟机计算。它模拟了所有对象和交互。
>>> from eth_tester import EthereumTester, MockBackend
>>> t = EthereumTester(MockBackend())
PyEVM (实验性)
警告 Py-EVM是实验性的,目前不应依赖它进行关键任务测试。
使用实验性Py-EVM库。
>>> from eth_tester import EthereumTester, PyEVMBackend
>>> t = EthereumTester(PyEVMBackend())
PyEVM创世参数和状态
如果您需要指定自定义创世参数和状态,可以构建自己的参数dict
来在初始化后端时使用默认值。只能覆盖默认值,否则将引发ValueError
。
# Default Genesis Parameters
default_genesis_params = {
"coinbase": GENESIS_COINBASE,
"difficulty": GENESIS_DIFFICULTY,
"extra_data": GENESIS_EXTRA_DATA,
"gas_limit": GENESIS_GAS_LIMIT,
"mix_hash": GENESIS_MIX_HASH,
"nonce": GENESIS_NONCE,
"receipt_root": BLANK_ROOT_HASH,
"timestamp": int(time.time()),
"transaction_root": BLANK_ROOT_HASH,
}
要生成一个带有覆盖参数的创世参数dict
,请传递一个genesis_overrides
dict
到PyEVM.generate_genesis_params
。
>>> from eth_tester import PyEVMBackend, EthereumTester
>>> genesis_overrides = {'gas_limit': 4500000}
>>> custom_genesis_params = PyEVMBackend.generate_genesis_params(overrides=genesis_overrides)
# Generates the following `dict`:
# custom_genesis_params = {
# "coinbase": GENESIS_COINBASE,
# "difficulty": GENESIS_DIFFICULTY,
# "extra_data": GENESIS_EXTRA_DATA,
# "gas_limit": 4500000 # <<< Overridden Value <<<
# "mix_hash": GENESIS_MIX_HASH,
# "nonce": GENESIS_NONCE,
# "receipt_root": BLANK_ROOT_HASH,
# "timestamp": int(time.time()),
# "transaction_root": BLANK_ROOT_HASH,
# }
然后将生成的custom_genesis_params
dict
传递给后端的__init__
>>> from eth_tester import PyEVMBackend, EthereumTester
>>> pyevm_backend = PyEVMBackend(genesis_parameters=custom_genesis_params)
>>> t = EthereumTester(backend=pyevm_backend)
与genesis_parameters
类似,通过传递一个overrides
dict
到PyEVMBackend.generate_genesis_state
来覆盖创世状态。可选地,提供num_accounts
来设置账户数量。
要获得对后端生成的账户的更多控制,请使用from_mnemonic()
类方法。给它一个mnemonic
(和可选的账户数量)并使用该信息生成账户。可选地,提供一个genesis_state_overrides
dict
来调整genesis_state
。
>>> from eth_tester import PyEVMBackend, EthereumTester
>>> from eth_utils import to_wei
>>> from hexbytes import HexBytes
>>>
>>> pyevm_backend = PyEVMBackend.from_mnemonic(
>>> 'test test test test test test test test test test test junk',
>>> genesis_state_overrides={'balance': to_wei(1000000, 'ether')}
>>> )
>>> t = EthereumTester(backend=pyevm_backend)
>>> print(t.get_accounts()[0]) # Outputs 0x1e59ce931B4CFea3fe4B875411e280e173cB7A9C
>>> print(t.get_balance('0x1e59ce931B4CFea3fe4B875411e280e173cB7A9C')) # Outputs 1000000000000000000000000
注意:相同的州应用于所有生成的测试账户。
# Default Account Genesis State
default_account_state = {
'balance': to_wei(1000000, 'ether'),
'storage': {},
'code': b'',
'nonce': 0,
}
例如,要创建3个测试账户,每个账户有100 ETH余额
>>> from eth_tester import EthereumTester, PyEVMBackend
>>> from eth_utils import to_wei
>>> state_overrides = {'balance': to_wei(100, 'ether')}
>>> custom_genesis_state = PyEVMBackend.generate_genesis_state(overrides=state_overrides, num_accounts=3)
# Then pass the generated `custom_genesis_state` `dict` to the backend's `__init__`
>>> pyevm_backend = PyEVMBackend(genesis_state=custom_genesis_state)
>>> t = EthereumTester(backend=pyevm_backend)
实现自定义后端
如果您想编写自己的后端,则建议从eth_tester.backends.base.BaseChainBackend
基类开始。
实现细节超出了本文件的范畴。
数据格式
Ethereum tester使用两种数据格式。
- 正常格式是所有
EthereumTester
方法的输入参数以及所有方法调用的返回类型所期望的数据格式。 - 规范格式是后端类内部使用的数据格式。
Ethereum tester对这些格式执行严格的验证规则。
规范格式
规范格式旨在由后端进行低级处理。
- 32字节散列:长度为32的
bytes
- 任意长度字符串:
bytes
- 地址:长度为20的
bytes
- 整数:
int
- 数组类型:
tuple
正常格式
正常格式旨在供最终用户使用。
- 32字节散列:以
0x
前缀的十六进制编码文本字符串(不是字节字符串) - 任意长度字符串:以
0x
前缀的十六进制编码文本字符串(不是字节字符串) - 地址:以
0x
前缀和EIP55校验和的十六进制编码文本字符串(不是字节字符串) - 整数:
int
- 数组类型:
tuple
规范化和验证
当心!这里充满了龙...本节文档仅适用于您打算在此库之上构建工具的情况。
以太坊测试器提供了强有力的保证,可以在不影响输入参数和返回值的数据格式的情况下无缝地替换后端。这是通过严格的规范化和验证两步过程实现的。
所有输入到EthereumTester
方法的输入首先进行验证,然后规范化到规范格式。返回值也经过这个过程,首先验证后端返回的数据,然后将其从规范格式规范化到正常格式,然后返回。
规范化
EthereumTester
将规范化委托给在实例化时传入的任何normalizer
。如果没有提供值,将使用来自eth_tester.normalization.default.DefaultNormalizer
的默认规范器。
此对象的具体内容超出了本文档的范围。
验证
EthereumTester
将验证委托给在实例化时传入的任何validator
。如果没有提供值,将使用来自eth_tester.validation.default.DefaultValidator
的默认验证器。
此对象的具体内容超出了本文档的范围。
与Web3.py一起使用
有关与该库集成的EthereumTester
提供程序的详细信息,请参阅web3.py文档。
开发者设置
如果您想对eth-tester进行开发,请查看蛇语者战术手册,了解我们如何进行
- 测试
- 拉取请求
- 文档
我们使用pre-commit来维护一致的代码风格。一旦安装,它将在每次提交时自动运行。您也可以通过make lint
手动运行它。如果您需要提交跳过pre-commit
检查的提交,可以使用git commit --no-verify
。
开发环境设置
您可以使用以下方法设置您的开发环境
git clone git@github.com:ethereum/eth-tester.git
cd eth-tester
virtualenv -p python3 venv
. venv/bin/activate
python -m pip install -e ".[dev]"
pre-commit install
发布设置
要发布新版本
make release bump=$$VERSION_PART_TO_BUMP$$
如何升级版本号
此存储库的版本格式为稳定版{major}.{minor}.{patch}
,不稳定版为{major}.{minor}.{patch}-{stage}.{devnum}
(stage
可以是alpha或beta)。
要发布下一个版本,指定要升级的部分,例如make release bump=minor
或make release bump=devnum
。这通常在主分支上进行,除非发布beta版(在这种情况下,beta版从主分支发布,之前的稳定版从该分支发布)。
如果您处于beta版,make release bump=stage
将切换到稳定版。
当当前版本是稳定版时,要发布不稳定版本,请明确指定新版本,例如make release bump="--new-version 4.0.0-alpha.1 devnum"
项目详情
下载文件
下载适合您平台的文件。如果您不确定该选择哪个,请了解有关安装包的更多信息。
源分布
构建分布
eth_tester-0.12.0b2.tar.gz 的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 2c2f32dd80bea32d5886d89dce444d598a8f1dd98a543b5f2564bc0f30a7ac1f |
|
MD5 | c56c01ddb12fa061d63e2a2f1cedcb20 |
|
BLAKE2b-256 | 22edf28c542e760adc5541f0e88bb2e28747fd6de8f2c7615b1e902d30d02ef5 |
eth_tester-0.12.0b2-py3-none-any.whl 的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 6b70afd1d75349220e05031618fd91c555b2fa8c3ff769c588078813aa9d42bc |
|
MD5 | 809b4de1506909e0ad73562f36cf1550 |
|
BLAKE2b-256 | e736ab2accfa7529b875366fbef281be159685866dd939f4f417c1dff4fa68b9 |