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); }
private static Script CombineSignatures(Script scriptPubKey, Transaction transaction, int n, byte[][] sigs1, byte[][] sigs2) { var 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) { if (sigs1.Length == 0 || sigs1[sigs1.Length - 1].Length == 0) { return(PushAll(sigs2)); } else if (sigs2.Length == 0 || sigs2[sigs2.Length - 1].Length == 0) { return(PushAll(sigs1)); } else { 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, transaction, n, sigs1, sigs2); result += Op.GetPushOp(redeemBytes); return(result); } } if (template is PayToMultiSigTemplate) { return(CombineMultisig(scriptPubKey, transaction, n, sigs1, sigs2)); } throw new NotSupportedException("An impossible thing happen !"); }
public override bool CheckScriptSig(Script scriptSig, Script scriptPubKey) { var ops = scriptSig.ToOps().ToArray(); if (ops.Length == 0) { return(false); } if (!scriptSig.IsPushOnly) { return(false); } if (!VerifyRedeemScript) { return(true); } var redeemScript = new Script(ops.Last().PushData); var template = StandardScripts.GetTemplateFromScriptPubKey(redeemScript); return(template != null && template.Type != TxOutType.TX_SCRIPTHASH); }
protected override bool CheckScriptSigCore(Script scriptSig, Op[] scriptSigOps, Script scriptPubKey, Op[] scriptPubKeyOps) { var ops = scriptSigOps; if (ops.Length == 0) { return(false); } if (!scriptSig.IsPushOnly) { return(false); } if (!VerifyRedeemScript) { return(true); } var redeemScript = new Script(ops[ops.Length - 1].PushData); var template = StandardScripts.GetTemplateFromScriptPubKey(redeemScript); return(template != null && template.Type != TxOutType.TX_SCRIPTHASH); }
public bool IsRelevantAndUpdate(Transaction tx) { if (tx == null) { throw new ArgumentNullException("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)); }
public virtual bool AreInputsStandard(Network network, Transaction tx, CoinsView coinsView) { return(StandardScripts.AreInputsStandard(network, tx, coinsView)); }
public virtual bool IsStandardScriptPubKey(Network network, Script scriptPubKey) { return(StandardScripts.IsStandardScriptPubKey(network, scriptPubKey)); }
public virtual ScriptTemplate GetTemplateFromScriptPubKey(Script script) { return(StandardScripts.GetTemplateFromScriptPubKey(script)); }
public virtual bool AreOutputsStandard(Network network, Transaction tx) { return(StandardScripts.AreOutputsStandard(network, tx)); }
public virtual bool IsStandardTransaction(Transaction tx, Network network) { return(StandardScripts.IsStandardTransaction(tx, network)); }
/// <summary> /// Registers a new standard script template if it does not exist yet based on <see cref="ScriptTemplate.Type" />. /// </summary> /// <param name="scriptTemplate">The standard script template to register.</param> public virtual void RegisterStandardScriptTemplate(ScriptTemplate scriptTemplate) { StandardScripts.RegisterStandardScriptTemplate(scriptTemplate); }
public static bool IsStandardTransaction(Transaction tx) { if (tx.Version > Transaction.CURRENT_VERSION || tx.Version < 1) { return(false); } //// Treat non-final transactions as non-standard to prevent a specific type //// of double-spend attack, as well as DoS attacks. (if the transaction //// can't be mined, the attacker isn't expending resources broadcasting it) //// Basically we don't want to propagate transactions that can't included in //// the next block. //// //// However, IsFinalTx() is confusing... Without arguments, it uses //// chainActive.Height() to evaluate nLockTime; when a block is accepted, chainActive.Height() //// is set to the value of nHeight in the block. However, when IsFinalTx() //// is called within CBlock::AcceptBlock(), the height of the block *being* //// evaluated is what is used. Thus if we want to know if a transaction can //// be part of the *next* block, we need to call IsFinalTx() with one more //// than chainActive.Height(). //// //// Timestamps on the other hand don't get any special treatment, because we //// can't know what timestamp the next block will have, and there aren't //// timestamp applications where it matters. //if (!IsFinalTx(tx, chainActive.Height() + 1)) { // reason = "non-final"; // return false; //} // Extremely large transactions with lots of inputs can cost the network // almost as much to process as they cost the sender in fees, because // computing signature hashes is O(ninputs*txsize). Limiting transactions // to MAX_STANDARD_TX_SIZE mitigates CPU exhaustion attacks. int sz = tx.GetSerializedSize(); if (sz >= Transaction.MAX_STANDARD_TX_SIZE) { return(false); } foreach (TxIn txin in tx.Inputs) { // Biggest 'standard' txin is a 3-signature 3-of-3 CHECKMULTISIG // pay-to-script-hash, which is 3 ~80-byte signatures, 3 // ~65-byte public keys, plus a few script ops. if (txin.ScriptSig.Length > 500) { return(false); } if (!txin.ScriptSig.IsPushOnly) { return(false); } if (!txin.ScriptSig.HasCanonicalPushes) { return(false); } } uint nDataOut = 0; foreach (TxOut txout in tx.Outputs) { var template = StandardScripts.GetTemplateFromScriptPubKey(txout.ScriptPubKey); if (template == null) { return(false); } if (template.Type == TxOutType.TX_NULL_DATA) { nDataOut++; } else if (txout.IsDust) { return(false); } } // only one OP_RETURN txout is permitted if (nDataOut > 1) { return(false); } return(true); }