@@ -160,6 +160,25 @@ pub enum InternalError {
160160 WasmWorker ( String ) ,
161161}
162162
163+ /// A cache of executors for different parachain Wasm instances.
164+ ///
165+ /// This should be reused across candidate validation instances.
166+ pub struct ExecutorCache ( sc_executor:: WasmExecutor ) ;
167+
168+ impl Default for ExecutorCache {
169+ fn default ( ) -> Self {
170+ ExecutorCache ( sc_executor:: WasmExecutor :: new (
171+ #[ cfg( all( feature = "wasmtime" , not( any( target_os = "android" , target_os = "unknown" ) ) ) ) ]
172+ sc_executor:: WasmExecutionMethod :: Compiled ,
173+ #[ cfg( any( not( feature = "wasmtime" ) , target_os = "android" , target_os = "unknown" ) ) ]
174+ sc_executor:: WasmExecutionMethod :: Interpreted ,
175+ // TODO: Make sure we don't use more than 1GB: https://github.com/paritytech/polkadot/issues/699
176+ Some ( 1024 ) ,
177+ HostFunctions :: host_functions ( ) ,
178+ 8
179+ ) )
180+ }
181+ }
163182
164183/// Validate a candidate under the given validation code.
165184///
@@ -172,7 +191,12 @@ pub fn validate_candidate(
172191) -> Result < ValidationResult , ValidationError > {
173192 match isolation_strategy {
174193 IsolationStrategy :: InProcess => {
175- validate_candidate_internal ( validation_code, & params. encode ( ) , spawner)
194+ validate_candidate_internal (
195+ & ExecutorCache :: default ( ) ,
196+ validation_code,
197+ & params. encode ( ) ,
198+ spawner,
199+ )
176200 } ,
177201 #[ cfg( not( any( target_os = "android" , target_os = "unknown" ) ) ) ]
178202 IsolationStrategy :: ExternalProcessSelfHost ( pool) => {
@@ -193,30 +217,29 @@ type HostFunctions = sp_io::SubstrateHostFunctions;
193217///
194218/// This will fail if the validation code is not a proper parachain validation module.
195219pub fn validate_candidate_internal (
220+ executor : & ExecutorCache ,
196221 validation_code : & [ u8 ] ,
197222 encoded_call_data : & [ u8 ] ,
198223 spawner : impl SpawnNamed + ' static ,
199224) -> Result < ValidationResult , ValidationError > {
200- let executor = sc_executor:: WasmExecutor :: new (
201- #[ cfg( all( feature = "wasmtime" , not( any( target_os = "android" , target_os = "unknown" ) ) ) ) ]
202- sc_executor:: WasmExecutionMethod :: Compiled ,
203- #[ cfg( any( not( feature = "wasmtime" ) , target_os = "android" , target_os = "unknown" ) ) ]
204- sc_executor:: WasmExecutionMethod :: Interpreted ,
205- // TODO: Make sure we don't use more than 1GB: https://github.com/paritytech/polkadot/issues/699
206- Some ( 1024 ) ,
207- HostFunctions :: host_functions ( ) ,
208- 8
209- ) ;
225+ let executor = & executor. 0 ;
210226
211227 let mut extensions = Extensions :: new ( ) ;
212228 extensions. register ( sp_core:: traits:: TaskExecutorExt :: new ( spawner) ) ;
213229 extensions. register ( sp_core:: traits:: CallInWasmExt :: new ( executor. clone ( ) ) ) ;
214230
215231 let mut ext = ValidationExternalities ( extensions) ;
216232
233+ // Expensive, but not more-so than recompiling the wasm module.
234+ // And we need this hash to access the `sc_executor` cache.
235+ let code_hash = {
236+ use polkadot_core_primitives:: { BlakeTwo256 , HashT } ;
237+ BlakeTwo256 :: hash ( validation_code)
238+ } ;
239+
217240 let res = executor. call_in_wasm (
218241 validation_code,
219- None ,
242+ Some ( code_hash . as_bytes ( ) . to_vec ( ) ) ,
220243 "validate_block" ,
221244 encoded_call_data,
222245 & mut ext,
0 commit comments