1use async_graphql::SimpleObject;
7use linera_base::{
8 crypto::CryptoHash,
9 data_types::{Amount, ApplicationPermissions},
10 hex,
11 identifiers::{Account, AccountOwner, ApplicationId, ChainId},
12 ownership::{ChainOwnership, TimeoutConfig},
13};
14use linera_execution::{system::AdminOperation, Message, SystemMessage, SystemOperation};
15use serde::{Deserialize, Serialize};
16
17#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
19pub struct TimeoutConfigMetadata {
20 pub fast_round_ms: Option<String>,
22 pub base_timeout_ms: String,
24 pub timeout_increment_ms: String,
26 pub fallback_duration_ms: String,
29}
30
31impl From<&TimeoutConfig> for TimeoutConfigMetadata {
32 fn from(config: &TimeoutConfig) -> Self {
33 TimeoutConfigMetadata {
34 fast_round_ms: config
35 .fast_round_duration
36 .map(|d| (d.as_micros() / 1000).to_string()),
37 base_timeout_ms: (config.base_timeout.as_micros() / 1000).to_string(),
38 timeout_increment_ms: (config.timeout_increment.as_micros() / 1000).to_string(),
39 fallback_duration_ms: (config.fallback_duration.as_micros() / 1000).to_string(),
40 }
41 }
42}
43
44#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
46pub struct ChainOwnershipMetadata {
47 pub ownership_json: String,
49}
50
51impl From<&ChainOwnership> for ChainOwnershipMetadata {
52 fn from(ownership: &ChainOwnership) -> Self {
53 ChainOwnershipMetadata {
54 ownership_json: serde_json::to_string(ownership)
57 .unwrap_or_else(|_| format!("{ownership:?}")),
58 }
59 }
60}
61
62#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
64pub struct ApplicationPermissionsMetadata {
65 pub permissions_json: String,
67}
68
69impl From<&ApplicationPermissions> for ApplicationPermissionsMetadata {
70 fn from(permissions: &ApplicationPermissions) -> Self {
71 ApplicationPermissionsMetadata {
72 permissions_json: serde_json::to_string(permissions)
75 .unwrap_or_else(|_| format!("{permissions:?}")),
76 }
77 }
78}
79
80#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
82pub struct SystemOperationMetadata {
83 pub system_operation_type: String,
85 pub transfer: Option<TransferOperationMetadata>,
87 pub claim: Option<ClaimOperationMetadata>,
89 pub open_chain: Option<OpenChainOperationMetadata>,
91 pub change_ownership: Option<ChangeOwnershipOperationMetadata>,
93 pub change_application_permissions: Option<ChangeApplicationPermissionsMetadata>,
95 pub admin: Option<AdminOperationMetadata>,
97 pub create_application: Option<CreateApplicationOperationMetadata>,
99 pub publish_data_blob: Option<PublishDataBlobMetadata>,
101 pub verify_blob: Option<VerifyBlobMetadata>,
103 pub publish_module: Option<PublishModuleMetadata>,
105 pub epoch: Option<i32>,
107 pub update_streams: Option<Vec<UpdateStreamMetadata>>,
109}
110
111impl SystemOperationMetadata {
112 fn new(system_operation_type: &str) -> Self {
114 SystemOperationMetadata {
115 system_operation_type: system_operation_type.to_string(),
116 transfer: None,
117 claim: None,
118 open_chain: None,
119 change_ownership: None,
120 change_application_permissions: None,
121 admin: None,
122 create_application: None,
123 publish_data_blob: None,
124 verify_blob: None,
125 publish_module: None,
126 epoch: None,
127 update_streams: None,
128 }
129 }
130}
131
132#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
134pub struct TransferOperationMetadata {
135 pub owner: AccountOwner,
136 pub recipient: Account,
137 pub amount: Amount,
138}
139
140#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
142pub struct ClaimOperationMetadata {
143 pub owner: AccountOwner,
144 pub target_id: ChainId,
145 pub recipient: Account,
146 pub amount: Amount,
147}
148
149#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
151pub struct OpenChainOperationMetadata {
152 pub balance: Amount,
153 pub ownership: ChainOwnershipMetadata,
154 pub application_permissions: ApplicationPermissionsMetadata,
155}
156
157#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
159pub struct ChangeOwnershipOperationMetadata {
160 pub super_owners: Vec<AccountOwner>,
161 pub owners: Vec<OwnerWithWeight>,
162 pub first_leader: Option<AccountOwner>,
163 pub multi_leader_rounds: i32,
164 pub open_multi_leader_rounds: bool,
165 pub timeout_config: TimeoutConfigMetadata,
166}
167
168#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
170pub struct OwnerWithWeight {
171 pub owner: AccountOwner,
172 pub weight: String, }
174
175#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
177pub struct ChangeApplicationPermissionsMetadata {
178 pub permissions: ApplicationPermissionsMetadata,
179}
180
181#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
183pub struct AdminOperationMetadata {
184 pub admin_operation_type: String,
185 pub epoch: Option<i32>,
186 pub blob_hash: Option<CryptoHash>,
187}
188
189#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
191pub struct CreateApplicationOperationMetadata {
192 pub module_id: String,
193 pub parameters_hex: String,
194 pub instantiation_argument_hex: String,
195 pub required_application_ids: Vec<ApplicationId>,
196}
197
198#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
200pub struct PublishDataBlobMetadata {
201 pub blob_hash: CryptoHash,
202}
203
204#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
206pub struct VerifyBlobMetadata {
207 pub blob_id: String,
208}
209
210#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
212pub struct PublishModuleMetadata {
213 pub module_id: String,
214}
215
216#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
218pub struct UpdateStreamMetadata {
219 pub chain_id: ChainId,
220 pub stream_id: String,
221 pub next_index: i32,
222}
223
224#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
226pub struct SystemMessageMetadata {
227 pub system_message_type: String,
229 pub credit: Option<CreditMessageMetadata>,
231 pub withdraw: Option<WithdrawMessageMetadata>,
233}
234
235#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
237pub struct CreditMessageMetadata {
238 pub target: AccountOwner,
239 pub amount: Amount,
240 pub source: AccountOwner,
241}
242
243#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
245pub struct WithdrawMessageMetadata {
246 pub owner: AccountOwner,
247 pub amount: Amount,
248 pub recipient: Account,
249}
250
251#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, SimpleObject)]
253pub struct MessageMetadata {
254 pub message_type: String,
256 pub application_id: Option<ApplicationId>,
258 pub user_bytes_hex: Option<String>,
260 pub system_message: Option<SystemMessageMetadata>,
262}
263
264impl From<&SystemOperation> for SystemOperationMetadata {
265 fn from(sys_op: &SystemOperation) -> Self {
266 match sys_op {
267 SystemOperation::Transfer {
268 owner,
269 recipient,
270 amount,
271 } => SystemOperationMetadata {
272 transfer: Some(TransferOperationMetadata {
273 owner: *owner,
274 recipient: *recipient,
275 amount: *amount,
276 }),
277 ..SystemOperationMetadata::new("Transfer")
278 },
279 SystemOperation::Claim {
280 owner,
281 target_id,
282 recipient,
283 amount,
284 } => SystemOperationMetadata {
285 claim: Some(ClaimOperationMetadata {
286 owner: *owner,
287 target_id: *target_id,
288 recipient: *recipient,
289 amount: *amount,
290 }),
291 ..SystemOperationMetadata::new("Claim")
292 },
293 SystemOperation::OpenChain(config) => SystemOperationMetadata {
294 open_chain: Some(OpenChainOperationMetadata {
295 balance: config.balance,
296 ownership: ChainOwnershipMetadata::from(&config.ownership),
297 application_permissions: ApplicationPermissionsMetadata::from(
298 &config.application_permissions,
299 ),
300 }),
301 ..SystemOperationMetadata::new("OpenChain")
302 },
303 SystemOperation::CloseChain => SystemOperationMetadata::new("CloseChain"),
304 SystemOperation::ChangeOwnership {
305 super_owners,
306 owners,
307 first_leader,
308 multi_leader_rounds,
309 open_multi_leader_rounds,
310 timeout_config,
311 } => SystemOperationMetadata {
312 change_ownership: Some(ChangeOwnershipOperationMetadata {
313 super_owners: super_owners.clone(),
314 owners: owners
315 .iter()
316 .map(|(owner, weight)| OwnerWithWeight {
317 owner: *owner,
318 weight: weight.to_string(),
319 })
320 .collect(),
321 first_leader: *first_leader,
322 multi_leader_rounds: *multi_leader_rounds as i32,
323 open_multi_leader_rounds: *open_multi_leader_rounds,
324 timeout_config: TimeoutConfigMetadata::from(timeout_config),
325 }),
326 ..SystemOperationMetadata::new("ChangeOwnership")
327 },
328 SystemOperation::ChangeApplicationPermissions(permissions) => SystemOperationMetadata {
329 change_application_permissions: Some(ChangeApplicationPermissionsMetadata {
330 permissions: ApplicationPermissionsMetadata::from(permissions),
331 }),
332 ..SystemOperationMetadata::new("ChangeApplicationPermissions")
333 },
334 SystemOperation::Admin(admin_op) => SystemOperationMetadata {
335 admin: Some(AdminOperationMetadata::from(admin_op)),
336 ..SystemOperationMetadata::new("Admin")
337 },
338 SystemOperation::CreateApplication {
339 module_id,
340 parameters,
341 instantiation_argument,
342 required_application_ids,
343 } => SystemOperationMetadata {
344 create_application: Some(CreateApplicationOperationMetadata {
345 module_id: module_id.to_string(),
346 parameters_hex: hex::encode(parameters),
347 instantiation_argument_hex: hex::encode(instantiation_argument),
348 required_application_ids: required_application_ids.clone(),
349 }),
350 ..SystemOperationMetadata::new("CreateApplication")
351 },
352 SystemOperation::PublishDataBlob { blob_hash } => SystemOperationMetadata {
353 publish_data_blob: Some(PublishDataBlobMetadata {
354 blob_hash: *blob_hash,
355 }),
356 ..SystemOperationMetadata::new("PublishDataBlob")
357 },
358 SystemOperation::VerifyBlob { blob_id } => SystemOperationMetadata {
359 verify_blob: Some(VerifyBlobMetadata {
360 blob_id: blob_id.to_string(),
361 }),
362 ..SystemOperationMetadata::new("VerifyBlob")
363 },
364 SystemOperation::PublishModule { module_id } => SystemOperationMetadata {
365 publish_module: Some(PublishModuleMetadata {
366 module_id: module_id.to_string(),
367 }),
368 ..SystemOperationMetadata::new("PublishModule")
369 },
370 SystemOperation::ProcessNewEpoch(epoch) => SystemOperationMetadata {
371 epoch: Some(epoch.0 as i32),
372 ..SystemOperationMetadata::new("ProcessNewEpoch")
373 },
374 SystemOperation::ProcessRemovedEpoch(epoch) => SystemOperationMetadata {
375 epoch: Some(epoch.0 as i32),
376 ..SystemOperationMetadata::new("ProcessRemovedEpoch")
377 },
378 SystemOperation::UpdateStreams(streams) => SystemOperationMetadata {
379 update_streams: Some(
380 streams
381 .iter()
382 .map(|(chain_id, stream_id, next_index)| UpdateStreamMetadata {
383 chain_id: *chain_id,
384 stream_id: stream_id.to_string(),
385 next_index: *next_index as i32,
386 })
387 .collect(),
388 ),
389 ..SystemOperationMetadata::new("UpdateStreams")
390 },
391 }
392 }
393}
394
395impl From<&AdminOperation> for AdminOperationMetadata {
396 fn from(admin_op: &AdminOperation) -> Self {
397 match admin_op {
398 AdminOperation::PublishCommitteeBlob { blob_hash } => AdminOperationMetadata {
399 admin_operation_type: "PublishCommitteeBlob".to_string(),
400 epoch: None,
401 blob_hash: Some(*blob_hash),
402 },
403 AdminOperation::CreateCommittee { epoch, blob_hash } => AdminOperationMetadata {
404 admin_operation_type: "CreateCommittee".to_string(),
405 epoch: Some(epoch.0 as i32),
406 blob_hash: Some(*blob_hash),
407 },
408 AdminOperation::RemoveCommittee { epoch } => AdminOperationMetadata {
409 admin_operation_type: "RemoveCommittee".to_string(),
410 epoch: Some(epoch.0 as i32),
411 blob_hash: None,
412 },
413 }
414 }
415}
416
417impl From<&Message> for MessageMetadata {
418 fn from(message: &Message) -> Self {
419 match message {
420 Message::System(sys_msg) => MessageMetadata {
421 message_type: "System".to_string(),
422 application_id: None,
423 user_bytes_hex: None,
424 system_message: Some(SystemMessageMetadata::from(sys_msg)),
425 },
426 Message::User {
427 application_id,
428 bytes,
429 } => MessageMetadata {
430 message_type: "User".to_string(),
431 application_id: Some(*application_id),
432 user_bytes_hex: Some(hex::encode(bytes)),
433 system_message: None,
434 },
435 }
436 }
437}
438
439impl From<&SystemMessage> for SystemMessageMetadata {
440 fn from(sys_msg: &SystemMessage) -> Self {
441 match sys_msg {
442 SystemMessage::Credit {
443 target,
444 amount,
445 source,
446 } => SystemMessageMetadata {
447 system_message_type: "Credit".to_string(),
448 credit: Some(CreditMessageMetadata {
449 target: *target,
450 amount: *amount,
451 source: *source,
452 }),
453 withdraw: None,
454 },
455 SystemMessage::Withdraw {
456 owner,
457 amount,
458 recipient,
459 } => SystemMessageMetadata {
460 system_message_type: "Withdraw".to_string(),
461 credit: None,
462 withdraw: Some(WithdrawMessageMetadata {
463 owner: *owner,
464 amount: *amount,
465 recipient: *recipient,
466 }),
467 },
468 }
469 }
470}