1use crate::storage::{ChunkAddress, GraphEntryAddress, PointerAddress, ScratchpadAddress};
10use bls::{PublicKey, SecretKey, Signature};
11use serde::{Deserialize, Serialize};
12use xor_name::XorName;
13
14#[derive(Clone, Serialize, Deserialize, PartialEq, Eq, Ord, PartialOrd)]
17pub struct Pointer {
18 owner: PublicKey,
19 counter: u64,
20 target: PointerTarget,
21 signature: Signature,
22}
23
24impl std::fmt::Debug for Pointer {
25 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
26 f.debug_struct("Pointer")
27 .field("owner", &self.owner.to_hex())
28 .field("counter", &self.counter)
29 .field("target", &self.target)
30 .field("signature", &hex::encode(self.signature.to_bytes()))
31 .finish()
32 }
33}
34
35#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Ord, PartialOrd)]
37pub enum PointerTarget {
38 ChunkAddress(ChunkAddress),
39 GraphEntryAddress(GraphEntryAddress),
40 PointerAddress(PointerAddress),
41 ScratchpadAddress(ScratchpadAddress),
42}
43
44impl PointerTarget {
45 pub fn xorname(&self) -> XorName {
47 match self {
48 PointerTarget::ChunkAddress(addr) => *addr.xorname(),
49 PointerTarget::GraphEntryAddress(addr) => addr.xorname(),
50 PointerTarget::PointerAddress(addr) => addr.xorname(),
51 PointerTarget::ScratchpadAddress(addr) => addr.xorname(),
52 }
53 }
54
55 pub fn to_hex(&self) -> String {
57 match self {
58 PointerTarget::ChunkAddress(addr) => addr.to_hex(),
59 PointerTarget::GraphEntryAddress(addr) => addr.to_hex(),
60 PointerTarget::PointerAddress(addr) => addr.to_hex(),
61 PointerTarget::ScratchpadAddress(addr) => addr.to_hex(),
62 }
63 }
64}
65
66impl Pointer {
67 pub fn new(owner: &SecretKey, counter: u64, target: PointerTarget) -> Self {
71 let pubkey = owner.public_key();
72 let bytes_to_sign = Self::bytes_to_sign(&pubkey, counter, &target);
73 let signature = owner.sign(&bytes_to_sign);
74
75 Self {
76 owner: pubkey,
77 counter,
78 target,
79 signature,
80 }
81 }
82
83 pub fn new_with_signature(
85 owner: PublicKey,
86 counter: u64,
87 target: PointerTarget,
88 signature: Signature,
89 ) -> Self {
90 Self {
91 owner,
92 counter,
93 target,
94 signature,
95 }
96 }
97
98 fn bytes_to_sign(owner: &PublicKey, counter: u64, target: &PointerTarget) -> Vec<u8> {
100 let counter_bytes: Vec<u8> = if counter > u32::MAX as u64 {
103 counter.to_le_bytes().to_vec()
104 } else {
105 let u32_counter = counter as u32;
106 u32_counter.to_le_bytes().to_vec()
107 };
108
109 let mut bytes = Vec::new();
110 bytes.extend_from_slice(&owner.to_bytes());
112 bytes.extend_from_slice(&counter_bytes);
114 if let Ok(target_bytes) = rmp_serde::to_vec(target) {
116 bytes.extend_from_slice(&target_bytes);
117 }
118 bytes
119 }
120
121 pub fn address(&self) -> PointerAddress {
123 PointerAddress::new(self.owner)
124 }
125
126 pub fn owner(&self) -> &PublicKey {
128 &self.owner
129 }
130
131 pub fn target(&self) -> &PointerTarget {
133 &self.target
134 }
135
136 pub fn bytes_for_signature(&self) -> Vec<u8> {
138 Self::bytes_to_sign(&self.owner, self.counter, &self.target)
139 }
140
141 pub fn xorname(&self) -> XorName {
142 self.address().xorname()
143 }
144
145 pub fn counter(&self) -> u64 {
148 self.counter
149 }
150
151 pub fn verify_signature(&self) -> bool {
153 let bytes = self.bytes_for_signature();
154 self.owner.verify(&self.signature, &bytes)
155 }
156
157 pub fn size() -> usize {
159 size_of::<Pointer>()
160 }
161}
162
163#[cfg(test)]
164mod tests {
165 use super::*;
166
167 #[test]
168 fn test_pointer_creation_and_validation() {
169 let owner_sk = SecretKey::random();
170 let counter = 1;
171 let pk = SecretKey::random().public_key();
172 let target = PointerTarget::GraphEntryAddress(GraphEntryAddress::new(pk));
173
174 let pointer = Pointer::new(&owner_sk, counter, target.clone());
176 assert!(pointer.verify_signature()); let wrong_sk = SecretKey::random();
180 let sig = wrong_sk.sign(pointer.bytes_for_signature());
181 let wrong_pointer =
182 Pointer::new_with_signature(owner_sk.public_key(), counter, target.clone(), sig);
183 assert!(!wrong_pointer.verify_signature()); }
185
186 #[test]
187 fn test_pointer_deserialize_counter_compatibility() {
188 #[derive(Serialize, Deserialize)]
189 struct OldPointer {
190 owner: PublicKey,
191 counter: u32,
192 target: PointerTarget,
193 signature: Signature,
194 }
195 fn bytes_to_sign_old_pointer(
196 owner: &PublicKey,
197 counter: u32,
198 target: &PointerTarget,
199 ) -> Vec<u8> {
200 let mut bytes = Vec::new();
201 bytes.extend_from_slice(&owner.to_bytes());
203 bytes.extend_from_slice(&counter.to_le_bytes());
205 if let Ok(target_bytes) = rmp_serde::to_vec(target) {
207 bytes.extend_from_slice(&target_bytes);
208 }
209 bytes
210 }
211
212 let xor = XorName::random(&mut rand::thread_rng());
213 let sk = SecretKey::random();
214 let old_pointer = OldPointer {
215 owner: sk.public_key(),
216 counter: 42u32,
217 target: PointerTarget::ChunkAddress(ChunkAddress::new(xor)),
218 signature: sk.sign(bytes_to_sign_old_pointer(
219 &sk.public_key(),
220 42u32,
221 &PointerTarget::ChunkAddress(ChunkAddress::new(xor)),
222 )),
223 };
224
225 let serialized_old =
227 rmp_serde::to_vec(&old_pointer).expect("Failed to serialize old pointer");
228
229 let deserialized_as_new: Pointer =
231 rmp_serde::from_slice(&serialized_old).expect("Failed to deserialize");
232
233 assert_eq!(deserialized_as_new.counter(), 42u64);
235 assert_eq!(deserialized_as_new.owner(), &old_pointer.owner);
236 assert_eq!(deserialized_as_new.target(), &old_pointer.target);
237 assert_eq!(deserialized_as_new.signature, old_pointer.signature);
238
239 let new_pointer =
241 Pointer::new(&sk, 42, PointerTarget::ChunkAddress(ChunkAddress::new(xor)));
242
243 let serialized_new =
245 rmp_serde::to_vec(&new_pointer).expect("Failed to serialize new pointer");
246
247 let deserialized_new: Pointer =
249 rmp_serde::from_slice(&serialized_new).expect("Failed to deserialize");
250
251 assert_eq!(deserialized_new.counter(), 42u64);
253 assert_eq!(deserialized_new.owner(), &new_pointer.owner);
254 assert_eq!(deserialized_new.target(), &new_pointer.target);
255 assert_eq!(deserialized_new.signature, new_pointer.signature);
256
257 let deserialized_as_old: OldPointer =
259 rmp_serde::from_slice(&serialized_new).expect("Failed to deserialize");
260
261 assert_eq!(deserialized_as_old.counter, 42u32);
263 assert_eq!(deserialized_as_old.owner, new_pointer.owner);
264 assert_eq!(deserialized_as_old.target, new_pointer.target);
265 assert_eq!(deserialized_as_old.signature, new_pointer.signature);
266
267 assert_eq!(old_pointer.counter as u64, new_pointer.counter);
269 assert_eq!(old_pointer.owner, new_pointer.owner);
270 assert_eq!(old_pointer.target, new_pointer.target);
271
272 assert_eq!(old_pointer.signature, new_pointer.signature);
274 }
275}