Skip to content

Commit a872b41

Browse files
committed
Create multiple transactions with one command.
RPC send commands have a new argument now that controls whether the amount specified can be split across multiple transactions. It defaults to single-transaction mode for now. SelectCoinsForOneTx: use a sliding window algorithm to pick inputs. This will pick one small input if possible, so that if change is produced it does not result in an ever-growing pile of tiny utxos.
1 parent 5230e52 commit a872b41

File tree

7 files changed

+427
-139
lines changed

7 files changed

+427
-139
lines changed

src/interfaces/wallet.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -502,12 +502,12 @@ class WalletImpl : public Wallet
502502
break;
503503
}
504504
case OUTPUT_CT:
505-
if (0 != pwalletAnon->AddBlindedInputs(wtx, rtx, recipients, !fCheckFeeOnly, nFeeRet, &coin_control, fail_reason))
505+
if (0 != pwalletAnon->AddBlindedInputs(wtx, rtx, recipients, !fCheckFeeOnly, 0, nFeeRet, &coin_control, fail_reason))
506506
fFailed = true;
507507
break;
508508
case OUTPUT_RINGCT:
509509
if (!pwalletAnon->AddAnonInputs(wtx, rtx, recipients, !fCheckFeeOnly, nRingSize,
510-
nInputsPerSig, nFeeRet, &coin_control, fail_reason))
510+
nInputsPerSig, 0, nFeeRet, &coin_control, fail_reason))
511511
fFailed = true;
512512
break;
513513
default:

src/veil/ringct/anonwallet.cpp

+241-36
Large diffs are not rendered by default.

src/veil/ringct/anonwallet.h

+14-6
Original file line numberDiff line numberDiff line change
@@ -227,9 +227,9 @@ class AnonWallet
227227
CAmount &nFeeRet, const CCoinControl *coinControl, std::string &sError, bool fZerocoinInputs, CAmount nInputValue);
228228

229229
int AddBlindedInputs(CWalletTx &wtx, CTransactionRecord &rtx, std::vector<CTempRecipient> &vecSend, bool sign,
230-
CAmount &nFeeRet, const CCoinControl *coinControl, std::string &sError);
230+
size_t nMaximumInputs, CAmount &nFeeRet, const CCoinControl *coinControl, std::string &sError);
231231
int AddBlindedInputs_Inner(CWalletTx &wtx, CTransactionRecord &rtx, std::vector<CTempRecipient> &vecSend, bool sign,
232-
CAmount &nFeeRet, const CCoinControl *coinControl, std::string &sError);
232+
size_t nMaximumInputs, CAmount &nFeeRet, const CCoinControl *coinControl, std::string &sError);
233233

234234

235235
bool PlaceRealOutputs(std::vector<std::vector<int64_t> > &vMI, size_t &nSecretColumn, size_t nRingSize, std::set<int64_t> &setHave,
@@ -240,10 +240,10 @@ class AnonWallet
240240

241241
bool IsMyAnonInput(const CTxIn& txin, COutPoint& myOutpoint);
242242
bool AddAnonInputs_Inner(CWalletTx &wtx, CTransactionRecord &rtx, std::vector<CTempRecipient> &vecSend,
243-
bool sign, size_t nRingSize, size_t nInputsPerSig, CAmount &nFeeRet,
243+
bool sign, size_t nRingSize, size_t nInputsPerSig, size_t nMaximumInputs, CAmount &nFeeRet,
244244
const CCoinControl *coinControl, std::string &sError, bool fZerocoinInputs, CAmount nInputValue);
245245
bool AddAnonInputs(CWalletTx &wtx, CTransactionRecord &rtx, std::vector<CTempRecipient> &vecSend,
246-
bool sign, size_t nRingSize, size_t nInputsPerSig, CAmount &nFeeRet,
246+
bool sign, size_t nRingSize, size_t nInputsPerSig, size_t nMaximumInputs, CAmount &nFeeRet,
247247
const CCoinControl *coinControl, std::string &sError, bool fZerocoinInputs = false,
248248
CAmount nInputValue = 0);
249249

@@ -322,15 +322,23 @@ class AnonWallet
322322
* populate vCoins with vector of available COutputs.
323323
*/
324324
void AvailableBlindedCoins(std::vector<COutputR>& vCoins, bool fOnlySafe=true, const CCoinControl *coinControl = nullptr, const CAmount& nMinimumAmount = 1, const CAmount& nMaximumAmount = MAX_MONEY, const CAmount& nMinimumSumAmount = MAX_MONEY, const uint64_t& nMaximumCount = 0, const int& nMinDepth = 0, const int& nMaxDepth = 0x7FFFFFFF, bool fIncludeImmature=false) const;
325-
bool SelectBlindedCoins(const std::vector<COutputR>& vAvailableCoins, const CAmount& nTargetValue, std::vector<std::pair<MapRecords_t::const_iterator,unsigned int> > &setCoinsRet, CAmount &nValueRet, const CCoinControl *coinControl = nullptr) const;
325+
/**
326+
* Returns a list of coins for a single transaction based on the target value and allowed number of inputs.
327+
*/
328+
bool SelectBlindedCoins(const std::vector<COutputR>& vAvailableCoins, const CAmount& nTargetValue, size_t nMaximumCount, std::vector<std::pair<MapRecords_t::const_iterator,unsigned int> > &setCoinsRet, CAmount &nValueRet, const CCoinControl *coinControl = nullptr) const;
326329

327330
void AvailableAnonCoins(std::vector<COutputR> &vCoins, bool fOnlySafe=true, const CCoinControl *coinControl = nullptr, const CAmount& nMinimumAmount = 1, const CAmount& nMaximumAmount = MAX_MONEY, const CAmount& nMinimumSumAmount = MAX_MONEY, const uint64_t& nMaximumCount = 0, const int& nMinDepth = 0, const int& nMaxDepth = 0x7FFFFFFF, bool fIncludeImmature=false) const;
328331

329332
/**
330333
* Return list of available coins and locked coins grouped by non-change output address.
331334
*/
332335

333-
bool SelectCoinsMinConf(const CAmount& nTargetValue, const CoinEligibilityFilter& eligibility_filter, std::vector<COutputR> vCoins, std::vector<std::pair<MapRecords_t::const_iterator,unsigned int> > &setCoinsRet, CAmount &nValueRet) const;
336+
bool SelectCoinsMinConf(const CAmount& nTargetValue, const CoinEligibilityFilter& eligibility_filter, std::vector<COutputR> &vCoins, std::vector<std::pair<MapRecords_t::const_iterator,unsigned int> > &setCoinsRet, CAmount &nValueRet) const;
337+
/**
338+
* Like SelectCoinsMinConf, but always selects at most nMaximumCount coins,
339+
* with the intention of being put in a single tx that partially accomplishes the target to be sent.
340+
*/
341+
bool SelectCoinsForOneTx(const CAmount& nTargetValue, const CoinEligibilityFilter& eligibility_filter, std::vector<COutputR> &vCoins, size_t nMaximumCount, std::vector<std::pair<MapRecords_t::const_iterator,unsigned int> > &setCoinsRet, CAmount &nValueRet) const;
334342

335343
bool IsSpent(const uint256& hash, unsigned int n) const EXCLUSIVE_LOCKS_REQUIRED(cs_main);
336344

0 commit comments

Comments
 (0)