ant_protocol/storage/
pointer.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 crate::storage::{ChunkAddress, GraphEntryAddress, PointerAddress, ScratchpadAddress};
10use bls::{PublicKey, SecretKey, Signature};
11use serde::{Deserialize, Serialize};
12use xor_name::XorName;
13
14/// Pointer, a mutable address pointing to other data on the Network
15/// It is stored at the owner's public key and can only be updated by the owner
16#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Ord, PartialOrd)]
17pub struct Pointer {
18    owner: PublicKey,
19    counter: u32,
20    target: PointerTarget,
21    signature: Signature,
22}
23
24#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Ord, PartialOrd)]
25pub enum PointerTarget {
26    ChunkAddress(ChunkAddress),
27    GraphEntryAddress(GraphEntryAddress),
28    PointerAddress(PointerAddress),
29    ScratchpadAddress(ScratchpadAddress),
30}
31
32impl PointerTarget {
33    /// Returns the xorname of the target
34    pub fn xorname(&self) -> XorName {
35        match self {
36            PointerTarget::ChunkAddress(addr) => *addr.xorname(),
37            PointerTarget::GraphEntryAddress(addr) => addr.xorname(),
38            PointerTarget::PointerAddress(addr) => addr.xorname(),
39            PointerTarget::ScratchpadAddress(addr) => addr.xorname(),
40        }
41    }
42
43    /// Returns the hex string representation of the target
44    pub fn to_hex(&self) -> String {
45        match self {
46            PointerTarget::ChunkAddress(addr) => addr.to_hex(),
47            PointerTarget::GraphEntryAddress(addr) => addr.to_hex(),
48            PointerTarget::PointerAddress(addr) => addr.to_hex(),
49            PointerTarget::ScratchpadAddress(addr) => addr.to_hex(),
50        }
51    }
52}
53
54impl Pointer {
55    /// Create a new pointer, signing it with the provided secret key.
56    /// This pointer would be stored on the network at the provided key's public key.
57    /// There can only be one pointer at a time at the same address (one per key).
58    pub fn new(owner: &SecretKey, counter: u32, target: PointerTarget) -> Self {
59        let pubkey = owner.public_key();
60        let bytes_to_sign = Self::bytes_to_sign(&pubkey, counter, &target);
61        let signature = owner.sign(&bytes_to_sign);
62
63        Self {
64            owner: pubkey,
65            counter,
66            target,
67            signature,
68        }
69    }
70
71    /// Create a new pointer with an existing signature
72    pub fn new_with_signature(
73        owner: PublicKey,
74        counter: u32,
75        target: PointerTarget,
76        signature: Signature,
77    ) -> Self {
78        Self {
79            owner,
80            counter,
81            target,
82            signature,
83        }
84    }
85
86    /// Get the bytes that the signature is calculated from
87    fn bytes_to_sign(owner: &PublicKey, counter: u32, target: &PointerTarget) -> Vec<u8> {
88        let mut bytes = Vec::new();
89        // Add owner public key bytes
90        bytes.extend_from_slice(&owner.to_bytes());
91        // Add counter
92        bytes.extend_from_slice(&counter.to_le_bytes());
93        // Add target bytes using MessagePack serialization
94        if let Ok(target_bytes) = rmp_serde::to_vec(target) {
95            bytes.extend_from_slice(&target_bytes);
96        }
97        bytes
98    }
99
100    /// Get the address of the pointer
101    pub fn address(&self) -> PointerAddress {
102        PointerAddress::new(self.owner)
103    }
104
105    /// Get the owner of the pointer
106    pub fn owner(&self) -> &PublicKey {
107        &self.owner
108    }
109
110    /// Get the target of the pointer
111    pub fn target(&self) -> &PointerTarget {
112        &self.target
113    }
114
115    /// Get the bytes that were signed for this pointer
116    pub fn bytes_for_signature(&self) -> Vec<u8> {
117        Self::bytes_to_sign(&self.owner, self.counter, &self.target)
118    }
119
120    pub fn xorname(&self) -> XorName {
121        self.target.xorname()
122    }
123
124    /// Get the counter of the pointer, the higher the counter, the more recent the pointer is
125    /// Similarly to counter CRDTs only the latest version (highest counter) of the pointer is kept on the network
126    pub fn counter(&self) -> u32 {
127        self.counter
128    }
129
130    /// Verifies if the pointer has a valid signature
131    pub fn verify_signature(&self) -> bool {
132        let bytes = self.bytes_for_signature();
133        self.owner.verify(&self.signature, &bytes)
134    }
135
136    /// Size of the pointer
137    pub fn size() -> usize {
138        size_of::<Pointer>()
139    }
140}
141
142#[cfg(test)]
143mod tests {
144    use super::*;
145
146    #[test]
147    fn test_pointer_creation_and_validation() {
148        let owner_sk = SecretKey::random();
149        let counter = 1;
150        let pk = SecretKey::random().public_key();
151        let target = PointerTarget::GraphEntryAddress(GraphEntryAddress::new(pk));
152
153        // Create and sign pointer
154        let pointer = Pointer::new(&owner_sk, counter, target.clone());
155        assert!(pointer.verify_signature()); // Should be valid with correct signature
156
157        // Create pointer with wrong signature
158        let wrong_sk = SecretKey::random();
159        let sig = wrong_sk.sign(pointer.bytes_for_signature());
160        let wrong_pointer =
161            Pointer::new_with_signature(owner_sk.public_key(), counter, target.clone(), sig);
162        assert!(!wrong_pointer.verify_signature()); // Should be invalid with wrong signature
163    }
164}