1pub mod amr;
9pub mod cmr;
10pub mod ihr;
11pub mod tmr;
12
13use crate::bit_encoding::BitCollector;
14use crate::Value;
15use hashes::{sha256, Hash, HashEngine};
16use std::fmt;
17
18pub trait HasCmr {
20 fn cmr(&self) -> cmr::Cmr;
22}
23
24#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
26pub struct FailEntropy([u8; 64]);
27
28impl FailEntropy {
29 pub const ZERO: Self = FailEntropy([0; 64]);
31
32 pub fn from_byte_array(data: [u8; 64]) -> Self {
34 FailEntropy(data)
35 }
36}
37
38impl fmt::Display for FailEntropy {
39 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
40 fmt::Display::fmt(&hex::DisplayHex::as_hex(&self.0), f)
41 }
42}
43
44impl AsRef<[u8]> for FailEntropy {
45 fn as_ref(&self) -> &[u8] {
46 self.0.as_ref()
47 }
48}
49
50fn compact_value(value: &Value) -> [u8; 32] {
53 let (mut bytes, bit_length) = value.iter_compact().collect_bits();
54
55 if bit_length % 8 == 0 {
58 bytes.push(0x80);
59 } else {
60 let delimiter_index = bit_length % 8;
61 *bytes.last_mut().unwrap() |= 1 << (7 - delimiter_index);
62 }
63
64 let k = if bytes.len() % 64 > 56 {
66 56 + (64 - (bytes.len() % 64))
69 } else {
70 56 - (bytes.len() % 64)
72 };
73 bytes.resize(bytes.len() + k, 0x00);
74 debug_assert!(bytes.len() % 64 == 56);
75
76 let bit_length_bytes = (bit_length as u64).to_be_bytes();
78 bytes.extend(bit_length_bytes.iter());
79 debug_assert!(bytes.len() % 16 == 0);
80
81 let mut consumed = 0;
83 let mut engine = sha256::HashEngine::default();
84 while consumed < bytes.len() {
85 engine.input(&bytes[consumed..(consumed + 16)]);
86 consumed += 16;
87 }
88 debug_assert!(consumed == bytes.len());
89 engine.midstate().to_byte_array()
90}
91
92fn bip340_iv(tag: &[u8]) -> sha256::Midstate {
93 let tag_hash = sha256::Hash::hash(tag);
94 let mut engine = sha256::Hash::engine();
95 engine.input(tag_hash.as_ref());
96 engine.input(tag_hash.as_ref());
97 engine.midstate()
98}
99
100#[macro_export]
105macro_rules! impl_midstate_wrapper {
106 ($wrapper:ident) => {
107 impl AsRef<[u8]> for $wrapper {
108 fn as_ref(&self) -> &[u8] {
109 self.0.as_ref()
110 }
111 }
112
113 impl std::fmt::Debug for $wrapper {
114 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
115 std::fmt::Display::fmt(&hex::DisplayHex::as_hex(self.as_ref()), f)
116 }
117 }
118
119 impl std::fmt::Display for $wrapper {
120 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
121 std::fmt::Debug::fmt(self, f)
122 }
123 }
124
125 impl std::str::FromStr for $wrapper {
126 type Err = hashes::hex::HexToArrayError;
127
128 fn from_str(s: &str) -> Result<Self, Self::Err> {
129 let x: [u8; 32] = hashes::hex::FromHex::from_hex(s)?;
130 Ok($wrapper(Midstate::from_byte_array(x)))
131 }
132 }
133
134 impl $wrapper {
135 pub fn update(self, left: Self, right: Self) -> Self {
141 use $crate::hashes::{sha256, HashEngine};
142
143 let mut engine = sha256::HashEngine::from_midstate(self.0, 0);
144 engine.input(left.as_ref());
145 engine.input(right.as_ref());
146 $wrapper(engine.midstate())
147 }
148
149 pub fn update_1(self, right: Self) -> Self {
155 use $crate::hashes::{sha256, HashEngine};
156
157 let mut engine = sha256::HashEngine::from_midstate(self.0, 0);
158 engine.input(&[0; 32]);
159 engine.input(&right.as_ref());
160 $wrapper(engine.midstate())
161 }
162
163 pub fn update_with_weight(self, left_weight: u64, right: Self) -> Self {
167 use $crate::hashes::{sha256, HashEngine};
168
169 let mut engine = sha256::HashEngine::from_midstate(self.0, 0);
170 let mut left_blk = [0; 32];
171 left_blk[24..].copy_from_slice(&left_weight.to_be_bytes());
172 engine.input(&left_blk);
173 engine.input(right.as_ref());
174 $wrapper(engine.midstate())
175 }
176
177 pub fn update_fail_entropy(self, entropy: $crate::FailEntropy) -> Self {
178 use $crate::hashes::{sha256, HashEngine};
179
180 let mut engine = sha256::HashEngine::from_midstate(self.0, 0);
181 engine.input(entropy.as_ref());
182 $wrapper(engine.midstate())
183 }
184
185 pub fn from_byte_array(data: [u8; 32]) -> Self {
187 $wrapper(Midstate::from_byte_array(data))
188 }
189
190 pub fn to_byte_array(self) -> [u8; 32] {
192 self.0.to_byte_array()
193 }
194 }
195
196 impl_serde_string!($wrapper);
197 };
198}