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

tari-project / tari / 19627520782

24 Nov 2025 08:11AM UTC coverage: 61.332% (-0.04%) from 61.372%
19627520782

push

github

web-flow
feat: improve wallet validation performance (#7596)

Description
---
Dont recheck 5 days' worth of transactions every time you need to
recheck the transaction statuses.
This will be processing a reorg, mark effected transactions as needing a
revalidate.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added blockchain reorganization handling via a new process_reorg flow
to detect and process reorgs.
* UTXO scanner now propagates reorganization events to the transaction
service to keep state consistent.

* **Changes**
* Reduced transaction confirmation safety margin from 3000 to 100
blocks.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

0 of 44 new or added lines in 5 files covered. (0.0%)

40 existing lines in 11 files now uncovered.

70419 of 114817 relevant lines covered (61.33%)

228356.89 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,580✔
50
        if accumulated_data.hash != block.hash() {
1,580✔
51
            return None;
×
52
        }
1,580✔
53

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

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

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

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

73
    /// Returns a reference to the inner block's header
74
    pub fn header(&self) -> &BlockHeader {
4,224✔
75
        &self.block.header
4,224✔
76
    }
4,224✔
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> {
502✔
81
        self.block.clone()
502✔
82
    }
502✔
83

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

88
    pub fn to_chain_header(&self) -> ChainHeader {
1,034✔
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,034✔
92
    }
1,034✔
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,424✔
115
        if accumulated_data.hash != header.hash() {
7,424✔
UNCOV
116
            return None;
×
117
        }
7,424✔
118

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

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

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

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

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

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

145
    pub fn into_parts(self) -> (BlockHeader, BlockHeaderAccumulatedData) {
227✔
146
        (self.header, self.accumulated_data)
227✔
147
    }
227✔
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