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 ecadd(computation: BaseComputation) -> BaseComputation: computation.consume_gas(constants.GAS_ECADD, 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_sar(vm_class, val1, val2, expected): computation = run_general_computation(vm_class) computation.stack_push_bytes(decode_hex(val1)) computation.stack_push_bytes(decode_hex(val2)) computation.opcodes[opcode_values.SAR](computation) result = computation.stack_pop1_int() assert encode_hex(pad32(int_to_big_endian(result))) == expected
def test_extcodehash(vm_class, address, expected): computation = prepare_general_computation(vm_class) computation.stack_push(decode_hex(address)) computation.opcodes[opcode_values.EXTCODEHASH](computation) result = computation.stack_pop(type_hint=constants.BYTES) assert encode_hex(pad32(result)) == expected
def test_sar(vm_class, val1, val2, expected): computation = prepare_general_computation(vm_class) computation.stack_push(decode_hex(val1)) computation.stack_push(decode_hex(val2)) computation.opcodes[opcode_values.SAR](computation) result = computation.stack_pop(type_hint=constants.UINT256) assert encode_hex(pad32(int_to_big_endian(result))) == expected
def test_extcodehash(vm_class, address, expected): computation = run_general_computation(vm_class) computation.stack_push_bytes(decode_hex(address)) computation.opcodes[opcode_values.EXTCODEHASH](computation) result = computation.stack_pop1_bytes() assert encode_hex(pad32(result)) == expected
async def getStorageAt(self, address: Address, position: int, at_block: Union[str, int]) -> str: if not is_integer(position) or position < 0: raise TypeError("Position of storage must be a whole number, but was: %r" % position) state = await state_at_block(self.chain, at_block) stored_val = state.get_storage(address, position) return encode_hex(pad32(int_to_big_endian(stored_val)))
def new_get_storage(self, address: Address, slot: int, from_journal: bool=True) -> int: account = self._get_account(address, from_journal) storage = HashTrie(HexaryTrie(self._journaldb, account.storage_root)) slot_as_key = pad32(int_to_big_endian(slot)) encoded_value = storage[slot_as_key] if not encoded_value: return 0 return rlp.decode(encoded_value, sedes=rlp.sedes.big_endian_int)
def ripemd160(computation: BaseComputation) -> BaseComputation: word_count = ceil32(len(computation.msg.data)) // 32 gas_fee = constants.GAS_RIPEMD160 + word_count * constants.GAS_RIPEMD160WORD computation.consume_gas(gas_fee, reason="RIPEMD160 Precompile") # TODO: this only works if openssl is installed. hash = hashlib.new('ripemd160', computation.msg.data).digest() padded_hash = pad32(hash) computation.output = padded_hash return computation
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 = self._get_account(address, from_journal) 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 ecrecover(computation: BaseComputation) -> BaseComputation: computation.consume_gas(constants.GAS_ECRECOVER, reason="ECRecover Precompile") data = computation.msg.data_as_bytes raw_message_hash = data[:32] message_hash = pad32r(raw_message_hash) v_bytes = pad32r(data[32:64]) v = big_endian_to_int(v_bytes) r_bytes = pad32r(data[64:96]) r = big_endian_to_int(r_bytes) s_bytes = pad32r(data[96:128]) s = big_endian_to_int(s_bytes) try: validate_lt_secpk1n(r, title="ECRecover: R") validate_lt_secpk1n(s, title="ECRecover: S") validate_lte(v, 28, title="ECRecover: V") validate_gte(v, 27, title="ECRecover: V") except ValidationError: return computation canonical_v = v - 27 try: signature = keys.Signature(vrs=(canonical_v, r, s)) public_key = signature.recover_public_key_from_msg_hash(message_hash) except BadSignature: return computation address = public_key.to_canonical_address() padded_address = pad32(address) computation.output = padded_address return computation
def generate_random_keypair() -> Tuple[bytes, Address]: key_object = keys.PrivateKey( pad32(int_to_big_endian(random.getrandbits(8 * 32)))) return key_object.to_bytes(), Address( key_object.public_key.to_canonical_address())
def pad32_dict_values(some_dict): return { key: encode_hex(pad32(decode_hex(value))) for key, value in some_dict.items() }
def generate_random_keypair_and_address( ) -> Tuple[PrivateKey, PublicKey, Address]: priv_key = keys.PrivateKey( pad32(int_to_big_endian(random.getrandbits(8 * 32)))) return priv_key, priv_key.public_key, Address( priv_key.public_key.to_canonical_address())
def _decode_key(self, key: bytes) -> bytes: padded_slot = pad32(key) return keccak(padded_slot)
def generate_privkey() -> datatypes.PrivateKey: """Generate a new SECP256K1 private key and return it""" privkey = ec.generate_private_key(CURVE, default_backend()) return keys.PrivateKey( pad32(int_to_big_endian(privkey.private_numbers().private_value)))
def test_pad_32(value, expected): assert pad32(value) == expected