{"record":{"id":"240a5370f8adf7d9","repo":"linera-io/linera-protocol","slug":"it-is-illegal-to-call-function-process-streams-fro","errorCode":null,"errorMessage":"It is illegal to call function process_streams from an operation","messagePattern":"It is illegal to call function process_streams from an operation","errorType":"validation","errorClass":"EvmExecutionError","httpStatus":null,"severity":"error","filePath":"linera-execution/src/evm/inputs.rs","lineNumber":173,"sourceCode":"/// only from a submitted message\npub(crate) const PROCESS_STREAMS_SELECTOR: &[u8] =\n    &<process_streamsCall as alloy_sol_types::SolCall>::SELECTOR;\n\n/// This is the selector of `summarize_events`, which is called by the system on a\n/// checkpoint and never from a submitted operation.\npub(crate) const SUMMARIZE_EVENTS_SELECTOR: &[u8] =\n    &<summarize_eventsCall as alloy_sol_types::SolCall>::SELECTOR;\n\n/// This is the selector of `instantiate` that should be called\n/// only when creating a new instance of a shared contract\npub(crate) const INSTANTIATE_SELECTOR: &[u8] = &[156, 163, 60, 158];\n\npub(crate) fn forbid_execute_operation_origin(vec: &[u8]) -> Result<(), EvmExecutionError> {\n    ensure!(\n        vec != EXECUTE_MESSAGE_SELECTOR,\n        EvmExecutionError::IllegalOperationCall(\"function execute_message\".to_string(),)\n    );\n    ensure!(\n        vec != PROCESS_STREAMS_SELECTOR,\n        EvmExecutionError::IllegalOperationCall(\"function process_streams\".to_string(),)\n    );\n    ensure!(\n        vec != SUMMARIZE_EVENTS_SELECTOR,\n        EvmExecutionError::IllegalOperationCall(\"function summarize_events\".to_string(),)\n    );\n    ensure!(\n        vec != INSTANTIATE_SELECTOR,\n        EvmExecutionError::IllegalOperationCall(\"function instantiate\".to_string(),)\n    );\n    Ok(())\n}\n\npub(crate) fn ensure_message_length(\n    actual_length: usize,\n    min_length: usize,\n) -> Result<(), EvmExecutionError> {","sourceCodeStart":155,"sourceCodeEnd":191,"githubUrl":"https://github.com/linera-io/linera-protocol/blob/6c226ddcb332ef55118dc8d0aafbd093d5420899/linera-execution/src/evm/inputs.rs#L155-L191","documentation":"Second guard in forbid_execute_operation_origin (used by execute_operation and init_transact): the operation calldata's 4-byte selector must not equal PROCESS_STREAMS_SELECTOR, the reserved function the system calls on an EVM contract when delivering stream messages. Invoking process_streams from a user operation is rejected before execution because it would let operations fake system-driven stream processing.","triggerScenarios":"An EVM operation or transact request whose calldata begins with the process_streams selector — a Solidity function with the same name/signature (common in stream-subscription contracts ported verbatim), or an ABI collision with an unrelated function hashing to the same 4 bytes.","commonSituations":"Contracts generated from Linera's EVM interface ABI re-exposing process_streams as public; hand-written wrappers around the stream API invoked via operations; selector collisions from large contracts (probability grows with many functions).","solutions":["Rename the function or alter its parameter types so its selector no longer matches process_streams","Route stream processing through actual message/stream delivery rather than operations","Pre-check the calldata selector client-side before submitting the operation"],"exampleFix":"// Solidity: rename to change the selector\n// before\nfunction process_streams(bytes calldata input) external { ... }\n// after\nfunction apply_stream_events(bytes calldata input) external { ... }","handlingStrategy":"validation","validationCode":"fn targets_process_streams(calldata: &[u8], process_streams_selector: [u8; 4]) -> bool {\n    calldata.get(..4) == Some(&process_streams_selector[..])\n}\n\n// compute the selector from your contract ABI, e.g. keccak(\"process_streams(...)\")[..4]\nassert!(!targets_process_streams(&operation_calldata, selector));","typeGuard":"fn is_illegal_process_streams_call(err: &ExecutionError) -> bool {\n    matches!(\n        err,\n        ExecutionError::EvmError(evm_error!::IllegalOperationCall(ref f)) if f.contains(\"process_streams\")\n    )\n}","tryCatchPattern":"match client.execute_operations(ops, vec![]).await {\n    Err(e) if is_illegal_process_streams_call(&e) => {\n        Err(anyhow::anyhow!(\"operation targets reserved process_streams selector: {e}\"))\n    }\n    other => other,\n}","preventionTips":["Keep system stream entry points out of your contract's external ABI (mark them internal)","Check generated bindings: some generators expose system functions as callable wrappers","Add a CI check that fails if any exported function's selector equals the reserved ones"],"tags":["linera","evm","solidity","selector","streams","entry-point"],"backgroundTag":"reserved-entrypoint-invocation","analyzedSha":"6c226ddcb332ef55118dc8d0aafbd093d5420899","analyzedAt":"2026-08-22T22:49:09.787Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}