partialSigVerify method
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;
}