massa_models/
mapping_grpc.rs

1// Copyright (c) 2023 MASSA LABS <info@massa.net>
2
3use crate::amount::Amount;
4use crate::async_msg::{AsyncMessage, AsyncMessageTrigger, AsyncMessageUpdate};
5use crate::block::{Block, BlockGraphStatus, FilledBlock, SecureShareBlock};
6use crate::block_header::{BlockHeader, SecuredHeader};
7use crate::config::CompactConfig;
8use crate::denunciation::{Denunciation, DenunciationIndex};
9use crate::endorsement::{Endorsement, SecureShareEndorsement};
10use crate::error::ModelsError;
11use crate::operation::{Operation, OperationType, SecureShareOperation};
12use crate::output_event::{EventExecutionContext, SCOutputEvent};
13use crate::slot::{IndexedSlot, Slot};
14use crate::stats::{ConsensusStats, ExecutionStats, NetworkStats};
15use crate::types::SetOrKeep;
16use massa_proto_rs::massa::model::v1 as grpc_model;
17
18//TODO check error type
19/// Converts a gRPC `grpc_model::DenunciationIndex` into a DenunciationIndex
20pub fn to_denunciation_index(
21    value: grpc_model::DenunciationIndex,
22) -> Result<DenunciationIndex, ModelsError> {
23    match value
24        .entry
25        .ok_or_else(|| ModelsError::ErrorRaised("no denunciation_index found".to_string()))?
26    {
27        grpc_model::denunciation_index::Entry::BlockHeader(block_header) => {
28            Ok(DenunciationIndex::BlockHeader {
29                slot: block_header
30                    .slot
31                    .ok_or_else(|| ModelsError::ErrorRaised("no slot found".to_string()))?
32                    .into(),
33            })
34        }
35        grpc_model::denunciation_index::Entry::Endorsement(endorsement) => {
36            Ok(DenunciationIndex::Endorsement {
37                slot: endorsement
38                    .slot
39                    .ok_or_else(|| ModelsError::ErrorRaised("no slot found".to_string()))?
40                    .into(),
41                index: endorsement.index,
42            })
43        }
44    }
45}
46
47impl From<Amount> for grpc_model::NativeAmount {
48    fn from(value: Amount) -> Self {
49        let (mantissa, scale) = value.to_mantissa_scale();
50        grpc_model::NativeAmount { mantissa, scale }
51    }
52}
53
54impl From<Block> for grpc_model::Block {
55    fn from(value: Block) -> Self {
56        grpc_model::Block {
57            header: Some(value.header.into()),
58            operations: value
59                .operations
60                .into_iter()
61                .map(|operation| operation.to_string())
62                .collect(),
63        }
64    }
65}
66
67impl From<BlockGraphStatus> for i32 {
68    fn from(value: BlockGraphStatus) -> Self {
69        match value {
70            BlockGraphStatus::ActiveInBlockclique => {
71                grpc_model::BlockStatus::NonFinalBlockclique.into()
72            }
73            BlockGraphStatus::ActiveInAlternativeCliques => {
74                grpc_model::BlockStatus::NonFinalAlternateClique.into()
75            }
76            BlockGraphStatus::Final => grpc_model::BlockStatus::Final.into(),
77            BlockGraphStatus::Discarded => grpc_model::BlockStatus::Discarded.into(),
78            _ => grpc_model::BlockStatus::Unspecified.into(),
79        }
80    }
81}
82
83impl From<BlockHeader> for grpc_model::BlockHeader {
84    fn from(value: BlockHeader) -> Self {
85        let res = value.endorsements.into_iter().map(|e| e.into()).collect();
86
87        grpc_model::BlockHeader {
88            slot: Some(value.slot.into()),
89            parents: value
90                .parents
91                .into_iter()
92                .map(|parent| parent.to_string())
93                .collect(),
94            endorsements: res,
95            denunciations: value.denunciations.into_iter().map(|d| d.into()).collect(),
96            current_version: value.current_version,
97            announced_version: value.announced_version,
98            //TODO to be updated in Massa models
99            operations_hash: value.operation_merkle_root.to_string(),
100        }
101    }
102}
103
104impl From<FilledBlock> for grpc_model::FilledBlock {
105    fn from(value: FilledBlock) -> Self {
106        grpc_model::FilledBlock {
107            header: Some(value.header.into()),
108            operations: value
109                .operations
110                .into_iter()
111                .map(|tuple| grpc_model::FilledOperationEntry {
112                    operation_id: tuple.0.to_string(),
113                    operation: tuple.1.map(|op| op.into()),
114                })
115                .collect(),
116        }
117    }
118}
119
120impl From<SecureShareBlock> for grpc_model::SignedBlock {
121    fn from(value: SecureShareBlock) -> Self {
122        let serialized_size = value.serialized_size() as u64;
123        grpc_model::SignedBlock {
124            content: Some(value.content.into()),
125            signature: value.signature.to_string(),
126            content_creator_pub_key: value.content_creator_pub_key.to_string(),
127            content_creator_address: value.content_creator_address.to_string(),
128            secure_hash: value.id.to_string(),
129            serialized_size,
130        }
131    }
132}
133
134impl From<SecuredHeader> for grpc_model::SignedBlockHeader {
135    fn from(value: SecuredHeader) -> Self {
136        let serialized_size = value.serialized_size() as u64;
137        grpc_model::SignedBlockHeader {
138            content: Some(value.content.into()),
139            signature: value.signature.to_string(),
140            content_creator_pub_key: value.content_creator_pub_key.to_string(),
141            content_creator_address: value.content_creator_address.to_string(),
142            secure_hash: value.id.to_string(),
143            serialized_size,
144        }
145    }
146}
147
148impl From<Endorsement> for grpc_model::Endorsement {
149    fn from(value: Endorsement) -> Self {
150        grpc_model::Endorsement {
151            slot: Some(value.slot.into()),
152            index: value.index,
153            endorsed_block: value.endorsed_block.to_string(),
154        }
155    }
156}
157
158impl From<SecureShareEndorsement> for grpc_model::SignedEndorsement {
159    fn from(value: SecureShareEndorsement) -> Self {
160        let serialized_size = value.serialized_size() as u64;
161        grpc_model::SignedEndorsement {
162            content: Some(value.content.into()),
163            signature: value.signature.to_string(),
164            content_creator_pub_key: value.content_creator_pub_key.to_string(),
165            content_creator_address: value.content_creator_address.to_string(),
166            secure_hash: value.id.to_string(),
167            serialized_size,
168        }
169    }
170}
171
172impl From<OperationType> for grpc_model::OperationType {
173    fn from(operation_type: OperationType) -> grpc_model::OperationType {
174        let mut grpc_operation_type = grpc_model::OperationType::default();
175        match operation_type {
176            OperationType::Transaction {
177                recipient_address,
178                amount,
179            } => {
180                let transaction = grpc_model::Transaction {
181                    recipient_address: recipient_address.to_string(),
182                    amount: Some(amount.into()),
183                };
184                grpc_operation_type.r#type =
185                    Some(grpc_model::operation_type::Type::Transaction(transaction));
186            }
187            OperationType::RollBuy { roll_count } => {
188                let roll_buy = grpc_model::RollBuy { roll_count };
189                grpc_operation_type.r#type =
190                    Some(grpc_model::operation_type::Type::RollBuy(roll_buy));
191            }
192            OperationType::RollSell { roll_count } => {
193                let roll_sell = grpc_model::RollSell { roll_count };
194                grpc_operation_type.r#type =
195                    Some(grpc_model::operation_type::Type::RollSell(roll_sell));
196            }
197            OperationType::ExecuteSC {
198                data,
199                max_gas,
200                max_coins,
201                datastore,
202            } => {
203                let execute_sc = grpc_model::ExecuteSc {
204                    data,
205                    max_coins: max_coins.to_raw(),
206                    max_gas,
207                    datastore: datastore
208                        .into_iter()
209                        .map(|(key, value)| grpc_model::BytesMapFieldEntry { key, value })
210                        .collect(),
211                };
212                grpc_operation_type.r#type =
213                    Some(grpc_model::operation_type::Type::ExecuteSc(execute_sc));
214            }
215            OperationType::CallSC {
216                target_addr,
217                target_func,
218                param,
219                max_gas,
220                coins,
221            } => {
222                let call_sc = grpc_model::CallSc {
223                    target_address: target_addr.to_string(),
224                    target_function: target_func,
225                    parameter: param,
226                    max_gas,
227                    coins: Some(coins.into()),
228                };
229                grpc_operation_type.r#type =
230                    Some(grpc_model::operation_type::Type::CallSc(call_sc));
231            }
232        }
233
234        grpc_operation_type
235    }
236}
237
238impl From<Operation> for grpc_model::Operation {
239    fn from(op: Operation) -> Self {
240        grpc_model::Operation {
241            fee: Some(op.fee.into()),
242            expire_period: op.expire_period,
243            op: Some(op.op.into()),
244        }
245    }
246}
247
248impl From<OperationType> for grpc_model::OpType {
249    fn from(value: OperationType) -> Self {
250        match value {
251            OperationType::Transaction { .. } => grpc_model::OpType::Transaction,
252            OperationType::RollBuy { .. } => grpc_model::OpType::RollBuy,
253            OperationType::RollSell { .. } => grpc_model::OpType::RollSell,
254            OperationType::ExecuteSC { .. } => grpc_model::OpType::ExecuteSc,
255            OperationType::CallSC { .. } => grpc_model::OpType::CallSc,
256        }
257    }
258}
259
260impl From<SecureShareOperation> for grpc_model::SignedOperation {
261    fn from(value: SecureShareOperation) -> Self {
262        grpc_model::SignedOperation {
263            serialized_size: value.serialized_size() as u64,
264            content: Some(value.content.into()),
265            signature: value.signature.to_string(),
266            content_creator_pub_key: value.content_creator_pub_key.to_string(),
267            content_creator_address: value.content_creator_address.to_string(),
268            secure_hash: value.id.to_string(),
269        }
270    }
271}
272
273impl From<IndexedSlot> for grpc_model::IndexedSlot {
274    fn from(s: IndexedSlot) -> Self {
275        grpc_model::IndexedSlot {
276            index: s.index as u64,
277            slot: Some(s.slot.into()),
278        }
279    }
280}
281
282impl From<Slot> for grpc_model::Slot {
283    fn from(s: Slot) -> Self {
284        grpc_model::Slot {
285            period: s.period,
286            thread: s.thread as u32,
287        }
288    }
289}
290
291impl From<grpc_model::Slot> for Slot {
292    fn from(s: grpc_model::Slot) -> Self {
293        Slot {
294            period: s.period,
295            thread: s.thread as u8,
296        }
297    }
298}
299
300impl From<SCOutputEvent> for grpc_model::ScExecutionEvent {
301    fn from(value: SCOutputEvent) -> Self {
302        grpc_model::ScExecutionEvent {
303            context: Some(value.context.into()),
304            data: value.data.as_bytes().to_vec(),
305        }
306    }
307}
308
309impl From<EventExecutionContext> for grpc_model::ScExecutionEventContext {
310    fn from(value: EventExecutionContext) -> Self {
311        Self {
312            origin_slot: Some(value.slot.into()),
313            block_id: value.block.map(|id| id.to_string()),
314            index_in_slot: value.index_in_slot,
315            call_stack: value
316                .call_stack
317                .into_iter()
318                .map(|a| a.to_string())
319                .collect(),
320            origin_operation_id: value.origin_operation_id.map(|id| id.to_string()),
321            is_failure: value.is_error,
322            status: if value.read_only {
323                grpc_model::ScExecutionEventStatus::ReadOnly as i32
324            } else if value.is_final {
325                grpc_model::ScExecutionEventStatus::Final as i32
326            } else {
327                grpc_model::ScExecutionEventStatus::Unspecified as i32
328            },
329        }
330    }
331}
332
333impl From<DenunciationIndex> for grpc_model::DenunciationIndex {
334    fn from(value: DenunciationIndex) -> Self {
335        grpc_model::DenunciationIndex {
336            entry: Some(match value {
337                DenunciationIndex::BlockHeader { slot } => {
338                    grpc_model::denunciation_index::Entry::BlockHeader(
339                        grpc_model::DenunciationBlockHeader {
340                            slot: Some(slot.into()),
341                        },
342                    )
343                }
344                DenunciationIndex::Endorsement { slot, index } => {
345                    grpc_model::denunciation_index::Entry::Endorsement(
346                        grpc_model::DenunciationEndorsement {
347                            slot: Some(slot.into()),
348                            index,
349                        },
350                    )
351                }
352            }),
353        }
354    }
355}
356
357impl From<CompactConfig> for grpc_model::CompactConfig {
358    fn from(value: CompactConfig) -> Self {
359        grpc_model::CompactConfig {
360            genesis_timestamp: Some(value.genesis_timestamp.into()),
361            end_timestamp: value.end_timestamp.map(|time| time.into()),
362            thread_count: value.thread_count as u32,
363            t0: Some(value.t0.into()),
364            delta_f0: value.delta_f0,
365            operation_validity_periods: value.operation_validity_periods,
366            periods_per_cycle: value.periods_per_cycle,
367            block_reward: Some(value.block_reward.into()),
368            roll_price: Some(value.roll_price.into()),
369            max_block_size: value.max_block_size,
370        }
371    }
372}
373
374impl From<ConsensusStats> for grpc_model::ConsensusStats {
375    fn from(value: ConsensusStats) -> Self {
376        grpc_model::ConsensusStats {
377            start_timespan: Some(value.start_timespan.into()),
378            end_timespan: Some(value.end_timespan.into()),
379            final_block_count: value.final_block_count,
380            stale_block_count: value.stale_block_count,
381            clique_count: value.clique_count,
382        }
383    }
384}
385
386impl From<ExecutionStats> for grpc_model::ExecutionStats {
387    fn from(value: ExecutionStats) -> Self {
388        grpc_model::ExecutionStats {
389            time_window_start: Some(value.time_window_start.into()),
390            time_window_end: Some(value.time_window_end.into()),
391            final_block_count: value.final_block_count as u64,
392            final_executed_operations_count: value.final_executed_operations_count as u64,
393        }
394    }
395}
396
397impl From<NetworkStats> for grpc_model::NetworkStats {
398    fn from(value: NetworkStats) -> Self {
399        grpc_model::NetworkStats {
400            in_connection_count: value.in_connection_count,
401            out_connection_count: value.out_connection_count,
402            known_peer_count: value.known_peer_count,
403            banned_peer_count: value.banned_peer_count,
404            active_node_count: value.active_node_count,
405        }
406    }
407}
408
409impl From<Denunciation> for grpc_model::Denunciation {
410    fn from(value: Denunciation) -> Self {
411        match value {
412            Denunciation::Endorsement(de) => grpc_model::Denunciation {
413                entry: Some(grpc_model::denunciation::Entry::Endorsement(
414                    grpc_model::EndorsementDenunciation {
415                        public_key: de.get_public_key().to_string(),
416                        slot: Some((*de.get_slot()).into()),
417                        index: *de.get_index(),
418                        hash_1: de.get_hash_1().to_string(),
419                        hash_2: de.get_hash_2().to_string(),
420                        signature_1: de.get_signature_1().to_string(),
421                        signature_2: de.get_signature_2().to_string(),
422                    },
423                )),
424            },
425            Denunciation::BlockHeader(db) => grpc_model::Denunciation {
426                entry: Some(grpc_model::denunciation::Entry::BlockHeader(
427                    grpc_model::BlockHeaderDenunciation {
428                        public_key: db.get_public_key().to_string(),
429                        slot: Some((*db.get_slot()).into()),
430                        hash_1: db.get_hash_1().to_string(),
431                        hash_2: db.get_hash_2().to_string(),
432                        signature_1: db.get_signature_1().to_string(),
433                        signature_2: db.get_signature_2().to_string(),
434                    },
435                )),
436            },
437        }
438    }
439}
440
441impl From<AsyncMessage> for grpc_model::AsyncMessage {
442    fn from(value: AsyncMessage) -> Self {
443        grpc_model::AsyncMessage {
444            emission_slot: Some(value.emission_slot.into()),
445            emission_index: value.emission_index,
446            sender: value.sender.to_string(),
447            destination: value.destination.to_string(),
448            handler: value.function.to_string(),
449            max_gas: value.max_gas,
450            fee: Some(value.fee.into()),
451            coins: Some(value.coins.into()),
452            validity_start: Some(value.validity_start.into()),
453            validity_end: Some(value.validity_start.into()),
454            data: value.function_params,
455            trigger: value.trigger.map(|trigger| trigger.into()),
456            can_be_executed: value.can_be_executed,
457        }
458    }
459}
460
461//TODO to be checked, use functions
462impl From<AsyncMessageUpdate> for grpc_model::AsyncMessageUpdate {
463    fn from(value: AsyncMessageUpdate) -> Self {
464        grpc_model::AsyncMessageUpdate {
465            emission_slot: match value.emission_slot {
466                SetOrKeep::Set(value) => Some(grpc_model::SetOrKeepSlot {
467                    change: Some(grpc_model::set_or_keep_slot::Change::Set(value.into())),
468                }),
469                SetOrKeep::Keep => Some(grpc_model::SetOrKeepSlot {
470                    change: Some(grpc_model::set_or_keep_slot::Change::Keep(
471                        grpc_model::Empty {},
472                    )),
473                }),
474            },
475            emission_index: match value.emission_index {
476                SetOrKeep::Set(value) => Some(grpc_model::SetOrKeepUint64 {
477                    change: Some(grpc_model::set_or_keep_uint64::Change::Set(value)),
478                }),
479                SetOrKeep::Keep => Some(grpc_model::SetOrKeepUint64 {
480                    change: Some(grpc_model::set_or_keep_uint64::Change::Keep(
481                        grpc_model::Empty {},
482                    )),
483                }),
484            },
485            sender: match value.sender {
486                SetOrKeep::Set(value) => Some(grpc_model::SetOrKeepString {
487                    change: Some(grpc_model::set_or_keep_string::Change::Set(
488                        value.to_string(),
489                    )),
490                }),
491                SetOrKeep::Keep => Some(grpc_model::SetOrKeepString {
492                    change: Some(grpc_model::set_or_keep_string::Change::Keep(
493                        grpc_model::Empty {},
494                    )),
495                }),
496            },
497            destination: match value.destination {
498                SetOrKeep::Set(value) => Some(grpc_model::SetOrKeepString {
499                    change: Some(grpc_model::set_or_keep_string::Change::Set(
500                        value.to_string(),
501                    )),
502                }),
503                SetOrKeep::Keep => Some(grpc_model::SetOrKeepString {
504                    change: Some(grpc_model::set_or_keep_string::Change::Keep(
505                        grpc_model::Empty {},
506                    )),
507                }),
508            },
509            handler: match value.function {
510                SetOrKeep::Set(value) => Some(grpc_model::SetOrKeepString {
511                    change: Some(grpc_model::set_or_keep_string::Change::Set(value)),
512                }),
513                SetOrKeep::Keep => Some(grpc_model::SetOrKeepString {
514                    change: Some(grpc_model::set_or_keep_string::Change::Keep(
515                        grpc_model::Empty {},
516                    )),
517                }),
518            },
519            max_gas: match value.max_gas {
520                SetOrKeep::Set(value) => Some(grpc_model::SetOrKeepUint64 {
521                    change: Some(grpc_model::set_or_keep_uint64::Change::Set(value)),
522                }),
523                SetOrKeep::Keep => Some(grpc_model::SetOrKeepUint64 {
524                    change: Some(grpc_model::set_or_keep_uint64::Change::Keep(
525                        grpc_model::Empty {},
526                    )),
527                }),
528            },
529            //TODO check Amount usage
530            fee: match value.fee {
531                SetOrKeep::Set(value) => Some(grpc_model::SetOrKeepUint64 {
532                    change: Some(grpc_model::set_or_keep_uint64::Change::Set(value.to_raw())),
533                }),
534                SetOrKeep::Keep => Some(grpc_model::SetOrKeepUint64 {
535                    change: Some(grpc_model::set_or_keep_uint64::Change::Keep(
536                        grpc_model::Empty {},
537                    )),
538                }),
539            },
540            //TODO check Amount usage
541            coins: match value.coins {
542                SetOrKeep::Set(value) => Some(grpc_model::SetOrKeepUint64 {
543                    change: Some(grpc_model::set_or_keep_uint64::Change::Set(value.to_raw())),
544                }),
545                SetOrKeep::Keep => Some(grpc_model::SetOrKeepUint64 {
546                    change: Some(grpc_model::set_or_keep_uint64::Change::Keep(
547                        grpc_model::Empty {},
548                    )),
549                }),
550            },
551            validity_start: match value.validity_start {
552                SetOrKeep::Set(value) => Some(grpc_model::SetOrKeepSlot {
553                    change: Some(grpc_model::set_or_keep_slot::Change::Set(value.into())),
554                }),
555                SetOrKeep::Keep => Some(grpc_model::SetOrKeepSlot {
556                    change: Some(grpc_model::set_or_keep_slot::Change::Keep(
557                        grpc_model::Empty {},
558                    )),
559                }),
560            },
561            validity_end: match value.validity_end {
562                SetOrKeep::Set(value) => Some(grpc_model::SetOrKeepSlot {
563                    change: Some(grpc_model::set_or_keep_slot::Change::Set(value.into())),
564                }),
565                SetOrKeep::Keep => Some(grpc_model::SetOrKeepSlot {
566                    change: Some(grpc_model::set_or_keep_slot::Change::Keep(
567                        grpc_model::Empty {},
568                    )),
569                }),
570            },
571            data: match value.function_params {
572                SetOrKeep::Set(value) => Some(grpc_model::SetOrKeepBytes {
573                    change: Some(grpc_model::set_or_keep_bytes::Change::Set(value)),
574                }),
575                SetOrKeep::Keep => Some(grpc_model::SetOrKeepBytes {
576                    change: Some(grpc_model::set_or_keep_bytes::Change::Keep(
577                        grpc_model::Empty {},
578                    )),
579                }),
580            },
581            trigger: match value.trigger {
582                SetOrKeep::Set(value) => match value {
583                    None => Some(grpc_model::SetOrKeepAsyncMessageTrigger { change: None }),
584                    Some(trigger) => Some(grpc_model::SetOrKeepAsyncMessageTrigger {
585                        change: Some(grpc_model::set_or_keep_async_message_trigger::Change::Set(
586                            trigger.into(),
587                        )),
588                    }),
589                },
590                SetOrKeep::Keep => Some(grpc_model::SetOrKeepAsyncMessageTrigger {
591                    change: Some(grpc_model::set_or_keep_async_message_trigger::Change::Keep(
592                        grpc_model::Empty {},
593                    )),
594                }),
595            },
596            can_be_executed: match value.can_be_executed {
597                SetOrKeep::Set(value) => Some(grpc_model::SetOrKeepBool {
598                    change: Some(grpc_model::set_or_keep_bool::Change::Set(value)),
599                }),
600                SetOrKeep::Keep => Some(grpc_model::SetOrKeepBool {
601                    change: Some(grpc_model::set_or_keep_bool::Change::Keep(
602                        grpc_model::Empty {},
603                    )),
604                }),
605            },
606        }
607    }
608}
609
610impl From<AsyncMessageTrigger> for grpc_model::AsyncMessageTrigger {
611    fn from(value: AsyncMessageTrigger) -> Self {
612        grpc_model::AsyncMessageTrigger {
613            address: value.address.to_string(),
614            datastore_key: value.datastore_key,
615        }
616    }
617}