pub mod amr;
pub mod cmr;
pub mod ihr;
pub mod tmr;
use crate::bit_encoding::BitCollector;
use crate::Value;
use hashes::{sha256, Hash, HashEngine};
use std::fmt;
pub trait HasCmr {
fn cmr(&self) -> cmr::Cmr;
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
pub struct FailEntropy([u8; 64]);
impl FailEntropy {
pub const ZERO: Self = FailEntropy([0; 64]);
pub fn from_byte_array(data: [u8; 64]) -> Self {
FailEntropy(data)
}
}
impl fmt::Display for FailEntropy {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&hex::DisplayHex::as_hex(&self.0), f)
}
}
impl AsRef<[u8]> for FailEntropy {
fn as_ref(&self) -> &[u8] {
self.0.as_ref()
}
}
fn compact_value(value: &Value) -> [u8; 32] {
let (mut bytes, bit_length) = value.iter_compact().collect_bits();
if bit_length % 8 == 0 {
bytes.push(0x80);
} else {
let delimiter_index = bit_length % 8;
*bytes.last_mut().unwrap() |= 1 << (7 - delimiter_index);
}
let k = if bytes.len() % 64 > 56 {
56 + (64 - (bytes.len() % 64))
} else {
56 - (bytes.len() % 64)
};
bytes.resize(bytes.len() + k, 0x00);
debug_assert!(bytes.len() % 64 == 56);
let bit_length_bytes = (bit_length as u64).to_be_bytes();
bytes.extend(bit_length_bytes.iter());
debug_assert!(bytes.len() % 16 == 0);
let mut consumed = 0;
let mut engine = sha256::HashEngine::default();
while consumed < bytes.len() {
engine.input(&bytes[consumed..(consumed + 16)]);
consumed += 16;
}
debug_assert!(consumed == bytes.len());
engine.midstate().to_byte_array()
}
fn bip340_iv(tag: &[u8]) -> sha256::Midstate {
let tag_hash = sha256::Hash::hash(tag);
let mut engine = sha256::Hash::engine();
engine.input(tag_hash.as_ref());
engine.input(tag_hash.as_ref());
engine.midstate()
}
#[macro_export]
macro_rules! impl_midstate_wrapper {
($wrapper:ident) => {
impl AsRef<[u8]> for $wrapper {
fn as_ref(&self) -> &[u8] {
self.0.as_ref()
}
}
impl std::fmt::Debug for $wrapper {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
std::fmt::Display::fmt(&hex::DisplayHex::as_hex(self.as_ref()), f)
}
}
impl std::fmt::Display for $wrapper {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
std::fmt::Debug::fmt(self, f)
}
}
impl std::str::FromStr for $wrapper {
type Err = hashes::hex::HexToArrayError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let x: [u8; 32] = hashes::hex::FromHex::from_hex(s)?;
Ok($wrapper(Midstate::from_byte_array(x)))
}
}
impl $wrapper {
pub fn update(self, left: Self, right: Self) -> Self {
use $crate::hashes::{sha256, HashEngine};
let mut engine = sha256::HashEngine::from_midstate(self.0, 0);
engine.input(left.as_ref());
engine.input(right.as_ref());
$wrapper(engine.midstate())
}
pub fn update_1(self, right: Self) -> Self {
use $crate::hashes::{sha256, HashEngine};
let mut engine = sha256::HashEngine::from_midstate(self.0, 0);
engine.input(&[0; 32]);
engine.input(&right.as_ref());
$wrapper(engine.midstate())
}
pub fn update_with_weight(self, left_weight: u64, right: Self) -> Self {
use $crate::hashes::{sha256, HashEngine};
let mut engine = sha256::HashEngine::from_midstate(self.0, 0);
let mut left_blk = [0; 32];
left_blk[24..].copy_from_slice(&left_weight.to_be_bytes());
engine.input(&left_blk);
engine.input(right.as_ref());
$wrapper(engine.midstate())
}
pub fn update_fail_entropy(self, entropy: $crate::FailEntropy) -> Self {
use $crate::hashes::{sha256, HashEngine};
let mut engine = sha256::HashEngine::from_midstate(self.0, 0);
engine.input(entropy.as_ref());
$wrapper(engine.midstate())
}
pub fn from_byte_array(data: [u8; 32]) -> Self {
$wrapper(Midstate::from_byte_array(data))
}
pub fn to_byte_array(self) -> [u8; 32] {
self.0.to_byte_array()
}
}
impl_serde_string!($wrapper);
};
}