@@ -28,36 +28,71 @@ use sp_state_machine::{
2828use  sc_executor:: { RuntimeVersion ,  RuntimeInfo ,  NativeVersion } ; 
2929use  sp_externalities:: Extensions ; 
3030use  sp_core:: { 
31- 	NativeOrEncoded ,  NeverNativeValue ,  traits:: { CodeExecutor ,  SpawnNamed } , 
31+ 	NativeOrEncoded ,  NeverNativeValue ,  traits:: { CodeExecutor ,  SpawnNamed ,   RuntimeCode } , 
3232	offchain:: storage:: OffchainOverlayedChanges , 
3333} ; 
3434use  sp_api:: { ProofRecorder ,  InitializeBlock ,  StorageTransactionCache } ; 
3535use  sc_client_api:: { backend,  call_executor:: CallExecutor } ; 
36- use  super :: client:: ClientConfig ; 
36+ use  super :: { client:: ClientConfig ,  wasm_override :: WasmOverride } ; 
3737
3838/// Call executor that executes methods locally, querying all required 
3939/// data from local backend. 
4040pub  struct  LocalCallExecutor < B ,  E >  { 
4141	backend :  Arc < B > , 
4242	executor :  E , 
43+ 	wasm_override :  Option < WasmOverride < E > > , 
4344	spawn_handle :  Box < dyn  SpawnNamed > , 
4445	client_config :  ClientConfig , 
4546} 
4647
47- impl < B ,  E >  LocalCallExecutor < B ,  E >  { 
48+ impl < B ,  E >  LocalCallExecutor < B ,  E > 
49+ where 
50+ 	E :  CodeExecutor  + RuntimeInfo  + Clone  + ' static 
51+ { 
4852	/// Creates new instance of local call executor. 
4953 	pub  fn  new ( 
5054		backend :  Arc < B > , 
5155		executor :  E , 
5256		spawn_handle :  Box < dyn  SpawnNamed > , 
5357		client_config :  ClientConfig , 
54- 	)  -> Self  { 
55- 		LocalCallExecutor  { 
58+ 	)  -> sp_blockchain:: Result < Self >  { 
59+ 		let  wasm_override = client_config. wasm_runtime_overrides 
60+ 			. as_ref ( ) 
61+ 			. map ( |p| WasmOverride :: new ( p. clone ( ) ,  executor. clone ( ) ) ) 
62+ 			. transpose ( ) ?; 
63+ 
64+ 		Ok ( LocalCallExecutor  { 
5665			backend, 
5766			executor, 
67+ 			wasm_override, 
5868			spawn_handle, 
5969			client_config, 
60- 		} 
70+ 		} ) 
71+ 	} 
72+ 
73+ 	/// Check if local runtime code overrides are enabled and one is available 
74+  	/// for the given `BlockId`. If yes, return it; otherwise return the same 
75+  	/// `RuntimeCode` instance that was passed. 
76+  	fn  check_override < ' a ,  Block > ( 
77+ 		& ' a  self , 
78+ 		onchain_code :  RuntimeCode < ' a > , 
79+ 		id :  & BlockId < Block > , 
80+ 	)  -> sp_blockchain:: Result < RuntimeCode < ' a > > 
81+ 	where 
82+ 		Block :  BlockT , 
83+ 		B :  backend:: Backend < Block > , 
84+ 	{ 
85+ 		let  code = self . wasm_override 
86+ 			. as_ref ( ) 
87+ 			. map :: < sp_blockchain:: Result < Option < RuntimeCode > > ,  _ > ( |o| { 
88+ 				let  spec = self . runtime_version ( id) ?. spec_version ; 
89+ 				Ok ( o. get ( & spec,  onchain_code. heap_pages ) ) 
90+ 			} ) 
91+ 			. transpose ( ) ?
92+ 			. flatten ( ) 
93+ 			. unwrap_or ( onchain_code) ; 
94+ 
95+ 		Ok ( code) 
6196	} 
6297} 
6398
@@ -66,6 +101,7 @@ impl<B, E> Clone for LocalCallExecutor<B, E> where E: Clone {
66101		LocalCallExecutor  { 
67102			backend :  self . backend . clone ( ) , 
68103			executor :  self . executor . clone ( ) , 
104+ 			wasm_override :  self . wasm_override . clone ( ) , 
69105			spawn_handle :  self . spawn_handle . clone ( ) , 
70106			client_config :  self . client_config . clone ( ) , 
71107		} 
@@ -101,6 +137,8 @@ where
101137		) ?; 
102138		let  state = self . backend . state_at ( * id) ?; 
103139		let  state_runtime_code = sp_state_machine:: backend:: BackendRuntimeCode :: new ( & state) ; 
140+ 		let  runtime_code = self . check_override ( state_runtime_code. runtime_code ( ) ?,  id) ?; 
141+ 
104142		let  return_data = StateMachine :: new ( 
105143			& state, 
106144			changes_trie, 
@@ -110,7 +148,7 @@ where
110148			method, 
111149			call_data, 
112150			extensions. unwrap_or_default ( ) , 
113- 			& state_runtime_code . runtime_code ( ) ? , 
151+ 			& runtime_code, 
114152			self . spawn_handle . clone ( ) , 
115153		) . execute_using_consensus_failure_handler :: < _ ,  NeverNativeValue ,  fn ( )  -> _ > ( 
116154			strategy. get_manager ( ) , 
@@ -173,7 +211,7 @@ where
173211				let  state_runtime_code = sp_state_machine:: backend:: BackendRuntimeCode :: new ( & trie_state) ; 
174212				// It is important to extract the runtime code here before we create the proof 
175213				// recorder. 
176- 				let  runtime_code = state_runtime_code. runtime_code ( ) ?; 
214+ 				let  runtime_code = self . check_override ( state_runtime_code. runtime_code ( ) ? ,  at ) ?; 
177215
178216				let  backend = sp_state_machine:: ProvingBackend :: new_with_recorder ( 
179217					trie_state, 
@@ -198,7 +236,8 @@ where
198236			} , 
199237			None  => { 
200238				let  state_runtime_code = sp_state_machine:: backend:: BackendRuntimeCode :: new ( & state) ; 
201- 				let  runtime_code = state_runtime_code. runtime_code ( ) ?; 
239+ 				let  runtime_code = self . check_override ( state_runtime_code. runtime_code ( ) ?,  at) ?; 
240+ 
202241				let  mut  state_machine = StateMachine :: new ( 
203242					& state, 
204243					changes_trie_state, 
@@ -279,3 +318,66 @@ impl<B, E, Block> sp_version::GetRuntimeVersion<Block> for LocalCallExecutor<B,
279318		CallExecutor :: runtime_version ( self ,  at) . map_err ( |e| format ! ( "{:?}" ,  e) ) 
280319	} 
281320} 
321+ 
322+ #[ cfg( test) ]  
323+ mod  tests { 
324+ 	use  super :: * ; 
325+ 	use  substrate_test_runtime_client:: { LocalExecutor ,  GenesisInit ,  runtime} ; 
326+ 	use  sc_executor:: { NativeExecutor ,  WasmExecutionMethod } ; 
327+ 	use  sp_core:: { traits:: { WrappedRuntimeCode ,  FetchRuntimeCode } ,  testing:: TaskExecutor } ; 
328+ 	use  sc_client_api:: in_mem; 
329+ 
330+ 	#[ test]  
331+ 	fn  should_get_override_if_exists ( )  { 
332+ 		let  executor =
333+ 			NativeExecutor :: < LocalExecutor > :: new ( WasmExecutionMethod :: Interpreted ,  Some ( 128 ) ,  1 ) ; 
334+ 
335+ 		let  overrides = crate :: client:: wasm_override:: dummy_overrides ( & executor) ; 
336+ 		let  onchain_code = WrappedRuntimeCode ( substrate_test_runtime:: wasm_binary_unwrap ( ) . into ( ) ) ; 
337+ 		let  onchain_code = RuntimeCode  { 
338+ 			code_fetcher :  & onchain_code, 
339+ 			heap_pages :  Some ( 128 ) , 
340+ 			hash :  vec ! [ 0 ,  0 ,  0 ,  0 ] , 
341+ 		} ; 
342+ 
343+ 		let  backend = Arc :: new ( in_mem:: Backend :: < runtime:: Block > :: new ( ) ) ; 
344+ 
345+ 		// wasm_runtime_overrides is `None` here because we construct the 
346+ 		// LocalCallExecutor directly later on 
347+ 		let  client_config = ClientConfig  { 
348+ 			offchain_worker_enabled :  false , 
349+ 			offchain_indexing_api :  false , 
350+ 			wasm_runtime_overrides :  None , 
351+ 		} ; 
352+ 
353+ 		// client is used for the convenience of creating and inserting the genesis block. 
354+ 		let  _client = substrate_test_runtime_client:: client:: new_with_backend :: < 
355+ 			_ , 
356+ 			_ , 
357+ 			runtime:: Block , 
358+ 			_ , 
359+ 			runtime:: RuntimeApi , 
360+ 		> ( 
361+ 			backend. clone ( ) , 
362+ 			executor. clone ( ) , 
363+ 			& substrate_test_runtime_client:: GenesisParameters :: default ( ) . genesis_storage ( ) , 
364+ 			None , 
365+ 			Box :: new ( TaskExecutor :: new ( ) ) , 
366+ 			None , 
367+ 			Default :: default ( ) , 
368+ 		) . expect ( "Creates a client" ) ; 
369+ 
370+ 		let  call_executor = LocalCallExecutor  { 
371+ 			backend :  backend. clone ( ) , 
372+ 			executor, 
373+ 			wasm_override :  Some ( overrides) , 
374+ 			spawn_handle :  Box :: new ( TaskExecutor :: new ( ) ) , 
375+ 			client_config, 
376+ 		} ; 
377+ 
378+ 		let  check = call_executor. check_override ( onchain_code,  & BlockId :: Number ( Default :: default ( ) ) ) 
379+ 			. expect ( "RuntimeCode override" ) ; 
380+ 
381+ 		assert_eq ! ( Some ( vec![ 2 ,  2 ,  2 ,  2 ,  2 ,  2 ,  2 ,  2 ] ) ,  check. fetch_runtime_code( ) . map( Into :: into) ) ; 
382+ 	} 
383+ } 
0 commit comments