Skip to main content

aleph_types/message/execution/
base.rs

1use crate::chain::{Address, Chain};
2use crate::item_hash::ItemHash;
3use crate::message::execution::environment::{HostRequirements, MachineResources};
4use crate::message::execution::volume::MachineVolume;
5use serde::{Deserialize, Deserializer, Serialize};
6use std::collections::HashMap;
7
8/// Code and data can be provided in plain format, as zip or as squashfs partition.
9#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
10#[serde(rename_all = "lowercase")]
11pub enum Encoding {
12    Plain,
13    Zip,
14    Squashfs,
15}
16
17#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
18#[serde(rename_all = "lowercase")]
19pub enum PaymentType {
20    Hold,
21    Superfluid,
22    Credit,
23}
24
25#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
26pub struct Payment {
27    /// Chain to check for funds.
28    #[serde(default, skip_serializing_if = "Option::is_none")]
29    pub chain: Option<Chain>,
30    /// Optional alternative address to send funds to.
31    #[serde(default, skip_serializing_if = "Option::is_none")]
32    pub receiver: Option<Address>,
33    #[serde(rename = "type")]
34    pub payment_type: PaymentType,
35}
36
37impl Payment {
38    pub fn credits() -> Self {
39        Self {
40            chain: None,
41            receiver: None,
42            payment_type: PaymentType::Credit,
43        }
44    }
45
46    pub fn hold() -> Self {
47        Self {
48            chain: None,
49            receiver: None,
50            payment_type: PaymentType::Hold,
51        }
52    }
53}
54
55///Two types of program interfaces supported: plain binaries and ASGI apps.
56#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
57#[serde(rename_all = "lowercase")]
58pub enum Interface {
59    Asgi,
60    Binary,
61}
62
63/// Deserializes a metadata field that may come as either a JSON object or an empty array.
64/// Some APIs incorrectly return `[]` instead of `{}` or `null` for empty metadata.
65fn deserialize_metadata_tolerant<'de, D>(
66    deserializer: D,
67) -> Result<Option<HashMap<String, serde_json::Value>>, D::Error>
68where
69    D: Deserializer<'de>,
70{
71    use serde_json::Value;
72
73    let value = Option::<Value>::deserialize(deserializer)?;
74
75    match value {
76        None => Ok(None),
77        Some(Value::Object(map)) => Ok(Some(map.into_iter().collect())),
78        Some(Value::Array(arr)) if arr.is_empty() => {
79            // Treat empty array as empty map
80            Ok(Some(HashMap::new()))
81        }
82        Some(other) => Err(serde::de::Error::custom(format!(
83            "expected object or empty array for metadata, got {}",
84            other
85        ))),
86    }
87}
88
89/// Fields shared by program and instance messages.
90#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
91#[serde(rename_all = "lowercase")]
92pub struct ExecutableContent {
93    /// Allow amends to update this function.
94    pub allow_amend: bool,
95    /// Metadata of the VM.
96    #[serde(
97        default,
98        deserialize_with = "deserialize_metadata_tolerant",
99        skip_serializing_if = "Option::is_none"
100    )]
101    pub metadata: Option<HashMap<String, serde_json::Value>>,
102    /// Environment variables to set in the VM.
103    #[serde(default, skip_serializing_if = "Option::is_none")]
104    pub variables: Option<HashMap<String, String>>,
105    /// System resources required.
106    pub resources: MachineResources,
107    /// Payment details.
108    #[serde(default, skip_serializing_if = "Option::is_none")]
109    pub payment: Option<Payment>,
110    #[serde(default, skip_serializing_if = "Option::is_none")]
111    pub requirements: Option<HostRequirements>,
112    /// Volumes to mount on the filesystem.
113    #[serde(default)]
114    pub volumes: Vec<MachineVolume>,
115    /// Previous version to replace.
116    #[serde(default, skip_serializing_if = "Option::is_none")]
117    pub replaces: Option<ItemHash>,
118    #[serde(default, skip_serializing_if = "Option::is_none")]
119    pub authorized_keys: Option<Vec<String>>,
120}