Struct holochain_types::dna::DnaFile
source · pub struct DnaFile { /* private fields */ }
Expand description
Represents a full DNA, including DnaDef and WebAssembly bytecode.
Historical note: This struct was written before DnaBundle
was introduced.
This used to be our file representation of a full distributable DNA.
That function has been superseded by DnaBundle
, but we use this type
widely, so there is simply a way to convert from DnaBundle
to DnaFile
.
TODO: Once we remove the InstallApp
command which accepts a DnaFile
,
we should remove the Serialize impl on this type, and perhaps rename
to indicate that this is simply a validated, fully-formed DnaBundle
(i.e. all Wasms are bundled and immediately available, not remote.)
Implementations§
source§impl DnaFile
impl DnaFile
sourcepub async fn new(dna: DnaDef, wasm: impl IntoIterator<Item = DnaWasm>) -> Self
pub async fn new(dna: DnaDef, wasm: impl IntoIterator<Item = DnaWasm>) -> Self
Construct a new DnaFile instance.
Examples found in repository?
205 206 207 208 209 210 211 212 213 214 215 216 217
pub async fn with_properties(self, properties: SerializedBytes) -> Self {
let (mut dna, wasm): (DnaDef, Vec<wasm::DnaWasm>) = self.into();
dna.modifiers.properties = properties;
DnaFile::new(dna, wasm).await
}
/// Transform this DnaFile into a new DnaFile with a different network seed
/// and, hence, a different DnaHash.
pub async fn with_network_seed(self, network_seed: NetworkSeed) -> Self {
let (mut dna, wasm): (DnaDef, Vec<wasm::DnaWasm>) = self.into();
dna.modifiers.network_seed = network_seed;
DnaFile::new(dna, wasm).await
}
More examples
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
pub fn fake_dna_zomes_named(
network_seed: &str,
name: &str,
zomes: Vec<(ZomeName, DnaWasm)>,
) -> DnaFile {
let mut dna = DnaDef {
name: name.to_string(),
modifiers: DnaModifiers {
properties: YamlProperties::new(serde_yaml::from_str("p: hi").unwrap())
.try_into()
.unwrap(),
network_seed: network_seed.to_string(),
origin_time: Timestamp::HOLOCHAIN_EPOCH,
quantum_time: kitsune_p2p_dht::spacetime::STANDARD_QUANTUM_TIME,
},
integrity_zomes: Vec::new(),
coordinator_zomes: Vec::new(),
};
tokio_helper::block_forever_on(async move {
let mut wasm_code = Vec::new();
for (zome_name, wasm) in zomes {
let wasm = crate::dna::wasm::DnaWasmHashed::from_content(wasm).await;
let (wasm, wasm_hash) = wasm.into_inner();
dna.integrity_zomes.push((
zome_name,
ZomeDef::Wasm(WasmZome {
wasm_hash,
dependencies: Default::default(),
})
.into(),
));
wasm_code.push(wasm);
}
DnaFile::new(dna, wasm_code).await
})
}
sourcepub async fn update_coordinators(
&mut self,
coordinator_zomes: CoordinatorZomes,
wasms: Vec<DnaWasm>
) -> Result<Vec<WasmHash>, DnaError>
pub async fn update_coordinators(
&mut self,
coordinator_zomes: CoordinatorZomes,
wasms: Vec<DnaWasm>
) -> Result<Vec<WasmHash>, DnaError>
Update coordinator zomes for this dna.
sourcepub fn from_parts(dna: DnaDefHashed, code: WasmMap) -> Self
pub fn from_parts(dna: DnaDefHashed, code: WasmMap) -> Self
Construct a DnaFile from its constituent parts
sourcepub fn dna(&self) -> &DnaDefHashed
pub fn dna(&self) -> &DnaDefHashed
The DnaDef along with its hash
sourcepub fn dna_hash(&self) -> &DnaHash
pub fn dna_hash(&self) -> &DnaHash
The hash of the DnaDef
Examples found in repository?
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 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234
pub async fn resolve_cells(
self,
agent: AgentPubKey,
_gamut: DnaGamut,
membrane_proofs: HashMap<RoleName, MembraneProof>,
) -> AppBundleResult<AppRoleResolution> {
let AppManifestValidated { name: _, roles } = self.manifest().clone().validate()?;
let bundle = Arc::new(self);
let tasks = roles.into_iter().map(|(role_name, role)| async {
let bundle = bundle.clone();
Ok((role_name, bundle.resolve_cell(role).await?))
});
let resolution = futures::future::join_all(tasks)
.await
.into_iter()
.collect::<AppBundleResult<Vec<_>>>()?
.into_iter()
.fold(
Ok(AppRoleResolution::new(agent.clone())),
|acc: AppBundleResult<AppRoleResolution>, (role_name, op)| {
if let Ok(mut resolution) = acc {
match op {
CellProvisioningOp::Create(dna, clone_limit) => {
let agent = resolution.agent.clone();
let dna_hash = dna.dna_hash().clone();
let cell_id = CellId::new(dna_hash, agent);
let role = AppRoleAssignment::new(cell_id, true, clone_limit);
// TODO: could sequentialize this to remove the clone
let proof = membrane_proofs.get(&role_name).cloned();
resolution.dnas_to_register.push((dna, proof));
resolution.role_assignments.push((role_name, role));
}
CellProvisioningOp::Existing(cell_id, clone_limit) => {
let role = AppRoleAssignment::new(cell_id, true, clone_limit);
resolution.role_assignments.push((role_name, role));
}
CellProvisioningOp::Noop(cell_id, clone_limit) => {
resolution.role_assignments.push((
role_name,
AppRoleAssignment::new(cell_id, false, clone_limit),
));
}
other => {
tracing::error!(
"Encountered unexpected CellProvisioningOp: {:?}",
other
);
unimplemented!()
}
}
Ok(resolution)
} else {
acc
}
},
)?;
// let resolution = cells.into_iter();
Ok(resolution)
}
async fn resolve_cell(
&self,
role: AppRoleManifestValidated,
) -> AppBundleResult<CellProvisioningOp> {
Ok(match role {
AppRoleManifestValidated::Create {
location,
version,
clone_limit,
modifiers,
deferred: _,
} => {
self.resolve_cell_create(&location, version.as_ref(), clone_limit, modifiers)
.await?
}
AppRoleManifestValidated::CreateClone { .. } => {
unimplemented!("`create_clone` provisioning strategy is currently unimplemented")
}
AppRoleManifestValidated::UseExisting {
version,
clone_limit,
deferred: _,
} => self.resolve_cell_existing(&version, clone_limit),
AppRoleManifestValidated::CreateIfNotExists {
location,
version,
clone_limit,
modifiers,
deferred: _,
} => match self.resolve_cell_existing(&version, clone_limit) {
op @ CellProvisioningOp::Existing(_, _) => op,
CellProvisioningOp::NoMatch => {
self.resolve_cell_create(&location, Some(&version), clone_limit, modifiers)
.await?
}
CellProvisioningOp::Conflict(_) => {
unimplemented!("conflicts are not handled, or even possible yet")
}
CellProvisioningOp::Create(_, _) => {
unreachable!("resolve_cell_existing will never return a Create op")
}
CellProvisioningOp::Noop(_, _) => {
unreachable!("resolve_cell_existing will never return a Noop")
}
},
AppRoleManifestValidated::Disabled {
version: _,
clone_limit: _,
} => {
unimplemented!("`disabled` provisioning strategy is currently unimplemented")
// CellProvisioningOp::Noop(clone_limit)
}
})
}
async fn resolve_cell_create(
&self,
location: &mr_bundle::Location,
version: Option<&DnaVersionSpec>,
clone_limit: u32,
modifiers: DnaModifiersOpt,
) -> AppBundleResult<CellProvisioningOp> {
let bytes = self.resolve(location).await?;
let dna_bundle: DnaBundle = mr_bundle::Bundle::decode(&bytes)?.into();
let (dna_file, original_dna_hash) = dna_bundle.into_dna_file(modifiers).await?;
if let Some(spec) = version {
if !spec.matches(original_dna_hash) {
return Ok(CellProvisioningOp::NoMatch);
}
}
Ok(CellProvisioningOp::Create(dna_file, clone_limit))
}
fn resolve_cell_existing(
&self,
_version: &DnaVersionSpec,
_clone_limit: u32,
) -> CellProvisioningOp {
unimplemented!("Reusing existing cells is not yet implemented")
}
}
/// This function is called in places where it will be necessary to rework that
/// area after use_existing has been implemented
pub fn we_must_remember_to_rework_cell_panic_handling_after_implementing_use_existing_cell_resolution(
) {
}
/// The answer to the question:
/// "how do we concretely assign DNAs to the open roles of this App?"
/// Includes the DNAs selected to fill the roles and the details of the role assignments.
// TODO: rework, make fields private
#[allow(missing_docs)]
#[derive(PartialEq, Eq, Debug)]
pub struct AppRoleResolution {
pub agent: AgentPubKey,
pub dnas_to_register: Vec<(DnaFile, Option<MembraneProof>)>,
pub role_assignments: Vec<(RoleName, AppRoleAssignment)>,
}
#[allow(missing_docs)]
impl AppRoleResolution {
pub fn new(agent: AgentPubKey) -> Self {
Self {
agent,
dnas_to_register: Default::default(),
role_assignments: Default::default(),
}
}
/// Return the IDs of new cells to be created as part of the resolution.
/// Does not return existing cells to be reused.
pub fn cells_to_create(&self) -> Vec<(CellId, Option<MembraneProof>)> {
self.dnas_to_register
.iter()
.map(|(dna, proof)| {
(
CellId::new(dna.dna_hash().clone(), self.agent.clone()),
proof.clone(),
)
})
.collect()
}
sourcepub fn verify_hash(&self) -> Result<(), DnaError>
pub fn verify_hash(&self) -> Result<(), DnaError>
Verify that the DNA hash in the file matches the DnaDef
Examples found in repository?
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246
pub async fn from_file_content(data: &[u8]) -> Result<Self, DnaError> {
// Not super efficient memory-wise, but doesn't block any threads
let data = data.to_vec();
// Block because gzipping could take some time
let dna_file = tokio::task::spawn_blocking(move || {
let mut gz = flate2::read::GzDecoder::new(&data[..]);
let mut bytes = Vec::new();
use std::io::Read;
gz.read_to_end(&mut bytes)?;
let sb: SerializedBytes = UnsafeBytes::from(bytes).into();
let dna_file: DnaFile = sb.try_into()?;
DnaResult::Ok(dna_file)
})
.await
.expect("blocking thread panicked - panicking here too")?;
dna_file.verify_hash()?;
Ok(dna_file)
}
/// Transform this DnaFile into a new DnaFile with different properties
/// and, hence, a different DnaHash.
pub async fn with_properties(self, properties: SerializedBytes) -> Self {
let (mut dna, wasm): (DnaDef, Vec<wasm::DnaWasm>) = self.into();
dna.modifiers.properties = properties;
DnaFile::new(dna, wasm).await
}
/// Transform this DnaFile into a new DnaFile with a different network seed
/// and, hence, a different DnaHash.
pub async fn with_network_seed(self, network_seed: NetworkSeed) -> Self {
let (mut dna, wasm): (DnaDef, Vec<wasm::DnaWasm>) = self.into();
dna.modifiers.network_seed = network_seed;
DnaFile::new(dna, wasm).await
}
/// The bytes of the WASM zomes referenced in the Dna portion.
pub fn code(&self) -> &BTreeMap<holo_hash::WasmHash, wasm::DnaWasm> {
&self.code.0
}
/// Fetch the Webassembly byte code for a zome.
pub fn get_wasm_for_zome(&self, zome_name: &ZomeName) -> Result<&wasm::DnaWasm, DnaError> {
let wasm_hash = &self.dna.get_wasm_zome(zome_name)?.wasm_hash;
self.code.0.get(wasm_hash).ok_or(DnaError::InvalidWasmHash)
}
#[deprecated = "remove after app bundles become standard; use DnaBundle instead"]
/// Render this dna_file as bytecode to send over the wire, or store in a file.
pub async fn to_file_content(&self) -> Result<Vec<u8>, DnaError> {
// Not super efficient memory-wise, but doesn't block any threads
let dna_file = self.clone();
dna_file.verify_hash()?;
// Block because gzipping could take some time
tokio::task::spawn_blocking(move || {
let data: SerializedBytes = dna_file.try_into()?;
let mut enc = flate2::write::GzEncoder::new(Vec::new(), flate2::Compression::default());
use std::io::Write;
enc.write_all(data.bytes())?;
Ok(enc.finish()?)
})
.await
.expect("blocking thread panic!d - panicing here too")
}
sourcepub async fn from_file_content(data: &[u8]) -> Result<Self, DnaError>
👎Deprecated: remove after app bundles become standard; use DnaBundle instead
pub async fn from_file_content(data: &[u8]) -> Result<Self, DnaError>
Load dna_file bytecode into this rust struct.
sourcepub async fn with_properties(self, properties: SerializedBytes) -> Self
pub async fn with_properties(self, properties: SerializedBytes) -> Self
Transform this DnaFile into a new DnaFile with different properties and, hence, a different DnaHash.
sourcepub async fn with_network_seed(self, network_seed: NetworkSeed) -> Self
pub async fn with_network_seed(self, network_seed: NetworkSeed) -> Self
Transform this DnaFile into a new DnaFile with a different network seed and, hence, a different DnaHash.
sourcepub fn code(&self) -> &BTreeMap<WasmHash, DnaWasm>
pub fn code(&self) -> &BTreeMap<WasmHash, DnaWasm>
The bytes of the WASM zomes referenced in the Dna portion.
sourcepub fn get_wasm_for_zome(
&self,
zome_name: &ZomeName
) -> Result<&DnaWasm, DnaError>
pub fn get_wasm_for_zome(
&self,
zome_name: &ZomeName
) -> Result<&DnaWasm, DnaError>
Fetch the Webassembly byte code for a zome.
sourcepub async fn to_file_content(&self) -> Result<Vec<u8>, DnaError>
👎Deprecated: remove after app bundles become standard; use DnaBundle instead
pub async fn to_file_content(&self) -> Result<Vec<u8>, DnaError>
Render this dna_file as bytecode to send over the wire, or store in a file.
sourcepub fn update_modifiers(&self, dna_modifiers: DnaModifiersOpt) -> Self
pub fn update_modifiers(&self, dna_modifiers: DnaModifiersOpt) -> Self
Change the DNA modifiers – the network seed, origin time and properties – while leaving the actual DNA code intact.
Trait Implementations§
source§impl<'de> Deserialize<'de> for DnaFile
impl<'de> Deserialize<'de> for DnaFile
source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
source§impl PartialEq<DnaFile> for DnaFile
impl PartialEq<DnaFile> for DnaFile
source§impl TryFrom<&DnaFile> for SerializedBytes
impl TryFrom<&DnaFile> for SerializedBytes
§type Error = SerializedBytesError
type Error = SerializedBytesError
source§fn try_from(t: &DnaFile) -> Result<SerializedBytes, SerializedBytesError>
fn try_from(t: &DnaFile) -> Result<SerializedBytes, SerializedBytesError>
source§impl TryFrom<DnaFile> for SerializedBytes
impl TryFrom<DnaFile> for SerializedBytes
§type Error = SerializedBytesError
type Error = SerializedBytesError
source§fn try_from(t: DnaFile) -> Result<SerializedBytes, SerializedBytesError>
fn try_from(t: DnaFile) -> Result<SerializedBytes, SerializedBytesError>
source§impl TryFrom<SerializedBytes> for DnaFile
impl TryFrom<SerializedBytes> for DnaFile
§type Error = SerializedBytesError
type Error = SerializedBytesError
source§fn try_from(sb: SerializedBytes) -> Result<DnaFile, SerializedBytesError>
fn try_from(sb: SerializedBytes) -> Result<DnaFile, SerializedBytesError>
impl Eq for DnaFile
impl StructuralEq for DnaFile
impl StructuralPartialEq for DnaFile
Auto Trait Implementations§
impl !RefUnwindSafe for DnaFile
impl Send for DnaFile
impl Sync for DnaFile
impl Unpin for DnaFile
impl !UnwindSafe for DnaFile
Blanket Implementations§
§impl<T> Any for Twhere
T: Any + ?Sized,
impl<T> Any for Twhere
T: Any + ?Sized,
§fn type_id_compat(&self) -> TypeId
fn type_id_compat(&self) -> TypeId
§impl<T> ArchivePointee for T
impl<T> ArchivePointee for T
§type ArchivedMetadata = ()
type ArchivedMetadata = ()
§fn pointer_metadata(
_: &<T as ArchivePointee>::ArchivedMetadata
) -> <T as Pointee>::Metadata
fn pointer_metadata(
_: &<T as ArchivePointee>::ArchivedMetadata
) -> <T as Pointee>::Metadata
§impl<F, W, T, D> Deserialize<With<T, W>, D> for Fwhere
W: DeserializeWith<F, T, D>,
D: Fallible + ?Sized,
F: ?Sized,
impl<F, W, T, D> Deserialize<With<T, W>, D> for Fwhere
W: DeserializeWith<F, T, D>,
D: Fallible + ?Sized,
F: ?Sized,
§fn deserialize(
&self,
deserializer: &mut D
) -> Result<With<T, W>, <D as Fallible>::Error>
fn deserialize(
&self,
deserializer: &mut D
) -> Result<With<T, W>, <D as Fallible>::Error>
source§impl<Q, K> Equivalent<K> for Qwhere
Q: Eq + ?Sized,
K: Borrow<Q> + ?Sized,
impl<Q, K> Equivalent<K> for Qwhere
Q: Eq + ?Sized,
K: Borrow<Q> + ?Sized,
source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key
and return true
if they are equal.§impl<T> FutureExt for T
impl<T> FutureExt for T
§fn with_context(self, otel_cx: Context) -> WithContext<Self>
fn with_context(self, otel_cx: Context) -> WithContext<Self>
§fn with_current_context(self) -> WithContext<Self>
fn with_current_context(self) -> WithContext<Self>
source§impl<T> Instrument for T
impl<T> Instrument for T
source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
source§impl<T> Instrument for T
impl<T> Instrument for T
source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
§impl<T> Pointable for T
impl<T> Pointable for T
§impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
§fn to_subset(&self) -> Option<SS>
fn to_subset(&self) -> Option<SS>
self
from the equivalent element of its
superset. Read more§fn is_in_subset(&self) -> bool
fn is_in_subset(&self) -> bool
self
is actually part of its subset T
(and can be converted to it).§fn to_subset_unchecked(&self) -> SS
fn to_subset_unchecked(&self) -> SS
self.to_subset
but without any property checks. Always succeeds.§fn from_subset(element: &SS) -> SP
fn from_subset(element: &SS) -> SP
self
to the equivalent element of its superset.