1#![allow(clippy::cast_possible_wrap)]
9
10use async_graphql::SimpleObject;
11use linera_base::{
12 crypto::CryptoHash,
13 data_types::{Amount, ApplicationPermissions, Cursor},
14 hex,
15 identifiers::{Account, AccountOwner, ApplicationId, ChainId},
16 ownership::{ChainOwnership, TimeoutConfig},
17};
18use linera_execution::{system::AdminOperation, Message, SystemMessage, SystemOperation};
19use serde::{Deserialize, Serialize};
20
21#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
23pub struct TimeoutConfigMetadata {
24 pub fast_round_ms: Option<String>,
26 pub base_timeout_ms: String,
28 pub timeout_increment_ms: String,
30 pub fallback_duration_ms: String,
33}
34
35impl From<&TimeoutConfig> for TimeoutConfigMetadata {
36 fn from(config: &TimeoutConfig) -> Self {
37 TimeoutConfigMetadata {
38 fast_round_ms: config
39 .fast_round_duration
40 .map(|d| (d.as_micros() / 1000).to_string()),
41 base_timeout_ms: (config.base_timeout.as_micros() / 1000).to_string(),
42 timeout_increment_ms: (config.timeout_increment.as_micros() / 1000).to_string(),
43 fallback_duration_ms: (config.fallback_duration.as_micros() / 1000).to_string(),
44 }
45 }
46}
47
48#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
50pub struct ChainOwnershipMetadata {
51 pub ownership_json: String,
53}
54
55impl From<&ChainOwnership> for ChainOwnershipMetadata {
56 fn from(ownership: &ChainOwnership) -> Self {
57 ChainOwnershipMetadata {
58 ownership_json: serde_json::to_string(ownership)
61 .unwrap_or_else(|_| format!("{ownership:?}")),
62 }
63 }
64}
65
66#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
68pub struct ApplicationPermissionsMetadata {
69 pub permissions_json: String,
71}
72
73impl From<&ApplicationPermissions> for ApplicationPermissionsMetadata {
74 fn from(permissions: &ApplicationPermissions) -> Self {
75 ApplicationPermissionsMetadata {
76 permissions_json: serde_json::to_string(permissions)
79 .unwrap_or_else(|_| format!("{permissions:?}")),
80 }
81 }
82}
83
84#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
86pub struct SystemOperationMetadata {
87 pub system_operation_type: String,
89 pub transfer: Option<TransferOperationMetadata>,
91 pub claim: Option<ClaimOperationMetadata>,
93 pub open_chain: Option<OpenChainOperationMetadata>,
95 pub change_ownership: Option<ChangeOwnershipOperationMetadata>,
97 pub change_application_permissions: Option<ChangeApplicationPermissionsMetadata>,
99 pub admin: Option<AdminOperationMetadata>,
101 pub create_application: Option<CreateApplicationOperationMetadata>,
103 pub publish_data_blob: Option<PublishDataBlobMetadata>,
105 pub verify_blob: Option<VerifyBlobMetadata>,
107 pub publish_module: Option<PublishModuleMetadata>,
109 pub epoch: Option<i32>,
111 pub update_stream: Option<UpdateStreamMetadata>,
113}
114
115impl SystemOperationMetadata {
116 fn new(system_operation_type: &str) -> Self {
118 SystemOperationMetadata {
119 system_operation_type: system_operation_type.to_string(),
120 transfer: None,
121 claim: None,
122 open_chain: None,
123 change_ownership: None,
124 change_application_permissions: None,
125 admin: None,
126 create_application: None,
127 publish_data_blob: None,
128 verify_blob: None,
129 publish_module: None,
130 epoch: None,
131 update_stream: None,
132 }
133 }
134}
135
136#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
138pub struct TransferOperationMetadata {
139 pub owner: AccountOwner,
141 pub recipient: Account,
143 pub amount: Amount,
145}
146
147#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
149pub struct ClaimOperationMetadata {
150 pub owner: AccountOwner,
152 pub target_id: ChainId,
154 pub recipient: Account,
156 pub amount: Amount,
158}
159
160#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
162pub struct OpenChainOperationMetadata {
163 pub account: AccountOwner,
165 pub balance: Amount,
167 pub ownership: ChainOwnershipMetadata,
169 pub application_permissions: ApplicationPermissionsMetadata,
171}
172
173#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
175pub struct ChangeOwnershipOperationMetadata {
176 pub super_owners: Vec<AccountOwner>,
178 pub owners: Vec<OwnerWithWeight>,
180 pub first_leader: Option<AccountOwner>,
182 pub multi_leader_rounds: i32,
184 pub open_multi_leader_rounds: bool,
186 pub timeout_config: TimeoutConfigMetadata,
188}
189
190#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
192pub struct OwnerWithWeight {
193 pub owner: AccountOwner,
195 pub weight: String, }
198
199#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
201pub struct ChangeApplicationPermissionsMetadata {
202 pub permissions: ApplicationPermissionsMetadata,
204}
205
206#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
208pub struct AdminOperationMetadata {
209 pub admin_operation_type: String,
211 pub epoch: Option<i32>,
213 pub blob_hash: Option<CryptoHash>,
215}
216
217#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
219pub struct CreateApplicationOperationMetadata {
220 pub module_id: String,
222 pub parameters_hex: String,
224 pub instantiation_argument_hex: String,
226 pub required_application_ids: Vec<ApplicationId>,
228}
229
230#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
232pub struct PublishDataBlobMetadata {
233 pub blob_hash: CryptoHash,
235}
236
237#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
239pub struct VerifyBlobMetadata {
240 pub blob_id: String,
242}
243
244#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
246pub struct PublishModuleMetadata {
247 pub module_id: String,
249}
250
251#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
253pub struct UpdateStreamMetadata {
254 pub application_id: String,
256 pub chain_id: ChainId,
258 pub stream_id: String,
260 pub first_index: i32,
262 pub next_index: i32,
264}
265
266#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
268pub struct SystemMessageMetadata {
269 pub system_message_type: String,
271 pub credit: Option<CreditMessageMetadata>,
273 pub withdraw: Option<WithdrawMessageMetadata>,
275 pub checkpoint_ack: Option<CheckpointAckMessageMetadata>,
277}
278
279#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
281pub struct CreditMessageMetadata {
282 pub target: AccountOwner,
284 pub amount: Amount,
286 pub source: AccountOwner,
288}
289
290#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
292pub struct WithdrawMessageMetadata {
293 pub owner: AccountOwner,
295 pub amount: Amount,
297 pub recipient: Account,
299}
300
301#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
303pub struct CheckpointAckMessageMetadata {
304 pub latest_received_cursor: Cursor,
306}
307
308#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
310pub struct MessageMetadata {
311 pub message_type: String,
313 pub application_id: Option<ApplicationId>,
315 pub user_bytes_hex: Option<String>,
317 pub system_message: Option<SystemMessageMetadata>,
319}
320
321impl From<&SystemOperation> for SystemOperationMetadata {
322 fn from(sys_op: &SystemOperation) -> Self {
323 match sys_op {
324 SystemOperation::Transfer {
325 owner,
326 recipient,
327 amount,
328 } => SystemOperationMetadata {
329 transfer: Some(TransferOperationMetadata {
330 owner: *owner,
331 recipient: *recipient,
332 amount: *amount,
333 }),
334 ..SystemOperationMetadata::new("Transfer")
335 },
336 SystemOperation::Claim {
337 owner,
338 target_id,
339 recipient,
340 amount,
341 } => SystemOperationMetadata {
342 claim: Some(ClaimOperationMetadata {
343 owner: *owner,
344 target_id: *target_id,
345 recipient: *recipient,
346 amount: *amount,
347 }),
348 ..SystemOperationMetadata::new("Claim")
349 },
350 SystemOperation::OpenChain(config) => SystemOperationMetadata {
351 open_chain: Some(OpenChainOperationMetadata {
352 account: config.account,
353 balance: config.balance,
354 ownership: ChainOwnershipMetadata::from(&config.ownership),
355 application_permissions: ApplicationPermissionsMetadata::from(
356 &config.application_permissions,
357 ),
358 }),
359 ..SystemOperationMetadata::new("OpenChain")
360 },
361 SystemOperation::CloseChain => SystemOperationMetadata::new("CloseChain"),
362 SystemOperation::ChangeOwnership {
363 super_owners,
364 owners,
365 first_leader,
366 multi_leader_rounds,
367 open_multi_leader_rounds,
368 timeout_config,
369 } => SystemOperationMetadata {
370 change_ownership: Some(ChangeOwnershipOperationMetadata {
371 super_owners: super_owners.clone(),
372 owners: owners
373 .iter()
374 .map(|(owner, weight)| OwnerWithWeight {
375 owner: *owner,
376 weight: weight.to_string(),
377 })
378 .collect(),
379 first_leader: *first_leader,
380 multi_leader_rounds: *multi_leader_rounds as i32,
381 open_multi_leader_rounds: *open_multi_leader_rounds,
382 timeout_config: TimeoutConfigMetadata::from(timeout_config),
383 }),
384 ..SystemOperationMetadata::new("ChangeOwnership")
385 },
386 SystemOperation::ChangeApplicationPermissions(permissions) => SystemOperationMetadata {
387 change_application_permissions: Some(ChangeApplicationPermissionsMetadata {
388 permissions: ApplicationPermissionsMetadata::from(permissions),
389 }),
390 ..SystemOperationMetadata::new("ChangeApplicationPermissions")
391 },
392 SystemOperation::Admin(admin_op) => SystemOperationMetadata {
393 admin: Some(AdminOperationMetadata::from(admin_op)),
394 ..SystemOperationMetadata::new("Admin")
395 },
396 SystemOperation::CreateApplication {
397 module_id,
398 parameters,
399 instantiation_argument,
400 required_application_ids,
401 } => SystemOperationMetadata {
402 create_application: Some(CreateApplicationOperationMetadata {
403 module_id: module_id.to_string(),
404 parameters_hex: hex::encode(parameters),
405 instantiation_argument_hex: hex::encode(instantiation_argument),
406 required_application_ids: required_application_ids.clone(),
407 }),
408 ..SystemOperationMetadata::new("CreateApplication")
409 },
410 SystemOperation::PublishDataBlob { blob_hash } => SystemOperationMetadata {
411 publish_data_blob: Some(PublishDataBlobMetadata {
412 blob_hash: *blob_hash,
413 }),
414 ..SystemOperationMetadata::new("PublishDataBlob")
415 },
416 SystemOperation::VerifyBlob { blob_id } => SystemOperationMetadata {
417 verify_blob: Some(VerifyBlobMetadata {
418 blob_id: blob_id.to_string(),
419 }),
420 ..SystemOperationMetadata::new("VerifyBlob")
421 },
422 SystemOperation::PublishModule { module_id } => SystemOperationMetadata {
423 publish_module: Some(PublishModuleMetadata {
424 module_id: module_id.to_string(),
425 }),
426 ..SystemOperationMetadata::new("PublishModule")
427 },
428 SystemOperation::ProcessNewEpoch(epoch) => SystemOperationMetadata {
429 epoch: Some(epoch.0 as i32),
430 ..SystemOperationMetadata::new("ProcessNewEpoch")
431 },
432 SystemOperation::UpdateStream {
433 application_id,
434 chain_id,
435 stream_id,
436 first_index,
437 next_index,
438 } => SystemOperationMetadata {
439 update_stream: Some(UpdateStreamMetadata {
440 application_id: application_id.to_string(),
441 chain_id: *chain_id,
442 stream_id: stream_id.to_string(),
443 first_index: *first_index as i32,
444 next_index: *next_index as i32,
445 }),
446 ..SystemOperationMetadata::new("UpdateStream")
447 },
448 SystemOperation::Checkpoint => SystemOperationMetadata::new("Checkpoint"),
449 }
450 }
451}
452
453impl From<&AdminOperation> for AdminOperationMetadata {
454 fn from(admin_op: &AdminOperation) -> Self {
455 match admin_op {
456 AdminOperation::PublishCommitteeBlob { blob_hash } => AdminOperationMetadata {
457 admin_operation_type: "PublishCommitteeBlob".to_string(),
458 epoch: None,
459 blob_hash: Some(*blob_hash),
460 },
461 AdminOperation::CreateCommittee { epoch, blob_hash } => AdminOperationMetadata {
462 admin_operation_type: "CreateCommittee".to_string(),
463 epoch: Some(epoch.0 as i32),
464 blob_hash: Some(*blob_hash),
465 },
466 AdminOperation::RemoveCommittee { epoch } => AdminOperationMetadata {
467 admin_operation_type: "RemoveCommittee".to_string(),
468 epoch: Some(epoch.0 as i32),
469 blob_hash: None,
470 },
471 }
472 }
473}
474
475impl From<&Message> for MessageMetadata {
476 fn from(message: &Message) -> Self {
477 match message {
478 Message::System(sys_msg) => MessageMetadata {
479 message_type: "System".to_string(),
480 application_id: None,
481 user_bytes_hex: None,
482 system_message: Some(SystemMessageMetadata::from(sys_msg)),
483 },
484 Message::User {
485 application_id,
486 bytes,
487 } => MessageMetadata {
488 message_type: "User".to_string(),
489 application_id: Some(*application_id),
490 user_bytes_hex: Some(hex::encode(bytes)),
491 system_message: None,
492 },
493 }
494 }
495}
496
497impl From<&SystemMessage> for SystemMessageMetadata {
498 fn from(sys_msg: &SystemMessage) -> Self {
499 match sys_msg {
500 SystemMessage::Credit {
501 target,
502 amount,
503 source,
504 } => SystemMessageMetadata {
505 system_message_type: "Credit".to_string(),
506 credit: Some(CreditMessageMetadata {
507 target: *target,
508 amount: *amount,
509 source: *source,
510 }),
511 withdraw: None,
512 checkpoint_ack: None,
513 },
514 SystemMessage::Withdraw {
515 owner,
516 amount,
517 recipient,
518 } => SystemMessageMetadata {
519 system_message_type: "Withdraw".to_string(),
520 credit: None,
521 withdraw: Some(WithdrawMessageMetadata {
522 owner: *owner,
523 amount: *amount,
524 recipient: *recipient,
525 }),
526 checkpoint_ack: None,
527 },
528 SystemMessage::CheckpointAck {
529 latest_received_cursor,
530 } => SystemMessageMetadata {
531 system_message_type: "CheckpointAck".to_string(),
532 credit: None,
533 withdraw: None,
534 checkpoint_ack: Some(CheckpointAckMessageMetadata {
535 latest_received_cursor: *latest_received_cursor,
536 }),
537 },
538 }
539 }
540}