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

tari-project / tari / 18097567115

29 Sep 2025 12:50PM UTC coverage: 58.554% (-2.3%) from 60.88%
18097567115

push

github

web-flow
chore(ci): switch rust toolchain to stable (#7524)

Description
switch rust toolchain to stable

Motivation and Context
use stable rust toolchain


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

## Summary by CodeRabbit

* **Chores**
* Standardized Rust toolchain on stable across CI workflows for more
predictable builds.
* Streamlined setup by removing unnecessary components and aligning
toolchain configuration with environment variables.
  * Enabled an environment flag to improve rustup behavior during CI.
* Improved coverage workflow consistency with dynamic toolchain
selection.

* **Tests**
* Removed nightly-only requirements, simplifying test commands and
improving compatibility.
* Expanded CI triggers to include ci-* branches for better pre-merge
validation.
* Maintained existing job logic while improving reliability and
maintainability.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

66336 of 113291 relevant lines covered (58.55%)

551641.45 hits per line

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

89.55
/base_layer/transaction_components/src/transaction_components/transaction_kernel.rs
1
// Copyright 2018 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
// Portions of this file were originally copyrighted (c) 2018 The Grin Developers, issued under the Apache License,
24
// Version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0.
25

26
use std::{
27
    cmp::Ordering,
28
    fmt::{Display, Formatter},
29
};
30

31
use blake2::Blake2b;
32
use borsh::{BorshDeserialize, BorshSerialize};
33
use digest::consts::{U32, U64};
34
use serde::{Deserialize, Serialize};
35
use tari_common_types::types::{CompressedCommitment, CompressedPublicKey, CompressedSignature, FixedHash};
36
use tari_hashing::TransactionHashDomain;
37
use tari_utilities::{hex::Hex, message_format::MessageFormat};
38

39
use super::TransactionKernelVersion;
40
use crate::{
41
    consensus::DomainSeparatedConsensusHasher,
42
    transaction_components::{KernelFeatures, TransactionError},
43
    MicroMinotari,
44
};
45

46
/// The transaction kernel tracks the excess for a given transaction. For an explanation of what the excess is, and
47
/// why it is necessary, refer to the
48
/// [Mimblewimble TLU post](https://tlu.tarilabs.com/protocols/mimblewimble-1/sources/PITCHME.link.html?highlight=mimblewimble#mimblewimble).
49
/// The kernel also tracks other transaction metadata, such as the lock height for the transaction (i.e. the earliest
50
/// this transaction can be mined) and the transaction fee, in cleartext.
51
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, BorshSerialize, BorshDeserialize, Default)]
×
52
pub struct TransactionKernel {
53
    pub version: TransactionKernelVersion,
54
    /// Options for a kernel's structure or use
55
    pub features: KernelFeatures,
56
    /// Fee originally included in the transaction this proof is for.
57
    pub fee: MicroMinotari,
58
    /// This kernel is not valid earlier than lock_height blocks
59
    /// The max lock_height of all *inputs* to this transaction
60
    pub lock_height: u64,
61
    /// Remainder of the sum of all transaction commitments (minus an offset). If the transaction is well-formed,
62
    /// amounts plus fee will sum to zero, and the excess is hence a valid public key.
63
    pub excess: CompressedCommitment,
64
    /// An aggregated signature of the metadata in this kernel, signed by the individual excess values and the offset
65
    /// excess of the sender.
66
    pub excess_sig: CompressedSignature,
67
    /// This is an optional field that must be set if the transaction contains a burned output.
68
    pub burn_commitment: Option<CompressedCommitment>,
69
}
70

