From aed1a8d886a88824a61b480af688d6f504f93dcc Mon Sep 17 00:00:00 2001 From: kamilsa Date: Wed, 18 Jun 2025 09:31:00 +0500 Subject: [PATCH 1/8] [fix] update max interval and enable audi timestamp --- core/authority_discovery/publisher/address_publisher.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/authority_discovery/publisher/address_publisher.cpp b/core/authority_discovery/publisher/address_publisher.cpp index db481bebf4..f0ffbb7371 100644 --- a/core/authority_discovery/publisher/address_publisher.cpp +++ b/core/authority_discovery/publisher/address_publisher.cpp @@ -27,10 +27,10 @@ std::vector pbEncodeVec(const T &v) { namespace kagome::authority_discovery { constexpr std::chrono::seconds kIntervalInitial{2}; - constexpr std::chrono::hours kIntervalMax{1}; + constexpr std::chrono::minutes kIntervalMax{5}; // TODO(kamilsa): #2351, remove this variable when resolved - constexpr bool kAudiDisableTimestamp = true; + constexpr bool kAudiDisableTimestamp = false; static const metrics::GaugeHelper metric_amount_addresses_last_published{ "kagome_authority_discovery_amount_external_addresses_last_published", From fab9b123b9371a5430085e2f1cdb58a7263d6ed0 Mon Sep 17 00:00:00 2001 From: kamilsa Date: Wed, 18 Jun 2025 09:39:26 +0500 Subject: [PATCH 2/8] [feat] add method to retrieve current AUDI session key pair --- core/crypto/key_store/session_keys.cpp | 17 +++++++++++++++++ core/crypto/key_store/session_keys.hpp | 9 +++++++++ 2 files changed, 26 insertions(+) diff --git a/core/crypto/key_store/session_keys.cpp b/core/crypto/key_store/session_keys.cpp index ffa5e6ea0e..d618ee2265 100644 --- a/core/crypto/key_store/session_keys.cpp +++ b/core/crypto/key_store/session_keys.cpp @@ -152,4 +152,21 @@ namespace kagome::crypto { authorities, std::equal_to{}); } + + std::optional SessionKeysImpl::getAudiKeyPair() { + auto keys_res = store_->sr25519().getPublicKeys(KeyTypes::AUTHORITY_DISCOVERY); + if (not keys_res || keys_res.value().empty()) { + return std::nullopt; + } + + // Get the first available AUTHORITY_DISCOVERY key + auto &pubkey = keys_res.value().front(); + auto keypair_opt = store_->sr25519().findKeypair(KeyTypes::AUTHORITY_DISCOVERY, pubkey); + + // Return the keypair if found, otherwise nullopt + if (keypair_opt) { + return keypair_opt.value(); + } + return std::nullopt; + } } // namespace kagome::crypto diff --git a/core/crypto/key_store/session_keys.hpp b/core/crypto/key_store/session_keys.hpp index 0e2d6d2249..dee8c66e50 100644 --- a/core/crypto/key_store/session_keys.hpp +++ b/core/crypto/key_store/session_keys.hpp @@ -78,6 +78,13 @@ namespace kagome::crypto { virtual std::shared_ptr getAudiKeyPair( const std::vector &authorities) = 0; + /** + * @return current AUDI session key pair from storage without checking + * authority list + * @note if there are multiple keys in storage, it returns the first one + */ + virtual std::optional getAudiKeyPair() = 0; + /** * @return current BEEF session key pair */ @@ -130,6 +137,8 @@ namespace kagome::crypto { const std::vector &authorities) override; + std::optional getAudiKeyPair() override; + KeypairWithIndexOpt getBeefKeyPair( const std::vector &authorities) override; }; From 369cbf2c50627f5041d025bcf8a07d528ff2e2a3 Mon Sep 17 00:00:00 2001 From: kamilsa Date: Wed, 18 Jun 2025 09:40:33 +0500 Subject: [PATCH 3/8] [feat] add mock method for retrieving AUDI key pair --- test/mock/core/crypto/session_keys_mock.hpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/mock/core/crypto/session_keys_mock.hpp b/test/mock/core/crypto/session_keys_mock.hpp index c3a7345c99..2b99917362 100644 --- a/test/mock/core/crypto/session_keys_mock.hpp +++ b/test/mock/core/crypto/session_keys_mock.hpp @@ -43,6 +43,11 @@ namespace kagome::crypto { (const std::vector &), (override)); + MOCK_METHOD(std::optional, + getAudiKeyPair, + (), + (override)); + MOCK_METHOD(KeypairWithIndexOpt, getBeefKeyPair, (const std::vector &), From 8c43aa9783a77fba1fd817c46b386bcc2a61c03e Mon Sep 17 00:00:00 2001 From: kamilsa Date: Wed, 18 Jun 2025 09:41:28 +0500 Subject: [PATCH 4/8] [fix] simplify AUDI key pair retrieval by removing unnecessary parameters --- core/authority_discovery/publisher/address_publisher.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/authority_discovery/publisher/address_publisher.cpp b/core/authority_discovery/publisher/address_publisher.cpp index f0ffbb7371..e34cd8f365 100644 --- a/core/authority_discovery/publisher/address_publisher.cpp +++ b/core/authority_discovery/publisher/address_publisher.cpp @@ -122,7 +122,7 @@ namespace kagome::authority_discovery { authorities, authority_discovery_api_->authorities(block_tree_->bestBlock().hash)); - auto audi_key = keys_->getAudiKeyPair(authorities); + auto audi_key = keys_->getAudiKeyPair(); if (not audi_key) { SL_WARN(log_, "No authority discovery key"); return outcome::success(); From 4b4274372c1d2924b6a9a08eda6a4fd259f1418e Mon Sep 17 00:00:00 2001 From: kamilsa Date: Wed, 18 Jun 2025 11:18:41 +0500 Subject: [PATCH 5/8] [feat] update AUDI key pair retrieval to return all key pairs instead of the first one --- core/crypto/key_store/session_keys.cpp | 25 ++++++++++++--------- core/crypto/key_store/session_keys.hpp | 8 +++---- test/mock/core/crypto/session_keys_mock.hpp | 5 +---- 3 files changed, 18 insertions(+), 20 deletions(-) diff --git a/core/crypto/key_store/session_keys.cpp b/core/crypto/key_store/session_keys.cpp index d618ee2265..cc8360e653 100644 --- a/core/crypto/key_store/session_keys.cpp +++ b/core/crypto/key_store/session_keys.cpp @@ -153,20 +153,23 @@ namespace kagome::crypto { std::equal_to{}); } - std::optional SessionKeysImpl::getAudiKeyPair() { - auto keys_res = store_->sr25519().getPublicKeys(KeyTypes::AUTHORITY_DISCOVERY); + std::vector SessionKeysImpl::getAudiKeyPairs() { + std::vector keypairs; + auto keys_res = + store_->sr25519().getPublicKeys(KeyTypes::AUTHORITY_DISCOVERY); if (not keys_res || keys_res.value().empty()) { - return std::nullopt; + return keypairs; } - // Get the first available AUTHORITY_DISCOVERY key - auto &pubkey = keys_res.value().front(); - auto keypair_opt = store_->sr25519().findKeypair(KeyTypes::AUTHORITY_DISCOVERY, pubkey); - - // Return the keypair if found, otherwise nullopt - if (keypair_opt) { - return keypair_opt.value(); + for (const auto &pubkey : keys_res.value()) { + auto keypair_opt = + store_->sr25519().findKeypair(KeyTypes::AUTHORITY_DISCOVERY, pubkey); + if (keypair_opt) { + keypairs.push_back(keypair_opt.value()); + } } - return std::nullopt; + + return keypairs; } + } // namespace kagome::crypto diff --git a/core/crypto/key_store/session_keys.hpp b/core/crypto/key_store/session_keys.hpp index dee8c66e50..e85b643bdd 100644 --- a/core/crypto/key_store/session_keys.hpp +++ b/core/crypto/key_store/session_keys.hpp @@ -79,11 +79,9 @@ namespace kagome::crypto { const std::vector &authorities) = 0; /** - * @return current AUDI session key pair from storage without checking - * authority list - * @note if there are multiple keys in storage, it returns the first one + * @return all AUDI session key pairs from storage without checking */ - virtual std::optional getAudiKeyPair() = 0; + virtual std::vector getAudiKeyPairs() = 0; /** * @return current BEEF session key pair @@ -137,7 +135,7 @@ namespace kagome::crypto { const std::vector &authorities) override; - std::optional getAudiKeyPair() override; + std::vector getAudiKeyPairs() override; KeypairWithIndexOpt getBeefKeyPair( const std::vector &authorities) override; diff --git a/test/mock/core/crypto/session_keys_mock.hpp b/test/mock/core/crypto/session_keys_mock.hpp index 2b99917362..d0d3480248 100644 --- a/test/mock/core/crypto/session_keys_mock.hpp +++ b/test/mock/core/crypto/session_keys_mock.hpp @@ -43,10 +43,7 @@ namespace kagome::crypto { (const std::vector &), (override)); - MOCK_METHOD(std::optional, - getAudiKeyPair, - (), - (override)); + MOCK_METHOD(std::vector, getAudiKeyPairs, (), (override)); MOCK_METHOD(KeypairWithIndexOpt, getBeefKeyPair, From e7b14243661b020c45eab0002308fcefc753cb83 Mon Sep 17 00:00:00 2001 From: kamilsa Date: Wed, 18 Jun 2025 12:16:16 +0500 Subject: [PATCH 6/8] [feat] update AUDI key retrieval to return all key pairs and handle empty cases --- .../publisher/address_publisher.cpp | 41 ++++++++------ core/crypto/key_store/session_keys.cpp | 54 +++++++++++++------ core/crypto/key_store/session_keys.hpp | 7 +-- core/parachain/validator/signer.cpp | 13 +++-- test/mock/core/crypto/session_keys_mock.hpp | 4 +- 5 files changed, 78 insertions(+), 41 deletions(-) diff --git a/core/authority_discovery/publisher/address_publisher.cpp b/core/authority_discovery/publisher/address_publisher.cpp index e34cd8f365..72b7c42a4c 100644 --- a/core/authority_discovery/publisher/address_publisher.cpp +++ b/core/authority_discovery/publisher/address_publisher.cpp @@ -118,14 +118,18 @@ namespace kagome::authority_discovery { return outcome::success(); } + // check if we have authority discovery keys in the keystore, that exist in + // authorities list OUTCOME_TRY( authorities, authority_discovery_api_->authorities(block_tree_->bestBlock().hash)); - auto audi_key = keys_->getAudiKeyPair(); - if (not audi_key) { - SL_WARN(log_, "No authority discovery key"); - return outcome::success(); + auto audi_keys = keys_->getAudiKeyPairs(authorities); + if (audi_keys.empty()) { + SL_WARN(log_, "No authority discovery keys found for authorities"); + // if we have no authority discovery keys, we publish anyway with all keys + // from the keystore + audi_keys = keys_->getAudiKeyPairs(); } std::optional now = @@ -133,17 +137,24 @@ namespace kagome::authority_discovery { if (kAudiDisableTimestamp) { now.reset(); } - OUTCOME_TRY(raw, - audiEncode(ed_crypto_provider_, - sr_crypto_provider_, - *libp2p_key_, - *libp2p_key_pb_, - peer_info, - *audi_key, - now)); - auto r = kademlia_->putValue(std::move(raw.first), std::move(raw.second)); - MetricDhtEventReceived::get().putResult(r.has_value()); - return r; + for (const auto &audi_key : audi_keys) { + OUTCOME_TRY(raw, + audiEncode(ed_crypto_provider_, + sr_crypto_provider_, + *libp2p_key_, + *libp2p_key_pb_, + peer_info, + audi_key, + now)); + auto r = kademlia_->putValue(std::move(raw.first), std::move(raw.second)); + MetricDhtEventReceived::get().putResult(r.has_value()); + if (not r) { + SL_ERROR(log_, "Failed to put value to kademlia: {}", r.error()); + return r.error(); + } + } + + return outcome::success(); } outcome::result> audiEncode( diff --git a/core/crypto/key_store/session_keys.cpp b/core/crypto/key_store/session_keys.cpp index cc8360e653..f51eda2ce8 100644 --- a/core/crypto/key_store/session_keys.cpp +++ b/core/crypto/key_store/session_keys.cpp @@ -131,26 +131,36 @@ namespace kagome::crypto { std::equal_to{}); } - std::shared_ptr SessionKeysImpl::getAudiKeyPair( + std::vector SessionKeysImpl::getAudiKeyPairs( const std::vector &authorities) { - if (auto res = find(audi_key_pair_, - KeyTypes::AUTHORITY_DISCOVERY, - store_->sr25519(), - authorities, - std::equal_to{})) { - return std::move(res->first); + if (not roles_.isAuthority()) { + return {}; } - return nullptr; - } - SessionKeys::KeypairWithIndexOpt - SessionKeysImpl::getBeefKeyPair( - const std::vector &authorities) { - return find(beef_key_pair_, - KeyTypes::BEEFY, - store_->ecdsa(), - authorities, - std::equal_to{}); + std::vector result; + auto keys_res = + store_->sr25519().getPublicKeys(KeyTypes::AUTHORITY_DISCOVERY); + if (not keys_res) { + return result; + } + + auto &keys = keys_res.value(); + for (auto &pubkey : keys) { + auto it = std::ranges::find_if( + authorities.begin(), authorities.end(), [&](const auto &authority) { + return pubkey == authority; + }); + + if (it != authorities.end()) { + auto keypair_opt = store_->sr25519().findKeypair( + KeyTypes::AUTHORITY_DISCOVERY, pubkey); + if (keypair_opt) { + result.push_back(std::move(keypair_opt.value())); + } + } + } + + return result; } std::vector SessionKeysImpl::getAudiKeyPairs() { @@ -172,4 +182,14 @@ namespace kagome::crypto { return keypairs; } + SessionKeys::KeypairWithIndexOpt + SessionKeysImpl::getBeefKeyPair( + const std::vector &authorities) { + return find(beef_key_pair_, + KeyTypes::BEEFY, + store_->ecdsa(), + authorities, + std::equal_to{}); + } + } // namespace kagome::crypto diff --git a/core/crypto/key_store/session_keys.hpp b/core/crypto/key_store/session_keys.hpp index e85b643bdd..5d671aa4a6 100644 --- a/core/crypto/key_store/session_keys.hpp +++ b/core/crypto/key_store/session_keys.hpp @@ -73,9 +73,10 @@ namespace kagome::crypto { const std::vector &authorities) = 0; /** - * @return current AUDI session key pair + * @return all AUDI session key pairs from storage that exist in authorities + * list */ - virtual std::shared_ptr getAudiKeyPair( + virtual std::vector getAudiKeyPairs( const std::vector &authorities) = 0; /** @@ -131,7 +132,7 @@ namespace kagome::crypto { KeypairWithIndexOpt getParaKeyPair( const std::vector &authorities) override; - std::shared_ptr getAudiKeyPair( + std::vector getAudiKeyPairs( const std::vector &authorities) override; diff --git a/core/parachain/validator/signer.cpp b/core/parachain/validator/signer.cpp index 82400c945b..e96ecfaf1f 100644 --- a/core/parachain/validator/signer.cpp +++ b/core/parachain/validator/signer.cpp @@ -77,11 +77,16 @@ namespace kagome::parachain { return std::nullopt; } - auto keys = session_keys_->getAudiKeyPair(session_info->discovery_keys); - if (keys != nullptr) { + auto keypairs = + session_keys_->getAudiKeyPairs(session_info->discovery_keys); + if (not keypairs.empty()) { + // Find the index of the first keypair that matches any discovery key. + for (ValidatorIndex i = 0; i < session_info->discovery_keys.size(); ++i) { - if (keys->public_key == session_info->discovery_keys[i]) { - return i; + for (const auto &keypair : keypairs) { + if (keypair.public_key == session_info->discovery_keys[i]) { + return i; + } } } } diff --git a/test/mock/core/crypto/session_keys_mock.hpp b/test/mock/core/crypto/session_keys_mock.hpp index d0d3480248..0f2effd9b3 100644 --- a/test/mock/core/crypto/session_keys_mock.hpp +++ b/test/mock/core/crypto/session_keys_mock.hpp @@ -38,8 +38,8 @@ namespace kagome::crypto { (const std::vector &), (override)); - MOCK_METHOD(std::shared_ptr, - getAudiKeyPair, + MOCK_METHOD(std::vector, + getAudiKeyPairs, (const std::vector &), (override)); From 9cff73186c2a43aa8b870f099325790df527476e Mon Sep 17 00:00:00 2001 From: kamilsa Date: Wed, 18 Jun 2025 12:24:18 +0500 Subject: [PATCH 7/8] feat: enhance address publishing with detailed logging of peer addresses --- .../publisher/address_publisher.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/core/authority_discovery/publisher/address_publisher.cpp b/core/authority_discovery/publisher/address_publisher.cpp index 72b7c42a4c..949db26936 100644 --- a/core/authority_discovery/publisher/address_publisher.cpp +++ b/core/authority_discovery/publisher/address_publisher.cpp @@ -179,9 +179,19 @@ namespace kagome::authority_discovery { } metric_amount_addresses_last_published->set(addresses.size()); ::authority_discovery_v3::AuthorityRecord record; + std::string peer_addresses; for (const auto &address : addresses) { PB_SPAN_ADD(record, addresses, address.getBytesAddress()); + if (not peer_addresses.empty()) { + peer_addresses.append(", "); + } + peer_addresses.append(address.getStringAddress()); } + auto log = log::createLogger("AddressPublisher", "authority_discovery"); + SL_DEBUG(log, + "Publishing authority discovery record for {} with addresses: {}", + audi_key.public_key.toHex(), + peer_addresses); if (now) { Timestamp time{now->count()}; OUTCOME_TRY(encoded_time, scale::encode(time)); From ffb498120040061901f0987c347d9dbed517699c Mon Sep 17 00:00:00 2001 From: kamilsa Date: Wed, 18 Jun 2025 13:21:38 +0500 Subject: [PATCH 8/8] fix: avoid moving keypair value --- core/crypto/key_store/session_keys.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/crypto/key_store/session_keys.cpp b/core/crypto/key_store/session_keys.cpp index f51eda2ce8..a6568bcc8a 100644 --- a/core/crypto/key_store/session_keys.cpp +++ b/core/crypto/key_store/session_keys.cpp @@ -155,7 +155,7 @@ namespace kagome::crypto { auto keypair_opt = store_->sr25519().findKeypair( KeyTypes::AUTHORITY_DISCOVERY, pubkey); if (keypair_opt) { - result.push_back(std::move(keypair_opt.value())); + result.push_back(keypair_opt.value()); } } }