Skip to content

Commit 7296c0f

Browse files
committed
add identifiers to nav
1 parent abcfc67 commit 7296c0f

File tree

6 files changed

+220
-252
lines changed

6 files changed

+220
-252
lines changed

src/pages/_data/navigation/mainNav.json5

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
},
2828
{ title: "Build", url: "/build/", children: [
2929
{ title: "Working with Data", url: "/build/working-with-data/", children: [
30+
{ title: "Identifiers", url: "/build/identifiers/" },
3031
{ title: "Entries", url: "/build/entries/" },
3132
{ title: "Links, Paths, and Anchors", url: "/build/links-paths-and-anchors/" },
3233
]},

src/pages/build/entries.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ let delete_action_hash: ActionHash = delete_entry(
230230
)?;
231231
```
232232

233-
As with an update, this does _not_ actually remove data from the source chain or the DHT. Instead, a [`Delete` action](https://docs.rs/holochain_integrity_types/latest/holochain_integrity_types/action/struct.Delete.html) is authored, which attaches to the entry creation action and marks it as 'dead'. An entry itself is only considered dead when all entry creation actions that created it are marked dead, and it can become live again in the future if a _new_ entry creation action writes it. Dead data can still be retrieved with [`hdk::prelude::get_details`](https://docs.rs/hdk/latest/hdk/prelude/fn.get_details.html) (see below).
233+
As with an update, this does _not_ actually remove data from the source chain or the DHT. Instead, a [`Delete` action](https://docs.rs/holochain_integrity_types/latest/holochain_integrity_types/action/struct.Delete.html) is authored, which attaches to the entry creation action and marks it as deleted. An entry itself is only considered deleted when _all_ entry creation actions that created it are marked deleted, and it can become live again in the future if a _new_ entry creation action writes it. Deleted data can still be retrieved with [`hdk::prelude::get_details`](https://docs.rs/hdk/latest/hdk/prelude/fn.get_details.html) (see below).
234234

235235
In the future we plan to include a 'purge' functionality. This will give agents permission to actually erase an entry from their DHT store, but not its associated entry creation action.
236236

src/pages/build/identifiers.md

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
---
2+
title: "Identifiers"
3+
---
4+
5+
::: intro
6+
Data in Holochain is **addressable content**, which means that it's retrieved using an address that's derived from the data itself.
7+
:::
8+
9+
## Address types
10+
11+
The address of most data is the [Blake2b-256](https://www.blake2.net/) hash of its bytes. This goes for both [**actions** and **entries**](/build/working-with-data/#entries-actions-and-records-primary-data) (with just one exception), and there are two extra address types that have content associated with them.
12+
13+
All addresses are 39 bytes long and are [multihash-friendly](https://www.multiformats.io/multihash/). Generally, you don't need to know how to construct an address. Functions and data structures that store data will give you the data's address. But when you see a hash in the wild, this is what it's made out of:
14+
15+
| Multihash prefix | Hash | DHT location |
16+
|------------------|----------|--------------|
17+
| 3 bytes | 32 bytes | 4 bytes |
18+
19+
The four-byte DHT location is calculated from the 32 bytes of the hash and is used in routing to the right peer. The three-byte multihash prefix will be one of the following:
20+
21+
| Hash type | [`holo_hash`](https://docs.rs/holo_hash/latest/holo_hash/#types) type | Prefix in Base64 |
22+
|-----------|-------------------------------------------------------------------------------------|------------------|
23+
| DNA | [`DnaHash`](https://docs.rs/holo_hash/latest/holo_hash/type.DnaHash.html) | `hC0k` |
24+
| agent ID | [`AgentPubKey`](https://docs.rs/holo_hash/latest/holo_hash/type.AgentPubKey.html) | `hCAk` |
25+
| action | [`ActionHash`](https://docs.rs/holo_hash/latest/holo_hash/type.ActionHash.html) | `hCkk` |
26+
| entry | [`EntryHash`](https://docs.rs/holo_hash/latest/holo_hash/type.EntryHash.html) | `hCEk` |
27+
| external | [`ExternalHash`](https://docs.rs/holo_hash/latest/holo_hash/type.ExternalHash.html) | `hC8k` |
28+
29+
You can see that, in the Rust SDK, each address is typed to what it represents. There are also a couple of composite types, [`AnyDhtHash`](https://docs.rs/holo_hash/latest/holo_hash/type.AnyDhtHash.html) and [`AnyLinkableHash`](https://docs.rs/holo_hash/latest/holo_hash/type.AnyLinkableHash.html), that certain functions (like link creation functions) accept. You can also use the above hash types as fields in your entry types.
30+
31+
Here's an overview of all seven address types:
32+
33+
* `DnaHash` is the hash of the DNA bundle, and is the [unique identifier for the network](/build/working-with-data/#storage-locations-and-privacy).
34+
* `AgentPubKey` is the public key of a participant in a network. Its address is the same as the entry content --- the agent's public key, not the hash of the public key.
35+
* `ActionHash` is the hash of a structure called an [action](/build/working-with-data/#entries-actions-and-records-primary-data) that records a participant's act of storing or changing private or shared data.
36+
* `EntryHash` is the hash of an arbitrary blob of bytes called an [entry](/build/entries/), which contains application or system data.
37+
* `ExternalHash` is the ID of a resource that exists outside the database, such as the hash of an IPFS resource or the public key of an Ethereum wallet. Holochain doesn't care about its content, as long as it's 32 bytes long. There's no content stored at the address; it simply serves as an anchor to attach [links](/build/links-paths-and-anchors/) to.
38+
* `AnyDhtHash` is the hash of any kind of addressable content (that is, actions and entries, including `AgentPubKey` entries).
39+
* `AnyLinkableHash` is the hash of anything that can be linked to or from (that is, all of the above).
40+
41+
### The unpredictability of action hashes
42+
43+
There are a few things to know about action hashes:
44+
45+
* You can't know an action's hash until you've written the action, because it's influenced by both the previous action's hash and participant's current system time.
46+
* When you write an action, you can specify "relaxed chain top ordering". We won't go into the details here, <!-- TODO: fill this in when I write about zome call lifecycles -->but it means an action hash may change after the action is written, so you shouldn't depend on the value of the hash within the function that writes it.
47+
* Any function that writes to an agent's source chain is **atomic**, which means that all actions are written, but only after the function succeeds _and_ all actions are successfully validated. That means that you shouldn't depend on content being available at an address until _after_ the function returns a success result.
48+
49+
## Getting hashes
50+
51+
Because Holochain's graph DHT is all about connecting hashes to other hashes, here's how you get hashes.
52+
53+
### Action
54+
55+
Any CRUD host function that records an action on an agent's source chain, such as `create`, `update`, `delete`, `create_link`, and `delete_link`, returns the hash of the action. You can use this in links, either for further writes in the same function call or elsewhere.
56+
57+
<!-- TODO: remove/simplify this with a pointer to the lifecycle document when I write it -->
58+
!!! info Actions aren't written until function lifecycle completes
59+
Like we mentioned in [Working with Data](/guide/working-with-data/#content-addresses), zome functions are atomic, so actions aren't actually there until the zome function that writes them completes successfully.
60+
61+
If you need to share an action hash via a signal (say, with a remote peer), it's safer to wait until the zome function has completed. You can do this by creating a callback called `post_commit()`. It'll be called after every successful function call within that zome.
62+
!!!
63+
64+
!!! info Don't depend on relaxed action hashes
65+
If you use 'relaxed' chain top ordering<!-- TODO: link to lifecycle doc -->, your zome function shouldn't depend on the action hash it gets back from the CRUD host function, because the final value might change by the time the actions are written.
66+
!!!
67+
68+
If you have a variable that contains a [`hdk::prelude::Action`](https://docs.rs/hdk/latest/hdk/prelude/enum.Action.html) or [`hdk::prelude::Record`](https://docs.rs/hdk/latest/hdk/prelude/struct.Record.html), you can also get its hash using the following methods:
69+
70+
```rust
71+
let action_hash_from_record = record.action_address();
72+
let action = record.signed_action;
73+
let action_hash_from_action = action.as_hash();
74+
assert_eq!(action_hash_from_record, action_hash_from_action);
75+
```
76+
77+
(But it's worth pointing out that if you have this value, it's probably because you just retrieved the action by hash, which means you probably already know the hash.)
78+
79+
To get the hash of an entry creation action from an action that deletes or updates it, match on the [`Action::Update`](https://docs.rs/hdk/latest/hdk/prelude/enum.Action.html#variant.Update) or [`Action::Delete`](https://docs.rs/hdk/latest/hdk/prelude/enum.Action.html#variant.Delete) action variants and access the appropriate field:
80+
81+
```rust
82+
if let Action::Update(action_data) = action {
83+
let replaced_action_hash = action_data.original_action_address;
84+
// Do some things with the original action.
85+
} else if let Action::Delete(action_data) = action {
86+
let deleted_action_hash = action_data.deletes_address;
87+
// Do some things with the deleted action.
88+
}
89+
```
90+
91+
### Entry
92+
93+
To get the hash of an entry, first construct the entry struct or enum that you [defined in the integrity zome](/build/entries/#define-an-entry-type), then pass it through the [`hdk::hash::hash_entry`](https://docs.rs/hdk/latest/hdk/hash/fn.hash_entry.html) function. (You don't actually have to write the entry to a source chain to get the entry hash.)
94+
95+
```rust
96+
use hdk::hash::*;
97+
use movie_integrity::*;
98+
99+
let director_entry_hash = EntryHash::from_raw_36(vec![/* Sergio Leone's hash */]);
100+
let movie = Movie {
101+
title: "The Good, the Bad, and the Ugly",
102+
director_entry_hash: director_entry_hash,
103+
imdb_id: Some("tt0060196"),
104+
release_date: Timestamp::from(Date::Utc("1966-12-23")),
105+
box_office_revenue: 389_000_000,
106+
};
107+
let movie_entry_hash = hash_entry(movie);
108+
```
109+
110+
To get the hash of an entry from the action that created it, call the action's [`entry_hash`](https://docs.rs/hdk/latest/hdk/prelude/enum.Action.html#method.entry_hash) method. It returns an optional value, because not all actions have associated entries.
111+
112+
```rust
113+
let entry_hash = action.entry_hash()?;
114+
```
115+
116+
If you know that your action is an entry creation action, you can get the entry hash from its `entry_hash` field:
117+
118+
```rust
119+
let entry_creation_action: EntryCreationAction = action.into()?;
120+
let entry_hash = action.entry_hash;
121+
```
122+
123+
To get the hash of an entry from a record, you can either get it from the record itself or the contained action:
124+
125+
```rust
126+
let entry_hash_from_record = record.entry().as_option()?.hash();
127+
let entry_hash_from_action = record.action().entry_hash()?
128+
assert_equal!(entry_hash_from_record, entry_hash_from_action);
129+
```
130+
131+
Finally, to get the hash of an entry from an action that updates or deletes it, match the action to the appropriate variant and access the corresponding field:
132+
133+
```rust
134+
if let Action::Update(action_data) = action {
135+
let replaced_entry_hash = action_data.original_entry_address;
136+
} else if let Action::Delete(action_data) = action {
137+
let deleted_entry_hash = action_data.deletes_entry_address;
138+
}
139+
```
140+
141+
### Agent
142+
143+
An agent's ID is just their public key, and an entry for their ID is stored on the DHT. The hashing function for an agent ID entry is just the literal value of the entry. This is a roundabout way of saying that you link to or from an agent using their public key as a hash.
144+
145+
An agent can get their own ID by calling [`hdk::prelude::agent_info`](https://docs.rs/hdk/latest/hdk/info/fn.agent_info.html). Note that agents may change their ID if their public key has been lost or stolen, so they may have more than one ID over the course of their participation in a network.
146+
147+
```rust
148+
use hdk::prelude::*;
149+
150+
let my_first_id = agent_info()?.agent_initial_pubkey;
151+
let my_current_id = agent_info()?.agent_latest_pubkey;
152+
```
153+
154+
All actions have their author's ID as a field. You can get this field by calling the action's `author()` method:
155+
156+
```rust
157+
let author_id = action.author();
158+
```
159+
160+
### External reference
161+
162+
An external reference is just any 32-byte identifier. Holochain doesn't care if it's an IPFS hash, an Ethereum wallet, the hash of a constant in your code, a very short URL, or the name of your pet cat. But because it comes from outside of a DHT, it's up to your application to decide how to construct or handle it. Typically, an external client such as a UI would do all that.
163+
164+
Construct an external hash from the raw bytes or a Base64 string:
165+
166+
```rust
167+
use holo_hash::*;
168+
169+
```
170+
171+
You can then use the value wherever linkable hashes can be used.
172+
My hovercraft is full of eels!!!
173+
### DNA
174+
175+
There is one global hash that everyone knows, and that's the hash of the DNA itself. You can get it by calling [`hdk::prelude::dna_info`](https://docs.rs/hdk/latest/hdk/info/fn.dna_info.html).
176+
177+
```rust
178+
use hdk::prelude::*;
179+
180+
let dna_hash = dna_info()?.hash;
181+
```

src/pages/build/index.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ This Build Guide organizes everything you need to know about developing Holochai
1616
### Topics {data-no-toc}
1717

1818
* [Overview](/build/working-with-data/) --- general concepts related to working with data in Holochain
19-
* [Entries](/build/entries/) --- creating, reading, updating, and deleting
20-
* [Links, Paths, and Anchors](/build/links-paths-and-anchors/) --- creating and deleting
19+
* [Identifiers](/build/identifiers) --- working with hashes and other unique IDs
20+
* [Entries](/build/entries/) --- defining, creating, reading, updating, and deleting data
21+
* [Links, Paths, and Anchors](/build/links-paths-and-anchors/) --- creating relationships between data
2122
:::

0 commit comments

Comments
 (0)