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 ecrecover(computation: BaseComputation) -> BaseComputation: computation.consume_gas(constants.GAS_ECRECOVER, reason="ECRecover Precompile") raw_message_hash = computation.msg.data[:32] message_hash = pad32r(raw_message_hash) v_bytes = pad32r(computation.msg.data[32:64]) v = big_endian_to_int(v_bytes) r_bytes = pad32r(computation.msg.data[64:96]) r = big_endian_to_int(r_bytes) s_bytes = pad32r(computation.msg.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 test_extcodehash(vm_class, address, expected): computation = prepare_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_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 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 ecpairing(computation): 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 = constants.GAS_ECPAIRING_BASE + num_points * constants.GAS_ECPAIRING_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 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 encode_for_smc(self) -> bytes: encoded = b"".join([ int_to_bytes32(self.shard_id), self.chunk_root, int_to_bytes32(self.period), pad32(self.proposer_address), ]) if len(encoded) != self.smc_encoded_size: raise ValueError( "Encoded header size is {} instead of {} bytes".format( len(encoded), self.smc_encoded_size, )) return encoded
def set_storage(self, address, slot, value): 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 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 generate_random_keypair() -> Tuple[bytes, Address]: key_object = keys.PrivateKey( pad32(int_to_big_endian(random.getrandbits(8 * 32)))) return key_object.to_bytes(), key_object.public_key.to_canonical_address()
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 test_pad_32(value, expected): assert pad32(value) == expected