1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
use std::path::PathBuf;

use crate::prelude::*;
use holo_hash::*;
use holochain_zome_types::ZomeName;
use serde_with::serde_as;

/// The structure of data that goes in the DNA bundle manifest "dna.yaml".
///
/// Navigating through this structure reveals all configurable DNA properties.
///
/// # Examples
///
/// An example "dna.yaml" with 2 integrity and 2 coordinator zomes:
///
/// ```yaml
/// manifest_version: "1"
/// name: multi integrity dna
/// integrity:
///   network_seed: 00000000-0000-0000-0000-000000000000
///   properties: ~
///   origin_time: 2022-02-11T23:05:19.470323Z
///   zomes:
///     - name: zome1
///       bundled: ../dna1/zomes/zome1.wasm
///     - name: zome2
///       bundled: ../dna2/zomes/zome1.wasm
/// coordinator:
///   zomes:
///     - name: zome3
///       bundled: ../dna1/zomes/zome2.wasm
///       dependencies:
///         - name: zome1
///     - name: zome4
///       bundled: ../dna2/zomes/zome2.wasm
///       dependencies:
///         - name: zome1
///         - name: zome2
/// ```
///
/// When there's only one integrity zome, it will automatically be a dependency
/// of the coordinator zomes. It doesn't need to be specified explicitly.
///
/// ```yaml
/// manifest_version: "1"
/// name: single integrity dna
/// integrity:
///   network_seed: 00000000-0000-0000-0000-000000000000
///   properties: ~
///   origin_time: 2022-02-11T23:05:19.470323Z
///   zomes:
///     - name: zome1
///       bundled: ../dna1/zomes/zome1.wasm
/// coordinator:
///   zomes:
///     - name: zome3
///       bundled: ../dna1/zomes/zome2.wasm
///     - name: zome4
///       bundled: ../dna2/zomes/zome2.wasm
/// ```

#[serde_as]
#[derive(
    Serialize,
    Deserialize,
    Clone,
    Debug,
    PartialEq,
    Eq,
    derive_more::Constructor,
    derive_builder::Builder,
)]
#[serde(rename_all = "snake_case", deny_unknown_fields)]
pub struct DnaManifestV1 {
    /// The friendly "name" of a Holochain DNA.
    pub name: String,

    /// Specification of integrity zomes and properties.
    ///
    /// Only this affects the [`DnaHash`].
    pub integrity: IntegrityManifest,

    #[serde(default)]
    /// Coordinator zomes to install with this DNA.
    ///
    /// Does not affect the [`DnaHash`].
    pub coordinator: CoordinatorManifest,
}

impl DnaManifestV1 {
    /// Get all integrity and coordinator zomes.
    pub fn all_zomes(&self) -> impl Iterator<Item = &ZomeManifest> {
        self.integrity
            .zomes
            .iter()
            .chain(self.coordinator.zomes.iter())
    }
}

#[serde_as]
#[derive(
    Serialize,
    Deserialize,
    Clone,
    Debug,
    PartialEq,
    Eq,
    derive_more::Constructor,
    derive_builder::Builder,
)]
#[serde(rename_all = "snake_case", deny_unknown_fields)]
/// Manifest for all items that will change the [`DnaHash`].
pub struct IntegrityManifest {
    /// A network seed for uniquifying this DNA. See [`DnaDef`].
    // TODO: consider Vec<u8> instead (https://github.com/holochain/holochain/pull/86#discussion_r412689085)
    pub network_seed: Option<String>,

    /// Any arbitrary application properties can be included in this object.
    pub properties: Option<YamlProperties>,

    /// The time used to denote the origin of the network, used to calculate
    /// time windows during gossip.
    /// All Action timestamps must come after this time.
    pub origin_time: HumanTimestamp,

    /// An array of zomes associated with your DNA.
    /// The order is significant: it determines initialization order.
    /// The integrity zome manifests.
    pub zomes: Vec<ZomeManifest>,
}

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, Default)]
#[serde(rename_all = "snake_case", deny_unknown_fields)]
/// Coordinator zomes.
pub struct CoordinatorManifest {
    /// Coordinator zomes to install with this dna.
    pub zomes: Vec<ZomeManifest>,
}

/// Manifest for an individual Zome
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
#[serde(rename_all = "snake_case", deny_unknown_fields)]
pub struct ZomeManifest {
    /// Just a friendly name, no semantic meaning.
    pub name: ZomeName,

    /// The hash of the wasm which defines this zome
    pub hash: Option<WasmHashB64>,

    /// The location of the wasm for this zome
    #[serde(flatten)]
    pub location: ZomeLocation,

    /// The integrity zomes this zome depends on.
    /// The order of these must match the order the types
    /// are used in the zome.
    pub dependencies: Option<Vec<ZomeDependency>>,

    /// The location of the wasm dylib for this zome
    /// Useful for iOS.
    #[serde(default)]
    pub dylib: Option<PathBuf>,
}

/// Manifest for integrity zomes that another zome
/// depends on.
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
#[serde(rename_all = "snake_case", deny_unknown_fields)]
pub struct ZomeDependency {
    /// The name of the integrity zome this zome depends on.
    pub name: ZomeName,
}

/// Alias for a suitable representation of zome location
pub type ZomeLocation = mr_bundle::Location;

impl ZomeManifest {
    /// Accessor
    pub fn location(&self) -> &ZomeLocation {
        &self.location
    }
}