ant_protocol/storage/
graph.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
// Copyright 2024 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under The General Public License (GPL), version 3.
// Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed
// under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. Please review the Licences for the specific language governing
// permissions and limitations relating to use of the SAFE Network Software.

use super::address::GraphEntryAddress;
use bls::SecretKey;
use serde::{Deserialize, Serialize};

// re-exports
pub use bls::{PublicKey, Signature};

/// Content of a graph, limited to 32 bytes
pub type GraphContent = [u8; 32];

/// A generic GraphEntry on the Network.
///
/// Graph entries are stored at the owner's public key. Note that there can only be one graph entry per owner.
/// Graph entries can be linked to other graph entries as parents or descendants.
/// Applications are free to define the meaning of these links, those are not enforced by the protocol.
/// The protocol only ensures that the graph entry is immutable once uploaded and that the signature is valid and matches the owner.
///
/// For convenience it is advised to make use of BLS key derivation to create multiple graph entries from a single key.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Hash, Ord, PartialOrd)]
pub struct GraphEntry {
    /// The owner of the graph. Note that graph entries are stored at the owner's public key
    pub owner: PublicKey,
    /// Other graph entries that this graph entry refers to as parents
    pub parents: Vec<PublicKey>,
    /// The content of the graph entry
    pub content: GraphContent,
    /// Other graph entries that this graph entry refers to as descendants/outputs along with some data associated to each one
    pub descendants: Vec<(PublicKey, GraphContent)>,
    /// signs the above 4 fields with the owners key
    pub signature: Signature,
}

impl GraphEntry {
    /// Maximum size of a graph entry: 100KB
    pub const MAX_SIZE: usize = 100 * 1024;

    /// Create a new graph entry, signing it with the provided secret key.
    pub fn new(
        owner: &SecretKey,
        parents: Vec<PublicKey>,
        content: GraphContent,
        descendants: Vec<(PublicKey, GraphContent)>,
    ) -> Self {
        let key = owner;
        let owner = key.public_key();
        let signature = key.sign(Self::bytes_to_sign(
            &owner,
            &parents,
            &content,
            &descendants,
        ));
        Self {
            owner,
            parents,
            content,
            descendants,
            signature,
        }
    }

    /// Create a new graph entry, with the signature already calculated.
    pub fn new_with_signature(
        owner: PublicKey,
        parents: Vec<PublicKey>,
        content: GraphContent,
        descendants: Vec<(PublicKey, GraphContent)>,
        signature: Signature,
    ) -> Self {
        Self {
            owner,
            parents,
            content,
            descendants,
            signature,
        }
    }

    /// Get the bytes that the signature is calculated from.
    pub fn bytes_to_sign(
        owner: &PublicKey,
        parents: &[PublicKey],
        content: &[u8],
        descendants: &[(PublicKey, GraphContent)],
    ) -> Vec<u8> {
        let mut bytes = Vec::new();
        bytes.extend_from_slice(&owner.to_bytes());
        bytes.extend_from_slice("parent".as_bytes());
        bytes.extend_from_slice(
            &parents
                .iter()
                .map(|p| p.to_bytes())
                .collect::<Vec<_>>()
                .concat(),
        );
        bytes.extend_from_slice("content".as_bytes());
        bytes.extend_from_slice(content);
        bytes.extend_from_slice("descendants".as_bytes());
        bytes.extend_from_slice(
            &descendants
                .iter()
                .flat_map(|(p, c)| [&p.to_bytes(), c.as_slice()].concat())
                .collect::<Vec<_>>(),
        );
        bytes
    }

    pub fn address(&self) -> GraphEntryAddress {
        GraphEntryAddress::from_owner(self.owner)
    }

    /// Get the bytes that the signature is calculated from.
    pub fn bytes_for_signature(&self) -> Vec<u8> {
        Self::bytes_to_sign(&self.owner, &self.parents, &self.content, &self.descendants)
    }

    /// Verify the signature of the graph entry
    pub fn verify_signature(&self) -> bool {
        self.owner
            .verify(&self.signature, self.bytes_for_signature())
    }

    /// Size of the graph entry
    pub fn size(&self) -> usize {
        size_of::<GraphEntry>()
            + self
                .descendants
                .iter()
                .map(|(p, c)| p.to_bytes().len() + c.len())
                .sum::<usize>()
            + self
                .parents
                .iter()
                .map(|p| p.to_bytes().len())
                .sum::<usize>()
    }

    /// Returns true if the graph entry is too big
    pub fn is_too_big(&self) -> bool {
        self.size() > Self::MAX_SIZE
    }
}