diff --git a/.github/workflows/ci-master.yml b/.github/workflows/ci-master.yml index 79b5109f51..659e995015 100644 --- a/.github/workflows/ci-master.yml +++ b/.github/workflows/ci-master.yml @@ -172,7 +172,7 @@ jobs: - name: Use Xcode instead of Command Line Tools run: sudo xcode-select -s /Applications/Xcode.app/Contents/Developer - name: Install Required Packages - run: brew install automake coreutils pkg-config + run: brew install automake coreutils pkg-config python-setuptools # Workaround for macOS: https://github.com/actions/runner/issues/2958 - name: Install setuptools run: sudo -H pip install setuptools @@ -181,7 +181,7 @@ jobs: working-directory: ${{ env.SOURCE_ARTIFACT }} - name: Build Firo run: | - ./configure --disable-jni --prefix=$(grealpath depends/x86_64-apple-darwin*) + ./configure --prefix=`pwd`/depends/`depends/config.guess` make -j$(sysctl -n hw.activecpu) working-directory: ${{ env.SOURCE_ARTIFACT }} - name: Prepare Files for Artifact diff --git a/README.md b/README.md index 1304e41610..627c6acea0 100644 --- a/README.md +++ b/README.md @@ -112,6 +112,8 @@ sudo apt-get install git curl python build-essential libtool automake pkg-config sudo apt-get install qttools5-dev qttools5-dev-tools libxcb-xkb-dev bison ``` +If you use a later version of Ubuntu, you may need to replace `python` with `python3`. + - Redhat/Fedora: ```sh diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index bbb1b4458a..613cc3178e 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -119,8 +119,7 @@ QT_FORMS_UI = \ qt/forms/sendtopcodedialog.ui \ qt/forms/signverifymessagedialog.ui \ qt/forms/transactiondescdialog.ui \ - qt/forms/lelantusdialog.ui \ - qt/forms/createpcodedialog.ui + qt/forms/lelantusdialog.ui QT_MOC_CPP = \ qt/moc_addressbookpage.cpp \ @@ -139,7 +138,6 @@ QT_MOC_CPP = \ qt/moc_manualmintdialog.cpp \ qt/moc_coincontroltreewidget.cpp \ qt/moc_csvmodelwriter.cpp \ - qt/moc_createpcodedialog.cpp \ qt/moc_editaddressdialog.cpp \ qt/moc_guiutil.cpp \ qt/moc_intro.cpp \ @@ -215,7 +213,6 @@ BITCOIN_QT_H = \ qt/cancelpassworddialog.h \ qt/clientmodel.h \ qt/coincontroldialog.h \ - qt/createpcodedialog.h \ qt/manualmintdialog.h \ qt/coincontroltreewidget.h \ qt/csvmodelwriter.h \ @@ -429,7 +426,6 @@ BITCOIN_QT_WALLET_CPP = \ qt/askpassphrasedialog.cpp \ qt/coincontroldialog.cpp \ qt/coincontroltreewidget.cpp \ - qt/createpcodedialog.cpp \ qt/editaddressdialog.cpp \ qt/manualmintdialog.cpp \ qt/openuridialog.cpp \ diff --git a/src/crypto/MerkleTreeProof/argon2.h b/src/crypto/MerkleTreeProof/argon2.h index 61cea72eb3..fc8682c2db 100644 --- a/src/crypto/MerkleTreeProof/argon2.h +++ b/src/crypto/MerkleTreeProof/argon2.h @@ -93,7 +93,7 @@ extern "C" { #define ARGON2_FLAG_CLEAR_SECRET (UINT32_C(1) << 1) /* Global flag to determine if we are wiping internal memory buffers. This flag - * is defined in core.c and deafults to 1 (wipe internal memory). */ + * is defined in core.c and defaults to 1 (wipe internal memory). */ extern int FLAG_clear_internal_memory; /* Error codes */ diff --git a/src/ctpl.h b/src/ctpl.h index 64f650d3e8..73a43373ca 100644 --- a/src/ctpl.h +++ b/src/ctpl.h @@ -116,7 +116,7 @@ namespace ctpl { // wait for all computing threads to finish and stop all threads - // may be called asyncronously to not pause the calling thread while waiting + // may be called asynchronously to not pause the calling thread while waiting // if isWait == true, all the functions in the queue are run, otherwise the queue is cleared without running the functions void stop(bool isWait = false) { if (!isWait) { diff --git a/src/fixed.h b/src/fixed.h index 19d0107b18..36a766206b 100644 --- a/src/fixed.h +++ b/src/fixed.h @@ -222,7 +222,7 @@ namespace detail { // lets us do things like "typedef numeric::fixed_from_type::fixed_type fixed"; -// NOTE: that we will use a type of equivalent size, not neccessarily the type +// NOTE: that we will use a type of equivalent size, not necessarily the type // specified. Should make little to no difference to the user template struct fixed_from_type { diff --git a/src/fuzz/FuzzedDataProvider.h b/src/fuzz/FuzzedDataProvider.h index 9f66afc9e7..ce16e95e17 100644 --- a/src/fuzz/FuzzedDataProvider.h +++ b/src/fuzz/FuzzedDataProvider.h @@ -158,7 +158,7 @@ FuzzedDataProvider::ConsumeRandomLengthString(size_t max_length) { // picking its contents. std::string result; - // Reserve the anticipated capaticity to prevent several reallocations. + // Reserve the anticipated capacity to prevent several reallocations. result.reserve(std::min(max_length, remaining_bytes_)); for (size_t i = 0; i < max_length && remaining_bytes_ != 0; ++i) { char next = ConvertUnsignedToSigned(data_ptr_[0]); diff --git a/src/fuzz/README.md b/src/fuzz/README.md index e3c68835e9..f23b23732b 100644 --- a/src/fuzz/README.md +++ b/src/fuzz/README.md @@ -75,7 +75,7 @@ example: 2. `honggfuzz -i ../input -- ./../libspark/bpplus_hfuzz ___FILE___` 3. To stop press `ctrl+c` -Here we are providing an empty corpora. In case of an already available corpora, we can provide the availabe corpora. +Here we are providing an empty corpora. In case of an already available corpora, we can provide the available corpora. The flag `-i` is for the input folder which we are providing `./../_hfuzz>` is the target binary which we want to fuzz. ### Analyzing the crashes @@ -129,7 +129,7 @@ sudo make install Once successfully installed, follow the below instructions to generate the code-coverage 1. First compile the harness with gdb flag. run `make _debug` inside src/fuzz to compile using gdb debugger. -2. take the input_folder as the input corpora from fuzzing or one can also create it by running: `honggfuzz -i -– ./_hfuzz ___FILE___ @@`. This will start the fuzzer. Kill it by `ctrl+C`. The fuzzer will generate some random inputs inside the input_folder. Since kcov will generate coverage for each input inside the input_folder, it's preffered to have only a few inputs, otherwise it will take a long time to generate the entire coverage. +2. take the input_folder as the input corpora from fuzzing or one can also create it by running: `honggfuzz -i -– ./_hfuzz ___FILE___ @@`. This will start the fuzzer. Kill it by `ctrl+C`. The fuzzer will generate some random inputs inside the input_folder. Since kcov will generate coverage for each input inside the input_folder, it's preferred to have only a few inputs, otherwise it will take a long time to generate the entire coverage. 3. inside the `generate_coverage.sh` replace the input_folder, output_folder and fuzz_exe by your inpur corpora, coverage output folder and harness binary. 4. run `./generate_coverage.sh`. This will generated a merged output for all the inputs present in the input_folder. diff --git a/src/hdmint/wallet.cpp b/src/hdmint/wallet.cpp index 98444fd720..829dcc3448 100644 --- a/src/hdmint/wallet.cpp +++ b/src/hdmint/wallet.cpp @@ -788,7 +788,7 @@ CKeyID CHDMintWallet::GetMintSeedID(CWalletDB& walletdb, int32_t nCount){ * @param mintSeed * @param nCount (optional) count in the HD Chain of the key to use for mint generation. * @param seedId (optional) seedId of the key to use for mint generation. - * @return sucess + * @return success */ bool CHDMintWallet::CreateMintSeed(CWalletDB& walletdb, uint512& mintSeed, const int32_t& nCount, CKeyID& seedId, bool fWriteChain) { diff --git a/src/libspark/spend_transaction.cpp b/src/libspark/spend_transaction.cpp index acb747c1dc..3e30b64a4c 100644 --- a/src/libspark/spend_transaction.cpp +++ b/src/libspark/spend_transaction.cpp @@ -270,7 +270,7 @@ bool SpendTransaction::verify( if (tx.S1.size() != w || tx.C1.size() != w || tx.T.size() != w || - tx.grootle_proofs.size() != w, + tx.grootle_proofs.size() != w || tx.cover_set_sizes.size() != tx.cover_set_representations.size()) { throw std::invalid_argument("Bad spend transaction semantics"); } diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 7e1096e776..bad8afeb82 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -122,7 +122,6 @@ BitcoinGUI::BitcoinGUI(const PlatformStyle *_platformStyle, const NetworkStyle * showHelpMessageAction(0), lelantusAction(0), masternodeAction(0), - createPcodeAction(0), logoAction(0), trayIcon(0), trayIconMenu(0), @@ -366,13 +365,6 @@ void BitcoinGUI::createActions() tabGroup->addAction(masternodeAction); #endif - createPcodeAction = new QAction(tr("RA&P addresses"), this); - createPcodeAction->setStatusTip(tr("Create RAP addresses (BIP47 payment codes)")); - createPcodeAction->setToolTip(createPcodeAction->statusTip()); - createPcodeAction->setCheckable(true); - createPcodeAction->setShortcut(QKeySequence(Qt::ALT + key++)); - tabGroup->addAction(createPcodeAction); - #ifdef ENABLE_WALLET connect(masternodeAction, &QAction::triggered, [this]{ showNormalIfMinimized(); }); connect(masternodeAction, &QAction::triggered, this, &BitcoinGUI::gotoMasternodePage); @@ -390,7 +382,6 @@ void BitcoinGUI::createActions() connect(historyAction, &QAction::triggered, this, &BitcoinGUI::gotoHistoryPage); connect(lelantusAction, &QAction::triggered, this, &BitcoinGUI::gotoLelantusPage); - connect(createPcodeAction, &QAction::triggered, this, &BitcoinGUI::gotoCreatePcodePage); #endif // ENABLE_WALLET quitAction = new QAction(tr("E&xit"), this); @@ -531,8 +522,7 @@ void BitcoinGUI::createToolBars() toolbar->addAction(historyAction); toolbar->addAction(lelantusAction); toolbar->addAction(masternodeAction); - toolbar->addAction(createPcodeAction); - + QLabel *logoLabel = new QLabel(); logoLabel->setObjectName("lblToolbarLogo"); logoLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); @@ -593,10 +583,6 @@ void BitcoinGUI::setClientModel(ClientModel *_clientModel) // update lelantus page if option is changed. connect(optionsModel, &OptionsModel::lelantusPageChanged, this, &BitcoinGUI::updateLelantusPage); - // update RAP Addresses page if option is changed. - connect(optionsModel, &OptionsModel::enableRapAddressesChanged, this, &BitcoinGUI::setRapAddressesVisible); - createPcodeAction->setVisible(optionsModel->getRapAddresses()); - // initialize the disable state of the tray icon with the current value in the model. setTrayIconVisible(optionsModel->getHideTrayIcon()); } @@ -659,7 +645,6 @@ void BitcoinGUI::setWalletActionsEnabled(bool enabled) sendCoinsMenuAction->setEnabled(enabled); receiveCoinsAction->setEnabled(enabled); receiveCoinsMenuAction->setEnabled(enabled); - createPcodeAction->setEnabled(enabled); historyAction->setEnabled(enabled); lelantusAction->setEnabled(enabled); masternodeAction->setEnabled(enabled); @@ -811,12 +796,6 @@ void BitcoinGUI::gotoReceiveCoinsPage() if (walletFrame) walletFrame->gotoReceiveCoinsPage(); } -void BitcoinGUI::gotoCreatePcodePage() -{ - createPcodeAction->setChecked(true); - if (walletFrame) walletFrame->gotoCreatePcodePage(); -} - void BitcoinGUI::gotoSendCoinsPage(QString addr) { sendCoinsAction->setChecked(true); @@ -1350,14 +1329,6 @@ void BitcoinGUI::updateLelantusPage() checkLelantusVisibility(blocks); } -void BitcoinGUI::setRapAddressesVisible(bool checked) -{ -#ifdef ENABLE_WALLET - gotoOverviewPage(); -#endif // ENABLE_WALLET - createPcodeAction->setVisible(checked); -} - static bool ThreadSafeMessageBox(BitcoinGUI *gui, const std::string& message, const std::string& caption, unsigned int style) { bool modal = (style & CClientUIInterface::MODAL); diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index 514b0f3501..a2e6b1c5fd 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -120,7 +120,6 @@ class BitcoinGUI : public QMainWindow QAction *showHelpMessageAction; QAction *lelantusAction; QAction *masternodeAction; - QAction *createPcodeAction; QAction *logoAction; QSystemTrayIcon *trayIcon; @@ -218,8 +217,6 @@ public Q_SLOTS: void gotoMasternodePage(); /** Switch to receive coins page */ void gotoReceiveCoinsPage(); - /** Switch to create payment code page */ - void gotoCreatePcodePage(); /** Switch to send coins page */ void gotoSendCoinsPage(QString addr = ""); /** Switch to lelantus page */ @@ -275,8 +272,6 @@ public Q_SLOTS: /** Update Lelantus page visibility */ void updateLelantusPage(); - /** Update RAP Addresses page visibility */ - void setRapAddressesVisible(bool); }; class UnitDisplayStatusBarControl : public QLabel diff --git a/src/qt/bitcoinstrings.cpp b/src/qt/bitcoinstrings.cpp index a26f1cf886..6b4d5aff98 100644 --- a/src/qt/bitcoinstrings.cpp +++ b/src/qt/bitcoinstrings.cpp @@ -553,7 +553,7 @@ QT_TRANSLATE_NOOP("firo-core", "Transaction has too long of a mempool chain"), QT_TRANSLATE_NOOP("firo-core", "Transaction must have at least one recipient"), QT_TRANSLATE_NOOP("firo-core", "Transaction not valid."), QT_TRANSLATE_NOOP("firo-core", "Transaction too large for fee policy"), -QT_TRANSLATE_NOOP("firo-core", "Transaction too large"), +QT_TRANSLATE_NOOP("firo-core", "Transaction is too large (size limit: 100Kb). Select less inputs or consolidate your UTXOs"), QT_TRANSLATE_NOOP("firo-core", "Trying to spend an already spent serial #, try again."), QT_TRANSLATE_NOOP("firo-core", "Unable to bind to %s on this computer (bind returned error %s)"), QT_TRANSLATE_NOOP("firo-core", "Unable to bind to %s on this computer. %s is probably already running."), diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp index 2963acd958..da7b9b5bb5 100644 --- a/src/qt/coincontroldialog.cpp +++ b/src/qt/coincontroldialog.cpp @@ -527,9 +527,9 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog, bool a { if (anonymousMode) { if(spark::IsSparkAllowed()) { - // 924 is constant part, mainly Schnorr and Range proofs, 2535 is for each grootle proof/aux data - // 213 for each private output, 144 other parts of tx, - nBytes = 924 + 2535 * (vOutputs.size()) + 213 * CoinControlDialog::payAmounts.size() + 144; + // 924 is constant part, mainly Schnorr and Range proofs, 1803 is for each grootle proof/aux data + // 213 for each private output, + nBytes = 924 + 1803 * (vOutputs.size()) + 322 * CoinControlDialog::payAmounts.size(); } else { // 1054 is constant part, mainly Schnorr and Range proofs, 2560 is for each sigma/aux data // 83 assuming 1 jmint, 34 is the size of each normal vout, 10 is the size of empty transaction, 52 other constant parts diff --git a/src/qt/createpcodedialog.cpp b/src/qt/createpcodedialog.cpp deleted file mode 100644 index 852fe864a5..0000000000 --- a/src/qt/createpcodedialog.cpp +++ /dev/null @@ -1,237 +0,0 @@ -// Copyright (c) 2019-2021 The Firo Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include "createpcodedialog.h" -#include "ui_createpcodedialog.h" - -#include "addressbookpage.h" -#include "addresstablemodel.h" -#include "bitcoinunits.h" -#include "guiutil.h" -#include "optionsmodel.h" -#include "platformstyle.h" -#include "receiverequestdialog.h" -#include "recentrequeststablemodel.h" -#include "walletmodel.h" -#include "pcodemodel.h" - -#include -#include -#include -#include -#include -#include - -CreatePcodeDialog::CreatePcodeDialog(const PlatformStyle *_platformStyle, QWidget *parent) : - QDialog(parent), - ui(new Ui::CreatePcodeDialog), - model(0), - platformStyle(_platformStyle) -{ - ui->setupUi(this); - - if (!_platformStyle->getImagesOnButtons()) { - ui->clearButton->setIcon(QIcon()); - ui->createPcodeButton->setIcon(QIcon()); - } else { - ui->clearButton->setIcon(_platformStyle->SingleColorIcon(":/icons/remove")); - ui->createPcodeButton->setIcon(_platformStyle->SingleColorIcon(":/icons/paymentcode")); - } - - // context menu actions - QAction *copyPcodeAction = new QAction(tr("Copy RAP Address"), this); - QAction *copyNotificationAddrAction = new QAction(tr("Copy Notification Address"), this); - QAction *showQrcodeAction = new QAction(tr("Show QR Code"), this); - - // context menu - contextMenu = new QMenu(this); - contextMenu->addAction(copyPcodeAction); - contextMenu->addAction(copyNotificationAddrAction); - contextMenu->addAction(showQrcodeAction); - - // context menu signals - connect(ui->pcodesView, &QWidget::customContextMenuRequested, this, &CreatePcodeDialog::showMenu); - connect(copyPcodeAction, &QAction::triggered, this, &CreatePcodeDialog::copyPcode); - connect(copyNotificationAddrAction, &QAction::triggered, this, &CreatePcodeDialog::copyNotificationAddr); - connect(showQrcodeAction, &QAction::triggered, this, &CreatePcodeDialog::showQrcode); - - connect(ui->clearButton, &QPushButton::clicked, this, &CreatePcodeDialog::clear); - - ui->statusLabel->setStyleSheet("QLabel { color: " + QColor(GUIUtil::GUIColors::warning).name() + "; }"); -} - -void CreatePcodeDialog::setModel(WalletModel *_model) -{ - model = _model; - - if(_model && _model->getOptionsModel()) - { - _model->getPcodeModel()->sort(int(PcodeModel::ColumnIndex::Number), Qt::DescendingOrder); - - QTableView* tableView = ui->pcodesView; - - tableView->verticalHeader()->hide(); - tableView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - tableView->setModel(_model->getPcodeModel()); - tableView->setAlternatingRowColors(true); - tableView->setSelectionBehavior(QAbstractItemView::SelectRows); - tableView->setSelectionMode(QAbstractItemView::ContiguousSelection); - tableView->setColumnWidth(static_cast(PcodeModel::ColumnIndex::Number), static_cast(ColumnWidths::Number)); - tableView->setColumnWidth(static_cast(PcodeModel::ColumnIndex::Pcode), static_cast(ColumnWidths::Pcode)); - tableView->setItemDelegateForColumn(int(PcodeModel::ColumnIndex::Pcode), new GUIUtil::TextElideStyledItemDelegate(tableView)); - connect(tableView->selectionModel(), &QItemSelectionModel::selectionChanged, - this, &CreatePcodeDialog::pcodesView_selectionChanged); - - ui->createPcodeButton->setEnabled(false); - ui->statusLabel->setText(tr("The label should not be empty.")); - } -} - -CreatePcodeDialog::~CreatePcodeDialog() -{ - delete ui; -} - -void CreatePcodeDialog::clear() -{ - ui->labelText->setText(""); -} - -void CreatePcodeDialog::reject() -{ - clear(); -} - -void CreatePcodeDialog::accept() -{ - clear(); -} - -void CreatePcodeDialog::on_createPcodeButton_clicked() -{ - WalletModel::UnlockContext ctx(model->requestUnlock()); - if(!ctx.isValid()) return; - try { - model->getWallet()->GeneratePcode(ui->labelText->text().toStdString()); - } - catch (std::runtime_error const & e) - { - QMessageBox::critical(0, tr(PACKAGE_NAME), - tr("RAP address creation failed with error: \"%1\"").arg(e.what())); - } - on_labelText_textChanged(); -} - -void CreatePcodeDialog::on_labelText_textChanged() -{ - QString status = ""; - if (ui->labelText->text().size() == 0) - status = tr("The label should not be empty."); - for (bip47::CPaymentCodeDescription const & desr : model->getPcodeModel()->getItems()) { - if (std::get<2>(desr) == ui->labelText->text().toStdString()) - status = tr("The label should be unique."); - } - ui->statusLabel->setText(status); - ui->createPcodeButton->setEnabled(status.size() == 0); -} - -void CreatePcodeDialog::on_pcodesView_doubleClicked(const QModelIndex &index) -{ - if(index.column() == int(PcodeModel::ColumnIndex::Label)) - { - ui->pcodesView->edit(index); - return; - } - showQrcode(); -} - -void CreatePcodeDialog::on_showPcodeButton_clicked() -{ - showQrcode(); -} - -void CreatePcodeDialog::pcodesView_selectionChanged(QItemSelection const & selected, QItemSelection const & deselected) -{ - bool const enable = !ui->pcodesView->selectionModel()->selectedRows().isEmpty(); - ui->showPcodeButton->setEnabled(enable); -} - -void CreatePcodeDialog::keyPressEvent(QKeyEvent *event) -{ - if (event->key() == Qt::Key_Return) - { - // press return -> submit form - if (ui->labelText->hasFocus()) - { - event->ignore(); - on_createPcodeButton_clicked(); - return; - } - } - - this->QDialog::keyPressEvent(event); -} - -QModelIndex CreatePcodeDialog::selectedRow() -{ - if(!model || !model->getRecentRequestsTableModel() || !ui->pcodesView->selectionModel()) - return QModelIndex(); - QModelIndexList selection = ui->pcodesView->selectionModel()->selectedRows(); - if(selection.empty()) - return QModelIndex(); - // correct for selection mode ContiguousSelection - QModelIndex firstIndex = selection.at(0); - return firstIndex; -} - -// copy column of selected row to clipboard -void CreatePcodeDialog::copyColumnToClipboard(int column) -{ - QModelIndex firstIndex = selectedRow(); - if (!firstIndex.isValid()) { - return; - } - GUIUtil::setClipboard(model->getRecentRequestsTableModel()->data(firstIndex.child(firstIndex.row(), column), Qt::EditRole).toString()); -} - -// context menu -void CreatePcodeDialog::showMenu(const QPoint &point) -{ - if (!selectedRow().isValid()) { - return; - } - contextMenu->exec(QCursor::pos()); -} - -void CreatePcodeDialog::copyPcode() -{ - QModelIndex sel = selectedRow(); - if (!sel.isValid()) { - return; - } - GUIUtil::setClipboard(std::get<1>(model->getPcodeModel()->getItems().at(sel.row())).toString().c_str()); -} - -void CreatePcodeDialog::copyNotificationAddr() -{ - QModelIndex sel = selectedRow(); - if (!sel.isValid()) { - return; - } - GUIUtil::setClipboard(std::get<3>(model->getPcodeModel()->getItems().at(sel.row())).ToString().c_str()); -} - -void CreatePcodeDialog::showQrcode() -{ - QModelIndex sel = selectedRow(); - if (!sel.isValid()) { - return; - } - recipient.address = QString(std::get<1>(model->getPcodeModel()->getItems().at(sel.row())).toString().c_str()); - ReceiveRequestDialog *dialog = new ReceiveRequestDialog(this); - dialog->setModel(model->getOptionsModel()); - dialog->setInfo(recipient); - dialog->setAttribute(Qt::WA_DeleteOnClose); - dialog->show(); -} diff --git a/src/qt/createpcodedialog.h b/src/qt/createpcodedialog.h deleted file mode 100644 index b41feec761..0000000000 --- a/src/qt/createpcodedialog.h +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright (c) 2019-2021 The Firo Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#ifndef BITCOIN_QT_CREATEPCODEDIALOG_H -#define BITCOIN_QT_CREATEPCODEDIALOG_H - -#include "guiutil.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "walletmodel.h" -#include "bip47/paymentcode.h" - -class OptionsModel; -class PlatformStyle; -class WalletModel; - -namespace Ui { - class CreatePcodeDialog; -} - -QT_BEGIN_NAMESPACE -class QModelIndex; -QT_END_NAMESPACE - -/** Dialog for requesting payment of bitcoins */ -class CreatePcodeDialog : public QDialog -{ - Q_OBJECT - -public: - enum struct ColumnWidths : int { - Number = 80, - Label = 180, - Pcode = 180 - }; - - explicit CreatePcodeDialog(const PlatformStyle *platformStyle, QWidget *parent = 0); - ~CreatePcodeDialog(); - - void setModel(WalletModel *model); - -public Q_SLOTS: - void clear(); - void reject(); - void accept(); - -protected: - virtual void keyPressEvent(QKeyEvent *event); - -private: - Ui::CreatePcodeDialog *ui; - WalletModel *model; - QMenu *contextMenu; - const PlatformStyle *platformStyle; - SendCoinsRecipient recipient; - - QModelIndex selectedRow(); - void copyColumnToClipboard(int column); - -private Q_SLOTS: - void on_createPcodeButton_clicked(); - void on_labelText_textChanged(); - void on_pcodesView_doubleClicked(const QModelIndex &index); - void pcodesView_selectionChanged(QItemSelection const & selected, QItemSelection const & deselected); - void on_showPcodeButton_clicked(); - void showMenu(const QPoint &point); - void copyPcode(); - void copyNotificationAddr(); - void showQrcode(); -}; - -#endif // BITCOIN_QT_CREATEPCODEDIALOG_H diff --git a/src/qt/forms/createpcodedialog.ui b/src/qt/forms/createpcodedialog.ui deleted file mode 100644 index db9d343f8c..0000000000 --- a/src/qt/forms/createpcodedialog.ui +++ /dev/null @@ -1,253 +0,0 @@ - - - CreatePcodeDialog - - - - 0 - 0 - 776 - 364 - - - - - - - - 0 - 0 - - - - QFrame::StyledPanel - - - QFrame::Sunken - - - - - - - - - 0 - 0 - - - - <html><head/><body><p>Use this form to create a Receiver Address Privacy (BIP47) payment code.</p></body></html> - - - - - - - An optional label to associate with the new receiving address. - - - &Label: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - labelText - - - - - - - - - - 150 - 0 - - - - C&reate payment code - - - - - - - - 0 - 0 - - - - Clear all fields of the form. - - - Clear - - - false - - - - - - - Qt::Horizontal - - - QSizePolicy::Minimum - - - - 10 - 20 - - - - - - - - - 0 - 0 - - - - statusLabel - - - - - - - - - - - - - - - - A mandatory label to associate with the new payment code. - - - - - - - - - - - - Qt::Vertical - - - - 20 - 10 - - - - - - - - - 0 - 0 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - 75 - true - - - - Recent payment codes - - - - - - - Qt::CustomContextMenu - - - Double click on Label to edit, on other columns for more info - - - false - - - true - - - - - - - - - false - - - Show more info on the selected payment code (does the same as double clicking an entry) - - - Show - - - false - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - labelText - createPcodeButton - clearButton - pcodesView - showPcodeButton - - - - - - - slot1() - - diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp index 26a4c9612e..ea0d1a7b12 100644 --- a/src/qt/overviewpage.cpp +++ b/src/qt/overviewpage.cpp @@ -185,7 +185,7 @@ void OverviewPage::handleEnabledTorChanged(){ if(ui->checkboxEnabledTor->isChecked()){ settings.setValue("fTorSetup", true); - msgBox.setText(tr("Please restart the Firo wallet to route your connection through Tor to protect your IP address.
Syncing your wallet might be slower with TOR.
Note that -torsetup in firo.conf will always override any changes made here.")); + msgBox.setText(tr("Please restart the Firo wallet to route your connection through Tor to protect your IP address.
Syncing your wallet might be slower with Tor.
Note that -torsetup in firo.conf will always override any changes made here.")); }else{ settings.setValue("fTorSetup", false); msgBox.setText(tr("Please restart the Firo wallet to disable routing of your connection through Tor to protect your IP address.
Note that -torsetup in firo.conf will always override any changes made here.")); diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index 5df00dd43d..925cc492b9 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -292,7 +292,6 @@ void SendCoinsDialog::on_sendButton_clicked() } // prepare transaction for getting txFee earlier - WalletModelTransaction currentTransaction(recipients); std::vector transactions; WalletModel::SendCoinsReturn prepareStatus; std::vector> wtxAndFees; @@ -310,13 +309,68 @@ void SendCoinsDialog::on_sendButton_clicked() ctrl.nConfirmTarget = 0; int sparkAddressCount = 0; + int exchangeAddressCount = 0; for(int i = 0; i < recipients.size(); ++i){ - bool check = model->validateSparkAddress(recipients[i].address); - if(check) { + if (model->validateSparkAddress(recipients[i].address)) sparkAddressCount++; + if (model->validateExchangeAddress(recipients[i].address)) + exchangeAddressCount++; + } + + bool fGoThroughTransparentAddress = false; + __decltype(recipients) exchangeRecipients; + CScript intermediateAddressScript; + CAmount extraFee = 0; + + if (fAnonymousMode && exchangeAddressCount > 0) { + CAmount exchangeAddressAmount = 0; + // if the transaction is performed in two stages through the intermediate address we need to calculate the size of the second transaction + uint32_t secondTxSize = 8 /*CTransaction: nVersion, nLockTime*/ + 1 /*vinSize*/ + 148 /*vin[0]*/ + 20 /*safety*/ + 1 /*voutSize*/; + + fGoThroughTransparentAddress = true; + + // remove exchange addresses from recipients array and add them to exchangeRecipients array + for(int i = 0; i < recipients.size(); ){ + if (model->validateExchangeAddress(recipients[i].address)) { + exchangeAddressAmount += recipients[i].amount; + // we use different fee calculation system and therefore can't reliably do the calculation + // of fee for the second transaction if some of recipients have this flag set + recipients[i].fSubtractFeeFromAmount = false; + exchangeRecipients.push_back(recipients[i]); + + secondTxSize += 8 /*amount*/ + 1 /*scriptSize*/ + 26 /*scriptPubKey*/; + + recipients.erase(recipients.begin() + i); + } + else { + ++i; + } + } + + LOCK2(cs_main, pwalletMain->cs_wallet); + // create a new transparent address and add it to the recipients array + if (!pwalletMain->IsLocked()) { + pwalletMain->TopUpKeyPool(); + } + CPubKey newKey; + if (!pwalletMain->GetKeyFromPool(newKey)) { + fNewRecipientAllowed = true; + return; } + pwalletMain->SetAddressBook(newKey.GetID(), "", "receive"); + intermediateAddressScript = GetScriptForDestination(newKey.GetID()); + + extraFee = CWallet::GetMinimumFee(secondTxSize, 0, mempool); + + SendCoinsRecipient newRecipient; + newRecipient.address = CBitcoinAddress(newKey.GetID()).ToString().c_str(); + newRecipient.amount = exchangeAddressAmount + extraFee; + newRecipient.fSubtractFeeFromAmount = false; + recipients.push_back(newRecipient); } + WalletModelTransaction currentTransaction(recipients); + CAmount mintSparkAmount = 0; CAmount txFee = 0; CAmount totalAmount = 0; @@ -355,6 +409,14 @@ void SendCoinsDialog::on_sendButton_clicked() return; } + // If the transaction is performed in two stages through the intermediate address we need to show the real + // recipients (for informational purposes), replacing the intermediate transparent address with the exchange address(es) + __decltype(recipients) realRecipients = recipients; + if (fGoThroughTransparentAddress) { + realRecipients.erase(realRecipients.end() - 1); + realRecipients.append(exchangeRecipients); + } + // Format confirmation message QStringList formatted; QString warningMessage; @@ -407,7 +469,7 @@ void SendCoinsDialog::on_sendButton_clicked() formatted.append(recipientElement); } } else if ((fAnonymousMode == true) && (recipients.size() == 1) && spark::IsSparkAllowed()) { - for (auto &rcp : recipients) + for (auto &rcp : realRecipients) { // generate bold amount string CAmount namount = rcp.amount; @@ -434,7 +496,7 @@ void SendCoinsDialog::on_sendButton_clicked() formatted.append(recipientElement); } } else { - for (const SendCoinsRecipient &rcp : currentTransaction.getRecipients()) + for (auto &rcp : realRecipients) { // generate bold amount string QString amount = "" + BitcoinUnits::formatHtmlWithUnit(model->getOptionsModel()->getDisplayUnit(), rcp.amount); @@ -460,6 +522,13 @@ void SendCoinsDialog::on_sendButton_clicked() } } + if (fGoThroughTransparentAddress) { + QString transparentAddress = "" + recipients[recipients.size()-1].address + ""; + formatted.append("
"); + formatted.append(tr("EX-addresses can only receive FIRO from transparent addresses.

