diff --git a/prdoc/pr_7266.prdoc b/prdoc/pr_7266.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..4fa7ddb7b41a50b2ba15a1fc3d531cbcf8c73406 --- /dev/null +++ b/prdoc/pr_7266.prdoc @@ -0,0 +1,13 @@ +title: Add `offchain_localStorageClear` RPC method +doc: +- audience: Node Operator + description: |- + Adds RPC method `offchain_localStorageClear` to clear the offchain local storage. +crates: +- name: sc-offchain + bump: minor +- name: sc-rpc-api + bump: minor + validate: false +- name: sc-rpc + bump: minor diff --git a/substrate/client/offchain/src/api.rs b/substrate/client/offchain/src/api.rs index a5981f14c093ce3c41a9e97e7e3331b6f2ff351e..7d5c07deca4fb6d8374ec26d35585dae236c5140 100644 --- a/substrate/client/offchain/src/api.rs +++ b/substrate/client/offchain/src/api.rs @@ -375,7 +375,7 @@ mod tests { } #[test] - fn should_set_and_get_local_storage() { + fn should_set_get_and_clear_local_storage() { // given let kind = StorageKind::PERSISTENT; let mut api = offchain_db(); @@ -387,6 +387,12 @@ mod tests { // then assert_eq!(api.local_storage_get(kind, key), Some(b"value".to_vec())); + + // when + api.local_storage_clear(kind, key); + + // then + assert_eq!(api.local_storage_get(kind, key), None); } #[test] diff --git a/substrate/client/rpc-api/src/offchain/mod.rs b/substrate/client/rpc-api/src/offchain/mod.rs index 4dd5b066d49fe90063d14a276a5ec2bf9731b8f9..606d441231b052f45e600c520a32c90d68ad6a97 100644 --- a/substrate/client/rpc-api/src/offchain/mod.rs +++ b/substrate/client/rpc-api/src/offchain/mod.rs @@ -31,6 +31,10 @@ pub trait OffchainApi { #[method(name = "offchain_localStorageSet", with_extensions)] fn set_local_storage(&self, kind: StorageKind, key: Bytes, value: Bytes) -> Result<(), Error>; + /// Clear offchain local storage under given key and prefix. + #[method(name = "offchain_localStorageClear", with_extensions)] + fn clear_local_storage(&self, kind: StorageKind, key: Bytes) -> Result<(), Error>; + /// Get offchain local storage under given key and prefix. #[method(name = "offchain_localStorageGet", with_extensions)] fn get_local_storage(&self, kind: StorageKind, key: Bytes) -> Result<Option<Bytes>, Error>; diff --git a/substrate/client/rpc/src/offchain/mod.rs b/substrate/client/rpc/src/offchain/mod.rs index af6bc1ba58c8fdce53679465f204332d6a59f66b..f5b1b35be1063062fb1f04cf744f7938deb365bb 100644 --- a/substrate/client/rpc/src/offchain/mod.rs +++ b/substrate/client/rpc/src/offchain/mod.rs @@ -66,6 +66,23 @@ impl<T: OffchainStorage + 'static> OffchainApiServer for Offchain<T> { Ok(()) } + fn clear_local_storage( + &self, + ext: &Extensions, + kind: StorageKind, + key: Bytes, + ) -> Result<(), Error> { + check_if_safe(ext)?; + + let prefix = match kind { + StorageKind::PERSISTENT => sp_offchain::STORAGE_PREFIX, + StorageKind::LOCAL => return Err(Error::UnavailableStorageKind), + }; + self.storage.write().remove(prefix, &key); + + Ok(()) + } + fn get_local_storage( &self, ext: &Extensions, diff --git a/substrate/client/rpc/src/offchain/tests.rs b/substrate/client/rpc/src/offchain/tests.rs index 41f22c2dc964227cb2989dd10a8322e49ef54103..6b8225a7b5eb21ece1cb9e39a109c4cad4af6d71 100644 --- a/substrate/client/rpc/src/offchain/tests.rs +++ b/substrate/client/rpc/src/offchain/tests.rs @@ -35,9 +35,14 @@ fn local_storage_should_work() { Ok(()) ); assert_matches!( - offchain.get_local_storage(&ext, StorageKind::PERSISTENT, key), + offchain.get_local_storage(&ext, StorageKind::PERSISTENT, key.clone()), Ok(Some(ref v)) if *v == value ); + assert_matches!( + offchain.clear_local_storage(&ext, StorageKind::PERSISTENT, key.clone()), + Ok(()) + ); + assert_matches!(offchain.get_local_storage(&ext, StorageKind::PERSISTENT, key), Ok(None)); } #[test] @@ -55,6 +60,12 @@ fn offchain_calls_considered_unsafe() { assert_eq!(e.to_string(), "RPC call is unsafe to be called externally") } ); + assert_matches!( + offchain.clear_local_storage(&ext, StorageKind::PERSISTENT, key.clone()), + Err(Error::UnsafeRpcCalled(e)) => { + assert_eq!(e.to_string(), "RPC call is unsafe to be called externally") + } + ); assert_matches!( offchain.get_local_storage(&ext, StorageKind::PERSISTENT, key), Err(Error::UnsafeRpcCalled(e)) => {