1use 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
18pub 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 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
461impl 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 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 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}