mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 07:01:05 +00:00
Add a browser-utils crate (#4394)
* Squash * Fix keystore on wasm * Update utils/browser/Cargo.toml Co-Authored-By: Benjamin Kampmann <ben@gnunicorn.org> * export console functions * Use an Option<PathBuf> in keystore instead of cfg flags * Add a KeystoreConfig * Update libp2p * Bump kvdb-web version * Fix cli * Upgrade versions * Update wasm-bindgen stuff Co-authored-by: Benjamin Kampmann <ben.kampmann@googlemail.com>
This commit is contained in:
@@ -28,7 +28,7 @@ pub mod informant;
|
||||
|
||||
use sc_client_api::execution_extensions::ExecutionStrategies;
|
||||
use sc_service::{
|
||||
config::{Configuration, DatabaseConfig},
|
||||
config::{Configuration, DatabaseConfig, KeystoreConfig},
|
||||
ServiceBuilderCommand,
|
||||
RuntimeGenesis, ChainSpecExtension, PruningMode, ChainSpec,
|
||||
};
|
||||
@@ -754,20 +754,22 @@ fn fill_config_keystore_password<C, G, E>(
|
||||
config: &mut sc_service::Configuration<C, G, E>,
|
||||
cli: &RunCmd,
|
||||
) -> Result<(), String> {
|
||||
config.keystore_password = if cli.password_interactive {
|
||||
#[cfg(not(target_os = "unknown"))]
|
||||
{
|
||||
Some(input_keystore_password()?.into())
|
||||
}
|
||||
#[cfg(target_os = "unknown")]
|
||||
None
|
||||
} else if let Some(ref file) = cli.password_filename {
|
||||
Some(fs::read_to_string(file).map_err(|e| format!("{}", e))?.into())
|
||||
} else if let Some(ref password) = cli.password {
|
||||
Some(password.clone().into())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
if let KeystoreConfig::Path { password, .. } = &mut config.keystore {
|
||||
*password = if cli.password_interactive {
|
||||
#[cfg(not(target_os = "unknown"))]
|
||||
{
|
||||
Some(input_keystore_password()?.into())
|
||||
}
|
||||
#[cfg(target_os = "unknown")]
|
||||
None
|
||||
} else if let Some(ref file) = cli.password_filename {
|
||||
Some(fs::read_to_string(file).map_err(|e| format!("{}", e))?.into())
|
||||
} else if let Some(ref password) = cli.password {
|
||||
Some(password.clone().into())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -873,7 +875,11 @@ where
|
||||
)?
|
||||
}
|
||||
|
||||
config.keystore_path = cli.keystore_path.or_else(|| config.in_chain_config_dir(DEFAULT_KEYSTORE_CONFIG_PATH));
|
||||
let default_keystore_path = config.in_chain_config_dir(DEFAULT_KEYSTORE_CONFIG_PATH);
|
||||
|
||||
if let KeystoreConfig::Path { path, ..} = &mut config.keystore {
|
||||
*path = path.clone().or(default_keystore_path);
|
||||
}
|
||||
|
||||
// set sentry mode (i.e. act as an authority but **never** actively participate)
|
||||
config.sentry_mode = cli.sentry;
|
||||
|
||||
@@ -71,7 +71,7 @@ impl std::error::Error for Error {
|
||||
///
|
||||
/// Every pair that is being generated by a `seed`, will be placed in memory.
|
||||
pub struct Store {
|
||||
path: PathBuf,
|
||||
path: Option<PathBuf>,
|
||||
additional: HashMap<(KeyTypeId, Vec<u8>), Vec<u8>>,
|
||||
password: Option<Protected<String>>,
|
||||
}
|
||||
@@ -84,10 +84,19 @@ impl Store {
|
||||
let path = path.into();
|
||||
fs::create_dir_all(&path)?;
|
||||
|
||||
let instance = Self { path, additional: HashMap::new(), password };
|
||||
let instance = Self { path: Some(path), additional: HashMap::new(), password };
|
||||
Ok(Arc::new(RwLock::new(instance)))
|
||||
}
|
||||
|
||||
/// Create a new in-memory store.
|
||||
pub fn new_in_memory() -> KeyStorePtr {
|
||||
Arc::new(RwLock::new(Self {
|
||||
path: None,
|
||||
additional: HashMap::new(),
|
||||
password: None
|
||||
}))
|
||||
}
|
||||
|
||||
/// Get the public/private key pair for the given public key and key type.
|
||||
fn get_additional_pair<Pair: PairT>(
|
||||
&self,
|
||||
@@ -113,9 +122,11 @@ impl Store {
|
||||
///
|
||||
/// Places it into the file system store.
|
||||
fn insert_unknown(&self, key_type: KeyTypeId, suri: &str, public: &[u8]) -> Result<()> {
|
||||
let mut file = File::create(self.key_file_path(public, key_type)).map_err(Error::Io)?;
|
||||
serde_json::to_writer(&file, &suri).map_err(Error::Json)?;
|
||||
file.flush().map_err(Error::Io)?;
|
||||
if let Some(path) = self.key_file_path(public, key_type) {
|
||||
let mut file = File::create(path).map_err(Error::Io)?;
|
||||
serde_json::to_writer(&file, &suri).map_err(Error::Json)?;
|
||||
file.flush().map_err(Error::Io)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -144,9 +155,11 @@ impl Store {
|
||||
/// Places it into the file system store.
|
||||
pub fn generate_by_type<Pair: PairT>(&self, key_type: KeyTypeId) -> Result<Pair> {
|
||||
let (pair, phrase, _) = Pair::generate_with_phrase(self.password.as_ref().map(|p| &***p));
|
||||
let mut file = File::create(self.key_file_path(pair.public().as_slice(), key_type))?;
|
||||
serde_json::to_writer(&file, &phrase)?;
|
||||
file.flush()?;
|
||||
if let Some(path) = self.key_file_path(pair.public().as_slice(), key_type) {
|
||||
let mut file = File::create(path)?;
|
||||
serde_json::to_writer(&file, &phrase)?;
|
||||
file.flush()?;
|
||||
}
|
||||
Ok(pair)
|
||||
}
|
||||
|
||||
@@ -186,7 +199,8 @@ impl Store {
|
||||
return Ok(pair)
|
||||
}
|
||||
|
||||
let path = self.key_file_path(public.as_slice(), key_type);
|
||||
let path = self.key_file_path(public.as_slice(), key_type)
|
||||
.ok_or_else(|| Error::Unavailable)?;
|
||||
let file = File::open(path)?;
|
||||
|
||||
let phrase: String = serde_json::from_reader(&file)?;
|
||||
@@ -219,19 +233,21 @@ impl Store {
|
||||
})
|
||||
.collect();
|
||||
|
||||
for entry in fs::read_dir(&self.path)? {
|
||||
let entry = entry?;
|
||||
let path = entry.path();
|
||||
if let Some(path) = &self.path {
|
||||
for entry in fs::read_dir(&path)? {
|
||||
let entry = entry?;
|
||||
let path = entry.path();
|
||||
|
||||
// skip directories and non-unicode file names (hex is unicode)
|
||||
if let Some(name) = path.file_name().and_then(|n| n.to_str()) {
|
||||
match hex::decode(name) {
|
||||
Ok(ref hex) if hex.len() > 4 => {
|
||||
if &hex[0..4] != &key_type.0 { continue }
|
||||
let public = TPublic::from_slice(&hex[4..]);
|
||||
public_keys.push(public);
|
||||
// skip directories and non-unicode file names (hex is unicode)
|
||||
if let Some(name) = path.file_name().and_then(|n| n.to_str()) {
|
||||
match hex::decode(name) {
|
||||
Ok(ref hex) if hex.len() > 4 => {
|
||||
if &hex[0..4] != &key_type.0 { continue }
|
||||
let public = TPublic::from_slice(&hex[4..]);
|
||||
public_keys.push(public);
|
||||
}
|
||||
_ => continue,
|
||||
}
|
||||
_ => continue,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -251,12 +267,12 @@ impl Store {
|
||||
}
|
||||
|
||||
/// Returns the file path for the given public key and key type.
|
||||
fn key_file_path(&self, public: &[u8], key_type: KeyTypeId) -> PathBuf {
|
||||
let mut buf = self.path.clone();
|
||||
fn key_file_path(&self, public: &[u8], key_type: KeyTypeId) -> Option<PathBuf> {
|
||||
let mut buf = self.path.as_ref()?.clone();
|
||||
let key_type = hex::encode(key_type.0);
|
||||
let key = hex::encode(public);
|
||||
buf.push(key_type + key.as_str());
|
||||
buf
|
||||
Some(buf)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
use crate::{Service, NetworkStatus, NetworkState, error::Error, DEFAULT_PROTOCOL_ID};
|
||||
use crate::{SpawnTaskHandle, start_rpc_servers, build_network_future, TransactionPoolAdapter};
|
||||
use crate::status_sinks;
|
||||
use crate::config::{Configuration, DatabaseConfig};
|
||||
use crate::config::{Configuration, DatabaseConfig, KeystoreConfig};
|
||||
use sc_client_api::{
|
||||
self,
|
||||
BlockchainEvents,
|
||||
@@ -165,10 +165,13 @@ fn new_full_parts<TBl, TRtApi, TExecDisp, TCfg, TGen, TCSExt>(
|
||||
TGen: sp_runtime::BuildStorage + serde::Serialize + for<'de> serde::Deserialize<'de>,
|
||||
TCSExt: Extension,
|
||||
{
|
||||
let keystore = Keystore::open(
|
||||
config.keystore_path.clone().ok_or("No basepath configured")?,
|
||||
config.keystore_password.clone()
|
||||
)?;
|
||||
let keystore = match &config.keystore {
|
||||
KeystoreConfig::Path { path, password } => Keystore::open(
|
||||
path.clone().ok_or("No basepath configured")?,
|
||||
password.clone()
|
||||
)?,
|
||||
KeystoreConfig::InMemory => Keystore::new_in_memory()
|
||||
};
|
||||
|
||||
let executor = NativeExecutor::<TExecDisp>::new(
|
||||
config.wasm_method,
|
||||
@@ -286,10 +289,13 @@ where TGen: RuntimeGenesis, TCSExt: Extension {
|
||||
(),
|
||||
TLightBackend<TBl>,
|
||||
>, Error> {
|
||||
let keystore = Keystore::open(
|
||||
config.keystore_path.clone().ok_or("No basepath configured")?,
|
||||
config.keystore_password.clone()
|
||||
)?;
|
||||
let keystore = match &config.keystore {
|
||||
KeystoreConfig::Path { path, password } => Keystore::open(
|
||||
path.clone().ok_or("No basepath configured")?,
|
||||
password.clone()
|
||||
)?,
|
||||
KeystoreConfig::InMemory => Keystore::new_in_memory()
|
||||
};
|
||||
|
||||
let executor = NativeExecutor::<TExecDisp>::new(
|
||||
config.wasm_method,
|
||||
|
||||
@@ -45,8 +45,8 @@ pub struct Configuration<C, G, E = NoExtension> {
|
||||
pub network: NetworkConfiguration,
|
||||
/// Path to the base configuration directory.
|
||||
pub config_dir: Option<PathBuf>,
|
||||
/// Path to key files.
|
||||
pub keystore_path: Option<PathBuf>,
|
||||
/// Configuration for the keystore.
|
||||
pub keystore: KeystoreConfig,
|
||||
/// Configuration for the database.
|
||||
pub database: DatabaseConfig,
|
||||
/// Size of internal state cache in Bytes
|
||||
@@ -92,8 +92,6 @@ pub struct Configuration<C, G, E = NoExtension> {
|
||||
pub force_authoring: bool,
|
||||
/// Disable GRANDPA when running in validator mode
|
||||
pub disable_grandpa: bool,
|
||||
/// Node keystore's password
|
||||
pub keystore_password: Option<Protected<String>>,
|
||||
/// Development key seed.
|
||||
///
|
||||
/// When running in development mode, the seed will be used to generate authority keys by the keystore.
|
||||
@@ -106,6 +104,20 @@ pub struct Configuration<C, G, E = NoExtension> {
|
||||
pub tracing_receiver: sc_tracing::TracingReceiver,
|
||||
}
|
||||
|
||||
/// Configuration of the client keystore.
|
||||
#[derive(Clone)]
|
||||
pub enum KeystoreConfig {
|
||||
/// Keystore at a path on-disk. Recommended for native nodes.
|
||||
Path {
|
||||
/// The path of the keystore. Will panic if no path is specified.
|
||||
path: Option<PathBuf>,
|
||||
/// Node keystore's password.
|
||||
password: Option<Protected<String>>
|
||||
},
|
||||
/// In-memory keystore. Recommended for in-browser nodes.
|
||||
InMemory
|
||||
}
|
||||
|
||||
/// Configuration of the database of the client.
|
||||
#[derive(Clone)]
|
||||
pub enum DatabaseConfig {
|
||||
@@ -138,7 +150,10 @@ impl<C, G, E> Configuration<C, G, E> where
|
||||
roles: Roles::FULL,
|
||||
transaction_pool: Default::default(),
|
||||
network: Default::default(),
|
||||
keystore_path: config_dir.map(|c| c.join("keystore")),
|
||||
keystore: KeystoreConfig::Path {
|
||||
path: config_dir.map(|c| c.join("keystore")),
|
||||
password: None
|
||||
},
|
||||
database: DatabaseConfig::Path {
|
||||
path: Default::default(),
|
||||
cache_size: Default::default(),
|
||||
@@ -161,7 +176,6 @@ impl<C, G, E> Configuration<C, G, E> where
|
||||
sentry_mode: false,
|
||||
force_authoring: false,
|
||||
disable_grandpa: false,
|
||||
keystore_password: None,
|
||||
dev_key_seed: None,
|
||||
tracing_targets: Default::default(),
|
||||
tracing_receiver: Default::default(),
|
||||
|
||||
@@ -29,7 +29,7 @@ use sc_service::{
|
||||
AbstractService,
|
||||
ChainSpec,
|
||||
Configuration,
|
||||
config::DatabaseConfig,
|
||||
config::{DatabaseConfig, KeystoreConfig},
|
||||
Roles,
|
||||
Error,
|
||||
};
|
||||
@@ -173,8 +173,10 @@ fn node_config<G, E: Clone> (
|
||||
roles: role,
|
||||
transaction_pool: Default::default(),
|
||||
network: network_config,
|
||||
keystore_path: Some(root.join("key")),
|
||||
keystore_password: None,
|
||||
keystore: KeystoreConfig::Path {
|
||||
path: Some(root.join("key")),
|
||||
password: None
|
||||
},
|
||||
config_dir: Some(root.clone()),
|
||||
database: DatabaseConfig::Path {
|
||||
path: root.join("db"),
|
||||
|
||||
Reference in New Issue
Block a user