1use std::{
8 collections::HashMap,
9 mem,
10 ops::DerefMut,
11 sync::{Arc, Mutex},
12};
13
14use linera_base::{
15 data_types::Amount,
16 ensure,
17 identifiers::{self, ApplicationId, ModuleId},
18 vm::{EvmInstantiation, EvmQuery, VmRuntime},
19};
20use linera_views::common::from_bytes_option;
21use revm::{primitives::keccak256, Database, DatabaseCommit, DatabaseRef};
22use revm_context::BlockEnv;
23use revm_context_interface::block::BlobExcessGasAndPrice;
24use revm_database::DBErrorMarker;
25use revm_primitives::{address, Address, B256, KECCAK_EMPTY, U256};
26use revm_state::{AccountInfo, Bytecode, EvmState};
27
28use crate::{
29 evm::{
30 inputs::{FAUCET_ADDRESS, FAUCET_BALANCE, ZERO_ADDRESS},
31 revm::{
32 address_to_user_application_id, ALREADY_CREATED_CONTRACT_SELECTOR,
33 COMMIT_CONTRACT_CHANGES_SELECTOR, GET_ACCOUNT_INFO_SELECTOR,
34 GET_CONTRACT_STORAGE_SELECTOR, JSON_EMPTY_VECTOR,
35 },
36 },
37 BaseRuntime, Batch, ContractRuntime, EvmExecutionError, ExecutionError, ServiceRuntime,
38};
39
40pub const EVM_SERVICE_GAS_LIMIT: u64 = 20_000_000;
45
46impl DBErrorMarker for ExecutionError {}
47
48pub(crate) struct InnerDatabase<Runtime> {
66 pub contract_address: Address,
71
72 pub caller: Address,
78
79 pub value: U256,
83
84 pub runtime: Arc<Mutex<Runtime>>,
89
90 pub changes: EvmState,
96
97 pub is_revm_instantiated: bool,
102
103 pub error: Arc<Mutex<Option<String>>>,
109}
110
111impl<Runtime> Clone for InnerDatabase<Runtime> {
112 fn clone(&self) -> Self {
113 Self {
114 contract_address: self.contract_address,
115 caller: self.caller,
116 value: self.value,
117 runtime: self.runtime.clone(),
118 changes: self.changes.clone(),
119 is_revm_instantiated: self.is_revm_instantiated,
120 error: self.error.clone(),
121 }
122 }
123}
124
125fn get_storage_key(index: U256) -> Vec<u8> {
128 let mut key = vec![KeyCategory::Storage as u8];
129 key.extend(index.as_le_slice());
130 key
131}
132
133fn get_category_key(category: KeyCategory) -> Vec<u8> {
135 vec![category as u8]
136}
137
138impl<Runtime> InnerDatabase<Runtime>
139where
140 Runtime: BaseRuntime,
141{
142 pub fn new(runtime: Runtime) -> Self {
149 Self {
150 contract_address: Address::ZERO,
151 caller: Address::ZERO,
152 value: U256::ZERO,
153 runtime: Arc::new(Mutex::new(runtime)),
154 changes: HashMap::new(),
155 is_revm_instantiated: false,
156 error: Arc::new(Mutex::new(None)),
157 }
158 }
159
160 pub fn lock_runtime(&self) -> std::sync::MutexGuard<'_, Runtime> {
172 self.runtime.lock().unwrap()
173 }
174
175 pub fn insert_error(&self, exec_error: &ExecutionError) {
180 let mut error = self.error.lock().unwrap();
181 *error = Some(format!("Runtime error {:?}", exec_error));
182 }
183
184 pub fn process_any_error(&self) -> Result<(), EvmExecutionError> {
193 let error = self.error.lock().unwrap();
194 if let Some(error) = error.clone() {
195 return Err(EvmExecutionError::RuntimeError(error.clone()));
196 }
197 Ok(())
198 }
199
200 fn read_basic_ref(
226 &self,
227 f: fn(&Self, Address) -> Result<Option<AccountInfo>, ExecutionError>,
228 address: Address,
229 is_newly_created: bool,
230 ) -> Result<Option<AccountInfo>, ExecutionError> {
231 if address == FAUCET_ADDRESS {
232 return Ok(Some(AccountInfo {
233 balance: FAUCET_BALANCE,
234 ..AccountInfo::default()
235 }));
236 }
237 let mut account_info = self
238 .account_info_from_storage(f, address)?
239 .unwrap_or_default();
240 if !is_newly_created {
241 account_info.balance = self.get_start_balance(address)?;
243 }
244 Ok(Some(account_info))
247 }
248
249 fn account_info_from_local_storage(&self) -> Result<Option<AccountInfo>, ExecutionError> {
251 let mut runtime = self.runtime.lock().unwrap();
252 let key_info = get_category_key(KeyCategory::AccountInfo);
253 let promise = runtime.read_value_bytes_new(key_info)?;
254 let result = runtime.read_value_bytes_wait(&promise)?;
255 Ok(from_bytes_option::<AccountInfo>(&result)?)
256 }
257
258 fn account_info_from_inner_database(
267 &self,
268 address: Address,
269 ) -> Result<Option<AccountInfo>, ExecutionError> {
270 if !self.changes.is_empty() {
271 let account = self.changes.get(&address);
277 return Ok(account.map(|account| account.info.clone()));
278 }
279 if address == self.contract_address {
280 self.account_info_from_local_storage()
282 } else {
283 Ok(None)
285 }
286 }
287
288 fn account_info_from_storage(
290 &self,
291 f: fn(&Self, Address) -> Result<Option<AccountInfo>, ExecutionError>,
292 address: Address,
293 ) -> Result<Option<AccountInfo>, ExecutionError> {
294 let account_info = self.account_info_from_inner_database(address)?;
295 if let Some(account_info) = account_info {
296 return Ok(Some(account_info));
298 }
299 if self.has_empty_storage(address)? {
300 Ok(None)
302 } else {
303 f(self, address)
305 }
306 }
307
308 fn has_empty_storage(&self, address: Address) -> Result<bool, ExecutionError> {
312 let application_id = address_to_user_application_id(address);
313 let mut runtime = self.runtime.lock().unwrap();
314 runtime.has_empty_storage(application_id)
315 }
316
317 fn get_start_balance(&self, address: Address) -> Result<U256, ExecutionError> {
336 let mut runtime = self.runtime.lock().unwrap();
337 let account_owner = address.into();
338 let balance = runtime.read_owner_balance(account_owner)?;
339 let balance: U256 = balance.into();
340
341 Ok(if self.caller == address {
342 balance + self.value
344 } else if self.contract_address == address {
345 assert!(
347 balance >= self.value,
348 "Contract balance should be >= transferred value"
349 );
350 balance - self.value
351 } else {
352 balance
354 })
355 }
356
357 pub fn get_account_info(&self) -> Result<AccountInfo, ExecutionError> {
358 let address = self.contract_address;
359 let account_info = self.account_info_from_inner_database(address)?;
360 let mut account_info = account_info.ok_or(EvmExecutionError::MissingAccountInfo)?;
361 account_info.balance = self.get_start_balance(address)?;
362 Ok(account_info)
363 }
364
365 fn read_storage(
370 &self,
371 f: fn(&Self, Address, U256) -> Result<U256, ExecutionError>,
372 address: Address,
373 index: U256,
374 ) -> Result<U256, ExecutionError> {
375 if !self.changes.is_empty() {
376 let account = self.changes.get(&address).unwrap();
379 return Ok(match account.storage.get(&index) {
380 None => U256::ZERO,
381 Some(slot) => slot.present_value(),
382 });
383 }
384 if address == self.contract_address {
385 return self.read_from_local_storage(index);
388 }
389 f(self, address, index)
391 }
392
393 pub fn read_from_local_storage(&self, index: U256) -> Result<U256, ExecutionError> {
395 let key = get_storage_key(index);
396 let mut runtime = self.runtime.lock().unwrap();
397 let promise = runtime.read_value_bytes_new(key)?;
398 let result = runtime.read_value_bytes_wait(&promise)?;
399 Ok(from_bytes_option::<U256>(&result)?.unwrap_or_default())
400 }
401
402 pub fn set_contract_address(&mut self) -> Result<(), ExecutionError> {
412 let mut runtime = self.runtime.lock().unwrap();
413 let application_id = runtime.application_id()?;
414 self.contract_address = application_id.evm_address();
415 Ok(())
416 }
417
418 pub fn set_is_initialized(&mut self) -> Result<bool, ExecutionError> {
438 let mut runtime = self.runtime.lock().unwrap();
439 let key_info = get_category_key(KeyCategory::AccountInfo);
440 let promise = runtime.contains_key_new(key_info)?;
441 let result = runtime.contains_key_wait(&promise)?;
442 self.is_revm_instantiated = result;
443 Ok(result)
444 }
445
446 pub fn get_block_env(&self) -> Result<BlockEnv, ExecutionError> {
447 let mut runtime = self.runtime.lock().unwrap();
448 let block_height_linera = runtime.block_height()?;
450 let block_height_evm = block_height_linera.0;
451 let beneficiary = address!("00000000000000000000000000000000000000bb");
453 let difficulty = U256::ZERO;
455 let gas_limit = u64::MAX;
458 let timestamp_linera = runtime.read_system_timestamp()?;
462 let timestamp_evm = timestamp_linera.micros() / 1_000_000;
463 let basefee = 0;
466 let chain_id = runtime.chain_id()?;
467 let entry = format!("{}{}", chain_id, block_height_linera);
468 let prevrandao = keccak256(entry.as_bytes());
470 let entry = BlobExcessGasAndPrice {
473 excess_blob_gas: 0,
474 blob_gasprice: 1,
475 };
476 let blob_excess_gas_and_price = Some(entry);
477 Ok(BlockEnv {
478 number: block_height_evm,
479 beneficiary,
480 difficulty,
481 gas_limit,
482 timestamp: timestamp_evm,
483 basefee,
484 prevrandao: Some(prevrandao),
485 blob_excess_gas_and_price,
486 })
487 }
488
489 pub fn constructor_argument(&self) -> Result<Vec<u8>, ExecutionError> {
490 let mut runtime = self.runtime.lock().unwrap();
491 let constructor_argument = runtime.application_parameters()?;
492 Ok(serde_json::from_slice::<Vec<u8>>(&constructor_argument)?)
493 }
494}
495
496impl<Runtime> InnerDatabase<Runtime>
497where
498 Runtime: ContractRuntime,
499{
500 fn get_contract_account_info(
502 &self,
503 address: Address,
504 ) -> Result<Option<AccountInfo>, ExecutionError> {
505 let application_id = address_to_user_application_id(address);
506 let argument = GET_ACCOUNT_INFO_SELECTOR.to_vec();
507 let mut runtime = self.runtime.lock().unwrap();
508 let account_info = runtime.try_call_application(false, application_id, argument)?;
509 let account_info = bcs::from_bytes(&account_info)?;
510 Ok(Some(account_info))
511 }
512
513 fn get_contract_storage_value(
515 &self,
516 address: Address,
517 index: U256,
518 ) -> Result<U256, ExecutionError> {
519 let application_id = address_to_user_application_id(address);
520 let mut argument = GET_CONTRACT_STORAGE_SELECTOR.to_vec();
521 argument.extend(bcs::to_bytes(&index)?);
522 let mut runtime = self.runtime.lock().unwrap();
523 let value = runtime.try_call_application(false, application_id, argument)?;
524 let value = bcs::from_bytes(&value)?;
525 Ok(value)
526 }
527
528 pub fn deposit_funds(&self) -> Result<(), ExecutionError> {
529 if self.value != U256::ZERO {
530 if self.caller == ZERO_ADDRESS {
531 let error = EvmExecutionError::UnknownSigner;
532 return Err(error.into());
533 }
534 let source = self.caller.into();
535 let amount = Amount::try_from(self.value).map_err(EvmExecutionError::from)?;
536 let mut runtime = self.runtime.lock().expect("The lock should be possible");
537 let chain_id = runtime.chain_id()?;
538 let application_id = runtime.application_id()?;
539 let owner = application_id.into();
540 let destination = identifiers::Account { chain_id, owner };
541 let authenticated_caller = runtime.authenticated_caller_id()?;
542 if authenticated_caller.is_none() {
543 runtime.transfer(source, destination, amount)?;
544 }
545 }
546 Ok(())
547 }
548}
549
550impl<Runtime> InnerDatabase<Runtime>
551where
552 Runtime: ServiceRuntime,
553{
554 fn get_service_account_info(
556 &self,
557 address: Address,
558 ) -> Result<Option<AccountInfo>, ExecutionError> {
559 let application_id = address_to_user_application_id(address);
560 let argument = serde_json::to_vec(&EvmQuery::AccountInfo)?;
561 let mut runtime = self.runtime.lock().expect("The lock should be possible");
562 let account_info = runtime.try_query_application(application_id, argument)?;
563 let account_info = serde_json::from_slice::<AccountInfo>(&account_info)?;
564 Ok(Some(account_info))
565 }
566
567 fn get_service_storage_value(
569 &self,
570 address: Address,
571 index: U256,
572 ) -> Result<U256, ExecutionError> {
573 let application_id = address_to_user_application_id(address);
574 let argument = serde_json::to_vec(&EvmQuery::Storage(index))?;
575 let mut runtime = self.runtime.lock().expect("The lock should be possible");
576 let value = runtime.try_query_application(application_id, argument)?;
577 let value = serde_json::from_slice::<U256>(&value)?;
578 Ok(value)
579 }
580}
581
582impl<Runtime> ContractDatabase<Runtime>
583where
584 Runtime: ContractRuntime,
585{
586 pub fn new(runtime: Runtime) -> Self {
587 Self {
588 inner: InnerDatabase::new(runtime),
589 modules: Arc::new(Mutex::new(HashMap::new())),
590 }
591 }
592
593 pub fn lock_runtime(&self) -> std::sync::MutexGuard<'_, Runtime> {
594 self.inner.lock_runtime()
595 }
596
597 fn check_balance(&self, address: Address, revm_balance: U256) -> Result<(), ExecutionError> {
601 let mut runtime = self.inner.runtime.lock().unwrap();
602 let owner = address.into();
603 let linera_balance: U256 = runtime.read_owner_balance(owner)?.into();
604 ensure!(
605 linera_balance == revm_balance,
606 EvmExecutionError::IncoherentBalances(address, linera_balance, revm_balance)
607 );
608 Ok(())
609 }
610
611 pub fn commit_contract_changes(
613 &self,
614 account: &revm_state::Account,
615 ) -> Result<(), ExecutionError> {
616 let mut runtime = self.inner.runtime.lock().unwrap();
617 let mut batch = Batch::new();
618 let key_prefix = get_category_key(KeyCategory::Storage);
619 let key_info = get_category_key(KeyCategory::AccountInfo);
620 if account.is_selfdestructed() {
621 batch.delete_key_prefix(key_prefix);
622 batch.put_key_value(key_info, &AccountInfo::default())?;
623 } else {
624 batch.put_key_value(key_info, &account.info)?;
625 for (index, value) in &account.storage {
626 if value.present_value() != value.original_value() {
627 let key = get_storage_key(*index);
628 if value.present_value() == U256::ZERO {
629 batch.delete_key(key);
630 } else {
631 batch.put_key_value(key, &value.present_value())?;
632 }
633 }
634 }
635 }
636 runtime.write_batch(batch)?;
637 Ok(())
638 }
639
640 fn is_account_writable(&self, address: &Address, account: &revm_state::Account) -> bool {
643 if *address == FAUCET_ADDRESS {
644 return false;
646 }
647 if !account.is_touched() {
648 return false;
650 }
651 let code_hash = account.info.code_hash;
652 let code_empty = code_hash == KECCAK_EMPTY || code_hash.is_zero();
656 !code_empty
657 }
658
659 fn is_account_checkable(&self, address: &Address) -> bool {
661 if *address == FAUCET_ADDRESS {
662 return false;
664 }
665 true
666 }
667
668 fn create_new_contract(
675 &self,
676 address: Address,
677 account: &revm_state::Account,
678 module_id: ModuleId,
679 ) -> Result<(), ExecutionError> {
680 let application_id = address_to_user_application_id(address);
681 let mut argument = ALREADY_CREATED_CONTRACT_SELECTOR.to_vec();
682 argument.extend(bcs::to_bytes(account)?);
683 let evm_instantiation = EvmInstantiation {
684 value: U256::ZERO,
685 argument,
686 };
687 let argument = serde_json::to_vec(&evm_instantiation)?;
688 let parameters = JSON_EMPTY_VECTOR.to_vec(); let required_application_ids = Vec::new();
690 let mut runtime = self.inner.runtime.lock().unwrap();
691 let created_application_id = runtime.create_application(
692 module_id,
693 parameters,
694 argument,
695 required_application_ids,
696 )?;
697 ensure!(
698 application_id == created_application_id,
699 EvmExecutionError::IncorrectApplicationId
700 );
701 Ok(())
702 }
703
704 fn commit_remote_contract(
707 &self,
708 address: Address,
709 account: &revm_state::Account,
710 ) -> Result<(), ExecutionError> {
711 let application_id = address_to_user_application_id(address);
712 let mut argument = COMMIT_CONTRACT_CHANGES_SELECTOR.to_vec();
713 argument.extend(bcs::to_bytes(account)?);
714 let mut runtime = self.inner.runtime.lock().unwrap();
715 runtime.try_call_application(false, application_id, argument)?;
716 Ok(())
717 }
718
719 pub fn commit_changes(&mut self) -> Result<(), ExecutionError> {
729 let changes = mem::take(&mut self.inner.changes);
730 let mut balances = Vec::new();
731 let modules = mem::take(self.modules.lock().unwrap().deref_mut());
732 let mut contracts_to_create = vec![None; modules.len()];
733 for (address, account) in changes {
734 if self.is_account_checkable(&address) {
735 let revm_balance = account.info.balance;
736 balances.push((address, revm_balance));
737 }
738 if self.is_account_writable(&address, &account) {
739 if address == self.inner.contract_address {
740 self.commit_contract_changes(&account)?;
741 } else {
742 let application_id = address_to_user_application_id(address);
743 if let Some((module_id, index)) = modules.get(&application_id) {
744 contracts_to_create[*index as usize] = Some((address, account, *module_id));
745 } else {
746 self.commit_remote_contract(address, &account)?;
747 }
748 }
749 }
750 }
751 for entry in contracts_to_create {
752 let (address, account, module_id) =
753 entry.expect("An entry since all have been matched above");
754 self.create_new_contract(address, &account, module_id)?;
755 }
756 for (address, revm_balance) in balances {
757 self.check_balance(address, revm_balance)?;
758 }
759 Ok(())
760 }
761}
762
763#[repr(u8)]
768pub enum KeyCategory {
769 AccountInfo,
771 Storage,
773}
774
775pub(crate) struct ContractDatabase<Runtime> {
777 pub inner: InnerDatabase<Runtime>,
778 pub modules: Arc<Mutex<HashMap<ApplicationId, (ModuleId, u32)>>>,
779}
780
781impl<Runtime> Clone for ContractDatabase<Runtime> {
782 fn clone(&self) -> Self {
783 Self {
784 inner: self.inner.clone(),
785 modules: self.modules.clone(),
786 }
787 }
788}
789
790impl<Runtime> DatabaseRef for ContractDatabase<Runtime>
791where
792 Runtime: ContractRuntime,
793{
794 type Error = ExecutionError;
795
796 fn basic_ref(&self, address: Address) -> Result<Option<AccountInfo>, ExecutionError> {
799 let is_newly_created = {
800 let modules = self.modules.lock().unwrap();
801 let application_id = address_to_user_application_id(address);
802 modules.contains_key(&application_id)
803 };
804 self.inner.read_basic_ref(
805 InnerDatabase::<Runtime>::get_contract_account_info,
806 address,
807 is_newly_created,
808 )
809 }
810
811 fn code_by_hash_ref(&self, _code_hash: B256) -> Result<Bytecode, ExecutionError> {
818 panic!("Returned AccountInfo should have code: Some(...) and so code_by_hash_ref should never be called");
819 }
820
821 fn storage_ref(&self, address: Address, index: U256) -> Result<U256, ExecutionError> {
823 self.inner.read_storage(
824 InnerDatabase::<Runtime>::get_contract_storage_value,
825 address,
826 index,
827 )
828 }
829
830 fn block_hash_ref(&self, number: u64) -> Result<B256, ExecutionError> {
831 Ok(keccak256(number.to_string().as_bytes()))
832 }
833}
834
835impl<Runtime> Database for ContractDatabase<Runtime>
836where
837 Runtime: ContractRuntime,
838{
839 type Error = ExecutionError;
840
841 fn basic(&mut self, address: Address) -> Result<Option<AccountInfo>, ExecutionError> {
842 self.basic_ref(address)
843 }
844
845 fn code_by_hash(&mut self, _code_hash: B256) -> Result<Bytecode, ExecutionError> {
846 panic!("Returned AccountInfo should have code: Some(...) and so code_by_hash should never be called");
847 }
848
849 fn storage(&mut self, address: Address, index: U256) -> Result<U256, ExecutionError> {
850 self.storage_ref(address, index)
851 }
852
853 fn block_hash(&mut self, number: u64) -> Result<B256, ExecutionError> {
854 <Self as DatabaseRef>::block_hash_ref(self, number)
855 }
856}
857
858impl<Runtime> DatabaseCommit for ContractDatabase<Runtime>
859where
860 Runtime: ContractRuntime,
861{
862 fn commit(&mut self, changes: EvmState) {
863 self.inner.changes = changes;
864 }
865}
866
867impl<Runtime> ContractDatabase<Runtime>
868where
869 Runtime: ContractRuntime,
870{
871 pub fn get_block_env(&self) -> Result<BlockEnv, ExecutionError> {
872 let mut block_env = self.inner.get_block_env()?;
873 let mut runtime = self.inner.runtime.lock().unwrap();
874 let gas_limit = runtime.maximum_fuel_per_block(VmRuntime::Evm)?;
876 block_env.gas_limit = gas_limit;
877 Ok(block_env)
878 }
879
880 pub fn get_nonce(&self, address: &Address) -> Result<u64, ExecutionError> {
882 let account_info = self.basic_ref(*address)?;
883 Ok(match account_info {
884 None => 0,
885 Some(account_info) => account_info.nonce,
886 })
887 }
888}
889
890pub(crate) struct ServiceDatabase<Runtime> {
893 pub inner: InnerDatabase<Runtime>,
894}
895
896impl<Runtime> Clone for ServiceDatabase<Runtime> {
897 fn clone(&self) -> Self {
898 Self {
899 inner: self.inner.clone(),
900 }
901 }
902}
903
904impl<Runtime> DatabaseRef for ServiceDatabase<Runtime>
905where
906 Runtime: ServiceRuntime,
907{
908 type Error = ExecutionError;
909
910 fn basic_ref(&self, address: Address) -> Result<Option<AccountInfo>, ExecutionError> {
913 let is_newly_created = false; self.inner.read_basic_ref(
915 InnerDatabase::<Runtime>::get_service_account_info,
916 address,
917 is_newly_created,
918 )
919 }
920
921 fn code_by_hash_ref(&self, _code_hash: B256) -> Result<Bytecode, ExecutionError> {
928 panic!("Returned AccountInfo should have code: Some(...) and so code_by_hash_ref should never be called");
929 }
930
931 fn storage_ref(&self, address: Address, index: U256) -> Result<U256, ExecutionError> {
932 self.inner.read_storage(
933 InnerDatabase::<Runtime>::get_service_storage_value,
934 address,
935 index,
936 )
937 }
938
939 fn block_hash_ref(&self, number: u64) -> Result<B256, ExecutionError> {
940 Ok(keccak256(number.to_string().as_bytes()))
941 }
942}
943
944impl<Runtime> Database for ServiceDatabase<Runtime>
945where
946 Runtime: ServiceRuntime,
947{
948 type Error = ExecutionError;
949
950 fn basic(&mut self, address: Address) -> Result<Option<AccountInfo>, ExecutionError> {
951 self.basic_ref(address)
952 }
953
954 fn code_by_hash(&mut self, _code_hash: B256) -> Result<Bytecode, ExecutionError> {
955 panic!("Returned AccountInfo should have code: Some(...) and so code_by_hash should never be called");
956 }
957
958 fn storage(&mut self, address: Address, index: U256) -> Result<U256, ExecutionError> {
959 self.storage_ref(address, index)
960 }
961
962 fn block_hash(&mut self, number: u64) -> Result<B256, ExecutionError> {
963 <Self as DatabaseRef>::block_hash_ref(self, number)
964 }
965}
966
967impl<Runtime> DatabaseCommit for ServiceDatabase<Runtime>
968where
969 Runtime: ServiceRuntime,
970{
971 fn commit(&mut self, changes: EvmState) {
972 self.inner.changes = changes;
973 }
974}
975
976impl<Runtime> ServiceDatabase<Runtime>
977where
978 Runtime: ServiceRuntime,
979{
980 pub fn new(runtime: Runtime) -> Self {
981 Self {
982 inner: InnerDatabase::new(runtime),
983 }
984 }
985
986 pub fn lock_runtime(&self) -> std::sync::MutexGuard<'_, Runtime> {
987 self.inner.lock_runtime()
988 }
989
990 pub fn get_block_env(&self) -> Result<BlockEnv, ExecutionError> {
991 let mut block_env = self.inner.get_block_env()?;
992 block_env.gas_limit = EVM_SERVICE_GAS_LIMIT;
993 Ok(block_env)
994 }
995
996 pub fn get_nonce(&self, address: &Address) -> Result<u64, ExecutionError> {
998 let account_info = self.basic_ref(*address)?;
999 Ok(match account_info {
1000 None => 0,
1001 Some(account_info) => account_info.nonce,
1002 })
1003 }
1004}