Skip to content

Commit 04eb2db

Browse files
committed
test: add utils for testing
1 parent 293e919 commit 04eb2db

File tree

3 files changed

+434
-0
lines changed

3 files changed

+434
-0
lines changed

test/utils/BN256G2.sol

Lines changed: 337 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,337 @@
1+
pragma solidity ^0.8.0;
2+
3+
/**
4+
* @title Elliptic curve operations on twist points for alt_bn128
5+
* @author Mustafa Al-Bassam ([email protected])
6+
* @dev Homepage: https://github.com/musalbas/solidity-BN256G2
7+
*/
8+
library BN256G2 {
9+
uint256 internal constant FIELD_MODULUS =
10+
0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47;
11+
uint256 internal constant TWISTBX =
12+
0x2b149d40ceb8aaae81be18991be06ac3b5b4c5e559dbefa33267e6dc24a138e5;
13+
uint256 internal constant TWISTBY =
14+
0x9713b03af0fed4cd2cafadeed8fdf4a74fa084e52d1852e4a2bd0685c315d2;
15+
uint256 internal constant PTXX = 0;
16+
uint256 internal constant PTXY = 1;
17+
uint256 internal constant PTYX = 2;
18+
uint256 internal constant PTYY = 3;
19+
uint256 internal constant PTZX = 4;
20+
uint256 internal constant PTZY = 5;
21+
22+
/**
23+
* @notice Add two twist points
24+
* @param pt1xx Coefficient 1 of x on point 1
25+
* @param pt1xy Coefficient 2 of x on point 1
26+
* @param pt1yx Coefficient 1 of y on point 1
27+
* @param pt1yy Coefficient 2 of y on point 1
28+
* @param pt2xx Coefficient 1 of x on point 2
29+
* @param pt2xy Coefficient 2 of x on point 2
30+
* @param pt2yx Coefficient 1 of y on point 2
31+
* @param pt2yy Coefficient 2 of y on point 2
32+
* @return (pt3xx, pt3xy, pt3yx, pt3yy)
33+
*/
34+
function ECTwistAdd(
35+
uint256 pt1xx,
36+
uint256 pt1xy,
37+
uint256 pt1yx,
38+
uint256 pt1yy,
39+
uint256 pt2xx,
40+
uint256 pt2xy,
41+
uint256 pt2yx,
42+
uint256 pt2yy
43+
) public view returns (uint256, uint256, uint256, uint256) {
44+
if (pt1xx == 0 && pt1xy == 0 && pt1yx == 0 && pt1yy == 0) {
45+
if (!(pt2xx == 0 && pt2xy == 0 && pt2yx == 0 && pt2yy == 0)) {
46+
assert(_isOnCurve(pt2xx, pt2xy, pt2yx, pt2yy));
47+
}
48+
return (pt2xx, pt2xy, pt2yx, pt2yy);
49+
} else if (pt2xx == 0 && pt2xy == 0 && pt2yx == 0 && pt2yy == 0) {
50+
assert(_isOnCurve(pt1xx, pt1xy, pt1yx, pt1yy));
51+
return (pt1xx, pt1xy, pt1yx, pt1yy);
52+
}
53+
54+
assert(_isOnCurve(pt1xx, pt1xy, pt1yx, pt1yy));
55+
assert(_isOnCurve(pt2xx, pt2xy, pt2yx, pt2yy));
56+
57+
uint256[6] memory pt3 =
58+
_ECTwistAddJacobian(pt1xx, pt1xy, pt1yx, pt1yy, 1, 0, pt2xx, pt2xy, pt2yx, pt2yy, 1, 0);
59+
60+
return _fromJacobian(pt3[PTXX], pt3[PTXY], pt3[PTYX], pt3[PTYY], pt3[PTZX], pt3[PTZY]);
61+
}
62+
63+
/**
64+
* @notice Multiply a twist point by a scalar
65+
* @param s Scalar to multiply by
66+
* @param pt1xx Coefficient 1 of x
67+
* @param pt1xy Coefficient 2 of x
68+
* @param pt1yx Coefficient 1 of y
69+
* @param pt1yy Coefficient 2 of y
70+
* @return (pt2xx, pt2xy, pt2yx, pt2yy)
71+
*/
72+
function ECTwistMul(
73+
uint256 s,
74+
uint256 pt1xx,
75+
uint256 pt1xy,
76+
uint256 pt1yx,
77+
uint256 pt1yy
78+
) public view returns (uint256, uint256, uint256, uint256) {
79+
uint256 pt1zx = 1;
80+
if (pt1xx == 0 && pt1xy == 0 && pt1yx == 0 && pt1yy == 0) {
81+
pt1xx = 1;
82+
pt1yx = 1;
83+
pt1zx = 0;
84+
} else {
85+
assert(_isOnCurve(pt1xx, pt1xy, pt1yx, pt1yy));
86+
}
87+
88+
uint256[6] memory pt2 = _ECTwistMulJacobian(s, pt1xx, pt1xy, pt1yx, pt1yy, pt1zx, 0);
89+
90+
return _fromJacobian(pt2[PTXX], pt2[PTXY], pt2[PTYX], pt2[PTYY], pt2[PTZX], pt2[PTZY]);
91+
}
92+
93+
/**
94+
* @notice Get the field modulus
95+
* @return The field modulus
96+
*/
97+
function GetFieldModulus() public pure returns (uint256) {
98+
return FIELD_MODULUS;
99+
}
100+
101+
function submod(uint256 a, uint256 b, uint256 n) internal pure returns (uint256) {
102+
return addmod(a, n - b, n);
103+
}
104+
105+
function _FQ2Mul(
106+
uint256 xx,
107+
uint256 xy,
108+
uint256 yx,
109+
uint256 yy
110+
) internal pure returns (uint256, uint256) {
111+
return (
112+
submod(mulmod(xx, yx, FIELD_MODULUS), mulmod(xy, yy, FIELD_MODULUS), FIELD_MODULUS),
113+
addmod(mulmod(xx, yy, FIELD_MODULUS), mulmod(xy, yx, FIELD_MODULUS), FIELD_MODULUS)
114+
);
115+
}
116+
117+
function _FQ2Muc(uint256 xx, uint256 xy, uint256 c) internal pure returns (uint256, uint256) {
118+
return (mulmod(xx, c, FIELD_MODULUS), mulmod(xy, c, FIELD_MODULUS));
119+
}
120+
121+
function _FQ2Add(
122+
uint256 xx,
123+
uint256 xy,
124+
uint256 yx,
125+
uint256 yy
126+
) internal pure returns (uint256, uint256) {
127+
return (addmod(xx, yx, FIELD_MODULUS), addmod(xy, yy, FIELD_MODULUS));
128+
}
129+
130+
function _FQ2Sub(
131+
uint256 xx,
132+
uint256 xy,
133+
uint256 yx,
134+
uint256 yy
135+
) internal pure returns (uint256 rx, uint256 ry) {
136+
return (submod(xx, yx, FIELD_MODULUS), submod(xy, yy, FIELD_MODULUS));
137+
}
138+
139+
function _FQ2Div(
140+
uint256 xx,
141+
uint256 xy,
142+
uint256 yx,
143+
uint256 yy
144+
) internal view returns (uint256, uint256) {
145+
(yx, yy) = _FQ2Inv(yx, yy);
146+
return _FQ2Mul(xx, xy, yx, yy);
147+
}
148+
149+
function _FQ2Inv(uint256 x, uint256 y) internal view returns (uint256, uint256) {
150+
uint256 inv = _modInv(
151+
addmod(mulmod(y, y, FIELD_MODULUS), mulmod(x, x, FIELD_MODULUS), FIELD_MODULUS),
152+
FIELD_MODULUS
153+
);
154+
return (mulmod(x, inv, FIELD_MODULUS), FIELD_MODULUS - mulmod(y, inv, FIELD_MODULUS));
155+
}
156+
157+
function _isOnCurve(
158+
uint256 xx,
159+
uint256 xy,
160+
uint256 yx,
161+
uint256 yy
162+
) internal pure returns (bool) {
163+
uint256 yyx;
164+
uint256 yyy;
165+
uint256 xxxx;
166+
uint256 xxxy;
167+
(yyx, yyy) = _FQ2Mul(yx, yy, yx, yy);
168+
(xxxx, xxxy) = _FQ2Mul(xx, xy, xx, xy);
169+
(xxxx, xxxy) = _FQ2Mul(xxxx, xxxy, xx, xy);
170+
(yyx, yyy) = _FQ2Sub(yyx, yyy, xxxx, xxxy);
171+
(yyx, yyy) = _FQ2Sub(yyx, yyy, TWISTBX, TWISTBY);
172+
return yyx == 0 && yyy == 0;
173+
}
174+
175+
function _modInv(uint256 a, uint256 n) internal view returns (uint256 result) {
176+
bool success;
177+
assembly ("memory-safe") {
178+
let freemem := mload(0x40)
179+
mstore(freemem, 0x20)
180+
mstore(add(freemem, 0x20), 0x20)
181+
mstore(add(freemem, 0x40), 0x20)
182+
mstore(add(freemem, 0x60), a)
183+
mstore(add(freemem, 0x80), sub(n, 2))
184+
mstore(add(freemem, 0xA0), n)
185+
success := staticcall(sub(gas(), 2000), 5, freemem, 0xC0, freemem, 0x20)
186+
result := mload(freemem)
187+
}
188+
require(success);
189+
}
190+
191+
function _fromJacobian(
192+
uint256 pt1xx,
193+
uint256 pt1xy,
194+
uint256 pt1yx,
195+
uint256 pt1yy,
196+
uint256 pt1zx,
197+
uint256 pt1zy
198+
) internal view returns (uint256 pt2xx, uint256 pt2xy, uint256 pt2yx, uint256 pt2yy) {
199+
uint256 invzx;
200+
uint256 invzy;
201+
(invzx, invzy) = _FQ2Inv(pt1zx, pt1zy);
202+
(pt2xx, pt2xy) = _FQ2Mul(pt1xx, pt1xy, invzx, invzy);
203+
(pt2yx, pt2yy) = _FQ2Mul(pt1yx, pt1yy, invzx, invzy);
204+
}
205+
206+
function _ECTwistAddJacobian(
207+
uint256 pt1xx,
208+
uint256 pt1xy,
209+
uint256 pt1yx,
210+
uint256 pt1yy,
211+
uint256 pt1zx,
212+
uint256 pt1zy,
213+
uint256 pt2xx,
214+
uint256 pt2xy,
215+
uint256 pt2yx,
216+
uint256 pt2yy,
217+
uint256 pt2zx,
218+
uint256 pt2zy
219+
) internal pure returns (uint256[6] memory pt3) {
220+
if (pt1zx == 0 && pt1zy == 0) {
221+
(pt3[PTXX], pt3[PTXY], pt3[PTYX], pt3[PTYY], pt3[PTZX], pt3[PTZY]) =
222+
(pt2xx, pt2xy, pt2yx, pt2yy, pt2zx, pt2zy);
223+
return pt3;
224+
} else if (pt2zx == 0 && pt2zy == 0) {
225+
(pt3[PTXX], pt3[PTXY], pt3[PTYX], pt3[PTYY], pt3[PTZX], pt3[PTZY]) =
226+
(pt1xx, pt1xy, pt1yx, pt1yy, pt1zx, pt1zy);
227+
return pt3;
228+
}
229+
230+
(pt2yx, pt2yy) = _FQ2Mul(pt2yx, pt2yy, pt1zx, pt1zy); // U1 = y2 * z1
231+
(pt3[PTYX], pt3[PTYY]) = _FQ2Mul(pt1yx, pt1yy, pt2zx, pt2zy); // U2 = y1 * z2
232+
(pt2xx, pt2xy) = _FQ2Mul(pt2xx, pt2xy, pt1zx, pt1zy); // V1 = x2 * z1
233+
(pt3[PTZX], pt3[PTZY]) = _FQ2Mul(pt1xx, pt1xy, pt2zx, pt2zy); // V2 = x1 * z2
234+
235+
if (pt2xx == pt3[PTZX] && pt2xy == pt3[PTZY]) {
236+
if (pt2yx == pt3[PTYX] && pt2yy == pt3[PTYY]) {
237+
(pt3[PTXX], pt3[PTXY], pt3[PTYX], pt3[PTYY], pt3[PTZX], pt3[PTZY]) =
238+
_ECTwistDoubleJacobian(pt1xx, pt1xy, pt1yx, pt1yy, pt1zx, pt1zy);
239+
return pt3;
240+
}
241+
(pt3[PTXX], pt3[PTXY], pt3[PTYX], pt3[PTYY], pt3[PTZX], pt3[PTZY]) = (1, 0, 1, 0, 0, 0);
242+
return pt3;
243+
}
244+
245+
(pt2zx, pt2zy) = _FQ2Mul(pt1zx, pt1zy, pt2zx, pt2zy); // W = z1 * z2
246+
(pt1xx, pt1xy) = _FQ2Sub(pt2yx, pt2yy, pt3[PTYX], pt3[PTYY]); // U = U1 - U2
247+
(pt1yx, pt1yy) = _FQ2Sub(pt2xx, pt2xy, pt3[PTZX], pt3[PTZY]); // V = V1 - V2
248+
(pt1zx, pt1zy) = _FQ2Mul(pt1yx, pt1yy, pt1yx, pt1yy); // V_squared = V * V
249+
(pt2yx, pt2yy) = _FQ2Mul(pt1zx, pt1zy, pt3[PTZX], pt3[PTZY]); // V_squared_times_V2 = V_squared * V2
250+
(pt1zx, pt1zy) = _FQ2Mul(pt1zx, pt1zy, pt1yx, pt1yy); // V_cubed = V * V_squared
251+
(pt3[PTZX], pt3[PTZY]) = _FQ2Mul(pt1zx, pt1zy, pt2zx, pt2zy); // newz = V_cubed * W
252+
(pt2xx, pt2xy) = _FQ2Mul(pt1xx, pt1xy, pt1xx, pt1xy); // U * U
253+
(pt2xx, pt2xy) = _FQ2Mul(pt2xx, pt2xy, pt2zx, pt2zy); // U * U * W
254+
(pt2xx, pt2xy) = _FQ2Sub(pt2xx, pt2xy, pt1zx, pt1zy); // U * U * W - V_cubed
255+
(pt2zx, pt2zy) = _FQ2Muc(pt2yx, pt2yy, 2); // 2 * V_squared_times_V2
256+
(pt2xx, pt2xy) = _FQ2Sub(pt2xx, pt2xy, pt2zx, pt2zy); // A = U * U * W - V_cubed - 2 * V_squared_times_V2
257+
(pt3[PTXX], pt3[PTXY]) = _FQ2Mul(pt1yx, pt1yy, pt2xx, pt2xy); // newx = V * A
258+
(pt1yx, pt1yy) = _FQ2Sub(pt2yx, pt2yy, pt2xx, pt2xy); // V_squared_times_V2 - A
259+
(pt1yx, pt1yy) = _FQ2Mul(pt1xx, pt1xy, pt1yx, pt1yy); // U * (V_squared_times_V2 - A)
260+
(pt1xx, pt1xy) = _FQ2Mul(pt1zx, pt1zy, pt3[PTYX], pt3[PTYY]); // V_cubed * U2
261+
(pt3[PTYX], pt3[PTYY]) = _FQ2Sub(pt1yx, pt1yy, pt1xx, pt1xy); // newy = U * (V_squared_times_V2 - A) - V_cubed * U2
262+
}
263+
264+
function _ECTwistDoubleJacobian(
265+
uint256 pt1xx,
266+
uint256 pt1xy,
267+
uint256 pt1yx,
268+
uint256 pt1yy,
269+
uint256 pt1zx,
270+
uint256 pt1zy
271+
)
272+
internal
273+
pure
274+
returns (
275+
uint256 pt2xx,
276+
uint256 pt2xy,
277+
uint256 pt2yx,
278+
uint256 pt2yy,
279+
uint256 pt2zx,
280+
uint256 pt2zy
281+
)
282+
{
283+
(pt2xx, pt2xy) = _FQ2Muc(pt1xx, pt1xy, 3); // 3 * x
284+
(pt2xx, pt2xy) = _FQ2Mul(pt2xx, pt2xy, pt1xx, pt1xy); // W = 3 * x * x
285+
(pt1zx, pt1zy) = _FQ2Mul(pt1yx, pt1yy, pt1zx, pt1zy); // S = y * z
286+
(pt2yx, pt2yy) = _FQ2Mul(pt1xx, pt1xy, pt1yx, pt1yy); // x * y
287+
(pt2yx, pt2yy) = _FQ2Mul(pt2yx, pt2yy, pt1zx, pt1zy); // B = x * y * S
288+
(pt1xx, pt1xy) = _FQ2Mul(pt2xx, pt2xy, pt2xx, pt2xy); // W * W
289+
(pt2zx, pt2zy) = _FQ2Muc(pt2yx, pt2yy, 8); // 8 * B
290+
(pt1xx, pt1xy) = _FQ2Sub(pt1xx, pt1xy, pt2zx, pt2zy); // H = W * W - 8 * B
291+
(pt2zx, pt2zy) = _FQ2Mul(pt1zx, pt1zy, pt1zx, pt1zy); // S_squared = S * S
292+
(pt2yx, pt2yy) = _FQ2Muc(pt2yx, pt2yy, 4); // 4 * B
293+
(pt2yx, pt2yy) = _FQ2Sub(pt2yx, pt2yy, pt1xx, pt1xy); // 4 * B - H
294+
(pt2yx, pt2yy) = _FQ2Mul(pt2yx, pt2yy, pt2xx, pt2xy); // W * (4 * B - H)
295+
(pt2xx, pt2xy) = _FQ2Muc(pt1yx, pt1yy, 8); // 8 * y
296+
(pt2xx, pt2xy) = _FQ2Mul(pt2xx, pt2xy, pt1yx, pt1yy); // 8 * y * y
297+
(pt2xx, pt2xy) = _FQ2Mul(pt2xx, pt2xy, pt2zx, pt2zy); // 8 * y * y * S_squared
298+
(pt2yx, pt2yy) = _FQ2Sub(pt2yx, pt2yy, pt2xx, pt2xy); // newy = W * (4 * B - H) - 8 * y * y * S_squared
299+
(pt2xx, pt2xy) = _FQ2Muc(pt1xx, pt1xy, 2); // 2 * H
300+
(pt2xx, pt2xy) = _FQ2Mul(pt2xx, pt2xy, pt1zx, pt1zy); // newx = 2 * H * S
301+
(pt2zx, pt2zy) = _FQ2Mul(pt1zx, pt1zy, pt2zx, pt2zy); // S * S_squared
302+
(pt2zx, pt2zy) = _FQ2Muc(pt2zx, pt2zy, 8); // newz = 8 * S * S_squared
303+
}
304+
305+
function _ECTwistMulJacobian(
306+
uint256 d,
307+
uint256 pt1xx,
308+
uint256 pt1xy,
309+
uint256 pt1yx,
310+
uint256 pt1yy,
311+
uint256 pt1zx,
312+
uint256 pt1zy
313+
) internal pure returns (uint256[6] memory pt2) {
314+
while (d != 0) {
315+
if ((d & 1) != 0) {
316+
pt2 = _ECTwistAddJacobian(
317+
pt2[PTXX],
318+
pt2[PTXY],
319+
pt2[PTYX],
320+
pt2[PTYY],
321+
pt2[PTZX],
322+
pt2[PTZY],
323+
pt1xx,
324+
pt1xy,
325+
pt1yx,
326+
pt1yy,
327+
pt1zx,
328+
pt1zy
329+
);
330+
}
331+
(pt1xx, pt1xy, pt1yx, pt1yy, pt1zx, pt1zy) =
332+
_ECTwistDoubleJacobian(pt1xx, pt1xy, pt1yx, pt1yy, pt1zx, pt1zy);
333+
334+
d = d / 2;
335+
}
336+
}
337+
}

test/utils/MockAVSDeployer.sol

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ import {BLSApkRegistryHarness} from "../harnesses/BLSApkRegistryHarness.sol";
5353
import {EmptyContract} from "eigenlayer-contracts/src/test/mocks/EmptyContract.sol";
5454

5555
import {StakeRegistryHarness} from "../harnesses/StakeRegistryHarness.sol";
56+
import {OperatorLib} from "../utils/OperatorLib.sol";
5657

5758
import "forge-std/Test.sol";
5859

@@ -547,4 +548,12 @@ contract MockAVSDeployer is Test {
547548
salt: salt
548549
});
549550
}
551+
552+
function _createOperators(uint256 numOperators, uint256 startIndex) internal returns (OperatorLib.Operator[] memory) {
553+
OperatorLib.Operator[] memory operators = new OperatorLib.Operator[](numOperators);
554+
for (uint256 i = 0; i < numOperators; i++) {
555+
operators[i] = OperatorLib.createOperator(string(abi.encodePacked("operator-", i + startIndex)));
556+
}
557+
return operators;
558+
}
550559
}

0 commit comments

Comments
 (0)