71
impl TransactionKernel {
72
    pub fn new(
331✔
73
        version: TransactionKernelVersion,
331✔
74
        features: KernelFeatures,
331✔
75
        fee: MicroMinotari,
331✔
76
        lock_height: u64,
331✔
77
        excess: CompressedCommitment,
331✔
78
        excess_sig: CompressedSignature,
331✔
79
        burn_commitment: Option<CompressedCommitment>,
331✔
80
    ) -> TransactionKernel {
331✔
81
        TransactionKernel {
331✔
82
            version,
331✔
83
            features,
331✔
84
            fee,
331✔
85
            lock_height,
331✔
86
            excess,
331✔
87
            excess_sig,
331✔
88
            burn_commitment,
331✔
89
        }
331✔
90
    }
331✔
91

92
    /// Produce a canonical hash for a transaction kernel.
93
    pub fn hash(&self) -> FixedHash {
3,166✔
94
        DomainSeparatedConsensusHasher::<TransactionHashDomain, Blake2b<U32>>::new("transaction_kernel")
3,166✔
95
            .chain(self)
3,166✔
96
            .finalize()
3,166✔
97
            .into()
3,166✔
98
    }
3,166✔
99

100
    pub fn new_current_version(
321✔
101
        features: KernelFeatures,
321✔
102
        fee: MicroMinotari,
321✔
103
        lock_height: u64,
321✔
104
        excess: CompressedCommitment,
321✔
105
        excess_sig: CompressedSignature,
321✔
106
        burn_commitment: Option<CompressedCommitment>,
321✔
107
    ) -> TransactionKernel {
321✔
108
        TransactionKernel::new(
321✔
109
            TransactionKernelVersion::get_current_version(),
321✔
110
            features,
321✔
111
            fee,
321✔
112
            lock_height,
321✔
113
            excess,
321✔
114
            excess_sig,
321✔
115
            burn_commitment,
321✔
116
        )
117
    }
321✔
118

119
    pub fn is_coinbase(&self) -> bool {
1✔
120
        self.features.is_coinbase()
1✔
121
    }
1✔
122

123
    /// Is this a burned output kernel?
124
    pub fn is_burned(&self) -> bool {
64✔
125
        self.features.is_burned()
64✔
126
    }
64✔
127

128
    pub fn verify_signature(&self) -> Result<(), TransactionError> {
634✔
129
        let excess = self.excess.to_compressed_key();
634✔
130
        let r = self.excess_sig.get_compressed_public_nonce();
634✔
131
        let c = TransactionKernel::build_kernel_signature_challenge(
634✔
132
            &self.version,
634✔
133
            r,
634✔
134
            &excess,
634✔
135
            self.fee,
634✔
136
            self.lock_height,
634✔
137
            &self.features,
634✔
138
            &self.burn_commitment,
634✔
139
        );
140

141
        if self
634✔
142
            .excess_sig
634✔
143
            .to_schnorr_signature()?
634✔
144
            .verify_raw_uniform(&excess.to_public_key()?, &c)
634✔
145
        {
146
            Ok(())
632✔
147
        } else {
148
            Err(TransactionError::InvalidSignatureError(
2✔
149
                "Verifying kernel signature".to_string(),
2✔
150
            ))
2✔
151
        }
152
    }
634✔
153

154
    /// This gets the burn commitment if it exists
155
    pub fn get_burn_commitment(&self) -> Result<&CompressedCommitment, TransactionError> {
11✔
156
        match self.burn_commitment {
11✔
157
            Some(ref burn_commitment) => Ok(burn_commitment),
11✔
158
            None => Err(TransactionError::InvalidKernel("Burn commitment not found".to_string())),
×
159
        }
160
    }
11✔
161

162
    /// Helper function to creates the kernel excess signature challenge.
163
    /// The challenge is defined as the hash of the following data:
164
    ///  Public nonce
165
    ///  Fee
166
    ///  Lock height
167
    ///  Features of the kernel
168
    ///  Burn commitment if present
169
    pub fn build_kernel_signature_challenge(
648✔
170
        version: &TransactionKernelVersion,
648✔
171
        sum_public_nonces: &CompressedPublicKey,
648✔
172
        total_excess: &CompressedPublicKey,
648✔
173
        fee: MicroMinotari,
648✔
174
        lock_height: u64,
648✔
175
        features: &KernelFeatures,
648✔
176
        burn_commitment: &Option<CompressedCommitment>,
648✔
177
    ) -> [u8; 64] {
648✔
178
        // We build the message separately to help with hardware wallet support. This reduces the amount of data that
179
        // needs to be transferred in order to sign the signature.
180
        let message =
648✔
181
            TransactionKernel::build_kernel_signature_message(version, fee, lock_height, features, burn_commitment);
648✔
182
        TransactionKernel::finalize_kernel_signature_challenge(version, sum_public_nonces, total_excess, &message)
648✔
183
    }
648✔
184

185
    /// Helper function to finalize the kernel excess signature challenge.
186
    pub fn finalize_kernel_signature_challenge(
2,021✔
187
        version: &TransactionKernelVersion,
2,021✔
188
        sum_public_nonces: &CompressedPublicKey,
2,021✔
189
        total_excess: &CompressedPublicKey,
2,021✔
190
        message: &[u8; 32],
2,021✔
191
    ) -> [u8; 64] {
2,021✔
192
        let common = DomainSeparatedConsensusHasher::<TransactionHashDomain, Blake2b<U64>>::new("kernel_signature")
2,021✔
193
            .chain(sum_public_nonces)
2,021✔
194
            .chain(total_excess)
2,021✔
195
            .chain(message);
2,021✔
196
        match version {
2,021✔
197
            TransactionKernelVersion::V0 => common.finalize().into(),
2,021✔
198
        }
199
    }
2,021✔
200

201
    /// Convenience function to create the entire kernel signature message for the challenge. This contains all data
202
    /// outside of the signing keys and nonces.
203
    pub fn build_kernel_signature_message(
959✔
204
        version: &TransactionKernelVersion,
959✔
205
        fee: MicroMinotari,
959✔
206
        lock_height: u64,
959✔
207
        features: &KernelFeatures,
959✔
208
        burn_commitment: &Option<CompressedCommitment>,
959✔
209
    ) -> [u8; 32] {
959✔
210
        let common = DomainSeparatedConsensusHasher::<TransactionHashDomain, Blake2b<U32>>::new("kernel_message")
959✔
211
            .chain(version)
959✔
212
            .chain(&fee)
959✔
213
            .chain(&lock_height)
959✔
214
            .chain(features)
959✔
215
            .chain(burn_commitment);
959✔
216
        match version {
959✔
217
            TransactionKernelVersion::V0 => common.finalize().into(),
959✔
218
        }
219
    }
959✔
220
}
221

222
impl Display for TransactionKernel {
223
    fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
×
224
        write!(
×
225
            fmt,
×
226
            "Fee: {}\nLock height: {}\nFeatures: {:?}\nExcess: {}\nExcess signature: {}\nCommitment: {}\n",
×
227
            self.fee,
228
            self.lock_height,
229
            self.features,
230
            self.excess.to_hex(),
×
231
            self.excess_sig
×
232
                .to_json()
×
233
                .unwrap_or_else(|_| "Failed to serialize signature".into()),
×
234
            match self.burn_commitment {
×
235
                Some(ref burn_commitment) => burn_commitment.to_hex(),
×
236
                None => "None".to_string(),
×
237
            }
238
        )
239
    }
×
240
}
241

242
impl PartialOrd for TransactionKernel {
243
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
3,526✔
244
        Some(self.cmp(other))
3,526✔
245
    }
3,526✔
246
}
247

248
impl Ord for TransactionKernel {
249
    fn cmp(&self, other: &Self) -> Ordering {
3,526✔
250
        self.excess_sig.cmp(&other.excess_sig)
3,526✔
251
    }
3,526✔
252
}
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