From 66bd26d35c21ad260120129776c86870ff1dd220 Mon Sep 17 00:00:00 2001
From: "Alisher A. Khassanov" <a.khssnv@gmail.com>
Date: Thu, 23 Jan 2025 16:01:55 +0500
Subject: [PATCH] Add `offchain_localStorageClear` RPC method (#7266)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

# Description

Closes https://github.com/paritytech/polkadot-sdk/issues/7265.

## Integration

Requires changes in
`https://github.com/polkadot-js/api/packages/{rpc-augment,types-support,types}`
to be visible in Polkadot\Substrate Portal and in other libraries where
we should explicitly state RPC methods.

Accompany PR to `polkadot-js/api`:
https://github.com/polkadot-js/api/pull/6070.

## Review Notes

Please put the right label on my PR.

---------

Co-authored-by: command-bot <>
Co-authored-by: Bastian Köcher <git@kchr.de>
---
 prdoc/pr_7266.prdoc                          | 13 +++++++++++++
 substrate/client/offchain/src/api.rs         |  8 +++++++-
 substrate/client/rpc-api/src/offchain/mod.rs |  4 ++++
 substrate/client/rpc/src/offchain/mod.rs     | 17 +++++++++++++++++
 substrate/client/rpc/src/offchain/tests.rs   | 13 ++++++++++++-
 5 files changed, 53 insertions(+), 2 deletions(-)
 create mode 100644 prdoc/pr_7266.prdoc

diff --git a/prdoc/pr_7266.prdoc b/prdoc/pr_7266.prdoc
new file mode 100644
index 00000000000..4fa7ddb7b41
--- /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 a5981f14c09..7d5c07deca4 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 4dd5b066d49..606d441231b 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 af6bc1ba58c..f5b1b35be10 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 41f22c2dc96..6b8225a7b5e 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)) => {
-- 
GitLab