diff --git a/src/qt/forms/optionsdialog.ui b/src/qt/forms/optionsdialog.ui
index a7affffa67..b567badcce 100644
--- a/src/qt/forms/optionsdialog.ui
+++ b/src/qt/forms/optionsdialog.ui
@@ -189,6 +189,13 @@
+ -
+
+
+ Enable &splitting when minting
+
+
+
-
diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp
index 6017558d4f..c7fb7d3df6 100644
--- a/src/qt/optionsdialog.cpp
+++ b/src/qt/optionsdialog.cpp
@@ -188,6 +188,7 @@ void OptionsDialog::setMapper()
/* Lelantus */
mapper->addMapping(ui->autoAnonymize, OptionsModel::AutoAnonymize);
+ mapper->addMapping(ui->fSplit, OptionsModel::Split);
if (!lelantus::IsLelantusAllowed()) {
ui->lelantusPage->setVisible(false);
}
diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp
index 74d4ea6f03..8569b0cb81 100644
--- a/src/qt/optionsmodel.cpp
+++ b/src/qt/optionsmodel.cpp
@@ -85,6 +85,10 @@ void OptionsModel::Init(bool resetSettings)
settings.setValue("fAutoAnonymize", false);
fAutoAnonymize = settings.value("fAutoAnonymize", false).toBool();
+ if (!settings.contains("fSplit"))
+ settings.setValue("fSplit", true);
+ fSplit = settings.value("fSplit", true).toBool();
+
if (!settings.contains("fLelantusPage"))
settings.setValue("fLelantusPage", false);
fLelantusPage = settings.value("fLelantusPage", false).toBool();
@@ -279,6 +283,8 @@ QVariant OptionsModel::data(const QModelIndex & index, int role) const
return fCoinControlFeatures;
case AutoAnonymize:
return fAutoAnonymize;
+ case Split:
+ return fSplit;
case LelantusPage:
return fLelantusPage;
case DatabaseCache:
@@ -429,6 +435,10 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in
settings.setValue("fAutoAnonymize", fAutoAnonymize);
Q_EMIT autoAnonymizeChanged(fAutoAnonymize);
break;
+ case Split:
+ fSplit = value.toBool();
+ settings.setValue("fSplit", fSplit);
+ break;
case LelantusPage:
fLelantusPage = value.toBool();
settings.setValue("fLelantusPage", fLelantusPage);
diff --git a/src/qt/optionsmodel.h b/src/qt/optionsmodel.h
index 1ff155b86d..7d22dd2494 100644
--- a/src/qt/optionsmodel.h
+++ b/src/qt/optionsmodel.h
@@ -49,6 +49,7 @@ class OptionsModel : public QAbstractListModel
Listen, // bool
TorSetup, // bool
AutoAnonymize, // bool
+ Split, // bool
LelantusPage, // bool
enableRapAddresses, // bool
OptionIDRowCount,
@@ -73,6 +74,7 @@ class OptionsModel : public QAbstractListModel
bool getRapAddresses() { return fenableRapAddresses; }
const QString& getOverriddenByCommandLine() { return strOverriddenByCommandLine; }
bool getAutoAnonymize() { return fAutoAnonymize; }
+ bool getfSplit() { return fSplit; }
bool getLelantusPage() {return fLelantusPage; }
/* Restart flag helper */
@@ -89,6 +91,7 @@ class OptionsModel : public QAbstractListModel
QString strThirdPartyTxUrls;
bool fCoinControlFeatures;
bool fAutoAnonymize;
+ bool fSplit;
bool fLelantusPage;
bool fenableRapAddresses;
diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp
index c625cf4b77..470675f6ef 100644
--- a/src/qt/walletmodel.cpp
+++ b/src/qt/walletmodel.cpp
@@ -1407,7 +1407,7 @@ WalletModel::SendCoinsReturn WalletModel::prepareMintSparkTransaction(std::vecto
int nChangePosRet = -1;
std::string strFailReason;
- bool fCreated = wallet->CreateSparkMintTransactions(outputs, wtxAndFees, nFeeRequired, reservekeys, nChangePosRet, fSubtractFeeFromAmount, strFailReason, coinControl, false);
+ bool fCreated = wallet->CreateSparkMintTransactions(outputs, wtxAndFees, nFeeRequired, reservekeys, nChangePosRet, fSubtractFeeFromAmount, strFailReason, optionsModel->getfSplit(), coinControl, false);
transactions.clear();
transactions.reserve(wtxAndFees.size());
for (auto &wtxAndFee : wtxAndFees) {
diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp
index 9fdf6e2eb3..3c2100b2c1 100644
--- a/src/rpc/client.cpp
+++ b/src/rpc/client.cpp
@@ -199,6 +199,8 @@ static const CRPCConvertParam vRPCConvertParams[] =
//Lelantus
{ "mintspark", 0 },
+ { "mintspark", 1 },
+ { "mintspark", 2 },
{ "spendspark", 0 },
{ "spendspark", 1 },
diff --git a/src/spark/sparkwallet.cpp b/src/spark/sparkwallet.cpp
index ed296578fd..325868f189 100644
--- a/src/spark/sparkwallet.cpp
+++ b/src/spark/sparkwallet.cpp
@@ -762,6 +762,7 @@ bool CSparkWallet::CreateSparkMintTransactions(
int& nChangePosInOut,
bool subtractFeeFromAmount,
std::string& strFailReason,
+ bool fSplit,
const CCoinControl *coinControl,
bool autoMintAll)
{
@@ -790,10 +791,17 @@ bool CSparkWallet::CreateSparkMintTransactions(
std::list cacheWtxs;
// vector pairs for each transparent address
std::vector>> valueAndUTXO;
- pwalletMain->AvailableCoinsForLMint(valueAndUTXO, coinControl);
-
- Shuffle(valueAndUTXO.begin(), valueAndUTXO.end(), FastRandomContext());
-
+ if (fSplit) {
+ pwalletMain->AvailableCoinsForLMint(valueAndUTXO, coinControl);
+ Shuffle(valueAndUTXO.begin(), valueAndUTXO.end(), FastRandomContext());
+ } else {
+ std::vector vAvailableCoins;
+ pwalletMain->AvailableCoins(vAvailableCoins, true, coinControl);
+ CAmount balance = 0;
+ for (auto& coin : vAvailableCoins)
+ balance += coin.tx->tx->vout[coin.i].nValue;
+ valueAndUTXO.emplace_back(std::make_pair(balance, vAvailableCoins));
+ }
while (!valueAndUTXO.empty()) {
// initialize
diff --git a/src/spark/sparkwallet.h b/src/spark/sparkwallet.h
index 8f707a5f94..a300f904a3 100644
--- a/src/spark/sparkwallet.h
+++ b/src/spark/sparkwallet.h
@@ -122,6 +122,7 @@ class CSparkWallet {
int& nChangePosInOut,
bool subtractFeeFromAmount,
std::string& strFailReason,
+ bool fSplit,
const CCoinControl *coinControl,
bool autoMintAll = false);
diff --git a/src/test/evospork_tests.cpp b/src/test/evospork_tests.cpp
index fb01ac97bc..e2c71c0053 100644
--- a/src/test/evospork_tests.cpp
+++ b/src/test/evospork_tests.cpp
@@ -604,7 +604,7 @@ BOOST_AUTO_TEST_CASE(limit)
for (int i=0; i<10; i++) {
std::vector> wtxAndFee;
std::vector mints{{address, 50*COIN, ""}};
- std::string error = pwalletMain->MintAndStoreSpark(mints, wtxAndFee, false);
+ std::string error = pwalletMain->MintAndStoreSpark(mints, wtxAndFee, false, true);
BOOST_ASSERT(error.empty());
for (auto &w: wtxAndFee)
sparkMints.emplace_back(*w.first.tx);
diff --git a/src/test/fixtures.cpp b/src/test/fixtures.cpp
index 65b9297a43..50f4d30a75 100644
--- a/src/test/fixtures.cpp
+++ b/src/test/fixtures.cpp
@@ -369,7 +369,7 @@ std::vector SparkTestingSetup::GenerateMints(
data.address = address;
outputs.push_back(data);
- auto result = pwalletMain->MintAndStoreSpark(outputs, wtxAndFee, false);
+ auto result = pwalletMain->MintAndStoreSpark(outputs, wtxAndFee, false, true);
if (result != "") {
throw std::runtime_error(_("Fail to generate mints, ") + result);
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index 9ed20ecbd8..a171740f08 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -31,6 +31,7 @@
#include "lelantusjoinsplitbuilder.h"
#include "bip47/paymentchannel.h"
#include "bip47/account.h"
+#include "wallet/coincontrol.h"
#include
@@ -3653,7 +3654,7 @@ UniValue mintspark(const JSONRPCRequest& request)
return NullUniValue;
}
- if (request.fHelp || request.params.size() == 0 || request.params.size() > 2)
+ if (request.fHelp || request.params.size() == 0 || request.params.size() > 3)
throw std::runtime_error(
"mintspark {\"address\":{amount,memo...}}\n"
+ HelpRequiringPassphrase(pwallet) + "\n"
@@ -3669,6 +3670,8 @@ UniValue mintspark(const JSONRPCRequest& request)
"\nExamples:\n"
"\nSend two amounts to two different spark addresses:\n"
+ HelpExampleCli("mintspark", "\"{\\\"sr1xtw3yd6v4ghgz873exv2r5nzfwryufxjzzz4xr48gl4jmh7fxml4568xr0nsdd7s4l5as2h50gakzjqrqpm7yrecne8ut8ylxzygj8klttsgm37tna4jk06acl2azph0dq4yxdqqgwa60\\\":{\\\"amount\\\":0.01, \\\"memo\\\":\\\"test_memo\\\"},\\\"sr1x7gcqdy670l2v4p9h2m4n5zgzde9y6ht86egffa0qrq40c6z329yfgvu8vyf99tgvnq4hwshvfxxhfzuyvz8dr3lt32j70x8l34japg73ca4w6z9x7c7ryd2gnafg9eg3gpr90gtunraw\\\":{\\\"amount\\\":0.01, \\\"memo\\\":\\\"\\\"}}\"") +
+ "\nSend two amounts to two different spark addresses, setting subtractFeeFromAmount flag and giving fromAddress array:\n"
+ + HelpExampleCli("mintspark", "\"{\\\"sr1xtw3yd6v4ghgz873exv2r5nzfwryufxjzzz4xr48gl4jmh7fxml4568xr0nsdd7s4l5as2h50gakzjqrqpm7yrecne8ut8ylxzygj8klttsgm37tna4jk06acl2azph0dq4yxdqqgwa60\\\":{\\\"amount\\\":0.01, \\\"memo\\\":\\\"test_memo\\\"},\\\"sr1x7gcqdy670l2v4p9h2m4n5zgzde9y6ht86egffa0qrq40c6z329yfgvu8vyf99tgvnq4hwshvfxxhfzuyvz8dr3lt32j70x8l34japg73ca4w6z9x7c7ryd2gnafg9eg3gpr90gtunraw\\\":{\\\"amount\\\":0.01, \\\"memo\\\":\\\"\\\"}}\" true [\\\"THhFWpJTDNyo6vL75kpob7UWVfwwp8t6kD\\\"]") +
"\nSend two amounts to two different spark addresses setting memo:\n"
+ HelpExampleRpc("mintspark", "\"{\"sr1xtw3yd6v4ghgz873exv2r5nzfwryufxjzzz4xr48gl4jmh7fxml4568xr0nsdd7s4l5as2h50gakzjqrqpm7yrecne8ut8ylxzygj8klttsgm37tna4jk06acl2azph0dq4yxdqqgwa60\":{\"amount\":1},\\\"sr1x7gcqdy670l2v4p9h2m4n5zgzde9y6ht86egffa0qrq40c6z329yfgvu8vyf99tgvnq4hwshvfxxhfzuyvz8dr3lt32j70x8l34japg73ca4w6z9x7c7ryd2gnafg9eg3gpr90gtunraw\":{\"amount\":0.01, \"memo\":\"test_memo2\"}}\"")
);
@@ -3725,8 +3728,31 @@ UniValue mintspark(const JSONRPCRequest& request)
bool subtractFeeFromAmount = false;
if (request.params.size() > 1)
subtractFeeFromAmount = request.params[1].get_bool();
+
+ CCoinControl coinControl;
+ if (request.params.size() > 2) {
+ UniValue sendFrom = request.params[2].get_array();
+ std::vector vAvailableCoins;
+ pwalletMain->AvailableCoins(vAvailableCoins, true);
+ for (unsigned int idx = 0; idx < sendFrom.size(); idx++)
+ {
+ std::string name_ =sendFrom[idx].get_str();
+ CBitcoinAddress address(name_);
+ if (!address.IsValid())
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Firo address: ") + name_);
+ CScript scriptPubKey = GetScriptForDestination(address.Get());
+ for (const auto& itr : vAvailableCoins) {
+ if (itr.tx->tx->vout[itr.i].scriptPubKey != scriptPubKey) {
+ continue;
+ }
+ coinControl.Select(COutPoint(itr.tx->GetHash(), itr.i));
+ }
+ }
+
+ }
+
std::vector> wtxAndFee;
- std::string strError = pwallet->MintAndStoreSpark(outputs, wtxAndFee, subtractFeeFromAmount);
+ std::string strError = pwallet->MintAndStoreSpark(outputs, wtxAndFee, subtractFeeFromAmount, false, false, false, &coinControl);
if (strError != "")
throw JSONRPCError(RPC_WALLET_ERROR, strError);
@@ -3761,7 +3787,7 @@ UniValue automintspark(const JSONRPCRequest& request) {
std::vector> wtxAndFee;
std::vector outputs;
- std::string strError = pwallet->MintAndStoreSpark(outputs, wtxAndFee, true, true);
+ std::string strError = pwallet->MintAndStoreSpark(outputs, wtxAndFee, true, true, true);
if (strError != "")
throw JSONRPCError(RPC_WALLET_ERROR, strError);
@@ -5775,7 +5801,7 @@ static const CRPCCommand commands[] =
{ "wallet", "getsparkaddressbalance", &getsparkaddressbalance, false },
{ "wallet", "resetsparkmints", &resetsparkmints, false },
{ "wallet", "setsparkmintstatus", &setsparkmintstatus, false },
- { "wallet", "mintspark", &mintspark, false },
+ { "wallet", "mintspark", &mintspark, true },
{ "wallet", "automintspark", &automintspark, false },
{ "wallet", "spendspark", &spendspark, false },
{ "wallet", "lelantustospark", &lelantustospark, false },
diff --git a/src/wallet/test/spark_tests.cpp b/src/wallet/test/spark_tests.cpp
index 7ed925fb2d..1d05c9e9df 100644
--- a/src/wallet/test/spark_tests.cpp
+++ b/src/wallet/test/spark_tests.cpp
@@ -76,7 +76,7 @@ BOOST_AUTO_TEST_CASE(mint_and_store_spark)
std::vector mintedCoins;
mintedCoins.push_back(data);
- std::string result = pwalletMain->MintAndStoreSpark(mintedCoins, wtxAndFee, false);
+ std::string result = pwalletMain->MintAndStoreSpark(mintedCoins, wtxAndFee, false, true);
BOOST_CHECK_EQUAL(result, "");
size_t mintAmount = 0;
@@ -119,7 +119,7 @@ BOOST_AUTO_TEST_CASE(mint_subtract_fee)
std::vector mintedCoins;
mintedCoins.push_back(data);
- std::string result = pwalletMain->MintAndStoreSpark(mintedCoins, wtxAndFee, true);
+ std::string result = pwalletMain->MintAndStoreSpark(mintedCoins, wtxAndFee, true, true);
BOOST_CHECK_EQUAL(result, "");
size_t mintAmount = 0;
@@ -207,10 +207,10 @@ BOOST_AUTO_TEST_CASE(spend)
mintedCoins.push_back(data);
std::vector> wtxAndFee;
- std::string result = pwalletMain->MintAndStoreSpark(mintedCoins, wtxAndFee, false);
+ std::string result = pwalletMain->MintAndStoreSpark(mintedCoins, wtxAndFee, false, true);
std::vector> wtxAndFee2;
- pwalletMain->MintAndStoreSpark(mintedCoins, wtxAndFee2, false);
+ pwalletMain->MintAndStoreSpark(mintedCoins, wtxAndFee2, false, true);
BOOST_CHECK_EQUAL("", result);
@@ -308,7 +308,7 @@ BOOST_AUTO_TEST_CASE(mintspark_and_mint_all)
std::vector mintedCoins;
mintedCoins.push_back(data);
- auto result = pwalletMain->MintAndStoreSpark(mintedCoins, wtxAndFee, false);
+ auto result = pwalletMain->MintAndStoreSpark(mintedCoins, wtxAndFee, false, true);
BOOST_CHECK_EQUAL("", result);
BOOST_CHECK_EQUAL(1, wtxAndFee.size());
BOOST_CHECK_EQUAL(10 * COIN, countMintsInBalance(wtxAndFee));
@@ -319,7 +319,7 @@ BOOST_AUTO_TEST_CASE(mintspark_and_mint_all)
mintedCoins.clear();
mintedCoins.push_back(data);
- result = pwalletMain->MintAndStoreSpark(mintedCoins, wtxAndFee, false);
+ result = pwalletMain->MintAndStoreSpark(mintedCoins, wtxAndFee, false, true);
BOOST_CHECK_EQUAL("", result);
BOOST_CHECK_GT(wtxAndFee.size(), 1);
BOOST_CHECK_EQUAL(600 * COIN, countMintsInBalance(wtxAndFee));
@@ -330,7 +330,7 @@ BOOST_AUTO_TEST_CASE(mintspark_and_mint_all)
auto balance = getAvailableCoinsForMintBalance();
BOOST_CHECK_GT(balance, 0);
- result = pwalletMain->MintAndStoreSpark({}, wtxAndFee, false, true);
+ result = pwalletMain->MintAndStoreSpark({}, wtxAndFee, false, true, true);
BOOST_CHECK_EQUAL("", result);
BOOST_CHECK_GT(balance, countMintsInBalance(wtxAndFee));
BOOST_CHECK_EQUAL(balance, countMintsInBalance(wtxAndFee, true));
@@ -344,7 +344,7 @@ BOOST_AUTO_TEST_CASE(mintspark_and_mint_all)
balance = getAvailableCoinsForMintBalance();
BOOST_CHECK_GT(balance, 0);
- result = pwalletMain->MintAndStoreSpark({ }, wtxAndFee, false, true);
+ result = pwalletMain->MintAndStoreSpark({ }, wtxAndFee, false, true, true);
BOOST_CHECK_EQUAL("", result);
BOOST_CHECK_GT(balance, countMintsInBalance(wtxAndFee));
BOOST_CHECK_EQUAL(balance, countMintsInBalance(wtxAndFee, true));
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index ab14516dfe..0b8a0e7603 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -5661,6 +5661,7 @@ std::string CWallet::MintAndStoreSpark(
const std::vector& outputs,
std::vector>& wtxAndFee,
bool subtractFeeFromAmount,
+ bool fSplit,
bool autoMintAll,
bool fAskFee,
const CCoinControl *coinControl) {
@@ -5687,7 +5688,7 @@ std::string CWallet::MintAndStoreSpark(
int nChangePosRet = -1;
std::list reservekeys;
- if (!sparkWallet->CreateSparkMintTransactions(outputs, wtxAndFee, nFeeRequired, reservekeys, nChangePosRet, subtractFeeFromAmount, strError, coinControl, autoMintAll)) {
+ if (!sparkWallet->CreateSparkMintTransactions(outputs, wtxAndFee, nFeeRequired, reservekeys, nChangePosRet, subtractFeeFromAmount, strError, fSplit, coinControl, autoMintAll)) {
return strError;
}
@@ -8224,10 +8225,11 @@ bool CWallet::CreateSparkMintTransactions(
int& nChangePosInOut,
bool subtractFeeFromAmount,
std::string& strFailReason,
+ bool fSplit,
const CCoinControl *coinControl,
bool autoMintAll)
{
- return sparkWallet->CreateSparkMintTransactions(outputs, wtxAndFee, nAllFeeRet, reservekeys, nChangePosInOut, subtractFeeFromAmount, strFailReason, coinControl, autoMintAll);
+ return sparkWallet->CreateSparkMintTransactions(outputs, wtxAndFee, nAllFeeRet, reservekeys, nChangePosInOut, subtractFeeFromAmount, strFailReason, fSplit, coinControl, autoMintAll);
}
std::pair CWallet::GetSparkBalance()
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index f1f1d0c6a9..8ac437eb26 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -1047,6 +1047,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface
int& nChangePosInOut,
bool subtractFeeFromAmount,
std::string& strFailReason,
+ bool fSplit,
const CCoinControl *coinControl,
bool autoMintAll = false);
@@ -1093,6 +1094,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface
const std::vector& outputs,
std::vector>& wtxAndFee,
bool subtractFeeFromAmount,
+ bool fSplit,
bool autoMintAll = false,
bool fAskFee = false,
const CCoinControl *coinControl = NULL);