arbiter_core/environment/instruction.rs
1//! This module contains the `Instruction` and `Outcome` enums that are used to
2//! communicate instructions and their outcomes between the
3//! [`middleware::ArbiterMiddleware`] and the [`Environment`].
4
5use super::*;
6
7/// [`Instruction`]s that can be sent to the [`Environment`] via the
8/// [`Socket`].
9/// These instructions can be:
10/// - [`Instruction::AddAccount`],
11/// - [`Instruction::BlockUpdate`],
12/// - [`Instruction::Call`],
13/// - [`Instruction::Cheatcode`],
14/// - [`Instruction::Query`].
15/// - [`Instruction::SetGasPrice`],
16/// - [`Instruction::Stop`],
17/// - [`Instruction::Transaction`],
18
19/// The [`Instruction`]s are sent to the [`Environment`] via the
20/// [`Socket::instruction_sender`] and the results are received via the
21/// [`crate::middleware::Connection::outcome_receiver`].
22#[derive(Debug, Clone)]
23pub(crate) enum Instruction {
24 /// An `AddAccount` is used to add a default/unfunded account to the
25 /// [`Environment`].
26 AddAccount {
27 /// The address of the account to add to the [`EVM`].
28 address: eAddress,
29
30 /// The sender used to to send the outcome of the account addition back
31 /// to.
32 outcome_sender: OutcomeSender,
33 },
34
35 /// A `BlockUpdate` is used to update the block number and timestamp of the
36 /// [`Environment`].
37 BlockUpdate {
38 /// The block number to update the [`EVM`] to.
39 block_number: eU256,
40
41 /// The block timestamp to update the [`EVM`] to.
42 block_timestamp: eU256,
43
44 /// The sender used to to send the outcome of the block update back to.
45 outcome_sender: OutcomeSender,
46 },
47
48 /// A `Call` is processed by the [`EVM`] but will not be state changing and
49 /// will not create events.
50 Call {
51 /// The transaction environment for the call.
52 tx_env: TxEnv,
53
54 /// The sender used to to send the outcome of the call back to.
55 outcome_sender: OutcomeSender,
56 },
57
58 /// A `cheatcode` enables direct access to the underlying [`EVM`].
59 Cheatcode {
60 /// The [`Cheatcode`] to use to access the underlying [`EVM`].
61 cheatcode: Cheatcodes,
62
63 /// The sender used to to send the outcome of the cheatcode back to.
64 outcome_sender: OutcomeSender,
65 },
66
67 /// A `Query` is used to query the [`EVM`] for some data, the choice of
68 /// which data is specified by the inner `EnvironmentData` enum.
69 Query {
70 /// The data to query the [`EVM`] for.
71 environment_data: EnvironmentData,
72
73 /// The sender used to to send the outcome of the query back to.
74 outcome_sender: OutcomeSender,
75 },
76
77 /// A `SetGasPrice` is used to set the gas price of the [`EVM`].
78 SetGasPrice {
79 /// The gas price to set the [`EVM`] to.
80 gas_price: eU256,
81
82 /// The sender used to to send the outcome of the gas price setting back
83 /// to.
84 outcome_sender: OutcomeSender,
85 },
86
87 /// A `Stop` is used to stop the [`Environment`].
88 Stop(OutcomeSender),
89
90 /// A `Transaction` is processed by the [`EVM`] and will be state changing
91 /// and will create events.
92 Transaction {
93 /// The transaction environment for the transaction.
94 tx_env: TxEnv,
95
96 /// The sender used to to send the outcome of the transaction back to.
97 outcome_sender: OutcomeSender,
98 },
99}
100
101/// [`Outcome`]s that can be sent back to the the client via the
102/// [`Socket`].
103/// These outcomes can be from `Call`, `Transaction`, or `BlockUpdate`
104/// instructions sent to the [`Environment`]
105#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
106pub(crate) enum Outcome {
107 /// The outcome of an [`Instruction::AddAccount`] instruction that is used
108 /// to signify that the account was added successfully.
109 AddAccountCompleted,
110
111 /// The outcome of a `BlockUpdate` instruction that is used to provide a
112 /// non-error output of updating the block number and timestamp of the
113 /// [`EVM`] to the client.
114 BlockUpdateCompleted(ReceiptData),
115
116 /// Return value from a cheatcode instruction.
117 /// todo: make a decision on how to handle cheatcode returns.
118 CheatcodeReturn(CheatcodesReturn),
119
120 /// The outcome of a `Call` instruction that is used to provide the output
121 /// of some [`EVM`] computation to the client.
122 CallCompleted(ExecutionResult),
123
124 /// The outcome of a [`Instruction::SetGasPrice`] instruction that is used
125 /// to signify that the gas price was set successfully.
126 SetGasPriceCompleted,
127
128 /// The outcome of a `Transaction` instruction that is first unpacked to see
129 /// if the result is successful, then it can be used to build a
130 /// `TransactionReceipt` in the `Middleware`.
131 TransactionCompleted(ExecutionResult, ReceiptData),
132
133 /// The outcome of a `Query` instruction that carries a `String`
134 /// representation of the data. Currently this may carry the block
135 /// number, block timestamp, gas price, or balance of an account.
136 QueryReturn(String),
137
138 /// The outcome of a `Stop` instruction that is used to signify that the
139 /// [`Environment`] was stopped successfully.
140 StopCompleted(ArbiterDB),
141}
142
143/// [`EnvironmentData`] is an enum used inside of the [`Instruction::Query`] to
144/// specify what data should be returned to the user.
145/// Currently this may be the block number, block timestamp, gas price, or
146/// balance of an account.
147#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
148#[allow(clippy::large_enum_variant)]
149pub(crate) enum EnvironmentData {
150 /// The query is for the block number of the [`EVM`].
151 BlockNumber,
152
153 /// The query is for the block timestamp of the [`EVM`].
154 BlockTimestamp,
155
156 /// The query is for the gas price of the [`EVM`].
157 GasPrice,
158
159 /// The query is for the balance of an account given by the inner `Address`.
160 Balance(eAddress),
161
162 // TODO: Rename this to `Nonce`?
163 /// The query is for the nonce of an account given by the inner `Address`.
164 TransactionCount(eAddress),
165
166 /// Query for logs in a range of blocks.
167 Logs {
168 /// The filter to use to query for logs
169 filter: Filter,
170 },
171}
172
173/// [`ReceiptData`] is a structure that holds the block number, transaction
174/// index, and cumulative gas used per block for a transaction.
175#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
176pub struct ReceiptData {
177 /// `block_number` is the number of the block in which the transaction was
178 /// included.
179 pub block_number: U64,
180 /// `transaction_index` is the index position of the transaction in the
181 /// block.
182 pub transaction_index: U64,
183 /// `cumulative_gas_per_block` is the total amount of gas used in the
184 /// block up until and including the transaction.
185 pub cumulative_gas_per_block: eU256,
186}
187
188/// Cheatcodes are a direct way to access the underlying [`EVM`] environment and
189/// database.
190#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
191pub enum Cheatcodes {
192 /// A `Deal` is used to increase the balance of an account in the [`EVM`].
193 Deal {
194 /// The address of the account to increase the balance of.
195 address: eAddress,
196
197 /// The amount to increase the balance of the account by.
198 amount: eU256,
199 },
200 /// Fetches the value of a storage slot of an account.
201 Load {
202 /// The address of the account to fetch the storage slot from.
203 account: eAddress,
204 /// The storage slot to fetch.
205 key: H256,
206 /// The block to fetch the storage slot from.
207 /// todo: implement storage slots at blocks.
208 block: Option<ethers::types::BlockId>,
209 },
210 /// Overwrites a storage slot of an account.
211 /// TODO: for more complicated data types, like structs, there's more work
212 /// to do.
213 Store {
214 /// The address of the account to overwrite the storage slot of.
215 account: ethers::types::Address,
216 /// The storage slot to overwrite.
217 key: ethers::types::H256,
218 /// The value to overwrite the storage slot with.
219 value: ethers::types::H256,
220 },
221 /// Fetches the `DbAccount` account at the given address.
222 Access {
223 /// The address of the account to fetch.
224 address: ethers::types::Address,
225 },
226}
227
228/// Wrapper around [`AccountState`] that can be serialized and deserialized.
229#[derive(Debug, Clone, Default, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
230pub enum AccountStateSerializable {
231 /// Before Spurious Dragon hardfork there was a difference between empty and
232 /// not existing. And we are flagging it here.
233 NotExisting,
234 /// EVM touched this account. For newer hardfork this means it can be
235 /// cleared/removed from state.
236 Touched,
237 /// EVM cleared storage of this account, mostly by selfdestruct, we don't
238 /// ask database for storage slots and assume they are U256::ZERO
239 StorageCleared,
240 /// EVM didn't interacted with this account
241 #[default]
242 None,
243}
244
245/// Return values of applying cheatcodes.
246#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
247pub enum CheatcodesReturn {
248 /// A `Load` returns the value of a storage slot of an account.
249 Load {
250 /// The value of the storage slot.
251 value: U256,
252 },
253 /// A `Store` returns nothing.
254 Store,
255 /// A `Deal` returns nothing.
256 Deal,
257 /// Gets the DbAccount associated with an address.
258 Access {
259 /// Basic account information like nonce, balance, code hash, bytcode.
260 info: AccountInfo,
261 /// todo: revm must be updated with serde deserialize, then `DbAccount`
262 /// can be used.
263 account_state: AccountStateSerializable,
264 /// Storage slots of the account.
265 storage: HashMap<U256, U256>,
266 },
267}