Multibroadcast transactions

This commit is contained in:
tobtoht 2021-03-16 04:17:01 +01:00
parent 858861436b
commit fcf764e03c
No known key found for this signature in database
GPG key ID: 1CADD27F41F45C3C
13 changed files with 260 additions and 206 deletions

View file

@ -265,6 +265,35 @@ void AppContext::onAmountPrecisionChanged(int precision) {
model->amountPrecision = precision; model->amountPrecision = precision;
} }
void AppContext::commitTransaction(PendingTransaction *tx) {
// Nodes - even well-connected, properly configured ones - consistently fail to relay transactions
// To mitigate transactions failing we just send the transaction to every node we know about over Tor
if (config()->get(Config::multiBroadcast).toBool()) {
this->onMultiBroadcast(tx);
}
this->currentWallet->commitTransactionAsync(tx);
}
void AppContext::onMultiBroadcast(PendingTransaction *tx) {
UtilsNetworking *net = new UtilsNetworking(this->network, this);
DaemonRpc *rpc = new DaemonRpc(this, net, "");
int count = tx->txCount();
for (int i = 0; i < count; i++) {
QString txData = tx->signedTxToHex(i);
for (const auto& node: this->nodes->websocketNodes()) {
if (!node.online) continue;
QString address = node.as_url();
qDebug() << QString("Relaying to: %1").arg(address);
rpc->setDaemonAddress(address);
rpc->sendRawTransaction(txData);
}
}
}
void AppContext::onWalletOpened(Wallet *wallet) { void AppContext::onWalletOpened(Wallet *wallet) {
auto state = wallet->status(); auto state = wallet->status();
if (state != Wallet::Status_Ok) { if (state != Wallet::Status_Ok) {

View file

@ -18,6 +18,7 @@
#include "utils/wsclient.h" #include "utils/wsclient.h"
#include "utils/txfiathistory.h" #include "utils/txfiathistory.h"
#include "utils/FeatherSeed.h" #include "utils/FeatherSeed.h"
#include "utils/daemonrpc.h"
#include "widgets/RedditPost.h" #include "widgets/RedditPost.h"
#include "widgets/CCSEntry.h" #include "widgets/CCSEntry.h"
#include "utils/RestoreHeightLookup.h" #include "utils/RestoreHeightLookup.h"
@ -66,6 +67,7 @@ public:
WSClient *ws; WSClient *ws;
XmRig *XMRig; XmRig *XMRig;
Nodes *nodes; Nodes *nodes;
DaemonRpc *daemonRpc;
static Prices *prices; static Prices *prices;
static WalletKeysFilesModel *wallets; static WalletKeysFilesModel *wallets;
static double balance; static double balance;
@ -81,6 +83,7 @@ public:
void createWallet(FeatherSeed seed, const QString &path, const QString &password, const QString &seedOffset = ""); void createWallet(FeatherSeed seed, const QString &path, const QString &password, const QString &seedOffset = "");
void createWalletFromKeys(const QString &path, const QString &password, const QString &address, const QString &viewkey, const QString &spendkey, quint64 restoreHeight, bool deterministic = false); void createWalletFromKeys(const QString &path, const QString &password, const QString &address, const QString &viewkey, const QString &spendkey, quint64 restoreHeight, bool deterministic = false);
void createWalletFinish(const QString &password); void createWalletFinish(const QString &password);
void commitTransaction(PendingTransaction *tx);
void syncStatusUpdated(quint64 height, quint64 target); void syncStatusUpdated(quint64 height, quint64 target);
void updateBalance(); void updateBalance();
void initTor(); void initTor();
@ -105,6 +108,7 @@ public slots:
void onSetRestoreHeight(quint64 height); void onSetRestoreHeight(quint64 height);
void onPreferredFiatCurrencyChanged(const QString &symbol); void onPreferredFiatCurrencyChanged(const QString &symbol);
void onAmountPrecisionChanged(int precision); void onAmountPrecisionChanged(int precision);
void onMultiBroadcast(PendingTransaction *tx);
private slots: private slots:
void onWSNodes(const QJsonArray &nodes); void onWSNodes(const QJsonArray &nodes);

View file

@ -172,7 +172,7 @@ void TxConfAdvDialog::signedQrCode() {
void TxConfAdvDialog::broadcastTransaction() { void TxConfAdvDialog::broadcastTransaction() {
if (m_tx == nullptr) return; if (m_tx == nullptr) return;
m_ctx->currentWallet->commitTransactionAsync(m_tx); m_ctx->commitTransaction(m_tx);
QDialog::accept(); QDialog::accept();
} }

View file

@ -1286,11 +1286,10 @@ Wallet::~Wallet()
//Monero::WalletManagerFactory::getWalletManager()->closeWallet(m_walletImpl); //Monero::WalletManagerFactory::getWalletManager()->closeWallet(m_walletImpl);
if(status() == Status_Critical) if(status() == Status_Critical)
qDebug("Not storing wallet cache"); qDebug("Not storing wallet cache");
// Don't store on wallet close for now else if( m_walletImpl->store(""))
// else if( m_walletImpl->store("")) qDebug("Wallet cache stored successfully");
// qDebug("Wallet cache stored successfully"); else
// else qDebug("Error storing wallet cache");
// qDebug("Error storing wallet cache");
delete m_walletImpl; delete m_walletImpl;
m_walletImpl = NULL; m_walletImpl = NULL;
delete m_walletListener; delete m_walletListener;

View file

@ -751,7 +751,7 @@ void MainWindow::onCreateTransactionSuccess(PendingTransaction *tx, const QVecto
break; break;
} }
case QDialog::Accepted: case QDialog::Accepted:
m_ctx->currentWallet->commitTransactionAsync(tx); m_ctx->commitTransaction(tx);
break; break;
} }

View file

@ -20,6 +20,9 @@ Settings::Settings(QWidget *parent) :
ui->tabWidget->setTabVisible(4, false); ui->tabWidget->setTabVisible(4, false);
connect(ui->btnCopyToClipboard, &QPushButton::clicked, this, &Settings::copyToClipboard); connect(ui->btnCopyToClipboard, &QPushButton::clicked, this, &Settings::copyToClipboard);
connect(ui->checkBox_multiBroadcast, &QCheckBox::toggled, [](bool toggled){
config()->set(Config::multiBroadcast, toggled);
});
connect(ui->checkBox_externalLink, &QCheckBox::clicked, this, &Settings::checkboxExternalLinkWarn); connect(ui->checkBox_externalLink, &QCheckBox::clicked, this, &Settings::checkboxExternalLinkWarn);
connect(ui->checkBox_hideBalance, &QCheckBox::toggled, [this](bool toggled){ connect(ui->checkBox_hideBalance, &QCheckBox::toggled, [this](bool toggled){
config()->set(Config::hideBalance, toggled); config()->set(Config::hideBalance, toggled);
@ -34,6 +37,7 @@ Settings::Settings(QWidget *parent) :
connect(ui->nodeWidget, &NodeWidget::connectToNode, m_ctx->nodes, QOverload<const FeatherNode&>::of(&Nodes::connectToNode)); connect(ui->nodeWidget, &NodeWidget::connectToNode, m_ctx->nodes, QOverload<const FeatherNode&>::of(&Nodes::connectToNode));
// setup checkboxes // setup checkboxes
ui->checkBox_multiBroadcast->setChecked(config()->get(Config::multiBroadcast).toBool());
ui->checkBox_externalLink->setChecked(config()->get(Config::warnOnExternalLink).toBool()); ui->checkBox_externalLink->setChecked(config()->get(Config::warnOnExternalLink).toBool());
ui->checkBox_hideBalance->setChecked(config()->get(Config::hideBalance).toBool()); ui->checkBox_hideBalance->setChecked(config()->get(Config::hideBalance).toBool());

View file

@ -23,7 +23,9 @@
<attribute name="title"> <attribute name="title">
<string>General</string> <string>General</string>
</attribute> </attribute>
<layout class="QFormLayout" name="formLayout"> <layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<layout class="QFormLayout" name="formLayout_3">
<item row="0" column="0"> <item row="0" column="0">
<widget class="QLabel" name="label"> <widget class="QLabel" name="label">
<property name="text"> <property name="text">
@ -161,20 +163,6 @@
</item> </item>
</widget> </widget>
</item> </item>
<item row="7" column="0">
<widget class="QCheckBox" name="checkBox_externalLink">
<property name="text">
<string>Warn before opening external link</string>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QCheckBox" name="checkBox_hideBalance">
<property name="text">
<string>Hide balance</string>
</property>
</widget>
</item>
<item row="3" column="0"> <item row="3" column="0">
<widget class="QLabel" name="label_8"> <widget class="QLabel" name="label_8">
<property name="text"> <property name="text">
@ -232,6 +220,29 @@
<widget class="QComboBox" name="comboBox_timeFormat"/> <widget class="QComboBox" name="comboBox_timeFormat"/>
</item> </item>
</layout> </layout>
</item>
<item>
<widget class="QCheckBox" name="checkBox_multiBroadcast">
<property name="text">
<string>Multibroadcast outgoing transactions</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBox_externalLink">
<property name="text">
<string>Warn before opening external link</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBox_hideBalance">
<property name="text">
<string>Hide balance</string>
</property>
</widget>
</item>
</layout>
</widget> </widget>
<widget class="QWidget" name="tab_node"> <widget class="QWidget" name="tab_node">
<attribute name="title"> <attribute name="title">

View file

@ -50,7 +50,8 @@ static const QHash<Config::ConfigKey, ConfigDirective> configStrings = {
{Config::GUI_HistoryViewState, {QS("GUI_HistoryViewState"), {}}}, {Config::GUI_HistoryViewState, {QS("GUI_HistoryViewState"), {}}},
{Config::amountPrecision, {QS("amountPrecision"), 4}}, {Config::amountPrecision, {QS("amountPrecision"), 4}},
{Config::dateFormat, {QS("dateFormat"), "yyyy-MM-dd"}}, {Config::dateFormat, {QS("dateFormat"), "yyyy-MM-dd"}},
{Config::timeFormat, {QS("timeFormat"), "HH:mm"}} {Config::timeFormat, {QS("timeFormat"), "HH:mm"}},
{Config::multiBroadcast, {QS("multiBroadcast"), true}}
}; };

View file

@ -54,7 +54,8 @@ public:
amountPrecision, amountPrecision,
portableMode, portableMode,
dateFormat, dateFormat,
timeFormat timeFormat,
multiBroadcast
}; };
~Config() override; ~Config() override;

View file

@ -376,6 +376,10 @@ QList<FeatherNode> Nodes::customNodes() {
return m_customNodes; return m_customNodes;
} }
QList<FeatherNode> Nodes::websocketNodes() {
return m_websocketNodes;
}
FeatherNode Nodes::connection() { FeatherNode Nodes::connection() {
return m_connection; return m_connection;
} }

View file

@ -69,8 +69,8 @@ struct FeatherNode {
return QString("%1%2").arg(auth).arg(this->address); return QString("%1%2").arg(auth).arg(this->address);
} }
QString as_url() { QString as_url() const {
return QString("%1://%2/get_info").arg(this->isHttps ? "https": "http",this->full); return QString("%1://%2").arg(this->isHttps ? "https": "http",this->full);
} }
bool operator == (const FeatherNode &other) const { bool operator == (const FeatherNode &other) const {
@ -88,7 +88,9 @@ public:
NodeSource source(); NodeSource source();
FeatherNode connection(); FeatherNode connection();
QList<FeatherNode> customNodes(); QList<FeatherNode> customNodes();
QList<FeatherNode> websocketNodes();
NodeModel *modelWebsocket; NodeModel *modelWebsocket;
NodeModel *modelCustom; NodeModel *modelCustom;

View file

@ -94,7 +94,7 @@ void NodeWidget::onContextConnect() {
void NodeWidget::onContextStatusURL() { void NodeWidget::onContextStatusURL() {
FeatherNode node = this->selectedNode(); FeatherNode node = this->selectedNode();
if (!node.full.isEmpty()) if (!node.full.isEmpty())
Utils::externalLinkWarning(this, node.as_url()); Utils::externalLinkWarning(this, QString("%1/get_info").arg(node.as_url()));
} }
void NodeWidget::onContextNodeCopy() { void NodeWidget::onContextNodeCopy() {

View file

@ -69,8 +69,7 @@ WalletWizard::WalletWizard(AppContext *ctx, WalletWizard::Page startPage, QWidge
}); });
connect(openWalletPage, &PageOpenWallet::openWallet, [=](const QString &path){ connect(openWalletPage, &PageOpenWallet::openWallet, [=](const QString &path){
const auto walletPassword = this->field("walletPassword").toString(); emit openWallet(path, "");
emit openWallet(path, walletPassword);
}); });
} }