ant_protocol/storage/graph.rs
1// Copyright 2024 MaidSafe.net limited.
2//
3// This SAFE Network Software is licensed to you under The General Public License (GPL), version 3.
4// Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed
5// under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
6// KIND, either express or implied. Please review the Licences for the specific language governing
7// permissions and limitations relating to use of the SAFE Network Software.
8
9use super::address::GraphEntryAddress;
10use bls::SecretKey;
11use serde::{Deserialize, Serialize};
12
13// re-exports
14pub use bls::{PublicKey, Signature};
15
16/// Content of a graph, limited to 32 bytes
17pub type GraphContent = [u8; 32];
18
19/// A generic GraphEntry on the Network.
20///
21/// Graph entries are stored at the owner's public key. Note that there can only be one graph entry per owner.
22/// Graph entries can be linked to other graph entries as parents or descendants.
23/// Applications are free to define the meaning of these links, those are not enforced by the protocol.
24/// The protocol only ensures that the graph entry is immutable once uploaded and that the signature is valid and matches the owner.
25///
26/// For convenience it is advised to make use of BLS key derivation to create multiple graph entries from a single key.
27#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Hash, Ord, PartialOrd)]
28pub struct GraphEntry {
29 /// The owner of the graph. Note that graph entries are stored at the owner's public key
30 pub owner: PublicKey,
31 /// Other graph entries that this graph entry refers to as parents
32 pub parents: Vec<PublicKey>,
33 /// The content of the graph entry
34 pub content: GraphContent,
35 /// Other graph entries that this graph entry refers to as descendants/outputs along with some data associated to each one
36 pub descendants: Vec<(PublicKey, GraphContent)>,
37 /// signs the above 4 fields with the owners key
38 pub signature: Signature,
39}
40
41impl GraphEntry {
42 /// Maximum size of a graph entry: 100KB
43 pub const MAX_SIZE: usize = 100 * 1024;
44
45 /// Create a new graph entry, signing it with the provided secret key.
46 pub fn new(
47 owner: &SecretKey,
48 parents: Vec<PublicKey>,
49 content: GraphContent,
50 descendants: Vec<(PublicKey, GraphContent)>,
51 ) -> Self {
52 let key = owner;
53 let owner = key.public_key();
54 let signature = key.sign(Self::bytes_to_sign(
55 &owner,
56 &parents,
57 &content,
58 &descendants,
59 ));
60 Self {
61 owner,
62 parents,
63 content,
64 descendants,
65 signature,
66 }
67 }
68
69 /// Create a new graph entry, with the signature already calculated.
70 pub fn new_with_signature(
71 owner: PublicKey,
72 parents: Vec<PublicKey>,
73 content: GraphContent,
74 descendants: Vec<(PublicKey, GraphContent)>,
75 signature: Signature,
76 ) -> Self {
77 Self {
78 owner,
79 parents,
80 content,
81 descendants,
82 signature,
83 }
84 }
85
86 /// Get the bytes that the signature is calculated from.
87 pub fn bytes_to_sign(
88 owner: &PublicKey,
89 parents: &[PublicKey],
90 content: &[u8],
91 descendants: &[(PublicKey, GraphContent)],
92 ) -> Vec<u8> {
93 let mut bytes = Vec::new();
94 bytes.extend_from_slice(&owner.to_bytes());
95 bytes.extend_from_slice("parent".as_bytes());
96 bytes.extend_from_slice(
97 &parents
98 .iter()
99 .map(|p| p.to_bytes())
100 .collect::<Vec<_>>()
101 .concat(),
102 );
103 bytes.extend_from_slice("content".as_bytes());
104 bytes.extend_from_slice(content);
105 bytes.extend_from_slice("descendants".as_bytes());
106 bytes.extend_from_slice(
107 &descendants
108 .iter()
109 .flat_map(|(p, c)| [&p.to_bytes(), c.as_slice()].concat())
110 .collect::<Vec<_>>(),
111 );
112 bytes
113 }
114
115 pub fn address(&self) -> GraphEntryAddress {
116 GraphEntryAddress::new(self.owner)
117 }
118
119 /// Get the bytes that the signature is calculated from.
120 pub fn bytes_for_signature(&self) -> Vec<u8> {
121 Self::bytes_to_sign(&self.owner, &self.parents, &self.content, &self.descendants)
122 }
123
124 /// Verify the signature of the graph entry
125 pub fn verify_signature(&self) -> bool {
126 self.owner
127 .verify(&self.signature, self.bytes_for_signature())
128 }
129
130 /// Size of the graph entry
131 pub fn size(&self) -> usize {
132 size_of::<GraphEntry>()
133 + self
134 .descendants
135 .iter()
136 .map(|(p, c)| p.to_bytes().len() + c.len())
137 .sum::<usize>()
138 + self
139 .parents
140 .iter()
141 .map(|p| p.to_bytes().len())
142 .sum::<usize>()
143 }
144
145 /// Returns true if the graph entry is too big
146 pub fn is_too_big(&self) -> bool {
147 self.size() > Self::MAX_SIZE
148 }
149}