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,
140 pub recipient: Account,
141 pub amount: Amount,
142}
143
144#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
146pub struct ClaimOperationMetadata {
147 pub owner: AccountOwner,
148 pub target_id: ChainId,
149 pub recipient: Account,
150 pub amount: Amount,
151}
152
153#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
155pub struct OpenChainOperationMetadata {
156 pub balance: Amount,
157 pub ownership: ChainOwnershipMetadata,
158 pub application_permissions: ApplicationPermissionsMetadata,
159}
160
161#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
163pub struct ChangeOwnershipOperationMetadata {
164 pub super_owners: Vec<AccountOwner>,
165 pub owners: Vec<OwnerWithWeight>,
166 pub first_leader: Option<AccountOwner>,
167 pub multi_leader_rounds: i32,
168 pub open_multi_leader_rounds: bool,
169 pub timeout_config: TimeoutConfigMetadata,
170}
171
172#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
174pub struct OwnerWithWeight {
175 pub owner: AccountOwner,
176 pub weight: String, }
178
179#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
181pub struct ChangeApplicationPermissionsMetadata {
182 pub permissions: ApplicationPermissionsMetadata,
183}
184
185#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
187pub struct AdminOperationMetadata {
188 pub admin_operation_type: String,
189 pub epoch: Option<i32>,
190 pub blob_hash: Option<CryptoHash>,
191}
192
193#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
195pub struct CreateApplicationOperationMetadata {
196 pub module_id: String,
197 pub parameters_hex: String,
198 pub instantiation_argument_hex: String,
199 pub required_application_ids: Vec<ApplicationId>,
200}
201
202#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
204pub struct PublishDataBlobMetadata {
205 pub blob_hash: CryptoHash,
206}
207
208#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
210pub struct VerifyBlobMetadata {
211 pub blob_id: String,
212}
213
214#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
216pub struct PublishModuleMetadata {
217 pub module_id: String,
218}
219
220#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
222pub struct UpdateStreamMetadata {
223 pub application_id: String,
224 pub chain_id: ChainId,
225 pub stream_id: String,
226 pub next_index: i32,
227}
228
229#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
231pub struct SystemMessageMetadata {
232 pub system_message_type: String,
234 pub credit: Option<CreditMessageMetadata>,
236 pub withdraw: Option<WithdrawMessageMetadata>,
238 pub checkpoint_ack: Option<CheckpointAckMessageMetadata>,
240}
241
242#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
244pub struct CreditMessageMetadata {
245 pub target: AccountOwner,
246 pub amount: Amount,
247 pub source: AccountOwner,
248}
249
250#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
252pub struct WithdrawMessageMetadata {
253 pub owner: AccountOwner,
254 pub amount: Amount,
255 pub recipient: Account,
256}
257
258#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
260pub struct CheckpointAckMessageMetadata {
261 pub latest_received_cursor: Cursor,
262}
263
264#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
266pub struct MessageMetadata {
267 pub message_type: String,
269 pub application_id: Option<ApplicationId>,
271 pub user_bytes_hex: Option<String>,
273 pub system_message: Option<SystemMessageMetadata>,
275}
276
277impl From<&SystemOperation> for SystemOperationMetadata {
278 fn from(sys_op: &SystemOperation) -> Self {
279 match sys_op {
280 SystemOperation::Transfer {
281 owner,
282 recipient,
283 amount,
284 } => SystemOperationMetadata {
285 transfer: Some(TransferOperationMetadata {
286 owner: *owner,
287 recipient: *recipient,
288 amount: *amount,
289 }),
290 ..SystemOperationMetadata::new("Transfer")
291 },
292 SystemOperation::Claim {
293 owner,
294 target_id,
295 recipient,
296 amount,
297 } => SystemOperationMetadata {
298 claim: Some(ClaimOperationMetadata {
299 owner: *owner,
300 target_id: *target_id,
301 recipient: *recipient,
302 amount: *amount,
303 }),
304 ..SystemOperationMetadata::new("Claim")
305 },
306 SystemOperation::OpenChain(config) => SystemOperationMetadata {
307 open_chain: Some(OpenChainOperationMetadata {
308 balance: config.balance,
309 ownership: ChainOwnershipMetadata::from(&config.ownership),
310 application_permissions: ApplicationPermissionsMetadata::from(
311 &config.application_permissions,
312 ),
313 }),
314 ..SystemOperationMetadata::new("OpenChain")
315 },
316 SystemOperation::CloseChain => SystemOperationMetadata::new("CloseChain"),
317 SystemOperation::ChangeOwnership {
318 super_owners,
319 owners,
320 first_leader,
321 multi_leader_rounds,
322 open_multi_leader_rounds,
323 timeout_config,
324 } => SystemOperationMetadata {
325 change_ownership: Some(ChangeOwnershipOperationMetadata {
326 super_owners: super_owners.clone(),
327 owners: owners
328 .iter()
329 .map(|(owner, weight)| OwnerWithWeight {
330 owner: *owner,
331 weight: weight.to_string(),
332 })
333 .collect(),
334 first_leader: *first_leader,
335 multi_leader_rounds: *multi_leader_rounds as i32,
336 open_multi_leader_rounds: *open_multi_leader_rounds,
337 timeout_config: TimeoutConfigMetadata::from(timeout_config),
338 }),
339 ..SystemOperationMetadata::new("ChangeOwnership")
340 },
341 SystemOperation::ChangeApplicationPermissions(permissions) => SystemOperationMetadata {
342 change_application_permissions: Some(ChangeApplicationPermissionsMetadata {
343 permissions: ApplicationPermissionsMetadata::from(permissions),
344 }),
345 ..SystemOperationMetadata::new("ChangeApplicationPermissions")
346 },
347 SystemOperation::Admin(admin_op) => SystemOperationMetadata {
348 admin: Some(AdminOperationMetadata::from(admin_op)),
349 ..SystemOperationMetadata::new("Admin")
350 },
351 SystemOperation::CreateApplication {
352 module_id,
353 parameters,
354 instantiation_argument,
355 required_application_ids,
356 } => SystemOperationMetadata {
357 create_application: Some(CreateApplicationOperationMetadata {
358 module_id: module_id.to_string(),
359 parameters_hex: hex::encode(parameters),
360 instantiation_argument_hex: hex::encode(instantiation_argument),
361 required_application_ids: required_application_ids.clone(),
362 }),
363 ..SystemOperationMetadata::new("CreateApplication")
364 },
365 SystemOperation::PublishDataBlob { blob_hash } => SystemOperationMetadata {
366 publish_data_blob: Some(PublishDataBlobMetadata {
367 blob_hash: *blob_hash,
368 }),
369 ..SystemOperationMetadata::new("PublishDataBlob")
370 },
371 SystemOperation::VerifyBlob { blob_id } => SystemOperationMetadata {
372 verify_blob: Some(VerifyBlobMetadata {
373 blob_id: blob_id.to_string(),
374 }),
375 ..SystemOperationMetadata::new("VerifyBlob")
376 },
377 SystemOperation::PublishModule { module_id } => SystemOperationMetadata {
378 publish_module: Some(PublishModuleMetadata {
379 module_id: module_id.to_string(),
380 }),
381 ..SystemOperationMetadata::new("PublishModule")
382 },
383 SystemOperation::ProcessNewEpoch(epoch) => SystemOperationMetadata {
384 epoch: Some(epoch.0 as i32),
385 ..SystemOperationMetadata::new("ProcessNewEpoch")
386 },
387 SystemOperation::UpdateStream {
388 application_id,
389 chain_id,
390 stream_id,
391 next_index,
392 } => SystemOperationMetadata {
393 update_stream: Some(UpdateStreamMetadata {
394 application_id: application_id.to_string(),
395 chain_id: *chain_id,
396 stream_id: stream_id.to_string(),
397 next_index: *next_index as i32,
398 }),
399 ..SystemOperationMetadata::new("UpdateStream")
400 },
401 SystemOperation::Checkpoint => SystemOperationMetadata::new("Checkpoint"),
402 }
403 }
404}
405
406impl From<&AdminOperation> for AdminOperationMetadata {
407 fn from(admin_op: &AdminOperation) -> Self {
408 match admin_op {
409 AdminOperation::PublishCommitteeBlob { blob_hash } => AdminOperationMetadata {
410 admin_operation_type: "PublishCommitteeBlob".to_string(),
411 epoch: None,
412 blob_hash: Some(*blob_hash),
413 },
414 AdminOperation::CreateCommittee { epoch, blob_hash } => AdminOperationMetadata {
415 admin_operation_type: "CreateCommittee".to_string(),
416 epoch: Some(epoch.0 as i32),
417 blob_hash: Some(*blob_hash),
418 },
419 AdminOperation::RemoveCommittee { epoch } => AdminOperationMetadata {
420 admin_operation_type: "RemoveCommittee".to_string(),
421 epoch: Some(epoch.0 as i32),
422 blob_hash: None,
423 },
424 }
425 }
426}
427
428impl From<&Message> for MessageMetadata {
429 fn from(message: &Message) -> Self {
430 match message {
431 Message::System(sys_msg) => MessageMetadata {
432 message_type: "System".to_string(),
433 application_id: None,
434 user_bytes_hex: None,
435 system_message: Some(SystemMessageMetadata::from(sys_msg)),
436 },
437 Message::User {
438 application_id,
439 bytes,
440 } => MessageMetadata {
441 message_type: "User".to_string(),
442 application_id: Some(*application_id),
443 user_bytes_hex: Some(hex::encode(bytes)),
444 system_message: None,
445 },
446 }
447 }
448}
449
450impl From<&SystemMessage> for SystemMessageMetadata {
451 fn from(sys_msg: &SystemMessage) -> Self {
452 match sys_msg {
453 SystemMessage::Credit {
454 target,
455 amount,
456 source,
457 } => SystemMessageMetadata {
458 system_message_type: "Credit".to_string(),
459 credit: Some(CreditMessageMetadata {
460 target: *target,
461 amount: *amount,
462 source: *source,
463 }),
464 withdraw: None,
465 checkpoint_ack: None,
466 },
467 SystemMessage::Withdraw {
468 owner,
469 amount,
470 recipient,
471 } => SystemMessageMetadata {
472 system_message_type: "Withdraw".to_string(),
473 credit: None,
474 withdraw: Some(WithdrawMessageMetadata {
475 owner: *owner,
476 amount: *amount,
477 recipient: *recipient,
478 }),
479 checkpoint_ack: None,
480 },
481 SystemMessage::CheckpointAck {
482 latest_received_cursor,
483 } => SystemMessageMetadata {
484 system_message_type: "CheckpointAck".to_string(),
485 credit: None,
486 withdraw: None,
487 checkpoint_ack: Some(CheckpointAckMessageMetadata {
488 latest_received_cursor: *latest_received_cursor,
489 }),
490 },
491 }
492 }
493}