massa_execution_exports/
execution_info.rs

1#![allow(dead_code)]
2
3use std::collections::HashMap;
4
5use massa_hash::Hash;
6use massa_models::async_msg_id::AsyncMessageId;
7use massa_models::block_id::BlockId;
8use massa_models::config::{GENESIS_TIMESTAMP, T0, THREAD_COUNT};
9use massa_models::deferred_calls::DeferredCallId;
10use massa_models::denunciation::DenunciationIndex;
11use massa_models::operation::OperationId;
12use massa_time::MassaTime;
13
14use massa_deferred_calls::DeferredCall;
15use massa_models::address::Address;
16use massa_models::amount::Amount;
17use massa_models::slot::Slot;
18use serde::Serialize;
19
20use crate::types_trace_info::ExecutionResult;
21
22/// Struct to store Roll related operation
23#[derive(Debug, Clone)]
24pub enum RollOperationInfo {
25    /// Roll buy amount
26    RollBuy(Address, u64),
27    /// Roll sell amount
28    RollSell(Address, u64),
29}
30
31#[derive(Debug, Clone, Serialize)]
32/// Transfer value struct
33pub enum TransferValue {
34    /// rolls
35    Rolls(u64),
36    /// amount of deferred credits
37    DeferredCredits(Amount),
38    /// amount of coins
39    Coins(Amount),
40}
41
42/// representation of a transfer
43#[derive(Clone, Debug, Serialize)]
44pub struct TransferInfo {
45    /// sender address
46    pub from: Option<Address>,
47    /// destination address
48    pub to: Option<Address>,
49    /// Transfer context
50    pub context: TransferContext,
51    /// Transfer id
52    pub id: Option<String>,
53    /// Transfer value
54    pub value: TransferValue,
55}
56
57impl TransferInfo {
58    /// Create a new TransferHistory structure
59    pub fn new(
60        value: TransferValue,
61        context: TransferContext,
62        from: Option<Address>,
63        to: Option<Address>,
64    ) -> Self {
65        Self {
66            from,
67            to,
68            context,
69            value,
70            id: None,
71        }
72    }
73}
74
75#[derive(Debug, Default, Clone, Serialize)]
76/// context for the transfer
77pub struct OriginTransferContext {
78    /// original operation id
79    pub operation_id: Option<OperationId>,
80    /// deferred call id
81    pub deferred_call_id: Option<DeferredCallId>,
82    /// async message id
83    pub async_message_id: Option<AsyncMessageId>,
84    /// async message id as string
85    pub async_message_id_str: Option<String>,
86    /// denunciation index
87    pub denunciation_index: Option<DenunciationIndex>,
88}
89
90#[allow(missing_docs)]
91#[derive(Debug, Clone, Serialize)]
92pub enum TransferContext {
93    TransactionCoins(OriginTransferContext),
94    AyncMsgCancel(OriginTransferContext),
95    DeferredCredits(OriginTransferContext),
96    DeferredCallFail(OriginTransferContext),
97    DeferredCallCancel(OriginTransferContext),
98    DeferredCallCoins(OriginTransferContext),
99    DeferredCallRegister(OriginTransferContext),
100    DeferredCallStorageRefund(OriginTransferContext),
101    OperationFee(OriginTransferContext),
102    RollBuy(OriginTransferContext),
103    RollSell(OriginTransferContext),
104    RollSlash,
105    CreateSCStorage,
106    DatastoreStorage,
107    CallSCCoins(OriginTransferContext),
108    AsyncMsgCoins(OriginTransferContext),
109    EndorsementCreatorReward,
110    EndorsementTargetReward,
111    BlockCreatorReward,
112    ReadOnlyBytecodeExecutionFee,
113    ReadOnlyFunctionCallFee,
114    ReadOnlyFunctionCallCoins,
115    SetBytecodeStorage,
116    AbiCallCoins,
117    AbiTransferCoins,
118    AbiTransferForCoins,
119    AbiSendMsgCoins,
120    AbiSendMsgFee,
121}
122
123/// Struct for execution info
124#[derive(Debug, Clone)]
125pub struct ExecutionInfoForSlot {
126    /// Slot
127    pub slot: Slot,
128    /// Timestamp
129    pub timestamp: MassaTime,
130    /// Reward for block producer
131    pub block_producer_reward: Option<(Address, Amount)>,
132    /// Rewards for endorsmement creators
133    pub endorsement_creator_rewards: HashMap<Address, Amount>,
134    /// Reward for endorsement target
135    pub endorsement_target_reward: Option<(Address, Amount)>,
136    /// Executed denunciation
137    pub denunciations: Vec<Result<DenunciationResult, String>>,
138    /// Executed Roll buy / sell
139    pub roll_operations: Vec<RollOperationInfo>,
140    /// Executed Async message
141    pub async_messages: Vec<Result<AsyncMessageExecutionResult, String>>,
142    /// Executed Deferred calls
143    pub deferred_calls_messages: Vec<Result<DeferredCallExecutionResult, String>>,
144    /// Deferred credits execution (empty if execution-info feature is NOT enabled)
145    pub deferred_credits_execution: Vec<(Address, Result<Amount, String>)>,
146    /// Cancel async message execution (empty if execution-info feature is NOT enabled)
147    pub cancel_async_message_execution: Vec<(Address, Result<Amount, String>)>,
148    /// Auto sell roll execution (empty if execution-info feature is NOT enabled)
149    pub auto_sell_execution: Vec<(Address, Amount)>,
150    /// execution trail hash
151    pub execution_trail_hash: Hash,
152    /// block id (empty if no block)
153    pub opt_block_id: Option<String>,
154    /// Transfers (empty if execution-info feature is NOT enabled)
155    pub transfers: Vec<TransferInfo>,
156}
157
158impl ExecutionInfoForSlot {
159    /// Create a new ExecutionInfoForSlot structure
160    pub fn new(slot: Slot, execution_trail_hash: Hash, block_id: Option<BlockId>) -> Self {
161        let timestamp = massa_models::timeslots::get_block_slot_timestamp(
162            THREAD_COUNT,
163            T0,
164            *GENESIS_TIMESTAMP,
165            slot,
166        )
167        .expect("Error getting timestamp for slot in ExecutionInfoForSlot");
168        Self {
169            slot,
170            timestamp,
171            block_producer_reward: None,
172            endorsement_creator_rewards: Default::default(),
173            endorsement_target_reward: None,
174            denunciations: Default::default(),
175            roll_operations: Default::default(),
176            async_messages: Default::default(),
177            deferred_calls_messages: Default::default(),
178            deferred_credits_execution: vec![],
179            cancel_async_message_execution: vec![],
180            auto_sell_execution: vec![],
181            opt_block_id: block_id.map(|b| b.to_string()),
182            transfers: vec![],
183            execution_trail_hash,
184        }
185    }
186
187    /// When the slot is finalized, we can build the transfer ids
188    pub fn build_transfer_list(&mut self) {
189        #[cfg(feature = "execution-info")]
190        {
191            use massa_models::async_msg_id::AsyncMessageIdSerializer;
192            use massa_serialization::Serializer;
193            use tracing::error;
194            let msg_id_serializer = AsyncMessageIdSerializer::new();
195            self.transfers
196                .iter_mut()
197                .enumerate()
198                .for_each(|(index, transfer)| {
199                    let id = format!("{}:{}", self.execution_trail_hash, index);
200                    transfer.id = Some(id);
201
202                    // serialize the msg_id if it exists
203                    match &transfer.context {
204                        TransferContext::AsyncMsgCoins(ctx)
205                        | TransferContext::AyncMsgCancel(ctx) => {
206                            if let Some(id) = ctx.async_message_id {
207                                let mut buf = Vec::new();
208                                let str_opt: Option<String> =
209                                    match msg_id_serializer.serialize(&id, &mut buf) {
210                                        Ok(_) => String::from_utf8(buf).ok(),
211                                        Err(er) => {
212                                            error!("Error serializing async_msg_id: {:?}", er);
213                                            None
214                                        }
215                                    };
216                                transfer.context = match transfer.context {
217                                    TransferContext::AsyncMsgCoins(_) => {
218                                        TransferContext::AsyncMsgCoins(OriginTransferContext {
219                                            async_message_id_str: str_opt,
220                                            ..Default::default()
221                                        })
222                                    }
223                                    TransferContext::AyncMsgCancel(_) => {
224                                        TransferContext::AyncMsgCancel(OriginTransferContext {
225                                            async_message_id_str: str_opt,
226                                            ..Default::default()
227                                        })
228                                    }
229                                    // not reachable
230                                    _ => transfer.context.clone(),
231                                };
232                            }
233                        }
234                        _ => {}
235                    }
236                });
237        }
238    }
239}
240
241/// structure describing the output of a denunciation execution
242#[derive(Debug, Clone)]
243pub struct DenunciationResult {
244    /// Target address of the denunciation
245    pub address_denounced: Address,
246    /// Denunciation slot
247    pub slot: Slot,
248    /// Amount slashed if successfully executed
249    pub slashed: Amount,
250}
251
252/// An async message execution result
253#[derive(Debug, Clone)]
254pub struct AsyncMessageExecutionResult {
255    /// Execution success or not
256    pub success: bool,
257    /// Sender address
258    pub sender: Option<Address>,
259    /// Destination address
260    pub destination: Option<Address>,
261    /// Amount
262    pub coins: Option<Amount>,
263    /// Traces
264    pub traces: Option<ExecutionResult>,
265}
266
267impl AsyncMessageExecutionResult {
268    /// Create a new AsyncMessageExecutionResult structure
269    pub fn new() -> Self {
270        Self {
271            success: false,
272            sender: None,
273            destination: None,
274            coins: None,
275            traces: None,
276        }
277    }
278}
279
280impl Default for AsyncMessageExecutionResult {
281    fn default() -> Self {
282        Self::new()
283    }
284}
285
286/// Deferred call execution result
287#[derive(Debug, Clone)]
288pub struct DeferredCallExecutionResult {
289    /// Execution success or not
290    pub success: bool,
291    /// sender address
292    pub sender: Address,
293    /// target address
294    pub target_address: Address,
295    pub(crate) target_function: String,
296    /// coins
297    pub coins: Amount,
298    /// fee
299    pub fee: Amount,
300    /// traces
301    pub traces: Option<ExecutionResult>,
302}
303
304impl DeferredCallExecutionResult {
305    /// Create a new DeferredCallExecutionResult structure
306    pub fn new(call: &DeferredCall) -> Self {
307        Self {
308            success: false,
309            sender: call.sender_address,
310            target_address: call.target_address,
311            target_function: call.target_function.clone(),
312            coins: call.coins,
313            fee: call.fee,
314            traces: None,
315        }
316    }
317}