dweb/helpers/
graph_entry.rs1use autonomi::files::archive_public::ArchiveAddress;
19use blsttc::PublicKey;
20use color_eyre::{eyre::eyre, Result};
21
22use autonomi::client::key_derivation::{DerivationIndex, MainSecretKey};
23use autonomi::client::vault::VaultSecretKey as SecretKey;
24use autonomi::client::Client;
25use autonomi::{graph::GraphError, GraphEntry, GraphEntryAddress};
26
27use crate::history::HistoryValue;
28
29pub fn debug_print_graph_entry(
33 intro: &str,
34 graph_entry: &GraphEntry,
35 main_owner: Option<MainSecretKey>,
36) {
37 let showing_addresses = if main_owner.is_some() {
38 "\n (showing GraphEntry addresses of parents/descendents)"
39 } else {
40 ""
41 };
42
43 println!(
44 "DEBUG {intro} graph entry with address {}{showing_addresses}",
45 graph_entry.address().to_hex()
46 );
47 let parents = if graph_entry.parents.len() > 0 {
48 if main_owner.is_none() {
49 &graph_entry.parents[0].to_hex() } else {
51 let parent_public_key = graph_entry.parents[0];
52 let address = GraphEntryAddress::new(parent_public_key);
53 &address.to_hex()
54 }
55 } else {
56 ""
57 };
58
59 let descendents = if graph_entry.descendants.len() > 0 {
60 if main_owner.is_none() {
61 &graph_entry.descendants[0].0.to_hex() } else {
63 let derivation_index = get_derivation_from_graph_entry(&graph_entry);
64 let descendent_public_key = main_owner
65 .unwrap()
66 .derive_key(&derivation_index.unwrap())
67 .public_key();
68
69 let address = GraphEntryAddress::new(descendent_public_key.into());
71 &address.to_hex()
72 }
73 } else {
74 ""
75 };
76
77 println!(
78 "\n owner : {}\n parents : [{}]\n content : {}\n descendents: [{}])",
79 graph_entry.owner.to_hex(),
80 parents,
81 hex::encode(&graph_entry.content),
82 descendents
83 );
84}
85
86pub async fn graph_entry_get(
88 client: &Client,
89 graph_entry_address: &GraphEntryAddress,
90 check_exists: bool,
91) -> Result<GraphEntry> {
92 if check_exists {
95 match client
96 .graph_entry_check_existence(graph_entry_address)
97 .await
98 {
99 Ok(exists) => {
100 if !exists {
101 println!("DEBUG GraphEntry does not exist");
102 return Err(eyre!("GraphEntry does not exist"));
103 } else {
104 println!("DEBUG GraphEntry exists");
105 }
106 }
107 Err(_e) => {}
108 };
109 };
110
111 match client.graph_entry_get(graph_entry_address).await {
112 Ok(entry) => {
113 Ok(entry)
115 }
116 Err(GraphError::Fork(entries)) => {
117 println!("Forked history, {entries:?} found. Using the smallest derivation index for the next entry");
118 let (entry_by_smallest_derivation, _) = if let Some(entry) = entries
119 .into_iter()
120 .filter_map(|e| {
121 get_derivation_from_graph_entry(&e)
122 .ok()
123 .map(|derivation| (e, derivation))
124 })
125 .min_by(|a, b| a.1.cmp(&b.1))
126 {
127 entry
129 } else {
130 let msg = format!(
131 "No valid descendants found for forked entry at {graph_entry_address:?}"
132 );
133 println!("{msg}");
134 return Err(eyre!(msg));
135 };
136 Ok(entry_by_smallest_derivation)
142 }
143 Err(e) => {
144 let msg = format!("failed to get graph entry - {e}");
145 return Err(eyre!(msg));
147 }
148 }
149}
150
151pub async fn create_graph_entry(
153 history_secret_key: &SecretKey,
154 parent_entry: Option<&GraphEntry>,
155 new_derivation: &DerivationIndex,
156 new_value: ArchiveAddress,
157) -> Result<GraphEntry> {
158 println!("DEBUG create_graph_entry()");
159
160 let history_secret_key = MainSecretKey::new(history_secret_key.clone());
161 let parents = if let Some(parent_entry) = parent_entry {
162 vec![parent_entry.owner]
163 } else {
164 vec![]
165 };
166
167 let entry_secret_key: SecretKey = if parent_entry.is_none() {
168 history_secret_key.clone().into()
169 } else {
170 history_secret_key
171 .clone()
172 .derive_key(&new_derivation)
173 .into()
174 };
175 let next_public_key = history_secret_key.public_key().derive_key(new_derivation);
176 let next_derivation = DerivationIndex::random(&mut rand::thread_rng());
177 let descendants: Vec<(PublicKey, [u8; 32])> =
178 vec![(next_public_key.into(), next_derivation.into_bytes())];
179
180 println!(
181 "DEBUG entry_secret_key: {}",
182 hex::encode(&history_secret_key.to_bytes())
183 );
184 println!(
185 "DEBUG next_public_key : {}",
186 hex::encode(&next_public_key.to_bytes())
187 );
188 let parents_str = if parents.len() > 0 {
189 &parents[0].to_hex()
190 } else {
191 ""
192 };
193 println!("DEBUG creating GraphEntry::new(\n owner : {}\n parents : [{}]\n content : {}\n descendents: [{}])",
194 entry_secret_key.public_key().to_hex(), parents_str, new_value.to_hex(), descendants[0].0.to_hex() );
195
196 let new_value: HistoryValue = new_value.xorname().0;
197 let next_entry = GraphEntry::new(&entry_secret_key, parents, new_value, descendants);
198 Ok(next_entry)
205}
206
207pub async fn get_graph_entry_and_next_derivation_index(
213 client: &Client,
214 graph_entry_addr: &GraphEntryAddress,
215) -> Result<(GraphEntry, DerivationIndex)> {
216 let entry = match client.graph_entry_get(graph_entry_addr).await {
217 Ok(e) => e,
218 Err(GraphError::Fork(entries)) => {
219 println!("DEBUG Forked register, multiple entries found: {entries:?}, choosing the one with the smallest derivation index for the next entry");
220 let (entry_by_smallest_derivation, _) = entries
221 .into_iter()
222 .filter_map(|e| {
223 get_derivation_from_graph_entry(&e)
224 .ok()
225 .map(|derivation| (e, derivation))
226 })
227 .min_by(|a, b| a.1.cmp(&b.1))
228 .ok_or(eyre!(
229 "no valid descendants found for FORKED entry at {graph_entry_addr:?}"
230 ))?;
231 entry_by_smallest_derivation
232 }
233 Err(err) => return Err(err.into()),
234 };
235 let new_derivation = get_derivation_from_graph_entry(&entry)?;
236 Ok((entry, new_derivation))
237}
238
239pub fn get_derivation_from_graph_entry(entry: &GraphEntry) -> Result<DerivationIndex> {
241 let graph_entry_addr = GraphEntryAddress::new(entry.owner);
242 let d = match entry.descendants.as_slice() {
243 [d] => d.1,
244 _ => {
246 let msg = format!("History graph_entry_addr: {:?} is corrupted, expected one descendant but got {}: {:?}",
247 graph_entry_addr,
248 entry.descendants.len(),
249 entry.descendants);
250 println!("DEBUG get_derivation_from_graph_entry() failed: {msg}");
251 return Err(eyre!(msg));
252 }
253 };
254 Ok(DerivationIndex::from_bytes(d))
255}