• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

tari-project / tari / 20915643654

12 Jan 2026 10:16AM UTC coverage: 60.476% (+0.8%) from 59.709%
20915643654

push

github

SWvheerden
chore: new release v5.2.0-rc.1

70123 of 115951 relevant lines covered (60.48%)

226118.68 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

75.34
/base_layer/node_components/src/blocks/chain_block.rs
1
//  Copyright 2025, The Tari Project
2
//
3
//  Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
4
//  following conditions are met:
5
//
6
//  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
7
//  disclaimer.
8
//
9
//  2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
10
//  following disclaimer in the documentation and/or other materials provided with the distribution.
11
//
12
//  3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
13
//  products derived from this software without specific prior written permission.
14
//
15
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
16
//  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17
//  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
18
//  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19
//  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
20
//  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
21
//  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22

23
use std::{fmt, fmt::Display, sync::Arc};
24

25
use tari_common_types::types::HashOutput;
26
use tari_transaction_components::aggregated_body::AggregateBody;
27

28
use crate::blocks::{Block, BlockHeader, BlockHeaderAccumulatedData};
29

30
/// A block linked to a chain.
31
/// A ChainBlock MUST have the same or stronger guarantees than `ChainHeader`
32
#[derive(Debug, Clone, PartialEq)]
33
pub struct ChainBlock {
34
    accumulated_data: BlockHeaderAccumulatedData,
35
    block: Arc<Block>,
36
}
37

38
impl Display for ChainBlock {
39
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
×
40
        writeln!(f, "{}", self.accumulated_data)?;
×
41
        writeln!(f, "{}", self.block)?;
×
42
        Ok(())
×
43
    }
×
44
}
45

46
impl ChainBlock {
47
    /// Attempts to construct a `ChainBlock` from a `Block` and associate `BlockHeaderAccumulatedData`. Returns None if
48
    /// the Block and the BlockHeaderAccumulatedData do not correspond (i.e have different hashes)
49
    pub fn try_construct(block: Arc<Block>, accumulated_data: BlockHeaderAccumulatedData) -> Option<Self> {
1,633✔
50
        if accumulated_data.hash != block.hash() {
1,633✔
51
            return None;
×
52
        }
1,633✔
53

54
        Some(Self {
1,633✔
55
            accumulated_data,
1,633✔
56
            block,
1,633✔
57
        })
1,633✔
58
    }
1,633✔
59

60
    pub fn height(&self) -> u64 {
855✔
61
        self.block.header.height
855✔
62
    }
855✔
63

64
    pub fn hash(&self) -> &HashOutput {
1,316✔
65
        &self.accumulated_data.hash
1,316✔
66
    }
1,316✔
67

68
    /// Returns a reference to the inner block
69
    pub fn block(&self) -> &Block {
1,773✔
70
        &self.block
1,773✔
71
    }
1,773✔
72

73
    /// Returns a reference to the inner block's header
74
    pub fn header(&self) -> &BlockHeader {
4,281✔
75
        &self.block.header
4,281✔
76
    }
4,281✔
77

78
    /// Returns the inner block wrapped in an atomically reference counted (ARC) pointer. This call is cheap and does
79
    /// not copy the block in memory.
80
    pub fn to_arc_block(&self) -> Arc<Block> {
533✔
81
        self.block.clone()
533✔
82
    }
533✔
83

84
    pub fn accumulated_data(&self) -> &BlockHeaderAccumulatedData {
2,307✔
85
        &self.accumulated_data
2,307✔
86
    }
2,307✔
87

88
    pub fn to_chain_header(&self) -> ChainHeader {
1,066✔
89
        // NOTE: Panic is impossible, a ChainBlock cannot be constructed if inconsistencies between the header and
90
        // accum data exist
91
        ChainHeader::try_construct(self.block.header.clone(), self.accumulated_data.clone()).unwrap()
1,066✔
92
    }
1,066✔
93
}
94

95
/// A block linked to a chain.
96
/// A ChainHeader guarantees (i.e cannot be constructed) that the block and accumulated data correspond by hash.
97
#[derive(Debug, Clone, PartialEq)]
98
pub struct ChainHeader {
99
    header: BlockHeader,
100
    accumulated_data: BlockHeaderAccumulatedData,
101
}
102

103
impl Display for ChainHeader {
104
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
×
105
        writeln!(f, "{}", self.header)?;
×
106
        writeln!(f, "{}", self.accumulated_data)?;
×
107
        Ok(())
×
108
    }
×
109
}
110

111
impl ChainHeader {
112
    /// Attempts to construct a `ChainHeader` from a `BlockHeader` and associate `BlockHeaderAccumulatedData`. Returns
113
    /// None if the Block and the BlockHeaderAccumulatedData do not correspond (i.e have different hashes)
114
    pub fn try_construct(header: BlockHeader, accumulated_data: BlockHeaderAccumulatedData) -> Option<Self> {
7,683✔
115
        if accumulated_data.hash != header.hash() {
7,683✔
116
            return None;
×
117
        }
7,683✔
118

119
        Some(Self {
7,683✔
120
            header,
7,683✔
121
            accumulated_data,
7,683✔
122
        })
7,683✔
123
    }
7,683✔
124

125
    pub fn height(&self) -> u64 {
3,362✔
126
        self.header.height
3,362✔
127
    }
3,362✔
128

129
    pub fn timestamp(&self) -> u64 {
1,524✔
130
        self.header.timestamp.as_u64()
1,524✔
131
    }
1,524✔
132

133
    pub fn hash(&self) -> &HashOutput {
2,372✔
134
        &self.accumulated_data.hash
2,372✔
135
    }
2,372✔
136

137
    pub fn header(&self) -> &BlockHeader {
7,763✔
138
        &self.header
7,763✔
139
    }
7,763✔
140

141
    pub fn accumulated_data(&self) -> &BlockHeaderAccumulatedData {
3,168✔
142
        &self.accumulated_data
3,168✔
143
    }
3,168✔
144

145
    pub fn into_parts(self) -> (BlockHeader, BlockHeaderAccumulatedData) {
201✔
146
        (self.header, self.accumulated_data)
201✔
147
    }
201✔
148

149
    pub fn into_header(self) -> BlockHeader {
×
150
        self.header
×
151
    }
×
152

153
    pub fn upgrade_to_chain_block(self, body: AggregateBody) -> ChainBlock {
×
154
        // NOTE: Panic cannot occur because a ChainBlock has the same guarantees as ChainHeader
155
        ChainBlock::try_construct(Arc::new(Block::new(self.header, body)), self.accumulated_data).unwrap()
×
156
    }
×
157
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc