def extract_lengths(data: bytes) -> Tuple[int, int, int]: # extract argument lengths base_length_bytes = pad32r(data[:32]) base_length = big_endian_to_int(base_length_bytes) exponent_length_bytes = pad32r(data[32:64]) exponent_length = big_endian_to_int(exponent_length_bytes) modulus_length_bytes = pad32r(data[64:96]) modulus_length = big_endian_to_int(modulus_length_bytes) return base_length, exponent_length, modulus_length
def _ecmull(data: bytes) -> Tuple[bn128.FQ, bn128.FQ]: x_bytes = pad32r(data[:32]) y_bytes = pad32r(data[32:64]) m_bytes = pad32r(data[64:96]) x = big_endian_to_int(x_bytes) y = big_endian_to_int(y_bytes) m = big_endian_to_int(m_bytes) p = validate_point(x, y) result = bn128.normalize(bn128.multiply(p, m)) return result
def _ecadd(data: bytes) -> Tuple[bn128.FQ, bn128.FQ]: x1_bytes = pad32r(data[:32]) y1_bytes = pad32r(data[32:64]) x2_bytes = pad32r(data[64:96]) y2_bytes = pad32r(data[96:128]) x1 = big_endian_to_int(x1_bytes) y1 = big_endian_to_int(y1_bytes) x2 = big_endian_to_int(x2_bytes) y2 = big_endian_to_int(y2_bytes) p1 = validate_point(x1, y1) p2 = validate_point(x2, y2) result = bn128.normalize(bn128.add(p1, p2)) return result
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 test_pad_32r(value, expected): assert pad32r(value) == expected