def add_log_entry(self, account: Address, topics: Tuple[int, ...], data: bytes) -> None: validate_canonical_address(account, title="Log entry address") for topic in topics: validate_uint256(topic, title="Log entry topic") validate_is_bytes(data, title="Log entry data") self._log_entries.append( (self.transaction_context.get_next_log_counter(), account, topics, data))
def extend_memory(self, start_position: int, size: int) -> None: validate_uint256(start_position, title="Memory start position") validate_uint256(size, title="Memory size") before_size = ceil32(len(self._memory)) after_size = ceil32(start_position + size) before_cost = memory_gas_cost(before_size) after_cost = memory_gas_cost(after_size) if self.logger.show_debug2: self.logger.debug2( "MEMORY: size (%s -> %s) | cost (%s -> %s)", before_size, after_size, before_cost, after_cost, ) if size: if before_cost < after_cost: gas_fee = after_cost - before_cost self._gas_meter.consume_gas(gas_fee, reason=" ".join(( "Expanding memory", str(before_size), "->", str(after_size), ))) self._memory.extend(start_position, size)
def set_vm(self, block_identifier='latest'): _block = None if self.w3: if block_identifier == 'latest': block_identifier = self.w3.eth.blockNumber validate_uint256(block_identifier) _block = self.w3.eth.getBlock(block_identifier) if not _block: if block_identifier in [ HOMESTEAD_MAINNET_BLOCK, BYZANTIUM_MAINNET_BLOCK, PETERSBURG_MAINNET_BLOCK ]: _block = self.get_cached_block_by_id(block_identifier) else: self.logger.error("Unknown block identifier.") sys.exit(-4) block_header = BlockHeader( difficulty=_block.difficulty, block_number=_block.number, gas_limit=_block.gasLimit, timestamp=_block.timestamp, coinbase=ZERO_ADDRESS, # default value parent_hash=_block.parentHash, uncles_hash=_block.uncles, state_root=_block.stateRoot, transaction_root=_block.transactionsRoot, receipt_root=_block.receiptsRoot, bloom=0, # default value gas_used=_block.gasUsed, extra_data=_block.extraData, mix_hash=_block.mixHash, nonce=_block.nonce) self.vm = self.chain.get_vm(block_header)
def __init__(self, start_gas: int) -> None: validate_uint256(start_gas, title="Start Gas") self.start_gas = start_gas self.gas_remaining = self.start_gas self.gas_refunded = 0
def extend_memory(self, start_position: int, size: int) -> None: """ Extend the size of the memory to be at minimum ``start_position + size`` bytes in length. Raise `eth.exceptions.OutOfGas` if there is not enough gas to pay for extending the memory. """ validate_uint256(start_position, title="Memory start position") validate_uint256(size, title="Memory size") before_size = ceil32(len(self._memory)) after_size = ceil32(start_position + size) before_cost = memory_gas_cost(before_size) after_cost = memory_gas_cost(after_size) self.logger.trace( "MEMORY: size (%s -> %s) | cost (%s -> %s)", before_size, after_size, before_cost, after_cost, ) if size: if before_cost < after_cost: gas_fee = after_cost - before_cost self._gas_meter.consume_gas(gas_fee, reason=" ".join(( "Expanding memory", str(before_size), "->", str(after_size), ))) self._memory.extend(start_position, size)
def set_storage(self, address: Address, slot: int, value: int) -> None: validate_uint256(value, title="Storage Value") validate_uint256(slot, title="Storage Slot") validate_canonical_address(address, title="Storage Address") if address not in self._storage_emulator: self._storage_emulator[address] = dict() self._storage_emulator[address][slot] = value
def __init__(self, chain_id: Optional[int]) -> None: if chain_id is None: chain_id = 0 # Default value (invalid for public networks) # Due to EIP-155's definition of Chain ID, # the number that needs to be RLP encoded is `CHAINID * 2 + 36` validate_uint256(chain_id) self._chain_id = chain_id
def set_storage(self, address: Address, slot: int, value: int) -> None: validate_uint256(value, title="Storage Value") validate_uint256(slot, title="Storage Slot") validate_canonical_address(address, title="Storage Address") account_store = self._get_address_store(address) self._dirty_accounts.add(address) account_store.set(slot, value)
def get_storage(self, address: Address, slot: int, from_journal: bool = True) -> int: validate_canonical_address(address, title="Storage Address") validate_uint256(slot, title="Storage Slot") account_store = self._get_address_store(address) return account_store.get(slot, from_journal)
def get_canonical_block_by_number(self, block_number: BlockNumber) -> BaseBlock: """ Returns the block with the given number in the canonical chain. Raises BlockNotFound if there's no block with the given number in the canonical chain. """ validate_uint256(block_number, title="Block Number") return self.get_block_by_hash(self.chaindb.get_canonical_block_hash(block_number))
def __init__(self, start_gas: int, refund_strategy: RefundStrategy = default_refund_strategy) -> None: validate_uint256(start_gas, title="Start Gas") self.refund_strategy = refund_strategy self.start_gas = start_gas self.gas_remaining = self.start_gas self.gas_refunded = 0
def write(self, start_position: int, size: int, value: bytes) -> None: if size: validate_uint256(start_position) validate_uint256(size) validate_is_bytes(value) validate_length(value, length=size) validate_lte(start_position + size, maximum=len(self)) for idx, v in enumerate(value): self._bytes[start_position + idx] = v
def validate(self) -> None: validate_uint256(self.chain_id, title="Transaction.chain_id") validate_uint256(self.nonce, title="Transaction.nonce") validate_uint256(self.gas_price, title="Transaction.gas_price") validate_uint256(self.gas, title="Transaction.gas") if self.to != CREATE_CONTRACT_ADDRESS: validate_canonical_address(self.to, title="Transaction.to") validate_uint256(self.value, title="Transaction.value") validate_is_bytes(self.data, title="Transaction.data") validate_is_transaction_access_list(self.access_list)
def __init__(self, gas: int, to: Address, sender: Address, value: int, data: BytesOrView, code: bytes, depth: int = 0, create_address: Address = None, code_address: Address = None, should_transfer_value: bool = True, is_static: bool = False) -> None: validate_uint256(gas, title="Message.gas") self.gas: int = gas if to != CREATE_CONTRACT_ADDRESS: validate_canonical_address(to, title="Message.to") self.to = to validate_canonical_address(sender, title="Message.sender") self.sender = sender validate_uint256(value, title="Message.value") self.value = value validate_is_bytes_or_view(data, title="Message.data") self.data = data validate_is_integer(depth, title="Message.depth") validate_gte(depth, minimum=0, title="Message.depth") self.depth = depth validate_is_bytes(code, title="Message.code") self.code = code if create_address is not None: validate_canonical_address(create_address, title="Message.storage_address") self.storage_address = create_address if code_address is not None: validate_canonical_address(code_address, title="Message.code_address") self.code_address = code_address validate_is_boolean(should_transfer_value, title="Message.should_transfer_value") self.should_transfer_value = should_transfer_value validate_is_boolean(is_static, title="Message.is_static") self.is_static = is_static
def get_storage(self, address, slot): validate_canonical_address(address, title="Storage Address") validate_uint256(slot, title="Storage Slot") account = self._get_account(address) storage = HashTrie(HexaryTrie(self._journaldb, account.storage_root)) slot_as_key = pad32(int_to_big_endian(slot)) if slot_as_key in storage: encoded_value = storage[slot_as_key] return rlp.decode(encoded_value, sedes=rlp.sedes.big_endian_int) else: return 0
def set_storage(self, address: Address, slot: int, value: int) -> None: validate_uint256(value, title="Storage Value") validate_uint256(slot, title="Storage Slot") validate_canonical_address(address, title="Storage Address") account = self._get_account(address) storage = HashTrie(HexaryTrie(self._journaldb, account.storage_root)) slot_as_key = pad32(int_to_big_endian(slot)) if value: encoded_value = rlp.encode(value) storage[slot_as_key] = encoded_value else: del storage[slot_as_key] self._set_account(address, account.copy(storage_root=storage.root_hash))
def write(self, start_position: int, size: int, value: bytes) -> None: """ Write `value` into memory. """ if size: validate_uint256(start_position) validate_uint256(size) validate_is_bytes(value) validate_length(value, length=size) validate_lte(start_position + size, maximum=len(self)) if len(self._bytes) < start_position + size: self._bytes.extend( itertools.repeat( 0, len(self._bytes) - (start_position + size), )) for idx, v in enumerate(value): self._bytes[start_position + idx] = v
def get_storage(self, address: Address, slot: int, from_journal: bool = True) -> int: validate_canonical_address(address, title="Storage Address") validate_uint256(slot, title="Storage Slot") if address in self._storage_emulator and slot in self._storage_emulator[ address] or not self._remote: try: return self._storage_emulator[address][slot] except KeyError: return 0 else: result = self._remote.getStorageAt(address, slot, "latest") result = to_int(result.hex()) self.set_storage(address, slot, result) if self.snapshot != None: if address not in self.snapshot["storage"]: self.snapshot["storage"][address] = dict() self.snapshot["storage"][address][slot] = result return result
def validate(self) -> None: validate_uint256(self.nonce, title="Transaction.nonce") validate_is_integer(self.gas_price, title="Transaction.gas_price") validate_uint256(self.gas, title="Transaction.gas") if self.to != CREATE_CONTRACT_ADDRESS: validate_canonical_address(self.to, title="Transaction.to") validate_uint256(self.value, title="Transaction.value") validate_is_bytes(self.data, title="Transaction.data") super().validate()
def __init__(self, gas_price: int, origin: Address) -> None: validate_uint256(gas_price, title="TransactionContext.gas_price") self._gas_price = gas_price validate_canonical_address(origin, title="TransactionContext.origin") self._origin = origin self._log_counter = itertools.count()
def validate(self) -> None: validate_uint256(self.nonce, title="Transaction.nonce") validate_uint256(self.gas_price, title="Transaction.gas_price") validate_uint256(self.gas, title="Transaction.gas") if self.to != CREATE_CONTRACT_ADDRESS: validate_canonical_address(self.to, title="Transaction.to") validate_uint256(self.value, title="Transaction.value") validate_is_bytes(self.data, title="Transaction.data") validate_uint256(self.v, title="Transaction.v") validate_uint256(self.r, title="Transaction.r") validate_uint256(self.s, title="Transaction.s") validate_lt_secpk1n(self.r, title="Transaction.r") validate_gte(self.r, minimum=1, title="Transaction.r") validate_lt_secpk1n(self.s, title="Transaction.s") validate_gte(self.s, minimum=1, title="Transaction.s") validate_gte(self.v, minimum=self.v_min, title="Transaction.v") validate_lte(self.v, maximum=self.v_max, title="Transaction.v") super().validate()
def set_nonce(self, address: Address, nonce: int) -> None: validate_canonical_address(address, title="Storage Address") validate_uint256(nonce, title="Nonce") account = self._get_account(address) self._set_account(address, account.copy(nonce=nonce))
def set_balance(self, address, balance): validate_canonical_address(address, title="Storage Address") validate_uint256(balance, title="Account Balance") account = self._get_account(address) self._set_account(address, account.copy(balance=balance))
def test_validate_uint256(value, is_valid): if is_valid: validate_uint256(value) else: with pytest.raises(ValidationError): validate_uint256(value)
def get_canonical_block_by_number(self, block_number: BlockNumber) -> BlockAPI: validate_uint256(block_number, title="Block Number") return self.get_block_by_hash(self.chaindb.get_canonical_block_hash(block_number))
def get_block_by_blockid(self, block_identifier): validate_uint256(block_identifier) return self.w3.eth.getBlock(block_identifier)