From f2fe6a4c56ff524d9fd3a35eda8b246740af69e8 Mon Sep 17 00:00:00 2001
From: yjh <yjh465402634@gmail.com>
Date: Wed, 29 Nov 2023 21:48:32 +0800
Subject: [PATCH] Improve `CodeExecutor` (#2358)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Since `sp-state-machine` and `GenesisConfigBuilderRuntimeCaller` always
set `use_native` to be false.
We should remove this param and make `NativeElseWasmExecutor` behave
like its name.
It could make the above components use the correct execution strategy.

Maybe polkadot do not need about `NativeElseWasmExecutor` anymore. But
it is still needed by other chains and it's useful for debugging.

---------

Co-authored-by: Bastian Köcher <git@kchr.de>
Co-authored-by: command-bot <>
Co-authored-by: Michal Kucharczyk <1728078+michalkucharczyk@users.noreply.github.com>
---
 substrate/bin/node/cli/benches/executor.rs    | 12 +---
 substrate/bin/node/cli/tests/basic.rs         | 69 +++++++------------
 substrate/bin/node/cli/tests/common.rs        |  9 ++-
 substrate/bin/node/cli/tests/fees.rs          | 14 ++--
 .../chain-spec/src/genesis_config_builder.rs  |  1 -
 substrate/client/executor/src/executor.rs     | 23 +++++--
 substrate/primitives/core/src/traits.rs       |  1 -
 substrate/primitives/state-machine/src/lib.rs |  5 +-
 substrate/test-utils/client/src/lib.rs        |  3 +-
 9 files changed, 56 insertions(+), 81 deletions(-)

diff --git a/substrate/bin/node/cli/benches/executor.rs b/substrate/bin/node/cli/benches/executor.rs
index d654646904b..a326e1a79ea 100644
--- a/substrate/bin/node/cli/benches/executor.rs
+++ b/substrate/bin/node/cli/benches/executor.rs
@@ -103,14 +103,7 @@ fn construct_block<E: Externalities>(
 
 	// execute the block to get the real header.
 	executor
-		.call(
-			ext,
-			&runtime_code,
-			"Core_initialize_block",
-			&header.encode(),
-			true,
-			CallContext::Offchain,
-		)
+		.call(ext, &runtime_code, "Core_initialize_block", &header.encode(), CallContext::Offchain)
 		.0
 		.unwrap();
 
@@ -121,7 +114,6 @@ fn construct_block<E: Externalities>(
 				&runtime_code,
 				"BlockBuilder_apply_extrinsic",
 				&i.encode(),
-				true,
 				CallContext::Offchain,
 			)
 			.0
@@ -135,7 +127,6 @@ fn construct_block<E: Externalities>(
 				&runtime_code,
 				"BlockBuilder_finalize_block",
 				&[0u8; 0],
-				true,
 				CallContext::Offchain,
 			)
 			.0
@@ -200,7 +191,6 @@ fn bench_execute_block(c: &mut Criterion) {
 							&runtime_code,
 							"Core_execute_block",
 							&block.0,
-							false,
 							CallContext::Offchain,
 						)
 						.0
diff --git a/substrate/bin/node/cli/tests/basic.rs b/substrate/bin/node/cli/tests/basic.rs
index cbceac04e8e..e5a8a397254 100644
--- a/substrate/bin/node/cli/tests/basic.rs
+++ b/substrate/bin/node/cli/tests/basic.rs
@@ -193,11 +193,9 @@ fn panic_execution_with_foreign_code_gives_error() {
 	t.insert(<pallet_balances::TotalIssuance<Runtime>>::hashed_key().to_vec(), 69_u128.encode());
 	t.insert(<frame_system::BlockHash<Runtime>>::hashed_key_for(0), vec![0u8; 32]);
 
-	let r =
-		executor_call(&mut t, "Core_initialize_block", &vec![].and(&from_block_number(1u32)), true)
-			.0;
+	let r = executor_call(&mut t, "Core_initialize_block", &vec![].and(&from_block_number(1u32))).0;
 	assert!(r.is_ok());
-	let v = executor_call(&mut t, "BlockBuilder_apply_extrinsic", &vec![].and(&xt()), true)
+	let v = executor_call(&mut t, "BlockBuilder_apply_extrinsic", &vec![].and(&xt()))
 		.0
 		.unwrap();
 	let r = ApplyExtrinsicResult::decode(&mut &v[..]).unwrap();
@@ -219,11 +217,9 @@ fn bad_extrinsic_with_native_equivalent_code_gives_error() {
 	t.insert(<pallet_balances::TotalIssuance<Runtime>>::hashed_key().to_vec(), 69u128.encode());
 	t.insert(<frame_system::BlockHash<Runtime>>::hashed_key_for(0), vec![0u8; 32]);
 
-	let r =
-		executor_call(&mut t, "Core_initialize_block", &vec![].and(&from_block_number(1u32)), true)
-			.0;
+	let r = executor_call(&mut t, "Core_initialize_block", &vec![].and(&from_block_number(1u32))).0;
 	assert!(r.is_ok());
-	let v = executor_call(&mut t, "BlockBuilder_apply_extrinsic", &vec![].and(&xt()), true)
+	let v = executor_call(&mut t, "BlockBuilder_apply_extrinsic", &vec![].and(&xt()))
 		.0
 		.unwrap();
 	let r = ApplyExtrinsicResult::decode(&mut &v[..]).unwrap();
@@ -256,14 +252,12 @@ fn successful_execution_with_native_equivalent_code_gives_ok() {
 	);
 	t.insert(<frame_system::BlockHash<Runtime>>::hashed_key_for(0), vec![0u8; 32]);
 
-	let r =
-		executor_call(&mut t, "Core_initialize_block", &vec![].and(&from_block_number(1u32)), true)
-			.0;
+	let r = executor_call(&mut t, "Core_initialize_block", &vec![].and(&from_block_number(1u32))).0;
 	assert!(r.is_ok());
 
 	let fees = t.execute_with(|| transfer_fee(&xt()));
 
-	let r = executor_call(&mut t, "BlockBuilder_apply_extrinsic", &vec![].and(&xt()), true).0;
+	let r = executor_call(&mut t, "BlockBuilder_apply_extrinsic", &vec![].and(&xt())).0;
 	assert!(r.is_ok());
 
 	t.execute_with(|| {
@@ -298,14 +292,12 @@ fn successful_execution_with_foreign_code_gives_ok() {
 	);
 	t.insert(<frame_system::BlockHash<Runtime>>::hashed_key_for(0), vec![0u8; 32]);
 
-	let r =
-		executor_call(&mut t, "Core_initialize_block", &vec![].and(&from_block_number(1u32)), true)
-			.0;
+	let r = executor_call(&mut t, "Core_initialize_block", &vec![].and(&from_block_number(1u32))).0;
 	assert!(r.is_ok());
 
 	let fees = t.execute_with(|| transfer_fee(&xt()));
 
-	let r = executor_call(&mut t, "BlockBuilder_apply_extrinsic", &vec![].and(&xt()), true).0;
+	let r = executor_call(&mut t, "BlockBuilder_apply_extrinsic", &vec![].and(&xt())).0;
 	assert!(r.is_ok());
 
 	t.execute_with(|| {
@@ -337,7 +329,7 @@ fn full_native_block_import_works() {
 				.base_extrinsic,
 		);
 
-	executor_call(&mut t, "Core_execute_block", &block1.0, true).0.unwrap();
+	executor_call(&mut t, "Core_execute_block", &block1.0).0.unwrap();
 
 	t.execute_with(|| {
 		assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - fees);
@@ -412,7 +404,7 @@ fn full_native_block_import_works() {
 	fees = t.execute_with(|| transfer_fee(&xt()));
 	let pot = t.execute_with(|| Treasury::pot());
 
-	executor_call(&mut t, "Core_execute_block", &block2.0, true).0.unwrap();
+	executor_call(&mut t, "Core_execute_block", &block2.0).0.unwrap();
 
 	t.execute_with(|| {
 		assert_eq!(
@@ -554,7 +546,7 @@ fn full_wasm_block_import_works() {
 	let mut alice_last_known_balance: Balance = Default::default();
 	let mut fees = t.execute_with(|| transfer_fee(&xt()));
 
-	executor_call(&mut t, "Core_execute_block", &block1.0, false).0.unwrap();
+	executor_call(&mut t, "Core_execute_block", &block1.0).0.unwrap();
 
 	t.execute_with(|| {
 		assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - fees);
@@ -564,7 +556,7 @@ fn full_wasm_block_import_works() {
 
 	fees = t.execute_with(|| transfer_fee(&xt()));
 
-	executor_call(&mut t, "Core_execute_block", &block2.0, false).0.unwrap();
+	executor_call(&mut t, "Core_execute_block", &block2.0).0.unwrap();
 
 	t.execute_with(|| {
 		assert_eq!(
@@ -717,7 +709,7 @@ fn deploying_wasm_contract_should_work() {
 
 	let mut t = new_test_ext(compact_code_unwrap());
 
-	executor_call(&mut t, "Core_execute_block", &b.0, false).0.unwrap();
+	executor_call(&mut t, "Core_execute_block", &b.0).0.unwrap();
 
 	t.execute_with(|| {
 		// Verify that the contract does exist by querying some of its storage items
@@ -732,8 +724,7 @@ fn wasm_big_block_import_fails() {
 
 	set_heap_pages(&mut t.ext(), 4);
 
-	let result =
-		executor_call(&mut t, "Core_execute_block", &block_with_size(42, 0, 120_000).0, false).0;
+	let result = executor_call(&mut t, "Core_execute_block", &block_with_size(42, 0, 120_000).0).0;
 	assert!(result.is_err()); // Err(Wasmi(Trap(Trap { kind: Host(AllocatorOutOfSpace) })))
 }
 
@@ -741,7 +732,7 @@ fn wasm_big_block_import_fails() {
 fn native_big_block_import_succeeds() {
 	let mut t = new_test_ext(compact_code_unwrap());
 
-	executor_call(&mut t, "Core_execute_block", &block_with_size(42, 0, 120_000).0, true)
+	executor_call(&mut t, "Core_execute_block", &block_with_size(42, 0, 120_000).0)
 		.0
 		.unwrap();
 }
@@ -754,11 +745,9 @@ fn native_big_block_import_fails_on_fallback() {
 	// block.
 	set_heap_pages(&mut t.ext(), 8);
 
-	assert!(
-		executor_call(&mut t, "Core_execute_block", &block_with_size(42, 0, 120_000).0, false,)
-			.0
-			.is_err()
-	);
+	assert!(executor_call(&mut t, "Core_execute_block", &block_with_size(42, 0, 120_000).0)
+		.0
+		.is_err());
 }
 
 #[test]
@@ -775,15 +764,9 @@ fn panic_execution_gives_error() {
 	t.insert(<pallet_balances::TotalIssuance<Runtime>>::hashed_key().to_vec(), 0_u128.encode());
 	t.insert(<frame_system::BlockHash<Runtime>>::hashed_key_for(0), vec![0u8; 32]);
 
-	let r = executor_call(
-		&mut t,
-		"Core_initialize_block",
-		&vec![].and(&from_block_number(1u32)),
-		false,
-	)
-	.0;
+	let r = executor_call(&mut t, "Core_initialize_block", &vec![].and(&from_block_number(1u32))).0;
 	assert!(r.is_ok());
-	let r = executor_call(&mut t, "BlockBuilder_apply_extrinsic", &vec![].and(&xt()), false)
+	let r = executor_call(&mut t, "BlockBuilder_apply_extrinsic", &vec![].and(&xt()))
 		.0
 		.unwrap();
 	let r = ApplyExtrinsicResult::decode(&mut &r[..]).unwrap();
@@ -816,13 +799,7 @@ fn successful_execution_gives_ok() {
 	);
 	t.insert(<frame_system::BlockHash<Runtime>>::hashed_key_for(0), vec![0u8; 32]);
 
-	let r = executor_call(
-		&mut t,
-		"Core_initialize_block",
-		&vec![].and(&from_block_number(1u32)),
-		false,
-	)
-	.0;
+	let r = executor_call(&mut t, "Core_initialize_block", &vec![].and(&from_block_number(1u32))).0;
 	assert!(r.is_ok());
 	t.execute_with(|| {
 		assert_eq!(Balances::total_balance(&alice()), 111 * DOLLARS);
@@ -830,7 +807,7 @@ fn successful_execution_gives_ok() {
 
 	let fees = t.execute_with(|| transfer_fee(&xt()));
 
-	let r = executor_call(&mut t, "BlockBuilder_apply_extrinsic", &vec![].and(&xt()), false)
+	let r = executor_call(&mut t, "BlockBuilder_apply_extrinsic", &vec![].and(&xt()))
 		.0
 		.unwrap();
 	ApplyExtrinsicResult::decode(&mut &r[..])
@@ -861,7 +838,7 @@ fn should_import_block_with_test_client() {
 #[test]
 fn default_config_as_json_works() {
 	let mut t = new_test_ext(compact_code_unwrap());
-	let r = executor_call(&mut t, "GenesisBuilder_create_default_config", &vec![], false)
+	let r = executor_call(&mut t, "GenesisBuilder_create_default_config", &vec![])
 		.0
 		.unwrap();
 	let r = Vec::<u8>::decode(&mut &r[..]).unwrap();
diff --git a/substrate/bin/node/cli/tests/common.rs b/substrate/bin/node/cli/tests/common.rs
index 7d8f6a9a0e7..9019594ff62 100644
--- a/substrate/bin/node/cli/tests/common.rs
+++ b/substrate/bin/node/cli/tests/common.rs
@@ -105,7 +105,6 @@ pub fn executor_call(
 	t: &mut TestExternalities<BlakeTwo256>,
 	method: &str,
 	data: &[u8],
-	use_native: bool,
 ) -> (Result<Vec<u8>>, bool) {
 	let mut t = t.ext();
 
@@ -117,7 +116,7 @@ pub fn executor_call(
 		heap_pages: heap_pages.and_then(|hp| Decode::decode(&mut &hp[..]).ok()),
 	};
 	sp_tracing::try_init_simple();
-	executor().call(&mut t, &runtime_code, method, data, use_native, CallContext::Onchain)
+	executor().call(&mut t, &runtime_code, method, data, CallContext::Onchain)
 }
 
 pub fn new_test_ext(code: &[u8]) -> TestExternalities<BlakeTwo256> {
@@ -168,12 +167,12 @@ pub fn construct_block(
 	};
 
 	// execute the block to get the real header.
-	executor_call(env, "Core_initialize_block", &header.encode(), true).0.unwrap();
+	executor_call(env, "Core_initialize_block", &header.encode()).0.unwrap();
 
 	for extrinsic in extrinsics.iter() {
 		// Try to apply the `extrinsic`. It should be valid, in the sense that it passes
 		// all pre-inclusion checks.
-		let r = executor_call(env, "BlockBuilder_apply_extrinsic", &extrinsic.encode(), true)
+		let r = executor_call(env, "BlockBuilder_apply_extrinsic", &extrinsic.encode())
 			.0
 			.expect("application of an extrinsic failed");
 
@@ -186,7 +185,7 @@ pub fn construct_block(
 	}
 
 	let header = Header::decode(
-		&mut &executor_call(env, "BlockBuilder_finalize_block", &[0u8; 0], true).0.unwrap()[..],
+		&mut &executor_call(env, "BlockBuilder_finalize_block", &[0u8; 0]).0.unwrap()[..],
 	)
 	.unwrap();
 
diff --git a/substrate/bin/node/cli/tests/fees.rs b/substrate/bin/node/cli/tests/fees.rs
index 7519ce6e8b1..8c7b3c87315 100644
--- a/substrate/bin/node/cli/tests/fees.rs
+++ b/substrate/bin/node/cli/tests/fees.rs
@@ -95,7 +95,7 @@ fn fee_multiplier_increases_and_decreases_on_big_weight() {
 	);
 
 	// execute a big block.
-	executor_call(&mut t, "Core_execute_block", &block1.0, true).0.unwrap();
+	executor_call(&mut t, "Core_execute_block", &block1.0).0.unwrap();
 
 	// weight multiplier is increased for next block.
 	t.execute_with(|| {
@@ -106,7 +106,7 @@ fn fee_multiplier_increases_and_decreases_on_big_weight() {
 	});
 
 	// execute a big block.
-	executor_call(&mut t, "Core_execute_block", &block2.0, true).0.unwrap();
+	executor_call(&mut t, "Core_execute_block", &block2.0).0.unwrap();
 
 	// weight multiplier is increased for next block.
 	t.execute_with(|| {
@@ -151,12 +151,10 @@ fn transaction_fee_is_correct() {
 		function: RuntimeCall::Balances(default_transfer_call()),
 	});
 
-	let r =
-		executor_call(&mut t, "Core_initialize_block", &vec![].and(&from_block_number(1u32)), true)
-			.0;
+	let r = executor_call(&mut t, "Core_initialize_block", &vec![].and(&from_block_number(1u32))).0;
 
 	assert!(r.is_ok());
-	let r = executor_call(&mut t, "BlockBuilder_apply_extrinsic", &vec![].and(&xt.clone()), true).0;
+	let r = executor_call(&mut t, "BlockBuilder_apply_extrinsic", &vec![].and(&xt.clone())).0;
 	assert!(r.is_ok());
 
 	t.execute_with(|| {
@@ -247,7 +245,7 @@ fn block_weight_capacity_report() {
 			len / 1024 / 1024,
 		);
 
-		let r = executor_call(&mut t, "Core_execute_block", &block.0, true).0;
+		let r = executor_call(&mut t, "Core_execute_block", &block.0).0;
 
 		println!(" || Result = {:?}", r);
 		assert!(r.is_ok());
@@ -310,7 +308,7 @@ fn block_length_capacity_report() {
 			len / 1024 / 1024,
 		);
 
-		let r = executor_call(&mut t, "Core_execute_block", &block.0, true).0;
+		let r = executor_call(&mut t, "Core_execute_block", &block.0).0;
 
 		println!(" || Result = {:?}", r);
 		assert!(r.is_ok());
diff --git a/substrate/client/chain-spec/src/genesis_config_builder.rs b/substrate/client/chain-spec/src/genesis_config_builder.rs
index 9ccf6b4efb2..68f3d886049 100644
--- a/substrate/client/chain-spec/src/genesis_config_builder.rs
+++ b/substrate/client/chain-spec/src/genesis_config_builder.rs
@@ -76,7 +76,6 @@ where
 				&RuntimeCode { heap_pages: None, code_fetcher: self, hash: self.code_hash.clone() },
 				method,
 				data,
-				false,
 				CallContext::Offchain,
 			)
 			.0
diff --git a/substrate/client/executor/src/executor.rs b/substrate/client/executor/src/executor.rs
index 7c292a83da0..499bb704b16 100644
--- a/substrate/client/executor/src/executor.rs
+++ b/substrate/client/executor/src/executor.rs
@@ -492,7 +492,6 @@ where
 		runtime_code: &RuntimeCode,
 		method: &str,
 		data: &[u8],
-		_use_native: bool,
 		context: CallContext,
 	) -> (Result<Vec<u8>>, bool) {
 		tracing::trace!(
@@ -565,6 +564,8 @@ pub struct NativeElseWasmExecutor<D: NativeExecutionDispatch> {
 	/// Fallback wasm executor.
 	wasm:
 		WasmExecutor<ExtendedHostFunctions<sp_io::SubstrateHostFunctions, D::ExtendHostFunctions>>,
+
+	use_native: bool,
 }
 
 impl<D: NativeExecutionDispatch> NativeElseWasmExecutor<D> {
@@ -601,7 +602,7 @@ impl<D: NativeExecutionDispatch> NativeElseWasmExecutor<D> {
 			.with_runtime_cache_size(runtime_cache_size)
 			.build();
 
-		NativeElseWasmExecutor { native_version: D::native_version(), wasm }
+		NativeElseWasmExecutor { native_version: D::native_version(), wasm, use_native: true }
 	}
 
 	/// Create a new instance using the given [`WasmExecutor`].
@@ -610,7 +611,14 @@ impl<D: NativeExecutionDispatch> NativeElseWasmExecutor<D> {
 			ExtendedHostFunctions<sp_io::SubstrateHostFunctions, D::ExtendHostFunctions>,
 		>,
 	) -> Self {
-		Self { native_version: D::native_version(), wasm: executor }
+		Self { native_version: D::native_version(), wasm: executor, use_native: true }
+	}
+
+	/// Disable to use native runtime when possible just behave like `WasmExecutor`.
+	///
+	/// Default to enabled.
+	pub fn disable_use_native(&mut self) {
+		self.use_native = false;
 	}
 
 	/// Ignore missing function imports if set true.
@@ -645,9 +653,10 @@ impl<D: NativeExecutionDispatch + 'static> CodeExecutor for NativeElseWasmExecut
 		runtime_code: &RuntimeCode,
 		method: &str,
 		data: &[u8],
-		use_native: bool,
 		context: CallContext,
 	) -> (Result<Vec<u8>>, bool) {
+		let use_native = self.use_native;
+
 		tracing::trace!(
 			target: "executor",
 			function = %method,
@@ -711,7 +720,11 @@ impl<D: NativeExecutionDispatch + 'static> CodeExecutor for NativeElseWasmExecut
 
 impl<D: NativeExecutionDispatch> Clone for NativeElseWasmExecutor<D> {
 	fn clone(&self) -> Self {
-		NativeElseWasmExecutor { native_version: D::native_version(), wasm: self.wasm.clone() }
+		NativeElseWasmExecutor {
+			native_version: D::native_version(),
+			wasm: self.wasm.clone(),
+			use_native: self.use_native,
+		}
 	}
 }
 
diff --git a/substrate/primitives/core/src/traits.rs b/substrate/primitives/core/src/traits.rs
index 9815c84f339..851d8910391 100644
--- a/substrate/primitives/core/src/traits.rs
+++ b/substrate/primitives/core/src/traits.rs
@@ -51,7 +51,6 @@ pub trait CodeExecutor: Sized + Send + Sync + ReadRuntimeVersion + Clone + 'stat
 		runtime_code: &RuntimeCode,
 		method: &str,
 		data: &[u8],
-		use_native: bool,
 		context: CallContext,
 	) -> (Result<Vec<u8>, Self::Error>, bool);
 }
diff --git a/substrate/primitives/state-machine/src/lib.rs b/substrate/primitives/state-machine/src/lib.rs
index 0e2b9bfdfff..1345097e8f6 100644
--- a/substrate/primitives/state-machine/src/lib.rs
+++ b/substrate/primitives/state-machine/src/lib.rs
@@ -289,7 +289,7 @@ mod execution {
 
 			let result = self
 				.exec
-				.call(&mut ext, self.runtime_code, self.method, self.call_data, false, self.context)
+				.call(&mut ext, self.runtime_code, self.method, self.call_data, self.context)
 				.0;
 
 			self.overlay
@@ -1120,10 +1120,9 @@ mod tests {
 			_: &RuntimeCode,
 			_method: &str,
 			_data: &[u8],
-			use_native: bool,
 			_: CallContext,
 		) -> (CallResult<Self::Error>, bool) {
-			let using_native = use_native && self.native_available;
+			let using_native = self.native_available;
 			match (using_native, self.native_succeeds, self.fallback_succeeds) {
 				(true, true, _) | (false, _, true) => (
 					Ok(vec![
diff --git a/substrate/test-utils/client/src/lib.rs b/substrate/test-utils/client/src/lib.rs
index 084dd2a1861..f383f7c3dc3 100644
--- a/substrate/test-utils/client/src/lib.rs
+++ b/substrate/test-utils/client/src/lib.rs
@@ -263,9 +263,10 @@ impl<Block: BlockT, D, Backend, G: GenesisInit>
 		D: sc_executor::NativeExecutionDispatch + 'static,
 		Backend: sc_client_api::backend::Backend<Block> + 'static,
 	{
-		let executor = executor.into().unwrap_or_else(|| {
+		let mut executor = executor.into().unwrap_or_else(|| {
 			NativeElseWasmExecutor::new_with_wasm_executor(WasmExecutor::builder().build())
 		});
+		executor.disable_use_native();
 		let executor = LocalCallExecutor::new(
 			self.backend.clone(),
 			executor.clone(),
-- 
GitLab