From c74f2cd8b24c7e9c3d3aa2cea401d3d259b95524 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Fri, 23 Aug 2019 21:02:33 +0300 Subject: [PATCH] Fix SelectCoinsMinConf to allow instant respends (#3061) * Modify tests to check for instant respends This should fail atm... * Fix SelectCoinsMinConf to allow instant respends Now tests should pass again. --- qa/rpc-tests/p2p-instantsend.py | 6 ++++++ src/wallet/wallet.cpp | 8 ++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/qa/rpc-tests/p2p-instantsend.py b/qa/rpc-tests/p2p-instantsend.py index 03a078d094..88f9bd0b02 100755 --- a/qa/rpc-tests/p2p-instantsend.py +++ b/qa/rpc-tests/p2p-instantsend.py @@ -78,6 +78,9 @@ class InstantSendTest(DashTestFramework): assert (res['hash'] != wrong_block) # wait for long time only for first node timeout = 1 + # send coins back to the controller node without waiting for confirmations + receiver.sendtoaddress(self.nodes[0].getnewaddress(), 0.9, "", "", True) + assert_equal(receiver.getwalletinfo()["balance"], 0) # mine more blocks # TODO: mine these blocks on an isolated node set_mocktime(get_mocktime() + 1) @@ -116,6 +119,9 @@ class InstantSendTest(DashTestFramework): for node in self.nodes: self.wait_for_instantlock(is_id, node) assert_raises_jsonrpc(-5, "No such mempool or blockchain transaction", isolated.getrawtransaction, dblspnd_txid) + # send coins back to the controller node without waiting for confirmations + receiver.sendtoaddress(self.nodes[0].getnewaddress(), 0.9, "", "", True) + assert_equal(receiver.getwalletinfo()["balance"], 0) if __name__ == '__main__': InstantSendTest().main() diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 4fdd185d93..89de54e5aa 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2677,6 +2677,8 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, const int nConfMin std::sort(vCoins.begin(), vCoins.end(), less_then_denom); } + int nMaxChainLength = std::min(gArgs.GetArg("-limitancestorcount", DEFAULT_ANCESTOR_LIMIT), gArgs.GetArg("-limitdescendantcount", DEFAULT_DESCENDANT_LIMIT)); + // try to find nondenom first to prevent unneeded spending of mixed coins for (unsigned int tryDenom = tryDenomStart; tryDenom < 2; tryDenom++) { @@ -2690,11 +2692,13 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, const int nConfMin const CWalletTx *pcoin = output.tx; + bool fLockedByIS = pcoin->IsLockedByInstantSend(); + // if (fDebug) LogPrint("selectcoins", "value %s confirms %d\n", FormatMoney(pcoin->vout[output.i].nValue), output.nDepth); - if (output.nDepth < (pcoin->IsFromMe(ISMINE_ALL) ? nConfMine : nConfTheirs)) + if (output.nDepth < (pcoin->IsFromMe(ISMINE_ALL) ? nConfMine : nConfTheirs) && !fLockedByIS) continue; - if (!mempool.TransactionWithinChainLimit(pcoin->GetHash(), nMaxAncestors)) + if (!mempool.TransactionWithinChainLimit(pcoin->GetHash(), fLockedByIS ? nMaxChainLength : nMaxAncestors)) continue; int i = output.i;