Browse Source

Make ATMP optionally return the CTransactionRefs it replaced

0.14
Matt Corallo 8 years ago
parent
commit
edded808fc
  1. 2
      src/rpc/rawtransaction.cpp
  2. 2
      src/test/txvalidationcache_tests.cpp
  3. 18
      src/validation.cpp
  4. 9
      src/validation.h
  5. 2
      src/wallet/wallet.cpp

2
src/rpc/rawtransaction.cpp

@ -899,7 +899,7 @@ UniValue sendrawtransaction(const JSONRPCRequest& request)
// push to local node and sync with wallets // push to local node and sync with wallets
CValidationState state; CValidationState state;
bool fMissingInputs; bool fMissingInputs;
if (!AcceptToMemoryPool(mempool, state, std::move(tx), fLimitFree, &fMissingInputs, false, nMaxRawTxFee)) { if (!AcceptToMemoryPool(mempool, state, std::move(tx), fLimitFree, &fMissingInputs, NULL, false, nMaxRawTxFee)) {
if (state.IsInvalid()) { if (state.IsInvalid()) {
throw JSONRPCError(RPC_TRANSACTION_REJECTED, strprintf("%i: %s", state.GetRejectCode(), state.GetRejectReason())); throw JSONRPCError(RPC_TRANSACTION_REJECTED, strprintf("%i: %s", state.GetRejectCode(), state.GetRejectReason()));
} else { } else {

2
src/test/txvalidationcache_tests.cpp

@ -23,7 +23,7 @@ ToMemPool(CMutableTransaction& tx)
LOCK(cs_main); LOCK(cs_main);
CValidationState state; CValidationState state;
return AcceptToMemoryPool(mempool, state, MakeTransactionRef(tx), false, NULL, true, 0); return AcceptToMemoryPool(mempool, state, MakeTransactionRef(tx), false, NULL, NULL, true, 0);
} }
BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, TestChain100Setup) BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, TestChain100Setup)

18
src/validation.cpp

