Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Develop durian #186

Open
wants to merge 12 commits into
base: develop
Choose a base branch
from
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)
+ 12 * computeLenThisBase(R_B_M),
binaries:
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),
};
}

// 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
+ 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
+ 3 * lenQE2,
ariths:
2
+ lenB
+ (lenB * (lenB + 1)) / 2
+ E2
+ computeLenThisBase(Q_Bsq_M) * lenM,
-1
+ 2 * lenM
+ (2 * lenM * (lenM - 1)) / 2
+ lenM ** 2,
};
}

// 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
+ 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
+ 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
64 changes: 61 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,56 @@ 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');
} else if (Scalar.lt(SECP256R1_N_MINUS_ONE, input.r)) {
this._reduceCounters(15, 'S');
this._reduceCounters(2, 'B');
} else if (input.s === 0n) {
this._reduceCounters(17, 'S');
this._reduceCounters(3, 'B');
} else if (Scalar.lt(SECP256R1_N_MINUS_ONE, input.s)) {
this._reduceCounters(19, 'S');
this._reduceCounters(4, 'B');
} else if (Scalar.lt(SECP256R1_P_MINUS_ONE, input.pubKeyX)) {
this._reduceCounters(22, 'S');
this._reduceCounters(5, 'B');
} else if (Scalar.lt(SECP256R1_P_MINUS_ONE, input.pubKeyY)) {
this._reduceCounters(24, 'S');
this._reduceCounters(6, 'B');
} else if (input.pubKeyX === 0n && input.pubKeyY === 0n) {
this._reduceCounters(29, 'S');
this._reduceCounters(8, 'B');
} else {
const auxX3 = Scalar.mod(Scalar.exp(input.pubKeyX, 3), SECP256R1_P);
const auxAxB = Scalar.add(Scalar.mul(input.pubKeyX, SECP256R1_A), SECP256R1_B);
const auxX3AxB = Scalar.mod(Scalar.add(auxX3, auxAxB), SECP256R1_P);
const auxY2 = Scalar.mod(Scalar.exp(input.pubKeyY, 2), SECP256R1_P);
if (!Scalar.eq(auxY2, auxX3AxB)) {
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 +1759,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
Loading