Skip to content

Commit 82b0b64

Browse files
authored
feat(sol): optimized pairing aggregation check (#16009)
Adds pairing aggregation to the opt verifier
1 parent 5ec5934 commit 82b0b64

File tree

2 files changed

+158
-4
lines changed

2 files changed

+158
-4
lines changed

barretenberg/cpp/src/barretenberg/dsl/acir_proofs/honk_optimized_contract.hpp

Lines changed: 79 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4390,8 +4390,85 @@ contract HonkVerifier is IVerifier {
43904390
mstore(0xc0, x)
43914391
mstore(0xe0, sub(q, y))
43924392
4393+
// p_0_agg
4394+
// 0x80 - p_0_agg x
4395+
// 0xa0 - p_0_agg y
4396+
mcopy(0x80, ACCUMULATOR, 0x40)
4397+
4398+
4399+
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
4400+
/* PAIRING AGGREGATION */
4401+
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
4402+
// Read the pairing encoded in the first 16 field elements of the proof
4403+
let p0_other_x := mload(PAIRING_POINT_0)
4404+
p0_other_x := or(shl(68, mload(PAIRING_POINT_1)), p0_other_x)
4405+
p0_other_x := or(shl(136, mload(PAIRING_POINT_2)), p0_other_x)
4406+
p0_other_x := or(shl(204, mload(PAIRING_POINT_3)), p0_other_x)
4407+
4408+
let p0_other_y := mload(PAIRING_POINT_4)
4409+
p0_other_y := or(shl(68, mload(PAIRING_POINT_5)), p0_other_y)
4410+
p0_other_y := or(shl(136, mload(PAIRING_POINT_6)), p0_other_y)
4411+
p0_other_y := or(shl(204, mload(PAIRING_POINT_7)), p0_other_y)
4412+
4413+
let p1_other_x := mload(PAIRING_POINT_8)
4414+
p1_other_x := or(shl(68, mload(PAIRING_POINT_9)), p1_other_x)
4415+
p1_other_x := or(shl(136, mload(PAIRING_POINT_10)), p1_other_x)
4416+
p1_other_x := or(shl(204, mload(PAIRING_POINT_11)), p1_other_x)
4417+
4418+
let p1_other_y := mload(PAIRING_POINT_12)
4419+
p1_other_y := or(shl(68, mload(PAIRING_POINT_13)), p1_other_y)
4420+
p1_other_y := or(shl(136, mload(PAIRING_POINT_14)), p1_other_y)
4421+
p1_other_y := or(shl(204, mload(PAIRING_POINT_15)), p1_other_y)
4422+
4423+
// Validate p_0_other on curve
4424+
let xx := mulmod(p0_other_x, p0_other_x, q)
4425+
let xxx := mulmod(xx, p0_other_x, q)
4426+
let yy := mulmod(p0_other_y, p0_other_y, q)
4427+
4428+
let success := eq(yy, addmod(xxx, 3, q))
4429+
4430+
// Validate p_1_other on curve
4431+
xx := mulmod(p1_other_x, p1_other_x, q)
4432+
xxx := mulmod(xx, p1_other_x, q)
4433+
yy := mulmod(p1_other_y, p1_other_y, q)
4434+
4435+
success := and(success, eq(yy, addmod(xxx, 3, q)))
4436+
43934437
// p_0
4394-
mcopy(0x00, ACCUMULATOR, 0x40)
4438+
mstore(0x00, p0_other_x)
4439+
mstore(0x20, p0_other_y)
4440+
4441+
// p_1
4442+
mstore(0x40, p1_other_x)
4443+
mstore(0x60, p1_other_y)
4444+
4445+
// p_1_agg is already in the correct location
4446+
4447+
let recursion_separator := keccak256(0x00, 0x100)
4448+
4449+
// Write separator back to scratch space
4450+
mstore(0x00, p0_other_x)
4451+
4452+
mstore(0x40, recursion_separator)
4453+
// recursion_separator * p_0_other
4454+
success := and(success, staticcall(gas(), 0x07, 0x00, 0x60, 0x00, 0x40))
4455+
4456+
// (recursion_separator * p_0_other) + p_0_agg
4457+
mcopy(0x40, 0x80, 0x40)
4458+
// p_0 = (recursion_separator * p_0_other) + p_0_agg
4459+
success := and(success, staticcall(gas(), 6, 0x00, 0x80, 0x00, 0x40))
4460+
4461+
mstore(0x40, p1_other_x)
4462+
mstore(0x60, p1_other_y)
4463+
mstore(0x80, recursion_separator)
4464+
4465+
success := and(success, staticcall(gas(), 7, 0x40, 0x60, 0x40, 0x40))
4466+
4467+
// Write p_1_agg back to scratch space
4468+
mcopy(0x80, 0xc0, 0x40)
4469+
4470+
// 0xc0 - (recursion_separator * p_1_other) + p_1_agg
4471+
success := and(success, staticcall(gas(), 6, 0x40, 0x80, 0xc0, 0x40))
43954472
43964473
// G2 [1]
43974474
mstore(0x40, 0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2)
@@ -4405,7 +4482,7 @@ contract HonkVerifier is IVerifier {
44054482
mstore(0x140, 0x04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe4)
44064483
mstore(0x160, 0x22febda3c0c0632a56475b4214e5615e11e6dd3f96e6cea2854a87d4dacc5e55)
44074484
4408-
let pairing_success := staticcall(gas(), 8, 0x00, 0x180, 0x00, 0x20)
4485+
let pairing_success := and(success, staticcall(gas(), 8, 0x00, 0x180, 0x00, 0x20))
44094486
if iszero(and(pairing_success, mload(0x00))) {
44104487
mstore(0x00, PAIRING_FAILED_SELECTOR)
44114488
revert(0x00, 0x04)

barretenberg/sol/src/honk/optimised/blake-opt.sol

Lines changed: 79 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4781,8 +4781,85 @@ contract BlakeOptHonkVerifier is IVerifier {
47814781
mstore(0xc0, x)
47824782
mstore(0xe0, sub(q, y))
47834783

4784+
// p_0_agg
4785+
// 0x80 - p_0_agg x
4786+
// 0xa0 - p_0_agg y
4787+
mcopy(0x80, ACCUMULATOR, 0x40)
4788+
4789+
4790+
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
4791+
/* PAIRING AGGREGATION */
4792+
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
4793+
// Read the pairing encoded in the first 16 field elements of the proof
4794+
let p0_other_x := mload(PAIRING_POINT_0)
4795+
p0_other_x := or(shl(68, mload(PAIRING_POINT_1)), p0_other_x)
4796+
p0_other_x := or(shl(136, mload(PAIRING_POINT_2)), p0_other_x)
4797+
p0_other_x := or(shl(204, mload(PAIRING_POINT_3)), p0_other_x)
4798+
4799+
let p0_other_y := mload(PAIRING_POINT_4)
4800+
p0_other_y := or(shl(68, mload(PAIRING_POINT_5)), p0_other_y)
4801+
p0_other_y := or(shl(136, mload(PAIRING_POINT_6)), p0_other_y)
4802+
p0_other_y := or(shl(204, mload(PAIRING_POINT_7)), p0_other_y)
4803+
4804+
let p1_other_x := mload(PAIRING_POINT_8)
4805+
p1_other_x := or(shl(68, mload(PAIRING_POINT_9)), p1_other_x)
4806+
p1_other_x := or(shl(136, mload(PAIRING_POINT_10)), p1_other_x)
4807+
p1_other_x := or(shl(204, mload(PAIRING_POINT_11)), p1_other_x)
4808+
4809+
let p1_other_y := mload(PAIRING_POINT_12)
4810+
p1_other_y := or(shl(68, mload(PAIRING_POINT_13)), p1_other_y)
4811+
p1_other_y := or(shl(136, mload(PAIRING_POINT_14)), p1_other_y)
4812+
p1_other_y := or(shl(204, mload(PAIRING_POINT_15)), p1_other_y)
4813+
4814+
// Validate p_0_other on curve
4815+
let xx := mulmod(p0_other_x, p0_other_x, q)
4816+
let xxx := mulmod(xx, p0_other_x, q)
4817+
let yy := mulmod(p0_other_y, p0_other_y, q)
4818+
4819+
let success := eq(yy, addmod(xxx, 3, q))
4820+
4821+
// Validate p_1_other on curve
4822+
xx := mulmod(p1_other_x, p1_other_x, q)
4823+
xxx := mulmod(xx, p1_other_x, q)
4824+
yy := mulmod(p1_other_y, p1_other_y, q)
4825+
4826+
success := and(success, eq(yy, addmod(xxx, 3, q)))
4827+
47844828
// p_0
4785-
mcopy(0x00, ACCUMULATOR, 0x40)
4829+
mstore(0x00, p0_other_x)
4830+
mstore(0x20, p0_other_y)
4831+
4832+
// p_1
4833+
mstore(0x40, p1_other_x)
4834+
mstore(0x60, p1_other_y)
4835+
4836+
// p_1_agg is already in the correct location
4837+
4838+
let recursion_separator := keccak256(0x00, 0x100)
4839+
4840+
// Write separator back to scratch space
4841+
mstore(0x00, p0_other_x)
4842+
4843+
mstore(0x40, recursion_separator)
4844+
// recursion_separator * p_0_other
4845+
success := and(success, staticcall(gas(), 0x07, 0x00, 0x60, 0x00, 0x40))
4846+
4847+
// (recursion_separator * p_0_other) + p_0_agg
4848+
mcopy(0x40, 0x80, 0x40)
4849+
// p_0 = (recursion_separator * p_0_other) + p_0_agg
4850+
success := and(success, staticcall(gas(), 6, 0x00, 0x80, 0x00, 0x40))
4851+
4852+
mstore(0x40, p1_other_x)
4853+
mstore(0x60, p1_other_y)
4854+
mstore(0x80, recursion_separator)
4855+
4856+
success := and(success, staticcall(gas(), 7, 0x40, 0x60, 0x40, 0x40))
4857+
4858+
// Write p_1_agg back to scratch space
4859+
mcopy(0x80, 0xc0, 0x40)
4860+
4861+
// 0xc0 - (recursion_separator * p_1_other) + p_1_agg
4862+
success := and(success, staticcall(gas(), 6, 0x40, 0x80, 0xc0, 0x40))
47864863

47874864
// G2 [1]
47884865
mstore(0x40, 0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2)
@@ -4796,7 +4873,7 @@ contract BlakeOptHonkVerifier is IVerifier {
47964873
mstore(0x140, 0x04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe4)
47974874
mstore(0x160, 0x22febda3c0c0632a56475b4214e5615e11e6dd3f96e6cea2854a87d4dacc5e55)
47984875

4799-
let pairing_success := staticcall(gas(), 8, 0x00, 0x180, 0x00, 0x20)
4876+
let pairing_success := and(success, staticcall(gas(), 8, 0x00, 0x180, 0x00, 0x20))
48004877
if iszero(and(pairing_success, mload(0x00))) {
48014878
mstore(0x00, PAIRING_FAILED_SELECTOR)
48024879
revert(0x00, 0x04)

0 commit comments

Comments
 (0)