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

tari-project / tari / 17584397018

09 Sep 2025 01:34PM UTC coverage: 60.008% (-0.9%) from 60.905%
17584397018

push

github

web-flow
feat: multi recipient support (#7480)

Description
---
Allows support of multiple recipients per single chain transaction. 
This will create a single on chain transaction with multiple recipients,
but in the wallet it will still only show a single transaction per
recipient.

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

- New Features
- Multi-recipient one-sided payments: send to many recipients in a
single request, returning multiple transaction IDs.
- Single-transaction toggle: choose to bundle multiple recipients into
one transaction or send separate transactions per recipient.

- Bug Fixes
- Added input validation with clear errors when no recipients are
provided.

- Refactor
- Safer memo construction and reduced memo data for large-recipient
transactions.

- Tests
  - Expanded multi-recipient and key-manager test coverage.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

417 of 585 new or added lines in 5 files covered. (71.28%)

1211 existing lines in 29 files now uncovered.

73153 of 121906 relevant lines covered (60.01%)

522967.98 hits per line

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

48.84
/base_layer/node_components/src/blocks/historical_block.rs
1
//  Copyright 2021, 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

27
use crate::blocks::{error::BlockError, Block, BlockHeader, BlockHeaderAccumulatedData, ChainBlock};
28

29
/// The representation of a historical block in the blockchain. It is essentially identical to a protocol-defined
30
/// block but contains some extra metadata that clients such as Block Explorers will find interesting.
31
#[derive(Debug, Clone, PartialEq)]
32
pub struct HistoricalBlock {
33
    /// The number of blocks that have been mined since this block, including this one. The current tip will have one
34
    /// confirmation.
35
    confirmations: u64,
36
    /// The underlying block
37
    block: Block,
38
    /// Accumulated data in the block header
39
    accumulated_data: BlockHeaderAccumulatedData,
40
}
41

42
impl HistoricalBlock {
43
    pub fn new(block: Block, confirmations: u64, accumulated_data: BlockHeaderAccumulatedData) -> Self {
61✔
44
        HistoricalBlock {
61✔
45
            confirmations,
61✔
46
            block,
61✔
47
            accumulated_data,
61✔
48
        }
61✔
49
    }
61✔
50

51
    pub fn confirmations(&self) -> u64 {
×
52
        self.confirmations
×
53
    }
×
54

55
    pub fn header(&self) -> &BlockHeader {
2✔
56
        &self.block.header
2✔
57
    }
2✔
58

59
    /// Returns a reference to the block of the HistoricalBlock
60
    pub fn block(&self) -> &Block {
26✔
61
        &self.block
26✔
62
    }
26✔
63

64
    pub fn into_block(self) -> Block {
11✔
65
        self.block
11✔
66
    }
11✔
67

UNCOV
68
    pub fn accumulated_data(&self) -> &BlockHeaderAccumulatedData {
×
UNCOV
69
        &self.accumulated_data
×
UNCOV
70
    }
×
71

72
    pub fn hash(&self) -> &HashOutput {
×
73
        &self.accumulated_data.hash
×
74
    }
×
75

76
    pub fn try_into_chain_block(self) -> Result<ChainBlock, BlockError> {
36✔
77
        let chain_block = ChainBlock::try_construct(Arc::new(self.block), self.accumulated_data).ok_or_else(|| {
36✔
78
            BlockError::ChainBlockInvariantError(
×
79
                "Unable to construct ChainBlock because of a hash mismatch".to_string(),
×
80
            )
×
81
        })?;
36✔
82

83
        Ok(chain_block)
36✔
84
    }
36✔
85

86
    pub fn dissolve(self) -> (Block, BlockHeaderAccumulatedData, u64) {
×
87
        (self.block, self.accumulated_data, self.confirmations)
×
88
    }
×
89
}
90

91
impl Display for HistoricalBlock {
92
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
×
93
        writeln!(f, "{}", self.block())?;
×
94
        Ok(())
×
95
    }
×
96
}
97

98
impl From<HistoricalBlock> for Block {
99
    fn from(block: HistoricalBlock) -> Self {
×
100
        block.block
×
101
    }
×
102
}
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