def _deploy_simple_token(self, chain: MiningChain) -> 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_tx = 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_tx['data']), ) logging.debug(f'Applying Transaction {tx}') block, receipt, computation = chain.apply_transaction(tx) # Keep track of deployed contract address self.deployed_contract_address = computation.msg.storage_address assert computation.is_success # Keep track of simple_token object self.simple_token = self.w3.eth.contract( address=Web3.toChecksumAddress( encode_hex(self.deployed_contract_address)), abi=self.contract_interface['abi'], )
def deploy_dos_contract(self, chain: MiningChain) -> None: # Instantiate the contract dos_contract = self.w3.eth.contract( abi=self.contract_interface['abi'], bytecode=self.contract_interface['bin'] ) # Build transaction to deploy the contract w3_tx1 = dos_contract.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(f'Applying Transaction {tx}') block, receipt, computation = chain.apply_transaction(tx) self.deployed_contract_address = computation.msg.storage_address assert computation.is_success # Interact with the deployed contract by calling the totalSupply() API ????? self.dos_contract = self.w3.eth.contract( address=Web3.toChecksumAddress(encode_hex(self.deployed_contract_address)), abi=self.contract_interface['abi'], )
def mine_blocks(num_blocks: int, chain: MiningChain) -> MiningChain: """ Variadic argument version of :func:`~eth.tools.builder.chain.mine_block` """ if not isinstance(chain, MiningChain): raise ValidationError('`mine_block` may only be used on MiningChain instances') for _ in range(num_blocks): chain.mine_block() return chain
def mine_block(chain: MiningChain, **kwargs: Any) -> MiningChain: """ Mine a new block on the chain. Header parameters for the new block can be overridden using keyword arguments. """ if not isinstance(chain, MiningChain): raise ValidationError('`mine_block` may only be used on MiningChain instances') chain.mine_block(**kwargs) return chain
def at_block_number(block_number: BlockNumber, chain: MiningChain) -> MiningChain: """ Rewind the chain back to the given block number. Calls to things like ``get_canonical_head`` will still return the canonical head of the chain, however, you can use ``mine_block`` to mine fork chains. """ if not isinstance(chain, MiningChain): raise ValidationError("`at_block_number` may only be used with 'MiningChain") at_block = chain.get_canonical_block_by_number(block_number) db = chain.chaindb.db chain_at_block = type(chain)(db, chain.create_header_from_parent(at_block.header)) return chain_at_block
def sstore_uint64_revert(self, chain: MiningChain) -> None: w3_tx4 = self.dos_contract.functions.storageEntropyRevert().buildTransaction(W3_TX_DEFAULTS) tx4 = new_transaction( vm=chain.get_vm(), private_key=FUNDED_ADDRESS_PRIVATE_KEY, from_=FUNDED_ADDRESS, to=self.deployed_contract_address, amount=0, gas=FORTH_TX_GAS_LIMIT, data=decode_hex(w3_tx4['data']), ) block, receipt, computation = chain.apply_transaction(tx4)
def apply_transaction(self, chain: MiningChain) -> 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 create_empty_contract_revert(self, chain: MiningChain) -> None: w3_tx5 = self.dos_contract.functions.createEmptyContractRevert().buildTransaction( W3_TX_DEFAULTS) tx5 = new_transaction( vm=chain.get_vm(), private_key=FUNDED_ADDRESS_PRIVATE_KEY, from_=FUNDED_ADDRESS, to=self.deployed_contract_address, amount=0, gas=FIFTH_TX_GAS_LIMIT, data=decode_hex(w3_tx5['data']), ) block, receipt, computation = chain.apply_transaction(tx5)
def next_transaction(self, chain: MiningChain) -> 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'', nonce=self._next_nonce, ) logging.debug(f'Built Transaction {tx}') self._next_nonce = tx.nonce + 1 def callback(receipt, computation) -> None: logging.debug(f'Receipt {receipt}') logging.debug(f'Computation {computation}') return tx, callback
def get_eth1_shell_context( database_dir: Path, trinity_config: TrinityConfig) -> Iterator[Dict[str, Any]]: app_config = trinity_config.get_app_config(Eth1AppConfig) ipc_path = trinity_config.database_ipc_path trinity_already_running = ipc_path.exists() with _get_base_db(database_dir, ipc_path) as db: chaindb = ChainDB(db) head = chaindb.get_canonical_head() chain_config = app_config.get_chain_config() chain = chain_config.full_chain_class(db) mining_chain_class = MiningChain.configure( __name__=chain_config.full_chain_class.__name__, vm_configuration=chain.vm_configuration, consensus_context_class=chain.consensus_context_class, chain_id=chain.chain_id, ) mining_chain = mining_chain_class(db) yield { 'db': db, 'chaindb': chaindb, 'trinity_config': trinity_config, 'chain_config': chain_config, 'chain': chain, 'mining_chain': mining_chain, 'block_number': head.block_number, 'hex_hash': head.hex_hash, 'state_root_hex': encode_hex(head.state_root), 'trinity_already_running': trinity_already_running, }
def chain_without_block_validation( base_db, genesis_state): """ Return a Chain object containing just the genesis block. This Chain does not perform any validation when importing new blocks. The Chain's state includes one funded account and a private key for it, which can be found in the funded_address and private_keys variables in the chain itself. """ klass = MiningChain.configure( __name__='TestChainWithoutBlockValidation', vm_configuration=ConsensusApplier(NoProofConsensus).amend_vm_configuration( ( (eth_constants.GENESIS_BLOCK_NUMBER, SpuriousDragonVM), ) ), chain_id=1337, ) genesis_params = { 'block_number': eth_constants.GENESIS_BLOCK_NUMBER, 'difficulty': eth_constants.GENESIS_DIFFICULTY, 'gas_limit': 3141592, 'parent_hash': eth_constants.GENESIS_PARENT_HASH, 'coinbase': eth_constants.GENESIS_COINBASE, 'nonce': eth_constants.GENESIS_NONCE, 'mix_hash': eth_constants.GENESIS_MIX_HASH, 'extra_data': eth_constants.GENESIS_EXTRA_DATA, 'timestamp': 1501851927, } chain = klass.from_genesis(base_db, genesis_params, genesis_state) return chain
def _setup_benchmark(self, chain: MiningChain) -> None: self._next_nonce = None txn, callback = self._deploy_simple_token(chain) _, receipts, computations = chain.mine_all([txn]) assert len(receipts) == 1 assert len(computations) == 1 callback(receipts[0], computations[0])
def _deploy_simple_token(self, chain: MiningChain, nonce: int = None) -> 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_tx = 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_tx['data']), nonce=nonce, ) def callback(receipt, computation) -> None: computation.raise_if_error() # Keep track of deployed contract address self.deployed_contract_address = computation.msg.storage_address # Keep track of simple_token object self.simple_token = self.w3.eth.contract( address=Web3.toChecksumAddress( encode_hex(self.deployed_contract_address)), abi=self.contract_interface['abi'], ) return tx, callback
def _erc_transfer_from(self, addr1: str, addr2: str, chain: MiningChain, nonce: int = None) -> None: w3_tx = self.simple_token.functions.transferFrom( addr1, addr2, TRANSER_FROM_AMOUNT).buildTransaction(W3_TX_DEFAULTS) tx = new_transaction( vm=chain.get_vm(), private_key=SECOND_ADDRESS_PRIVATE_KEY, from_=SECOND_ADDRESS, to=self.deployed_contract_address, amount=0, gas=SECOND_TX_GAS_LIMIT, data=decode_hex(w3_tx['data']), nonce=nonce, ) def callback(receipt, computation) -> None: computation.raise_if_error() assert computation.output == b'\0' * 31 + b'\x01', computation.output return tx, callback
def mine_block(self, chain: MiningChain, block_number: int, num_tx: int) -> BaseBlock: for i in range(1, num_tx + 1): self.apply_transaction(chain) return chain.mine_block()
def get_eth1_shell_context(database_dir: Path, trinity_config: TrinityConfig) -> Dict[str, Any]: app_config = trinity_config.get_app_config(Eth1AppConfig) ipc_path = trinity_config.database_ipc_path db: DatabaseAPI trinity_already_running = ipc_path.exists() if trinity_already_running: db = DBClient.connect(ipc_path) else: db = LevelDB(database_dir) chaindb = ChainDB(db) head = chaindb.get_canonical_head() chain_config = app_config.get_chain_config() chain = chain_config.full_chain_class(db) mining_chain_class = MiningChain.configure( __name__=chain_config.full_chain_class.__name__, vm_configuration=chain.vm_configuration, chain_id=chain.chain_id, ) mining_chain = mining_chain_class(db) return { 'db': db, 'chaindb': chaindb, 'trinity_config': trinity_config, 'chain_config': chain_config, 'chain': chain, 'mining_chain': mining_chain, 'block_number': head.block_number, 'hex_hash': head.hex_hash, 'state_root_hex': encode_hex(head.state_root), 'trinity_already_running': trinity_already_running, }
def _setup_benchmark(self, chain: MiningChain) -> None: self._next_nonce = None txn, callback = self._deploy_simple_token(chain) _, receipts, computations = chain.mine_all([txn]) assert len(receipts) == 1 assert len(computations) == 1 callback(receipts[0], computations[0]) actions = [ self._erc_transfer(self.addr1, chain, nonce=1), self._erc_approve(self.addr2, chain, nonce=2), ] transactions, callbacks = zip(*actions) _, receipts, computations = chain.mine_all(transactions) for callback, receipt, computation in zip(callbacks, receipts, computations): callback(receipt, computation)
def _erc_approve(self, addr2: str, chain: MiningChain) -> None: w3_tx = self.simple_token.functions.approve( addr2, TRANSFER_AMOUNT).buildTransaction(W3_TX_DEFAULTS) tx = new_transaction( vm=chain.get_vm(), private_key=FUNDED_ADDRESS_PRIVATE_KEY, from_=FUNDED_ADDRESS, to=self.deployed_contract_address, amount=0, gas=SECOND_TX_GAS_LIMIT, data=decode_hex(w3_tx['data']), ) block, receipt, computation = chain.apply_transaction(tx) assert computation.is_success assert to_int(computation.output) == 1
def chain_without_pow(base_db: AtomicDB, vm: Type[BaseVM], genesis_params: Any, genesis_state: Any) -> MiningChain: vm_without_pow = vm.configure(validate_seal=lambda block: None) klass = MiningChain.configure( __name__='TestChain', vm_configuration=((constants.GENESIS_BLOCK_NUMBER, vm_without_pow), )) chain = klass.from_genesis(base_db, genesis_params, genesis_state) return chain
def mine_blocks(self, chain: MiningChain, 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 mine_block(self, chain: MiningChain, block_number: int, num_tx: int) -> BaseBlock: transactions, callbacks = zip(*(self._next_transaction(chain) for _ in range(num_tx))) mining_result, receipts, computations = chain.mine_all(transactions) for callback, receipt, computation in zip(callbacks, receipts, computations): callback(receipt, computation) return mining_result
def apply_transaction(self, chain: MiningChain) -> 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))
def _erc_transfer_from(self, addr1: str, addr2: str, chain: MiningChain) -> None: w3_tx = self.simple_token.functions.transferFrom( addr1, addr2, TRANSER_FROM_AMOUNT).buildTransaction(W3_TX_DEFAULTS) tx = new_transaction( vm=chain.get_vm(), private_key=SECOND_ADDRESS_PRIVATE_KEY, from_=SECOND_ADDRESS, to=self.deployed_contract_address, amount=0, gas=SECOND_TX_GAS_LIMIT, data=decode_hex(w3_tx['data']), ) block, receipt, computation = chain.apply_transaction(tx) computation.raise_if_error() assert to_int(computation.output) == 1
def goerli_chain(base_db): vms = (( 0, PetersburgVM, ), ) clique_vms = CliqueApplier().amend_vm_configuration(vms) chain = MiningChain.configure( vm_configuration=clique_vms, consensus_context_class=CliqueConsensusContext, chain_id=5, ).from_genesis_header(base_db, GOERLI_GENESIS_HEADER) return chain
def main(): args = parse_args() # print('Called with args:') # print(args) # genesis address init_address = to_canonical_address( "8888f1f195afa192cfee860698584c030f4c9db1") base_state = base_genesis_state(init_address, funded_address_initial_balance()) # just an address simple_contract_address = create_simple_contract_address() # create chain klass = MiningChain.configure( __name__='MyTestChain', vm_configuration=((constants.GENESIS_BLOCK_NUMBER, SpuriousDragonVM), ), network_id=1337, ) chain = klass.from_genesis( MemoryDB(), GENESIS_PARAMS, genesis_state(base_state, simple_contract_address, args.data)) # TODO # signature = 'getMeaningOfLife()' # function name # function_selector = function_signature_to_4byte_selector(signature) ''' new_transaction( vm, from_, to, amount=0, private_key=None, gas_price=10, gas=100000, data=b'' ) ''' call_txn = new_transaction( chain.get_vm(), SENDER, simple_contract_address, gas_price=0, # data=function_selector, data=decode_hex(args.signature), ) result_bytes = chain.get_transaction_result(call_txn, chain.get_canonical_head())
def _configure_mining_chain(starting_vm, vm_under_test): return MiningChain.configure( __name__="AllVMs", vm_configuration=( ( constants.GENESIS_BLOCK_NUMBER, starting_vm.configure(consensus_class=NoProofConsensus), ), ( constants.GENESIS_BLOCK_NUMBER + 1, vm_under_test.configure(consensus_class=NoProofConsensus), ), ), chain_id=1337, )
def make_chain(self): klass = MiningChain.configure( __name__='Shard{}Chain'.format(self.shard_id), vm_configuration=((constants.GENESIS_BLOCK_NUMBER, ByzantiumVM), )) self.chain = klass.from_genesis(AtomicDB(), self.genesis_params, self.genesis_state) self.vm = self.chain.get_vm() print("Shard " + str(self.shard_id) + " was initialized") print("Parent Shard ID:", self.parent_id) print("Child Shard IDs:", self.child_ids) print("\tAccounts on this shard are:") for address in self.accounts['addresses']: print("\t\t", encode_hex(address)) print("\tMagic Account is:") print("\t\t", encode_hex(MAGIC_ADDRESS)) return self.chain
def paragon_chain_with_clique(base_db): vms = (( 0, PetersburgVM, ), ) clique = CliqueConsensus(base_db) vms = clique.amend_vm_configuration(vms) chain = MiningChain.configure( vm_configuration=vms, chain_id=5, ).from_genesis(base_db, PARAGON_GENESIS_PARAMS, PARAGON_GENESIS_STATE) return chain, clique
def paragon_chain(base_db): vms = (( 0, PetersburgVM, ), ( 2, IstanbulVM, )) clique_vms = CliqueApplier().amend_vm_configuration(vms) chain = MiningChain.configure( vm_configuration=clique_vms, consensus_context_class=CliqueConsensusContext, chain_id=5, ).from_genesis(base_db, PARAGON_GENESIS_PARAMS, PARAGON_GENESIS_STATE) return chain
def vm_crossover_chain(request, base_db, genesis_state): start_vm, end_vm = request.param klass = MiningChain.configure( __name__='CrossoverTestChain', vm_configuration=( ( constants.GENESIS_BLOCK_NUMBER, start_vm.configure(consensus_class=NoProofConsensus), ), # Can mine one block of the first VM, then the next block with be the next VM ( constants.GENESIS_BLOCK_NUMBER + 2, end_vm.configure(consensus_class=NoProofConsensus), ), ), chain_id=1337, ) return klass.from_genesis(base_db, dict(difficulty=1), genesis_state)