kaspa_consensus_core/
lib.rs

1//!
2//! # Consensus Core
3//!
4//! This crate implements primitives used in the Kaspa node consensus processing.
5//!
6
7extern crate alloc;
8extern crate core;
9extern crate self as consensus_core;
10
11use std::collections::{HashMap, HashSet};
12use std::hash::{BuildHasher, Hasher};
13
14pub use kaspa_hashes::Hash;
15
16pub mod acceptance_data;
17pub mod api;
18pub mod block;
19pub mod blockhash;
20pub mod blockstatus;
21pub mod coinbase;
22pub mod config;
23pub mod constants;
24pub mod daa_score_timestamp;
25pub mod errors;
26pub mod hashing;
27pub mod header;
28pub mod mass;
29pub mod merkle;
30pub mod muhash;
31pub mod network;
32pub mod pruning;
33pub mod sign;
34pub mod subnets;
35pub mod trusted;
36pub mod tx;
37pub mod utxo;
38
39/// Integer type for accumulated PoW of blue blocks. We expect no more than
40/// 2^128 work in a single block (btc has ~2^80), and no more than 2^64
41/// overall blocks, so 2^192 is definitely a justified upper-bound.
42pub type BlueWorkType = kaspa_math::Uint192;
43
44/// The type used to represent the GHOSTDAG K parameter
45pub type KType = u16;
46
47/// Map from Block hash to K type
48pub type HashKTypeMap = std::sync::Arc<BlockHashMap<KType>>;
49
50/// This HashMap skips the hashing of the key and uses the key directly as the hash.
51/// Should only be used for block hashes that have correct DAA,
52/// otherwise it is susceptible to DOS attacks via hash collisions.
53pub type BlockHashMap<V> = HashMap<Hash, V, BlockHasher>;
54
55/// Same as `BlockHashMap` but a `HashSet`.
56pub type BlockHashSet = HashSet<Hash, BlockHasher>;
57
58pub trait HashMapCustomHasher {
59    fn new() -> Self;
60    fn with_capacity(capacity: usize) -> Self;
61}
62
63// HashMap::new and HashMap::with_capacity are only implemented on Hasher=RandomState
64// to avoid type inference problems, so we need to provide our own versions.
65impl<V> HashMapCustomHasher for BlockHashMap<V> {
66    #[inline(always)]
67    fn new() -> Self {
68        Self::with_hasher(BlockHasher::new())
69    }
70    #[inline(always)]
71    fn with_capacity(cap: usize) -> Self {
72        Self::with_capacity_and_hasher(cap, BlockHasher::new())
73    }
74}
75
76impl HashMapCustomHasher for BlockHashSet {
77    #[inline(always)]
78    fn new() -> Self {
79        Self::with_hasher(BlockHasher::new())
80    }
81    #[inline(always)]
82    fn with_capacity(cap: usize) -> Self {
83        Self::with_capacity_and_hasher(cap, BlockHasher::new())
84    }
85}
86
87#[derive(Default, Debug)]
88pub struct ChainPath {
89    pub added: Vec<Hash>,
90    pub removed: Vec<Hash>,
91}
92
93/// `hashes::Hash` writes 4 u64s so we just use the last one as the hash here
94#[derive(Default, Clone, Copy)]
95pub struct BlockHasher(u64);
96
97impl BlockHasher {
98    #[inline(always)]
99    pub const fn new() -> Self {
100        Self(0)
101    }
102}
103
104impl Hasher for BlockHasher {
105    #[inline(always)]
106    fn finish(&self) -> u64 {
107        self.0
108    }
109    #[inline(always)]
110    fn write_u64(&mut self, v: u64) {
111        self.0 = v;
112    }
113    #[cold]
114    fn write(&mut self, _: &[u8]) {
115        unimplemented!("use write_u64")
116    }
117}
118
119impl BuildHasher for BlockHasher {
120    type Hasher = Self;
121
122    #[inline(always)]
123    fn build_hasher(&self) -> Self::Hasher {
124        Self(0)
125    }
126}
127
128pub type BlockLevel = u8;
129
130#[cfg(test)]
131mod tests {
132    use super::BlockHasher;
133    use kaspa_hashes::Hash;
134    use std::hash::{Hash as _, Hasher as _};
135    #[test]
136    fn test_block_hasher() {
137        let hash = Hash::from_le_u64([1, 2, 3, 4]);
138        let mut hasher = BlockHasher::default();
139        hash.hash(&mut hasher);
140        assert_eq!(hasher.finish(), 4);
141    }
142}