MetacoSA / NBitcoin

Comprehensive Bitcoin library for the .NET framework.
MIT License
1.87k stars 845 forks source link

Implementing musig2 #1017

Closed NicolasDorier closed 3 years ago

NicolasDorier commented 3 years ago

Typical usage:

var msg32 = random_scalar_order().ToBytes();
var tweak = random_scalar_order().ToBytes();
var adaptor = ctx.CreateECPrivKey(random_scalar_order());
var peers = 3;
var privKeys = new ECPrivKey[peers];
var privNonces = new MusigPrivNonce[peers];
var pubNonces = new MusigPubNonce[peers];
var musig = new MusigContext[peers];
var sigs = new MusigPartialSignature[peers];
var pubKeys = new ECXOnlyPubKey[peers];

for (int i = 0; i < peers; i++)
{
    privKeys[i] = ctx.CreateECPrivKey(random_scalar_order());
    pubKeys[i] = privKeys[i].CreateXOnlyPubKey();
}

for (int i = 0; i < peers; i++)
{
    musig[i] = new MusigContext(pubKeys, msg32);
    privNonces[i] = musig[i].GenerateNonce((uint)i, privKeys[i]);
    pubNonces[i] = privNonces[i].CreatePubNonce();
}

for (int i = 0; i < peers; i++)
{
    if (useTweak)
    {
        musig[i].Tweak(tweak);
    }
    if (useAdaptor)
    {
        musig[i].UseAdaptor(adaptor.CreatePubKey());
    }

    musig[i].ProcessNonces(pubNonces);
    sigs[i] = musig[i].Sign(privKeys[i], privNonces[i]);
}

// Verify all the partial sigs
for (int i = 0; i < peers; i++)
{
    Assert.True(musig[i].Verify(pubKeys[i], pubNonces[i], sigs[i]));
}

// Combine
var schnorrSig = musig[0].Combine(sigs);

if (useAdaptor)
    schnorrSig = musig[0].Adapt(schnorrSig, adaptor);
// Verify resulting signature
// SigningPubKey is the tweaked key if tweaked, or the combined key if not
Assert.True(musig[0].SigningPubKey.SigVerifyBIP340(schnorrSig, msg32));
dangershony commented 3 years ago

Brilliant, the typical use example will be hard to find when this PR is closed that will be a shame.

NicolasDorier commented 3 years ago

@dangershony I should really work on a better doc of NBitcoin :(