Skip to content
55 changes: 38 additions & 17 deletions core/authority_discovery/publisher/address_publisher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ std::vector<uint8_t> 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",
Expand Down Expand Up @@ -118,32 +118,43 @@ 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(authorities);
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<std::chrono::nanoseconds> now =
std::chrono::system_clock::now().time_since_epoch();
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<std::pair<Buffer, Buffer>> audiEncode(
Expand All @@ -168,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));
Expand Down
56 changes: 48 additions & 8 deletions core/crypto/key_store/session_keys.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,16 +131,55 @@ namespace kagome::crypto {
std::equal_to{});
}

std::shared_ptr<Sr25519Keypair> SessionKeysImpl::getAudiKeyPair(
std::vector<Sr25519Keypair> SessionKeysImpl::getAudiKeyPairs(
const std::vector<primitives::AuthorityDiscoveryId> &authorities) {
if (auto res = find<Sr25519Provider>(audi_key_pair_,
KeyTypes::AUTHORITY_DISCOVERY,
store_->sr25519(),
authorities,
std::equal_to{})) {
return std::move(res->first);
if (not roles_.isAuthority()) {
return {};
}
return nullptr;

std::vector<Sr25519Keypair> 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(keypair_opt.value());
}
}
}

return result;
}

std::vector<Sr25519Keypair> SessionKeysImpl::getAudiKeyPairs() {
std::vector<Sr25519Keypair> keypairs;
auto keys_res =
store_->sr25519().getPublicKeys(KeyTypes::AUTHORITY_DISCOVERY);
if (not keys_res || keys_res.value().empty()) {
return keypairs;
}

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 keypairs;
}

SessionKeys::KeypairWithIndexOpt<EcdsaKeypair>
Expand All @@ -152,4 +191,5 @@ namespace kagome::crypto {
authorities,
std::equal_to{});
}

} // namespace kagome::crypto
14 changes: 11 additions & 3 deletions core/crypto/key_store/session_keys.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,17 @@ namespace kagome::crypto {
const std::vector<Sr25519PublicKey> &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<Sr25519Keypair> getAudiKeyPair(
virtual std::vector<Sr25519Keypair> getAudiKeyPairs(
const std::vector<primitives::AuthorityDiscoveryId> &authorities) = 0;

/**
* @return all AUDI session key pairs from storage without checking
*/
virtual std::vector<Sr25519Keypair> getAudiKeyPairs() = 0;

/**
* @return current BEEF session key pair
*/
Expand Down Expand Up @@ -126,10 +132,12 @@ namespace kagome::crypto {
KeypairWithIndexOpt<Sr25519Keypair> getParaKeyPair(
const std::vector<Sr25519PublicKey> &authorities) override;

std::shared_ptr<Sr25519Keypair> getAudiKeyPair(
std::vector<Sr25519Keypair> getAudiKeyPairs(
const std::vector<primitives::AuthorityDiscoveryId> &authorities)
override;

std::vector<Sr25519Keypair> getAudiKeyPairs() override;

KeypairWithIndexOpt<EcdsaKeypair> getBeefKeyPair(
const std::vector<EcdsaPublicKey> &authorities) override;
};
Expand Down
13 changes: 9 additions & 4 deletions core/parachain/validator/signer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
}
}
Expand Down
6 changes: 4 additions & 2 deletions test/mock/core/crypto/session_keys_mock.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,13 @@ namespace kagome::crypto {
(const std::vector<Sr25519PublicKey> &),
(override));

MOCK_METHOD(std::shared_ptr<Sr25519Keypair>,
getAudiKeyPair,
MOCK_METHOD(std::vector<Sr25519Keypair>,
getAudiKeyPairs,
(const std::vector<primitives::AuthorityDiscoveryId> &),
(override));

MOCK_METHOD(std::vector<Sr25519Keypair>, getAudiKeyPairs, (), (override));

MOCK_METHOD(KeypairWithIndexOpt<EcdsaKeypair>,
getBeefKeyPair,
(const std::vector<EcdsaPublicKey> &),
Expand Down
Loading