aboutsummaryrefslogtreecommitdiff
path: root/src/policy
diff options
context:
space:
mode:
Diffstat (limited to 'src/policy')
-rw-r--r--src/policy/policy.cpp37
-rw-r--r--src/policy/rbf.cpp46
-rw-r--r--src/policy/rbf.h20
3 files changed, 72 insertions, 31 deletions
diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp
index 273a482fa1..c92a249c17 100644
--- a/src/policy/policy.cpp
+++ b/src/policy/policy.cpp
@@ -135,45 +135,20 @@ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
const CScript& prevScript = prev.scriptPubKey;
if (!Solver(prevScript, whichType, vSolutions))
return false;
- int nArgsExpected = ScriptSigArgsExpected(whichType, vSolutions);
- if (nArgsExpected < 0)
- return false;
-
- // Transactions with extra stuff in their scriptSigs are
- // non-standard. Note that this EvalScript() call will
- // be quick, because if there are any operations
- // beside "push data" in the scriptSig
- // IsStandardTx() will have already returned false
- // and this method isn't called.
- std::vector<std::vector<unsigned char> > stack;
- if (!EvalScript(stack, tx.vin[i].scriptSig, SCRIPT_VERIFY_NONE, BaseSignatureChecker()))
- return false;
if (whichType == TX_SCRIPTHASH)
{
+ std::vector<std::vector<unsigned char> > stack;
+ // convert the scriptSig into a stack, so we can inspect the redeemScript
+ if (!EvalScript(stack, tx.vin[i].scriptSig, SCRIPT_VERIFY_NONE, BaseSignatureChecker(), 0))
+ return false;
if (stack.empty())
return false;
CScript subscript(stack.back().begin(), stack.back().end());
- std::vector<std::vector<unsigned char> > vSolutions2;
- txnouttype whichType2;
- if (Solver(subscript, whichType2, vSolutions2))
- {
- int tmpExpected = ScriptSigArgsExpected(whichType2, vSolutions2);
- if (tmpExpected < 0)
- return false;
- nArgsExpected += tmpExpected;
- }
- else
- {
- // Any other Script with less than 15 sigops OK:
- unsigned int sigops = subscript.GetSigOpCount(true);
- // ... extra data left on the stack after execution is OK, too:
- return (sigops <= MAX_P2SH_SIGOPS);
+ if (subscript.GetSigOpCount(true) > MAX_P2SH_SIGOPS) {
+ return false;
}
}
-
- if (stack.size() != (unsigned int)nArgsExpected)
- return false;
}
return true;
diff --git a/src/policy/rbf.cpp b/src/policy/rbf.cpp
new file mode 100644
index 0000000000..98b1a1ba4c
--- /dev/null
+++ b/src/policy/rbf.cpp
@@ -0,0 +1,46 @@
+// Copyright (c) 2016 The Bitcoin developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include "policy/rbf.h"
+
+bool SignalsOptInRBF(const CTransaction &tx)
+{
+ BOOST_FOREACH(const CTxIn &txin, tx.vin) {
+ if (txin.nSequence < std::numeric_limits<unsigned int>::max()-1) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool IsRBFOptIn(const CTxMemPoolEntry &entry, CTxMemPool &pool)
+{
+ AssertLockHeld(pool.cs);
+
+ CTxMemPool::setEntries setAncestors;
+
+ // First check the transaction itself.
+ if (SignalsOptInRBF(entry.GetTx())) {
+ return true;
+ }
+
+ // If this transaction is not in our mempool, then we can't be sure
+ // we will know about all its inputs.
+ if (!pool.exists(entry.GetTx().GetHash())) {
+ throw std::runtime_error("Cannot determine RBF opt-in signal for non-mempool transaction\n");
+ }
+
+ // If all the inputs have nSequence >= maxint-1, it still might be
+ // signaled for RBF if any unconfirmed parents have signaled.
+ uint64_t noLimit = std::numeric_limits<uint64_t>::max();
+ std::string dummy;
+ pool.CalculateMemPoolAncestors(entry, setAncestors, noLimit, noLimit, noLimit, noLimit, dummy, false);
+
+ BOOST_FOREACH(CTxMemPool::txiter it, setAncestors) {
+ if (SignalsOptInRBF(it->GetTx())) {
+ return true;
+ }
+ }
+ return false;
+}
diff --git a/src/policy/rbf.h b/src/policy/rbf.h
new file mode 100644
index 0000000000..925ce0d9bd
--- /dev/null
+++ b/src/policy/rbf.h
@@ -0,0 +1,20 @@
+// Copyright (c) 2016 The Bitcoin developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_POLICY_RBF_H
+#define BITCOIN_POLICY_RBF_H
+
+#include "txmempool.h"
+
+// Check whether the sequence numbers on this transaction are signaling
+// opt-in to replace-by-fee, according to BIP 125
+bool SignalsOptInRBF(const CTransaction &tx);
+
+// Determine whether an in-mempool transaction is signaling opt-in to RBF
+// according to BIP 125
+// This involves checking sequence numbers of the transaction, as well
+// as the sequence numbers of all in-mempool ancestors.
+bool IsRBFOptIn(const CTxMemPoolEntry &entry, CTxMemPool &pool);
+
+#endif // BITCOIN_POLICY_RBF_H