everscale_network/dht/
entry.rs1use std::borrow::{Borrow, Cow};
2use std::sync::Arc;
3
4use anyhow::Result;
5use tl_proto::BoxedConstructor;
6
7use super::futures::StoreValue;
8use super::node::Node;
9use super::streams::DhtValuesStream;
10use crate::adnl;
11use crate::proto;
12use crate::util::now;
13
14#[must_use]
16#[derive(Copy, Clone)]
17pub struct Entry<'a> {
18 dht: &'a Arc<Node>,
19 id: &'a [u8; 32],
20 name: &'a str,
21 key_index: u32,
22}
23
24impl<'a> Entry<'a> {
25 pub(super) fn new<T>(dht: &'a Arc<Node>, id: &'a T, name: &'a str) -> Self
26 where
27 T: Borrow<[u8; 32]>,
28 {
29 Self {
30 dht,
31 id: id.borrow(),
32 name,
33 key_index: 0,
34 }
35 }
36
37 pub fn with_key_index(mut self, idx: u32) -> Self {
39 self.key_index = idx;
40 self
41 }
42
43 pub fn with_data<T>(self, data: T) -> EntryWithData<'a>
49 where
50 T: tl_proto::TlWrite<Repr = tl_proto::Boxed>,
51 {
52 EntryWithData {
53 inner: self,
54 data: Cow::Owned(tl_proto::serialize(data)),
55 expire_at: None,
56 }
57 }
58
59 pub fn with_data_raw(self, data: &'a [u8]) -> EntryWithData<'a> {
65 EntryWithData {
66 inner: self,
67 data: Cow::Borrowed(data),
68 expire_at: None,
69 }
70 }
71
72 pub fn values<T>(self) -> DhtValuesStream<T>
74 where
75 for<'tl> T: tl_proto::TlRead<'tl, Repr = tl_proto::Boxed> + Send + 'static,
76 {
77 DhtValuesStream::new(self.dht.clone(), self.key())
78 }
79
80 pub async fn value_from<T>(
82 self,
83 peer_id: &adnl::NodeIdShort,
84 ) -> Result<Option<(proto::dht::KeyDescriptionOwned, T)>>
85 where
86 for<'tl> T: tl_proto::TlRead<'tl, Repr = tl_proto::Boxed> + Send + 'static,
87 {
88 let key_id = tl_proto::hash_as_boxed(self.key());
89 let query = tl_proto::serialize(proto::rpc::DhtFindValue { key: &key_id, k: 6 }).into();
90
91 match self.dht.query_raw(peer_id, query).await? {
92 Some(result) => self.dht.parse_value_result(&result),
93 None => Ok(None),
94 }
95 }
96
97 pub fn key(&self) -> proto::dht::Key<'a> {
99 proto::dht::Key {
100 id: self.id,
101 name: self.name.as_bytes(),
102 idx: self.key_index,
103 }
104 }
105}
106
107pub struct EntryWithData<'a> {
108 inner: Entry<'a>,
109 data: Cow<'a, [u8]>,
110 expire_at: Option<u32>,
111}
112
113impl<'a> EntryWithData<'a> {
114 pub fn expire_at(mut self, timestamp: u32) -> Self {
116 self.expire_at = Some(timestamp);
117 self
118 }
119
120 pub fn with_ttl(mut self, ttl: u32) -> Self {
122 self.expire_at = Some(now() + ttl);
123 self
124 }
125
126 pub fn sign(self, key: &adnl::Key) -> proto::dht::ValueOwned {
128 let mut value = self.make_value(key);
129
130 let key_signature = key.sign(value.key.as_boxed());
131 value.key.signature = &key_signature;
132
133 let value_signature = key.sign(value.as_boxed());
134 value.signature = &value_signature;
135
136 value.as_equivalent_owned()
137 }
138
139 pub fn sign_and_store(self, key: &adnl::Key) -> Result<StoreValue> {
143 let mut value = self.make_value(key);
144
145 let key_signature = key.sign(value.key.as_boxed());
146 value.key.signature = &key_signature;
147
148 let value_signature = key.sign(value.as_boxed());
149 value.signature = &value_signature;
150
151 StoreValue::new(self.inner.dht.clone(), value)
152 }
153
154 fn make_value<'b>(&'b self, key: &'b adnl::Key) -> proto::dht::Value<'b>
155 where
156 'a: 'b,
157 {
158 proto::dht::Value {
159 key: proto::dht::KeyDescription {
160 key: self.inner.key(),
161 id: key.full_id().as_tl(),
162 update_rule: proto::dht::UpdateRule::Signature,
163 signature: Default::default(),
164 },
165 value: &self.data,
166 ttl: self
167 .expire_at
168 .unwrap_or_else(|| now() + self.inner.dht.options().value_ttl_sec),
169 signature: Default::default(),
170 }
171 }
172}