hotshot_types/
stake_table.rs1use alloy::primitives::U256;
10use ark_ff::PrimeField;
11use derive_more::derive::{Deref, DerefMut};
12use jf_crhf::CRHF;
13use jf_rescue::crhf::VariableLengthRescueCRHF;
14use serde::{Deserialize, Serialize};
15
16use crate::{
17 light_client::{CircuitField, StakeTableState, ToFieldsLightClientCompat},
18 traits::signature_key::{SignatureKey, StakeTableEntryType},
19 NodeType, PeerConfig,
20};
21
22#[derive(Serialize, Deserialize, PartialEq, Debug, Clone, Hash, Eq)]
24#[serde(bound(deserialize = ""))]
25pub struct StakeTableEntry<K: SignatureKey> {
26 pub stake_key: K,
28 pub stake_amount: U256,
30}
31
32impl<K: SignatureKey> StakeTableEntryType<K> for StakeTableEntry<K> {
33 fn stake(&self) -> U256 {
35 self.stake_amount
36 }
37
38 fn public_key(&self) -> K {
40 self.stake_key.clone()
41 }
42}
43
44impl<K: SignatureKey> StakeTableEntry<K> {
45 pub fn key(&self) -> &K {
47 &self.stake_key
48 }
49}
50
51#[derive(Debug, Clone, PartialEq, Eq, Hash, Default, Deref, DerefMut)]
52pub struct HSStakeTable<TYPES: NodeType>(pub Vec<PeerConfig<TYPES>>);
53
54impl<TYPES: NodeType> From<Vec<PeerConfig<TYPES>>> for HSStakeTable<TYPES> {
55 fn from(peers: Vec<PeerConfig<TYPES>>) -> Self {
56 Self(peers)
57 }
58}
59
60#[inline]
61pub fn one_honest_threshold(total_stake: U256) -> U256 {
63 total_stake / U256::from(3) + U256::from(1)
64}
65
66#[inline]
67fn u256_to_field(amount: U256) -> CircuitField {
68 let amount_bytes: [u8; 32] = amount.to_le_bytes();
69 CircuitField::from_le_bytes_mod_order(&amount_bytes)
70}
71
72impl<TYPES: NodeType> std::iter::IntoIterator for HSStakeTable<TYPES> {
73 type Item = PeerConfig<TYPES>;
74 type IntoIter = std::vec::IntoIter<PeerConfig<TYPES>>;
75
76 fn into_iter(self) -> Self::IntoIter {
77 self.0.into_iter()
78 }
79}
80
81impl<TYPES: NodeType> HSStakeTable<TYPES> {
82 pub fn commitment(&self, stake_table_capacity: usize) -> anyhow::Result<StakeTableState> {
83 if stake_table_capacity < self.0.len() {
84 return Err(anyhow::anyhow!(
85 "Stake table over capacity: {} < {}",
86 stake_table_capacity,
87 self.0.len(),
88 ));
89 }
90 let padding_len = stake_table_capacity - self.0.len();
91 let mut bls_preimage = vec![];
92 let mut schnorr_preimage = vec![];
93 let mut amount_preimage = vec![];
94 let mut total_stake = U256::from(0);
95 for peer in &self.0 {
96 bls_preimage.extend(peer.stake_table_entry.public_key().to_fields());
97 schnorr_preimage.extend(peer.state_ver_key.to_fields());
98 amount_preimage.push(u256_to_field(peer.stake_table_entry.stake()));
99 total_stake += peer.stake_table_entry.stake();
100 }
101 bls_preimage.resize(
102 <TYPES::SignatureKey as ToFieldsLightClientCompat>::SIZE * stake_table_capacity,
103 CircuitField::default(),
104 );
105 schnorr_preimage.extend(
107 std::iter::repeat_n(TYPES::StateSignatureKey::default().to_fields(), padding_len)
108 .flatten(),
109 );
110 amount_preimage.resize(stake_table_capacity, CircuitField::default());
111 let threshold = u256_to_field(one_honest_threshold(total_stake));
112 Ok(StakeTableState {
113 bls_key_comm: VariableLengthRescueCRHF::<CircuitField, 1>::evaluate(bls_preimage)
114 .unwrap()[0],
115 schnorr_key_comm: VariableLengthRescueCRHF::<CircuitField, 1>::evaluate(
116 schnorr_preimage,
117 )
118 .unwrap()[0],
119 amount_comm: VariableLengthRescueCRHF::<CircuitField, 1>::evaluate(amount_preimage)
120 .unwrap()[0],
121 threshold,
122 })
123 }
124
125 pub fn total_stakes(&self) -> U256 {
126 self.0
127 .iter()
128 .map(|peer| peer.stake_table_entry.stake())
129 .sum()
130 }
131}
132
133pub struct StakeTableEntries<TYPES: NodeType>(
134 pub Vec<<<TYPES as NodeType>::SignatureKey as SignatureKey>::StakeTableEntry>,
135);
136
137impl<TYPES: NodeType> From<Vec<PeerConfig<TYPES>>> for StakeTableEntries<TYPES> {
138 fn from(peers: Vec<PeerConfig<TYPES>>) -> Self {
139 Self(
140 peers
141 .into_iter()
142 .map(|peer| peer.stake_table_entry)
143 .collect::<Vec<_>>(),
144 )
145 }
146}
147
148impl<TYPES: NodeType> From<HSStakeTable<TYPES>> for StakeTableEntries<TYPES> {
149 fn from(stake_table: HSStakeTable<TYPES>) -> Self {
150 Self::from(stake_table.0)
151 }
152}