1use crate::error::{Error, Result};
2use crate::pbft::Round;
3use crate::types::{Block, NodeId, Role};
4use crate::vrf::{sortition, VrfClient, VrfParams};
5
6pub struct Node {
7 id: NodeId,
8 weight: u64,
9 secret_key: Vec<u8>,
10 public_key: Vec<u8>,
11 seed: u64,
12 role: Role,
13 round: Option<Round>,
14 ledger: Vec<Block>,
15 byzantine: bool,
16}
17
18impl Node {
19 pub fn new(id: NodeId, weight: u64) -> Result<Self> {
20 let mut vrf = VrfClient::new()?;
21 let (sk, pk) = vrf.generate_keys(id)?;
22 Ok(Self {
23 id,
24 weight,
25 secret_key: sk,
26 public_key: pk,
27 seed: id.wrapping_mul(31).wrapping_add(7),
28 role: Role::Normal,
29 round: None,
30 ledger: vec![Block::genesis()],
31 byzantine: false,
32 })
33 }
34
35 pub fn id(&self) -> NodeId {
36 self.id
37 }
38
39 pub fn weight(&self) -> u64 {
40 self.weight
41 }
42
43 pub fn role(&self) -> Role {
44 self.role
45 }
46
47 pub fn seed(&self) -> u64 {
48 self.seed
49 }
50
51 pub fn ledger(&self) -> &[Block] {
52 &self.ledger
53 }
54
55 pub fn public_key(&self) -> &[u8] {
56 &self.public_key
57 }
58
59 pub fn is_byzantine(&self) -> bool {
60 self.byzantine
61 }
62
63 pub fn set_byzantine(&mut self, byzantine: bool) {
64 self.byzantine = byzantine;
65 }
66
67 pub fn assign_role(
71 &mut self,
72 round_num: u64,
73 total_weight: u64,
74 role_expected: &[(Role, u64)],
75 ) -> Result<Role> {
76 let mut vrf = VrfClient::new()?;
77
78 for &(role, expected) in role_expected {
79 let params = VrfParams {
80 weight: self.weight,
81 round: round_num,
82 seed: self.seed,
83 role,
84 };
85 let vrf_proof = vrf.prove(&self.secret_key, ¶ms)?;
86 let index = sortition(&vrf_proof.hash, self.weight, expected, total_weight);
87 if index > 0 {
88 self.role = role;
89 return Ok(role);
90 }
91 }
92
93 self.role = Role::Normal;
94 Ok(Role::Normal)
95 }
96
97 pub fn propose_block(&self, round_num: u64) -> Result<Block> {
99 if self.role != Role::Proposer {
100 return Err(Error::WrongRole(Role::Proposer));
101 }
102 let prev_hash = self
103 .ledger
104 .last()
105 .map(|b| b.hash())
106 .unwrap_or([0u8; 32]);
107 Ok(Block::new(round_num, prev_hash, self.id, self.seed))
108 }
109
110 pub fn validate_block(&self, block: &Block) -> bool {
112 if self.byzantine {
113 return false;
114 }
115 match self.ledger.last() {
116 Some(last) => block.prev_hash == last.hash(),
117 None => true,
118 }
119 }
120
121 pub fn commit_block(&mut self, block: Block) {
123 self.seed = block.seed.wrapping_add(block.round);
124 self.ledger.push(block);
125 }
126
127 pub fn start_round(&mut self, round_num: u64, threshold: u64) {
128 self.round = Some(Round::new(round_num, self.role, threshold));
129 }
130}