Extract key ID
MODIFY
WalletWasabi/Blockchain/TransactionOutputs/ForeignVirtualOutput.cs
WalletWasabi/Blockchain/TransactionOutputs/ForeignVirtualOutput.cs
@@ -9,14 +9,17 @@ namespace WalletWasabi.Blockchain.TransactionOutputs;
public class ForeignVirtualOutput
{
- public ForeignVirtualOutput(Script script, Money amount, ISet<OutPoint> outPoints)
+ /// <param name="keyId">Unique public key identifier or if we can't have that, then the scriptpubkey byte array.</param>
+ public ForeignVirtualOutput(byte[] keyId, Money amount, ISet<OutPoint> outPoints)
{
- Script = script;
+ KeyId = keyId;
Amount = amount;
OutPoints = outPoints;
}
- public Script Script { get; }
+ /// <summary>Unique public key identifier or if we can't have that, then the scriptpubkey byte array. </summary>
+ public byte[] KeyId { get; }
+
public Money Amount { get; }
public ISet<OutPoint> OutPoints { get; }
}

MODIFY
WalletWasabi/Blockchain/Transactions/SmartTransaction.cs
WalletWasabi/Blockchain/Transactions/SmartTransaction.cs
@@ -132,7 +132,7 @@ public class SmartTransaction : IEquatable<SmartTransaction>
if (ForeignVirtualOutputsCache is null)
{
ForeignVirtualOutputsCache = ForeignOutputs
- .GroupBy(o => o.TxOut.ScriptPubKey)
+ .GroupBy(o => o.TxOut.ScriptPubKey.ExtractKeyId())
.Select(g => new ForeignVirtualOutput(g.Key, g.Sum(o => o.TxOut.Value), g.Select(o => new OutPoint(GetHash(), o.N)).ToHashSet()))
.ToHashSet();
}

MODIFY
WalletWasabi/Extensions/NBitcoinExtensions.cs
WalletWasabi/Extensions/NBitcoinExtensions.cs
@@ -495,4 +495,29 @@ public static class NBitcoinExtensions
return instance;
}
+
+ /// <summary>
+ /// Extracts a unique public key identifier. If it can't do that, then it returns the scriptpubkey byte array.
+ /// </summary>
+ public static byte[] ExtractKeyId(this Script scriptPubKey)
+ => scriptPubKey.TryGetScriptType() switch
+ {
+ ScriptType.P2WPKH => PayToWitPubKeyHashTemplate.Instance.ExtractScriptPubKeyParameters(scriptPubKey)!.ToBytes(),
+ ScriptType.P2PKH => PayToPubkeyHashTemplate.Instance.ExtractScriptPubKeyParameters(scriptPubKey)!.ToBytes(),
+ ScriptType.P2PK => PayToPubkeyTemplate.Instance.ExtractScriptPubKeyParameters(scriptPubKey)!.ToBytes(),
+ _ => scriptPubKey.ToBytes()
+ };
+
+ public static ScriptType? TryGetScriptType(this Script script)
+ {
+ foreach (ScriptType scriptType in new ScriptType[] { ScriptType.P2WPKH, ScriptType.P2PKH, ScriptType.P2PK, ScriptType.Taproot })
+ {
+ if (script.IsScriptType(scriptType))
+ {
+ return scriptType;
+ }
+ }
+
+ return null;
+ }
}

Extract key ID