UNPKG

@covenance/dlc

Version:

Crypto and Bitcoin functions for Covenance DLC implementation

108 lines 4.95 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.createAdaptorSig = createAdaptorSig; exports.adaptSig = adaptSig; exports.verifyAdaptorSig = verifyAdaptorSig; exports.generateEvenYPrivateKey = generateEvenYPrivateKey; const secp256k1_1 = require("./secp256k1"); const utils_1 = require("../utils"); const general_1 = require("./general"); /** * Counterparty function to create an adaptor signature for a specific event outcome * @param counterpartyPrivKey - Counterparty's private key * @param oracleSigPoint - Oracle's signature point for the event outcome * @param cetSighash - Sighash of the event outcome CET * @returns Counterparty's adaptor signature */ async function createAdaptorSig(counterpartyPrivKey, oracleSigPoint, cetSighash, tag = Uint8Array.from(Buffer.from('7bb52d7a9fef58323eb1bf7a407db382d2f3f2d81bb1224f49fe518f6d48d37c', 'hex')) // SHA256('BIP0340/challenge') ) { let r_cp; let r_cpBigInt; let R_cp; let R_prime_cp; // Generate nonce UNTIL (R_cp + S_i).y is even do { // Generate random nonce r_cp = secp256k1_1.utils.randomPrivateKey(); r_cpBigInt = BigInt('0x' + (0, utils_1.bytesToHex)(r_cp)); // Compute R_cp = r_cp * G R_cp = secp256k1_1.Point.fromPrivateKey(r_cpBigInt); // Compute R'_cp = R_cp + S_i R_prime_cp = R_cp.add(oracleSigPoint); } while ((R_prime_cp.y & 1n) === 1n); // Fail if r = 0 if (r_cpBigInt === 0n) { throw new Error('Generated nonce is zero'); } // Get counterparty's public key const P_cp = secp256k1_1.Point.fromPrivateKey(counterpartyPrivKey); // Compute H(tag||tag||R'_cp||P_cp||cet_i) const hashInput = new Uint8Array([ ...tag, ...tag, ...R_prime_cp.toRawBytes(true).slice(1), ...P_cp.toRawBytes(true).slice(1), ...cetSighash ]); const hash = await (0, utils_1.sha256)(hashInput); const e = (0, general_1.mod)(BigInt('0x' + (0, utils_1.bytesToHex)(hash)), secp256k1_1.CURVE.n); // Compute s'_cp = r_cp + H(R'_cp||P_cp||cet_i)x_cp const x_cp = BigInt('0x' + (0, utils_1.bytesToHex)(counterpartyPrivKey)); const s_prime_cp = (0, general_1.mod)(r_cpBigInt + e * x_cp, secp256k1_1.CURVE.n); return { R_prime: R_prime_cp, s_prime: s_prime_cp }; } /** * Counterparty function to adapt (finalize) an adaptor signature * @param adaptorSig - The adaptor signature to finalize * @param s - The oracle's scalar value (s) from their signature or repayment secret * @returns The final signature */ function adaptSig(adaptorSig, s) { // Compute s_cp = s'_cp + s const s_cp = adaptorSig.s_prime + s; return { R: adaptorSig.R_prime, s: (0, general_1.mod)(s_cp, secp256k1_1.CURVE.n) }; } /** * Function to verify an adaptor signature * @param adaptorSig - The adaptor signature to verify * @param counterpartyPubKey - The counterparty's public key * @param cetSighash - The sighash of the event outcome CET * @param oracleSigPoint - The oracle's signature point for the event outcome * @returns Boolean indicating whether the adaptor signature is valid */ async function verifyAdaptorSig(adaptorSig, counterpartyPubKey, cetSighash, oracleSigPoint, tag = Uint8Array.from(Buffer.from('7bb52d7a9fef58323eb1bf7a407db382d2f3f2d81bb1224f49fe518f6d48d37c', 'hex')) // SHA256('BIP0340/challenge') ) { // Compute H(tag||tag||R'_cp||P_cp||cet_i) const hashInput = new Uint8Array([ ...tag, ...tag, ...adaptorSig.R_prime.toRawBytes(true).slice(1), ...counterpartyPubKey.toRawBytes(true).slice(1), ...cetSighash ]); const hash = await (0, utils_1.sha256)(hashInput); const e = (0, general_1.mod)(BigInt('0x' + (0, utils_1.bytesToHex)(hash)), secp256k1_1.CURVE.n); // Compute s'_cp * G const sG = secp256k1_1.Point.BASE.multiply(adaptorSig.s_prime); // Compute R_cp = R'_cp - S_i const R_cp = adaptorSig.R_prime.subtract(oracleSigPoint); // Compute R_cp + e * P_cp const rightSide = R_cp.add(counterpartyPubKey.multiply(e)); // Verify s'_cp * G = R_cp + e * P_cp return sG.equals(rightSide); } /** * Function to generate a private key which produces a public key with even y. * This is to avoid doing BIP-340 secret-key parity adjustment (flip if public key has odd Y) each time an adaptor signature is created. * @returns A private key which produces a public key with even y. */ function generateEvenYPrivateKey() { let privKey = BigInt('0x' + (0, utils_1.bytesToHex)(secp256k1_1.utils.randomPrivateKey())); let pubKey = secp256k1_1.Point.fromPrivateKey(privKey); if ((pubKey.y & 1n) === 1n) { privKey = secp256k1_1.CURVE.n - privKey; // negate secret pubKey = secp256k1_1.Point.fromPrivateKey(privKey); // now pubKey.y is even } return Buffer.from(privKey.toString(16).padStart(64, "0"), "hex"); } //# sourceMappingURL=counterparty.js.map