linera_execution/evm/
revm.rs

1// Copyright (c) Zefchain Labs, Inc.
2// SPDX-License-Identifier: Apache-2.0
3
4//! Code specific to the usage of the [Revm](https://bluealloy.github.io/revm/) runtime.
5
6use core::ops::Range;
7use std::{collections::BTreeSet, convert::TryFrom};
8
9#[cfg(with_metrics)]
10use linera_base::prometheus_util::MeasureLatency as _;
11use linera_base::{
12    crypto::CryptoHash,
13    data_types::{Bytecode, Resources, SendMessageRequest, StreamUpdate},
14    ensure,
15    identifiers::{AccountOwner, ApplicationId, ChainId, StreamName},
16    vm::{EvmQuery, VmRuntime},
17};
18use revm::{primitives::Bytes, InspectCommitEvm, InspectEvm, Inspector};
19use revm_context::{
20    result::{ExecutionResult, Output, SuccessReason},
21    BlockEnv, Cfg, ContextTr, Evm, Journal, LocalContextTr, TxEnv,
22};
23use revm_database::WrapDatabaseRef;
24use revm_handler::{
25    instructions::EthInstructions, EthPrecompiles, MainnetContext, PrecompileProvider,
26};
27use revm_interpreter::{
28    CallInput, CallInputs, CallOutcome, CreateInputs, CreateOutcome, CreateScheme, Gas, InputsImpl,
29    InstructionResult, InterpreterResult,
30};
31use revm_primitives::{address, hardfork::SpecId, Address, Log, TxKind, U256};
32use revm_state::EvmState;
33use serde::{Deserialize, Serialize};
34
35use crate::{
36    evm::{
37        data_types::AmountU256,
38        database::{DatabaseRuntime, StorageStats, EVM_SERVICE_GAS_LIMIT},
39    },
40    BaseRuntime, ContractRuntime, ContractSyncRuntimeHandle, DataBlobHash, EvmExecutionError,
41    EvmRuntime, ExecutionError, ServiceRuntime, ServiceSyncRuntimeHandle, UserContract,
42    UserContractInstance, UserContractModule, UserService, UserServiceInstance, UserServiceModule,
43};
44
45/// This is the selector of the `execute_message` that should be called
46/// only from a submitted message
47const EXECUTE_MESSAGE_SELECTOR: &[u8] = &[173, 125, 234, 205];
48
49/// This is the selector of the `process_streams` that should be called
50/// only from a submitted message
51const PROCESS_STREAMS_SELECTOR: &[u8] = &[254, 72, 102, 28];
52
53/// This is the selector of the `instantiate` that should be called
54/// only when creating a new instance of a shared contract
55const INSTANTIATE_SELECTOR: &[u8] = &[156, 163, 60, 158];
56
57/// The selector when calling for `InterpreterResult`. This is a fictional
58/// selector that does not correspond to a real function.
59const INTERPRETER_RESULT_SELECTOR: &[u8] = &[1, 2, 3, 4];
60
61/// The selector when accessing for the deployed bytecode. This is a fictional
62/// selector that does not correspond to a real function.
63const GET_DEPLOYED_BYTECODE_SELECTOR: &[u8] = &[21, 34, 55, 89];
64
65/// The json serialization of a trivial vector.
66const JSON_EMPTY_VECTOR: &[u8] = &[91, 93];
67
68fn forbid_execute_operation_origin(vec: &[u8]) -> Result<(), EvmExecutionError> {
69    if vec == EXECUTE_MESSAGE_SELECTOR {
70        return Err(EvmExecutionError::IllegalOperationCall(
71            "function execute_message".to_string(),
72        ));
73    }
74    if vec == PROCESS_STREAMS_SELECTOR {
75        return Err(EvmExecutionError::IllegalOperationCall(
76            "function process_streams".to_string(),
77        ));
78    }
79    if vec == INSTANTIATE_SELECTOR {
80        return Err(EvmExecutionError::IllegalOperationCall(
81            "function instantiate".to_string(),
82        ));
83    }
84    Ok(())
85}
86
87fn ensure_message_length(actual_length: usize, min_length: usize) -> Result<(), EvmExecutionError> {
88    ensure!(
89        actual_length >= min_length,
90        EvmExecutionError::OperationIsTooShort
91    );
92    Ok(())
93}
94
95fn ensure_selector_presence(
96    module: &[u8],
97    selector: &[u8],
98    fct_name: &str,
99) -> Result<(), EvmExecutionError> {
100    if !has_selector(module, selector) {
101        return Err(EvmExecutionError::MissingFunction(fct_name.to_string()));
102    }
103    Ok(())
104}
105
106#[cfg(test)]
107mod tests {
108    use revm_primitives::keccak256;
109
110    use crate::evm::revm::{
111        EXECUTE_MESSAGE_SELECTOR, INSTANTIATE_SELECTOR, PROCESS_STREAMS_SELECTOR,
112    };
113
114    // The function keccak256 is not const so we cannot build the execute_message
115    // selector directly.
116    #[test]
117    fn check_execute_message_selector() {
118        let selector = &keccak256("execute_message(bytes)".as_bytes())[..4];
119        assert_eq!(selector, EXECUTE_MESSAGE_SELECTOR);
120    }
121
122    #[test]
123    fn check_process_streams_selector() {
124        use alloy_sol_types::{sol, SolCall};
125        sol! {
126            struct InternalApplicationId {
127                bytes32 application_description_hash;
128            }
129
130            struct InternalGenericApplicationId {
131                uint8 choice;
132                InternalApplicationId user;
133            }
134
135            struct InternalStreamName {
136                bytes stream_name;
137            }
138
139            struct InternalStreamId {
140                InternalGenericApplicationId application_id;
141                InternalStreamName stream_name;
142            }
143
144            struct InternalChainId {
145                bytes32 value;
146            }
147
148            struct InternalStreamUpdate {
149                InternalChainId chain_id;
150                InternalStreamId stream_id;
151                uint32 previous_index;
152                uint32 next_index;
153            }
154
155            function process_streams(InternalStreamUpdate[] internal_streams);
156        }
157        assert_eq!(
158            process_streamsCall::SIGNATURE,
159            "process_streams(((bytes32),((uint8,(bytes32)),(bytes)),uint32,uint32)[])"
160        );
161        assert_eq!(process_streamsCall::SELECTOR, PROCESS_STREAMS_SELECTOR);
162    }
163
164    #[test]
165    fn check_instantiate_selector() {
166        let selector = &keccak256("instantiate(bytes)".as_bytes())[..4];
167        assert_eq!(selector, INSTANTIATE_SELECTOR);
168    }
169}
170
171fn has_selector(module: &[u8], selector: &[u8]) -> bool {
172    let push4 = 0x63; // An EVM instruction
173    let mut vec = vec![push4];
174    vec.extend(selector);
175    module.windows(5).any(|window| window == vec)
176}
177
178#[cfg(with_metrics)]
179mod metrics {
180    use std::sync::LazyLock;
181
182    use linera_base::prometheus_util::{exponential_bucket_latencies, register_histogram_vec};
183    use prometheus::HistogramVec;
184
185    pub static CONTRACT_INSTANTIATION_LATENCY: LazyLock<HistogramVec> = LazyLock::new(|| {
186        register_histogram_vec(
187            "evm_contract_instantiation_latency",
188            "EVM contract instantiation latency",
189            &[],
190            exponential_bucket_latencies(1.0),
191        )
192    });
193
194    pub static SERVICE_INSTANTIATION_LATENCY: LazyLock<HistogramVec> = LazyLock::new(|| {
195        register_histogram_vec(
196            "evm_service_instantiation_latency",
197            "EVM service instantiation latency",
198            &[],
199            exponential_bucket_latencies(1.0),
200        )
201    });
202}
203
204fn get_revm_instantiation_bytes(value: Vec<u8>) -> Vec<u8> {
205    use alloy_primitives::Bytes;
206    use alloy_sol_types::{sol, SolCall};
207    sol! {
208        function instantiate(bytes value);
209    }
210    let bytes = Bytes::from(value);
211    let argument = instantiateCall { value: bytes };
212    argument.abi_encode()
213}
214
215fn get_revm_execute_message_bytes(value: Vec<u8>) -> Vec<u8> {
216    use alloy_primitives::Bytes;
217    use alloy_sol_types::{sol, SolCall};
218    sol! {
219        function execute_message(bytes value);
220    }
221    let value = Bytes::from(value);
222    let argument = execute_messageCall { value };
223    argument.abi_encode()
224}
225
226fn get_revm_process_streams_bytes(streams: Vec<StreamUpdate>) -> Vec<u8> {
227    // See TODO(#3966) for a better support of the input.
228    use alloy_primitives::{Bytes, B256};
229    use alloy_sol_types::{sol, SolCall};
230    use linera_base::identifiers::{GenericApplicationId, StreamId};
231    sol! {
232        struct InternalApplicationId {
233            bytes32 application_description_hash;
234        }
235
236        struct InternalGenericApplicationId {
237            uint8 choice;
238            InternalApplicationId user;
239        }
240
241        struct InternalStreamName {
242            bytes stream_name;
243        }
244
245        struct InternalStreamId {
246            InternalGenericApplicationId application_id;
247            InternalStreamName stream_name;
248        }
249
250        struct InternalChainId {
251            bytes32 value;
252        }
253
254        struct InternalStreamUpdate {
255            InternalChainId chain_id;
256            InternalStreamId stream_id;
257            uint32 previous_index;
258            uint32 next_index;
259        }
260
261        function process_streams(InternalStreamUpdate[] internal_streams);
262    }
263
264    fn crypto_hash_to_internal_crypto_hash(hash: CryptoHash) -> B256 {
265        let hash: [u64; 4] = <[u64; 4]>::from(hash);
266        let hash: [u8; 32] = linera_base::crypto::u64_array_to_be_bytes(hash);
267        hash.into()
268    }
269
270    fn chain_id_to_internal_chain_id(chain_id: ChainId) -> InternalChainId {
271        let value = crypto_hash_to_internal_crypto_hash(chain_id.0);
272        InternalChainId { value }
273    }
274
275    fn application_id_to_internal_application_id(
276        application_id: ApplicationId,
277    ) -> InternalApplicationId {
278        let application_description_hash =
279            crypto_hash_to_internal_crypto_hash(application_id.application_description_hash);
280        InternalApplicationId {
281            application_description_hash,
282        }
283    }
284
285    fn stream_name_to_internal_stream_name(stream_name: StreamName) -> InternalStreamName {
286        let stream_name = Bytes::from(stream_name.0);
287        InternalStreamName { stream_name }
288    }
289
290    fn generic_application_id_to_internal_generic_application_id(
291        generic_application_id: GenericApplicationId,
292    ) -> InternalGenericApplicationId {
293        match generic_application_id {
294            GenericApplicationId::System => {
295                let application_description_hash = B256::ZERO;
296                InternalGenericApplicationId {
297                    choice: 0,
298                    user: InternalApplicationId {
299                        application_description_hash,
300                    },
301                }
302            }
303            GenericApplicationId::User(application_id) => InternalGenericApplicationId {
304                choice: 1,
305                user: application_id_to_internal_application_id(application_id),
306            },
307        }
308    }
309
310    fn stream_id_to_internal_stream_id(stream_id: StreamId) -> InternalStreamId {
311        let application_id =
312            generic_application_id_to_internal_generic_application_id(stream_id.application_id);
313        let stream_name = stream_name_to_internal_stream_name(stream_id.stream_name);
314        InternalStreamId {
315            application_id,
316            stream_name,
317        }
318    }
319
320    fn stream_update_to_internal_stream_update(
321        stream_update: StreamUpdate,
322    ) -> InternalStreamUpdate {
323        let chain_id = chain_id_to_internal_chain_id(stream_update.chain_id);
324        let stream_id = stream_id_to_internal_stream_id(stream_update.stream_id);
325        InternalStreamUpdate {
326            chain_id,
327            stream_id,
328            previous_index: stream_update.previous_index,
329            next_index: stream_update.next_index,
330        }
331    }
332
333    let internal_streams = streams
334        .into_iter()
335        .map(stream_update_to_internal_stream_update)
336        .collect::<Vec<_>>();
337
338    let fct_call = process_streamsCall { internal_streams };
339    fct_call.abi_encode()
340}
341
342#[derive(Clone)]
343pub enum EvmContractModule {
344    #[cfg(with_revm)]
345    Revm { module: Vec<u8> },
346}
347
348impl EvmContractModule {
349    /// Creates a new [`EvmContractModule`] using the EVM module with the provided `contract_bytecode`.
350    pub fn new(
351        contract_bytecode: Bytecode,
352        runtime: EvmRuntime,
353    ) -> Result<Self, EvmExecutionError> {
354        match runtime {
355            #[cfg(with_revm)]
356            EvmRuntime::Revm => Self::from_revm(contract_bytecode),
357        }
358    }
359
360    /// Creates a new [`EvmContractModule`] using the EVM module in `contract_bytecode_file`.
361    #[cfg(with_fs)]
362    pub fn from_file(
363        contract_bytecode_file: impl AsRef<std::path::Path>,
364        runtime: EvmRuntime,
365    ) -> Result<Self, EvmExecutionError> {
366        Self::new(
367            Bytecode::load_from_file(contract_bytecode_file)
368                .map_err(anyhow::Error::from)
369                .map_err(EvmExecutionError::LoadContractModule)?,
370            runtime,
371        )
372    }
373
374    /// Creates a new [`EvmContractModule`] using Revm with the provided bytecode files.
375    pub fn from_revm(contract_bytecode: Bytecode) -> Result<Self, EvmExecutionError> {
376        let module = contract_bytecode.bytes;
377        Ok(EvmContractModule::Revm { module })
378    }
379}
380
381impl UserContractModule for EvmContractModule {
382    fn instantiate(
383        &self,
384        runtime: ContractSyncRuntimeHandle,
385    ) -> Result<UserContractInstance, ExecutionError> {
386        #[cfg(with_metrics)]
387        let _instantiation_latency = metrics::CONTRACT_INSTANTIATION_LATENCY.measure_latency();
388
389        let instance: UserContractInstance = match self {
390            #[cfg(with_revm)]
391            EvmContractModule::Revm { module } => {
392                Box::new(RevmContractInstance::prepare(module.to_vec(), runtime))
393            }
394        };
395
396        Ok(instance)
397    }
398}
399
400/// A user service in a compiled EVM module.
401#[derive(Clone)]
402pub enum EvmServiceModule {
403    #[cfg(with_revm)]
404    Revm { module: Vec<u8> },
405}
406
407impl EvmServiceModule {
408    /// Creates a new [`EvmServiceModule`] using the EVM module with the provided bytecode.
409    pub fn new(service_bytecode: Bytecode, runtime: EvmRuntime) -> Result<Self, EvmExecutionError> {
410        match runtime {
411            #[cfg(with_revm)]
412            EvmRuntime::Revm => Self::from_revm(service_bytecode),
413        }
414    }
415
416    /// Creates a new [`EvmServiceModule`] using the EVM module in `service_bytecode_file`.
417    #[cfg(with_fs)]
418    pub fn from_file(
419        service_bytecode_file: impl AsRef<std::path::Path>,
420        runtime: EvmRuntime,
421    ) -> Result<Self, EvmExecutionError> {
422        Self::new(
423            Bytecode::load_from_file(service_bytecode_file)
424                .map_err(anyhow::Error::from)
425                .map_err(EvmExecutionError::LoadServiceModule)?,
426            runtime,
427        )
428    }
429
430    /// Creates a new [`EvmServiceModule`] using Revm with the provided bytecode files.
431    pub fn from_revm(contract_bytecode: Bytecode) -> Result<Self, EvmExecutionError> {
432        let module = contract_bytecode.bytes;
433        Ok(EvmServiceModule::Revm { module })
434    }
435}
436
437impl UserServiceModule for EvmServiceModule {
438    fn instantiate(
439        &self,
440        runtime: ServiceSyncRuntimeHandle,
441    ) -> Result<UserServiceInstance, ExecutionError> {
442        #[cfg(with_metrics)]
443        let _instantiation_latency = metrics::SERVICE_INSTANTIATION_LATENCY.measure_latency();
444
445        let instance: UserServiceInstance = match self {
446            #[cfg(with_revm)]
447            EvmServiceModule::Revm { module } => {
448                Box::new(RevmServiceInstance::prepare(module.to_vec(), runtime))
449            }
450        };
451
452        Ok(instance)
453    }
454}
455
456type Ctx<'a, Runtime> = MainnetContext<WrapDatabaseRef<&'a mut DatabaseRuntime<Runtime>>>;
457
458// This is the precompile address that contains the Linera specific
459// functionalities accessed from the EVM.
460const PRECOMPILE_ADDRESS: Address = address!("000000000000000000000000000000000000000b");
461
462// This is the zero address used when no address can be obtained from `authenticated_signer`
463// and `authenticated_caller_id`. This scenario does not occur if an Address20 user calls or
464// if an EVM contract calls another EVM contract.
465const ZERO_ADDRESS: Address = address!("0000000000000000000000000000000000000000");
466
467// This is the address being used for service calls.
468const SERVICE_ADDRESS: Address = address!("0000000000000000000000000000000000002000");
469
470fn address_to_user_application_id(address: Address) -> ApplicationId {
471    let mut vec = vec![0_u8; 32];
472    vec[..20].copy_from_slice(address.as_ref());
473    ApplicationId::new(CryptoHash::try_from(&vec as &[u8]).unwrap())
474}
475
476/// Some functionalities from the BaseRuntime
477#[derive(Debug, Serialize, Deserialize)]
478enum BaseRuntimePrecompile {
479    /// Calling `chain_id` of `BaseRuntime`
480    ChainId,
481    /// Calling `block_height_id` of `BaseRuntime`
482    BlockHeight,
483    /// Calling `application_creator_chain_id` of `BaseRuntime`
484    ApplicationCreatorChainId,
485    /// Calling `read_system_timestamp` of `BaseRuntime`
486    ReadSystemTimestamp,
487    /// Calling `read_chain_balance` of `BaseRuntime`
488    ReadChainBalance,
489    /// Calling `read_owner_balance` of `BaseRuntime`
490    ReadOwnerBalance(AccountOwner),
491    /// Calling `read_owner_balances` of `BaseRuntime`
492    ReadOwnerBalances,
493    /// Calling `read_balance_owners` of `BaseRuntime`
494    ReadBalanceOwners,
495    /// Calling `chain_ownership` of `BaseRuntime`
496    ChainOwnership,
497    /// Calling `read_data_blob` of `BaseRuntime`
498    ReadDataBlob(DataBlobHash),
499    /// Calling `assert_data_blob_exists` of `BaseRuntime`
500    AssertDataBlobExists(DataBlobHash),
501}
502
503/// Some functionalities from the ContractRuntime not in BaseRuntime
504#[derive(Debug, Serialize, Deserialize)]
505enum ContractRuntimePrecompile {
506    /// Calling `authenticated_signer` of `ContractRuntime`
507    AuthenticatedSigner,
508    /// Calling `message_origin_chain_id` of `ContractRuntime`
509    MessageOriginChainId,
510    /// Calling `message_is_bouncing` of `ContractRuntime`
511    MessageIsBouncing,
512    /// Calling `authenticated_caller_id` of `ContractRuntime`
513    AuthenticatedCallerId,
514    /// Calling `send_message` of `ContractRuntime`
515    SendMessage {
516        destination: ChainId,
517        message: Vec<u8>,
518    },
519    /// Calling `try_call_application` of `ContractRuntime`
520    TryCallApplication {
521        target: ApplicationId,
522        argument: Vec<u8>,
523    },
524    /// Calling `emit` of `ContractRuntime`
525    Emit {
526        stream_name: StreamName,
527        value: Vec<u8>,
528    },
529    /// Calling `read_event` of `ContractRuntime`
530    ReadEvent {
531        chain_id: ChainId,
532        stream_name: StreamName,
533        index: u32,
534    },
535    /// Calling `subscribe_to_events` of `ContractRuntime`
536    SubscribeToEvents {
537        chain_id: ChainId,
538        application_id: ApplicationId,
539        stream_name: StreamName,
540    },
541    /// Calling `unsubscribe_from_events` of `ContractRuntime`
542    UnsubscribeFromEvents {
543        chain_id: ChainId,
544        application_id: ApplicationId,
545        stream_name: StreamName,
546    },
547    /// Calling `query_service` of `ContractRuntime`
548    QueryService {
549        application_id: ApplicationId,
550        query: Vec<u8>,
551    },
552    /// Calling `validation_round` of `ContractRuntime`
553    ValidationRound,
554}
555
556/// Some functionalities from the ServiceRuntime not in BaseRuntime
557#[derive(Debug, Serialize, Deserialize)]
558enum ServiceRuntimePrecompile {
559    /// Calling `try_query_application` of `ServiceRuntime`
560    TryQueryApplication {
561        target: ApplicationId,
562        argument: Vec<u8>,
563    },
564}
565
566/// Key prefixes used to transmit precompiles.
567#[derive(Debug, Serialize, Deserialize)]
568enum RuntimePrecompile {
569    Base(BaseRuntimePrecompile),
570    Contract(ContractRuntimePrecompile),
571    Service(ServiceRuntimePrecompile),
572}
573
574fn get_precompile_output(output: Vec<u8>, gas_limit: u64) -> InterpreterResult {
575    // The gas usage is set to `gas_limit` and no spending is being done on it.
576    // This means that for REVM, it looks like the precompile call costs nothing.
577    // This is because the costs of the EVM precompile calls is accounted for
578    // separately in Linera.
579    let output = Bytes::from(output);
580    let result = InstructionResult::default();
581    let gas = Gas::new(gas_limit);
582    InterpreterResult {
583        result,
584        output,
585        gas,
586    }
587}
588
589fn get_precompile_argument<Ctx: ContextTr>(context: &mut Ctx, input: &CallInput) -> Vec<u8> {
590    let mut argument = Vec::new();
591    get_argument(context, &mut argument, input);
592    argument
593}
594
595fn base_runtime_call<Runtime: BaseRuntime>(
596    request: BaseRuntimePrecompile,
597    context: &mut Ctx<'_, Runtime>,
598) -> Result<Vec<u8>, ExecutionError> {
599    let mut runtime = context.db().0.runtime.lock().unwrap();
600    match request {
601        BaseRuntimePrecompile::ChainId => {
602            let chain_id = runtime.chain_id()?;
603            Ok(bcs::to_bytes(&chain_id)?)
604        }
605        BaseRuntimePrecompile::BlockHeight => {
606            let block_height = runtime.block_height()?;
607            Ok(bcs::to_bytes(&block_height)?)
608        }
609        BaseRuntimePrecompile::ApplicationCreatorChainId => {
610            let chain_id = runtime.application_creator_chain_id()?;
611            Ok(bcs::to_bytes(&chain_id)?)
612        }
613        BaseRuntimePrecompile::ReadSystemTimestamp => {
614            let timestamp = runtime.read_system_timestamp()?;
615            Ok(bcs::to_bytes(&timestamp)?)
616        }
617        BaseRuntimePrecompile::ReadChainBalance => {
618            let balance: linera_base::data_types::Amount = runtime.read_chain_balance()?;
619            let balance: AmountU256 = balance.into();
620            Ok(bcs::to_bytes(&balance)?)
621        }
622        BaseRuntimePrecompile::ReadOwnerBalance(account_owner) => {
623            let balance = runtime.read_owner_balance(account_owner)?;
624            let balance = Into::<U256>::into(balance);
625            Ok(bcs::to_bytes(&balance)?)
626        }
627        BaseRuntimePrecompile::ReadOwnerBalances => {
628            let owner_balances = runtime.read_owner_balances()?;
629            let owner_balances = owner_balances
630                .into_iter()
631                .map(|(account_owner, balance)| (account_owner, balance.into()))
632                .collect::<Vec<(AccountOwner, AmountU256)>>();
633            Ok(bcs::to_bytes(&owner_balances)?)
634        }
635        BaseRuntimePrecompile::ReadBalanceOwners => {
636            let owners = runtime.read_balance_owners()?;
637            Ok(bcs::to_bytes(&owners)?)
638        }
639        BaseRuntimePrecompile::ChainOwnership => {
640            let chain_ownership = runtime.chain_ownership()?;
641            Ok(bcs::to_bytes(&chain_ownership)?)
642        }
643        BaseRuntimePrecompile::ReadDataBlob(hash) => runtime.read_data_blob(hash),
644        BaseRuntimePrecompile::AssertDataBlobExists(hash) => {
645            runtime.assert_data_blob_exists(hash)?;
646            Ok(Vec::new())
647        }
648    }
649}
650
651fn precompile_addresses() -> BTreeSet<Address> {
652    let mut addresses = BTreeSet::new();
653    for address in EthPrecompiles::default().warm_addresses() {
654        addresses.insert(address);
655    }
656    addresses.insert(PRECOMPILE_ADDRESS);
657    addresses
658}
659
660#[derive(Debug, Default)]
661struct ContractPrecompile {
662    inner: EthPrecompiles,
663}
664
665impl<'a, Runtime: ContractRuntime> PrecompileProvider<Ctx<'a, Runtime>> for ContractPrecompile {
666    type Output = InterpreterResult;
667
668    fn set_spec(&mut self, spec: <<Ctx<'a, Runtime> as ContextTr>::Cfg as Cfg>::Spec) -> bool {
669        <EthPrecompiles as PrecompileProvider<Ctx<'a, Runtime>>>::set_spec(&mut self.inner, spec)
670    }
671
672    fn run(
673        &mut self,
674        context: &mut Ctx<'a, Runtime>,
675        address: &Address,
676        inputs: &InputsImpl,
677        is_static: bool,
678        gas_limit: u64,
679    ) -> Result<Option<InterpreterResult>, String> {
680        if address == &PRECOMPILE_ADDRESS {
681            let input = get_precompile_argument(context, &inputs.input);
682            let output = Self::call_or_fail(&input, context)
683                .map_err(|error| format!("ContractPrecompile error: {error}"))?;
684            return Ok(Some(get_precompile_output(output, gas_limit)));
685        }
686        self.inner
687            .run(context, address, inputs, is_static, gas_limit)
688    }
689
690    fn warm_addresses(&self) -> Box<impl Iterator<Item = Address>> {
691        let mut addresses = self.inner.warm_addresses().collect::<Vec<Address>>();
692        addresses.push(PRECOMPILE_ADDRESS);
693        Box::new(addresses.into_iter())
694    }
695
696    fn contains(&self, address: &Address) -> bool {
697        address == &PRECOMPILE_ADDRESS || self.inner.contains(address)
698    }
699}
700
701impl<'a> ContractPrecompile {
702    fn contract_runtime_call<Runtime: ContractRuntime>(
703        request: ContractRuntimePrecompile,
704        context: &mut Ctx<'a, Runtime>,
705    ) -> Result<Vec<u8>, ExecutionError> {
706        let mut runtime = context.db().0.runtime.lock().unwrap();
707        match request {
708            ContractRuntimePrecompile::AuthenticatedSigner => {
709                let account_owner = runtime.authenticated_signer()?;
710                Ok(bcs::to_bytes(&account_owner)?)
711            }
712
713            ContractRuntimePrecompile::MessageOriginChainId => {
714                let origin_chain_id = runtime.message_origin_chain_id()?;
715                Ok(bcs::to_bytes(&origin_chain_id)?)
716            }
717
718            ContractRuntimePrecompile::MessageIsBouncing => {
719                let result = runtime.message_is_bouncing()?;
720                Ok(bcs::to_bytes(&result)?)
721            }
722            ContractRuntimePrecompile::AuthenticatedCallerId => {
723                let application_id = runtime.authenticated_caller_id()?;
724                Ok(bcs::to_bytes(&application_id)?)
725            }
726            ContractRuntimePrecompile::SendMessage {
727                destination,
728                message,
729            } => {
730                let authenticated = true;
731                let is_tracked = true;
732                let grant = Resources::default();
733                let send_message_request = SendMessageRequest {
734                    destination,
735                    authenticated,
736                    is_tracked,
737                    grant,
738                    message,
739                };
740                runtime.send_message(send_message_request)?;
741                Ok(vec![])
742            }
743            ContractRuntimePrecompile::TryCallApplication { target, argument } => {
744                let authenticated = true;
745                runtime.try_call_application(authenticated, target, argument)
746            }
747            ContractRuntimePrecompile::Emit { stream_name, value } => {
748                let result = runtime.emit(stream_name, value)?;
749                Ok(bcs::to_bytes(&result)?)
750            }
751            ContractRuntimePrecompile::ReadEvent {
752                chain_id,
753                stream_name,
754                index,
755            } => runtime.read_event(chain_id, stream_name, index),
756            ContractRuntimePrecompile::SubscribeToEvents {
757                chain_id,
758                application_id,
759                stream_name,
760            } => {
761                runtime.subscribe_to_events(chain_id, application_id, stream_name)?;
762                Ok(vec![])
763            }
764            ContractRuntimePrecompile::UnsubscribeFromEvents {
765                chain_id,
766                application_id,
767                stream_name,
768            } => {
769                runtime.unsubscribe_from_events(chain_id, application_id, stream_name)?;
770                Ok(vec![])
771            }
772            ContractRuntimePrecompile::QueryService {
773                application_id,
774                query,
775            } => runtime.query_service(application_id, query),
776            ContractRuntimePrecompile::ValidationRound => {
777                let value = runtime.validation_round()?;
778                Ok(bcs::to_bytes(&value)?)
779            }
780        }
781    }
782
783    fn call_or_fail<Runtime: ContractRuntime>(
784        input: &[u8],
785        context: &mut Ctx<'a, Runtime>,
786    ) -> Result<Vec<u8>, ExecutionError> {
787        match bcs::from_bytes(input)? {
788            RuntimePrecompile::Base(base_tag) => base_runtime_call(base_tag, context),
789            RuntimePrecompile::Contract(contract_tag) => {
790                Self::contract_runtime_call(contract_tag, context)
791            }
792            RuntimePrecompile::Service(_) => Err(EvmExecutionError::PrecompileError(
793                "Service tags are not available in GeneralContractCall".to_string(),
794            )
795            .into()),
796        }
797    }
798}
799
800#[derive(Debug, Default)]
801struct ServicePrecompile {
802    inner: EthPrecompiles,
803}
804
805impl<'a> ServicePrecompile {
806    fn service_runtime_call<Runtime: ServiceRuntime>(
807        request: ServiceRuntimePrecompile,
808        context: &mut Ctx<'a, Runtime>,
809    ) -> Result<Vec<u8>, ExecutionError> {
810        let mut runtime = context.db().0.runtime.lock().unwrap();
811        match request {
812            ServiceRuntimePrecompile::TryQueryApplication { target, argument } => {
813                runtime.try_query_application(target, argument)
814            }
815        }
816    }
817
818    fn call_or_fail<Runtime: ServiceRuntime>(
819        input: &[u8],
820        context: &mut Ctx<'a, Runtime>,
821    ) -> Result<Vec<u8>, ExecutionError> {
822        match bcs::from_bytes(input)? {
823            RuntimePrecompile::Base(base_tag) => base_runtime_call(base_tag, context),
824            RuntimePrecompile::Contract(_) => Err(EvmExecutionError::PrecompileError(
825                "Contract calls are not available in GeneralServiceCall".to_string(),
826            )
827            .into()),
828            RuntimePrecompile::Service(service_tag) => {
829                Self::service_runtime_call(service_tag, context)
830            }
831        }
832    }
833}
834
835impl<'a, Runtime: ServiceRuntime> PrecompileProvider<Ctx<'a, Runtime>> for ServicePrecompile {
836    type Output = InterpreterResult;
837
838    fn set_spec(&mut self, spec: <<Ctx<'a, Runtime> as ContextTr>::Cfg as Cfg>::Spec) -> bool {
839        <EthPrecompiles as PrecompileProvider<Ctx<'a, Runtime>>>::set_spec(&mut self.inner, spec)
840    }
841
842    fn run(
843        &mut self,
844        context: &mut Ctx<'a, Runtime>,
845        address: &Address,
846        inputs: &InputsImpl,
847        is_static: bool,
848        gas_limit: u64,
849    ) -> Result<Option<InterpreterResult>, String> {
850        if address == &PRECOMPILE_ADDRESS {
851            let input = get_precompile_argument(context, &inputs.input);
852            let output = Self::call_or_fail(&input, context)
853                .map_err(|error| format!("ServicePrecompile error: {error}"))?;
854            return Ok(Some(get_precompile_output(output, gas_limit)));
855        }
856        self.inner
857            .run(context, address, inputs, is_static, gas_limit)
858    }
859
860    fn warm_addresses(&self) -> Box<impl Iterator<Item = Address>> {
861        let mut addresses = self.inner.warm_addresses().collect::<Vec<Address>>();
862        addresses.push(PRECOMPILE_ADDRESS);
863        Box::new(addresses.into_iter())
864    }
865
866    fn contains(&self, address: &Address) -> bool {
867        address == &PRECOMPILE_ADDRESS || self.inner.contains(address)
868    }
869}
870
871fn map_result_create_outcome<Runtime: BaseRuntime>(
872    database: &DatabaseRuntime<Runtime>,
873    result: Result<Option<CreateOutcome>, ExecutionError>,
874) -> Option<CreateOutcome> {
875    match result {
876        Err(error) => {
877            database.insert_error(error);
878            // The use of Revert immediately stops the execution.
879            let result = InstructionResult::Revert;
880            let output = Bytes::default();
881            let gas = Gas::default();
882            let result = InterpreterResult {
883                result,
884                output,
885                gas,
886            };
887            Some(CreateOutcome {
888                result,
889                address: None,
890            })
891        }
892        Ok(result) => result,
893    }
894}
895
896fn map_result_call_outcome<Runtime: BaseRuntime>(
897    database: &DatabaseRuntime<Runtime>,
898    result: Result<Option<CallOutcome>, ExecutionError>,
899) -> Option<CallOutcome> {
900    match result {
901        Err(error) => {
902            database.insert_error(error);
903            // The use of Revert immediately stops the execution.
904            let result = InstructionResult::Revert;
905            let output = Bytes::default();
906            let gas = Gas::default();
907            let result = InterpreterResult {
908                result,
909                output,
910                gas,
911            };
912            let memory_offset = Range::default();
913            Some(CallOutcome {
914                result,
915                memory_offset,
916            })
917        }
918        Ok(result) => result,
919    }
920}
921
922fn get_interpreter_result(
923    result: &[u8],
924    inputs: &mut CallInputs,
925) -> Result<InterpreterResult, ExecutionError> {
926    let mut result = bcs::from_bytes::<InterpreterResult>(result)?;
927    // This effectively means that no cost is incurred by the call to another contract.
928    // This is fine since the costs are incurred by the other contract itself.
929    result.gas = Gas::new(inputs.gas_limit);
930    Ok(result)
931}
932
933struct CallInterceptorContract<Runtime> {
934    db: DatabaseRuntime<Runtime>,
935    // This is the contract address of the contract being created.
936    contract_address: Address,
937    precompile_addresses: BTreeSet<Address>,
938}
939
940impl<Runtime> Clone for CallInterceptorContract<Runtime> {
941    fn clone(&self) -> Self {
942        Self {
943            db: self.db.clone(),
944            contract_address: self.contract_address,
945            precompile_addresses: self.precompile_addresses.clone(),
946        }
947    }
948}
949
950fn get_argument<Ctx: ContextTr>(context: &mut Ctx, argument: &mut Vec<u8>, input: &CallInput) {
951    match input {
952        CallInput::Bytes(bytes) => {
953            argument.extend(bytes.to_vec());
954        }
955        CallInput::SharedBuffer(range) => {
956            if let Some(slice) = context.local().shared_memory_buffer_slice(range.clone()) {
957                argument.extend(&*slice);
958            }
959        }
960    };
961}
962
963fn get_call_argument<Ctx: ContextTr>(context: &mut Ctx, inputs: &CallInputs) -> Vec<u8> {
964    let mut argument = INTERPRETER_RESULT_SELECTOR.to_vec();
965    get_argument(context, &mut argument, &inputs.input);
966    argument
967}
968
969impl<'a, Runtime: ContractRuntime> Inspector<Ctx<'a, Runtime>>
970    for CallInterceptorContract<Runtime>
971{
972    fn create(
973        &mut self,
974        context: &mut Ctx<'a, Runtime>,
975        inputs: &mut CreateInputs,
976    ) -> Option<CreateOutcome> {
977        let result = self.create_or_fail(context, inputs);
978        map_result_create_outcome(&self.db, result)
979    }
980
981    fn call(
982        &mut self,
983        context: &mut Ctx<'a, Runtime>,
984        inputs: &mut CallInputs,
985    ) -> Option<CallOutcome> {
986        let result = self.call_or_fail(context, inputs);
987        map_result_call_outcome(&self.db, result)
988    }
989}
990
991impl<Runtime: ContractRuntime> CallInterceptorContract<Runtime> {
992    /// The function `fn create` of the inspector trait is called
993    /// when a contract is going to be instantiated. Since the
994    /// function can have some error case which are not supported
995    /// in `fn create`, we call a `fn create_or_fail` that can
996    /// return errors.
997    /// When the database runtime is created, the REVM contract
998    /// may or may not have been created. Therefore, at startup
999    /// we have `is_revm_instantiated = false`. That boolean
1000    /// can be updated after `set_is_initialized`.
1001    ///
1002    /// The inspector can do two things:
1003    /// * It can change the inputs in `CreateInputs`. Here we
1004    ///   change the address being created.
1005    /// * It can return some specific CreateInput to be used.
1006    ///
1007    /// Therefore, the first case of the call is going to
1008    /// be about the creation of the contract with just the
1009    /// address being the one chosen by Linera.
1010    ///
1011    /// The second case occurs when the first contract has
1012    /// been created and that contrac starts making new
1013    /// contracts.
1014    /// In relation to bytecode, the following notions are
1015    /// relevant:
1016    /// * The bytecode is created from the compilation.
1017    /// * The bytecode concatenated with the constructor
1018    ///   argument. This is what is sent to EVM when we
1019    ///   create a new contract.
1020    /// * The deployed bytecode. This is essentially the
1021    ///   bytecode minus the constructor code.
1022    ///
1023    /// In relation to that, the following points are
1024    /// important:
1025    /// * The inputs.init_code is formed by the concatenation
1026    ///   of compiled bytecode + constructor argument.
1027    /// * It is impossible to separate the compiled bytecode
1028    ///   from the constructor argument. Think for example
1029    ///   of the following two contracts:
1030    ///   constructor(uint a, uint b) {
1031    ///   value = a + b
1032    ///   }
1033    ///   or
1034    ///   constructor(uint b) {
1035    ///   value = 3 + b
1036    ///   }
1037    ///   Calling the first constructor with (3,4) leads
1038    ///   to the same concatenation as the second constructor
1039    ///   with input (4).
1040    /// * It turns out that we do not need to determine the
1041    ///   constructor argument.
1042    /// * What needs to be determined is the deployed bytecode.
1043    ///   This is stored in the AccountInfo entry. It is
1044    ///   the result of the execution by the REVM interpreter
1045    ///   and there is no way to do it without doing the execution.
1046    ///
1047    /// The strategy for creating the contract is thus:
1048    /// * For the case of a new contract being created, we proceed
1049    ///   like for services. We just adjust the address of the
1050    ///   creation.
1051    /// * In the second case, we first create the contract and
1052    ///   service bytecode (empty, but not used) and then publish
1053    ///   the module.
1054    /// * The parameters is empty because the constructor argument
1055    ///   have already put in the init_code.
1056    /// * The instantiation argument is empty since an EVM contract
1057    ///   creating a new contract will not support Linera features.
1058    ///   This is simply not part of create/create2 in the EVM.
1059    /// * That call to `create_application` leads to a creation of
1060    ///   a new contract and so a call to `fn create_or_fail` in
1061    ///   another instance of REVM.
1062    /// * When returning the `CreateOutcome`, we need to have the
1063    ///   deployed bytecode. This is implemented through a special
1064    ///   call to `GET_DEPLOYED_BYTECODE_SELECTOR`. This is done
1065    ///   with an `execute_operation`.
1066    /// * Data is put together as a `Some(...)` which tells REVM
1067    ///   that it does not need to execute the bytecode since the
1068    ///   output is given to it.
1069    fn create_or_fail(
1070        &mut self,
1071        context: &mut Ctx<'_, Runtime>,
1072        inputs: &mut CreateInputs,
1073    ) -> Result<Option<CreateOutcome>, ExecutionError> {
1074        if !self.db.is_revm_instantiated {
1075            self.db.is_revm_instantiated = true;
1076            inputs.scheme = CreateScheme::Custom {
1077                address: self.contract_address,
1078            };
1079            Ok(None)
1080        } else {
1081            let contract = linera_base::data_types::Bytecode::new(inputs.init_code.to_vec());
1082            let service = linera_base::data_types::Bytecode::new(vec![]);
1083            let mut runtime = context.db().0.runtime.lock().unwrap();
1084            let module_id = runtime.publish_module(contract, service, VmRuntime::Evm)?;
1085            let parameters = JSON_EMPTY_VECTOR.to_vec(); // No constructor
1086            let argument = JSON_EMPTY_VECTOR.to_vec(); // No call to "fn instantiate"
1087            let required_application_ids = Vec::new();
1088            let application_id = runtime.create_application(
1089                module_id,
1090                parameters,
1091                argument,
1092                required_application_ids,
1093            )?;
1094            let argument = GET_DEPLOYED_BYTECODE_SELECTOR.to_vec();
1095            let deployed_bytecode: Vec<u8> =
1096                runtime.try_call_application(false, application_id, argument)?;
1097            let result = InterpreterResult {
1098                result: InstructionResult::Return, // Only possibility if no error occured.
1099                output: Bytes::from(deployed_bytecode),
1100                gas: Gas::new(inputs.gas_limit),
1101            };
1102            let address = application_id.evm_address();
1103            let creation_outcome = CreateOutcome {
1104                result,
1105                address: Some(address),
1106            };
1107            Ok(Some(creation_outcome))
1108        }
1109    }
1110
1111    fn call_or_fail(
1112        &mut self,
1113        context: &mut Ctx<'_, Runtime>,
1114        inputs: &mut CallInputs,
1115    ) -> Result<Option<CallOutcome>, ExecutionError> {
1116        // Every call to a contract passes by this function.
1117        // Three kinds:
1118        // --- Call to the PRECOMPILE smart contract.
1119        // --- Call to the EVM smart contract itself
1120        // --- Call to other EVM smart contract
1121        if self.precompile_addresses.contains(&inputs.target_address)
1122            || inputs.target_address == self.contract_address
1123        {
1124            // Precompile calls are handled by the precompile code.
1125            // The EVM smart contract is being called
1126            return Ok(None);
1127        }
1128        // Other smart contracts calls are handled by the runtime
1129        let target = address_to_user_application_id(inputs.target_address);
1130        let argument = get_call_argument(context, inputs);
1131        let authenticated = true;
1132        let result = {
1133            let mut runtime = self.db.runtime.lock().unwrap();
1134            runtime.try_call_application(authenticated, target, argument)?
1135        };
1136        let call_outcome = CallOutcome {
1137            result: get_interpreter_result(&result, inputs)?,
1138            memory_offset: inputs.return_memory_offset.clone(),
1139        };
1140        Ok(Some(call_outcome))
1141    }
1142}
1143
1144struct CallInterceptorService<Runtime> {
1145    db: DatabaseRuntime<Runtime>,
1146    // This is the contract address of the contract being created.
1147    contract_address: Address,
1148    precompile_addresses: BTreeSet<Address>,
1149}
1150
1151impl<Runtime> Clone for CallInterceptorService<Runtime> {
1152    fn clone(&self) -> Self {
1153        Self {
1154            db: self.db.clone(),
1155            contract_address: self.contract_address,
1156            precompile_addresses: self.precompile_addresses.clone(),
1157        }
1158    }
1159}
1160
1161impl<'a, Runtime: ServiceRuntime> Inspector<Ctx<'a, Runtime>> for CallInterceptorService<Runtime> {
1162    /// See below on `fn create_or_fail`.
1163    fn create(
1164        &mut self,
1165        context: &mut Ctx<'a, Runtime>,
1166        inputs: &mut CreateInputs,
1167    ) -> Option<CreateOutcome> {
1168        let result = self.create_or_fail(context, inputs);
1169        map_result_create_outcome(&self.db, result)
1170    }
1171
1172    /// See below on `fn call_or_fail`.
1173    fn call(
1174        &mut self,
1175        context: &mut Ctx<'a, Runtime>,
1176        inputs: &mut CallInputs,
1177    ) -> Option<CallOutcome> {
1178        let result = self.call_or_fail(context, inputs);
1179        map_result_call_outcome(&self.db, result)
1180    }
1181}
1182
1183impl<Runtime: ServiceRuntime> CallInterceptorService<Runtime> {
1184    /// The function `fn create` of the inspector trait is called
1185    /// when a contract is going to be instantiated. Since the
1186    /// function can have some error case which are not supported
1187    /// in `fn create`, we call a `fn create_or_fail` that can
1188    /// return errors.
1189    /// When the database runtime is created, the REVM contract
1190    /// may or may not have been created. Therefore, at startup
1191    /// we have `is_revm_instantiated = false`. That boolean
1192    /// can be updated after `set_is_initialized`.
1193    ///
1194    /// The inspector can do two things:
1195    /// * It can change the inputs in `CreateInputs`. Here we
1196    ///   change the address being created.
1197    /// * It can return some specific CreateInput to be used.
1198    ///
1199    /// Therefore, the first case of the call is going to
1200    /// be about the creation of the contract with just the
1201    /// address being the one chosen by Linera.
1202    /// The second case of creating a new contract does not
1203    /// apply in services and so lead to an error.
1204    fn create_or_fail(
1205        &mut self,
1206        _context: &mut Ctx<'_, Runtime>,
1207        inputs: &mut CreateInputs,
1208    ) -> Result<Option<CreateOutcome>, ExecutionError> {
1209        if !self.db.is_revm_instantiated {
1210            self.db.is_revm_instantiated = true;
1211            inputs.scheme = CreateScheme::Custom {
1212                address: self.contract_address,
1213            };
1214            Ok(None)
1215        } else {
1216            Err(EvmExecutionError::NoContractCreationInService.into())
1217        }
1218    }
1219
1220    /// Every call to a contract passes by this function.
1221    /// Three kinds:
1222    /// --- Call to the EVM smart contract itself
1223    /// --- Call to the PRECOMPILE smart contract.
1224    /// --- Call to other EVM smart contract
1225    ///
1226    /// The first kind is the call to the contract itself like
1227    /// constructor or from an external call.
1228    /// The second kind is precompile calls. This include the
1229    /// classic one but also the one that accesses the Linera
1230    /// functionalities.
1231    /// The last kind is the calls to other EVM smart contracts.
1232    fn call_or_fail(
1233        &mut self,
1234        context: &mut Ctx<'_, Runtime>,
1235        inputs: &mut CallInputs,
1236    ) -> Result<Option<CallOutcome>, ExecutionError> {
1237        if self.precompile_addresses.contains(&inputs.target_address)
1238            || inputs.target_address == self.contract_address
1239        {
1240            // Precompile calls are handled by the precompile code.
1241            // The EVM smart contract is being called
1242            return Ok(None);
1243        }
1244        // Other smart contracts calls are handled by the runtime
1245        let target = address_to_user_application_id(inputs.target_address);
1246        let argument = get_call_argument(context, inputs);
1247        let result = {
1248            let evm_query = EvmQuery::Query(argument);
1249            let evm_query = serde_json::to_vec(&evm_query)?;
1250            let mut runtime = self.db.runtime.lock().unwrap();
1251            runtime.try_query_application(target, evm_query)?
1252        };
1253        let call_outcome = CallOutcome {
1254            result: get_interpreter_result(&result, inputs)?,
1255            memory_offset: inputs.return_memory_offset.clone(),
1256        };
1257        Ok(Some(call_outcome))
1258    }
1259}
1260
1261pub struct RevmContractInstance<Runtime> {
1262    module: Vec<u8>,
1263    db: DatabaseRuntime<Runtime>,
1264}
1265
1266#[derive(Debug)]
1267enum EvmTxKind {
1268    Create,
1269    Call,
1270}
1271
1272#[derive(Debug)]
1273struct ExecutionResultSuccess {
1274    reason: SuccessReason,
1275    gas_final: u64,
1276    logs: Vec<Log>,
1277    output: Output,
1278}
1279
1280impl ExecutionResultSuccess {
1281    fn interpreter_result_and_logs(self) -> Result<(u64, Vec<u8>, Vec<Log>), ExecutionError> {
1282        let result: InstructionResult = self.reason.into();
1283        let Output::Call(output) = self.output else {
1284            unreachable!("The output should have been created from a EvmTxKind::Call");
1285        };
1286        let gas = Gas::new(0);
1287        let result = InterpreterResult {
1288            result,
1289            output,
1290            gas,
1291        };
1292        let result = bcs::to_bytes(&result)?;
1293        Ok((self.gas_final, result, self.logs))
1294    }
1295
1296    fn output_and_logs(self) -> (u64, Vec<u8>, Vec<Log>) {
1297        let Output::Call(output) = self.output else {
1298            unreachable!("The output should have been created from a EvmTxKind::Call");
1299        };
1300        let output = output.as_ref().to_vec();
1301        (self.gas_final, output, self.logs)
1302    }
1303
1304    // Checks that the contract has been correctly instantiated
1305    fn check_contract_initialization(&self, expected_address: Address) -> Result<(), String> {
1306        // Checks that the output is the expected one.
1307        let Output::Create(_, contract_address) = self.output else {
1308            return Err("Input should be ExmTxKind::Create".to_string());
1309        };
1310        // Checks that the contract address exists.
1311        let contract_address = contract_address.ok_or("Deployment failed")?;
1312        // Checks that the created contract address is the one of the `ApplicationId`.
1313        if contract_address == expected_address {
1314            Ok(())
1315        } else {
1316            Err("Contract address is not the same as ApplicationId".to_string())
1317        }
1318    }
1319}
1320
1321impl<Runtime> UserContract for RevmContractInstance<Runtime>
1322where
1323    Runtime: ContractRuntime,
1324{
1325    fn instantiate(&mut self, argument: Vec<u8>) -> Result<(), ExecutionError> {
1326        self.db.set_contract_address()?;
1327        let caller = self.get_msg_address()?;
1328        self.initialize_contract(caller)?;
1329        if has_selector(&self.module, INSTANTIATE_SELECTOR) {
1330            let instantiation_argument = serde_json::from_slice::<Vec<u8>>(&argument)?;
1331            let argument = get_revm_instantiation_bytes(instantiation_argument);
1332            let result = self.transact_commit(EvmTxKind::Call, argument, caller)?;
1333            self.write_logs(result.logs, "instantiate")?;
1334        }
1335        Ok(())
1336    }
1337
1338    fn execute_operation(&mut self, operation: Vec<u8>) -> Result<Vec<u8>, ExecutionError> {
1339        self.db.set_contract_address()?;
1340        ensure_message_length(operation.len(), 4)?;
1341        if operation == GET_DEPLOYED_BYTECODE_SELECTOR {
1342            return self.db.get_deployed_bytecode();
1343        }
1344        let caller = self.get_msg_address()?;
1345        let (gas_final, output, logs) = if &operation[..4] == INTERPRETER_RESULT_SELECTOR {
1346            ensure_message_length(operation.len(), 8)?;
1347            forbid_execute_operation_origin(&operation[4..8])?;
1348            let result = self.init_transact_commit(operation[4..].to_vec(), caller)?;
1349            result.interpreter_result_and_logs()?
1350        } else {
1351            ensure_message_length(operation.len(), 4)?;
1352            forbid_execute_operation_origin(&operation[..4])?;
1353            let result = self.init_transact_commit(operation, caller)?;
1354            result.output_and_logs()
1355        };
1356        self.consume_fuel(gas_final)?;
1357        self.write_logs(logs, "operation")?;
1358        Ok(output)
1359    }
1360
1361    fn execute_message(&mut self, message: Vec<u8>) -> Result<(), ExecutionError> {
1362        self.db.set_contract_address()?;
1363        ensure_selector_presence(
1364            &self.module,
1365            EXECUTE_MESSAGE_SELECTOR,
1366            "function execute_message(bytes)",
1367        )?;
1368        let operation = get_revm_execute_message_bytes(message);
1369        let caller = self.get_msg_address()?;
1370        self.execute_no_return_operation(operation, "message", caller)
1371    }
1372
1373    fn process_streams(&mut self, streams: Vec<StreamUpdate>) -> Result<(), ExecutionError> {
1374        self.db.set_contract_address()?;
1375        let operation = get_revm_process_streams_bytes(streams);
1376        ensure_selector_presence(
1377            &self.module,
1378            PROCESS_STREAMS_SELECTOR,
1379            "function process_streams(Linera.StreamUpdate[] memory streams)",
1380        )?;
1381        // For process_streams, authenticated_signer and authenticated_called_id are None.
1382        let caller = Address::ZERO;
1383        self.execute_no_return_operation(operation, "process_streams", caller)
1384    }
1385
1386    fn finalize(&mut self) -> Result<(), ExecutionError> {
1387        Ok(())
1388    }
1389}
1390
1391fn process_execution_result(
1392    storage_stats: StorageStats,
1393    result: ExecutionResult,
1394) -> Result<ExecutionResultSuccess, EvmExecutionError> {
1395    match result {
1396        ExecutionResult::Success {
1397            reason,
1398            gas_used,
1399            gas_refunded,
1400            logs,
1401            output,
1402        } => {
1403            let mut gas_final = gas_used;
1404            gas_final -= storage_stats.storage_costs();
1405            assert_eq!(gas_refunded, storage_stats.storage_refund());
1406            if !matches!(reason, SuccessReason::Return) {
1407                Err(EvmExecutionError::NoReturnInterpreter {
1408                    reason,
1409                    gas_used,
1410                    gas_refunded,
1411                    logs,
1412                    output,
1413                })
1414            } else {
1415                Ok(ExecutionResultSuccess {
1416                    reason,
1417                    gas_final,
1418                    logs,
1419                    output,
1420                })
1421            }
1422        }
1423        ExecutionResult::Revert { gas_used, output } => {
1424            Err(EvmExecutionError::Revert { gas_used, output })
1425        }
1426        ExecutionResult::Halt { gas_used, reason } => {
1427            Err(EvmExecutionError::Halt { gas_used, reason })
1428        }
1429    }
1430}
1431
1432impl<Runtime> RevmContractInstance<Runtime>
1433where
1434    Runtime: ContractRuntime,
1435{
1436    pub fn prepare(module: Vec<u8>, runtime: Runtime) -> Self {
1437        let db = DatabaseRuntime::new(runtime);
1438        Self { module, db }
1439    }
1440
1441    fn execute_no_return_operation(
1442        &mut self,
1443        operation: Vec<u8>,
1444        origin: &str,
1445        caller: Address,
1446    ) -> Result<(), ExecutionError> {
1447        let result = self.init_transact_commit(operation, caller)?;
1448        let (gas_final, output, logs) = result.output_and_logs();
1449        self.consume_fuel(gas_final)?;
1450        self.write_logs(logs, origin)?;
1451        assert_eq!(output.len(), 0);
1452        Ok(())
1453    }
1454
1455    /// Executes the transaction. If needed initializes the contract.
1456    fn init_transact_commit(
1457        &mut self,
1458        vec: Vec<u8>,
1459        caller: Address,
1460    ) -> Result<ExecutionResultSuccess, ExecutionError> {
1461        // An application can be instantiated in Linera sense, but not in EVM sense,
1462        // that is the contract entries corresponding to the deployed contract may
1463        // be missing.
1464        if !self.db.set_is_initialized()? {
1465            self.initialize_contract(caller)?;
1466        }
1467        self.transact_commit(EvmTxKind::Call, vec, caller)
1468    }
1469
1470    /// Initializes the contract.
1471    fn initialize_contract(&mut self, caller: Address) -> Result<(), ExecutionError> {
1472        let mut vec_init = self.module.clone();
1473        let constructor_argument = self.db.constructor_argument()?;
1474        vec_init.extend_from_slice(&constructor_argument);
1475        let result = self.transact_commit(EvmTxKind::Create, vec_init, caller)?;
1476        result
1477            .check_contract_initialization(self.db.contract_address)
1478            .map_err(EvmExecutionError::IncorrectContractCreation)?;
1479        self.write_logs(result.logs, "deploy")
1480    }
1481
1482    /// Computes the address used in the `msg.sender` variable.
1483    /// It is computed in the following way:
1484    /// * If a Wasm contract calls an EVM contract then it is `Address::ZERO`.
1485    /// * If an EVM contract calls an EVM contract it is the address of the contract.
1486    /// * If a user having an `AccountOwner::Address32` address calls an EVM contract
1487    ///   then it is `Address::ZERO`.
1488    /// * If a user having an `AccountOwner::Address20` address calls an EVM contract
1489    ///   then it is this address.
1490    ///
1491    /// By doing this we ensure that EVM smart contracts works in the same way as
1492    /// on the EVM and that users and contracts outside of that realm can still
1493    /// call EVM smart contracts.
1494    fn get_msg_address(&self) -> Result<Address, ExecutionError> {
1495        let mut runtime = self.db.runtime.lock().unwrap();
1496        let application_id = runtime.authenticated_caller_id()?;
1497        if let Some(application_id) = application_id {
1498            return Ok(if application_id.is_evm() {
1499                application_id.evm_address()
1500            } else {
1501                Address::ZERO
1502            });
1503        };
1504        let account_owner = runtime.authenticated_signer()?;
1505        if let Some(AccountOwner::Address20(address)) = account_owner {
1506            return Ok(Address::from(address));
1507        };
1508        Ok(ZERO_ADDRESS)
1509    }
1510
1511    fn transact_commit(
1512        &mut self,
1513        ch: EvmTxKind,
1514        input: Vec<u8>,
1515        caller: Address,
1516    ) -> Result<ExecutionResultSuccess, ExecutionError> {
1517        let data = Bytes::from(input);
1518        let kind = match ch {
1519            EvmTxKind::Create => TxKind::Create,
1520            EvmTxKind::Call => TxKind::Call(self.db.contract_address),
1521        };
1522        let inspector = CallInterceptorContract {
1523            db: self.db.clone(),
1524            contract_address: self.db.contract_address,
1525            precompile_addresses: precompile_addresses(),
1526        };
1527        let block_env = self.db.get_contract_block_env()?;
1528        let gas_limit = {
1529            let mut runtime = self.db.runtime.lock().unwrap();
1530            runtime.remaining_fuel(VmRuntime::Evm)?
1531        };
1532        let nonce = self.db.get_nonce(&caller)?;
1533        let result = {
1534            let ctx: revm_context::Context<
1535                BlockEnv,
1536                _,
1537                _,
1538                _,
1539                Journal<WrapDatabaseRef<&mut DatabaseRuntime<Runtime>>>,
1540                (),
1541            > = revm_context::Context::<BlockEnv, _, _, _, _, _>::new(
1542                WrapDatabaseRef(&mut self.db),
1543                SpecId::PRAGUE,
1544            )
1545            .with_block(block_env);
1546            let instructions = EthInstructions::new_mainnet();
1547            let mut evm = Evm::new_with_inspector(
1548                ctx,
1549                inspector.clone(),
1550                instructions,
1551                ContractPrecompile::default(),
1552            );
1553            evm.inspect_commit(
1554                TxEnv {
1555                    kind,
1556                    data,
1557                    nonce,
1558                    gas_limit,
1559                    caller,
1560                    ..TxEnv::default()
1561                },
1562                inspector,
1563            )
1564            .map_err(|error| {
1565                let error = format!("{:?}", error);
1566                EvmExecutionError::TransactCommitError(error)
1567            })
1568        }?;
1569        self.db.process_any_error()?;
1570        let storage_stats = self.db.take_storage_stats();
1571        self.db.commit_changes()?;
1572        let result = process_execution_result(storage_stats, result)?;
1573        Ok(result)
1574    }
1575
1576    fn consume_fuel(&mut self, gas_final: u64) -> Result<(), ExecutionError> {
1577        let mut runtime = self.db.runtime.lock().unwrap();
1578        runtime.consume_fuel(gas_final, VmRuntime::Evm)
1579    }
1580
1581    fn write_logs(&mut self, logs: Vec<Log>, origin: &str) -> Result<(), ExecutionError> {
1582        // TODO(#3758): Extracting Ethereum events from the Linera events.
1583        if !logs.is_empty() {
1584            let mut runtime = self.db.runtime.lock().unwrap();
1585            let block_height = runtime.block_height()?;
1586            let stream_name = bcs::to_bytes("ethereum_event")?;
1587            let stream_name = StreamName(stream_name);
1588            for log in &logs {
1589                let value = bcs::to_bytes(&(origin, block_height.0, log))?;
1590                runtime.emit(stream_name.clone(), value)?;
1591            }
1592        }
1593        Ok(())
1594    }
1595}
1596
1597pub struct RevmServiceInstance<Runtime> {
1598    module: Vec<u8>,
1599    db: DatabaseRuntime<Runtime>,
1600}
1601
1602impl<Runtime> RevmServiceInstance<Runtime>
1603where
1604    Runtime: ServiceRuntime,
1605{
1606    pub fn prepare(module: Vec<u8>, runtime: Runtime) -> Self {
1607        let db = DatabaseRuntime::new(runtime);
1608        Self { module, db }
1609    }
1610}
1611
1612impl<Runtime> UserService for RevmServiceInstance<Runtime>
1613where
1614    Runtime: ServiceRuntime,
1615{
1616    fn handle_query(&mut self, argument: Vec<u8>) -> Result<Vec<u8>, ExecutionError> {
1617        self.db.set_contract_address()?;
1618        let evm_query = serde_json::from_slice(&argument)?;
1619        let query = match evm_query {
1620            EvmQuery::Query(vec) => vec,
1621            EvmQuery::Mutation(operation) => {
1622                let mut runtime = self.db.runtime.lock().unwrap();
1623                runtime.schedule_operation(operation)?;
1624                return Ok(Vec::new());
1625            }
1626        };
1627
1628        ensure_message_length(query.len(), 4)?;
1629        // We drop the logs since the "eth_call" execution does not return any log.
1630        // Also, for handle_query, we do not have associated costs.
1631        // More generally, there is gas costs associated to service operation.
1632        let answer = if &query[..4] == INTERPRETER_RESULT_SELECTOR {
1633            let result = self.init_transact(query[4..].to_vec())?;
1634            let (_gas_final, answer, _logs) = result.interpreter_result_and_logs()?;
1635            answer
1636        } else {
1637            let result = self.init_transact(query)?;
1638            let (_gas_final, output, _logs) = result.output_and_logs();
1639            serde_json::to_vec(&output)?
1640        };
1641        Ok(answer)
1642    }
1643}
1644
1645impl<Runtime> RevmServiceInstance<Runtime>
1646where
1647    Runtime: ServiceRuntime,
1648{
1649    fn init_transact(&mut self, vec: Vec<u8>) -> Result<ExecutionResultSuccess, ExecutionError> {
1650        // In case of a shared application, we need to instantiate it first
1651        // However, since in ServiceRuntime, we cannot modify the storage,
1652        // therefore the compiled contract is saved in the changes.
1653        if !self.db.set_is_initialized()? {
1654            let changes = {
1655                let mut vec_init = self.module.clone();
1656                let constructor_argument = self.db.constructor_argument()?;
1657                vec_init.extend_from_slice(&constructor_argument);
1658                let (result, changes) = self.transact(TxKind::Create, vec_init)?;
1659                result
1660                    .check_contract_initialization(self.db.contract_address)
1661                    .map_err(EvmExecutionError::IncorrectContractCreation)?;
1662                changes
1663            };
1664            self.db.changes = changes;
1665        }
1666        ensure_message_length(vec.len(), 4)?;
1667        forbid_execute_operation_origin(&vec[..4])?;
1668        let kind = TxKind::Call(self.db.contract_address);
1669        let (execution_result, _) = self.transact(kind, vec)?;
1670        Ok(execution_result)
1671    }
1672
1673    fn transact(
1674        &mut self,
1675        kind: TxKind,
1676        input: Vec<u8>,
1677    ) -> Result<(ExecutionResultSuccess, EvmState), ExecutionError> {
1678        let data = Bytes::from(input);
1679        let block_env = self.db.get_service_block_env()?;
1680        let inspector = CallInterceptorService {
1681            db: self.db.clone(),
1682            contract_address: self.db.contract_address,
1683            precompile_addresses: precompile_addresses(),
1684        };
1685        let caller = SERVICE_ADDRESS;
1686        let nonce = self.db.get_nonce(&caller)?;
1687        let result_state = {
1688            let ctx: revm_context::Context<
1689                BlockEnv,
1690                _,
1691                _,
1692                _,
1693                Journal<WrapDatabaseRef<&mut DatabaseRuntime<Runtime>>>,
1694                (),
1695            > = revm_context::Context::<BlockEnv, _, _, _, _, _>::new(
1696                WrapDatabaseRef(&mut self.db),
1697                SpecId::PRAGUE,
1698            )
1699            .with_block(block_env);
1700            let instructions = EthInstructions::new_mainnet();
1701            let mut evm = Evm::new_with_inspector(
1702                ctx,
1703                inspector.clone(),
1704                instructions,
1705                ServicePrecompile::default(),
1706            );
1707            evm.inspect(
1708                TxEnv {
1709                    kind,
1710                    data,
1711                    nonce,
1712                    caller,
1713                    gas_limit: EVM_SERVICE_GAS_LIMIT,
1714                    ..TxEnv::default()
1715                },
1716                inspector,
1717            )
1718            .map_err(|error| {
1719                let error = format!("{:?}", error);
1720                EvmExecutionError::TransactCommitError(error)
1721            })
1722        }?;
1723        self.db.process_any_error()?;
1724        let storage_stats = self.db.take_storage_stats();
1725        Ok((
1726            process_execution_result(storage_stats, result_state.result)?,
1727            result_state.state,
1728        ))
1729    }
1730}