" + "Your FIRO will go from Spark to a newly generated transparent address %1 and then immediately be sent to the EX-address.").arg(transparentAddress)); + } + QString questionString = tr("Are you sure you want to send?"); questionString.append(warningMessage); questionString.append("

%1"); @@ -486,6 +555,15 @@ void SendCoinsDialog::on_sendButton_clicked() // append transaction size questionString.append(" (" + QString::number(txSize / 1000) + " kB)"); + + if (fGoThroughTransparentAddress) { + QString feeString; + feeString.append(""); + feeString.append(BitcoinUnits::formatHtmlWithUnit(model->getOptionsModel()->getDisplayUnit(), extraFee)); + feeString.append(""); + + questionString.append(tr(". An additional transaction fee of %1 will apply to complete the send from the transparent address to the EX-address.").arg(feeString)); + } } // add total amount in all subdivision units @@ -558,6 +636,53 @@ void SendCoinsDialog::on_sendButton_clicked() CoinControlDialog::coinControl->UnSelectAll(); coinControlUpdateLabels(); } + + // Launch the second stage of the transaction if needed + if (fGoThroughTransparentAddress) { + // prepare the coin control so the transaction will use (by default) only the transparent address + // created in the first stage + COutPoint outpoint; + outpoint.hash = currentTransaction.getTransaction()->GetHash(); + outpoint.n = UINT_MAX; + + const auto &vout = currentTransaction.getTransaction()->tx->vout; + for (size_t i = 0; i < vout.size(); i++) { + if (vout[i].scriptPubKey == intermediateAddressScript) { + outpoint.n = i; + break; + } + } + + if (outpoint.n == UINT_MAX) { + sendStatus.status = WalletModel::InvalidAddress; + sendStatus.reasonCommitFailed = "Intermediate address was not found in the transaction"; + fNewRecipientAllowed = true; + return; + } + + CCoinControl ctrl; + ctrl.fAllowOtherInputs = false; + ctrl.fNoChange = true; + ctrl.Select(outpoint); + + WalletModelTransaction secondTransaction(exchangeRecipients); + + prepareStatus = model->prepareTransaction(secondTransaction, &ctrl); + + // process prepareStatus and on error generate message shown to user + processSendCoinsReturn(prepareStatus, + BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), currentTransaction.getTransactionFee())); + + if(prepareStatus.status != WalletModel::OK) { + fNewRecipientAllowed = true; + return; + } + + sendStatus = model->sendCoins(secondTransaction); + // process sendStatus and on error generate message shown to user + processSendCoinsReturn(sendStatus); + } + fNewRecipientAllowed = true; } diff --git a/src/qt/walletframe.cpp b/src/qt/walletframe.cpp index 21cf5b0302..06ca9a2868 100644 --- a/src/qt/walletframe.cpp +++ b/src/qt/walletframe.cpp @@ -146,13 +146,6 @@ void WalletFrame::gotoReceiveCoinsPage() i.value()->gotoReceiveCoinsPage(); } -void WalletFrame::gotoCreatePcodePage() -{ - QMap::const_iterator i; - for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i) - i.value()->gotoCreatePcodePage(); -} - void WalletFrame::gotoSendCoinsPage(QString addr) { QMap::const_iterator i; diff --git a/src/qt/walletframe.h b/src/qt/walletframe.h index 4addb0552b..2c99bd74bd 100644 --- a/src/qt/walletframe.h +++ b/src/qt/walletframe.h @@ -76,7 +76,6 @@ public Q_SLOTS: void gotoMasternodePage(); /** Switch to receive coins page */ void gotoReceiveCoinsPage(); - void gotoCreatePcodePage(); /** Switch to send coins page */ void gotoSendCoinsPage(QString addr = ""); /** Switch to lelantus page */ diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index e6908f973d..66a8538941 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -272,6 +272,12 @@ bool WalletModel::validateAddress(const QString &address) return addressParsed.IsValid(); } +bool WalletModel::validateExchangeAddress(const QString &address) +{ + CBitcoinAddress addressParsed(address.toStdString()); + return addressParsed.IsValid() && addressParsed.Get().type() == typeid(CExchangeKeyID); +} + WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransaction &transaction, const CCoinControl *coinControl) { CAmount total = 0; diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h index f05b3829f0..f7e85ef62c 100644 --- a/src/qt/walletmodel.h +++ b/src/qt/walletmodel.h @@ -153,6 +153,7 @@ class WalletModel : public QObject // Check address for validity bool validateAddress(const QString &address); + bool validateExchangeAddress(const QString &address); bool validateSparkAddress(const QString &address); std::pair getSparkBalance(); diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp index abaf8c4871..eb65f9fa6b 100644 --- a/src/qt/walletview.cpp +++ b/src/qt/walletview.cpp @@ -10,7 +10,6 @@ #include "automintmodel.h" #include "bitcoingui.h" #include "clientmodel.h" -#include "createpcodedialog.h" #include "guiutil.h" #include "lelantusdialog.h" #include "lelantusmodel.h" @@ -52,7 +51,6 @@ WalletView::WalletView(const PlatformStyle *_platformStyle, QWidget *parent): overviewPage = new OverviewPage(platformStyle); transactionsPage = new QWidget(this); receiveCoinsPage = new ReceiveCoinsDialog(platformStyle); - createPcodePage = new CreatePcodeDialog(platformStyle); usedSendingAddressesPage = new AddressBookPage(platformStyle, AddressBookPage::ForEditing, AddressBookPage::SendingTab, this); usedReceivingAddressesPage = new AddressBookPage(platformStyle, AddressBookPage::ForEditing, AddressBookPage::ReceivingTab, this, false); lelantusPage = new QWidget(this); @@ -73,7 +71,6 @@ WalletView::WalletView(const PlatformStyle *_platformStyle, QWidget *parent): addWidget(overviewPage); addWidget(transactionsPage); addWidget(receiveCoinsPage); - addWidget(createPcodePage); addWidget(sendCoinsPage); addWidget(lelantusPage); addWidget(masternodeListPage); @@ -200,7 +197,6 @@ void WalletView::setWalletModel(WalletModel *_walletModel) firoTransactionList->setModel(_walletModel); overviewPage->setWalletModel(_walletModel); receiveCoinsPage->setModel(_walletModel); - createPcodePage->setModel(_walletModel); // TODO: fix this //sendCoinsPage->setModel(_walletModel); if (pwalletMain->IsHDSeedAvailable()) { @@ -308,11 +304,6 @@ void WalletView::gotoReceiveCoinsPage() setCurrentWidget(receiveCoinsPage); } -void WalletView::gotoCreatePcodePage() -{ - setCurrentWidget(createPcodePage); -} - void WalletView::gotoLelantusPage() { setCurrentWidget(lelantusPage); diff --git a/src/qt/walletview.h b/src/qt/walletview.h index 4e94074fa0..b0203dd00c 100644 --- a/src/qt/walletview.h +++ b/src/qt/walletview.h @@ -22,7 +22,6 @@ class ClientModel; class OverviewPage; class PlatformStyle; class ReceiveCoinsDialog; -class CreatePcodeDialog; class SendCoinsDialog; class SendCoinsRecipient; class TransactionView; @@ -79,7 +78,6 @@ class WalletView : public QStackedWidget QWidget *transactionsPage; QWidget *smartPropertyPage; ReceiveCoinsDialog *receiveCoinsPage; - CreatePcodeDialog *createPcodePage; AddressBookPage *usedSendingAddressesPage; AddressBookPage *usedReceivingAddressesPage; QWidget *sendCoinsPage; @@ -109,7 +107,6 @@ public Q_SLOTS: void gotoMasternodePage(); /** Switch to receive coins page */ void gotoReceiveCoinsPage(); - void gotoCreatePcodePage(); /** Switch to send coins page */ void gotoSendCoinsPage(QString addr = ""); /** Switch to lelantus page */ diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index 74479aaa71..ad96886540 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -23,6 +23,7 @@ #include "txdb.h" #include "masternode-sync.h" +#include "evo/deterministicmns.h" #include @@ -1430,6 +1431,42 @@ UniValue getsparklatestcoinid(const JSONRPCRequest& request) return UniValue(latestCoinId); } +UniValue checkifmncollateral(const JSONRPCRequest& request) +{ + if (request.fHelp || request.params.size() != 2) + throw std::runtime_error( + "checkifmncollateral\n" + "\nReturns bool value.\n" + "\nArguments:\n" + " \"txHash\"\n" + " \"index\"\n" + + HelpExampleCli("checkifmncollateral", "\"b476ed2b374bb081ea51d111f68f0136252521214e213d119b8dc67b92f5a390\"" "\"0\" ") + + HelpExampleRpc("checkifmncollateral", "\"b476ed2b374bb081ea51d111f68f0136252521214e213d119b8dc67b92f5a390\"" "\"0\" ") + ); + + std::string strTxId; + int index; + + try { + strTxId = request.params[0].get_str(); + index = std::stol(request.params[1].get_str()); + } catch (std::logic_error const & e) { + throw std::runtime_error(std::string("An exception occurred while parsing parameters: ") + e.what()); + } + + uint256 txid = uint256S(strTxId); + + CTransactionRef tx; + uint256 hashBlock; + if(!GetTransaction(txid, tx, Params().GetConsensus(), hashBlock, true)) + throw std::runtime_error("Unknown transaction."); + + auto mnList = deterministicMNManager->GetListAtChainTip(); + COutPoint o(txid, index); + bool fMnExists = deterministicMNManager->IsProTxWithCollateral(tx, index) || mnList.HasMNByCollateral(o); + return UniValue(fMnExists); +} + UniValue getaddresstxids(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 1) @@ -1727,6 +1764,7 @@ static const CRPCCommand commands[] = { "mobile", "getusedcoinstags", &getusedcoinstags, false }, { "mobile", "getsparklatestcoinid", &getsparklatestcoinid, true }, + { "mobile", "checkifmncollateral", &checkifmncollateral, false }, { "hidden", "setmocktime", &setmocktime, true, {"timestamp"}}, { "hidden", "echo", &echo, true, {"arg0","arg1","arg2","arg3","arg4","arg5","arg6","arg7","arg8","arg9"}}, diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 88c97abee2..04870a06bc 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -344,6 +344,8 @@ static const CRPCCommand vRPCCommands[] = { "mobile", "getusedcoinstags", &getusedcoinstags, false }, { "mobile", "getsparklatestcoinid", &getsparklatestcoinid, true }, + { "mobile", "checkifmncollateral", &checkifmncollateral, false }, + }; CRPCTable::CRPCTable() diff --git a/src/rpc/server.h b/src/rpc/server.h index 642e33451e..b16f0f4e95 100644 --- a/src/rpc/server.h +++ b/src/rpc/server.h @@ -218,6 +218,8 @@ extern UniValue getsparkmintmetadata(const JSONRPCRequest& params); extern UniValue getusedcoinstags(const JSONRPCRequest& params); extern UniValue getsparklatestcoinid(const JSONRPCRequest& params); +extern UniValue checkifmncollateral(const JSONRPCRequest& params); + extern UniValue znode(const JSONRPCRequest &request); extern UniValue znodelist(const JSONRPCRequest &request); extern UniValue znodebroadcast(const JSONRPCRequest &request); diff --git a/src/spark/sparkwallet.cpp b/src/spark/sparkwallet.cpp index 79c973703b..0852256861 100644 --- a/src/spark/sparkwallet.cpp +++ b/src/spark/sparkwallet.cpp @@ -1024,7 +1024,7 @@ bool CSparkWallet::CreateSparkMintTransactions( // Limit size CTransaction txConst(tx); if (GetTransactionWeight(txConst) >= MAX_STANDARD_TX_WEIGHT) { - strFailReason = _("Transaction too large"); + strFailReason = _("Transaction is too large (size limit: 100Kb). Select less inputs or consolidate your UTXOs"); return false; } dPriority = txConst.ComputePriority(dPriority, nBytes); @@ -1536,7 +1536,7 @@ CWalletTx CSparkWallet::CreateSparkSpendTransaction( } if (GetTransactionWeight(tx) >= MAX_NEW_TX_WEIGHT) { - throw std::runtime_error(_("Transaction too large")); + throw std::runtime_error(_("Transaction is too large (size limit: 100Kb). Select less inputs or consolidate your UTXOs")); } // check fee @@ -1697,9 +1697,9 @@ std::pair> CSparkWallet::SelectSparkCoins( throw std::invalid_argument(_("Unable to select cons for spend")); } - // 924 is constant part, mainly Schnorr and Range proofs, 2535 is for each grootle proof/aux data - // 213 for each private output, 144 other parts of tx, - size = 924 + 2535 * (spendCoins.size()) + 213 * mintNum + 144; //TODO (levon) take in account also utxoNum + // 1803 is for first grootle proof/aux data + // 213 for each private output, 34 for each utxo,924 constant parts of tx parts of tx, + size = 924 + 1803*(spendCoins.size()) + 322*(mintNum+1) + 34*utxoNum; CAmount feeNeeded = CWallet::GetMinimumFee(size, nTxConfirmTarget, mempool); if (fee >= feeNeeded) { diff --git a/src/txdb.cpp b/src/txdb.cpp index e554c15de0..acb6463381 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -17,6 +17,10 @@ #include +#ifdef __linux__ +#include +#endif + static const char DB_COIN = 'C'; static const char DB_COINS = 'c'; static const char DB_BLOCK_FILES = 'f'; @@ -365,6 +369,14 @@ bool CBlockTreeDB::LoadBlockIndexGuts(boost::functionValid()) { boost::this_thread::interruption_point(); @@ -423,7 +435,7 @@ bool CBlockTreeDB::LoadBlockIndexGuts(boost::functionnHeight >= firstInLastNBlocksHeight) { lastNBlocks.insert(std::pair(pindexNew->nHeight, pindexNew)); - if (lastNBlocks.size() > DEFAULT_BLOCKINDEX_NUMBER_OF_BLOCKS_TO_CHECK) { + if (lastNBlocks.size() > nBlocksToCheck) { // pop the first element from the map auto firstElement = lastNBlocks.begin(); auto elementToPop = firstElement++; diff --git a/src/txdb.h b/src/txdb.h index 591a4e9987..fb35aa4c9f 100644 --- a/src/txdb.h +++ b/src/txdb.h @@ -47,6 +47,8 @@ static const int64_t nMaxCoinsDBCache = 8; static const bool DEFAULT_FULL_BLOCKINDEX_CHECK = false; //! If not doing full check of block index, check only N of the latest blocks static const int DEFAULT_BLOCKINDEX_NUMBER_OF_BLOCKS_TO_CHECK = 10000; +//! Check fewer blocks if low on memory +static const int DEFAULT_BLOCKINDEX_LOWMEM_NUMBER_OF_BLOCKS_TO_CHECK = 50; struct CDiskTxPos : public CDiskBlockPos { diff --git a/src/wallet/coincontrol.h b/src/wallet/coincontrol.h index 064a2b9d99..feed073c26 100644 --- a/src/wallet/coincontrol.h +++ b/src/wallet/coincontrol.h @@ -24,6 +24,8 @@ class CCoinControl { public: CTxDestination destChange; + //! If true, don't use any change + bool fNoChange; //! If false, allows unselected inputs, but requires all selected inputs be used bool fAllowOtherInputs; //! Includes watch only addresses which match the ISMINE_WATCH_SOLVABLE criteria @@ -49,6 +51,7 @@ class CCoinControl void SetNull() { destChange = CNoDestination(); + fNoChange = false; fAllowOtherInputs = false; fRequireAllInputs = true; fAllowWatchOnly = false; diff --git a/src/wallet/lelantusjoinsplitbuilder.cpp b/src/wallet/lelantusjoinsplitbuilder.cpp index a10eb4483f..eba439524c 100644 --- a/src/wallet/lelantusjoinsplitbuilder.cpp +++ b/src/wallet/lelantusjoinsplitbuilder.cpp @@ -321,7 +321,7 @@ CWalletTx LelantusJoinSplitBuilder::Build( result.SetTx(MakeTransactionRef(tx)); if (GetTransactionWeight(tx) >= MAX_NEW_TX_WEIGHT) { - throw std::runtime_error(_("Transaction too large")); + throw std::runtime_error(_("Transaction is too large (size limit: 100Kb). Select less inputs or consolidate your UTXOs")); } // check fee diff --git a/src/wallet/txbuilder.cpp b/src/wallet/txbuilder.cpp index 1419db6cbf..637bc26a14 100644 --- a/src/wallet/txbuilder.cpp +++ b/src/wallet/txbuilder.cpp @@ -224,7 +224,7 @@ CWalletTx TxBuilder::Build(const std::vector& recipients, CAmount& f result.SetTx(MakeTransactionRef(tx)); if (GetTransactionWeight(tx) >= MAX_STANDARD_TX_WEIGHT) { - throw std::runtime_error(_("Transaction too large")); + throw std::runtime_error(_("Transaction is too large (size limit: 100Kb). Select less inputs or consolidate your UTXOs")); } // check fee diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index fababfae30..b1f5715403 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -4450,7 +4450,7 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletT const CAmount nChange = nValueIn - nValueToSelect; CTxOut newTxOut; - if (nChange > 0) + if (nChange > 0 && !(coinControl && coinControl->fNoChange)) { // Fill a vout to ourself // TODO: pass in scriptChange instead of reservekey so @@ -4566,7 +4566,7 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletT if (GetTransactionWeight(txNew) >= MAX_STANDARD_TX_WEIGHT) { // Do not create oversized transactions (bad-txns-oversize). - strFailReason = _("Transaction too large"); + strFailReason = _("Transaction is too large (size limit: 100Kb). Select less inputs or consolidate your UTXOs"); return false; } @@ -4991,7 +4991,7 @@ bool CWallet::CreateMintTransaction(const std::vector &vecSend, CWa // Limit size if (GetTransactionWeight(*wtxNew.tx) >= MAX_STANDARD_TX_WEIGHT) { - strFailReason = _("Transaction too large"); + strFailReason = _("Transaction is too large (size limit: 100Kb). Select less inputs or consolidate your UTXOs"); return false; } dPriority = wtxNew.tx->ComputePriority(dPriority, nBytes); @@ -5271,7 +5271,7 @@ bool CWallet::CreateLelantusMintTransactions( // Limit size CTransaction txConst(tx); if (GetTransactionWeight(txConst) >= MAX_STANDARD_TX_WEIGHT) { - strFailReason = _("Transaction too large"); + strFailReason = _("Transaction is too large (size limit: 100Kb). Select less inputs or consolidate your UTXOs"); return false; } dPriority = txConst.ComputePriority(dPriority, nBytes);