def import_empty_blocks(self, chain: Chain, number_blocks: int) -> int: total_gas_used = 0 for _ in range(1, number_blocks + 1): block = chain.import_block(chain.get_vm().block, False) total_gas_used = total_gas_used + block.header.gas_used logging.debug(format_block(block)) return total_gas_used
def apply_transaction(self, chain: Chain) -> None: # Instantiate the contract SimpleToken = self.w3.eth.contract( abi=self.contract_interface['abi'], bytecode=self.contract_interface['bin']) # Build transaction to deploy the contract w3_tx1 = SimpleToken.constructor().buildTransaction(W3_TX_DEFAULTS) tx = new_transaction( vm=chain.get_vm(), private_key=FUNDED_ADDRESS_PRIVATE_KEY, from_=FUNDED_ADDRESS, to=CREATE_CONTRACT_ADDRESS, amount=0, gas=FIRST_TX_GAS_LIMIT, data=decode_hex(w3_tx1['data']), ) logging.debug('Applying Transaction {}'.format(tx)) block, receipt, computation = chain.apply_transaction(tx) deployed_contract_address = computation.msg.storage_address assert computation.is_success # Interact with the deployed contract by calling the totalSupply() API simple_token = self.w3.eth.contract( address=Web3.toChecksumAddress( encode_hex(deployed_contract_address)), abi=self.contract_interface['abi'], ) w3_tx2 = simple_token.functions.totalSupply().buildTransaction( W3_TX_DEFAULTS) tx2 = new_transaction( vm=chain.get_vm(), private_key=FUNDED_ADDRESS_PRIVATE_KEY, from_=FUNDED_ADDRESS, to=deployed_contract_address, amount=0, gas=SECOND_TX_GAS_LIMIT, data=decode_hex(w3_tx2['data']), ) block, receipt, computation = chain.apply_transaction(tx2) assert computation.is_success assert to_int(computation.output) == EXPECTED_TOTAL_SUPPLY
def mine_block(self, chain: Chain, block_number: int, num_tx: int) -> BaseBlock: for i in range(1, num_tx + 1): self.apply_transaction(chain) return chain.mine_block()
def mine_blocks(self, chain: Chain, num_blocks: int) -> Tuple[int, int]: total_gas_used = 0 total_num_tx = 0 for i in range(1, num_blocks + 1): num_tx = chain.get_block( ).header.gas_limit // SIMPLE_VALUE_TRANSFER_GAS_COST block = self.mine_block(chain, i, num_tx) total_num_tx = total_num_tx + len(block.transactions) total_gas_used = total_gas_used + block.header.gas_used return total_gas_used, total_num_tx
def apply_transaction(self, chain: Chain) -> None: if self.config.to_address is None: to_address = generate_random_address() else: to_address = self.config.to_address tx = new_transaction(vm=chain.get_vm(), private_key=FUNDED_ADDRESS_PRIVATE_KEY, from_=FUNDED_ADDRESS, to=to_address, amount=100, data=b'') logging.debug('Applying Transaction {}'.format(tx)) block, receipt, computation = chain.apply_transaction(tx) logging.debug('Block {}'.format(block)) logging.debug('Receipt {}'.format(receipt)) logging.debug('Computation {}'.format(computation))
SpuriousDragonVM, TangerineWhistleVM, ) ROPSTEN_VM_CONFIGURATION = ( # Note: Frontier and Homestead are excluded since this chain starts at Tangerine Whistle. (TANGERINE_WHISTLE_ROPSTEN_BLOCK, TangerineWhistleVM), (SPURIOUS_DRAGON_ROPSTEN_BLOCK, SpuriousDragonVM), (BYZANTIUM_ROPSTEN_BLOCK, ByzantiumVM), ) ROPSTEN_NETWORK_ID = 3 RopstenChain = Chain.configure( 'RopstenChain', vm_configuration=ROPSTEN_VM_CONFIGURATION, network_id=ROPSTEN_NETWORK_ID, ) ROPSTEN_GENESIS_HEADER = BlockHeader( difficulty=1048576, extra_data=decode_hex( "0x3535353535353535353535353535353535353535353535353535353535353535"), gas_limit=16777216, gas_used=0, bloom=0, mix_hash=constants.ZERO_HASH32, nonce=constants.GENESIS_NONCE, block_number=0, parent_hash=constants.ZERO_HASH32, receipt_root=constants.BLANK_ROOT_HASH,
ByzantiumVM, ) MAINNET_VM_CONFIGURATION = ( (0, FrontierVM), (HOMESTEAD_MAINNET_BLOCK, HomesteadVM), (TANGERINE_WHISTLE_MAINNET_BLOCK, TangerineWhistleVM), (SPURIOUS_DRAGON_MAINNET_BLOCK, SpuriousDragonVM), (BYZANTIUM_MAINNET_BLOCK, ByzantiumVM), ) MAINNET_NETWORK_ID = 1 MainnetChain = Chain.configure( 'MainnetChain', vm_configuration=MAINNET_VM_CONFIGURATION, network_id=MAINNET_NETWORK_ID, ) MAINNET_GENESIS_HEADER = BlockHeader( difficulty=17179869184, extra_data=decode_hex( "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa"), gas_limit=5000, gas_used=0, bloom=0, mix_hash=constants.ZERO_HASH32, nonce=constants.GENESIS_NONCE, block_number=0, parent_hash=constants.ZERO_HASH32, receipt_root=constants.BLANK_ROOT_HASH,
def test_vm_not_found_if_no_matching_block_number(genesis_header): chain_class = Chain.configure('ChainStartsAtBlock10', vm_configuration=( (10, VM_A), )) with pytest.raises(VMNotFound): chain_class.get_vm_class_for_block_number(9)
def chain_with_block_validation(base_db, funded_address, funded_address_initial_balance): """ Return a Chain object containing just the genesis block. The Chain's state includes one funded account, which can be found in the funded_address in the chain itself. This Chain will perform all validations when importing new blocks, so only valid and finalized blocks can be used with it. If you want to test importing arbitrarily constructe, not finalized blocks, use the chain_without_block_validation fixture instead. """ genesis_params = { "bloom": 0, "coinbase": to_canonical_address("8888f1f195afa192cfee860698584c030f4c9db1"), "difficulty": 131072, "extra_data": b"B", "gas_limit": 3141592, "gas_used": 0, "mix_hash": decode_hex( "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" ), # noqa: E501 "nonce": decode_hex("0102030405060708"), "block_number": 0, "parent_hash": decode_hex( "0000000000000000000000000000000000000000000000000000000000000000" ), # noqa: E501 "receipt_root": decode_hex( "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" ), # noqa: E501 "timestamp": 1422494849, "transaction_root": decode_hex( "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" ), # noqa: E501 "uncles_hash": decode_hex( "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" ) # noqa: E501 } genesis_state = { funded_address: { "balance": funded_address_initial_balance, "nonce": 0, "code": b"", "storage": {} } } klass = Chain.configure( __name__='TestChain', vm_configuration=((constants.GENESIS_BLOCK_NUMBER, SpuriousDragonVM), ), network_id=1337, ) chain = klass.from_genesis(base_db, genesis_params, genesis_state) return chain
yield (start_block, vm_class.configure(support_dao_fork=False)) elif dao_start_block is None: yield (start_block, vm_class.configure(dao_fork_block_number=start_block)) elif isinstance(dao_start_block, int): validate_gte(dao_start_block, start_block) yield (start_block, vm_class.configure( dao_fork_block_number=dao_start_block)) else: raise Exception("Invariant: unreachable code path") else: yield (start_block, vm_class) BaseMainnetTesterChain = Chain.configure( 'MainnetTesterChain', vm_configuration=_generate_vm_configuration()) class MainnetTesterChain(BaseMainnetTesterChain): # type: ignore """ This class is intended to be used for in-memory test chains. It explicitely bypasses the proof of work validation to allow for instant block mining. It exposes one additional API `configure_forks` to allow for in-flight configuration of fork rules. """ def validate_seal(self, block): """ We don't validate the proof of work seal on the tester chain. """
def mine_empty_blocks(self, chain: Chain, number_blocks: int) -> None: for _ in range(1, number_blocks + 1): block = chain.mine_block() logging.debug(format_block(block))