penumbra_sdk_stake/
state_key.rs

1pub mod parameters {
2    pub fn key() -> &'static str {
3        "staking/parameters"
4    }
5}
6
7pub mod validators {
8    pub mod consensus_set_index {
9        pub fn prefix() -> &'static str {
10            "staking/validators/consensus_set_index/"
11        }
12        pub fn by_id(id: &crate::IdentityKey) -> String {
13            format!("{}{id}", prefix())
14        }
15    }
16
17    pub mod lookup_by {
18        use tendermint::PublicKey;
19
20        pub fn consensus_key(pk: &PublicKey) -> String {
21            format!("staking/validators/lookup_by/consensus_key/{}", pk.to_hex())
22        }
23
24        pub fn cometbft_address(address: &[u8; 20]) -> String {
25            format!(
26                "staking/validators/lookup_by/cometbft_address/{}",
27                hex::encode(address)
28            )
29        }
30    }
31
32    pub mod definitions {
33        pub fn prefix() -> &'static str {
34            "staking/validators/definitions/"
35        }
36        pub fn by_id(id: &crate::IdentityKey) -> String {
37            format!("{}{id}", prefix())
38        }
39    }
40
41    pub mod state {
42        pub fn by_id(id: &crate::IdentityKey) -> String {
43            format!("staking/validators/data/state/{id}")
44        }
45    }
46
47    pub mod rate {
48        pub fn current_by_id(id: &crate::IdentityKey) -> String {
49            format!("staking/validators/data/rate/current/{id}")
50        }
51
52        pub fn previous_by_id(id: &crate::IdentityKey) -> String {
53            format!("staking/validators/data/rate/previous/{id}")
54        }
55    }
56
57    pub mod power {
58        pub fn by_id(id: &crate::IdentityKey) -> String {
59            format!("staking/validators/data/power/{id}")
60        }
61    }
62
63    pub mod pool {
64        pub mod balance {
65            pub fn by_id(id: &crate::IdentityKey) -> String {
66                format!("staking/validators/data/pool/balance/{id}")
67            }
68        }
69
70        pub mod bonding_state {
71            pub fn by_id(id: &crate::IdentityKey) -> String {
72                format!("staking/validators/data/pool/bonding_state/{id}")
73            }
74        }
75    }
76
77    pub mod uptime {
78        pub fn by_id(id: &crate::IdentityKey) -> String {
79            format!("staking/validators/data/uptime/{id}")
80        }
81    }
82
83    pub mod last_disabled {
84        pub fn by_id(id: &crate::IdentityKey) -> String {
85            format!("staking/validators/data/last_disabled/{id}")
86        }
87    }
88
89    /// Tracks the funding rewards of the previously active validator set
90    /// in object storage. Consumed by the funding component.
91    pub mod rewards {
92        pub fn staking() -> &'static str {
93            "staking/validators/staking_rewards"
94        }
95    }
96}
97
98pub mod chain {
99    pub mod base_rate {
100        pub fn current() -> &'static str {
101            "staking/chain/base_rate/current"
102        }
103
104        pub fn previous() -> &'static str {
105            "staking/chain/base_rate/previous"
106        }
107    }
108
109    pub fn total_bonded() -> &'static str {
110        "staking/chain/total_bonded"
111    }
112
113    pub mod delegation_changes {
114        pub fn key() -> &'static str {
115            "staking/delegation_changes"
116        }
117
118        pub fn by_height(height: u64) -> String {
119            format!("staking/delegation_changes/{height}")
120        }
121    }
122}
123
124pub mod penalty {
125    use crate::IdentityKey;
126
127    pub fn prefix(id: &IdentityKey) -> String {
128        // Note: We typically put the key at the end of the path to increase
129        // locality. Here we don't because we want to build a prefix iterator
130        // to accumulate validator penalty across epochs.
131        format!("staking/penalty/{id}/")
132    }
133    pub fn for_id_in_epoch(id: &crate::IdentityKey, epoch_index: u64) -> String {
134        // Load-bearing format string: we need to pad with 0s to ensure that
135        // the lex order agrees with the numeric order on epochs.
136        // 10 decimal digits covers 2^32 epochs.
137        format!("{}{epoch_index:010}", prefix(id))
138    }
139}
140
141pub mod consensus_update {
142    pub fn consensus_keys() -> &'static str {
143        "staking/cometbft_data/consensus_keys"
144    }
145}
146
147pub(super) mod internal {
148
149    pub fn cometbft_validator_updates() -> &'static str {
150        "staking/cometbft_validator_updates"
151    }
152}
153
154#[cfg(test)]
155mod tests {
156    use decaf377_rdsa as rdsa;
157    use std::collections::BTreeSet;
158    use tests::penalty;
159
160    use crate::IdentityKey;
161
162    use super::*;
163    use rand_core::OsRng;
164
165    #[test]
166    fn penalty_in_epoch_padding() {
167        let vk = rdsa::VerificationKey::from(rdsa::SigningKey::new(OsRng));
168        let ik = IdentityKey(vk.into());
169
170        assert_eq!(
171            penalty::for_id_in_epoch(&ik, 791),
172            //                            0123456789
173            format!("staking/penalty/{ik}/0000000791")
174        );
175    }
176
177    #[test]
178    fn penalty_in_epoch_sorting() {
179        let vk = rdsa::VerificationKey::from(rdsa::SigningKey::new(OsRng));
180        let ik = IdentityKey(vk.into());
181
182        let k791 = penalty::for_id_in_epoch(&ik, 791);
183        let k792 = penalty::for_id_in_epoch(&ik, 792);
184        let k793 = penalty::for_id_in_epoch(&ik, 793);
185        let k79 = penalty::for_id_in_epoch(&ik, 79);
186        let k7 = penalty::for_id_in_epoch(&ik, 7);
187
188        let keys = vec![k791.clone(), k792.clone(), k793.clone(), k79, k7]
189            .into_iter()
190            .collect::<BTreeSet<String>>();
191
192        // All keys are distinct
193        assert_eq!(keys.len(), 5);
194
195        // Check that lex order agrees with numeric order
196        let range = keys
197            .range(k791.clone()..=k793.clone())
198            .cloned()
199            .collect::<Vec<_>>();
200        assert_eq!(range, vec![k791, k792, k793,]);
201    }
202}