Skip to content
This repository has been archived by the owner on Feb 3, 2023. It is now read-only.

Bridges DNA definition #752

Merged
merged 19 commits into from
Dec 19, 2018
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions core_types/src/dna/bridges.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
use crate::cas::content::Address;

/// A bridge is the definition of a connection to another DNA that runs under the same agency,
/// i.e. in the same container.
///
/// Defining a bridge means that the code in this DNA can call zome functions of that other
/// DNA.
///
/// The other DNA can either be referenced statically by exact DNA address/hash or dynamically
/// by defining the trait that other DNA has to implement in order to be used as bridge.
///
/// Bridges can be required or optional. If a required bridge DNA is not installed this DNA
/// can't run, so required bridges are hard dependencies that have to be enforced by the container.
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Hash)]
#[serde(untagged)]
pub enum Bridge {
Address(AddressBridge),
lucksus marked this conversation as resolved.
Show resolved Hide resolved
Trait(TraitBridge),
}

/// A bridge that defines another DNA statically by its address (i.e. hash).
/// If this variant is used the other DNA gets locked in as per DNA hash
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Hash)]
pub struct AddressBridge {
/// Required or optional
pub presence: BridgePresence,

/// An arbitrary name of this bridge that is used as handle to reference this
/// bridge in according zome API functions
pub handle: String,

/// The address (= hash) of the other DNA that we want to use.
pub dna_address: Address,
}

/// A bridge that defines another DNA loosely by expecting a DNA that implements
/// a given trait, i.e. that has a specific set of zome functions.
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Hash)]
pub struct TraitBridge {
/// Required or optional
pub presence: BridgePresence,

/// An arbitrary name of this bridge that is used as handle to reference this
/// bridge in according zome API functions
pub handle: String,

/// The unique, qualified domain name of a predefined trait.
/// Example: org.holochain.my-trait.
pub library_trait: String,
}

/// Required or optional
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Hash)]
lucksus marked this conversation as resolved.
Show resolved Hide resolved
pub enum BridgePresence {
/// A required bridge is a dependency to another DNA.
/// This DNA won't load without it.
Required,

/// An optional bridge may be missing.
/// This DNA's code can check via API functions if the other DNA is installed and connected.
Optional,
}
10 changes: 9 additions & 1 deletion core_types/src/dna/dna.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::{
dna::{capabilities::Capability, entry_types::EntryTypeDef, wasm, zome},
dna::{bridges::Bridge, capabilities::Capability, entry_types::EntryTypeDef, wasm, zome},
entry::entry_type::EntryType,
error::{DnaError, HolochainError},
json::JsonString,
Expand Down Expand Up @@ -192,6 +192,14 @@ impl Dna {
multihash::encode(multihash::Hash::SHA2256, &s.into_bytes())
.map_err(|error| HolochainError::ErrorGeneric(error.to_string()))
}

pub fn get_required_bridges(&self) -> Vec<Bridge> {
self.zomes
.values()
.map(|zome| zome.get_required_bridges())
.flatten()
.collect()
}
}

impl Hash for Dna {
Expand Down
85 changes: 83 additions & 2 deletions core_types/src/dna/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
//! assert_eq!(name, dna2.name);
//! ```

pub mod bridges;
pub mod capabilities;
pub mod dna;
pub mod entry_types;
Expand All @@ -36,7 +37,12 @@ pub mod tests {
use super::*;
extern crate base64;
use crate::{
dna::{entry_types::EntryTypeDef, zome::tests::test_zome},
cas::content::Address,
dna::{
bridges::{AddressBridge, Bridge, BridgePresence, TraitBridge},
entry_types::EntryTypeDef,
zome::tests::test_zome,
},
entry::entry_type::{AppEntryType, EntryType},
json::JsonString,
};
Expand Down Expand Up @@ -132,7 +138,8 @@ pub mod tests {
},
"code": {
"code": "AAECAw=="
}
},
"bridges": []
}
}
}"#,
Expand Down Expand Up @@ -457,4 +464,78 @@ pub mod tests {
.get_zome_name_for_app_entry_type(&AppEntryType::from("non existant entry type"))
.is_none());
}