@ -538,8 +538,8 @@ static bool IsCurrentForFeeEstimation()
} }
bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const CTransactionRef& ptx, bool fLimitFree, bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const CTransactionRef& ptx, bool fLimitFree,
bool* pfMissingInputs, int64_t nAcceptTime, bool fOverrideMempoolLimit, const CAmount& nAbsurdFee, bool* pfMissingInputs, int64_t nAcceptTime, std::list<CTransactionRef>* plTxnReplaced,
std::vector<uint256>& vHashTxnToUncache) bool fOverrideMempoolLimit, const CAmount& nAbsurdFee, std::vector<uint256>& vHashTxnToUncache)
{ {
const CTransaction& tx = *ptx; const CTransaction& tx = *ptx;
const uint256 hash = tx.GetHash(); const uint256 hash = tx.GetHash();
@ -950,6 +950,8 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
hash.ToString(), hash.ToString(),
FormatMoney(nModifiedFees - nConflictingFees), FormatMoney(nModifiedFees - nConflictingFees),
(int)nSize - (int)nConflictingSize); (int)nSize - (int)nConflictingSize);
if (plTxnReplaced)
plTxnReplaced->push_back(it->GetSharedTx());
} }
pool.RemoveStaged(allConflicting, false); pool.RemoveStaged(allConflicting, false);
@ -975,10 +977,11 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
} }
bool AcceptToMemoryPoolWithTime(CTxMemPool& pool, CValidationState &state, const CTransactionRef &tx, bool fLimitFree, bool AcceptToMemoryPoolWithTime(CTxMemPool& pool, CValidationState &state, const CTransactionRef &tx, bool fLimitFree,
bool* pfMissingInputs, int64_t nAcceptTime, bool fOverrideMempoolLimit, const CAmount nAbsurdFee) bool* pfMissingInputs, int64_t nAcceptTime, std::list<CTransactionRef>* plTxnReplaced,
bool fOverrideMempoolLimit, const CAmount nAbsurdFee)
{ {
std::vector<uint256> vHashTxToUncache; std::vector<uint256> vHashTxToUncache;
bool res = AcceptToMemoryPoolWorker(pool, state, tx, fLimitFree, pfMissingInputs, nAcceptTime, fOverrideMempoolLimit, nAbsurdFee, vHashTxToUncache); bool res = AcceptToMemoryPoolWorker(pool, state, tx, fLimitFree, pfMissingInputs, nAcceptTime, plTxnReplaced, fOverrideMempoolLimit, nAbsurdFee, vHashTxToUncache);
if (!res) { if (!res) {
BOOST_FOREACH(const uint256& hashTx, vHashTxToUncache) BOOST_FOREACH(const uint256& hashTx, vHashTxToUncache)
pcoinsTip->Uncache(hashTx); pcoinsTip->Uncache(hashTx);
@ -990,9 +993,10 @@ bool AcceptToMemoryPoolWithTime(CTxMemPool& pool, CValidationState &state, const
} }
bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransactionRef &tx, bool fLimitFree, bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransactionRef &tx, bool fLimitFree,
bool* pfMissingInputs, bool fOverrideMempoolLimit, const CAmount nAbsurdFee) bool* pfMissingInputs, std::list<CTransactionRef>* plTxnReplaced,
bool fOverrideMempoolLimit, const CAmount nAbsurdFee)
{ {
return AcceptToMemoryPoolWithTime(pool, state, tx, fLimitFree, pfMissingInputs, GetTime(), fOverrideMempoolLimit, nAbsurdFee); return AcceptToMemoryPoolWithTime(pool, state, tx, fLimitFree, pfMissingInputs, GetTime(), plTxnReplaced, fOverrideMempoolLimit, nAbsurdFee);
} }
/** Return transaction in txOut, and if it was found inside a block, its hash is placed in hashBlock */ /** Return transaction in txOut, and if it was found inside a block, its hash is placed in hashBlock */
@ -2138,7 +2142,7 @@ bool static DisconnectTip(CValidationState& state, const CChainParams& chainpara
const CTransaction& tx = *it; const CTransaction& tx = *it;
// ignore validation errors in resurrected transactions // ignore validation errors in resurrected transactions
CValidationState stateDummy; CValidationState stateDummy;
if (tx.IsCoinBase() || !AcceptToMemoryPool(mempool, stateDummy, it, false, NULL, true)) { if (tx.IsCoinBase() || !AcceptToMemoryPool(mempool, stateDummy, it, false, NULL, NULL, true)) {
mempool.removeRecursive(tx); mempool.removeRecursive(tx);
} else if (mempool.exists(tx.GetHash())) { } else if (mempool.exists(tx.GetHash())) {
vHashUpdate.push_back(tx.GetHash()); vHashUpdate.push_back(tx.GetHash());

9
src/validation.h

@ -304,13 +304,16 @@ void FlushStateToDisk();
/** Prune block files and flush state to disk. */ /** Prune block files and flush state to disk. */
void PruneAndFlush(); void PruneAndFlush();
/** (try to) add transaction to memory pool **/ /** (try to) add transaction to memory pool
* plTxnReplaced will be appended to with all transactions replaced from mempool **/
bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransactionRef &tx, bool fLimitFree, bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransactionRef &tx, bool fLimitFree,
bool* pfMissingInputs, bool fOverrideMempoolLimit=false, const CAmount nAbsurdFee=0); bool* pfMissingInputs, std::list<CTransactionRef>* plTxnReplaced = NULL,
bool fOverrideMempoolLimit=false, const CAmount nAbsurdFee=0);
/** (try to) add transaction to memory pool with a specified acceptance time **/ /** (try to) add transaction to memory pool with a specified acceptance time **/
bool AcceptToMemoryPoolWithTime(CTxMemPool& pool, CValidationState &state, const CTransactionRef &tx, bool fLimitFree, bool AcceptToMemoryPoolWithTime(CTxMemPool& pool, CValidationState &state, const CTransactionRef &tx, bool fLimitFree,
bool* pfMissingInputs, int64_t nAcceptTime, bool fOverrideMempoolLimit=false, const CAmount nAbsurdFee=0); bool* pfMissingInputs, int64_t nAcceptTime, std::list<CTransactionRef>* plTxnReplaced = NULL,
bool fOverrideMempoolLimit=false, const CAmount nAbsurdFee=0);
/** Convert CValidationState to a human-readable message for logging */ /** Convert CValidationState to a human-readable message for logging */
std::string FormatStateMessage(const CValidationState &state); std::string FormatStateMessage(const CValidationState &state);

2
src/wallet/wallet.cpp

@ -3847,5 +3847,5 @@ int CMerkleTx::GetBlocksToMaturity() const
bool CMerkleTx::AcceptToMemoryPool(const CAmount& nAbsurdFee, CValidationState& state) bool CMerkleTx::AcceptToMemoryPool(const CAmount& nAbsurdFee, CValidationState& state)
{ {
return ::AcceptToMemoryPool(mempool, state, tx, true, NULL, false, nAbsurdFee); return ::AcceptToMemoryPool(mempool, state, tx, true, NULL, NULL, false, nAbsurdFee);
} }

Loading…
Cancel
Save