def ec_pair(data: List[int]) -> List[int]: if len(data) % 192: return [] zero = (bn128.FQ2.one(), bn128.FQ2.one(), bn128.FQ2.zero()) exponent = bn128.FQ12.one() bytes_data = bytearray(data) for i in range(0, len(bytes_data), 192): x1 = extract32(bytes_data, i) y1 = extract32(bytes_data, i + 32) x2_i = extract32(bytes_data, i + 64) x2_r = extract32(bytes_data, i + 96) y2_i = extract32(bytes_data, i + 128) y2_r = extract32(bytes_data, i + 160) p1 = validate_point(x1, y1) if p1 is False: return [] for v in (x2_i, x2_r, y2_i, y2_r): if v >= bn128.field_modulus: return [] fq2_x = bn128.FQ2([x2_r, x2_i]) fq2_y = bn128.FQ2([y2_r, y2_i]) if (fq2_x, fq2_y) != (bn128.FQ2.zero(), bn128.FQ2.zero()): p2 = (fq2_x, fq2_y, bn128.FQ2.one()) if not bn128.is_on_curve(p2, bn128.b2): return [] else: p2 = zero if bn128.multiply(p2, bn128.curve_order)[-1] != bn128.FQ2.zero(): return [] exponent *= bn128.pairing(p2, p1, final_exponentiate=False) result = bn128.final_exponentiate(exponent) == bn128.FQ12.one() return [0] * 31 + [1 if result else 0]
def _process_point(data_buffer: bytes, exponent: int) -> bn128.FQP: x1, y1, x2_i, x2_r, y2_i, y2_r = _extract_point(data_buffer) p1 = validate_point(x1, y1) for v in (x2_i, x2_r, y2_i, y2_r): if v >= bn128.field_modulus: raise ValidationError("value greater than field modulus") fq2_x = bn128.FQ2([x2_r, x2_i]) fq2_y = bn128.FQ2([y2_r, y2_i]) p2 = ZERO if (fq2_x, fq2_y) != (bn128.FQ2.zero(), bn128.FQ2.zero()): p2 = (fq2_x, fq2_y, bn128.FQ2.one()) if not bn128.is_on_curve(p2, bn128.b2): raise ValidationError("point is not on curve") if bn128.multiply(p2, bn128.curve_order)[-1] != bn128.FQ2.zero(): raise ValidationError("TODO: what case is this?????") return exponent * bn128.pairing(FQP_point_to_FQ2_point(p2), p1, final_exponentiate=False)
def proc_ecpairing(ext, msg): if not ext.post_metropolis_hardfork(): return 1, msg.gas, [] import py_ecc.optimized_bn128 as bn128 FQ = bn128.FQ print('pairing proc', msg.gas) # Data must be an exact multiple of 192 byte if msg.data.size % 192: return 0, 0, [] gascost = opcodes.GPAIRINGBASE + msg.data.size // 192 * opcodes.GPAIRINGPERPOINT if msg.gas < gascost: return 0, 0, [] zero = (bn128.FQ2.one(), bn128.FQ2.one(), bn128.FQ2.zero()) exponent = bn128.FQ12.one() for i in range(0, msg.data.size, 192): x1 = msg.data.extract32(i) y1 = msg.data.extract32(i + 32) x2_i = msg.data.extract32(i + 64) x2_r = msg.data.extract32(i + 96) y2_i = msg.data.extract32(i + 128) y2_r = msg.data.extract32(i + 160) p1 = validate_point(x1, y1) if p1 is False: return 0, 0, [] for v in (x2_i, x2_r, y2_i, y2_r): if v >= bn128.field_modulus: return 0, 0, [] fq2_x = bn128.FQ2([x2_r, x2_i]) fq2_y = bn128.FQ2([y2_r, y2_i]) if (fq2_x, fq2_y) != (bn128.FQ2.zero(), bn128.FQ2.zero()): p2 = (fq2_x, fq2_y, bn128.FQ2.one()) if not bn128.is_on_curve(p2, bn128.b2): return 0, 0, [] else: p2 = zero if bn128.multiply(p2, bn128.curve_order)[-1] != bn128.FQ2.zero(): return 0, 0, [] exponent *= bn128.pairing(p2, p1, final_exponentiate=False) result = bn128.final_exponentiate(exponent) == bn128.FQ12.one() return 1, msg.gas - gascost, [0] * 31 + [1 if result else 0]