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
37///Two types of program interfaces supported: plain binaries and ASGI apps.
38#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
39#[serde(rename_all = "lowercase")]
40pub enum Interface {
41    Asgi,
42    Binary,
43}
44
45/// Deserializes a metadata field that may come as either a JSON object or an empty array.
46/// Some APIs incorrectly return `[]` instead of `{}` or `null` for empty metadata.
47fn deserialize_metadata_tolerant<'de, D>(
48    deserializer: D,
49) -> Result<Option<HashMap<String, serde_json::Value>>, D::Error>
50where
51    D: Deserializer<'de>,
52{
53    use serde_json::Value;
54
55    let value = Option::<Value>::deserialize(deserializer)?;
56
57    match value {
58        None => Ok(None),
59        Some(Value::Object(map)) => Ok(Some(map.into_iter().collect())),
60        Some(Value::Array(arr)) if arr.is_empty() => {
61            // Treat empty array as empty map
62            Ok(Some(HashMap::new()))
63        }
64        Some(other) => Err(serde::de::Error::custom(format!(
65            "expected object or empty array for metadata, got {}",
66            other
67        ))),
68    }
69}
70
71/// Fields shared by program and instance messages.
72#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
73#[serde(rename_all = "lowercase")]
74pub struct ExecutableContent {
75    /// Allow amends to update this function.
76    pub allow_amend: bool,
77    /// Metadata of the VM.
78    #[serde(
79        default,
80        deserialize_with = "deserialize_metadata_tolerant",
81        skip_serializing_if = "Option::is_none"
82    )]
83    pub metadata: Option<HashMap<String, serde_json::Value>>,
84    /// Environment variables to set in the VM.
85    #[serde(default, skip_serializing_if = "Option::is_none")]
86    pub variables: Option<HashMap<String, String>>,
87    /// System resources required.
88    pub resources: MachineResources,
89    /// Payment details.
90    #[serde(default, skip_serializing_if = "Option::is_none")]
91    pub payment: Option<Payment>,
92    #[serde(default, skip_serializing_if = "Option::is_none")]
93    pub requirements: Option<HostRequirements>,
94    /// Volumes to mount on the filesystem.
95    #[serde(default)]
96    pub volumes: Vec<MachineVolume>,
97    /// Previous version to replace.
98    #[serde(default, skip_serializing_if = "Option::is_none")]
99    pub replaces: Option<ItemHash>,
100    #[serde(default, skip_serializing_if = "Option::is_none")]
101    pub authorized_keys: Option<Vec<String>>,
102}