Skip to content

Commit

Permalink
Merge pull request #185 from 0xPolygonHermez/feature/p256verify
Browse files Browse the repository at this point in the history
Feature/p256verify
  • Loading branch information
laisolizq authored Oct 17, 2024
2 parents 00dbce0 + d407683 commit 5d7f217
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 113 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@
"dependencies": {
"@ethereumjs/block": "^3.6.2",
"@ethereumjs/tx": "^3.4.0",
"@polygon-hermez/common": "2.6.4",
"@polygon-hermez/vm": "6.0.12",
"@polygon-hermez/common": "2.6.5",
"@polygon-hermez/vm": "7.0.3",
"ethereumjs-util": "^7.1.4",
"ethers": "^5.5.4",
"ffjavascript": "^0.2.55",
Expand Down
154 changes: 46 additions & 108 deletions src/virtual-counters-manager-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,13 @@
/* eslint-disable guard-for-in */
/* eslint-disable camelcase */
/* eslint-disable no-use-before-define */
/**
* Computes the expected modExp counters for the given inputs.
* @param ctx - Context.
* @param tag - Tag.
* @sets ctx.ctx.emodExpCounters.
*/

const BASE = 1n << 256n;

function expectedModExpCounters(lenB, lenE, lenM, B, E, M) {
const [Q_B_M, R_B_M] = [B / M, B % M];
const Bsq = B * B;
const NZ_Bsq = 2 * lenB - computeLenThisBase(Bsq);
const [Q_Bsq_M, R_Bsq_M] = [Bsq / M, Bsq % M];
const BM = B * M;

const E2 = Math.floor(lenE / 2) || 1;
const lenQE2 = Math.floor(lenE / 2) || 1;

// const log2E = Math.floor(Math.log(Number(E)) / Math.log(2));

let nTimesOdd = 0;
while (E > 0n) {
Expand All @@ -38,6 +28,7 @@ function expectedModExpCounters(lenB, lenE, lenM, B, E, M) {
const c = fullLoopCounters();

for (const key in counters) {
// counters[key] = a[key] + log2E * b[key];
counters[key] = a[key] + nTimesEven * b[key] + nTimesOdd * c[key];
}

Expand All @@ -56,122 +47,69 @@ function expectedModExpCounters(lenB, lenE, lenM, B, E, M) {
return len;
}

// Computes the positions of the first different chunk between x and y.
function first_diff_chunk(x, y) {
const xLen = computeLenThisBase(x);
const yLen = computeLenThisBase(y);

if (xLen > yLen || xLen < yLen) {
return xLen;
}

let i = xLen - 1;
while (i >= 0 && ((x >> (256n * BigInt(i))) & 0xffffffffffffffffffffffffffffffffn) === ((y >> (256n * BigInt(i))) & 0xffffffffffffffffffffffffffffffffn)) {
i -= 1;
}

return i + 1;
}

// Counters computation of the setup and first division.
// Counters computation of the setup and first division. + 2 last steps
function setupAndFirstDivCounters() {
return {
steps:
218
+ 39 * lenB
+ 45 * lenM
+ computeLenThisBase(Q_B_M) * (30 + 33 * lenM)
+ 17 * computeLenThisBase(R_B_M)
- 14 * first_diff_chunk(B, M)
- 7 * first_diff_chunk(M, R_B_M),
binaries:
12
+ 6 * lenB
84
+ 2 // last 2 steps
+ 10 * lenB
+ 3 * lenM
+ computeLenThisBase(Q_B_M) * (1 + 4 * lenM)
+ (8 + 19 * lenM ) * computeLenThisBase(Q_B_M)

Check failure on line 58 in src/virtual-counters-manager-utils.js

View workflow job for this annotation

GitHub Actions / build (16.x)

There should be no space before this paren
+ 12 * computeLenThisBase(R_B_M),
binaries:

Check failure on line 60 in src/virtual-counters-manager-utils.js

View workflow job for this annotation

GitHub Actions / build (16.x)

Expected indentation of 12 spaces but found 13
4
- lenM
+ computeLenThisBase(R_B_M)
- 4 * first_diff_chunk(B, M)
- 2 * first_diff_chunk(M, R_B_M),
ariths: 1 + computeLenThisBase(Q_B_M) * lenM,
+ 2 * computeLenThisBase(Q_B_M) * lenM,
ariths:
lenM * computeLenThisBase(Q_B_M)

Check failure on line 66 in src/virtual-counters-manager-utils.js

View workflow job for this annotation

GitHub Actions / build (16.x)

Missing trailing comma
};
}

// Counters computation of the half loop.
function halfLoopCounters() {
return {
steps:
399
+ 100 * lenB
+ 61 * ((lenB * (lenB + 1)) / 2)
+ 48 * lenM
+ 19 * lenE
+ 44 * E2
+ computeLenThisBase(Q_Bsq_M) * (30 + 33 * lenM)
+ 14 * computeLenThisBase(R_Bsq_M)
- 14 * first_diff_chunk(Bsq, M)
- 7 * first_diff_chunk(M, R_Bsq_M)
- 5 * NZ_Bsq,
153
+ 82 * lenM
+ 6 * lenE
+ (80 * lenM * (lenM - 1)) / 2
+ 19 * lenM**2

Check failure on line 77 in src/virtual-counters-manager-utils.js

View workflow job for this annotation

GitHub Actions / build (16.x)

Operator '**' must be spaced
+ 25 * lenQE2,
binaries:
23
+ 14 * lenB
+ 9 * ((lenB * (lenB + 1)) / 2)
+ 3 * lenM
+ 2 * lenE
+ 3 * E2
+ computeLenThisBase(Q_Bsq_M) * (1 + 4 * lenM)
+ computeLenThisBase(R_Bsq_M)
- 4 * first_diff_chunk(Bsq, M)
- 2 * first_diff_chunk(M, R_Bsq_M)
- NZ_Bsq,
9
+ 6 * lenM
+ (23 * lenM * (lenM - 1)) / 2
+ 2 * lenM**2

Check failure on line 83 in src/virtual-counters-manager-utils.js

View workflow job for this annotation

GitHub Actions / build (16.x)

Operator '**' must be spaced
+ 3 * lenQE2,
ariths:
2
+ lenB
+ (lenB * (lenB + 1)) / 2
+ E2
+ computeLenThisBase(Q_Bsq_M) * lenM,
- 1

Check failure on line 86 in src/virtual-counters-manager-utils.js

View workflow job for this annotation

GitHub Actions / build (16.x)

Unexpected space after unary operator '-'
+ 2 * lenM
+ (2 * lenM * (lenM - 1)) / 2
+ lenM**2

Check failure on line 89 in src/virtual-counters-manager-utils.js

View workflow job for this annotation

GitHub Actions / build (16.x)

Operator '**' must be spaced

Check failure on line 89 in src/virtual-counters-manager-utils.js

View workflow job for this annotation

GitHub Actions / build (16.x)

Missing trailing comma
};
}

// Counters computation of the full loop.
function fullLoopCounters() {
return {
steps:
674
+ 180 * lenB
+ 61 * ((lenB * (lenB + 1)) / 2)
+ 149 * lenM
+ 19 * lenE
+ 44 * E2
+ 66 * lenB * lenM
+ computeLenThisBase(Q_Bsq_M) * (30 + 33 * lenM)
+ 14 * computeLenThisBase(R_Bsq_M)
- 14 * first_diff_chunk(BM, M)
- 14 * first_diff_chunk(Bsq, M)
- 7 * first_diff_chunk(M, [0n])
- 7 * first_diff_chunk(M, R_Bsq_M)
- 5 * NZ_Bsq,
263
+ 114 * lenM
+ 6 * lenE
+ (80 * lenM * (lenM - 1)) / 2
+ 57 * lenM**2

Check failure on line 100 in src/virtual-counters-manager-utils.js

View workflow job for this annotation

GitHub Actions / build (16.x)

Operator '**' must be spaced
+ 25 * lenQE2,
binaries:
36
+ 21 * lenB
+ 9 * ((lenB * (lenB + 1)) / 2)
+ 12 * lenM
+ 2 * lenE
+ 3 * E2
+ 8 * lenB * lenM
+ computeLenThisBase(Q_Bsq_M) * (1 + 4 * lenM)
+ computeLenThisBase(R_Bsq_M)
- 4 * first_diff_chunk(BM, M)
- 4 * first_diff_chunk(Bsq, M)
- 2 * first_diff_chunk(M, [0n])
- 2 * first_diff_chunk(M, R_Bsq_M)
- NZ_Bsq,
17
+ 3 * lenM
+ (23 * lenM * (lenM - 1)) / 2
+ 6 * lenM**2

Check failure on line 106 in src/virtual-counters-manager-utils.js

View workflow job for this annotation

GitHub Actions / build (16.x)

Operator '**' must be spaced
+ 3 * lenQE2,
ariths:
4
+ lenB
+ (lenB * (lenB + 1)) / 2
+ E2
+ 2 * lenB * lenM
+ computeLenThisBase(Q_Bsq_M) * lenM,
- 1
+ 2 * lenM
+ (2 * lenM * (lenM - 1)) / 2
+ 3 * lenM**2
};
}
}
Expand Down
69 changes: 66 additions & 3 deletions src/virtual-counters-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@ const { expectedModExpCounters } = require('./virtual-counters-manager-utils');
const FPEC = Scalar.e('0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F');
const FNEC = Scalar.e('0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141');
const FNEC_MINUS_ONE = Scalar.sub(FNEC, Scalar.e(1));

const SECP256R1_N = Scalar.e('0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551');
const SECP256R1_N_MINUS_ONE = Scalar.sub(SECP256R1_N, 1);
const SECP256R1_P = Scalar.e('0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff');
const SECP256R1_P_MINUS_ONE = Scalar.sub(SECP256R1_P, 1);
const SECP256R1_A = Scalar.e('0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc');
const SECP256R1_B = Scalar.e('0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b');

const spentCountersByFunction = {};
module.exports = class VirtualCountersManager {
/**
Expand Down Expand Up @@ -236,7 +244,7 @@ module.exports = class VirtualCountersManager {
processTx(input) {
this._checkInput(input, ['bytecodeLength', 'isDeploy']);
this._reduceCounters(300, 'S');
this._reduceCounters(11 + 7, 'B');
this._reduceCounters(12 + 7, 'B');
this._reduceCounters(14 * MCP, 'P');
this._reduceCounters(5, 'D');
this._reduceCounters(2, 'A');
Expand Down Expand Up @@ -350,7 +358,7 @@ module.exports = class VirtualCountersManager {
}

_modexp(bLen, mLen, eLen, base, exponent, modulus) {
const modexpCounters = expectedModExpCounters(Math.ceil(bLen / 32), Math.ceil(mLen / 32), Math.ceil(eLen / 32), base, exponent, modulus);
const modexpCounters = expectedModExpCounters(Math.ceil(bLen / 32), Math.ceil(eLen / 32), Math.ceil(mLen / 32), base, exponent, modulus);
this._reduceCounters(modexpCounters.steps, 'S');
this._reduceCounters(modexpCounters.binaries, 'B');
this._reduceCounters(modexpCounters.ariths, 'A');
Expand Down Expand Up @@ -406,6 +414,61 @@ module.exports = class VirtualCountersManager {
this._mStore32();
}

preP256Verify(input) {
this._checkInput(input, ['r', 's', 'pubKeyX', 'pubKeyY']);
this._reduceCounters(50, 'S');
this._reduceCounters(1, 'B');
this._multiCall('_readFromCalldataOffset', 5);
this._p256verify(input);
this._mStore32();
this._mStoreX();
}

_p256verify(input) {
if(input.r === 0n) {
this._reduceCounters(13, 'S');
this._reduceCounters(1, 'B');
return;
} else if(Scalar.lt(SECP256R1_N_MINUS_ONE, input.r)) {
this._reduceCounters(15, 'S');
this._reduceCounters(2, 'B');
return;
} else if(input.s === 0n) {
this._reduceCounters(17, 'S');
this._reduceCounters(3, 'B');
return;
} else if(Scalar.lt(SECP256R1_N_MINUS_ONE, input.s)) {
this._reduceCounters(19, 'S');
this._reduceCounters(4, 'B');
return;
} else if(Scalar.lt(SECP256R1_P_MINUS_ONE, input.pubKeyX)) {
this._reduceCounters(22, 'S');
this._reduceCounters(5, 'B');
return;
} else if(Scalar.lt(SECP256R1_P_MINUS_ONE, input.pubKeyY)) {
this._reduceCounters(24, 'S');
this._reduceCounters(6, 'B');
return;
} else if(input.pubKeyX === 0n && input.pubKeyY === 0n) {
this._reduceCounters(29, 'S');
this._reduceCounters(8, 'B');
} else {
const aux_x3 = Scalar.mod(Scalar.exp(input.pubKeyX, 3),SECP256R1_P);
const aux_ax_b = Scalar.add(Scalar.mul(input.pubKeyX, SECP256R1_A), SECP256R1_B);
const aux_x3_ax_b = Scalar.mod(Scalar.add(aux_x3, aux_ax_b),SECP256R1_P);
const aux_y2 = Scalar.mod(Scalar.exp(input.pubKeyY, 2),SECP256R1_P);
if (!Scalar.eq(aux_y2,aux_x3_ax_b)) {
this._reduceCounters(104, 'S');
this._reduceCounters(15, 'B');
this._reduceCounters(12, 'A');
return;
}
this._reduceCounters(7718, 'S');
this._reduceCounters(22, 'B');
this._reduceCounters(531, 'A');
}
}

opAdd(input) {
this._opcode(input);
this._reduceCounters(10, 'S');
Expand Down Expand Up @@ -1701,7 +1764,7 @@ module.exports = class VirtualCountersManager {

_isColdAddress() {
this._reduceCounters(100, 'S');
this._reduceCounters(2 + 1, 'B');
this._reduceCounters(3 + 1, 'B');
this._reduceCounters(2 * MCPL, 'P');
}

Expand Down

0 comments on commit 5d7f217

Please sign in to comment.