|
| 1 | +import { Signature } from '@noble/secp256k1'; |
| 2 | +import { Secp256k1Curve } from '../../curves'; |
| 3 | +import { bigIntFromBufferBE, bigIntToBufferBE } from '../../util'; |
| 4 | +import { DeserializedDklsSignature } from './types'; |
| 5 | +import { decode } from 'cbor'; |
| 6 | + |
| 7 | +/** |
| 8 | + * Combines partial signatures from parties participating in DSG. |
| 9 | + * @param round4MessagePayloads - round 4 message payloads from participating parties |
| 10 | + * @param rHex - hex representation of the r value in the signature |
| 11 | + * @returns {DeserializedMessages} - messages to send to other parties for the next round |
| 12 | + */ |
| 13 | +export function combinePartialSignatures(round4MessagePayloads: Uint8Array[], rHex: string): DeserializedDklsSignature { |
| 14 | + const r = bigIntFromBufferBE(Buffer.from(rHex, 'hex').subarray(1)); |
| 15 | + const s0Arr = round4MessagePayloads.map((p) => decode(p).s_0); |
| 16 | + const s1Arr = round4MessagePayloads.map((p) => decode(p).s_1); |
| 17 | + const s0BigInts = s0Arr.map((s0) => bigIntFromBufferBE(Buffer.from(s0))); |
| 18 | + const s1BigInts = s1Arr.map((s1) => bigIntFromBufferBE(Buffer.from(s1))); |
| 19 | + const secp256k1Curve = new Secp256k1Curve(); |
| 20 | + const s0Sum = s0BigInts.slice(1).reduce((sumSoFar, s0) => secp256k1Curve.scalarAdd(sumSoFar, s0), s0BigInts[0]); |
| 21 | + const s1Sum = s1BigInts.slice(1).reduce((sumSoFar, s1) => secp256k1Curve.scalarAdd(sumSoFar, s1), s1BigInts[0]); |
| 22 | + const s = secp256k1Curve.scalarMult(s0Sum, secp256k1Curve.scalarInvert(s1Sum)); |
| 23 | + const sig = new Signature(r, s); |
| 24 | + const normalizedSig = sig.normalizeS(); |
| 25 | + return { |
| 26 | + R: new Uint8Array(bigIntToBufferBE(normalizedSig.r)), |
| 27 | + S: new Uint8Array(bigIntToBufferBE(normalizedSig.s)), |
| 28 | + }; |
| 29 | +} |
0 commit comments