Skip to content

Commit

Permalink
Mint refactor (#1515)
Browse files Browse the repository at this point in the history
* Don't split when minting in firod, add option in QT not to split

* Implemented sendFrom for mintSpark rpc

* Fixing typos
  • Loading branch information
levonpetrosyan93 authored Feb 18, 2025
1 parent 987f067 commit 14ed437
Show file tree
Hide file tree
Showing 14 changed files with 83 additions and 21 deletions.
7 changes: 7 additions & 0 deletions src/qt/forms/optionsdialog.ui
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,13 @@
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="fSplit">
<property name="text">
<string>Enable &amp;splitting when minting</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="lelantusPage">
<property name="text">
Expand Down
1 change: 1 addition & 0 deletions src/qt/optionsdialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
10 changes: 10 additions & 0 deletions src/qt/optionsmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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);
Expand Down
3 changes: 3 additions & 0 deletions src/qt/optionsmodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ class OptionsModel : public QAbstractListModel
Listen, // bool
TorSetup, // bool
AutoAnonymize, // bool
Split, // bool
LelantusPage, // bool
enableRapAddresses, // bool
OptionIDRowCount,
Expand All @@ -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 */
Expand All @@ -89,6 +91,7 @@ class OptionsModel : public QAbstractListModel
QString strThirdPartyTxUrls;
bool fCoinControlFeatures;
bool fAutoAnonymize;
bool fSplit;
bool fLelantusPage;
bool fenableRapAddresses;

Expand Down
2 changes: 1 addition & 1 deletion src/qt/walletmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
2 changes: 2 additions & 0 deletions src/rpc/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,8 @@ static const CRPCConvertParam vRPCConvertParams[] =

//Lelantus
{ "mintspark", 0 },
{ "mintspark", 1 },
{ "mintspark", 2 },
{ "spendspark", 0 },
{ "spendspark", 1 },

Expand Down
16 changes: 12 additions & 4 deletions src/spark/sparkwallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -762,6 +762,7 @@ bool CSparkWallet::CreateSparkMintTransactions(
int& nChangePosInOut,
bool subtractFeeFromAmount,
std::string& strFailReason,
bool fSplit,
const CCoinControl *coinControl,
bool autoMintAll)
{
Expand Down Expand Up @@ -790,10 +791,17 @@ bool CSparkWallet::CreateSparkMintTransactions(
std::list<CWalletTx> cacheWtxs;
// vector pairs<available amount, outputs> for each transparent address
std::vector<std::pair<CAmount, std::vector<COutput>>> 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<COutput> 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
Expand Down
1 change: 1 addition & 0 deletions src/spark/sparkwallet.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ class CSparkWallet {
int& nChangePosInOut,
bool subtractFeeFromAmount,
std::string& strFailReason,
bool fSplit,
const CCoinControl *coinControl,
bool autoMintAll = false);

Expand Down
2 changes: 1 addition & 1 deletion src/test/evospork_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -604,7 +604,7 @@ BOOST_AUTO_TEST_CASE(limit)
for (int i=0; i<10; i++) {
std::vector<std::pair<CWalletTx, CAmount>> wtxAndFee;
std::vector<spark::MintedCoinData> 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);
Expand Down
2 changes: 1 addition & 1 deletion src/test/fixtures.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@ std::vector<CSparkMintMeta> 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);
Expand Down
34 changes: 30 additions & 4 deletions src/wallet/rpcwallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "lelantusjoinsplitbuilder.h"
#include "bip47/paymentchannel.h"
#include "bip47/account.h"
#include "wallet/coincontrol.h"

#include <stdint.h>

Expand Down Expand Up @@ -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"
Expand All @@ -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\"}}\"")
);
Expand Down Expand Up @@ -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<COutput> 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<std::pair<CWalletTx, CAmount>> 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);

Expand Down Expand Up @@ -3761,7 +3787,7 @@ UniValue automintspark(const JSONRPCRequest& request) {

std::vector<std::pair<CWalletTx, CAmount>> wtxAndFee;
std::vector<spark::MintedCoinData> 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);
Expand Down Expand Up @@ -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 },
Expand Down
16 changes: 8 additions & 8 deletions src/wallet/test/spark_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ BOOST_AUTO_TEST_CASE(mint_and_store_spark)
std::vector<spark::MintedCoinData> 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;
Expand Down Expand Up @@ -119,7 +119,7 @@ BOOST_AUTO_TEST_CASE(mint_subtract_fee)
std::vector<spark::MintedCoinData> 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;
Expand Down Expand Up @@ -207,10 +207,10 @@ BOOST_AUTO_TEST_CASE(spend)
mintedCoins.push_back(data);

std::vector<std::pair<CWalletTx, CAmount>> wtxAndFee;
std::string result = pwalletMain->MintAndStoreSpark(mintedCoins, wtxAndFee, false);
std::string result = pwalletMain->MintAndStoreSpark(mintedCoins, wtxAndFee, false, true);

std::vector<std::pair<CWalletTx, CAmount>> wtxAndFee2;
pwalletMain->MintAndStoreSpark(mintedCoins, wtxAndFee2, false);
pwalletMain->MintAndStoreSpark(mintedCoins, wtxAndFee2, false, true);

BOOST_CHECK_EQUAL("", result);

Expand Down Expand Up @@ -308,7 +308,7 @@ BOOST_AUTO_TEST_CASE(mintspark_and_mint_all)
std::vector<spark::MintedCoinData> 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));
Expand All @@ -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));
Expand All @@ -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));
Expand All @@ -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));
Expand Down
6 changes: 4 additions & 2 deletions src/wallet/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5661,6 +5661,7 @@ std::string CWallet::MintAndStoreSpark(
const std::vector<spark::MintedCoinData>& outputs,
std::vector<std::pair<CWalletTx, CAmount>>& wtxAndFee,
bool subtractFeeFromAmount,
bool fSplit,
bool autoMintAll,
bool fAskFee,
const CCoinControl *coinControl) {
Expand All @@ -5687,7 +5688,7 @@ std::string CWallet::MintAndStoreSpark(
int nChangePosRet = -1;

std::list<CReserveKey> 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;
}

Expand Down Expand Up @@ -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<CAmount, CAmount> CWallet::GetSparkBalance()
Expand Down
2 changes: 2 additions & 0 deletions src/wallet/wallet.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -1093,6 +1094,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface
const std::vector<spark::MintedCoinData>& outputs,
std::vector<std::pair<CWalletTx, CAmount>>& wtxAndFee,
bool subtractFeeFromAmount,
bool fSplit,
bool autoMintAll = false,
bool fAskFee = false,
const CCoinControl *coinControl = NULL);
Expand Down

0 comments on commit 14ed437

Please sign in to comment.