litep2p/protocol/libp2p/kademlia/
record.rs

1// Copyright 2019 Parity Technologies (UK) Ltd.
2// Copyright 2023 litep2p developers
3//
4// Permission is hereby granted, free of charge, to any person obtaining a
5// copy of this software and associated documentation files (the "Software"),
6// to deal in the Software without restriction, including without limitation
7// the rights to use, copy, modify, merge, publish, distribute, sublicense,
8// and/or sell copies of the Software, and to permit persons to whom the
9// Software is furnished to do so, subject to the following conditions:
10//
11// The above copyright notice and this permission notice shall be included in
12// all copies or substantial portions of the Software.
13//
14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20// DEALINGS IN THE SOFTWARE.
21
22use crate::{
23    protocol::libp2p::kademlia::types::{Distance, Key as KademliaKey},
24    Multiaddr, PeerId,
25};
26
27use bytes::Bytes;
28use multihash::Multihash;
29
30use std::{borrow::Borrow, time::Instant};
31
32/// The (opaque) key of a record.
33#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
34#[derive(Clone, Debug, PartialEq, Eq, Hash)]
35pub struct Key(Bytes);
36
37impl Key {
38    /// Creates a new key from the bytes of the input.
39    pub fn new<K: AsRef<[u8]>>(key: &K) -> Self {
40        Key(Bytes::copy_from_slice(key.as_ref()))
41    }
42
43    /// Copies the bytes of the key into a new vector.
44    pub fn to_vec(&self) -> Vec<u8> {
45        Vec::from(&self.0[..])
46    }
47}
48
49impl From<Key> for Vec<u8> {
50    fn from(k: Key) -> Vec<u8> {
51        Vec::from(&k.0[..])
52    }
53}
54
55impl Borrow<[u8]> for Key {
56    fn borrow(&self) -> &[u8] {
57        &self.0[..]
58    }
59}
60
61impl AsRef<[u8]> for Key {
62    fn as_ref(&self) -> &[u8] {
63        &self.0[..]
64    }
65}
66
67impl From<Vec<u8>> for Key {
68    fn from(v: Vec<u8>) -> Key {
69        Key(Bytes::from(v))
70    }
71}
72
73impl From<Multihash> for Key {
74    fn from(m: Multihash) -> Key {
75        Key::from(m.to_bytes())
76    }
77}
78
79/// A record stored in the DHT.
80#[derive(Clone, Debug, Eq, PartialEq, Hash)]
81pub struct Record {
82    /// Key of the record.
83    pub key: Key,
84
85    /// Value of the record.
86    pub value: Vec<u8>,
87
88    /// The (original) publisher of the record.
89    pub publisher: Option<PeerId>,
90
91    /// The expiration time as measured by a local, monotonic clock.
92    pub expires: Option<Instant>,
93}
94
95impl Record {
96    /// Creates a new record for insertion into the DHT.
97    pub fn new<K>(key: K, value: Vec<u8>) -> Self
98    where
99        K: Into<Key>,
100    {
101        Record {
102            key: key.into(),
103            value,
104            publisher: None,
105            expires: None,
106        }
107    }
108
109    /// Checks whether the record is expired w.r.t. the given `Instant`.
110    pub fn is_expired(&self, now: Instant) -> bool {
111        self.expires.map_or(false, |t| now >= t)
112    }
113}
114
115/// A record received by the given peer.
116#[derive(Debug, Clone, PartialEq, Eq)]
117pub struct PeerRecord {
118    /// The peer from whom the record was received
119    pub peer: PeerId,
120
121    /// The provided record.
122    pub record: Record,
123}
124
125/// A record keeping information about a content provider.
126#[derive(Clone, Debug, Eq, PartialEq, Hash)]
127pub struct ProviderRecord {
128    /// Key of the record.
129    pub key: Key,
130
131    /// Key of the provider, based on its peer ID.
132    pub provider: PeerId,
133
134    /// Cached addresses of the provider.
135    pub addresses: Vec<Multiaddr>,
136
137    /// The expiration time of the record. The provider records must always have the expiration
138    /// time.
139    pub expires: Instant,
140}
141
142impl ProviderRecord {
143    /// The distance from the provider's peer ID to the provided key.
144    pub fn distance(&self) -> Distance {
145        // Note that the record key is raw (opaque bytes). In order to calculate the distance from
146        // the provider's peer ID to this key we must first hash both.
147        KademliaKey::from(self.provider).distance(&KademliaKey::new(self.key.clone()))
148    }
149
150    /// Checks whether the record is expired w.r.t. the given `Instant`.
151    pub fn is_expired(&self, now: Instant) -> bool {
152        now >= self.expires
153    }
154}