Support P2TR in BIP322
MODIFY
WalletWasabi/Crypto/Bip322Signature.cs
WalletWasabi/Crypto/Bip322Signature.cs
@@ -44,7 +44,8 @@ public record Bip322Signature : IBitcoinSerializable
scriptPubKey.GetScriptType() switch
{
ScriptType.P2WPKH => VerifyP2wpkh(hash, scriptPubKey),
- _ => throw new NotImplementedException("Only P2WPKH scripts are supported.")
+ ScriptType.Taproot => VerifyP2tr(hash, scriptPubKey),
+ _ => throw new NotImplementedException("Only P2WPKH and P2TR scripts are supported.")
};
public static Bip322Signature Generate(Key key, uint256 hash, ScriptPubKeyType scriptPubKeyType) =>
@@ -55,7 +56,11 @@ public record Bip322Signature : IBitcoinSerializable
PayToWitPubKeyHashTemplate.Instance.GenerateWitScript(
key.Sign(hash, new SigningOptions(SigHash.All, useLowR: false)),
key.PubKey)),
- _ => throw new NotImplementedException("Only P2WPKH scripts are supported.")
+ ScriptPubKeyType.TaprootBIP86 => new Bip322Signature(
+ Script.Empty,
+ PayToTaprootTemplate.Instance.GenerateWitScript(
+ key.SignTaprootKeySpend(hash, null, uint256.Zero, TaprootSigHash.Default))),
+ _ => throw new NotImplementedException("Only P2WPKH and P2TR scripts are supported.")
};
private bool VerifyP2wpkh(uint256 hash, Script scriptPubKey)
@@ -89,4 +94,31 @@ public record Bip322Signature : IBitcoinSerializable
return false;
}
}
+
+ private bool VerifyP2tr(uint256 hash, Script scriptPubKey)
+ {
+ if (ScriptSig != Script.Empty)
+ {
+ return false;
+ }
+
+ try
+ {
+ if (PayToTaprootTemplate.Instance.ExtractWitScriptParameters(Witness) is not { } witnessParameters)
+ {
+ return false;
+ }
+
+ if (PayToTaprootTemplate.Instance.ExtractScriptPubKeyParameters(scriptPubKey) is not { } publicKey)
+ {
+ return false;
+ }
+
+ return publicKey.VerifySignature(hash, witnessParameters.TransactionSignature.SchnorrSignature);
+ }
+ catch (FormatException)
+ {
+ return false;
+ }
+ }
}

MODIFY
WalletWasabi/Extensions/NBitcoinExtensions.cs
WalletWasabi/Extensions/NBitcoinExtensions.cs
@@ -355,7 +355,7 @@ public static class NBitcoinExtensions
public static ScriptType? GetScriptType(this Script script)
{
- foreach (ScriptType scriptType in new ScriptType[] { ScriptType.P2WPKH })
+ foreach (ScriptType scriptType in new ScriptType[] { ScriptType.P2WPKH, ScriptType.Taproot })
{
if (script.IsScriptType(scriptType))
{

Support P2TR in BIP322