1use celestia_tendermint_proto::v0_37::types::SimpleValidator as RawSimpleValidator;
4use celestia_tendermint_proto::Protobuf;
5use serde::{Deserialize, Serialize};
6
7use crate::{
8 account,
9 crypto::signature::Verifier,
10 crypto::Sha256,
11 hash::Hash,
12 merkle::{self, MerkleHash},
13 prelude::*,
14 public_key::deserialize_public_key,
15 vote, Error, PublicKey, Signature,
16};
17
18#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
20pub struct Set {
21 validators: Vec<Info>,
22 proposer: Option<Info>,
23 total_voting_power: vote::Power,
24}
25
26impl Set {
27 pub fn new(mut validators: Vec<Info>, proposer: Option<Info>) -> Set {
29 Self::sort_validators(&mut validators);
30
31 let total_voting_power = validators
33 .iter()
34 .map(|v| v.power.value())
35 .sum::<u64>()
36 .try_into()
37 .unwrap();
38
39 Set {
40 validators,
41 proposer,
42 total_voting_power,
43 }
44 }
45
46 pub fn without_proposer(validators: Vec<Info>) -> Set {
48 Self::new(validators, None)
49 }
50
51 pub fn with_proposer(
53 validators: Vec<Info>,
54 proposer_address: account::Id,
55 ) -> Result<Self, Error> {
56 let proposer = validators
58 .iter()
59 .find(|v| v.address == proposer_address)
60 .cloned()
61 .ok_or_else(|| Error::proposer_not_found(proposer_address))?;
62
63 Ok(Self::new(validators, Some(proposer)))
66 }
67
68 pub fn validators(&self) -> &Vec<Info> {
70 &self.validators
71 }
72
73 pub fn proposer(&self) -> &Option<Info> {
75 &self.proposer
76 }
77
78 pub fn total_voting_power(&self) -> vote::Power {
80 self.total_voting_power
81 }
82
83 fn sort_validators(vals: &mut [Info]) {
86 vals.sort_by_key(|v| (core::cmp::Reverse(v.power), v.address));
87 }
88
89 pub fn validator(&self, val_id: account::Id) -> Option<Info> {
91 self.validators
92 .iter()
93 .find(|val| val.address == val_id)
94 .cloned()
95 }
96
97 #[cfg(feature = "rust-crypto")]
99 pub fn hash(&self) -> Hash {
100 self.hash_with::<crate::crypto::default::Sha256>()
101 }
102
103 pub fn hash_with<H>(&self) -> Hash
105 where
106 H: MerkleHash + Sha256 + Default,
107 {
108 let validator_bytes: Vec<Vec<u8>> = self
109 .validators()
110 .iter()
111 .map(|validator| validator.hash_bytes())
112 .collect();
113
114 Hash::Sha256(merkle::simple_hash_from_byte_vectors::<H>(&validator_bytes))
115 }
116}
117
118#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
121pub struct Info {
122 pub address: account::Id,
124
125 pub pub_key: PublicKey,
127
128 #[serde(alias = "voting_power", alias = "total_voting_power")]
131 pub power: vote::Power,
132
133 pub name: Option<String>,
135
136 #[serde(skip)]
138 pub proposer_priority: ProposerPriority,
139}
140
141impl Info {
142 pub fn power(&self) -> u64 {
144 self.power.value()
145 }
146
147 pub fn verify_signature<V>(&self, sign_bytes: &[u8], signature: &Signature) -> Result<(), Error>
150 where
151 V: Verifier,
152 {
153 V::verify(self.pub_key, sign_bytes, signature)
154 .map_err(|_| Error::signature_invalid("Ed25519 signature verification failed".into()))
155 }
156
157 #[cfg(feature = "rust-crypto")]
158 pub fn new(pk: PublicKey, vp: vote::Power) -> Info {
160 Info {
161 address: account::Id::from(pk),
162 pub_key: pk,
163 power: vp,
164 name: None,
165 proposer_priority: ProposerPriority::default(),
166 }
167 }
168}
169
170#[derive(Clone, PartialEq, Eq)]
176pub struct SimpleValidator {
177 pub pub_key: PublicKey,
179 pub voting_power: vote::Power,
181}
182
183impl From<&Info> for SimpleValidator {
185 fn from(info: &Info) -> SimpleValidator {
186 SimpleValidator {
187 pub_key: info.pub_key,
188 voting_power: info.power,
189 }
190 }
191}
192
193impl Info {
194 pub fn hash_bytes(&self) -> Vec<u8> {
197 Protobuf::<RawSimpleValidator>::encode_vec(&SimpleValidator::from(self)).unwrap()
198 }
199}
200
201#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Default)]
204pub struct ProposerPriority(i64);
205
206impl From<i64> for ProposerPriority {
207 fn from(value: i64) -> Self {
208 ProposerPriority(value)
209 }
210}
211
212impl From<ProposerPriority> for i64 {
213 fn from(priority: ProposerPriority) -> i64 {
214 priority.value()
215 }
216}
217
218impl ProposerPriority {
219 pub fn value(self) -> i64 {
221 self.0
222 }
223}
224
225#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
231pub struct Update {
232 #[serde(deserialize_with = "deserialize_public_key")]
234 pub pub_key: PublicKey,
235
236 #[serde(default)]
238 pub power: vote::Power,
239}
240
241tendermint_pb_modules! {
246 use pb::{
247 abci::ValidatorUpdate as RawValidatorUpdate,
248 types::{
249 SimpleValidator as RawSimpleValidator, Validator as RawValidator,
250 ValidatorSet as RawValidatorSet,
251 },
252 };
253 use super::{Info, Set, SimpleValidator, Update};
254 use crate::{prelude::*, Error};
255
256 impl Protobuf<RawValidatorSet> for Set {}
257
258 impl TryFrom<RawValidatorSet> for Set {
259 type Error = Error;
260
261 fn try_from(value: RawValidatorSet) -> Result<Self, Self::Error> {
262 let validators = value
263 .validators
264 .into_iter()
265 .map(TryInto::try_into)
266 .collect::<Result<Vec<_>, _>>()?;
267
268 let proposer = value.proposer.map(TryInto::try_into).transpose()?;
269 let validator_set = Self::new(validators, proposer);
270
271 Ok(validator_set)
272 }
273 }
274
275 impl From<Set> for RawValidatorSet {
276 fn from(value: Set) -> Self {
277 RawValidatorSet {
278 validators: value.validators.into_iter().map(Into::into).collect(),
279 proposer: value.proposer.map(Into::into),
280 total_voting_power: value.total_voting_power.into(),
281 }
282 }
283 }
284
285 impl TryFrom<RawValidator> for Info {
286 type Error = Error;
287
288 fn try_from(value: RawValidator) -> Result<Self, Self::Error> {
289 Ok(Info {
290 address: value.address.try_into()?,
291 pub_key: value
292 .pub_key
293 .ok_or_else(Error::missing_public_key)?
294 .try_into()?,
295 power: value.voting_power.try_into()?,
296 name: None,
297 proposer_priority: value.proposer_priority.into(),
298 })
299 }
300 }
301
302 impl From<Info> for RawValidator {
303 fn from(value: Info) -> Self {
304 RawValidator {
305 address: value.address.into(),
306 pub_key: Some(value.pub_key.into()),
307 voting_power: value.power.into(),
308 proposer_priority: value.proposer_priority.into(),
309 }
310 }
311 }
312
313 impl Protobuf<RawSimpleValidator> for SimpleValidator {}
314
315 impl TryFrom<RawSimpleValidator> for SimpleValidator {
316 type Error = Error;
317
318 fn try_from(value: RawSimpleValidator) -> Result<Self, Self::Error> {
319 Ok(SimpleValidator {
320 pub_key: value.pub_key
321 .ok_or_else(Error::missing_public_key)?
322 .try_into()?,
323 voting_power: value.voting_power.try_into()?,
324 })
325 }
326 }
327
328 impl From<SimpleValidator> for RawSimpleValidator {
329 fn from(value: SimpleValidator) -> Self {
330 RawSimpleValidator {
331 pub_key: Some(value.pub_key.into()),
332 voting_power: value.voting_power.into(),
333 }
334 }
335 }
336
337 impl Protobuf<RawValidatorUpdate> for Update {}
338
339 impl From<Update> for RawValidatorUpdate {
340 fn from(vu: Update) -> Self {
341 Self {
342 pub_key: Some(vu.pub_key.into()),
343 power: vu.power.into(),
344 }
345 }
346 }
347
348 impl TryFrom<RawValidatorUpdate> for Update {
349 type Error = Error;
350
351 fn try_from(vu: RawValidatorUpdate) -> Result<Self, Self::Error> {
352 Ok(Self {
353 pub_key: vu
354 .pub_key
355 .ok_or_else(Error::missing_public_key)?
356 .try_into()?,
357 power: vu.power.try_into()?,
358 })
359 }
360 }
361}
362
363#[cfg(test)]
364mod tests {
365 use super::*;
366
367 #[cfg(feature = "rust-crypto")]
368 mod crypto {
369 use super::*;
370
371 fn make_validator(pk: Vec<u8>, vp: u64) -> Info {
373 let pk = PublicKey::from_raw_ed25519(&pk).unwrap();
374 Info::new(pk, vote::Power::try_from(vp).unwrap())
375 }
376
377 #[test]
378 fn test_validator_set() {
379 let v1 = make_validator(
409 vec![
410 48, 163, 55, 132, 231, 147, 230, 163, 56, 158, 127, 218, 179, 139, 212, 103,
411 218, 89, 122, 126, 229, 88, 84, 48, 32, 0, 185, 174, 63, 72, 203, 52,
412 ],
413 148_151_478_422_287_875,
414 );
415 let v2 = make_validator(
416 vec![
417 54, 253, 174, 153, 121, 74, 145, 180, 111, 16, 214, 48, 193, 109, 104, 134, 55,
418 162, 151, 16, 182, 114, 125, 135, 32, 195, 236, 248, 64, 112, 74, 101,
419 ],
420 158_095_448_483_785_107,
421 );
422 let v3 = make_validator(
423 vec![
424 182, 205, 13, 86, 147, 27, 65, 49, 160, 118, 11, 180, 117, 35, 206, 35, 68, 19,
425 27, 173, 69, 92, 204, 224, 200, 51, 249, 81, 105, 128, 112, 244,
426 ],
427 770_561_664_770_006_272,
428 );
429 let hash_expect = vec![
430 11, 64, 107, 4, 234, 81, 232, 75, 204, 199, 160, 114, 229, 97, 243, 95, 118, 213,
431 17, 22, 57, 84, 71, 122, 200, 169, 192, 252, 41, 148, 223, 180,
432 ];
433
434 let val_set = Set::without_proposer(vec![v1.clone(), v2.clone(), v3.clone()]);
435 let hash = val_set.hash();
436 assert_eq!(hash_expect, hash.as_bytes().to_vec());
437
438 let not_in_set = make_validator(
439 vec![
440 110, 147, 87, 120, 27, 218, 66, 209, 81, 4, 169, 153, 64, 163, 137, 89, 168,
441 97, 219, 233, 42, 119, 24, 61, 47, 59, 76, 31, 182, 60, 13, 4,
442 ],
443 10_000_000_000_000_000,
444 );
445
446 assert_eq!(val_set.validator(v1.address).unwrap(), v1);
447 assert_eq!(val_set.validator(v2.address).unwrap(), v2);
448 assert_eq!(val_set.validator(v3.address).unwrap(), v3);
449 assert_eq!(val_set.validator(not_in_set.address), None);
450 assert_eq!(
451 val_set.total_voting_power().value(),
452 148_151_478_422_287_875 + 158_095_448_483_785_107 + 770_561_664_770_006_272
453 );
454 }
455 }
456
457 #[test]
458 fn deserialize_validator_updates() {
459 const FMT1: &str = r#"{
460 "pub_key": {
461 "Sum": {
462 "type": "tendermint.crypto.PublicKey_Ed25519",
463 "value": {
464 "ed25519": "VqJCr3vjQdffcLIG6RMBl2MgXDFYNY6b3Joaa43gV3o="
465 }
466 }
467 },
468 "power": "573929"
469 }"#;
470 const FMT2: &str = r#"{
471 "pub_key": {
472 "type": "tendermint/PubKeyEd25519",
473 "value": "VqJCr3vjQdffcLIG6RMBl2MgXDFYNY6b3Joaa43gV3o="
474 },
475 "power": "573929"
476 }"#;
477
478 let update1 = serde_json::from_str::<Update>(FMT1).unwrap();
479 let update2 = serde_json::from_str::<Update>(FMT2).unwrap();
480
481 assert_eq!(u64::from(update1.power), 573929);
482 assert_eq!(update1, update2);
483 }
484}