#[test]
fn test_get_required_bridges() {
let dna = Dna::try_from(JsonString::from(
r#"{
"name": "test",
"description": "test",
"version": "test",
"uuid": "00000000-0000-0000-0000-000000000000",
"dna_spec_version": "2.0",
"properties": {
"test": "test"
},
"zomes": {
"test zome": {
"name": "test zome",
"description": "test",
"config": {},
"capabilities": {
"test capability": {
"capability": {
"membrane": "public"
},
"fn_declarations": []
}
},
"entry_types": {
"test type": {
"description": "",
"sharing": "public"
}
},
"code": {
"code": ""
},
"bridges": [
{
"presence": "Required",
"handle": "DPKI",
"dna_address": "Qmabcdef1234567890"
},
{
"presence": "Optional",
"handle": "Vault",
"library_trait": "org.holochain.alpha.personal-data-handler"
},
{
"presence": "Required",
"handle": "HCHC",
"library_trait": "org.holochain.alpha.dna-repository"
}
]
}
}
}"#,
))
.unwrap();

assert_eq!(
dna.get_required_bridges(),
vec![
Bridge::Address(AddressBridge {
presence: BridgePresence::Required,
handle: String::from("DPKI"),
dna_address: Address::from("Qmabcdef1234567890"),
}),
Bridge::Trait(TraitBridge {
presence: BridgePresence::Required,
handle: String::from("HCHC"),
library_trait: String::from("org.holochain.alpha.dna-repository"),
}),
]
);
}
}
27 changes: 25 additions & 2 deletions core_types/src/dna/zome.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
//! holochain_core_types::dna::zome is a set of structs for working with holochain dna.

use crate::{
dna::wasm::DnaWasm, entry::entry_type::EntryType, error::HolochainError, json::JsonString,
dna::{
bridges::{Bridge, BridgePresence},
wasm::DnaWasm,
},
entry::entry_type::EntryType,
error::HolochainError,
json::JsonString,
};
use dna::{
capabilities,
Expand Down Expand Up @@ -76,6 +82,10 @@ pub struct Zome {
/// Validation code for this entry_type.
#[serde(default)]
pub code: DnaWasm,

/// A list of bridges to other DNAs that this DNA can use or depends on.
#[serde(default)]
pub bridges: Vec<Bridge>,
}

impl Eq for Zome {}
Expand All @@ -89,6 +99,7 @@ impl Default for Zome {
entry_types: BTreeMap::new(),
capabilities: BTreeMap::new(),
code: DnaWasm::new(),
bridges: Vec::new(),
}
}
}
Expand All @@ -108,8 +119,20 @@ impl Zome {
entry_types: entry_types.to_owned(),
capabilities: capabilities.to_owned(),
code: code.clone(),
bridges: Vec::new(),
}
}

pub fn get_required_bridges(&self) -> Vec<Bridge> {
self.bridges
.iter()
.filter(|bridge| match bridge {
Bridge::Address(b) => b.presence == BridgePresence::Required,
Bridge::Trait(b) => b.presence == BridgePresence::Required,
})
.cloned()
.collect()
}
}

#[cfg(test)]
Expand Down Expand Up @@ -153,7 +176,7 @@ pub mod tests {
..Default::default()
};

let expected = "{\"description\":\"\",\"config\":{\"error_handling\":\"throw-errors\"},\"entry_types\":{\"foo\":{\"description\":\"\",\"sharing\":\"public\",\"links_to\":[],\"linked_from\":[]}},\"capabilities\":{},\"code\":{\"code\":\"\"}}";
let expected = "{\"description\":\"\",\"config\":{\"error_handling\":\"throw-errors\"},\"entry_types\":{\"foo\":{\"description\":\"\",\"sharing\":\"public\",\"links_to\":[],\"linked_from\":[]}},\"capabilities\":{},\"code\":{\"code\":\"\"},\"bridges\":[]}";

assert_eq!(
JsonString::from(expected.clone()),
Expand Down