Skip to content

Instantly share code, notes, and snippets.

@samlaf
Last active November 2, 2023 06:10
Show Gist options
  • Save samlaf/f7ebf03e95214ff6b31fc5e6534d6245 to your computer and use it in GitHub Desktop.
Save samlaf/f7ebf03e95214ff6b31fc5e6534d6245 to your computer and use it in GitHub Desktop.
//
// _ _____ ______ _____ _
// /\ (_) | __ \| ____| __ \| |
// / \ __ ___ ___ _ __ ___ | |__) | |__ | |__) | |
// / /\ \ \ \/ / |/ _ \| '_ ` _ \| _ /| __| | ___/| |
// / ____ \ > <| | (_) | | | | | | | \ \| |____| | | |____
// /_/ \_\/_/\_\_|\___/|_| |_| |_|_| \_\______|_| |______|
//
//
// BLSPubkeyRegistry contract stores the apk of registered operators, for each quorum (we only look at quorum 0 for now)
const quorumG1ApkXMapping = getSolidityMapping(taskCreatedBlock, blsPubkeyRegistryAddr, quorumG1ApkXSlot)
const quorumG1ApkYMapping = getSolidityMapping(taskCreatedBlock, blsPubkeyRegistryAddr, quorumG1ApkYSlot)
const allOperatorsCircuitG1Apk = { x: quorumG1ApkXMapping.key(0), y: quorumG1ApkYMapping.key(0) }
// BLSPubkeyCompendium contract contains the following mappings (at slots 0 and 1):
// mapping(address => uint256) public operatorToG1PubkeyX;
// mapping(address => uint256) public operatorToG1PubkeyY;
const operatorToG1PubkeyXMapping = getSolidityMapping(taskCreatedBlock, blsPubkeyCompendiumAddr, operatorToG1PubkeyXSlot)
const operatorToG1PubkeyYMapping = getSolidityMapping(taskCreatedBlock, blsPubkeyCompendiumAddr, operatorToG1PubkeyYSlot)
const nonsignersCircuitPubkeys = nonsignersAddrs.map(nonsignerAddr => {
const nonsignerG1PubkeyX = operatorToG1PubkeyXMapping.key(nonsignerAddr)
const nonsignerG1PubkeyY = operatorToG1PubkeyYMapping.key(nonsignerAddr)
return { x: nonsignerG1PubkeyX, y: nonsignerG1PubkeyY }
})
let signersG1Apk;
if (nonsignersCircuitPubkeys.length > 0) {
const nonsignersG1Apk = bn254G1Sum(nonsignersCircuitPubkeys)
// we subtract all nonsigners pubkeys from the apk to get the signersApk
signersG1Apk = bn254G1SubUnequal(allOperatorsCircuitG1Apk, bn254G1AffinePointToCircuitBn254G1Affine(nonsignersG1Apk))
} else {
signersG1Apk = loadBn254G1(allOperatorsCircuitG1Apk)
}
// // bls sig check function is still tbd
// // halo2-lib one is here: https://github.com/axiom-crypto/halo2-lib/blob/980b39bcca5b3327aaef6c8d73577d9381bfa899/halo2-ecc/src/bn254/bls_signature.rs#L27C12-L34C6
// // might look something like:
let g1Generator = loadBn254G1({ x: newCircuitValue256(constant(0), constant(1)), y: newCircuitValue256(constant(0), constant(2)) })
const taskResponseDigestBn254G2 = loadBn254G2FromCircuitValue256(
taskResponseDigestG2Coords[0], taskResponseDigestG2Coords[1],
taskResponseDigestG2Coords[2], taskResponseDigestG2Coords[3]
)
const aggSigG2 = loadBn254G2FromCircuitValue256(aggSigG2Coords[0], aggSigG2Coords[1], aggSigG2Coords[2], aggSigG2Coords[3])
bn254PairingCheck(signersG1Apk, taskResponseDigestBn254G2, g1Generator, aggSigG2)
// TODO: we also need to check that number of signers > threshold
taskResponseDigestG2Coords.map(addToCallback)
nonsignersAddrs.map(addToCallback)
// // we also need to make sure that the blspubkeyregistry points to the blspubkeycompendium
addToCallback(blsPubkeyRegistryAddr)
addToCallback(blsPubkeyCompendiumAddr)
// TODO (in ts code): make sure to add task and taskResponse as extraData
// helper functions
function bn254G1AffinePointToCircuitBn254G1Affine(p) {
return {
x: convertBn254FqToCircuitValue256(p.x()),
y: convertBn254FqToCircuitValue256(p.y())
}
}
function loadBn254G1FromCircuitValue256(x, y) {
return loadBn254G1({ x: x, y: y })
}
function loadBn254G2FromCircuitValue256(x_c0, x_c1, y_c0, y_c1) {
let circuitBn254Fq2X = { c0: x_c0, c1: x_c1 };
let circuitBn254Fq2Y = { c0: y_c0, c1: y_c1 };
return loadBn254G2({ x: circuitBn254Fq2X, y: circuitBn254Fq2Y })
}
function loadBn254G2FromBigInts(x_c0, x_c1, y_c0, y_c1) {
const { hi: high128xC0, lo: low128xC0 } = splitBigInt(x_c0);
const { hi: high128xC1, lo: low128xC1 } = splitBigInt(x_c1);
const { hi: high128yC0, lo: low128yC0 } = splitBigInt(y_c0);
const { hi: high128yC1, lo: low128yC1 } = splitBigInt(y_c1);
const circuitValue256XC0 = newCircuitValue256(witness(high128xC0), witness(low128xC0));
const circuitValue256XC1 = newCircuitValue256(witness(high128xC1), witness(low128xC1));
const circuitValue256YC0 = newCircuitValue256(witness(high128yC0), witness(low128yC0));
const circuitValue256YC1 = newCircuitValue256(witness(high128yC1), witness(low128yC1));
let circuitBn254Fq2X = { c0: circuitValue256XC0, c1: circuitValue256XC1 };
let circuitBn254Fq2Y = { c0: circuitValue256YC0, c1: circuitValue256YC1 };
return loadBn254G2({ x: circuitBn254Fq2X, y: circuitBn254Fq2Y })
}
function splitBigInt(bigIntValue) {
const mask128 = BigInt("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"); // 128-bit mask
const lo = bigIntValue & mask128; // Low 128 bits
const hi = (bigIntValue >> BigInt(128)) & mask128; // High 128 bits
return { hi, lo };
}
{
"taskResponseDigestG2Coords": [
"0x1A9F9C2192443DAD96DEA99809D7BCB4BF07B77E776B2EE5A110673DDB35ADC6",
"0x1C85512EA29263F26D472EBE329A35A370047DB2A87FC03186ECC67AFC54EE7C",
"0x2A562852B360FEB4C9E320C6B3DE2A22F83D3D58B4298781BB7CDF0EA7D7DB2E",
"0x17F0207F8241C307BD89E3A22CB8E47AA200E0912C2368519567348689C22193"
],
"aggSigG2Coords": [
"0x1E1CEEF9F6607D1C99879951AC4D74A48106A664ED6F0F86C4698E43D0304BBF",
"0x1FBD095B66A4A00E66F6575C269873A43271AC1669381F55312634B43C444199",
"0x2DFFD3B20751A407EC594E26B7EE3130115B1B0D6AE2C5391F03171C1360825D",
"0x2DDDC27321F17DB8CBFA5B55E997DF2CFE2B64C9C989937D8F935A9002409043"
],
"taskCreatedBlock": 9961355,
"blsPubkeyRegistryAddr": "0x7c46B99d6182dACCbeb3D82Eaff2Dc3266da7B02",
"quorumG1ApkXSlot": 3,
"quorumG1ApkYSlot": 4,
"blsPubkeyCompendiumAddr": "0x40971B1c11c71D60e0e18E0B400a4ADD2485961F",
"operatorToG1PubkeyXSlot": 0,
"operatorToG1PubkeyYSlot": 1,
"nonsignersAddrs": []
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment