1use std::{
71 collections::{BTreeMap, BTreeSet, HashSet, VecDeque},
72 sync::Arc,
73 time::{Duration, UNIX_EPOCH},
74};
75
76use futures_buffered::FuturesUnordered;
77use indexmap::IndexSet;
78use iroh::NodeId;
79use irpc::channel::{mpsc, oneshot};
80use n0_future::{BufferedStreamExt, MaybeFuture, StreamExt, stream};
81use rand::{Rng, SeedableRng, rngs::StdRng, seq::index::sample};
82use serde::{Deserialize, Serialize};
83use tokio::task::JoinSet;
84#[cfg(test)]
85mod tests;
86pub mod rpc {
87 use std::{
99 fmt,
100 num::NonZeroU64,
101 ops::Deref,
102 sync::{Arc, Weak},
103 };
104
105 use iroh::{Endpoint, NodeAddr, NodeId, PublicKey};
106 use iroh_base::SignatureError;
107 use irpc::{
108 channel::{mpsc, oneshot},
109 rpc_requests,
110 };
111 use serde::{Deserialize, Serialize};
112 use serde_big_array::BigArray;
113
114 pub const ALPN: &[u8] = b"iroh/dht/0";
115
116 #[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
121 pub struct Blake3Provider {
122 timestamp: u64, node_id: [u8; 32],
124 }
125
126 #[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
128 pub struct Blake3Immutable {
129 pub timestamp: u64, pub data: Vec<u8>,
131 }
132
133 #[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
137 pub struct ED25519SignedMessage {
138 pub timestamp: u64,
140 #[serde(with = "BigArray")]
142 pub signature: [u8; 64],
143 pub data: Vec<u8>,
147 }
148
149 #[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
153 pub enum Value {
154 Blake3Provider(Blake3Provider),
155 ED25519SignedMessage(ED25519SignedMessage),
156 Blake3Immutable(Blake3Immutable),
157 }
158
159 impl Value {
160 pub fn kind(&self) -> Kind {
162 match self {
163 Value::Blake3Provider(_) => Kind::Blake3Provider,
164 Value::ED25519SignedMessage(_) => Kind::ED25519SignedMessage,
165 Value::Blake3Immutable(_) => Kind::Blake3Immutable,
166 }
167 }
168 }
169
170 #[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
174 pub enum Kind {
175 Blake3Provider,
176 ED25519SignedMessage,
177 Blake3Immutable,
178 }
179
180 #[derive(Clone, Copy, Ord, PartialOrd, PartialEq, Eq, Hash, Serialize, Deserialize)]
183 pub struct Id([u8; 32]); impl From<[u8; 32]> for Id {
186 fn from(bytes: [u8; 32]) -> Self {
187 Id(bytes)
188 }
189 }
190
191 impl Deref for Id {
192 type Target = [u8; 32];
193
194 fn deref(&self) -> &Self::Target {
195 &self.0
196 }
197 }
198
199 impl fmt::Debug for Id {
200 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
201 write!(f, "Id({})", hex::encode(self.0))
202 }
203 }
204
205 impl fmt::Display for Id {
206 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
207 write!(f, "{}", hex::encode(self.0))
208 }
209 }
210
211 impl From<PublicKey> for Id {
212 fn from(pk: PublicKey) -> Self {
213 Id(*pk.as_bytes())
214 }
215 }
216
217 impl From<blake3::Hash> for Id {
218 fn from(pk: blake3::Hash) -> Self {
219 Id(*pk.as_bytes())
220 }
221 }
222
223 impl Id {
224 pub fn blake3_hash(data: &[u8]) -> Self {
225 let hash = blake3::hash(data);
226 Id(hash.into())
227 }
228
229 pub fn node_id(id: iroh::NodeId) -> Self {
230 Id::from(*id.as_bytes())
231 }
232 }
233
234 #[derive(Debug, Serialize, Deserialize)]
242 pub struct Set {
243 pub key: Id,
245 pub value: Value,
247 }
248
249 #[derive(Debug, Serialize, Deserialize)]
250 pub enum SetResponse {
251 Ok,
253 ErrDistance,
255 ErrExpired,
257 ErrFull,
259 ErrInvalid,
261 }
262
263 #[derive(Debug, Serialize, Deserialize)]
265 pub struct GetAll {
266 pub key: Id,
268 pub kind: Kind,
270 pub seed: Option<NonZeroU64>,
273 pub n: Option<NonZeroU64>,
277 }
278
279 #[derive(Debug, Serialize, Deserialize)]
281 pub struct FindNode {
282 pub id: Id,
284 pub requester: Option<NodeId>,
289 }
290
291 #[rpc_requests(message = RpcMessage)]
298 #[derive(Debug, Serialize, Deserialize)]
299 pub enum RpcProto {
300 #[rpc(tx = oneshot::Sender<SetResponse>)]
302 Set(Set),
303 #[rpc(tx = mpsc::Sender<Value>)]
305 GetAll(GetAll),
306 #[rpc(tx = oneshot::Sender<Vec<NodeAddr>>)]
308 FindNode(FindNode),
309 }
310
311 #[derive(Debug, Clone)]
312 pub struct RpcClient(pub(crate) Arc<irpc::Client<RpcProto>>);
313
314 #[derive(Debug, Clone)]
315 pub struct WeakRpcClient(pub(crate) Weak<irpc::Client<RpcProto>>);
316
317 impl WeakRpcClient {
318 pub fn upgrade(&self) -> Option<RpcClient> {
319 self.0.upgrade().map(RpcClient)
320 }
321 }
322
323 impl RpcClient {
324 pub fn remote(endpoint: Endpoint, id: Id) -> std::result::Result<Self, SignatureError> {
325 let id = iroh::NodeId::from_bytes(&id)?;
326 let client = irpc_iroh::client(endpoint, id, ALPN);
327 Ok(Self::new(client))
328 }
329
330 pub fn new(client: irpc::Client<RpcProto>) -> Self {
331 Self(Arc::new(client))
332 }
333
334 pub async fn set(&self, key: Id, value: Value) -> irpc::Result<SetResponse> {
335 self.0.rpc(Set { key, value }).await
336 }
337
338 pub async fn get_all(
339 &self,
340 key: Id,
341 kind: Kind,
342 seed: Option<NonZeroU64>,
343 n: Option<NonZeroU64>,
344 ) -> irpc::Result<irpc::channel::mpsc::Receiver<Value>> {
345 self.0
346 .server_streaming(GetAll { key, kind, seed, n }, 32)
347 .await
348 }
349
350 pub async fn find_node(
351 &self,
352 id: Id,
353 requester: Option<NodeId>,
354 ) -> irpc::Result<Vec<NodeAddr>> {
355 self.0.rpc(FindNode { id, requester }).await
356 }
357
358 pub fn downgrade(&self) -> WeakRpcClient {
359 WeakRpcClient(Arc::downgrade(&self.0))
360 }
361 }
362}
363
364pub mod api {
365 use std::{
374 collections::BTreeMap,
375 num::NonZeroU64,
376 sync::{Arc, Weak},
377 time::Duration,
378 };
379
380 use iroh::NodeId;
381 use irpc::{
382 channel::{mpsc, none::NoSender, oneshot},
383 rpc_requests,
384 };
385 use serde::{Deserialize, Serialize};
386
387 use crate::{
388 now,
389 routing::NodeInfo,
390 rpc::{Blake3Immutable, Id, Kind, Value},
391 };
392
393 #[rpc_requests(message = ApiMessage)]
394 #[derive(Debug, Serialize, Deserialize)]
395 pub enum ApiProto {
396 #[rpc(tx = NoSender)]
399 #[wrap(NodesSeen)]
400 NodesSeen { ids: Vec<NodeId> },
401 #[rpc(tx = NoSender)]
404 #[wrap(NodesDead)]
405 NodesDead { ids: Vec<NodeId> },
406 #[rpc(tx = oneshot::Sender<Vec<NodeId>>)]
407 #[wrap(Lookup)]
408 Lookup {
409 initial: Option<Vec<NodeId>>,
410 id: Id,
411 },
412 #[rpc(tx = mpsc::Sender<NodeId>)]
413 #[wrap(NetworkPut)]
414 NetworkPut { id: Id, value: Value },
415 #[rpc(tx = mpsc::Sender<(NodeId, Value)>)]
416 #[wrap(NetworkGet)]
417 NetworkGet {
418 id: Id,
419 kind: Kind,
420 seed: Option<NonZeroU64>,
421 n: Option<NonZeroU64>,
422 },
423 #[rpc(tx = oneshot::Sender<Vec<Vec<NodeInfo>>>)]
425 #[wrap(GetRoutingTable)]
426 GetRoutingTable,
427 #[rpc(tx = oneshot::Sender<BTreeMap<Id, BTreeMap<Kind, usize>>>)]
429 #[wrap(GetStorageStats)]
430 GetStorageStats,
431 #[rpc(tx = oneshot::Sender<()>)]
433 #[wrap(SelfLookup)]
434 SelfLookup,
435 #[rpc(tx = oneshot::Sender<()>)]
437 #[wrap(RandomLookup)]
438 RandomLookup,
439 #[rpc(tx = oneshot::Sender<()>)]
441 #[wrap(CandidateLookup)]
442 CandidateLookup,
443 }
444
445 #[derive(Debug, Clone)]
446 pub struct ApiClient(pub(crate) Arc<irpc::Client<ApiProto>>);
447
448 impl ApiClient {
449 pub async fn nodes_seen(&self, ids: &[NodeId]) -> irpc::Result<()> {
453 self.0.notify(NodesSeen { ids: ids.to_vec() }).await
454 }
455
456 pub async fn nodes_dead(&self, ids: &[NodeId]) -> irpc::Result<()> {
460 self.0.notify(NodesDead { ids: ids.to_vec() }).await
461 }
462
463 pub async fn get_storage_stats(&self) -> irpc::Result<BTreeMap<Id, BTreeMap<Kind, usize>>> {
464 self.0.rpc(GetStorageStats).await
465 }
466
467 pub async fn get_routing_table(&self) -> irpc::Result<Vec<Vec<NodeInfo>>> {
468 self.0.rpc(GetRoutingTable).await
469 }
470
471 pub async fn lookup(
472 &self,
473 id: Id,
474 initial: Option<Vec<NodeId>>,
475 ) -> irpc::Result<Vec<NodeId>> {
476 self.0.rpc(Lookup { id, initial }).await
477 }
478
479 pub async fn get_immutable(&self, hash: blake3::Hash) -> irpc::Result<Option<Vec<u8>>> {
480 let id = Id::from(*hash.as_bytes());
481 let mut rx = self
482 .0
483 .server_streaming(
484 NetworkGet {
485 id,
486 kind: Kind::Blake3Immutable,
487 seed: None,
488 n: Some(NonZeroU64::new(1).unwrap()),
489 },
490 32,
491 )
492 .await?;
493 loop {
494 match rx.recv().await {
495 Ok(Some((_, value))) => {
496 let Value::Blake3Immutable(Blake3Immutable { data, .. }) = value else {
497 continue; };
499 if blake3::hash(&data) == hash {
500 return Ok(Some(data));
501 } else {
502 continue; }
504 }
505 Ok(None) => {
506 break Ok(None);
507 }
508 Err(e) => {
509 break Err(e.into());
510 }
511 }
512 }
513 }
514
515 pub async fn put_immutable(
516 &self,
517 value: &[u8],
518 ) -> irpc::Result<(blake3::Hash, Vec<NodeId>)> {
519 let hash = blake3::hash(value);
520 let id = Id::from(*hash.as_bytes());
521 let mut rx = self
522 .0
523 .server_streaming(
524 NetworkPut {
525 id,
526 value: Value::Blake3Immutable(Blake3Immutable {
527 timestamp: now(),
528 data: value.to_vec(),
529 }),
530 },
531 32,
532 )
533 .await?;
534 let mut res = Vec::new();
535 loop {
536 match rx.recv().await {
537 Ok(Some(id)) => res.push(id),
538 Ok(None) => break,
539 Err(_) => {}
540 }
541 }
542 Ok((hash, res))
543 }
544
545 pub async fn self_lookup(&self) {
546 self.0.rpc(SelfLookup).await.ok();
547 }
548
549 pub async fn random_lookup(&self) {
550 self.0.rpc(RandomLookup).await.ok();
551 }
552
553 pub async fn candidate_lookup(&self) {
554 self.0.rpc(CandidateLookup).await.ok();
555 }
556
557 pub fn downgrade(&self) -> WeakApiClient {
558 WeakApiClient(Arc::downgrade(&self.0))
559 }
560 }
561
562 #[derive(Debug, Clone)]
563 pub struct WeakApiClient(pub(crate) Weak<irpc::Client<ApiProto>>);
564
565 impl WeakApiClient {
566 pub fn upgrade(&self) -> irpc::Result<ApiClient> {
567 self.0
568 .upgrade()
569 .map(ApiClient)
570 .ok_or(irpc::Error::Send(irpc::channel::SendError::ReceiverClosed))
571 }
572
573 pub async fn nodes_dead(&self, ids: &[NodeId]) -> irpc::Result<()> {
574 self.upgrade()?.nodes_dead(ids).await
575 }
576
577 pub async fn nodes_seen(&self, ids: &[NodeId]) -> irpc::Result<()> {
578 self.upgrade()?.nodes_seen(ids).await
579 }
580
581 pub(crate) async fn self_lookup_periodic(self, interval: Duration) {
582 loop {
583 tokio::time::sleep(interval).await;
584 let Ok(api) = self.upgrade() else {
585 return;
586 };
587 api.self_lookup().await;
588 }
589 }
590
591 pub(crate) async fn random_lookup_periodic(self, interval: Duration) {
592 loop {
593 tokio::time::sleep(interval).await;
594 let Ok(api) = self.upgrade() else {
595 return;
596 };
597 api.random_lookup().await;
598 }
599 }
600
601 pub(crate) async fn candidate_lookup_periodic(self, interval: Duration) {
602 loop {
603 tokio::time::sleep(interval).await;
604 let Ok(api) = self.upgrade() else {
605 return;
606 };
607 api.candidate_lookup().await;
608 }
609 }
610 }
611}
612pub use api::ApiClient;
613use tracing::{error, info, warn};
614
615mod routing {
616 use std::{
617 fmt,
618 ops::{Index, IndexMut},
619 };
620
621 use arrayvec::ArrayVec;
622 use iroh::NodeId;
623 use serde::{Deserialize, Serialize};
624
625 use super::rpc::Id;
626
627 pub const K: usize = 20; pub const ALPHA: usize = 3; pub const BUCKET_COUNT: usize = 256; fn xor(a: &[u8; 32], b: &[u8; 32]) -> [u8; 32] {
633 let mut result = [0u8; 32];
634 for i in 0..32 {
635 result[i] = a[i] ^ b[i];
636 }
637 result
638 }
639
640 fn leading_zeros(data: &[u8; 32]) -> usize {
642 for (byte_idx, &byte) in data.iter().enumerate() {
643 if byte != 0 {
644 return byte_idx * 8 + byte.leading_zeros() as usize;
645 }
646 }
647 256 }
649
650 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
651 pub struct Distance([u8; 32]);
652
653 impl Distance {
654 pub fn between(a: &[u8; 32], b: &[u8; 32]) -> Self {
655 Self(xor(a, b))
656 }
657
658 pub fn inverse(&self, b: &[u8; 32]) -> [u8; 32] {
662 xor(&self.0, b)
663 }
664
665 pub const MAX: Self = Self([u8::MAX; 32]);
666 }
667
668 impl fmt::Debug for Distance {
669 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
670 write!(f, "Distance({self})")
671 }
672 }
673
674 impl fmt::Display for Distance {
675 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
676 write!(f, "{}", hex::encode(self.0))
677 }
678 }
679
680 #[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
681 pub struct NodeInfo {
682 pub id: NodeId,
683 pub last_seen: u64,
684 }
685
686 impl NodeInfo {
687 pub fn new(id: NodeId, last_seen: u64) -> Self {
688 Self { id, last_seen }
689 }
690 }
691
692 #[derive(Debug, Clone, Default)]
693 pub struct KBucket {
694 nodes: ArrayVec<NodeInfo, K>,
695 }
696
697 impl KBucket {
698 fn new() -> Self {
699 Self {
700 nodes: ArrayVec::new(),
701 }
702 }
703
704 pub fn add_node(&mut self, node: NodeInfo) -> bool {
705 for existing in &mut self.nodes {
707 if existing.id == node.id {
708 existing.last_seen = node.last_seen;
709 return true; }
711 }
712
713 if self.nodes.len() < K {
715 self.nodes.push(node);
716 return true;
717 }
718
719 false }
721
722 fn remove_node(&mut self, id: &NodeId) {
723 self.nodes.retain(|n| n.id != *id);
724 }
725
726 pub fn nodes(&self) -> &[NodeInfo] {
727 &self.nodes
728 }
729 }
730
731 #[derive(Debug)]
732 pub struct RoutingTable {
733 pub buckets: Box<Buckets>,
734 pub local_id: NodeId,
735 }
736
737 #[derive(Debug, Clone)]
738 pub struct Buckets(pub [KBucket; BUCKET_COUNT]);
739
740 impl Buckets {
741 pub fn iter(&self) -> std::slice::Iter<'_, KBucket> {
742 self.0.iter()
743 }
744 }
745
746 impl Index<usize> for Buckets {
747 type Output = KBucket;
748 fn index(&self, index: usize) -> &Self::Output {
749 &self.0[index]
750 }
751 }
752
753 impl IndexMut<usize> for Buckets {
754 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
755 &mut self.0[index]
756 }
757 }
758
759 impl Default for Buckets {
760 fn default() -> Self {
761 Self(std::array::from_fn(|_| KBucket::new()))
762 }
763 }
764
765 impl RoutingTable {
766 pub fn new(local_id: NodeId, buckets: Option<Box<Buckets>>) -> Self {
767 let buckets = buckets
768 .map(|mut buckets| {
769 for bucket in buckets.0.iter_mut() {
770 bucket.nodes.retain(|n| n.id != local_id);
771 }
772 buckets
773 })
774 .unwrap_or_default();
775 Self { buckets, local_id }
776 }
777
778 fn bucket_index(&self, target: &[u8; 32]) -> usize {
779 let distance = xor(self.local_id.as_bytes(), target);
780 let zeros = leading_zeros(&distance);
781 if zeros >= BUCKET_COUNT {
782 0 } else {
784 BUCKET_COUNT - 1 - zeros
785 }
786 }
787
788 pub(crate) fn contains(&self, id: &NodeId) -> bool {
789 let bucket_idx = self.bucket_index(id.as_bytes());
790 self.buckets[bucket_idx]
791 .nodes()
792 .iter()
793 .any(|node| node.id == *id)
794 }
795
796 pub fn add_node(&mut self, node: NodeInfo) -> bool {
797 if node.id == self.local_id {
798 return false;
799 }
800
801 let bucket_idx = self.bucket_index(node.id.as_bytes());
802 self.buckets[bucket_idx].add_node(node)
803 }
804
805 pub(crate) fn remove_node(&mut self, id: &NodeId) {
806 let bucket_idx = self.bucket_index(id.as_bytes());
807 self.buckets[bucket_idx].remove_node(id);
808 }
809
810 pub fn nodes(&self) -> impl Iterator<Item = &NodeInfo> {
811 self.buckets.iter().flat_map(|bucket| bucket.nodes())
812 }
813
814 pub fn find_closest_nodes(&self, target: &Id, k: usize) -> Vec<NodeId> {
815 let mut candidates = Vec::with_capacity(self.nodes().count());
821 candidates.extend(
822 self.nodes()
823 .map(|node| Distance::between(target, node.id.as_bytes())),
824 );
825 if k < candidates.len() {
826 candidates.select_nth_unstable(k - 1);
827 candidates.truncate(k);
828 }
829 candidates.sort_unstable();
830
831 candidates
832 .into_iter()
833 .map(|dist| {
834 NodeId::from_bytes(&dist.inverse(target))
835 .expect("inverse called with different target than between")
836 })
837 .collect()
838 }
839 }
840}
841
842#[doc(hidden)]
843pub mod bench_exports {
844 pub use crate::{
845 routing::{Buckets, KBucket, NodeInfo, RoutingTable},
846 rpc::Id,
847 };
848}
849
850use crate::{
851 api::{ApiMessage, Lookup, NetworkGet, NetworkPut, WeakApiClient},
852 pool::ClientPool,
853 routing::{ALPHA, BUCKET_COUNT, Buckets, Distance, K, NodeInfo, RoutingTable},
854 rpc::{Id, Kind, RpcClient, RpcMessage, SetResponse, Value},
855 u256::U256,
856};
857
858struct Node {
859 routing_table: RoutingTable,
860 storage: MemStorage,
861}
862
863impl Node {
864 fn id(&self) -> &NodeId {
865 &self.routing_table.local_id
866 }
867}
868
869struct MemStorage {
870 data: BTreeMap<Id, BTreeMap<Kind, IndexSet<Value>>>,
873}
874
875impl MemStorage {
876 fn new() -> Self {
877 Self {
878 data: BTreeMap::new(),
879 }
880 }
881
882 fn set(&mut self, key: Id, value: Value) {
884 let kind = value.kind();
885 self.data
886 .entry(key)
887 .or_default()
888 .entry(kind)
889 .or_default()
890 .insert(value);
891 }
892
893 fn get_all(&self, key: &Id, kind: &Kind) -> Option<&IndexSet<Value>> {
895 self.data.get(key).and_then(|kinds| kinds.get(kind))
896 }
897}
898
899mod u256 {
900 #![allow(clippy::needless_range_loop)]
901 use std::ops::{BitAnd, BitOr, BitXor, Deref, Not, Shl, Shr};
902
903 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
904 pub struct U256([u8; 32]);
905
906 impl Deref for U256 {
907 type Target = [u8; 32];
908
909 fn deref(&self) -> &Self::Target {
910 &self.0
911 }
912 }
913
914 impl U256 {
915 pub const MIN: U256 = U256([0u8; 32]);
917
918 pub const MAX: U256 = U256([0xffu8; 32]);
920
921 pub fn from_le_bytes(bytes: [u8; 32]) -> Self {
923 U256(bytes)
924 }
925
926 #[allow(clippy::wrong_self_convention)]
928 pub fn to_le_bytes(&self) -> [u8; 32] {
929 self.0
930 }
931
932 #[allow(dead_code)]
934 pub fn leading_zeros(&self) -> u32 {
935 let mut count = 0;
936 for &byte in self.0.iter().rev() {
937 if byte == 0 {
938 count += 8;
939 } else {
940 count += byte.leading_zeros();
941 break;
942 }
943 }
944 count
945 }
946 }
947
948 impl BitXor for U256 {
950 type Output = Self;
951
952 fn bitxor(self, rhs: Self) -> Self::Output {
953 let mut result = [0u8; 32];
954 for i in 0..32 {
955 result[i] = self.0[i] ^ rhs.0[i];
956 }
957 U256(result)
958 }
959 }
960
961 impl BitAnd for U256 {
963 type Output = Self;
964
965 fn bitand(self, rhs: Self) -> Self::Output {
966 let mut result = [0u8; 32];
967 for i in 0..32 {
968 result[i] = self.0[i] & rhs.0[i];
969 }
970 U256(result)
971 }
972 }
973
974 impl BitOr for U256 {
976 type Output = Self;
977
978 fn bitor(self, rhs: Self) -> Self::Output {
979 let mut result = [0u8; 32];
980 for i in 0..32 {
981 result[i] = self.0[i] | rhs.0[i];
982 }
983 U256(result)
984 }
985 }
986
987 impl Not for U256 {
989 type Output = Self;
990
991 fn not(self) -> Self::Output {
992 let mut result = [0u8; 32];
993 for i in 0..32 {
994 result[i] = !self.0[i];
995 }
996 U256(result)
997 }
998 }
999
1000 impl Shl<u32> for U256 {
1002 type Output = Self;
1003
1004 fn shl(self, rhs: u32) -> Self::Output {
1005 if rhs >= 256 {
1006 return U256::MIN;
1007 }
1008
1009 let low = u128::from_le_bytes(self.0[0..16].try_into().unwrap());
1011 let high = u128::from_le_bytes(self.0[16..32].try_into().unwrap());
1012
1013 let (new_low, new_high) = if rhs >= 128 {
1014 let shift_amount = rhs - 128;
1016 (0, low << shift_amount)
1017 } else {
1018 let overflow_bits = 128 - rhs;
1020 let new_low = low << rhs;
1021 let new_high = (high << rhs) | (low >> overflow_bits);
1022 (new_low, new_high)
1023 };
1024
1025 let mut result = [0u8; 32];
1026 result[0..16].copy_from_slice(&new_low.to_le_bytes());
1027 result[16..32].copy_from_slice(&new_high.to_le_bytes());
1028
1029 U256(result)
1030 }
1031 }
1032
1033 impl Shr<u32> for U256 {
1035 type Output = Self;
1036
1037 fn shr(self, rhs: u32) -> Self::Output {
1038 if rhs >= 256 {
1039 return U256::MIN;
1040 }
1041
1042 let low = u128::from_le_bytes(self.0[0..16].try_into().unwrap());
1044 let high = u128::from_le_bytes(self.0[16..32].try_into().unwrap());
1045
1046 let (new_low, new_high) = if rhs >= 128 {
1047 let shift_amount = rhs - 128;
1049 (high >> shift_amount, 0)
1050 } else {
1051 let overflow_bits = 128 - rhs;
1053 let new_low = (low >> rhs) | (high << overflow_bits);
1054 let new_high = high >> rhs;
1055 (new_low, new_high)
1056 };
1057
1058 let mut result = [0u8; 32];
1059 result[0..16].copy_from_slice(&new_low.to_le_bytes());
1060 result[16..32].copy_from_slice(&new_high.to_le_bytes());
1061
1062 U256(result)
1063 }
1064 }
1065}
1066
1067pub mod pool {
1068 use std::sync::{Arc, RwLock};
1074
1075 use iroh::{
1076 Endpoint, NodeAddr, NodeId,
1077 endpoint::{RecvStream, SendStream},
1078 };
1079 use iroh_blobs::util::connection_pool::{ConnectionPool, ConnectionRef};
1080 use snafu::Snafu;
1081 use tracing::error;
1082
1083 use crate::rpc::{RpcClient, WeakRpcClient};
1084
1085 pub trait ClientPool: Send + Sync + Clone + Sized + 'static {
1091 fn id(&self) -> NodeId;
1093
1094 fn node_addr(&self, node_id: NodeId) -> NodeAddr {
1098 node_id.into()
1099 }
1100
1101 fn add_node_addr(&self, _addr: NodeAddr) {}
1105
1106 fn client(&self, id: NodeId) -> impl Future<Output = Result<RpcClient, String>> + Send;
1111 }
1112
1113 #[derive(Debug, Snafu)]
1115 pub struct PoolError {
1116 pub message: String,
1117 }
1118
1119 #[derive(Debug, Clone)]
1121 pub struct IrohPool {
1122 endpoint: Endpoint,
1123 inner: ConnectionPool,
1124 self_client: Arc<RwLock<Option<WeakRpcClient>>>,
1125 }
1126
1127 impl IrohPool {
1128 pub fn new(endpoint: Endpoint, inner: ConnectionPool) -> Self {
1129 Self {
1130 endpoint,
1131 inner,
1132 self_client: Arc::new(RwLock::new(None)),
1133 }
1134 }
1135
1136 pub fn set_self_client(&self, client: Option<WeakRpcClient>) {
1144 let mut self_client = self.self_client.write().unwrap();
1145 *self_client = client;
1146 }
1147 }
1148
1149 #[derive(Debug, Clone)]
1150 struct IrohConnection(Arc<ConnectionRef>);
1151
1152 impl irpc::rpc::RemoteConnection for IrohConnection {
1153 fn clone_boxed(&self) -> Box<dyn irpc::rpc::RemoteConnection> {
1154 Box::new(self.clone())
1155 }
1156
1157 fn open_bi(
1158 &self,
1159 ) -> n0_future::future::Boxed<
1160 std::result::Result<(SendStream, RecvStream), irpc::RequestError>,
1161 > {
1162 let conn = self.0.clone();
1163 Box::pin(async move {
1164 let (send, recv) = conn.open_bi().await?;
1165 Ok((send, recv))
1166 })
1167 }
1168 }
1169
1170 impl ClientPool for IrohPool {
1171 fn id(&self) -> NodeId {
1172 self.endpoint.node_id()
1173 }
1174
1175 fn node_addr(&self, node_id: NodeId) -> NodeAddr {
1176 match self.endpoint.remote_info(node_id) {
1182 Some(info) => info.into(),
1183 None => node_id.into(),
1184 }
1185 }
1186
1187 fn add_node_addr(&self, addr: NodeAddr) {
1188 if addr.node_id == self.id() {
1191 return;
1192 }
1193 if addr.relay_url.is_none() && addr.direct_addresses.is_empty() {
1195 return;
1196 }
1197 self.endpoint.add_node_addr_with_source(addr, "").ok();
1199 }
1200
1201 async fn client(&self, node_id: NodeId) -> Result<RpcClient, String> {
1202 if node_id == self.id() {
1203 if let Some(client) = self.self_client.read().unwrap().clone() {
1205 return client
1206 .upgrade()
1207 .ok_or_else(|| "Self client is no longer available".to_string());
1208 } else {
1209 error!("Self client not set");
1210 return Err("Self client not set".to_string());
1211 }
1212 }
1213 let connection = self
1214 .inner
1215 .get_or_connect(node_id)
1216 .await
1217 .map_err(|e| format!("Failed to connect: {e}"));
1218 let connection = connection?;
1219 let client = RpcClient::new(irpc::Client::boxed(IrohConnection(Arc::new(connection))));
1220 Ok(client)
1221 }
1222 }
1223}
1224
1225#[derive(Debug, Clone)]
1227struct State<P> {
1228 api: WeakApiClient,
1230 pool: P,
1232 config: Config,
1234}
1235
1236struct Candidates {
1237 ids: VecDeque<NodeId>,
1238 max_size: usize,
1239}
1240
1241impl Candidates {
1242 fn new(max_size: usize) -> Self {
1243 Self {
1244 ids: VecDeque::new(),
1245 max_size,
1246 }
1247 }
1248
1249 fn add(&mut self, id: NodeId) {
1251 self.ids.retain(|x| x != &id);
1252 self.ids.push_front(id);
1253 while self.ids.len() > self.max_size {
1254 self.ids.pop_back();
1255 }
1256 }
1257
1258 fn clear_and_take(&mut self) -> Vec<NodeId> {
1260 let res = self.ids.iter().cloned().collect();
1261 self.ids.clear();
1262 res
1263 }
1264}
1265
1266struct Actor<P> {
1267 node: Node,
1268 rpc_rx: tokio::sync::mpsc::Receiver<RpcMessage>,
1270 api_rx: tokio::sync::mpsc::Receiver<ApiMessage>,
1272 tasks: JoinSet<()>,
1274 state: State<P>,
1276 candidates: Option<Candidates>,
1278 rng: rand::rngs::StdRng,
1280}
1281
1282#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1287pub struct Config {
1288 k: usize,
1290 alpha: usize,
1292 parallelism: usize,
1295 transient: bool,
1297 rng_seed: Option<[u8; 32]>,
1299 lookup_strategies: LookupStrategies,
1301}
1302
1303pub mod config {
1304 use super::*;
1306
1307 #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1308 pub struct LookupStrategies {
1309 pub random: Option<RandomLookupStrategy>,
1311 pub self_id: Option<SelfLookupStrategy>,
1313 pub candidate: Option<CandidateLookupStrategy>,
1315 }
1316
1317 impl LookupStrategies {
1318 pub fn none() -> Self {
1323 Self {
1324 random: None,
1325 self_id: None,
1326 candidate: None,
1327 }
1328 }
1329 }
1330
1331 #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
1342 pub struct CandidateLookupStrategy {
1343 pub max_lookups: usize,
1344 pub interval: Duration,
1345 }
1346
1347 #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
1353 pub struct SelfLookupStrategy {
1354 pub interval: Duration,
1355 }
1356
1357 #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
1361 pub struct RandomLookupStrategy {
1362 pub interval: Duration,
1363 pub blended: bool,
1364 }
1365}
1366use config::*;
1367
1368impl Config {
1369 pub fn transient() -> Self {
1372 Self {
1373 transient: true,
1374 ..Default::default()
1375 }
1376 }
1377
1378 pub fn persistent() -> Self {
1381 Self {
1382 transient: false,
1383 ..Default::default()
1384 }
1385 }
1386
1387 pub fn candidate_lookup_strategy(mut self, value: CandidateLookupStrategy) -> Self {
1388 self.lookup_strategies.candidate = Some(value);
1389 self
1390 }
1391
1392 pub fn random_lookup_strategy(mut self, value: RandomLookupStrategy) -> Self {
1393 self.lookup_strategies.random = Some(value);
1394 self
1395 }
1396
1397 pub fn self_lookup_strategy(mut self, value: SelfLookupStrategy) -> Self {
1398 self.lookup_strategies.self_id = Some(value);
1399 self
1400 }
1401}
1402
1403impl Default for Config {
1404 fn default() -> Self {
1405 Self {
1406 k: K,
1407 alpha: ALPHA,
1408 parallelism: 4,
1409 transient: true,
1410 lookup_strategies: LookupStrategies {
1411 random: None,
1412 self_id: None,
1413 candidate: None,
1414 },
1415 rng_seed: None,
1416 }
1417 }
1418}
1419
1420impl<P> Actor<P>
1421where
1422 P: ClientPool,
1423{
1424 fn new(
1425 node: Node,
1426 rx: tokio::sync::mpsc::Receiver<RpcMessage>,
1427 pool: P,
1428 config: Config,
1429 ) -> (Self, ApiClient) {
1430 let (api_tx, internal_rx) = tokio::sync::mpsc::channel(32);
1431 let api = ApiClient(Arc::new(api_tx.into()));
1432 let mut tasks = JoinSet::new();
1433 let state = State {
1434 api: api.downgrade(),
1435 pool,
1436 config: config.clone(),
1437 };
1438 tasks.spawn(state.clone().notify_self());
1439 (
1440 Self {
1441 node,
1442 rpc_rx: rx,
1443 api_rx: internal_rx,
1444 tasks,
1445 state,
1446 candidates: config
1447 .lookup_strategies
1448 .candidate
1449 .map(|s| Candidates::new(s.max_lookups * config.k)),
1450 rng: config
1451 .rng_seed
1452 .map(StdRng::from_seed)
1453 .unwrap_or(StdRng::from_entropy()),
1454 },
1455 api,
1456 )
1457 }
1458
1459 async fn run(mut self) {
1460 loop {
1461 tokio::select! {
1462 msg = self.rpc_rx.recv() => {
1463 if let Some(msg) = msg {
1464 self.handle_rpc(msg).await;
1465 } else {
1466 break;
1467 }
1468 }
1469 msg = self.api_rx.recv() => {
1470 if let Some(msg) = msg {
1471 self.handle_api(msg).await;
1472 } else {
1473 break;
1474 }
1475 }
1476 Some(res) = self.tasks.join_next(), if !self.tasks.is_empty() => {
1477 if let Err(e) = res {
1478 error!("Task failed: {:?}", e);
1479 }
1480 }
1481 }
1482 }
1483 }
1484
1485 async fn handle_api(&mut self, message: ApiMessage) {
1487 match message {
1488 ApiMessage::NodesSeen(msg) => {
1489 let now = now();
1490 for id in msg.ids.iter().copied() {
1491 self.node
1492 .routing_table
1493 .add_node(NodeInfo { id, last_seen: now });
1494 }
1495 }
1496 ApiMessage::NodesDead(msg) => {
1497 for id in msg.ids.iter() {
1498 self.node.routing_table.remove_node(id);
1499 }
1500 }
1501 ApiMessage::Lookup(msg) => {
1502 let initial = msg
1503 .initial
1504 .clone()
1505 .unwrap_or_else(|| self.node.routing_table.find_closest_nodes(&msg.id, K));
1506 self.tasks
1507 .spawn(self.state.clone().lookup(initial, msg.inner, msg.tx));
1508 }
1509 ApiMessage::NetworkGet(msg) => {
1510 let initial = self.node.routing_table.find_closest_nodes(&msg.id, K);
1514 self.tasks
1515 .spawn(self.state.clone().network_get(initial, msg.inner, msg.tx));
1516 }
1517 ApiMessage::NetworkPut(msg) => {
1518 let initial = self.node.routing_table.find_closest_nodes(&msg.id, K);
1522 self.tasks
1523 .spawn(self.state.clone().network_put(initial, msg.inner, msg.tx));
1524 }
1525 ApiMessage::GetRoutingTable(msg) => {
1526 let table = self
1527 .node
1528 .routing_table
1529 .buckets
1530 .iter()
1531 .map(|bucket| bucket.nodes().to_vec())
1532 .collect();
1533 msg.tx.send(table).await.ok();
1534 }
1535 ApiMessage::GetStorageStats(msg) => {
1536 let mut stats = BTreeMap::new();
1538 for (key, kinds) in &self.node.storage.data {
1539 let kind_stats = kinds
1540 .iter()
1541 .map(|(kind, values)| (*kind, values.len()))
1542 .collect();
1543 stats.insert(*key, kind_stats);
1544 }
1545 msg.tx.send(stats).await.ok();
1546 }
1547 ApiMessage::SelfLookup(msg) => {
1548 let id = self.state.pool.id().into();
1549 let api = self.state.api.clone();
1552 self.tasks.spawn(async move {
1553 let Ok(api) = api.upgrade() else {
1554 return;
1555 };
1556 api.lookup(id, None).await.ok();
1557 msg.tx.send(()).await.ok();
1558 });
1559 }
1560 ApiMessage::RandomLookup(msg) => {
1561 let blended = false;
1564 let id = if blended {
1565 let bucket = self.rng.gen_range::<u32, _>(0..BUCKET_COUNT as u32 + 2);
1566 let this = U256::from_le_bytes(*self.node.id().as_bytes());
1567 let random = U256::from_le_bytes(self.rng.r#gen());
1568 let res = blend(this, random, bucket);
1569 Id::from(res.to_le_bytes())
1570 } else {
1571 Id::from(self.rng.r#gen::<[u8; 32]>())
1572 };
1573 let api = self.state.api.clone();
1574 self.tasks.spawn(async move {
1575 let Ok(api) = api.upgrade() else {
1576 return;
1577 };
1578 api.lookup(id, None).await.ok();
1579 msg.tx.send(()).await.ok();
1580 });
1581 }
1582 ApiMessage::CandidateLookup(msg) => {
1583 if self.state.config.lookup_strategies.candidate.is_none() {
1584 warn!(
1585 "Received CandidateLookup request, but no candidate lookup strategy is configured"
1586 );
1587 return;
1588 };
1589 let Some(candidates) = self.candidates.as_mut() else {
1590 warn!("Received CandidateLookup request, but no candidates are being tracked");
1591 return;
1592 };
1593 let chosen = candidates.clear_and_take();
1595 let api = self.state.api.clone();
1598 let groups = chosen
1599 .chunks(self.state.config.k)
1600 .map(|chunk| {
1601 let id = Id::from(self.rng.r#gen::<[u8; 32]>());
1602 (id, chunk.to_vec())
1603 })
1604 .collect::<Vec<_>>();
1605 self.tasks.spawn(async move {
1606 let Ok(api) = api.upgrade() else {
1607 return;
1608 };
1609 for (id, ids) in groups {
1611 api.lookup(id, Some(ids)).await.ok();
1612 }
1613 msg.tx.send(()).await.ok();
1614 });
1615 }
1616 }
1617 }
1618
1619 async fn handle_rpc(&mut self, message: RpcMessage) {
1620 match message {
1621 RpcMessage::Set(msg) => {
1622 let ids = self
1631 .node
1632 .routing_table
1633 .find_closest_nodes(&msg.key, self.state.config.k);
1634 let self_dist = Distance::between(self.node.id().as_bytes(), &msg.key);
1635 if ids.len() >= self.state.config.k
1638 && ids.iter().all(|id| {
1639 Distance::between(self.node.id().as_bytes(), id.as_bytes()) < self_dist
1640 })
1641 {
1642 msg.tx.send(SetResponse::ErrDistance).await.ok();
1643 return;
1644 }
1645 self.node.storage.set(msg.key, msg.value.clone());
1646 msg.tx.send(SetResponse::Ok).await.ok();
1647 }
1648 RpcMessage::GetAll(msg) => {
1649 let Some(values) = self.node.storage.get_all(&msg.key, &msg.kind) else {
1651 return;
1652 };
1653 if let Some(seed) = msg.seed {
1655 let mut rng = rand::rngs::StdRng::seed_from_u64(seed.get());
1656 let n = msg.n.map(|x| x.get()).unwrap_or(values.len() as u64) as usize;
1657 let indices = sample(&mut rng, values.len(), n);
1658 for i in indices {
1659 if let Some(value) = values.get_index(i)
1660 && msg.tx.send(value.clone()).await.is_err()
1661 {
1662 break;
1663 }
1664 }
1665 } else {
1666 for value in values {
1668 if msg.tx.send(value.clone()).await.is_err() {
1669 break;
1670 }
1671 }
1672 }
1673 }
1674 RpcMessage::FindNode(msg) => {
1675 let ids = self
1677 .node
1678 .routing_table
1679 .find_closest_nodes(&msg.id, self.state.config.k)
1680 .into_iter()
1681 .take(self.state.config.k) .map(|id| self.state.pool.node_addr(id))
1683 .collect();
1684 if let Some(requester) = msg.requester {
1685 self.add_candidate(requester);
1686 }
1687 msg.tx.send(ids).await.ok();
1688 }
1689 }
1690 }
1691
1692 fn add_candidate(&mut self, id: NodeId) {
1693 if self.state.config.transient {
1694 warn!("Received FindNode request for transient node");
1695 return;
1696 }
1697 if self.node.routing_table.contains(&id) {
1698 self.node.routing_table.add_node(NodeInfo {
1700 id,
1701 last_seen: now(),
1702 });
1703 }
1704 let Some(candidates) = &mut self.candidates else {
1705 return;
1707 };
1708 candidates.add(id);
1710 }
1711}
1712
1713impl<P: ClientPool> State<P> {
1714 async fn lookup(self, initial: Vec<NodeId>, msg: Lookup, tx: oneshot::Sender<Vec<NodeId>>) {
1715 let ids = self.clone().iterative_find_node(msg.id, initial).await;
1716 tx.send(ids).await.ok();
1717 }
1718
1719 async fn network_put(self, initial: Vec<NodeId>, msg: NetworkPut, tx: mpsc::Sender<NodeId>) {
1720 let ids = self.clone().iterative_find_node(msg.id, initial).await;
1721 stream::iter(ids)
1722 .for_each_concurrent(self.config.parallelism, |id| {
1723 let pool = self.pool.clone();
1724 let value = msg.value.clone();
1725 let tx = tx.clone();
1726 async move {
1727 let Ok(client) = pool.client(id).await else {
1728 return;
1729 };
1730 if client.set(msg.id, value).await.is_ok() {
1731 tx.send(id).await.ok();
1732 }
1733 drop(client);
1734 }
1735 })
1736 .await;
1737 }
1738
1739 async fn network_get(
1740 self,
1741 initial: Vec<NodeId>,
1742 msg: NetworkGet,
1743 tx: mpsc::Sender<(NodeId, Value)>,
1744 ) {
1745 let ids = self.clone().iterative_find_node(msg.id, initial).await;
1746 stream::iter(ids)
1747 .for_each_concurrent(self.config.parallelism, |id| {
1748 let pool = self.pool.clone();
1749 let tx = tx.clone();
1750 let msg = NetworkGet {
1751 id: msg.id,
1752 kind: msg.kind,
1753 seed: msg.seed,
1754 n: msg.n,
1755 };
1756 async move {
1757 let Ok(client) = pool.client(id).await else {
1758 return;
1759 };
1760 let Ok(mut rx) = client.get_all(msg.id, msg.kind, msg.seed, msg.n).await else {
1762 return;
1763 };
1764 while let Ok(Some(value)) = rx.recv().await {
1765 if tx.send((id, value)).await.is_err() {
1766 break;
1767 }
1768 }
1769 drop(client);
1770 }
1771 })
1772 .await;
1773 }
1774
1775 async fn query_one(&self, id: NodeId, target: Id) -> Result<Vec<NodeId>, &'static str> {
1776 let requester = if self.config.transient {
1777 None
1778 } else {
1779 Some(self.pool.id())
1780 };
1781
1782 let client = self
1783 .pool
1784 .client(id)
1785 .await
1786 .map_err(|_| "Error getting client")?;
1787 let infos = client
1788 .find_node(target, requester)
1789 .await
1790 .map_err(|_| "Failed to query node");
1791 if let Err(e) = &infos {
1792 info!(%id, "Failed to query node: {e}");
1793 return Err("Failed to query node");
1794 }
1795 let infos = infos?;
1796 drop(client);
1797 let ids = infos.iter().map(|info| info.node_id).collect();
1798 for info in infos {
1799 self.pool.add_node_addr(info);
1800 }
1801 Ok(ids)
1802 }
1803
1804 async fn iterative_find_node(self, target: Id, initial: Vec<NodeId>) -> Vec<NodeId> {
1805 let mut candidates = initial
1806 .into_iter()
1807 .filter(|addr| *addr != self.pool.id())
1808 .map(|id| (Distance::between(&target, id.as_bytes()), id))
1809 .collect::<BTreeSet<_>>();
1810 let mut queried = HashSet::new();
1811 let mut tasks = FuturesUnordered::new();
1812 let mut result = BTreeSet::new();
1813 queried.insert(self.pool.id());
1814 result.insert((
1815 Distance::between(self.pool.id().as_bytes(), &target),
1816 self.pool.id(),
1817 ));
1818
1819 loop {
1820 for _ in 0..self.config.alpha {
1821 let Some(pair @ (_, id)) = candidates.pop_first() else {
1822 break;
1823 };
1824 queried.insert(id);
1825 let fut = self.query_one(id, target);
1826 tasks.push(async move { (pair, fut.await) });
1827 }
1828
1829 while let Some((pair @ (_, id), cands)) = tasks.next().await {
1830 let Ok(cands) = cands else {
1831 self.api.nodes_dead(&[id]).await.ok();
1832 continue;
1833 };
1834 for cand in cands {
1835 let dist = Distance::between(&target, cand.as_bytes());
1836 if !queried.contains(&cand) {
1837 candidates.insert((dist, cand));
1838 }
1839 }
1840 self.api.nodes_seen(&[id]).await.ok();
1841 result.insert(pair);
1842 }
1843
1844 while result.len() > self.config.k {
1846 result.pop_last();
1847 }
1848
1849 let kth_best_distance = result
1851 .iter()
1852 .nth(self.config.k - 1)
1853 .map(|(dist, _)| *dist)
1854 .unwrap_or(Distance::MAX);
1855
1856 let has_closer_candidates = candidates
1858 .first()
1859 .map(|(dist, _)| *dist < kth_best_distance)
1860 .unwrap_or_default();
1861
1862 if !has_closer_candidates {
1863 break;
1864 }
1865 }
1866
1867 result.into_iter().map(|(_, id)| id).collect()
1869 }
1870
1871 async fn notify_self(self) {
1874 let mut self_lookup = MaybeFuture::None;
1875 let mut random_lookup = MaybeFuture::None;
1876 let mut candidate_lookup = MaybeFuture::None;
1877 if let Some(strategy) = &self.config.lookup_strategies.self_id {
1878 let api = self.api.clone();
1879 self_lookup = MaybeFuture::Some(api.self_lookup_periodic(strategy.interval));
1880 }
1881 if let Some(strategy) = &self.config.lookup_strategies.random {
1882 let api = self.api.clone();
1883 random_lookup = MaybeFuture::Some(api.random_lookup_periodic(strategy.interval));
1884 }
1885 if let Some(strategy) = &self.config.lookup_strategies.candidate {
1886 let api = self.api.clone();
1887 candidate_lookup = MaybeFuture::Some(api.candidate_lookup_periodic(strategy.interval));
1888 }
1889 tokio::pin!(self_lookup, random_lookup, candidate_lookup);
1890 loop {
1891 tokio::select! {
1892 _ = &mut self_lookup => {
1893 }
1894 _ = &mut random_lookup => {
1895 }
1896 _ = &mut candidate_lookup => {
1897 }
1898 }
1899 }
1900 }
1901}
1902
1903fn blend(a: U256, b: U256, n: u32) -> U256 {
1912 if n >= 256 {
1913 return b;
1914 }
1915 let a_mask = U256::MAX << n;
1916 let b_mask = (!a_mask) >> 1;
1917 let xor_mask = !(a_mask | b_mask);
1918 a & a_mask | a ^ xor_mask | b & b_mask
1919}
1920
1921fn now() -> u64 {
1922 UNIX_EPOCH.elapsed().unwrap().as_secs()
1923}
1924
1925pub fn create_node<P: ClientPool>(
1927 id: NodeId,
1928 pool: P,
1929 bootstrap: Vec<NodeId>,
1930 config: Config,
1931) -> (RpcClient, ApiClient) {
1932 create_node_impl(id, pool, bootstrap, None, config)
1933}
1934
1935fn create_node_impl<P: ClientPool>(
1937 id: NodeId,
1938 pool: P,
1939 bootstrap: Vec<NodeId>,
1940 buckets: Option<Box<Buckets>>,
1941 config: Config,
1942) -> (RpcClient, ApiClient) {
1943 let mut node = Node {
1944 routing_table: RoutingTable::new(id, buckets),
1945 storage: MemStorage::new(),
1946 };
1947 for bootstrap_id in bootstrap {
1948 if bootstrap_id != id {
1949 node.routing_table.add_node(NodeInfo {
1950 id: bootstrap_id,
1951 last_seen: now(),
1952 });
1953 }
1954 }
1955 let (tx, rx) = tokio::sync::mpsc::channel(32);
1956 let (actor, api) = Actor::<P>::new(node, rx, pool, config);
1957 tokio::spawn(actor.run());
1958 (RpcClient::new(irpc::Client::local(tx)), api)
1959}