Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Encryption support for the statement store #14440

Merged
merged 8 commits into from
Jul 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions bin/node/cli/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ pub fn new_partial(
&config.data_path,
Default::default(),
client.clone(),
keystore_container.local_keystore(),
config.prometheus_registry(),
&task_manager.spawn_handle(),
)
Expand Down
2 changes: 1 addition & 1 deletion client/cli/src/runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,7 @@ mod tests {
},
);

let Some(output) = output else { return } ;
let Some(output) = output else { return };

let stderr = dbg!(String::from_utf8(output.stderr).unwrap());

Expand Down
1 change: 1 addition & 0 deletions client/keystore/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ use std::io;
/// Local keystore implementation
mod local;
pub use local::LocalKeystore;
pub use sp_keystore::Keystore;

/// Keystore error.
#[derive(Debug, thiserror::Error)]
Expand Down
2 changes: 1 addition & 1 deletion client/network/src/discovery.rs
Original file line number Diff line number Diff line change
Expand Up @@ -548,7 +548,7 @@ impl NetworkBehaviour for DiscoveryBehaviour {
addresses: &[Multiaddr],
effective_role: Endpoint,
) -> Result<Vec<Multiaddr>, ConnectionDenied> {
let Some(peer_id) = maybe_peer else { return Ok(Vec::new()); };
let Some(peer_id) = maybe_peer else { return Ok(Vec::new()) };

let mut list = self
.permanent_addresses
Expand Down
8 changes: 2 additions & 6 deletions client/network/src/protocol_controller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -658,9 +658,7 @@ impl ProtocolController {
/// disconnected, `Ok(false)` if it wasn't found, `Err(PeerId)`, if the peer found, but not in
/// connected state.
fn drop_reserved_peer(&mut self, peer_id: &PeerId) -> Result<bool, PeerId> {
let Some(state) = self.reserved_nodes.get_mut(peer_id) else {
return Ok(false)
};
let Some(state) = self.reserved_nodes.get_mut(peer_id) else { return Ok(false) };

if let PeerState::Connected(direction) = state {
trace!(
Expand All @@ -678,9 +676,7 @@ impl ProtocolController {
/// Try dropping the peer as a regular peer. Return `true` if the peer was found and
/// disconnected, `false` if it wasn't found.
fn drop_regular_peer(&mut self, peer_id: &PeerId) -> bool {
let Some(direction) = self.nodes.remove(peer_id) else {
return false
};
let Some(direction) = self.nodes.remove(peer_id) else { return false };

trace!(
target: LOG_TARGET,
Expand Down
3 changes: 2 additions & 1 deletion client/rpc-spec-v2/src/chain_head/chain_head.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,8 @@ where
},
};
// Keep track of the subscription.
let Some(rx_stop) = self.subscriptions.insert_subscription(sub_id.clone(), with_runtime) else {
let Some(rx_stop) = self.subscriptions.insert_subscription(sub_id.clone(), with_runtime)
else {
// Inserting the subscription can only fail if the JsonRPSee
// generated a duplicate subscription ID.
debug!(target: LOG_TARGET, "[follow][id={:?}] Subscription already accepted", sub_id);
Expand Down
4 changes: 1 addition & 3 deletions client/rpc-spec-v2/src/chain_head/chain_head_follow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -339,9 +339,7 @@ where
let mut events = Vec::new();

// Nothing to be done if no finalized hashes are provided.
let Some(first_hash) = finalized_block_hashes.get(0) else {
return Ok(Default::default())
};
let Some(first_hash) = finalized_block_hashes.get(0) else { return Ok(Default::default()) };

// Find the parent header.
let Some(first_header) = self.client.header(*first_hash)? else {
Expand Down
4 changes: 1 addition & 3 deletions client/rpc-spec-v2/src/chain_head/subscription/inner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -328,9 +328,7 @@ impl<Block: BlockT, BE: Backend<Block>> SubscriptionsInner<Block, BE> {

/// Remove the subscription ID with associated pinned blocks.
pub fn remove_subscription(&mut self, sub_id: &str) {
let Some(mut sub) = self.subs.remove(sub_id) else {
return
};
let Some(mut sub) = self.subs.remove(sub_id) else { return };

// The `Stop` event can be generated only once.
sub.stop();
Expand Down
2 changes: 1 addition & 1 deletion client/service/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ pub async fn build_system_rpc_future<
// Answer incoming RPC requests.
let Some(req) = rpc_rx.next().await else {
debug!("RPC requests stream has terminated, shutting down the system RPC future.");
return;
return
};

match req {
Expand Down
1 change: 1 addition & 0 deletions client/statement-store/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" }
sp-core = { version = "21.0.0", path = "../../primitives/core" }
sp-runtime = { version = "24.0.0", path = "../../primitives/runtime" }
sc-client-api = { version = "4.0.0-dev", path = "../api" }
sc-keystore = { version = "4.0.0-dev", path = "../../client/keystore" }

[dev-dependencies]
tempfile = "3.1.0"
Expand Down
78 changes: 71 additions & 7 deletions client/statement-store/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,10 @@ pub use sp_statement_store::{Error, StatementStore, MAX_TOPICS};
use metrics::MetricsLink as PrometheusMetrics;
use parking_lot::RwLock;
use prometheus_endpoint::Registry as PrometheusRegistry;
use sc_keystore::LocalKeystore;
use sp_api::ProvideRuntimeApi;
use sp_blockchain::HeaderBackend;
use sp_core::{hexdisplay::HexDisplay, traits::SpawnNamed, Decode, Encode};
use sp_core::{crypto::UncheckedFrom, hexdisplay::HexDisplay, traits::SpawnNamed, Decode, Encode};
use sp_runtime::traits::Block as BlockT;
use sp_statement_store::{
runtime_api::{
Expand Down Expand Up @@ -201,6 +202,7 @@ pub struct Store {
+ Send
+ Sync,
>,
keystore: Arc<LocalKeystore>,
// Used for testing
time_override: Option<u64>,
metrics: PrometheusMetrics,
Expand Down Expand Up @@ -479,6 +481,7 @@ impl Store {
path: &std::path::Path,
options: Options,
client: Arc<Client>,
keystore: Arc<LocalKeystore>,
prometheus: Option<&PrometheusRegistry>,
task_spawner: &dyn SpawnNamed,
) -> Result<Arc<Store>>
Expand All @@ -493,7 +496,7 @@ impl Store {
+ 'static,
Client::Api: ValidateStatement<Block>,
{
let store = Arc::new(Self::new(path, options, client, prometheus)?);
let store = Arc::new(Self::new(path, options, client, keystore, prometheus)?);

// Perform periodic statement store maintenance
let worker_store = store.clone();
Expand All @@ -518,6 +521,7 @@ impl Store {
path: &std::path::Path,
options: Options,
client: Arc<Client>,
keystore: Arc<LocalKeystore>,
prometheus: Option<&PrometheusRegistry>,
) -> Result<Store>
where
Expand Down Expand Up @@ -566,6 +570,7 @@ impl Store {
db,
index: RwLock::new(Index::new(options)),
validate_fn,
keystore,
time_override: None,
metrics: PrometheusMetrics::new(prometheus),
};
Expand Down Expand Up @@ -768,7 +773,45 @@ impl StatementStore for Store {
/// Return the decrypted data of all known statements whose decryption key is identified as
/// `dest`. The key must be available to the client.
fn posted_clear(&self, match_all_topics: &[Topic], dest: [u8; 32]) -> Result<Vec<Vec<u8>>> {
self.collect_statements(Some(dest), match_all_topics, |statement| statement.into_data())
self.collect_statements(Some(dest), match_all_topics, |statement| {
if let (Some(key), Some(_)) = (statement.decryption_key(), statement.data()) {
let public: sp_core::ed25519::Public = UncheckedFrom::unchecked_from(key);
let public: sp_statement_store::ed25519::Public = public.into();
match self.keystore.key_pair::<sp_statement_store::ed25519::Pair>(&public) {
Err(e) => {
log::debug!(
target: LOG_TARGET,
"Keystore error: {:?}, for statement {:?}",
e,
HexDisplay::from(&statement.hash())
);
None
},
Ok(None) => {
log::debug!(
target: LOG_TARGET,
"Keystore is missing key for statement {:?}",
HexDisplay::from(&statement.hash())
);
None
},
Ok(Some(pair)) => match statement.decrypt_private(&pair.into_inner()) {
Ok(r) => r,
Err(e) => {
log::debug!(
target: LOG_TARGET,
"Decryption error: {:?}, for statement {:?}",
e,
HexDisplay::from(&statement.hash())
);
None
},
},
}
} else {
None
}
})
}

/// Submit a statement to the store. Validates the statement and returns validation result.
Expand Down Expand Up @@ -887,6 +930,7 @@ impl StatementStore for Store {
#[cfg(test)]
mod tests {
use crate::Store;
use sc_keystore::Keystore;
use sp_core::Pair;
use sp_statement_store::{
runtime_api::{InvalidStatement, ValidStatement, ValidateStatement},
Expand Down Expand Up @@ -916,6 +960,7 @@ mod tests {
RuntimeApi { _inner: self.clone() }.into()
}
}

sp_api::mock_impl_runtime_apis! {
impl ValidateStatement<Block> for RuntimeApi {
fn validate_statement(
Expand Down Expand Up @@ -983,7 +1028,8 @@ mod tests {
let client = std::sync::Arc::new(TestClient);
let mut path: std::path::PathBuf = temp_dir.path().into();
path.push("db");
let store = Store::new(&path, Default::default(), client, None).unwrap();
let keystore = std::sync::Arc::new(sc_keystore::LocalKeystore::in_memory());
let store = Store::new(&path, Default::default(), client, keystore, None).unwrap();
(store, temp_dir) // return order is important. Store must be dropped before TempDir
}

Expand Down Expand Up @@ -1086,12 +1132,13 @@ mod tests {
assert_eq!(store.statements().unwrap().len(), 3);
assert_eq!(store.broadcasts(&[]).unwrap().len(), 3);
assert_eq!(store.statement(&statement1.hash()).unwrap(), Some(statement1.clone()));
let keystore = store.keystore.clone();
drop(store);

let client = std::sync::Arc::new(TestClient);
let mut path: std::path::PathBuf = temp.path().into();
path.push("db");
let store = Store::new(&path, Default::default(), client, None).unwrap();
let store = Store::new(&path, Default::default(), client, keystore, None).unwrap();
assert_eq!(store.statements().unwrap().len(), 3);
assert_eq!(store.broadcasts(&[]).unwrap().len(), 3);
assert_eq!(store.statement(&statement1.hash()).unwrap(), Some(statement1));
Expand Down Expand Up @@ -1196,7 +1243,6 @@ mod tests {
statement(2, 4, None, 1000).hash(),
statement(3, 4, Some(3), 300).hash(),
statement(3, 5, None, 500).hash(),
//statement(4, 6, None, 100).hash(),
];
expected_statements.sort();
let mut statements: Vec<_> =
Expand All @@ -1220,13 +1266,31 @@ mod tests {
store.set_time(DEFAULT_PURGE_AFTER_SEC + 1);
store.maintain();
assert_eq!(store.index.read().expired.len(), 0);
let keystore = store.keystore.clone();
drop(store);

let client = std::sync::Arc::new(TestClient);
let mut path: std::path::PathBuf = temp.path().into();
path.push("db");
let store = Store::new(&path, Default::default(), client, None).unwrap();
let store = Store::new(&path, Default::default(), client, keystore, None).unwrap();
assert_eq!(store.statements().unwrap().len(), 0);
assert_eq!(store.index.read().expired.len(), 0);
}

#[test]
fn posted_clear_decrypts() {
let (store, _temp) = test_store();
let public = store
.keystore
.ed25519_generate_new(sp_core::crypto::key_types::STATEMENT, None)
.unwrap();
let statement1 = statement(1, 1, None, 100);
let mut statement2 = statement(1, 2, None, 0);
let plain = b"The most valuable secret".to_vec();
statement2.encrypt(&plain, &public).unwrap();
store.submit(statement1, StatementSource::Network);
store.submit(statement2, StatementSource::Network);
let posted_clear = store.posted_clear(&[], public.into()).unwrap();
assert_eq!(posted_clear, vec![plain]);
}
}
8 changes: 2 additions & 6 deletions frame/glutton/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -271,9 +271,7 @@ pub mod pallet {
///
/// Tries to come as close to the limit as possible.
pub(crate) fn waste_at_most_proof_size(meter: &mut WeightMeter) {
let Ok(n) = Self::calculate_proof_size_iters(&meter) else {
return;
};
let Ok(n) = Self::calculate_proof_size_iters(&meter) else { return };

meter.defensive_saturating_accrue(T::WeightInfo::waste_proof_size_some(n));

Expand Down Expand Up @@ -303,9 +301,7 @@ pub mod pallet {
///
/// Tries to come as close to the limit as possible.
pub(crate) fn waste_at_most_ref_time(meter: &mut WeightMeter) {
let Ok(n) = Self::calculate_ref_time_iters(&meter) else {
return;
};
let Ok(n) = Self::calculate_ref_time_iters(&meter) else { return };
meter.defensive_saturating_accrue(T::WeightInfo::waste_ref_time_iter(n));

let clobber = Self::waste_ref_time_iter(vec![0u8; 64], n);
Expand Down
6 changes: 3 additions & 3 deletions frame/support/procedural/src/benchmark.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,11 +166,11 @@ fn ensure_valid_return_type(item_fn: &ItemFn) -> Result<()> {
if let ReturnType::Type(_, typ) = &item_fn.sig.output {
let non_unit = |span| return Err(Error::new(span, "expected `()`"));
let Type::Path(TypePath { path, qself: _ }) = &**typ else {
return Err(Error::new(
return Err(Error::new(
typ.span(),
"Only `Result<(), BenchmarkError>` or a blank return type is allowed on benchmark function definitions",
))
};
};
let seg = path
.segments
.last()
Expand Down Expand Up @@ -780,7 +780,7 @@ fn expand_benchmark(
let call_name = match *expr_call.func {
Expr::Path(expr_path) => {
// normal function call
let Some(segment) = expr_path.path.segments.last() else { return call_err(); };
let Some(segment) = expr_path.path.segments.last() else { return call_err() };
segment.ident.to_string()
},
Expr::Infer(_) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,7 @@ pub fn expand_outer_enum(
let enum_name_ident = Ident::new(enum_ty.struct_name(), Span::call_site());

for pallet_decl in pallet_decls {
let Some(pallet_entry) = pallet_decl.find_part(enum_name_str) else {
continue
};
let Some(pallet_entry) = pallet_decl.find_part(enum_name_str) else { continue };

let path = &pallet_decl.path;
let pallet_name = &pallet_decl.name;
Expand Down
Loading