casper_types/transaction/
approvals_hash.rs1use alloc::{collections::BTreeSet, vec::Vec};
2use core::fmt::{self, Display, Formatter};
3
4#[cfg(feature = "datasize")]
5use datasize::DataSize;
6#[cfg(any(feature = "testing", test))]
7use rand::Rng;
8use serde::{Deserialize, Serialize};
9
10use super::Approval;
11#[cfg(any(feature = "testing", test))]
12use crate::testing::TestRng;
13use crate::{
14 bytesrepr::{self, FromBytes, ToBytes},
15 Digest,
16};
17
18#[derive(
20 Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Serialize, Deserialize, Debug, Default,
21)]
22#[cfg_attr(feature = "datasize", derive(DataSize))]
23#[serde(deny_unknown_fields)]
24pub struct ApprovalsHash(pub Digest);
25
26impl ApprovalsHash {
27 pub const LENGTH: usize = Digest::LENGTH;
29
30 pub fn compute(approvals: &BTreeSet<Approval>) -> Result<Self, bytesrepr::Error> {
33 let digest = Digest::hash(approvals.to_bytes()?);
34 Ok(ApprovalsHash(digest))
35 }
36
37 pub fn inner(&self) -> &Digest {
39 &self.0
40 }
41
42 #[cfg(any(feature = "testing", test))]
45 pub const fn from_raw(raw_digest: [u8; Self::LENGTH]) -> Self {
46 ApprovalsHash(Digest::from_raw(raw_digest))
47 }
48
49 #[cfg(any(feature = "testing", test))]
51 pub fn random(rng: &mut TestRng) -> Self {
52 let hash = rng.gen::<[u8; Digest::LENGTH]>().into();
53 ApprovalsHash(hash)
54 }
55}
56
57impl From<ApprovalsHash> for Digest {
58 fn from(hash: ApprovalsHash) -> Self {
59 hash.0
60 }
61}
62
63impl From<Digest> for ApprovalsHash {
64 fn from(digest: Digest) -> Self {
65 Self(digest)
66 }
67}
68
69impl Display for ApprovalsHash {
70 fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
71 write!(formatter, "transaction-v1-approvals-hash({})", self.0,)
72 }
73}
74
75impl AsRef<[u8]> for ApprovalsHash {
76 fn as_ref(&self) -> &[u8] {
77 self.0.as_ref()
78 }
79}
80
81impl ToBytes for ApprovalsHash {
82 fn write_bytes(&self, writer: &mut Vec<u8>) -> Result<(), bytesrepr::Error> {
83 self.0.write_bytes(writer)
84 }
85
86 fn to_bytes(&self) -> Result<Vec<u8>, bytesrepr::Error> {
87 self.0.to_bytes()
88 }
89
90 fn serialized_length(&self) -> usize {
91 self.0.serialized_length()
92 }
93}
94
95impl FromBytes for ApprovalsHash {
96 fn from_bytes(bytes: &[u8]) -> Result<(Self, &[u8]), bytesrepr::Error> {
97 Digest::from_bytes(bytes).map(|(inner, remainder)| (ApprovalsHash(inner), remainder))
98 }
99}
100
101#[cfg(test)]
102mod tests {
103 use super::*;
104
105 #[test]
106 fn bytesrepr_roundtrip() {
107 let rng = &mut TestRng::new();
108 let hash = ApprovalsHash::random(rng);
109 bytesrepr::test_serialization_roundtrip(&hash);
110 }
111}