Skip to content

Commit

Permalink
Create multiple transactions with one command.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Zannick committed Mar 13, 2022
1 parent 5230e52 commit a216c18
Show file tree
Hide file tree
Showing 7 changed files with 427 additions and 139 deletions.
4 changes: 2 additions & 2 deletions src/interfaces/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -502,12 +502,12 @@ class WalletImpl : public Wallet
break;
}
case OUTPUT_CT:
if (0 != pwalletAnon->AddBlindedInputs(wtx, rtx, recipients, !fCheckFeeOnly, nFeeRet, &coin_control, fail_reason))
if (0 != pwalletAnon->AddBlindedInputs(wtx, rtx, recipients, !fCheckFeeOnly, 0, nFeeRet, &coin_control, fail_reason))
fFailed = true;
break;
case OUTPUT_RINGCT:
if (!pwalletAnon->AddAnonInputs(wtx, rtx, recipients, !fCheckFeeOnly, nRingSize,
nInputsPerSig, nFeeRet, &coin_control, fail_reason))
nInputsPerSig, 0, nFeeRet, &coin_control, fail_reason))
fFailed = true;
break;
default:
Expand Down
277 changes: 241 additions & 36 deletions src/veil/ringct/anonwallet.cpp

Large diffs are not rendered by default.

20 changes: 14 additions & 6 deletions src/veil/ringct/anonwallet.h
Original file line number Diff line number Diff line change
Expand Up @@ -227,9 +227,9 @@ class AnonWallet
CAmount &nFeeRet, const CCoinControl *coinControl, std::string &sError, bool fZerocoinInputs, CAmount nInputValue);

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


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

bool IsMyAnonInput(const CTxIn& txin, COutPoint& myOutpoint);
bool AddAnonInputs_Inner(CWalletTx &wtx, CTransactionRecord &rtx, std::vector<CTempRecipient> &vecSend,
bool sign, size_t nRingSize, size_t nInputsPerSig, CAmount &nFeeRet,
bool sign, size_t nRingSize, size_t nInputsPerSig, size_t nMaximumInputs, CAmount &nFeeRet,
const CCoinControl *coinControl, std::string &sError, bool fZerocoinInputs, CAmount nInputValue);
bool AddAnonInputs(CWalletTx &wtx, CTransactionRecord &rtx, std::vector<CTempRecipient> &vecSend,
bool sign, size_t nRingSize, size_t nInputsPerSig, CAmount &nFeeRet,
bool sign, size_t nRingSize, size_t nInputsPerSig, size_t nMaximumInputs, CAmount &nFeeRet,
const CCoinControl *coinControl, std::string &sError, bool fZerocoinInputs = false,
CAmount nInputValue = 0);

Expand Down Expand Up @@ -322,15 +322,23 @@ class AnonWallet
* populate vCoins with vector of available COutputs.
*/
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;
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;
/**
* Returns a list of coins for a single transaction based on the target value and allowed number of inputs.
*/
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;

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;

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

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;
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;
/**
* Like SelectCoinsMinConf, but always selects at most nMaximumCount coins,
* with the intention of being put in a single tx that partially accomplishes the target to be sent.
*/
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;

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

Expand Down
Loading

0 comments on commit a216c18

Please sign in to comment.