mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-14 06:21:11 +00:00
[offchain] Support for sign & verify for crypto keys (#3023)
* Implement sign & verify. * Use phrases and password. * Sign & verify with authority keys. * Fix tests. * WiP * WiP * Allow the caller to decide on 'CryptoKind'. * Remove TODO. * Make seed private back. * Fix non-std build and bump version. * Use Into<u32> instead of asses. * Add missing typedef.
This commit is contained in:
committed by
Gavin Wood
parent
ed630e5eda
commit
e729dbabbe
@@ -21,7 +21,7 @@ use serde::{Serialize, de::DeserializeOwned};
|
||||
use crate::chain_spec::ChainSpec;
|
||||
use client_db;
|
||||
use client::{self, Client, runtime_api};
|
||||
use crate::{error, Service};
|
||||
use crate::{error, Service, AuthorityKeyProvider};
|
||||
use consensus_common::{import_queue::ImportQueue, SelectChain};
|
||||
use network::{self, OnDemand, FinalityProofProvider};
|
||||
use substrate_executor::{NativeExecutor, NativeExecutionDispatch};
|
||||
@@ -191,7 +191,7 @@ fn maintain_transaction_pool<Api, Backend, Block, Executor, PoolApi>(
|
||||
client: &Client<Backend, Executor, Block, Api>,
|
||||
transaction_pool: &TransactionPool<PoolApi>,
|
||||
) -> error::Result<()> where
|
||||
Block: BlockT<Hash = <Blake2Hasher as ::primitives::Hasher>::Out>,
|
||||
Block: BlockT<Hash = <Blake2Hasher as primitives::Hasher>::Out>,
|
||||
Backend: client::backend::Backend<Block, Blake2Hasher>,
|
||||
Client<Backend, Executor, Block, Api>: ProvideRuntimeApi,
|
||||
<Client<Backend, Executor, Block, Api> as ProvideRuntimeApi>::Api: runtime_api::TaggedTransactionQueue<Block>,
|
||||
@@ -231,6 +231,7 @@ pub trait OffchainWorker<C: Components> {
|
||||
offchain: &offchain::OffchainWorkers<
|
||||
ComponentClient<C>,
|
||||
ComponentOffchainStorage<C>,
|
||||
AuthorityKeyProvider,
|
||||
ComponentBlock<C>
|
||||
>,
|
||||
pool: &Arc<TransactionPool<C::TransactionPoolApi>>,
|
||||
@@ -246,6 +247,7 @@ impl<C: Components> OffchainWorker<Self> for C where
|
||||
offchain: &offchain::OffchainWorkers<
|
||||
ComponentClient<C>,
|
||||
ComponentOffchainStorage<C>,
|
||||
AuthorityKeyProvider,
|
||||
ComponentBlock<C>
|
||||
>,
|
||||
pool: &Arc<TransactionPool<C::TransactionPoolApi>>,
|
||||
|
||||
@@ -16,12 +16,14 @@
|
||||
|
||||
//! Service configuration.
|
||||
|
||||
use std::{path::PathBuf, net::SocketAddr};
|
||||
use transaction_pool;
|
||||
use crate::chain_spec::ChainSpec;
|
||||
pub use client::ExecutionStrategies;
|
||||
pub use client_db::PruningMode;
|
||||
pub use network::config::{ExtTransport, NetworkConfiguration, Roles};
|
||||
|
||||
use std::{path::PathBuf, net::SocketAddr};
|
||||
use transaction_pool;
|
||||
use crate::chain_spec::ChainSpec;
|
||||
use primitives::crypto::Protected;
|
||||
use runtime_primitives::BuildStorage;
|
||||
use serde::{Serialize, de::DeserializeOwned};
|
||||
use target_info::Target;
|
||||
@@ -86,7 +88,7 @@ pub struct Configuration<C, G: Serialize + DeserializeOwned + BuildStorage> {
|
||||
/// Disable GRANDPA when running in validator mode
|
||||
pub disable_grandpa: bool,
|
||||
/// Node keystore's password
|
||||
pub password: String,
|
||||
pub password: Protected<String>,
|
||||
}
|
||||
|
||||
impl<C: Default, G: Serialize + DeserializeOwned + BuildStorage> Configuration<C, G> {
|
||||
@@ -120,7 +122,7 @@ impl<C: Default, G: Serialize + DeserializeOwned + BuildStorage> Configuration<C
|
||||
offchain_worker: Default::default(),
|
||||
force_authoring: false,
|
||||
disable_grandpa: false,
|
||||
password: "".to_string(),
|
||||
password: "".to_string().into(),
|
||||
};
|
||||
configuration.network.boot_nodes = configuration.chain_spec.boot_nodes().to_vec();
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ use keystore::Store as Keystore;
|
||||
use network::NetworkState;
|
||||
use log::{info, warn, debug, error};
|
||||
use parity_codec::{Encode, Decode};
|
||||
use primitives::{Pair, Public, crypto::TypedKey, ed25519};
|
||||
use primitives::{Pair, ed25519, crypto};
|
||||
use runtime_primitives::generic::BlockId;
|
||||
use runtime_primitives::traits::{Header, NumberFor, SaturatedConversion};
|
||||
use substrate_executor::NativeExecutor;
|
||||
@@ -74,14 +74,14 @@ const DEFAULT_PROTOCOL_ID: &str = "sup";
|
||||
/// Substrate service.
|
||||
pub struct Service<Components: components::Components> {
|
||||
client: Arc<ComponentClient<Components>>,
|
||||
select_chain: Option<<Components as components::Components>::SelectChain>,
|
||||
select_chain: Option<Components::SelectChain>,
|
||||
network: Arc<components::NetworkService<Components>>,
|
||||
/// Sinks to propagate network status updates.
|
||||
network_status_sinks: Arc<Mutex<Vec<mpsc::UnboundedSender<(
|
||||
NetworkStatus<ComponentBlock<Components>>, NetworkState
|
||||
)>>>>,
|
||||
transaction_pool: Arc<TransactionPool<Components::TransactionPoolApi>>,
|
||||
keystore: Option<Keystore>,
|
||||
keystore: AuthorityKeyProvider,
|
||||
exit: ::exit_future::Exit,
|
||||
signal: Option<Signal>,
|
||||
/// Sender for futures that must be spawned as background tasks.
|
||||
@@ -101,6 +101,7 @@ pub struct Service<Components: components::Components> {
|
||||
_offchain_workers: Option<Arc<offchain::OffchainWorkers<
|
||||
ComponentClient<Components>,
|
||||
ComponentOffchainStorage<Components>,
|
||||
AuthorityKeyProvider,
|
||||
ComponentBlock<Components>>
|
||||
>>,
|
||||
}
|
||||
@@ -192,7 +193,7 @@ impl<Components: components::Components> Service<Components> {
|
||||
public_key = match keystore.contents::<ed25519::Public>()?.get(0) {
|
||||
Some(public_key) => public_key.to_string(),
|
||||
None => {
|
||||
let key: ed25519::Pair = keystore.generate(&config.password)?;
|
||||
let key: ed25519::Pair = keystore.generate(&config.password.as_ref())?;
|
||||
let public_key = key.public();
|
||||
info!("Generated a new keypair: {:?}", public_key);
|
||||
public_key.to_string()
|
||||
@@ -259,6 +260,12 @@ impl<Components: components::Components> Service<Components> {
|
||||
let network = network_mut.service().clone();
|
||||
let network_status_sinks = Arc::new(Mutex::new(Vec::new()));
|
||||
|
||||
let keystore_authority_key = AuthorityKeyProvider {
|
||||
roles: config.roles,
|
||||
password: config.password.clone(),
|
||||
keystore: keystore.map(Arc::new),
|
||||
};
|
||||
|
||||
#[allow(deprecated)]
|
||||
let offchain_storage = client.backend().offchain_storage();
|
||||
let offchain_workers = match (config.offchain_worker, offchain_storage) {
|
||||
@@ -266,6 +273,8 @@ impl<Components: components::Components> Service<Components> {
|
||||
Some(Arc::new(offchain::OffchainWorkers::new(
|
||||
client.clone(),
|
||||
db,
|
||||
keystore_authority_key.clone(),
|
||||
config.password.clone(),
|
||||
)))
|
||||
},
|
||||
(true, None) => {
|
||||
@@ -469,7 +478,7 @@ impl<Components: components::Components> Service<Components> {
|
||||
to_spawn_tx,
|
||||
to_spawn_rx,
|
||||
to_poll: Vec::new(),
|
||||
keystore,
|
||||
keystore: keystore_authority_key,
|
||||
config,
|
||||
exit,
|
||||
rpc_handlers,
|
||||
@@ -481,23 +490,10 @@ impl<Components: components::Components> Service<Components> {
|
||||
}
|
||||
|
||||
/// give the authority key, if we are an authority and have a key
|
||||
pub fn authority_key<TPair>(&self) -> Option<TPair>
|
||||
where
|
||||
TPair: Pair + TypedKey,
|
||||
<TPair as Pair>::Public: Public + TypedKey,
|
||||
{
|
||||
if self.config.roles != Roles::AUTHORITY { return None }
|
||||
if let Some(keystore) = &self.keystore {
|
||||
if let Ok(Some(Ok(key))) = keystore.contents::<TPair::Public>().map(|keys| keys.get(0)
|
||||
.map(|k| keystore.load::<TPair>(k, &self.config.password)))
|
||||
{
|
||||
Some(key)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
pub fn authority_key<TPair: Pair>(&self) -> Option<TPair> {
|
||||
use offchain::AuthorityKeyProvider;
|
||||
|
||||
self.keystore.authority_key()
|
||||
}
|
||||
|
||||
/// return a shared instance of Telemetry (if enabled)
|
||||
@@ -870,6 +866,39 @@ impl<C: Components> network::TransactionPool<ComponentExHash<C>, ComponentBlock<
|
||||
}
|
||||
}
|
||||
|
||||
/// A provider of current authority key.
|
||||
#[derive(Clone)]
|
||||
pub struct AuthorityKeyProvider {
|
||||
roles: Roles,
|
||||
keystore: Option<Arc<Keystore>>,
|
||||
password: crypto::Protected<String>,
|
||||
}
|
||||
|
||||
impl offchain::AuthorityKeyProvider for AuthorityKeyProvider {
|
||||
fn authority_key<TPair: Pair>(&self) -> Option<TPair> {
|
||||
if self.roles != Roles::AUTHORITY {
|
||||
return None
|
||||
}
|
||||
|
||||
let keystore = match self.keystore {
|
||||
Some(ref keystore) => keystore,
|
||||
None => return None
|
||||
};
|
||||
|
||||
let loaded_key = keystore
|
||||
.contents()
|
||||
.map(|keys| keys.get(0)
|
||||
.map(|k| keystore.load(k, self.password.as_ref()))
|
||||
);
|
||||
|
||||
if let Ok(Some(Ok(key))) = loaded_key {
|
||||
Some(key)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Constructs a service factory with the given name that implements the `ServiceFactory` trait.
|
||||
/// The required parameters are required to be given in the exact order. Some parameters are followed
|
||||
/// by `{}` blocks. These blocks are required and used to initialize the given parameter.
|
||||
|
||||
Reference in New Issue
Block a user