def push_n(evm: Evm, num_bytes: int) -> None: """ Pushes a N-byte immediate onto the stack. Parameters ---------- evm : The current EVM frame. num_bytes : The number of immediate bytes to be read from the code and pushed to the stack. Raises ------ StackOverflowError If `len(stack)` is equals `1024`. OutOfGasError If `evm.gas_left` is less than `3`. """ assert evm.pc + num_bytes < len(evm.code) evm.gas_left = subtract_gas(evm.gas_left, GAS_VERY_LOW) data_to_push = U256.from_be_bytes(evm.code[evm.pc + 1:evm.pc + num_bytes + 1]) push(evm.stack, data_to_push) evm.pc += num_bytes
def signextend(evm: Evm) -> None: """ Sign extend operation. In other words, extend a signed number which fits in N bytes to 32 bytes. Parameters ---------- evm : The current EVM frame. Raises ------ StackUnderflowError If `len(stack)` is less than `2`. OutOfGasError If `evm.gas_left` is less than `5`. """ evm.gas_left = subtract_gas(evm.gas_left, GAS_LOW) # byte_num would be 0-indexed when inserted to the stack. byte_num = pop(evm.stack) value = pop(evm.stack) if byte_num > 31: # Can't extend any further result = value else: # U256(0).to_be_bytes() gives b'' instead b'\x00'. # noqa: SC100 value_bytes = value.to_be_bytes() or b"\x00" # Now among the obtained value bytes, consider only # N `least significant bytes`, where N is `byte_num + 1`. value_bytes = value_bytes[len(value_bytes) - 1 - byte_num:] sign_bit = value_bytes[0] >> 7 if sign_bit == 0: result = U256.from_be_bytes(value_bytes) else: num_bytes_prepend = 32 - (byte_num + 1) result = U256.from_be_bytes( bytearray([0xFF] * num_bytes_prepend) + value_bytes) push(evm.stack, result)
def json_to_state(raw: Any) -> State: state = {} for (addr, acc_state) in raw.items(): account = Account( nonce=hex2uint(acc_state.get("nonce", "0x0")), balance=hex2uint(acc_state.get("balance", "0x0")), code=hex2bytes(acc_state.get("code", "")), storage={}, ) for (k, v) in acc_state.get("storage", {}).items(): account.storage[hex2bytes32(k)] = U256.from_be_bytes( hex2bytes32(v) ) state[hex2address(addr)] = account return state
def test_u256_from_be_bytes_too_large() -> None: with pytest.raises(ValueError): U256.from_be_bytes(bytes([0xFF] * 33))
def test_u256_from_be_bytes_is_big_endian() -> None: value = U256.from_be_bytes(bytes([0xAB, 0xCD])) assert value == 0xABCD
def test_u256_from_be_bytes_one() -> None: value = U256.from_be_bytes(bytes([1])) assert value == 1
def test_u256_from_be_bytes_empty() -> None: value = U256.from_be_bytes(b"") assert value == 0