massa_execution_exports/types.rs
1// Copyright (c) 2022 MASSA LABS <info@massa.net>
2
3//! This file exports useful types used to interact with the execution worker
4
5use crate::error::ExecutionQueryError;
6use crate::event_store::EventStore;
7use crate::execution_info::{ExecutionInfoForSlot, TransferInfo};
8use massa_deferred_calls::DeferredCall;
9use massa_final_state::StateChanges;
10use massa_hash::Hash;
11use massa_models::block_id::BlockId;
12use massa_models::bytecode::Bytecode;
13use massa_models::datastore::Datastore;
14use massa_models::deferred_calls::DeferredCallId;
15use massa_models::denunciation::DenunciationIndex;
16use massa_models::execution::EventFilter;
17use massa_models::operation::OperationId;
18use massa_models::output_event::SCOutputEvent;
19use massa_models::prehash::PreHashSet;
20use massa_models::{
21 address::Address, address::ExecutionAddressCycleInfo, amount::Amount, slot::Slot,
22};
23use massa_pos_exports::ProductionStats;
24use massa_storage::Storage;
25use serde::Serialize;
26use std::collections::{BTreeMap, BTreeSet};
27use std::ops::Bound;
28
29#[cfg(feature = "execution-trace")]
30use crate::types_trace_info::{SlotAbiCallStack, Transfer};
31
32/// Metadata needed to execute the block
33#[derive(Clone, Debug)]
34pub struct ExecutionBlockMetadata {
35 /// Address of the creator of the parent in the same thread
36 pub same_thread_parent_creator: Option<Address>,
37 /// Storage referencing the block and its contents
38 pub storage: Option<Storage>,
39}
40
41/// Request to atomically execute a batch of execution state queries
42pub struct ExecutionQueryRequest {
43 /// List of requests
44 pub requests: Vec<ExecutionQueryRequestItem>,
45 /// Maximum aggregate size (bytes) of large payload items
46 /// (`Bytecode`, `DatastoreValue`, `Events`, datastore keys)
47 /// allowed in the response. Callers should pass their transport limit
48 /// (e.g. JSON-RPC `max_response_body_size` or gRPC `max_encoding_message_size`).
49 /// Other response variants are treated as zero-cost for this budget.
50 pub max_response_size: usize,
51 /// Event budget for the whole batch: each `Events` item takes
52 /// `min(remaining, per-item cap)` and decrements what it returns; an `Events`
53 /// item past zero gets a per-item `TooLargeResponse` error instead of being
54 /// fetched. `None` means unbounded (explicit opt-out, e.g. tests and empty
55 /// requests — never for transport-facing batches).
56 pub max_event_count: Option<usize>,
57 /// Wall-clock deadline for the whole batch, in milliseconds. Past the
58 /// deadline, remaining items return a per-item `TooLargeResponse` error;
59 /// already-computed items stay valid. `None` means no deadline (explicit
60 /// opt-out, e.g. tests and empty requests — never for transport-facing
61 /// batches). Safety net against lock contention, not the main bound.
62 pub query_state_deadline_ms: Option<u64>,
63}
64
65/// Response to a list of execution queries
66pub struct ExecutionQueryResponse {
67 /// List of responses
68 pub responses: Vec<Result<ExecutionQueryResponseItem, ExecutionQueryError>>,
69 /// Last executed candidate slot
70 pub candidate_cursor: Slot,
71 /// Last executed final slot
72 pub final_cursor: Slot,
73 /// Final state hash
74 pub final_state_fingerprint: Hash,
75}
76
77/// Execution state query item
78pub enum ExecutionQueryRequestItem {
79 /// checks if address exists (candidate) returns ExecutionQueryResponseItem::Boolean(true) if it does
80 AddressExistsCandidate(Address),
81 /// checks if address exists (final) returns ExecutionQueryResponseItem::Boolean(true) if it does
82 AddressExistsFinal(Address),
83 /// gets the balance (candidate) of an address, returns ExecutionQueryResponseItem::Amount(balance) or an error if the address is not found
84 AddressBalanceCandidate(Address),
85 /// gets the balance (final) of an address, returns ExecutionQueryResponseItem::Amount(balance) or an error if the address is not found
86 AddressBalanceFinal(Address),
87 /// gets the bytecode (candidate) of an address, returns ExecutionQueryResponseItem::Bytecode(bytecode) or an error if the address is not found
88 AddressBytecodeCandidate(Address),
89 /// gets the bytecode (final) of an address, returns ExecutionQueryResponseItem::Bytecode(bytecode) or an error if the address is not found
90 AddressBytecodeFinal(Address),
91 /// gets the datastore keys (candidate) of an address, returns ExecutionQueryResponseItem::AddressDatastoreKeys(keys, addr, is_final) or an error if the address is not found
92 AddressDatastoreKeysCandidate {
93 /// Address for which to query the datastore
94 address: Address,
95 /// Filter only entries whose key starts with a prefix
96 prefix: Vec<u8>,
97 /// Bound to start from
98 start_key: Bound<Vec<u8>>,
99 /// End bound
100 end_key: Bound<Vec<u8>>,
101 /// Maximum number of keys to return
102 count: Option<u32>,
103 },
104 /// gets the datastore keys (final) of an address, returns ExecutionQueryResponseItem::AddressDatastoreKeys(keys, addr, is_final) or an error if the address is not found
105 AddressDatastoreKeysFinal {
106 /// Address for which to query the datastore
107 address: Address,
108 /// Filter only entries whose key starts with a prefix
109 prefix: Vec<u8>,
110 /// Bound to start from
111 start_key: Bound<Vec<u8>>,
112 /// End bound
113 end_key: Bound<Vec<u8>>,
114 /// Maximum number of keys to return
115 count: Option<u32>,
116 },
117 /// gets a datastore value (candidate) for an address, returns ExecutionQueryResponseItem::DatastoreValue(keys) or an error if the address or key is not found
118 AddressDatastoreValueCandidate {
119 /// Address for which to query the datastore
120 addr: Address,
121 /// Key of the entry
122 key: Vec<u8>,
123 },
124 /// gets a datastore value (final) for an address, returns ExecutionQueryResponseItem::DatastoreValue(keys) or an error if the address or key is not found
125 AddressDatastoreValueFinal {
126 /// Address for which to query the datastore
127 addr: Address,
128 /// Key of the entry
129 key: Vec<u8>,
130 },
131
132 /// gets the execution status (candidate) for an operation, returns ExecutionQueryResponseItem::ExecutionStatus(status)
133 OpExecutionStatusCandidate(OperationId),
134 /// gets the execution status (final) for an operation, returns ExecutionQueryResponseItem::ExecutionStatus(status)
135 OpExecutionStatusFinal(OperationId),
136
137 /// gets the deferred call quote (candidate) for a slot, returns ExecutionQueryResponseItem::DeferredCallQuote(available, price)
138 DeferredCallQuote {
139 /// slot to query
140 target_slot: Slot,
141 /// gas request
142 max_gas_request: u64,
143 /// params size
144 params_size: u64,
145 },
146 /// get info of deferred calls
147 DeferredCallInfo(DeferredCallId),
148 /// retrieves the deferred call for given slot
149 DeferredCallsBySlot(Slot),
150
151 /// gets the execution status (candidate) for an denunciation, returns ExecutionQueryResponseItem::ExecutionStatus(status)
152 DenunciationExecutionStatusCandidate(DenunciationIndex),
153 /// gets the execution status (final) for an denunciation, returns ExecutionQueryResponseItem::ExecutionStatus(status)
154 DenunciationExecutionStatusFinal(DenunciationIndex),
155
156 /// gets the roll count (candidate) of an address, returns ExecutionQueryResponseItem::RollCount(rolls) or an error if the address is not found
157 AddressRollsCandidate(Address),
158 /// gets the roll count (final) of an address, returns ExecutionQueryResponseItem::RollCount(rolls) or an error if the address is not found
159 AddressRollsFinal(Address),
160 /// gets the deferred credits (candidate) of an address, returns ExecutionQueryResponseItem::DeferredCredits(deferred_credits) or an error if the address is not found
161 AddressDeferredCreditsCandidate(Address),
162 /// gets the deferred credits (final) of an address, returns ExecutionQueryResponseItem::DeferredCredits(deferred_credits) or an error if the address is not found
163 AddressDeferredCreditsFinal(Address),
164
165 /// get all information for a given cycle, returns ExecutionQueryResponseItem::CycleInfos(cycle_infos) or an error if the cycle is not found
166 CycleInfos {
167 /// cycle to query
168 cycle: u64,
169 /// optionally restrict the query to a set of addresses. If None, the info for all addresses will be returned.
170 restrict_to_addresses: Option<PreHashSet<Address>>,
171 },
172
173 /// get filtered events. Returns ExecutionQueryResponseItem::Events
174 Events(EventFilter),
175}
176
177/// Execution state query response item
178pub enum ExecutionQueryResponseItem {
179 /// boolean value
180 Boolean(bool),
181 /// roll counts value
182 RollCount(u64),
183 /// amount value
184 Amount(Amount),
185 /// bytecode
186 Bytecode(Bytecode),
187 /// datastore value
188 DatastoreValue(Vec<u8>),
189 /// list of keys (keys, address, is_final)
190 AddressDatastoreKeys(BTreeSet<Vec<u8>>, Address, bool),
191 /// deferred call quote (target_slot, gas_request, available, price)
192 DeferredCallQuote(Slot, u64, bool, Amount),
193 /// deferred call info value
194 DeferredCallInfo(DeferredCallId, DeferredCall),
195 /// deferred call slot calls value
196 DeferredCallsBySlot(Slot, Vec<DeferredCallId>),
197 /// deferred credits value
198 DeferredCredits(BTreeMap<Slot, Amount>),
199 /// execution status value
200 ExecutionStatus(ExecutionQueryExecutionStatus),
201 /// cycle infos value
202 CycleInfos(ExecutionQueryCycleInfos),
203 /// Events
204 Events(Vec<SCOutputEvent>),
205}
206
207/// Execution status of an operation or denunciation
208pub enum ExecutionQueryExecutionStatus {
209 /// The operation or denunciation was found as successfully executed in the active history
210 AlreadyExecutedWithSuccess,
211 /// The operation or denunciation was found as executed with errors in the active history
212 AlreadyExecutedWithFailure,
213 /// No information about the operation or denunciation execution were found in the node.
214 /// However the node only keeps execution information until the operation or denunciation expires
215 /// in order to prevent it from being re-executed during its validity time.
216 /// ExecutableOrExpired means that the operation or denunciations was either never executed,
217 /// or was executed previously and ran out of its validify period.
218 /// In other terms, the operation or denunciation can still be executed unless it has expired.
219 ExecutableOrExpired,
220}
221
222/// Information about cycles
223pub struct ExecutionQueryCycleInfos {
224 /// cycle number
225 pub cycle: u64,
226 /// whether the cycle is final
227 pub is_final: bool,
228 /// infos for each PoS-participating address among the ones that were asked
229 pub staker_infos: BTreeMap<Address, ExecutionQueryStakerInfo>,
230}
231
232/// Staker information for a given cycle
233pub struct ExecutionQueryStakerInfo {
234 /// active roll count
235 pub active_rolls: u64,
236 /// production stats
237 pub production_stats: ProductionStats,
238}
239
240/// Execution info about an address
241#[derive(Clone, Debug)]
242pub struct ExecutionAddressInfo {
243 /// candidate balance of the address
244 pub candidate_balance: Amount,
245 /// final balance of the address
246 pub final_balance: Amount,
247
248 /// final number of rolls the address has
249 pub final_roll_count: u64,
250 /// final datastore keys of the address
251 pub final_datastore_keys: BTreeSet<Vec<u8>>,
252
253 /// candidate number of rolls the address has
254 pub candidate_roll_count: u64,
255 /// candidate datastore keys of the address
256 pub candidate_datastore_keys: BTreeSet<Vec<u8>>,
257
258 /// future deferred credits
259 pub future_deferred_credits: BTreeMap<Slot, Amount>,
260
261 /// cycle information
262 pub cycle_infos: Vec<ExecutionAddressCycleInfo>,
263}
264
265/// structure describing the output of the execution of a slot
266#[derive(Debug, Clone)]
267pub enum SlotExecutionOutput {
268 /// Executed slot output
269 ExecutedSlot(ExecutionOutput),
270
271 /// Finalized slot output
272 FinalizedSlot(ExecutionOutput),
273}
274
275/// structure storing a block id + network versions (from a block header)
276#[derive(Debug, Clone, Serialize)]
277pub struct ExecutedBlockInfo {
278 /// Block id
279 pub block_id: BlockId,
280 /// Current network version (see Versioning doc)
281 pub current_version: u32,
282 /// Announced network version (see Versioning doc)
283 pub announced_version: Option<u32>,
284}
285
286/// structure describing the output of a single execution
287#[derive(Debug, Clone, Serialize)]
288pub struct ExecutionOutput {
289 /// slot
290 pub slot: Slot,
291 /// optional executed block info at that slot (None if miss)
292 pub block_info: Option<ExecutedBlockInfo>,
293 /// state changes caused by the execution step
294 pub state_changes: StateChanges,
295 /// events emitted by the execution step
296 pub events: EventStore,
297 /// slot trace
298 #[cfg(feature = "execution-trace")]
299 pub slot_trace: Option<(SlotAbiCallStack, Vec<Transfer>)>,
300 /// storage
301 #[cfg(feature = "dump-block")]
302 #[serde(skip_serializing)]
303 pub storage: Option<Storage>,
304 /// Deferred credits execution (empty if execution-info feature is NOT enabled)
305 pub deferred_credits_execution: Vec<(Address, Result<Amount, String>)>,
306 /// Cancel async message execution (empty if execution-info feature is NOT enabled)
307 pub cancel_async_message_execution: Vec<(Address, Result<Amount, String>)>,
308 /// Auto sell roll execution (empty if execution-info feature is NOT enabled)
309 pub auto_sell_execution: Vec<(Address, Amount)>,
310 /// history of transfers (empty if execution-info feature is NOT enabled)
311 pub transfers_history: Vec<TransferInfo>,
312 /// Per-slot execution info (rewards, denunciations, roll ops, async /
313 /// deferred call results, etc.) gathered during `execute_slot` and
314 /// carried on the `ExecutionOutput` so that finalization can broadcast
315 /// it with the correct slot metadata even when multiple active slots
316 /// have been speculatively executed ahead of the finalized one.
317 ///
318 /// Not serialized: `ExecutionInfoForSlot` bundles traces that are not
319 /// `Serialize`. The slot-replayer dump path (which is the only user
320 /// of `ExecutionOutput`'s `Serialize`) doesn't need this field.
321 ///
322 /// Populated only when the `execution-info` feature is enabled in the
323 /// execution worker — `None` otherwise.
324 #[serde(skip)]
325 pub execution_info: Option<ExecutionInfoForSlot>,
326}
327
328/// structure describing the output of a read only execution
329#[derive(Debug, Clone)]
330pub struct ReadOnlyExecutionOutput {
331 /// Output of a single execution
332 pub out: ExecutionOutput,
333 /// Gas cost for this execution, with needed adjustments
334 pub gas_cost: u64,
335 /// Returned value from the module call
336 pub call_result: Vec<u8>,
337}
338
339/// structure describing different types of read-only execution request
340#[derive(Debug, Clone)]
341pub struct ReadOnlyExecutionRequest {
342 /// Maximum gas to spend in the execution.
343 pub max_gas: u64,
344 /// Call stack to simulate, older caller first
345 pub call_stack: Vec<ExecutionStackElement>,
346 /// Target of the request
347 pub target: ReadOnlyExecutionTarget,
348 /// Coins transferred to the target address during the call
349 pub coins: Option<Amount>,
350 /// Fee
351 pub fee: Option<Amount>,
352}
353
354/// structure describing different possible targets of a read-only execution request
355#[derive(Debug, Clone)]
356pub enum ReadOnlyExecutionTarget {
357 /// Execute the main function of a bytecode
358 BytecodeExecution(Vec<u8>),
359
360 /// Execute a function call
361 FunctionCall {
362 /// Target address
363 target_addr: Address,
364 /// Target function
365 target_func: String,
366 /// Parameter to pass to the target function
367 parameter: Vec<u8>,
368 },
369}
370
371/// structure describing a read-only call
372#[derive(Debug, Clone)]
373pub struct ReadOnlyCallRequest {
374 /// Maximum gas to spend in the execution.
375 pub max_gas: u64,
376 /// Call stack to simulate, older caller first. Target should be last.
377 pub call_stack: Vec<ExecutionStackElement>,
378 /// Target address
379 pub target_addr: Address,
380 /// Target function
381 pub target_func: String,
382 /// Parameter to pass to the target function
383 pub parameter: String,
384 /// execution start state
385 ///
386 /// Whether to start execution from final or active state
387 pub is_final: bool,
388}
389
390/// Structure describing an element of the execution stack.
391/// Every time a function is called from bytecode,
392/// a new `ExecutionStackElement` is pushed at the top of the execution stack
393/// to represent the local execution context of the called function,
394/// instead of the caller's which should lie just below in the stack.
395#[derive(Debug, Clone)]
396pub struct ExecutionStackElement {
397 /// Called address
398 pub address: Address,
399 /// Coins transferred to the target address during the call
400 pub coins: Amount,
401 /// List of addresses owned by the current call, and on which the current call has write access.
402 /// This list should contain `ExecutionStackElement::address` in the sense that an address should have write access to itself.
403 /// This list should also contain all addresses created previously during the call
404 /// to allow write access on newly created addresses in order to set them up,
405 /// but only within the scope of the current stack element.
406 /// That way, only the current scope and neither its caller not the functions it calls gain this write access,
407 /// which is important for security.
408 /// Note that we use a vector instead of a pre-hashed set to ensure order determinism,
409 /// the performance hit of linear search remains minimal because `owned_addresses` will always contain very few elements.
410 pub owned_addresses: Vec<Address>,
411 /// Datastore (key value store) for `ExecuteSC` Operation
412 pub operation_datastore: Option<Datastore>,
413}