floresta_chain/pruned_utreexo/
chainstore.rsuse bitcoin::block::Header as BlockHeader;
use bitcoin::consensus::Decodable;
use bitcoin::consensus::Encodable;
use bitcoin::BlockHash;
use crate::prelude::*;
use crate::BlockchainError;
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum DiskBlockHeader {
FullyValid(BlockHeader, u32),
AssumedValid(BlockHeader, u32),
Orphan(BlockHeader),
HeadersOnly(BlockHeader, u32),
InFork(BlockHeader, u32),
InvalidChain(BlockHeader),
}
impl DiskBlockHeader {
pub fn block_hash(&self) -> BlockHash {
self.deref().block_hash()
}
pub fn height(&self) -> Option<u32> {
match self {
DiskBlockHeader::InFork(_, height) => Some(*height),
DiskBlockHeader::FullyValid(_, height) => Some(*height),
DiskBlockHeader::HeadersOnly(_, height) => Some(*height),
DiskBlockHeader::AssumedValid(_, height) => Some(*height),
DiskBlockHeader::Orphan(_) => None,
DiskBlockHeader::InvalidChain(_) => None,
}
}
pub fn try_height(&self) -> Result<u32, BlockchainError> {
self.height().ok_or(BlockchainError::OrphanOrInvalidBlock)
}
}
impl Deref for DiskBlockHeader {
type Target = BlockHeader;
fn deref(&self) -> &Self::Target {
match self {
DiskBlockHeader::FullyValid(header, _) => header,
DiskBlockHeader::Orphan(header) => header,
DiskBlockHeader::HeadersOnly(header, _) => header,
DiskBlockHeader::InFork(header, _) => header,
DiskBlockHeader::InvalidChain(header) => header,
DiskBlockHeader::AssumedValid(header, _) => header,
}
}
}
impl Decodable for DiskBlockHeader {
fn consensus_decode<R: bitcoin::io::Read + ?Sized>(
reader: &mut R,
) -> core::result::Result<Self, bitcoin::consensus::encode::Error> {
let tag = u8::consensus_decode(reader)?;
let header = BlockHeader::consensus_decode(reader)?;
match tag {
0x00 => {
let height = u32::consensus_decode(reader)?;
Ok(Self::FullyValid(header, height))
}
0x01 => Ok(Self::Orphan(header)),
0x02 => {
let height = u32::consensus_decode(reader)?;
Ok(Self::HeadersOnly(header, height))
}
0x03 => {
let height = u32::consensus_decode(reader)?;
Ok(Self::InFork(header, height))
}
0x04 => Ok(Self::InvalidChain(header)),
0x05 => {
let height = u32::consensus_decode(reader)?;
Ok(Self::AssumedValid(header, height))
}
_ => unreachable!(),
}
}
}
impl Encodable for DiskBlockHeader {
fn consensus_encode<W: bitcoin::io::Write + ?Sized>(
&self,
writer: &mut W,
) -> bitcoin::io::Result<usize> {
let mut len = 80 + 1; match self {
DiskBlockHeader::FullyValid(header, height) => {
0x00_u8.consensus_encode(writer)?;
header.consensus_encode(writer)?;
height.consensus_encode(writer)?;
len += 4;
}
DiskBlockHeader::Orphan(header) => {
0x01_u8.consensus_encode(writer)?;
header.consensus_encode(writer)?;
}
DiskBlockHeader::HeadersOnly(header, height) => {
0x02_u8.consensus_encode(writer)?;
header.consensus_encode(writer)?;
height.consensus_encode(writer)?;
len += 4;
}
DiskBlockHeader::InFork(header, height) => {
0x03_u8.consensus_encode(writer)?;
header.consensus_encode(writer)?;
height.consensus_encode(writer)?;
len += 4;
}
DiskBlockHeader::InvalidChain(header) => {
0x04_u8.consensus_encode(writer)?;
header.consensus_encode(writer)?;
}
DiskBlockHeader::AssumedValid(header, height) => {
0x05_u8.consensus_encode(writer)?;
header.consensus_encode(writer)?;
height.consensus_encode(writer)?;
len += 4;
}
};
Ok(len)
}
}