• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In
No new info detected.

Neptune-Crypto / neptune-core / 13934460366

18 Mar 2025 10:10PM UTC coverage: 84.31% (+0.03%) from 84.279%
13934460366

Pull #512

github

web-flow
Merge 9c4947ba6 into ee3795966
Pull Request #512: `proptest_state_machine` over `PeerMessage`

9 of 26 new or added lines in 7 files covered. (34.62%)

42 existing lines in 5 files now uncovered.

50796 of 60249 relevant lines covered (84.31%)

178560.53 hits per line

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

98.75
/src/models/state/transaction_kernel_id.rs
1
use std::fmt::Display;
2

3
use get_size2::GetSize;
4
use itertools::Itertools;
5
use serde::Deserialize;
6
use serde::Serialize;
7
use tasm_lib::triton_vm::prelude::Digest;
8
use tasm_lib::triton_vm::prelude::Tip5;
9
use tasm_lib::twenty_first::prelude::MerkleTree;
10

11
use crate::models::blockchain::transaction::transaction_kernel::TransactionKernel;
12

13
/// A unique identifier of a transaction whose value is unaffected by a
14
/// transaction update.
15
#[derive(Debug, Clone, Copy, PartialEq, Eq, GetSize, Hash, Serialize, Deserialize)]
16✔
NEW
16
#[cfg_attr(any(test, feature = "arbitrary-impls"), derive(arbitrary::Arbitrary))]
×
17
pub struct TransactionKernelId(Digest);
18

19
impl Display for TransactionKernelId {
20
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
28✔
21
        write!(f, "{}", self.0.to_hex())
28✔
22
    }
28✔
23
}
24

25
impl TransactionKernel {
26
    // Return a digest that is unchanged by transaction updates.
27
    ///
28
    /// Return a digest that only commits to those fields of the
29
    /// [TransactionKernel] that are *unchanged* by a transaction update, where
30
    /// a transaction update makes a transaction valid relative to a new state
31
    /// of the mutator set. A transaction update refers to the returned
32
    /// transaction from [new_with_updated_mutator_set_records].
33
    ///
34
    ///
35
    /// [new_with_updated_mutator_set_records]: super::Transaction
36
    pub(crate) fn txid(&self) -> TransactionKernelId {
538✔
37
        // Since the `Update` program allows permutation of inputs, we must sort
538✔
38
        // the digests of the absolute indices to arrive at a digest that is
538✔
39
        // unchanged by an update.
538✔
40
        let mut index_set_hash = self
538✔
41
            .inputs
538✔
42
            .iter()
538✔
43
            .map(|x| Tip5::hash(&x.absolute_indices))
744✔
44
            .collect_vec();
538✔
45
        index_set_hash.sort_unstable();
538✔
46
        let index_set_hash = index_set_hash
538✔
47
            .into_iter()
538✔
48
            .flat_map(|x| x.values().to_vec())
744✔
49
            .collect_vec();
538✔
50
        let index_set_hash = Tip5::hash_varlen(&index_set_hash);
538✔
51

538✔
52
        // The `Update` consensus program does not permit permutation of outputs
538✔
53
        // so we don't have to sort here.
538✔
54
        let output_hash = self
538✔
55
            .outputs
538✔
56
            .iter()
538✔
57
            .flat_map(|x| x.canonical_commitment.values().to_vec())
5,900✔
58
            .collect_vec();
538✔
59
        let output_hash = Tip5::hash_varlen(&output_hash);
538✔
60

538✔
61
        // No permutation of public announcements allowed
538✔
62
        let public_announcements_hash = self
538✔
63
            .public_announcements
538✔
64
            .iter()
538✔
65
            .flat_map(|x| Tip5::hash_varlen(&x.message).values().to_vec())
724✔
66
            .collect_vec();
538✔
67
        let public_announcements_hash = Tip5::hash_varlen(&public_announcements_hash);
538✔
68

538✔
69
        let fee_hash = Tip5::hash(&self.fee);
538✔
70

538✔
71
        let coinbase_hash = Tip5::hash(&self.coinbase);
538✔
72

538✔
73
        let merge_bit_hash = Tip5::hash(&self.merge_bit);
538✔
74

538✔
75
        // Build a Merkle tree from all five digests, and treat the root as the
538✔
76
        // digest
538✔
77
        let mut digests = vec![
538✔
78
            index_set_hash,
538✔
79
            output_hash,
538✔
80
            public_announcements_hash,
538✔
81
            fee_hash,
538✔
82
            coinbase_hash,
538✔
83
            merge_bit_hash,
538✔
84
        ];
538✔
85

86
        // pad until length is a power of two
87
        while digests.len() & (digests.len() - 1) != 0 {
1,614✔
88
            digests.push(Digest::default());
1,076✔
89
        }
1,076✔
90

91
        let as_digest = MerkleTree::par_new(&digests).unwrap().root();
538✔
92

538✔
93
        TransactionKernelId(as_digest)
538✔
94
    }
538✔
95
}
96

97
#[cfg(test)]
98
mod tests {
99
    use proptest::prelude::Strategy;
100
    use proptest::strategy::ValueTree;
101
    use proptest::test_runner::TestRunner;
102

103
    use crate::models::blockchain::transaction::primitive_witness::PrimitiveWitness;
104
    use crate::models::blockchain::transaction::Transaction;
105

106
    #[test]
107
    fn txid_value_is_constant_under_transaction_update() {
1✔
108
        // Verify that the function `txid` returns the same digest before and
1✔
109
        // after a transaction has been updated wrt. a new block.
1✔
110
        let mut test_runner = TestRunner::deterministic();
1✔
111

1✔
112
        let [to_be_updated, mined] =
1✔
113
            PrimitiveWitness::arbitrary_tuple_with_matching_mutator_sets([(4, 4, 4), (3, 3, 3)])
1✔
114
                .new_tree(&mut test_runner)
1✔
115
                .unwrap()
1✔
116
                .current();
1✔
117
        let tx_id_original = to_be_updated.kernel.txid();
1✔
118

1✔
119
        let additions = mined.kernel.outputs.clone();
1✔
120
        let removals = mined.kernel.inputs.clone();
1✔
121
        let updated =
1✔
122
            Transaction::new_with_primitive_witness_ms_data(to_be_updated, additions, removals);
1✔
123

1✔
124
        assert_eq!(tx_id_original, updated.kernel.txid());
1✔
125
    }
1✔
126
}
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