kaspa_consensus_core/
header.rs1use crate::{hashing, BlueWorkType};
2use borsh::{BorshDeserialize, BorshSerialize};
3use kaspa_hashes::Hash;
4use kaspa_utils::mem_size::MemSizeEstimator;
5use serde::{Deserialize, Serialize};
6
7#[derive(Clone, Debug, Serialize, Deserialize, BorshSerialize, BorshDeserialize)]
9#[serde(rename_all = "camelCase")]
10pub struct Header {
11 pub hash: Hash,
13 pub version: u16,
14 pub parents_by_level: Vec<Vec<Hash>>,
15 pub hash_merkle_root: Hash,
16 pub accepted_id_merkle_root: Hash,
17 pub utxo_commitment: Hash,
18 pub timestamp: u64,
20 pub bits: u32,
21 pub nonce: u64,
22 pub daa_score: u64,
23 pub blue_work: BlueWorkType,
24 pub blue_score: u64,
25 pub pruning_point: Hash,
26}
27
28impl Header {
29 #[allow(clippy::too_many_arguments)]
30 pub fn new_finalized(
31 version: u16,
32 parents_by_level: Vec<Vec<Hash>>,
33 hash_merkle_root: Hash,
34 accepted_id_merkle_root: Hash,
35 utxo_commitment: Hash,
36 timestamp: u64,
37 bits: u32,
38 nonce: u64,
39 daa_score: u64,
40 blue_work: BlueWorkType,
41 blue_score: u64,
42 pruning_point: Hash,
43 ) -> Self {
44 let mut header = Self {
45 hash: Default::default(), version,
47 parents_by_level,
48 hash_merkle_root,
49 accepted_id_merkle_root,
50 utxo_commitment,
51 nonce,
52 timestamp,
53 daa_score,
54 bits,
55 blue_work,
56 blue_score,
57 pruning_point,
58 };
59 header.finalize();
60 header
61 }
62
63 pub fn finalize(&mut self) {
65 self.hash = hashing::header::hash(self);
66 }
67
68 pub fn direct_parents(&self) -> &[Hash] {
69 if self.parents_by_level.is_empty() {
70 &[]
71 } else {
72 &self.parents_by_level[0]
73 }
74 }
75
76 pub fn from_precomputed_hash(hash: Hash, parents: Vec<Hash>) -> Header {
78 Header {
79 version: crate::constants::BLOCK_VERSION,
80 hash,
81 parents_by_level: vec![parents],
82 hash_merkle_root: Default::default(),
83 accepted_id_merkle_root: Default::default(),
84 utxo_commitment: Default::default(),
85 nonce: 0,
86 timestamp: 0,
87 daa_score: 0,
88 bits: 0,
89 blue_work: 0.into(),
90 blue_score: 0,
91 pruning_point: Default::default(),
92 }
93 }
94}
95
96impl AsRef<Header> for Header {
97 fn as_ref(&self) -> &Header {
98 self
99 }
100}
101
102impl MemSizeEstimator for Header {
103 fn estimate_mem_bytes(&self) -> usize {
104 size_of::<Self>() + self.parents_by_level.iter().map(|l| l.len()).sum::<usize>() * size_of::<Hash>()
105 }
106}
107
108#[cfg(test)]
109mod tests {
110 use super::*;
111 use kaspa_math::Uint192;
112 use serde_json::Value;
113
114 #[test]
115 fn test_header_ser() {
116 let header = Header::new_finalized(
117 1,
118 vec![vec![1.into()]],
119 Default::default(),
120 Default::default(),
121 Default::default(),
122 234,
123 23,
124 567,
125 0,
126 Uint192([0x1234567890abcfed, 0xc0dec0ffeec0ffee, 0x1234567890abcdef]),
127 u64::MAX,
128 Default::default(),
129 );
130 let json = serde_json::to_string(&header).unwrap();
131 println!("{}", json);
132
133 let v = serde_json::from_str::<Value>(&json).unwrap();
134 let blue_work = v.get("blueWork").expect("missing `blueWork` property");
135 let blue_work = blue_work.as_str().expect("`blueWork` is not a string");
136 assert_eq!(blue_work, "1234567890abcdefc0dec0ffeec0ffee1234567890abcfed");
137 let blue_score = v.get("blueScore").expect("missing `blueScore` property");
138 let blue_score: u64 = blue_score.as_u64().expect("blueScore is not a u64 compatible value");
139 assert_eq!(blue_score, u64::MAX);
140
141 let h = serde_json::from_str::<Header>(&json).unwrap();
142 assert!(h.blue_score == header.blue_score && h.blue_work == header.blue_work);
143 }
144}