bb_ops/protocols/constant_view/
mod.rs1use bb_derive::{Concrete, PeerSelector};
9use bb_runtime::completion::{CompletionHandle, ContractResponse};
10use bb_runtime::contracts::peer_selector::SelectParams;
11use bb_runtime::ids::PeerId;
12use bb_runtime::runtime::RuntimeResourceRef;
13use serde::{Deserialize, Serialize};
14
15#[derive(Clone, Debug, Default, Serialize, Deserialize, Concrete, PeerSelector)]
18pub struct ConstantView {
19 pub peers: Vec<PeerId>,
21 pub seed: u64,
23}
24
25impl ConstantView {
26 pub fn new(peers: Vec<PeerId>, seed: u64) -> Self {
30 Self { peers, seed }
31 }
32}
33
34#[derive(Debug)]
36pub enum ConstantViewError {
37 Empty,
40}
41
42impl std::fmt::Display for ConstantViewError {
43 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
44 match self {
45 Self::Empty => f.write_str("ConstantView has no peers configured"),
46 }
47 }
48}
49
50impl std::error::Error for ConstantViewError {}
51
52impl bb_runtime::contracts::PeerSelector for ConstantView {
53 type Error = ConstantViewError;
54
55 fn select(
56 &mut self,
57 _ctx: &mut RuntimeResourceRef<'_>,
58 params: SelectParams,
59 _completion: CompletionHandle<Vec<PeerId>, Self::Error>,
60 ) -> ContractResponse<Vec<PeerId>, Self::Error> {
61 match params {
62 SelectParams::All => ContractResponse::Now(Ok(self.peers.clone())),
63 SelectParams::Random { n } => {
64 if self.peers.is_empty() {
65 return ContractResponse::Now(Err(ConstantViewError::Empty));
66 }
67 let take = (n as usize).min(self.peers.len());
68 let mut chosen: Vec<PeerId> = Vec::with_capacity(take);
69 let mut state = self.seed.wrapping_add(1);
71 while chosen.len() < take {
72 state ^= state << 13;
73 state ^= state >> 7;
74 state ^= state << 17;
75 let idx = (state as usize) % self.peers.len();
76 let pick = self.peers[idx];
77 if !chosen.contains(&pick) {
78 chosen.push(pick);
79 }
80 }
81 ContractResponse::Now(Ok(chosen))
82 }
83 SelectParams::NearKey { key: _, n } => {
84 if self.peers.is_empty() {
88 return ContractResponse::Now(Err(ConstantViewError::Empty));
89 }
90 let take = (n as usize).min(self.peers.len());
91 ContractResponse::Now(Ok(self.peers[..take].to_vec()))
92 }
93 }
94 }
95
96 fn current_view(
97 &mut self,
98 _ctx: &mut RuntimeResourceRef<'_>,
99 _completion: CompletionHandle<Vec<PeerId>, Self::Error>,
100 ) -> ContractResponse<Vec<PeerId>, Self::Error> {
101 ContractResponse::Now(Ok(self.peers.clone()))
102 }
103}
104