partialSigVerify method

bool partialSigVerify({
  1. required List<int> signature,
  2. required List<int> pubnonce,
  3. required List<int> pk,
  4. required MuSig2Session session,
})

Verifies a MuSig2 partial signature

Implementation

bool partialSigVerify({
  required List<int> signature,
  required List<int> pubnonce,
  required List<int> pk,
  required MuSig2Session session,
}) {
  if (pubnonce.length != MuSig2Constants.pubnonceLength) {
    throw ArgumentException.invalidOperationArguments(
      "partialSigVerify",
      name: "pubnonce",
      reason: "Invalid pubnonce bytes length.",
      expecteLen: MuSig2Constants.pubnonceLength,
    );
  }
  final values = MuSig2Utils.decodeSession(session);
  final sBig = BigintUtils.fromBytes(signature);
  if (sBig >= MuSig2Constants.order) return false;
  final rS1 = MuSig2Utils.encodePointAsEven(
    pubnonce.sublist(0, EcdsaKeysConst.pubKeyCompressedByteLen),
  );
  final rS2 = MuSig2Utils.encodePointAsEven(
    pubnonce.sublist(
      EcdsaKeysConst.pubKeyCompressedByteLen,
      EcdsaKeysConst.pubKeyCompressedByteLen * 2,
    ),
  );
  BaseProjectivePointNative reS = (rS1 + (rS2 * values.bAsInteger));
  if (values.r.isOdd) {
    reS = -reS;
  }
  final p = MuSig2Utils.encodePoint(pk);
  final a = MuSig2Utils.getSessionKeyAggCoeff(session: session, pk: p);
  BigInt g = BigInt.one;
  if (values.publicKey.isOdd) {
    g = MuSig2Constants.order - BigInt.one;
  }
  g = g * values.gaccAsInteger % MuSig2Constants.order;
  final expected = MuSig2Constants.generator * sBig;
  final r = (reS + (p * (values.eAsInteger * a * g % MuSig2Constants.order)));

  return expected == r;
}