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 balance: Amount,
165 pub ownership: ChainOwnershipMetadata,
167 pub application_permissions: ApplicationPermissionsMetadata,
169}
170
171#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
173pub struct ChangeOwnershipOperationMetadata {
174 pub super_owners: Vec<AccountOwner>,
176 pub owners: Vec<OwnerWithWeight>,
178 pub first_leader: Option<AccountOwner>,
180 pub multi_leader_rounds: i32,
182 pub open_multi_leader_rounds: bool,
184 pub timeout_config: TimeoutConfigMetadata,
186}
187
188#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
190pub struct OwnerWithWeight {
191 pub owner: AccountOwner,
193 pub weight: String, }
196
197#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
199pub struct ChangeApplicationPermissionsMetadata {
200 pub permissions: ApplicationPermissionsMetadata,
202}
203
204#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
206pub struct AdminOperationMetadata {
207 pub admin_operation_type: String,
209 pub epoch: Option<i32>,
211 pub blob_hash: Option<CryptoHash>,
213}
214
215#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
217pub struct CreateApplicationOperationMetadata {
218 pub module_id: String,
220 pub parameters_hex: String,
222 pub instantiation_argument_hex: String,
224 pub required_application_ids: Vec<ApplicationId>,
226}
227
228#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
230pub struct PublishDataBlobMetadata {
231 pub blob_hash: CryptoHash,
233}
234
235#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
237pub struct VerifyBlobMetadata {
238 pub blob_id: String,
240}
241
242#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
244pub struct PublishModuleMetadata {
245 pub module_id: String,
247}
248
249#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
251pub struct UpdateStreamMetadata {
252 pub application_id: String,
254 pub chain_id: ChainId,
256 pub stream_id: String,
258 pub first_index: i32,
260 pub next_index: i32,
262}
263
264#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
266pub struct SystemMessageMetadata {
267 pub system_message_type: String,
269 pub credit: Option<CreditMessageMetadata>,
271 pub withdraw: Option<WithdrawMessageMetadata>,
273 pub checkpoint_ack: Option<CheckpointAckMessageMetadata>,
275}
276
277#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
279pub struct CreditMessageMetadata {
280 pub target: AccountOwner,
282 pub amount: Amount,
284 pub source: AccountOwner,
286}
287
288#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
290pub struct WithdrawMessageMetadata {
291 pub owner: AccountOwner,
293 pub amount: Amount,
295 pub recipient: Account,
297}
298
299#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
301pub struct CheckpointAckMessageMetadata {
302 pub latest_received_cursor: Cursor,
304}
305
306#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
308pub struct MessageMetadata {
309 pub message_type: String,
311 pub application_id: Option<ApplicationId>,
313 pub user_bytes_hex: Option<String>,
315 pub system_message: Option<SystemMessageMetadata>,
317}
318
319impl From<&SystemOperation> for SystemOperationMetadata {
320 fn from(sys_op: &SystemOperation) -> Self {
321 match sys_op {
322 SystemOperation::Transfer {
323 owner,
324 recipient,
325 amount,
326 } => SystemOperationMetadata {
327 transfer: Some(TransferOperationMetadata {
328 owner: *owner,
329 recipient: *recipient,
330 amount: *amount,
331 }),
332 ..SystemOperationMetadata::new("Transfer")
333 },
334 SystemOperation::Claim {
335 owner,
336 target_id,
337 recipient,
338 amount,
339 } => SystemOperationMetadata {
340 claim: Some(ClaimOperationMetadata {
341 owner: *owner,
342 target_id: *target_id,
343 recipient: *recipient,
344 amount: *amount,
345 }),
346 ..SystemOperationMetadata::new("Claim")
347 },
348 SystemOperation::OpenChain(config) => SystemOperationMetadata {
349 open_chain: Some(OpenChainOperationMetadata {
350 balance: config.balance,
351 ownership: ChainOwnershipMetadata::from(&config.ownership),
352 application_permissions: ApplicationPermissionsMetadata::from(
353 &config.application_permissions,
354 ),
355 }),
356 ..SystemOperationMetadata::new("OpenChain")
357 },
358 SystemOperation::CloseChain => SystemOperationMetadata::new("CloseChain"),
359 SystemOperation::ChangeOwnership {
360 super_owners,
361 owners,
362 first_leader,
363 multi_leader_rounds,
364 open_multi_leader_rounds,
365 timeout_config,
366 } => SystemOperationMetadata {
367 change_ownership: Some(ChangeOwnershipOperationMetadata {
368 super_owners: super_owners.clone(),
369 owners: owners
370 .iter()
371 .map(|(owner, weight)| OwnerWithWeight {
372 owner: *owner,
373 weight: weight.to_string(),
374 })
375 .collect(),
376 first_leader: *first_leader,
377 multi_leader_rounds: *multi_leader_rounds as i32,
378 open_multi_leader_rounds: *open_multi_leader_rounds,
379 timeout_config: TimeoutConfigMetadata::from(timeout_config),
380 }),
381 ..SystemOperationMetadata::new("ChangeOwnership")
382 },
383 SystemOperation::ChangeApplicationPermissions(permissions) => SystemOperationMetadata {
384 change_application_permissions: Some(ChangeApplicationPermissionsMetadata {
385 permissions: ApplicationPermissionsMetadata::from(permissions),
386 }),
387 ..SystemOperationMetadata::new("ChangeApplicationPermissions")
388 },
389 SystemOperation::Admin(admin_op) => SystemOperationMetadata {
390 admin: Some(AdminOperationMetadata::from(admin_op)),
391 ..SystemOperationMetadata::new("Admin")
392 },
393 SystemOperation::CreateApplication {
394 module_id,
395 parameters,
396 instantiation_argument,
397 required_application_ids,
398 } => SystemOperationMetadata {
399 create_application: Some(CreateApplicationOperationMetadata {
400 module_id: module_id.to_string(),
401 parameters_hex: hex::encode(parameters),
402 instantiation_argument_hex: hex::encode(instantiation_argument),
403 required_application_ids: required_application_ids.clone(),
404 }),
405 ..SystemOperationMetadata::new("CreateApplication")
406 },
407 SystemOperation::PublishDataBlob { blob_hash } => SystemOperationMetadata {
408 publish_data_blob: Some(PublishDataBlobMetadata {
409 blob_hash: *blob_hash,
410 }),
411 ..SystemOperationMetadata::new("PublishDataBlob")
412 },
413 SystemOperation::VerifyBlob { blob_id } => SystemOperationMetadata {
414 verify_blob: Some(VerifyBlobMetadata {
415 blob_id: blob_id.to_string(),
416 }),
417 ..SystemOperationMetadata::new("VerifyBlob")
418 },
419 SystemOperation::PublishModule { module_id } => SystemOperationMetadata {
420 publish_module: Some(PublishModuleMetadata {
421 module_id: module_id.to_string(),
422 }),
423 ..SystemOperationMetadata::new("PublishModule")
424 },
425 SystemOperation::ProcessNewEpoch(epoch) => SystemOperationMetadata {
426 epoch: Some(epoch.0 as i32),
427 ..SystemOperationMetadata::new("ProcessNewEpoch")
428 },
429 SystemOperation::UpdateStream {
430 application_id,
431 chain_id,
432 stream_id,
433 first_index,
434 next_index,
435 } => SystemOperationMetadata {
436 update_stream: Some(UpdateStreamMetadata {
437 application_id: application_id.to_string(),
438 chain_id: *chain_id,
439 stream_id: stream_id.to_string(),
440 first_index: *first_index as i32,
441 next_index: *next_index as i32,
442 }),
443 ..SystemOperationMetadata::new("UpdateStream")
444 },
445 SystemOperation::Checkpoint => SystemOperationMetadata::new("Checkpoint"),
446 }
447 }
448}
449
450impl From<&AdminOperation> for AdminOperationMetadata {
451 fn from(admin_op: &AdminOperation) -> Self {
452 match admin_op {
453 AdminOperation::PublishCommitteeBlob { blob_hash } => AdminOperationMetadata {
454 admin_operation_type: "PublishCommitteeBlob".to_string(),
455 epoch: None,
456 blob_hash: Some(*blob_hash),
457 },
458 AdminOperation::CreateCommittee { epoch, blob_hash } => AdminOperationMetadata {
459 admin_operation_type: "CreateCommittee".to_string(),
460 epoch: Some(epoch.0 as i32),
461 blob_hash: Some(*blob_hash),
462 },
463 AdminOperation::RemoveCommittee { epoch } => AdminOperationMetadata {
464 admin_operation_type: "RemoveCommittee".to_string(),
465 epoch: Some(epoch.0 as i32),
466 blob_hash: None,
467 },
468 }
469 }
470}
471
472impl From<&Message> for MessageMetadata {
473 fn from(message: &Message) -> Self {
474 match message {
475 Message::System(sys_msg) => MessageMetadata {
476 message_type: "System".to_string(),
477 application_id: None,
478 user_bytes_hex: None,
479 system_message: Some(SystemMessageMetadata::from(sys_msg)),
480 },
481 Message::User {
482 application_id,
483 bytes,
484 } => MessageMetadata {
485 message_type: "User".to_string(),
486 application_id: Some(*application_id),
487 user_bytes_hex: Some(hex::encode(bytes)),
488 system_message: None,
489 },
490 }
491 }
492}
493
494impl From<&SystemMessage> for SystemMessageMetadata {
495 fn from(sys_msg: &SystemMessage) -> Self {
496 match sys_msg {
497 SystemMessage::Credit {
498 target,
499 amount,
500 source,
501 } => SystemMessageMetadata {
502 system_message_type: "Credit".to_string(),
503 credit: Some(CreditMessageMetadata {
504 target: *target,
505 amount: *amount,
506 source: *source,
507 }),
508 withdraw: None,
509 checkpoint_ack: None,
510 },
511 SystemMessage::Withdraw {
512 owner,
513 amount,
514 recipient,
515 } => SystemMessageMetadata {
516 system_message_type: "Withdraw".to_string(),
517 credit: None,
518 withdraw: Some(WithdrawMessageMetadata {
519 owner: *owner,
520 amount: *amount,
521 recipient: *recipient,
522 }),
523 checkpoint_ack: None,
524 },
525 SystemMessage::CheckpointAck {
526 latest_received_cursor,
527 } => SystemMessageMetadata {
528 system_message_type: "CheckpointAck".to_string(),
529 credit: None,
530 withdraw: None,
531 checkpoint_ack: Some(CheckpointAckMessageMetadata {
532 latest_received_cursor: *latest_received_cursor,
533 }),
534 },
535 }
536 }
537}