@@ -18,7 +18,10 @@ use revm_database::{AccountState, DBErrorMarker};
1818use revm_primitives:: { address, Address , B256 , U256 } ;
1919use revm_state:: { AccountInfo , Bytecode , EvmState } ;
2020
21- use crate :: { ApplicationId , BaseRuntime , Batch , ContractRuntime , ExecutionError , ServiceRuntime } ;
21+ use crate :: {
22+ ApplicationId , BaseRuntime , Batch , ContractRuntime , EvmExecutionError , ExecutionError ,
23+ ServiceRuntime ,
24+ } ;
2225
2326// The runtime costs are not available in service operations.
2427// We need to set a limit to gas usage in order to avoid blocking
@@ -78,6 +81,10 @@ pub(crate) struct DatabaseRuntime<Runtime> {
7881 pub runtime : Arc < Mutex < Runtime > > ,
7982 /// The uncommitted changes to the contract.
8083 pub changes : EvmState ,
84+ /// Whether the contract has been instantiated in REVM.
85+ pub is_revm_instantiated : bool ,
86+ /// The error that can occur during runtime.
87+ pub error : Arc < Mutex < Option < String > > > ,
8188}
8289
8390impl < Runtime > Clone for DatabaseRuntime < Runtime > {
@@ -87,6 +94,8 @@ impl<Runtime> Clone for DatabaseRuntime<Runtime> {
8794 contract_address : self . contract_address ,
8895 runtime : self . runtime . clone ( ) ,
8996 changes : self . changes . clone ( ) ,
97+ is_revm_instantiated : self . is_revm_instantiated ,
98+ error : self . error . clone ( ) ,
9099 }
91100 }
92101}
@@ -131,19 +140,33 @@ impl<Runtime: BaseRuntime> DatabaseRuntime<Runtime> {
131140 contract_address : Address :: ZERO ,
132141 runtime : Arc :: new ( Mutex :: new ( runtime) ) ,
133142 changes : HashMap :: new ( ) ,
143+ is_revm_instantiated : false ,
144+ error : Arc :: new ( Mutex :: new ( None ) ) ,
134145 }
135146 }
136147
137148 /// Returns the current storage states and clears it to default.
138149 pub fn take_storage_stats ( & self ) -> StorageStats {
139- let mut storage_stats_read = self
140- . storage_stats
141- . lock ( )
142- . expect ( "The lock should be possible" ) ;
150+ let mut storage_stats_read = self . storage_stats . lock ( ) . unwrap ( ) ;
143151 let storage_stats = storage_stats_read. clone ( ) ;
144152 * storage_stats_read = StorageStats :: default ( ) ;
145153 storage_stats
146154 }
155+
156+ /// Insert error into the database
157+ pub fn insert_error ( & self , exec_error : ExecutionError ) {
158+ let mut error = self . error . lock ( ) . unwrap ( ) ;
159+ * error = Some ( format ! ( "Runtime error {:?}" , exec_error) ) ;
160+ }
161+
162+ /// Process the error.
163+ pub fn process_any_error ( & self ) -> Result < ( ) , EvmExecutionError > {
164+ let error = self . error . lock ( ) . unwrap ( ) ;
165+ if let Some ( error) = error. clone ( ) {
166+ return Err ( EvmExecutionError :: RuntimeError ( error. clone ( ) ) ) ;
167+ }
168+ Ok ( ( ) )
169+ }
147170}
148171
149172impl DBErrorMarker for ExecutionError { }
@@ -191,7 +214,7 @@ where
191214 let account = self . changes . get ( & address) . unwrap ( ) ;
192215 return Ok ( Some ( account. info . clone ( ) ) ) ;
193216 }
194- let mut runtime = self . runtime . lock ( ) . expect ( "The lock should be possible" ) ;
217+ let mut runtime = self . runtime . lock ( ) . unwrap ( ) ;
195218 let key_info = self . get_address_key ( KeyCategory :: AccountInfo as u8 , address) ;
196219 let promise = runtime. read_value_bytes_new ( key_info) ?;
197220 let result = runtime. read_value_bytes_wait ( & promise) ?;
@@ -214,14 +237,11 @@ where
214237 let key_prefix = self . get_address_key ( KeyCategory :: Storage as u8 , address) ;
215238 let key = Self :: get_linera_key ( & key_prefix, index) ?;
216239 {
217- let mut storage_stats = self
218- . storage_stats
219- . lock ( )
220- . expect ( "The lock should be possible" ) ;
240+ let mut storage_stats = self . storage_stats . lock ( ) . unwrap ( ) ;
221241 storage_stats. key_read += 1 ;
222242 }
223243 let result = {
224- let mut runtime = self . runtime . lock ( ) . expect ( "The lock should be possible" ) ;
244+ let mut runtime = self . runtime . lock ( ) . unwrap ( ) ;
225245 let promise = runtime. read_value_bytes_new ( key) ?;
226246 runtime. read_value_bytes_wait ( & promise)
227247 } ?;
@@ -239,11 +259,8 @@ where
239259{
240260 /// Effectively commits changes to storage.
241261 pub fn commit_changes ( & mut self ) -> Result < ( ) , ExecutionError > {
242- let mut storage_stats = self
243- . storage_stats
244- . lock ( )
245- . expect ( "The lock should be possible" ) ;
246- let mut runtime = self . runtime . lock ( ) . expect ( "The lock should be possible" ) ;
262+ let mut storage_stats = self . storage_stats . lock ( ) . unwrap ( ) ;
263+ let mut runtime = self . runtime . lock ( ) . unwrap ( ) ;
247264 let mut batch = Batch :: new ( ) ;
248265 for ( address, account) in & self . changes {
249266 if !account. is_touched ( ) {
@@ -305,35 +322,53 @@ where
305322{
306323 /// Reads the nonce of the user
307324 pub fn get_nonce ( & self , address : & Address ) -> Result < u64 , ExecutionError > {
308- let account_info = self . basic_ref ( * address) ?;
325+ let account_info: Option < AccountInfo > = self . basic_ref ( * address) ?;
309326 Ok ( match account_info {
310327 None => 0 ,
311328 Some ( account_info) => account_info. nonce ,
312329 } )
313330 }
314331
332+ pub fn get_deployed_bytecode ( & self ) -> Result < Vec < u8 > , ExecutionError > {
333+ let account_info = self . basic_ref ( self . contract_address ) ?;
334+ Ok ( match account_info {
335+ None => Vec :: new ( ) ,
336+ Some ( account_info) => {
337+ let bytecode = account_info
338+ . code
339+ . ok_or ( EvmExecutionError :: MissingBytecode ) ?;
340+ bytecode. bytes_ref ( ) . to_vec ( )
341+ }
342+ } )
343+ }
344+
315345 /// Sets the EVM contract address from the value Address::ZERO.
316346 /// The value is set from the `ApplicationId`.
317347 pub fn set_contract_address ( & mut self ) -> Result < ( ) , ExecutionError > {
318- let mut runtime = self . runtime . lock ( ) . expect ( "The lock should be possible" ) ;
348+ let mut runtime = self . runtime . lock ( ) . unwrap ( ) ;
319349 let application_id = runtime. application_id ( ) ?;
320350 self . contract_address = application_id_to_address ( application_id) ;
321351 Ok ( ( ) )
322352 }
323353
324- /// Checks if the contract is already initialized. It is possible
325- /// that the constructor has not yet been called.
326- pub fn is_initialized ( & self ) -> Result < bool , ExecutionError > {
327- let mut runtime = self . runtime . lock ( ) . expect ( "The lock should be possible" ) ;
354+ /// A contract is called initialized if the execution of the constructor
355+ /// with the constructor argument yield the storage and the deployed
356+ /// bytecode. The deployed bytecode is stored in the storage of the
357+ /// bytecode address.
358+ /// We determine whether the contract is already initialized, sets the
359+ /// `is_revm_initialized` and then returns the result.
360+ pub fn set_is_initialized ( & mut self ) -> Result < bool , ExecutionError > {
361+ let mut runtime = self . runtime . lock ( ) . unwrap ( ) ;
328362 let evm_address = runtime. application_id ( ) ?. evm_address ( ) ;
329363 let key_info = self . get_address_key ( KeyCategory :: AccountInfo as u8 , evm_address) ;
330364 let promise = runtime. contains_key_new ( key_info) ?;
331365 let result = runtime. contains_key_wait ( & promise) ?;
366+ self . is_revm_instantiated = result;
332367 Ok ( result)
333368 }
334369
335370 pub fn get_block_env ( & self ) -> Result < BlockEnv , ExecutionError > {
336- let mut runtime = self . runtime . lock ( ) . expect ( "The lock should be possible" ) ;
371+ let mut runtime = self . runtime . lock ( ) . unwrap ( ) ;
337372 // The block height being used
338373 let block_height_linera = runtime. block_height ( ) ?;
339374 let block_height_evm = block_height_linera. 0 ;
@@ -376,7 +411,7 @@ where
376411 }
377412
378413 pub fn constructor_argument ( & self ) -> Result < Vec < u8 > , ExecutionError > {
379- let mut runtime = self . runtime . lock ( ) . expect ( "The lock should be possible" ) ;
414+ let mut runtime = self . runtime . lock ( ) . unwrap ( ) ;
380415 let constructor_argument = runtime. application_parameters ( ) ?;
381416 Ok ( serde_json:: from_slice :: < Vec < u8 > > ( & constructor_argument) ?)
382417 }
@@ -388,7 +423,7 @@ where
388423{
389424 pub fn get_contract_block_env ( & self ) -> Result < BlockEnv , ExecutionError > {
390425 let mut block_env = self . get_block_env ( ) ?;
391- let mut runtime = self . runtime . lock ( ) . expect ( "The lock should be possible" ) ;
426+ let mut runtime = self . runtime . lock ( ) . unwrap ( ) ;
392427 // We use the gas_limit from the runtime
393428 let gas_limit = runtime. maximum_fuel_per_block ( VmRuntime :: Evm ) ?;
394429 block_env. gas_limit = gas_limit;
0 commit comments