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