From 6d79da0e2f3d537bf9fa6e6b00dfea2bfc183189 Mon Sep 17 00:00:00 2001 From: acetone <63557806+freeacetone@users.noreply.github.com> Date: Mon, 22 Jun 2026 21:57:06 +0300 Subject: [PATCH] refresh offline transient on destination service --- libi2pd/Destination.cpp | 22 +++++++++++++--------- libi2pd/Identity.cpp | 11 +++++++++++ libi2pd/Identity.h | 1 + 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index eca0ddd1..45cc400d 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -1169,17 +1169,21 @@ namespace client void ClientDestination::UpdateOfflineSignature (const i2p::data::PrivateKeys& keys) { - // Adopt a newer offline transient of the same identity in place: swap keys and - // republish the LeaseSet, keeping tunnels and streams (unlike SetPrivateKeys). - if (!keys.IsOfflineSignature () || !m_Keys.IsOfflineSignature ()) return; - if (keys.GetPublic ()->GetIdentHash () != GetIdentHash ()) return; - const uint32_t expires = bufbe32toh (keys.GetOfflineSignature ().data ()); - if (expires <= bufbe32toh (m_Keys.GetOfflineSignature ().data ())) return; // only move forward - LogPrint (eLogInfo, "Destination: Refreshing offline signature for ", - GetIdentHash ().ToBase32 (), ", transient expires ", expires); + // Adopt a newer offline transient of the same identity in place, on the + // destination's service so it stays single-threaded with LeaseSet and stream + // signing. Only the transient is refreshed, the identity is unchanged. + if (!keys.IsOfflineSignature ()) return; boost::asio::post (GetService (), [s = GetSharedFromThis (), keys]() { - s->m_Keys = keys; + if (!s->m_Keys.IsOfflineSignature ()) return; + if (keys.GetPublic ()->GetIdentHash () != s->GetIdentHash ()) return; + const auto& next = keys.GetOfflineSignature (); + const auto& cur = s->m_Keys.GetOfflineSignature (); + if (next == cur) return; // same transient + if (bufbe32toh (next.data ()) < bufbe32toh (cur.data ())) return; // do not shorten validity + LogPrint (eLogInfo, "Destination: Refreshing offline signature for ", + s->GetIdentHash ().ToBase32 (), ", transient expires ", bufbe32toh (next.data ())); + s->m_Keys.UpdateOfflineSignature (keys); s->UpdateLeaseSet (); }); } diff --git a/libi2pd/Identity.cpp b/libi2pd/Identity.cpp index 57b12e91..becd4439 100644 --- a/libi2pd/Identity.cpp +++ b/libi2pd/Identity.cpp @@ -643,6 +643,17 @@ namespace data m_Signer->Sign (buf, len, signature); } + void PrivateKeys::UpdateOfflineSignature (const PrivateKeys& other) + { + // same identity (m_Public): refresh only the transient material and the signer + m_SigningPrivateKey = other.m_SigningPrivateKey; + m_OfflineSignature = other.m_OfflineSignature; + m_TransientSignatureLen = other.m_TransientSignatureLen; + m_TransientSigningPrivateKeyLen = other.m_TransientSigningPrivateKeyLen; + m_Signer = nullptr; + CreateSigner (); + } + void PrivateKeys::CreateSigner () const { if (IsOfflineSignature ()) diff --git a/libi2pd/Identity.h b/libi2pd/Identity.h index f4445807..d3415768 100644 --- a/libi2pd/Identity.h +++ b/libi2pd/Identity.h @@ -191,6 +191,7 @@ namespace data // offline keys PrivateKeys CreateOfflineKeys (SigningKeyType type, uint32_t expires) const; const std::vector& GetOfflineSignature () const { return m_OfflineSignature; }; + void UpdateOfflineSignature (const PrivateKeys& other); // refresh transient material, keep identity private: