private static Script CombineSignatures(Script scriptPubKey, TransactionChecker checker, byte[][] sigs1, byte[][] sigs2, HashVersion hashVersion) { var template = StandardScripts.GetTemplateFromScriptPubKey(scriptPubKey); if (template is PayToWitPubKeyHashTemplate) { scriptPubKey = new KeyId(scriptPubKey.ToBytes(true).SafeSubarray(1, 20)).ScriptPubKey; template = StandardScripts.GetTemplateFromScriptPubKey(scriptPubKey); } if (template == null || template is TxNullDataTemplate) { return(PushAll(Max(sigs1, sigs2))); } if (template is PayToPubkeyTemplate || template is PayToPubkeyHashTemplate) { if (sigs1.Length == 0 || sigs1[0].Length == 0) { return(PushAll(sigs2)); } else { return(PushAll(sigs1)); } } if (template is PayToScriptHashTemplate || template is PayToWitTemplate) { if (sigs1.Length == 0 || sigs1[sigs1.Length - 1].Length == 0) { return(PushAll(sigs2)); } if (sigs2.Length == 0 || sigs2[sigs2.Length - 1].Length == 0) { return(PushAll(sigs1)); } var redeemBytes = sigs1[sigs1.Length - 1]; var redeem = new Script(redeemBytes); sigs1 = sigs1.Take(sigs1.Length - 1).ToArray(); sigs2 = sigs2.Take(sigs2.Length - 1).ToArray(); Script result = CombineSignatures(redeem, checker, sigs1, sigs2, hashVersion); result += Op.GetPushOp(redeemBytes); return(result); } if (template is PayToMultiSigTemplate) { return(CombineMultisig(scriptPubKey, checker, sigs1, sigs2, hashVersion)); } return(null); }
public bool IsRelevantAndUpdate(Transaction tx) { if (tx == null) { throw new ArgumentNullException(nameof(tx)); } var hash = tx.GetHash(); bool fFound = false; // Match if the filter contains the hash of tx // for finding tx when they appear in a block if (isFull) { return(true); } if (isEmpty) { return(false); } if (Contains(hash)) { fFound = true; } for (uint i = 0; i < tx.Outputs.Count; i++) { TxOut txout = tx.Outputs[(int)i]; // Match if the filter contains any arbitrary script data element in any scriptPubKey in tx // If this matches, also add the specific output that was matched. // This means clients don't have to update the filter themselves when a new relevant tx // is discovered in order to find spending transactions, which avoids round-tripping and race conditions. foreach (Op op in txout.ScriptPubKey.ToOps()) { if (op.PushData != null && op.PushData.Length != 0 && Contains(op.PushData)) { fFound = true; if ((nFlags & (byte)BloomFlags.UPDATE_MASK) == (byte)BloomFlags.UPDATE_ALL) { Insert(new OutPoint(hash, i)); } else if ((nFlags & (byte)BloomFlags.UPDATE_MASK) == (byte)BloomFlags.UPDATE_P2PUBKEY_ONLY) { var template = StandardScripts.GetTemplateFromScriptPubKey(txout.ScriptPubKey); if (template != null && (template.Type == TxOutType.TX_PUBKEY || template.Type == TxOutType.TX_MULTISIG)) { Insert(new OutPoint(hash, i)); } } break; } } } if (fFound) { return(true); } foreach (TxIn txin in tx.Inputs) { // Match if the filter contains an outpoint tx spends if (Contains(txin.PrevOut)) { return(true); } // Match if the filter contains any arbitrary script data element in any scriptSig in tx foreach (Op op in txin.ScriptSig.ToOps()) { if (op.PushData != null && op.PushData.Length != 0 && Contains(op.PushData)) { return(true); } } } return(false); }
public ScriptTemplate FindTemplate() { return(StandardScripts.GetTemplateFromScriptPubKey(this)); }