1
// Copyright 2019-2025 PureStake Inc.
2
// This file is part of Moonbeam.
3

            
4
// Moonbeam is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8

            
9
// Moonbeam is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13

            
14
// You should have received a copy of the GNU General Public License
15
// along with Moonbeam.  If not, see <http://www.gnu.org/licenses/>.
16

            
17
//! A Proxy in this context is an environmental trait implementor meant to be used for capturing
18
//! EVM trace events sent to a Host function from the Runtime. Works like:
19
//! - Runtime Api call `using` environmental.
20
//! - Runtime calls a Host function with some scale-encoded Evm event.
21
//! - Host function emits an additional event to this Listener.
22
//! - Proxy listens for the event and format the actual trace response.
23
//!
24
//! There are two proxy types: `Raw` and `CallList`.
25
//! - `Raw` - used for opcode-level traces.
26
//! - `CallList` - used for block tracing (stack of call stacks) and custom tracing outputs.
27
//!
28
//! The EVM event types may contain references and not implement Encode/Decode.
29
//! This module provide mirror types and conversion into them from the original events.
30

            
31
#![cfg_attr(not(feature = "std"), no_std)]
32
extern crate alloc;
33

            
34
pub mod evm;
35
pub mod gasometer;
36
pub mod runtime;
37

            
38
pub use self::evm::EvmEvent;
39
pub use gasometer::GasometerEvent;
40
pub use runtime::RuntimeEvent;
41

            
42
use ethereum_types::{H160, U256};
43
use parity_scale_codec::{Decode, Encode};
44

            
45
environmental::environmental!(listener: dyn Listener + 'static);
46

            
47
pub fn using<R, F: FnOnce() -> R>(l: &mut (dyn Listener + 'static), f: F) -> R {
48
	listener::using(l, f)
49
}
50

            
51
/// Allow to configure which data of the Step event
52
/// we want to keep or discard. Not discarding the data requires cloning the data
53
/// in the runtime which have a significant cost for each step.
54
#[derive(Clone, Copy, Eq, PartialEq, Debug, Encode, Decode, Default)]
55
pub struct StepEventFilter {
56
	pub enable_stack: bool,
57
	pub enable_memory: bool,
58
}
59

            
60
#[derive(Clone, Eq, PartialEq, Debug, Encode, Decode)]
61
pub enum Event {
62
	Evm(evm::EvmEvent),
63
	Gasometer(gasometer::GasometerEvent),
64
	Runtime(runtime::RuntimeEvent),
65
	CallListNew(),
66
}
67

            
68
impl Event {
69
	/// Access the global reference and call it's `event` method, passing the `Event` itself as
70
	/// argument.
71
	///
72
	/// This only works if we are `using` a global reference to a `Listener` implementor.
73
285
	pub fn emit(self) {
74
285
		listener::with(|listener| listener.event(self));
75
285
	}
76
}
77

            
78
/// Main trait to proxy emitted messages.
79
/// Used 2 times :
80
/// - Inside the runtime to proxy the events through the host functions
81
/// - Inside the client to forward those events to the client listener.
82
pub trait Listener {
83
	fn event(&mut self, event: Event);
84

            
85
	/// Allow the runtime to know which data should be discarded and not cloned.
86
	/// WARNING: It is only called once when the runtime tracing is instantiated to avoid
87
	/// performing many ext calls.
88
	fn step_event_filter(&self) -> StepEventFilter;
89
}
90

            
91
228
pub fn step_event_filter() -> Option<StepEventFilter> {
92
228
	let mut filter = None;
93
228
	listener::with(|listener| filter = Some(listener.step_event_filter()));
94
228
	filter
95
228
}
96

            
97
#[derive(Clone, Debug, Encode, Decode, PartialEq, Eq)]
98
pub struct Context {
99
	/// Execution address.
100
	pub address: H160,
101
	/// Caller of the EVM.
102
	pub caller: H160,
103
	/// Apparent value of the EVM.
104
	pub apparent_value: U256,
105
}
106

            
107
impl From<evm_runtime::Context> for Context {
108
	fn from(i: evm_runtime::Context) -> Self {
109
		Self {
110
			address: i.address,
111
			caller: i.caller,
112
			apparent_value: i.apparent_value,
113
		}
114
	}
115
}