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