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}