Skip to content

Commit

Permalink
Add logic to reject long chains to CreateTransaction.
Browse files Browse the repository at this point in the history
  • Loading branch information
sproxet committed Nov 20, 2023
1 parent fad1302 commit 7a76600
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 1 deletion.
31 changes: 30 additions & 1 deletion src/wallet/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,22 @@ unsigned int CTransparentTxout::GetDepthInMainChain() const {
return wallet->mapWallet.at(GetHash()).GetDepthInMainChain();
}

unsigned int CTransparentTxout::GetDepthInMempool() const {
if (_isMockup)
return GetDepthInMainChain() ? 0 : 1;

assert(wallet);
AssertLockHeld(wallet->cs_wallet);
AssertLockHeld(mempool.cs);

auto entry = mempool.mapTx.find(GetHash());
if (entry == mempool.mapTx.end())
return 0;

uint64_t nAncestors = entry->GetCountWithAncestors();
return nAncestors;
}

const uint256 CMerkleTx::ABANDON_HASH(uint256S("0000000000000000000000000000000000000000000000000000000000000001"));

/** @defgroup mapWallet
Expand Down Expand Up @@ -4321,7 +4337,7 @@ void CWallet::CheckTransparentTransactionSanity(CMutableTransaction& tx,
throw std::runtime_error("txFee > maxTxFee. This is probably a bug.");

bool fHasDataOut = false;
for (CTxOut& txout: tx.vout) {
for (const CTxOut& txout: tx.vout) {
txnouttype whichType;

if (!::IsStandard(txout.scriptPubKey, whichType, false))
Expand Down Expand Up @@ -4357,6 +4373,18 @@ void CWallet::CheckTransparentTransactionSanity(CMutableTransaction& tx,
for (CTxOut& txout: tx.vout) totalOutputValue += txout.nValue;
assert(totalInputValue == totalOutputValue + nFee);
assert(totalInputValue > 0);

if (GetBoolArg("-walletrejectlongchains", DEFAULT_WALLET_REJECT_LONG_CHAINS)) {
// We should probably not make these transactions in the first place, but throwing this exception instead is the
// backwards compatible behaviour.
size_t nTotalMempoolAncestors = 0;

for (const CTransparentTxout& txin: vInputTxs)
nTotalMempoolAncestors += txin.GetDepthInMempool();

if (nTotalMempoolAncestors >= GetArg("-limitancestorcount", DEFAULT_ANCESTOR_LIMIT))
throw std::runtime_error("mempool chain");
}
}

// Create a transaction to vecSend, placing it in wtxNew. reservekey is the keypool. nFeeRet will be populated with the
Expand Down Expand Up @@ -4386,6 +4414,7 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CWalletT
CAmount& nFeeRet, int& nChangePosInOut, std::string& strFailReason,
const CCoinControl* coinControl, bool sign, int nExtraPayloadSize,
bool fUseInstantSend, const std::vector<CTransparentTxout>& vTransparentTxouts) {
LOCK(mempool.cs);
AssertLockHeld(cs_main);

if (!coinControl || coinControl->destChange.which() == 0)
Expand Down
7 changes: 7 additions & 0 deletions src/wallet/wallet.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "tinyformat.h"
#include "ui_interface.h"
#include "utilstrencodings.h"
#include "validation.h"
#include "validationinterface.h"
#include "script/ismine.h"
#include "script/sign.h"
Expand Down Expand Up @@ -668,6 +669,7 @@ class CTransparentTxout {
bool IsCoinBase() const;
bool IsFromMe() const;
unsigned int GetDepthInMainChain() const;
unsigned int GetDepthInMempool() const;

private:
const CWallet* wallet = nullptr;
Expand Down Expand Up @@ -736,6 +738,9 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface
if (coinControl && coinControl->nCoinType == CoinType::WITH_MINTS)
throw std::runtime_error("CoinType::WITH_MINTS is not supported for any transactions.");

unsigned int nMaxMempoolDepth = GetArg("-limitancestorcount", DEFAULT_ANCESTOR_LIMIT);
bool fRejectLongChains = GetBoolArg("-walletrejectlongchains", DEFAULT_WALLET_REJECT_LONG_CHAINS);

for (const AbstractTxout& tx: vRelevantTransactions) {
bool isSelected = coinControl && coinControl->HasSelected() && coinControl->IsSelected(tx.GetOutpoint());

Expand All @@ -754,6 +759,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface
(!fUseInstantSend || !tx.IsLLMQInstantSendLocked()) &&
((coinControl && !coinControl->fAllowUnconfirmed) || !tx.IsFromMe())
) continue;
if (fRejectLongChains && tx.GetDepthInMempool() + 1 >= nMaxMempoolDepth) continue;

if (isSelected) vCoinControlInputs.push_back(tx);
else vAvailableInputs.push_back(tx);
Expand Down Expand Up @@ -801,6 +807,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface
nCollectedRet = 0;

size_t nMaxSize = coinControl && coinControl->nMaxSize ? coinControl->nMaxSize : (MAX_STANDARD_TX_WEIGHT / 4);
size_t nMaxAncestors = GetArg("-limitancestorcount", DEFAULT_ANCESTOR_LIMIT);

if (nRequired < 0)
throw std::runtime_error("Transaction amounts must be positive");
Expand Down

0 comments on commit 7a76600

Please sign in to comment.