Keystore overhaul (final) (#13683)

* Introduce keystore specialized sign methods

* Get rid of 'AppKey::UntypedGeneric' associated type.

Untyped generics are accessible using associated types 'Generic' associated type.
I.e. <T as AppKey>::Public::Generic

* Get rid of 'CryptoTypePublicPair'

* Trivial fix

* Small refactory of local keystore implementations

* Remove 'crypto_id' method from 'Public'

* Trivial rename of 'AppKey' to 'AppCrypto'

* Remove unused import

* Improve docs

* Better signature related errors for authority-discovery

* Apply review suggestion

* Apply review suggestions

Co-authored-by: Koute <koute@users.noreply.github.com>

* Authority discoverty signing error revisited

* Signing error revisited for babe and aura as well

* Further cleanup

---------

Co-authored-by: Koute <koute@users.noreply.github.com>
This commit is contained in:
Davide Galassi
2023-03-24 14:46:02 +01:00
committed by GitHub
parent 370e71cb20
commit 40e1704e1c
27 changed files with 552 additions and 616 deletions
@@ -18,8 +18,6 @@
//! Authority discovery errors.
use sp_core::crypto::CryptoTypePublicPair;
/// AuthorityDiscovery Result.
pub type Result<T> = std::result::Result<T, Error>;
@@ -59,11 +57,8 @@ pub enum Error {
#[error("Failed to parse a libp2p key.")]
ParsingLibp2pIdentity(#[from] libp2p::identity::error::DecodingError),
#[error("Failed to sign using a specific public key.")]
MissingSignature(CryptoTypePublicPair),
#[error("Failed to sign using all public keys.")]
Signing,
#[error("Failed to sign: {0}.")]
CannotSign(String),
#[error("Failed to register Prometheus metric.")]
Prometheus(#[from] prometheus_endpoint::PrometheusError),
@@ -32,7 +32,7 @@ use std::{
use futures::{channel::mpsc, future, stream::Fuse, FutureExt, Stream, StreamExt};
use addr_cache::AddrCache;
use codec::Decode;
use codec::{Decode, Encode};
use ip_network::IpNetwork;
use libp2p::{
core::multiaddr,
@@ -43,6 +43,7 @@ use log::{debug, error, log_enabled};
use prometheus_endpoint::{register, Counter, CounterVec, Gauge, Opts, U64};
use prost::Message;
use rand::{seq::SliceRandom, thread_rng};
use sc_network::{
event::DhtEvent, KademliaKey, NetworkDHTProvider, NetworkSigner, NetworkStateInfo, Signature,
};
@@ -51,8 +52,7 @@ use sp_authority_discovery::{
AuthorityDiscoveryApi, AuthorityId, AuthorityPair, AuthoritySignature,
};
use sp_blockchain::HeaderBackend;
use sp_core::crypto::{key_types, CryptoTypePublicPair, Pair};
use sp_core::crypto::{key_types, ByteArray, Pair};
use sp_keystore::{Keystore, KeystorePtr};
use sp_runtime::traits::Block as BlockT;
@@ -127,7 +127,7 @@ pub struct Worker<Client, Network, Block, DhtEventStream> {
publish_if_changed_interval: ExpIncInterval,
/// List of keys onto which addresses have been published at the latest publication.
/// Used to check whether they have changed.
latest_published_keys: HashSet<CryptoTypePublicPair>,
latest_published_keys: HashSet<AuthorityId>,
/// Same value as in the configuration.
publish_non_global_ips: bool,
/// Same value as in the configuration.
@@ -339,7 +339,7 @@ where
let keys = Worker::<Client, Network, Block, DhtEventStream>::get_own_public_keys_within_authority_set(
key_store.clone(),
self.client.as_ref(),
).await?.into_iter().map(Into::into).collect::<HashSet<_>>();
).await?.into_iter().collect::<HashSet<_>>();
if only_if_changed && keys == self.latest_published_keys {
return Ok(())
@@ -654,7 +654,7 @@ fn sign_record_with_peer_id(
) -> Result<schema::PeerSignature> {
let signature = network
.sign_with_local_identity(serialized_record)
.map_err(|_| Error::Signing)?;
.map_err(|e| Error::CannotSign(format!("{} (network packet)", e)))?;
let public_key = signature.public_key.to_protobuf_encoding();
let signature = signature.bytes;
Ok(schema::PeerSignature { signature, public_key })
@@ -664,15 +664,20 @@ fn sign_record_with_authority_ids(
serialized_record: Vec<u8>,
peer_signature: Option<schema::PeerSignature>,
key_store: &dyn Keystore,
keys: Vec<CryptoTypePublicPair>,
keys: Vec<AuthorityId>,
) -> Result<Vec<(KademliaKey, Vec<u8>)>> {
let mut result = Vec::with_capacity(keys.len());
for key in keys.iter() {
let auth_signature = key_store
.sign_with(key_types::AUTHORITY_DISCOVERY, key, &serialized_record)
.map_err(|_| Error::Signing)?
.ok_or_else(|| Error::MissingSignature(key.clone()))?;
.sr25519_sign(key_types::AUTHORITY_DISCOVERY, key.as_ref(), &serialized_record)
.map_err(|e| Error::CannotSign(format!("{}. Key: {:?}", e, key)))?
.ok_or_else(|| {
Error::CannotSign(format!("Could not find key in keystore. Key: {:?}", key))
})?;
// Scale encode
let auth_signature = auth_signature.encode();
let signed_record = schema::SignedAuthorityRecord {
record: serialized_record.clone(),
@@ -681,7 +686,7 @@ fn sign_record_with_authority_ids(
}
.encode_to_vec();
result.push((hash_authority_id(&key.1), signed_record));
result.push((hash_authority_id(key.as_slice()), signed_record));
}
Ok(result)