1use {
2 bitcoin::{
3 block::{Header, Version},
4 hashes::Hash,
5 BlockHash, CompactTarget, TxMerkleNode,
6 },
7 borsh::{BorshDeserialize, BorshSerialize},
8 ordinals::RuneId,
9 serde::{Deserialize, Serialize},
10 std::io::{Read, Result, Write},
11};
12
13#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
14pub struct Block {
15 pub height: u64,
16 pub header: Header,
17 pub tx_ids: Vec<String>,
18 pub etched_runes: Vec<RuneId>,
19}
20
21impl BorshSerialize for Block {
22 fn serialize<W: Write>(&self, writer: &mut W) -> Result<()> {
23 BorshSerialize::serialize(&self.height, writer)?;
25
26 BorshSerialize::serialize(&self.header.version.to_consensus(), writer)?;
28
29 BorshSerialize::serialize(
32 &self.header.prev_blockhash.as_raw_hash().as_byte_array(),
33 writer,
34 )?;
35
36 BorshSerialize::serialize(
37 &self.header.merkle_root.as_raw_hash().as_byte_array(),
38 writer,
39 )?;
40 BorshSerialize::serialize(&self.header.time, writer)?;
41 BorshSerialize::serialize(&self.header.bits.to_consensus(), writer)?;
42 BorshSerialize::serialize(&self.header.nonce, writer)?;
43
44 BorshSerialize::serialize(&self.tx_ids, writer)?;
47
48 let etched_len = self.etched_runes.len() as u64;
55 BorshSerialize::serialize(&etched_len, writer)?;
56
57 for rune_id in &self.etched_runes {
58 BorshSerialize::serialize(&rune_id.block, writer)?;
59 BorshSerialize::serialize(&rune_id.tx, writer)?;
60 }
61
62 Ok(())
63 }
64}
65
66impl BorshDeserialize for Block {
67 fn deserialize_reader<R: Read>(reader: &mut R) -> std::io::Result<Self> {
68 let height = u64::deserialize_reader(reader)?;
70
71 let version = Version::from_consensus(i32::deserialize_reader(reader)?);
73
74 let mut prev_hash = [0u8; 32];
75 reader.read_exact(&mut prev_hash)?;
76 let prev_blockhash =
77 BlockHash::from_raw_hash(Hash::from_slice(&prev_hash).map_err(|_| {
78 std::io::Error::new(std::io::ErrorKind::InvalidData, "Invalid prev_blockhash")
79 })?);
80
81 let mut merkle = [0u8; 32];
82 reader.read_exact(&mut merkle)?;
83 let merkle_root = TxMerkleNode::from_raw_hash(Hash::from_slice(&merkle).map_err(|_| {
84 std::io::Error::new(std::io::ErrorKind::InvalidData, "Invalid merkle_root")
85 })?);
86
87 let time = u32::deserialize_reader(reader)?;
88 let bits = CompactTarget::from_consensus(u32::deserialize_reader(reader)?);
89 let nonce = u32::deserialize_reader(reader)?;
90
91 let header = Header {
92 version,
93 prev_blockhash,
94 merkle_root,
95 time,
96 bits,
97 nonce,
98 };
99
100 let tx_ids = Vec::<String>::deserialize_reader(reader)?;
102
103 let etched_len = u64::deserialize_reader(reader)?;
108 let mut etched_runes = Vec::with_capacity(etched_len as usize);
109
110 for _ in 0..etched_len {
111 let block = u64::deserialize_reader(reader)?;
112 let tx = u32::deserialize_reader(reader)?;
113 etched_runes.push(RuneId { block, tx });
114 }
115
116 Ok(Self {
117 height,
118 header,
119 tx_ids,
120 etched_runes,
121 })
122 }
123}
124
125impl Block {
126 pub fn empty_block(height: u64, header: Header) -> Self {
127 Self {
128 height,
129 header,
130 tx_ids: vec![],
131 etched_runes: vec![],
132 }
133 }
134}