mirror of
https://github.com/logos-blockchain/lez-programs.git
synced 2026-07-25 16:23:16 +00:00
fix(amm): back off network identity probes
This commit is contained in:
parent
57c3712bb8
commit
df5152c5ee
@ -1,5 +1,8 @@
|
|||||||
#include "ActiveNetwork.h"
|
#include "ActiveNetwork.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <iterator>
|
||||||
|
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QJsonArray>
|
#include <QJsonArray>
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
@ -30,6 +33,7 @@ bool ActiveNetwork::load()
|
|||||||
m_network = {};
|
m_network = {};
|
||||||
m_network.status = QStringLiteral("config_missing");
|
m_network.status = QStringLiteral("config_missing");
|
||||||
m_expectedIdentity.clear();
|
m_expectedIdentity.clear();
|
||||||
|
m_failedIdentityProbes = 0;
|
||||||
|
|
||||||
const QByteArray selected = qgetenv(NETWORK_ENV);
|
const QByteArray selected = qgetenv(NETWORK_ENV);
|
||||||
m_network.id = selected.isEmpty()
|
m_network.id = selected.isEmpty()
|
||||||
@ -93,8 +97,28 @@ bool ActiveNetwork::needsIdentityProbe() const
|
|||||||
|| m_network.status == QStringLiteral("network_unknown");
|
|| m_network.status == QStringLiteral("network_unknown");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ActiveNetwork::identityRetryDelayMs() const
|
||||||
|
{
|
||||||
|
static constexpr int retryDelays[] = {
|
||||||
|
1000,
|
||||||
|
2000,
|
||||||
|
4000,
|
||||||
|
8000,
|
||||||
|
16000,
|
||||||
|
30000,
|
||||||
|
};
|
||||||
|
if (m_failedIdentityProbes <= 0
|
||||||
|
|| m_network.status != QStringLiteral("network_unknown")) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
const int index = (std::min)(m_failedIdentityProbes,
|
||||||
|
static_cast<int>(std::size(retryDelays))) - 1;
|
||||||
|
return retryDelays[index];
|
||||||
|
}
|
||||||
|
|
||||||
void ActiveNetwork::sequencerChanged(bool available)
|
void ActiveNetwork::sequencerChanged(bool available)
|
||||||
{
|
{
|
||||||
|
m_failedIdentityProbes = 0;
|
||||||
if (isConfigured())
|
if (isConfigured())
|
||||||
clearIdentity(available ? QStringLiteral("loading") : QStringLiteral("network_unknown"));
|
clearIdentity(available ? QStringLiteral("loading") : QStringLiteral("network_unknown"));
|
||||||
}
|
}
|
||||||
@ -103,6 +127,8 @@ void ActiveNetwork::reachabilityChanged(bool reachable, bool wasReachable)
|
|||||||
{
|
{
|
||||||
if (!isConfigured())
|
if (!isConfigured())
|
||||||
return;
|
return;
|
||||||
|
if (!reachable || !wasReachable)
|
||||||
|
m_failedIdentityProbes = 0;
|
||||||
if (!reachable)
|
if (!reachable)
|
||||||
clearIdentity(QStringLiteral("network_unknown"));
|
clearIdentity(QStringLiteral("network_unknown"));
|
||||||
else if (!wasReachable)
|
else if (!wasReachable)
|
||||||
@ -118,10 +144,13 @@ void ActiveNetwork::beginIdentityProbe()
|
|||||||
void ActiveNetwork::finishIdentityProbe(const QString& identity)
|
void ActiveNetwork::finishIdentityProbe(const QString& identity)
|
||||||
{
|
{
|
||||||
if (identity.isEmpty()) {
|
if (identity.isEmpty()) {
|
||||||
|
m_failedIdentityProbes = (std::min)(m_failedIdentityProbes + 1, 6);
|
||||||
clearIdentity(QStringLiteral("network_unknown"));
|
clearIdentity(QStringLiteral("network_unknown"));
|
||||||
} else if (identity != m_expectedIdentity) {
|
} else if (identity != m_expectedIdentity) {
|
||||||
|
m_failedIdentityProbes = 0;
|
||||||
clearIdentity(QStringLiteral("network_mismatch"));
|
clearIdentity(QStringLiteral("network_mismatch"));
|
||||||
} else {
|
} else {
|
||||||
|
m_failedIdentityProbes = 0;
|
||||||
m_network.status = QStringLiteral("ready");
|
m_network.status = QStringLiteral("ready");
|
||||||
m_network.fingerprint = (isDevnet() ? QStringLiteral("channel:")
|
m_network.fingerprint = (isDevnet() ? QStringLiteral("channel:")
|
||||||
: QStringLiteral("block10:"))
|
: QStringLiteral("block10:"))
|
||||||
|
|||||||
@ -19,6 +19,7 @@ public:
|
|||||||
bool isConfigured() const;
|
bool isConfigured() const;
|
||||||
bool isDevnet() const;
|
bool isDevnet() const;
|
||||||
bool needsIdentityProbe() const;
|
bool needsIdentityProbe() const;
|
||||||
|
int identityRetryDelayMs() const;
|
||||||
ActiveNetworkSnapshot snapshot() const { return m_network; }
|
ActiveNetworkSnapshot snapshot() const { return m_network; }
|
||||||
|
|
||||||
void sequencerChanged(bool available);
|
void sequencerChanged(bool available);
|
||||||
@ -33,4 +34,5 @@ private:
|
|||||||
|
|
||||||
ActiveNetworkSnapshot m_network;
|
ActiveNetworkSnapshot m_network;
|
||||||
QString m_expectedIdentity;
|
QString m_expectedIdentity;
|
||||||
|
int m_failedIdentityProbes = 0;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -69,13 +69,17 @@ AmmUiBackend::AmmUiBackend(LogosAPI* logosAPI, QObject* parent)
|
|||||||
m_newPosition(std::make_unique<NewPositionRuntime>(
|
m_newPosition(std::make_unique<NewPositionRuntime>(
|
||||||
m_wallet.get(), m_ammClient.get(), m_sequencer.get())),
|
m_wallet.get(), m_ammClient.get(), m_sequencer.get())),
|
||||||
m_net(new QNetworkAccessManager(this)),
|
m_net(new QNetworkAccessManager(this)),
|
||||||
m_transactionTimer(new QTimer(this))
|
m_transactionTimer(new QTimer(this)),
|
||||||
|
m_identityRetryTimer(new QTimer(this))
|
||||||
{
|
{
|
||||||
setNewPositionQuoteResult({});
|
setNewPositionQuoteResult({});
|
||||||
setNewPositionSubmitResult({});
|
setNewPositionSubmitResult({});
|
||||||
m_transactionTimer->setInterval(5000);
|
m_transactionTimer->setInterval(5000);
|
||||||
connect(m_transactionTimer, &QTimer::timeout,
|
connect(m_transactionTimer, &QTimer::timeout,
|
||||||
this, &AmmUiBackend::pollTransactions);
|
this, &AmmUiBackend::pollTransactions);
|
||||||
|
m_identityRetryTimer->setSingleShot(true);
|
||||||
|
connect(m_identityRetryTimer, &QTimer::timeout,
|
||||||
|
this, &AmmUiBackend::probeNetworkIdentity);
|
||||||
m_network.load();
|
m_network.load();
|
||||||
|
|
||||||
connect(m_walletController.get(), &WalletController::stateChanged,
|
connect(m_walletController.get(), &WalletController::stateChanged,
|
||||||
@ -157,8 +161,6 @@ void AmmUiBackend::refreshNewPositionContext(QVariantMap request)
|
|||||||
else {
|
else {
|
||||||
request = m_newPositionHints;
|
request = m_newPositionHints;
|
||||||
}
|
}
|
||||||
if (m_network.status() == QStringLiteral("network_unknown"))
|
|
||||||
probeNetworkIdentity();
|
|
||||||
const quint64 generation = ++m_contextGeneration;
|
const quint64 generation = ++m_contextGeneration;
|
||||||
m_newPosition->contextAsync(
|
m_newPosition->contextAsync(
|
||||||
request, m_network.snapshot(), isWalletOpen(), refreshWalletAccounts,
|
request, m_network.snapshot(), isWalletOpen(), refreshWalletAccounts,
|
||||||
@ -222,11 +224,13 @@ void AmmUiBackend::syncWalletState()
|
|||||||
|
|
||||||
const bool addressChanged = previousAddress != state.sequencerAddress;
|
const bool addressChanged = previousAddress != state.sequencerAddress;
|
||||||
if (addressChanged) {
|
if (addressChanged) {
|
||||||
|
m_identityRetryTimer->stop();
|
||||||
m_pendingTransactions.clear();
|
m_pendingTransactions.clear();
|
||||||
m_transactionTimer->stop();
|
m_transactionTimer->stop();
|
||||||
m_network.sequencerChanged(!state.sequencerAddress.isEmpty());
|
m_network.sequencerChanged(!state.sequencerAddress.isEmpty());
|
||||||
}
|
}
|
||||||
if (addressChanged || wasReachable != state.sequencerReachable) {
|
if (addressChanged || wasReachable != state.sequencerReachable) {
|
||||||
|
m_identityRetryTimer->stop();
|
||||||
m_network.reachabilityChanged(state.sequencerReachable, wasReachable);
|
m_network.reachabilityChanged(state.sequencerReachable, wasReachable);
|
||||||
}
|
}
|
||||||
if (walletWasOpen && !state.isWalletOpen)
|
if (walletWasOpen && !state.isWalletOpen)
|
||||||
@ -245,6 +249,7 @@ void AmmUiBackend::syncWalletState()
|
|||||||
void AmmUiBackend::probeNetworkIdentity()
|
void AmmUiBackend::probeNetworkIdentity()
|
||||||
{
|
{
|
||||||
if (m_identityProbeInFlight
|
if (m_identityProbeInFlight
|
||||||
|
|| m_identityRetryTimer->isActive()
|
||||||
|| !m_network.isConfigured()
|
|| !m_network.isConfigured()
|
||||||
|| sequencerAddr().isEmpty()) {
|
|| sequencerAddr().isEmpty()) {
|
||||||
return;
|
return;
|
||||||
@ -283,6 +288,9 @@ void AmmUiBackend::probeNetworkIdentity()
|
|||||||
? channelIdFromResponse(payload)
|
? channelIdFromResponse(payload)
|
||||||
: blockHashFromResponse(payload);
|
: blockHashFromResponse(payload);
|
||||||
m_network.finishIdentityProbe(actual);
|
m_network.finishIdentityProbe(actual);
|
||||||
|
const int retryDelay = m_network.identityRetryDelayMs();
|
||||||
|
if (retryDelay > 0)
|
||||||
|
m_identityRetryTimer->start(retryDelay);
|
||||||
reply->deleteLater();
|
reply->deleteLater();
|
||||||
publishNetworkContext();
|
publishNetworkContext();
|
||||||
});
|
});
|
||||||
|
|||||||
@ -74,6 +74,7 @@ private:
|
|||||||
|
|
||||||
QNetworkAccessManager* m_net;
|
QNetworkAccessManager* m_net;
|
||||||
QTimer* m_transactionTimer;
|
QTimer* m_transactionTimer;
|
||||||
|
QTimer* m_identityRetryTimer;
|
||||||
|
|
||||||
ActiveNetwork m_network;
|
ActiveNetwork m_network;
|
||||||
QVariantMap m_newPositionHints;
|
QVariantMap m_newPositionHints;
|
||||||
|
|||||||
@ -40,7 +40,24 @@ int main()
|
|||||||
"loaded network should await identity"))
|
"loaded network should await identity"))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
network.finishIdentityProbe({});
|
||||||
|
if (!expect(network.identityRetryDelayMs() == 1000,
|
||||||
|
"first failed identity probe should back off for one second"))
|
||||||
|
return 1;
|
||||||
|
network.finishIdentityProbe({});
|
||||||
|
if (!expect(network.identityRetryDelayMs() == 2000,
|
||||||
|
"repeated identity failures should increase the delay"))
|
||||||
|
return 1;
|
||||||
|
for (int attempt = 0; attempt < 8; ++attempt)
|
||||||
|
network.finishIdentityProbe({});
|
||||||
|
if (!expect(network.identityRetryDelayMs() == 30000,
|
||||||
|
"identity retry delay should cap at thirty seconds"))
|
||||||
|
return 1;
|
||||||
|
|
||||||
network.sequencerChanged(true);
|
network.sequencerChanged(true);
|
||||||
|
if (!expect(network.identityRetryDelayMs() == 0,
|
||||||
|
"sequencer changes should reset identity retry backoff"))
|
||||||
|
return 1;
|
||||||
network.finishIdentityProbe(QString(64, QLatin1Char('d')));
|
network.finishIdentityProbe(QString(64, QLatin1Char('d')));
|
||||||
if (!expect(network.status() == QStringLiteral("network_mismatch"),
|
if (!expect(network.status() == QStringLiteral("network_mismatch"),
|
||||||
"wrong identity should block the network"))
|
"wrong identity should block the network"))
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user