def ecpairing( computation: BaseComputation, gas_cost_base: int = constants.GAS_ECPAIRING_BASE, gas_cost_per_point: int = constants.GAS_ECPAIRING_PER_POINT) -> BaseComputation: if len(computation.msg.data) % 192: # data length must be an exact multiple of 192 raise VMError("Invalid ECPAIRING parameters") num_points = len(computation.msg.data) // 192 gas_fee = gas_cost_base + num_points * gas_cost_per_point computation.consume_gas(gas_fee, reason='ECPAIRING Precompile') try: result = _ecpairing(computation.msg.data) except ValidationError: raise VMError("Invalid ECPAIRING parameters") if result is True: computation.output = pad32(b'\x01') elif result is False: computation.output = pad32(b'\x00') else: raise Exception("Invariant: unreachable code path") return computation
def test_output_with_vmerror(computation): # Trigger an out of gas error causing output to be b'' computation.output = b'1' with computation: raise VMError('Triggered VMError for tests') assert computation.is_error assert computation.output == b''
def test_get_gas_remaining_with_vmerror(computation): assert computation.get_gas_remaining() == 100 # Trigger an out of gas error causing get gas remaining to be 0 with computation: raise VMError('Triggered VMError for tests') assert computation.is_error assert computation.get_gas_remaining() == 0
def test_get_gas_refund_with_vmerror(computation): # Trigger an out of gas error causing get gas refund to be 0 computation._gas_meter.refund_gas(100) with computation: raise VMError('Triggered VMError for tests') assert computation.is_error assert computation.get_gas_refund() == 0
def test_get_log_entries_with_vmerror(computation, canonical_address_a): # Trigger an out of gas error causing get log entries to be () computation.add_log_entry(canonical_address_a, [1, 2, 3], b'') with computation: raise VMError('Triggered VMError for tests') assert computation.is_error assert computation.get_log_entries() == ()
def test_get_log_entries_with_vmerror(computation): # Trigger an out of gas error causing get log entries to be () computation.add_log_entry(CANONICAL_ADDRESS_A, [1, 2, 3], b'') with computation: raise VMError('Triggered VMError for tests') assert computation.is_error assert computation.get_log_entries() == ()
def test_should_erase_return_data_with_vm_error(computation): assert computation.get_gas_remaining() == 100 computation.return_data = b'\x1337' # Trigger a VMError which should erase the return data with computation: raise VMError('Triggered VMError for tests') assert computation.should_erase_return_data assert computation.return_data == b''
def test_should_burn_gas_with_vm_error(computation): assert computation.get_gas_remaining() == 100 # Trigger an out of gas error causing remaining gas to be 0 with computation: raise VMError('Triggered VMError for tests') assert computation.should_burn_gas assert computation.get_gas_used() == 100 assert computation.get_gas_remaining() == 0
def test_get_gas_used_with_vmerror(computation): # Trigger an out of gas error causing get gas used to be 150 computation.consume_gas(3, reason='testing') computation.consume_gas(2, reason='testing') with computation: raise VMError('Triggered VMError for tests') assert computation.is_error assert computation.get_gas_used() == 100
def blake2b_fcompress(computation: BaseComputation) -> BaseComputation: try: parameters = extract_blake2b_parameters(computation.msg.data_as_bytes) except ValidationError as exc: raise VMError( f"Blake2b input parameter validation failure: {exc}") from exc num_rounds = parameters[0] gas_cost = GAS_COST_PER_ROUND * num_rounds computation.consume_gas( gas_cost, reason=f"Blake2b Compress Precompile w/ {num_rounds} rounds") computation.output = _do_compression(*parameters) return computation
def ecmul(computation: BaseComputation) -> BaseComputation: computation.consume_gas(constants.GAS_ECMUL, reason='ECMUL Precompile') try: result = _ecmull(computation.msg.data) except ValidationError: raise VMError("Invalid ECMUL parameters") result_x, result_y = result result_bytes = b''.join(( pad32(int_to_big_endian(result_x.n)), pad32(int_to_big_endian(result_y.n)), )) computation.output = result_bytes return computation
def ecadd( computation: BaseComputation, gas_cost: int = constants.GAS_ECADD) -> BaseComputation: computation.consume_gas(gas_cost, reason='ECADD Precompile') try: result = _ecadd(computation.msg.data_as_bytes) except ValidationError: raise VMError("Invalid ECADD parameters") result_x, result_y = result result_bytes = b''.join(( pad32(int_to_big_endian(result_x.n)), pad32(int_to_big_endian(result_y.n)), )) computation.output = result_bytes return computation
def test_should_erase_return_data_with_vm_error(computation): assert computation.get_gas_remaining() == 100 # Trigger an out of gas error causing get gas remaining to be 0 with computation: raise VMError('Triggered VMError for tests') assert computation.should_erase_return_data