跳转到主要内容

eth-tester:用于测试以太坊应用的工具。

项目描述

eth-tester

Join the conversation on Discord Build Status PyPI version Python versions

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入口点。实例化此对象接受以下参数。

>>> 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参数必须是十六进制编码的地址。

EthereumTester.get_accounts()

返回测试者所知的账户的可迭代对象。列表中的所有账户都将进行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_indexblock_numberblock_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_hashblock_numbertransaction_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>替换为所需的测试后端名称。可用的后端有

选择后端

您可以通过几种不同的方式选择后端。

最直接的方式是手动传递您希望使用的后端实例。

>>> 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 dictPyEVMBackend.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=minormake release bump=devnum。这通常在主分支上进行,除非发布beta版(在这种情况下,beta版从主分支发布,之前的稳定版从该分支发布)。

如果您处于beta版,make release bump=stage将切换到稳定版。

当当前版本是稳定版时,要发布不稳定版本,请明确指定新版本,例如make release bump="--new-version 4.0.0-alpha.1 devnum"

项目详情


发布历史 发布通知 | RSS源

下载文件

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

源分布

eth_tester-0.12.0b2.tar.gz (99.5 kB 查看哈希值)

上传时间

构建分布

eth_tester-0.12.0b2-py3-none-any.whl (75.2 kB 查看哈希值)

上传时间 Python 3

由以下机构支持