3333//!
3434//! Often there is a need for having multiple chain extensions. This is often the case when
3535//! some generally useful off-the-shelf extensions should be included. To have multiple chain
36- //! extensions they can be put into a tuple which is then passed to `[ Config::ChainExtension]` like
36+ //! extensions they can be put into a tuple which is then passed to [` Config::ChainExtension`] like
3737//! this `type Extensions = (ExtensionA, ExtensionB)`.
3838//!
3939//! However, only extensions implementing [`RegisteredChainExtension`] can be put into a tuple.
@@ -94,6 +94,12 @@ pub type Result<T> = sp_std::result::Result<T, DispatchError>;
9494/// In order to create a custom chain extension this trait must be implemented and supplied
9595/// to the pallet contracts configuration trait as the associated type of the same name.
9696/// Consult the [module documentation](self) for a general explanation of chain extensions.
97+ ///
98+ /// # Lifetime
99+ ///
100+ /// The extension will be [`Default`] initialized at the beginning of each call
101+ /// (**not** per call stack) and dropped afterwards. Hence any value held inside the extension
102+ /// can be used as a per-call scratch buffer.
97103pub trait ChainExtension < C : Config > {
98104 /// Call the chain extension logic.
99105 ///
@@ -102,16 +108,14 @@ pub trait ChainExtension<C: Config> {
102108 /// imported wasm function.
103109 ///
104110 /// # Parameters
105- /// - `func_id`: The first argument to `seal_call_chain_extension`. Usually used to determine
106- /// which function to realize.
107111 /// - `env`: Access to the remaining arguments and the execution environment.
108112 ///
109113 /// # Return
110114 ///
111115 /// In case of `Err` the contract execution is immediately suspended and the passed error
112116 /// is returned to the caller. Otherwise the value of [`RetVal`] determines the exit
113117 /// behaviour.
114- fn call < E > ( func_id : u32 , env : Environment < E , InitState > ) -> Result < RetVal >
118+ fn call < E > ( & mut self , env : Environment < E , InitState > ) -> Result < RetVal >
115119 where
116120 E : Ext < T = C > ,
117121 <E :: T as SysConfig >:: AccountId : UncheckedFrom < <E :: T as SysConfig >:: Hash > + AsRef < [ u8 ] > ;
@@ -132,7 +136,7 @@ pub trait ChainExtension<C: Config> {
132136///
133137/// An extension that implements this trait can be put in a tuple in order to have multiple
134138/// extensions available. The tuple implementation routes requests based on the first two
135- /// most significant bytes of the `func_id ` passed to `call`.
139+ /// most significant bytes of the `id ` passed to `call`.
136140///
137141/// If this extensions is to be used by multiple runtimes consider
138142/// [registering it](https://github.com/paritytech/chainextension-registry) to ensure that there
@@ -150,15 +154,15 @@ pub trait RegisteredChainExtension<C: Config>: ChainExtension<C> {
150154#[ impl_trait_for_tuples:: impl_for_tuples( 10 ) ]
151155#[ tuple_types_custom_trait_bound( RegisteredChainExtension <C >) ]
152156impl < C : Config > ChainExtension < C > for Tuple {
153- fn call < E > ( func_id : u32 , mut env : Environment < E , InitState > ) -> Result < RetVal >
157+ fn call < E > ( & mut self , mut env : Environment < E , InitState > ) -> Result < RetVal >
154158 where
155159 E : Ext < T = C > ,
156160 <E :: T as SysConfig >:: AccountId : UncheckedFrom < <E :: T as SysConfig >:: Hash > + AsRef < [ u8 ] > ,
157161 {
158162 for_tuples ! (
159163 #(
160- if ( Tuple :: ID == ( func_id >> 16 ) as u16 ) && Tuple :: enabled( ) {
161- return Tuple :: call( func_id , env) ;
164+ if ( Tuple :: ID == env . ext_id ( ) ) && Tuple :: enabled( ) {
165+ return Tuple . call( env) ;
162166 }
163167 ) *
164168 ) ;
@@ -206,6 +210,22 @@ impl<'a, 'b, E: Ext, S: state::State> Environment<'a, 'b, E, S>
206210where
207211 <E :: T as SysConfig >:: AccountId : UncheckedFrom < <E :: T as SysConfig >:: Hash > + AsRef < [ u8 ] > ,
208212{
213+ /// The function id within the `id` passed by a contract.
214+ ///
215+ /// It returns the two least significant bytes of the `id` passed by a contract as the other
216+ /// two bytes represent the chain extension itself (the code which is calling this function).
217+ pub fn func_id ( & self ) -> u16 {
218+ ( self . inner . id & 0x00FF ) as u16
219+ }
220+
221+ /// The chain extension id within the `id` passed by a contract.
222+ ///
223+ /// It returns the two most significant bytes of the `id` passed by a contract which represent
224+ /// the chain extension itself (the code which is calling this function).
225+ pub fn ext_id ( & self ) -> u16 {
226+ ( self . inner . id >> 16 ) as u16
227+ }
228+
209229 /// Charge the passed `amount` of weight from the overall limit.
210230 ///
211231 /// It returns `Ok` when there the remaining weight budget is larger than the passed
@@ -251,13 +271,14 @@ impl<'a, 'b, E: Ext> Environment<'a, 'b, E, state::Init> {
251271 /// ever create this type. Chain extensions merely consume it.
252272 pub ( crate ) fn new (
253273 runtime : & ' a mut Runtime < ' b , E > ,
274+ id : u32 ,
254275 input_ptr : u32 ,
255276 input_len : u32 ,
256277 output_ptr : u32 ,
257278 output_len_ptr : u32 ,
258279 ) -> Self {
259280 Environment {
260- inner : Inner { runtime, input_ptr, input_len, output_ptr, output_len_ptr } ,
281+ inner : Inner { runtime, id , input_ptr, input_len, output_ptr, output_len_ptr } ,
261282 phantom : PhantomData ,
262283 }
263284 }
@@ -406,6 +427,8 @@ struct Inner<'a, 'b, E: Ext> {
406427 /// The runtime contains all necessary functions to interact with the running contract.
407428 runtime : & ' a mut Runtime < ' b , E > ,
408429 /// Verbatim argument passed to `seal_call_chain_extension`.
430+ id : u32 ,
431+ /// Verbatim argument passed to `seal_call_chain_extension`.
409432 input_ptr : u32 ,
410433 /// Verbatim argument passed to `seal_call_chain_extension`.
411434 input_len : u32 ,
0 commit comments