sapio_base/
util.rs

1// Copyright Judica, Inc 2021
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4//  License, v. 2.0. If a copy of the MPL was not distributed with this
5//  file, You can obtain one at https://mozilla.org/MPL/2.0/.
6
7use bitcoin::consensus::encode::Encodable;
8use bitcoin::hashes::sha256;
9use bitcoin::hashes::Hash;
10use bitcoin::util::amount::Amount;
11
12/// Any type which can generate a CTVHash. Allows some decoupling in the future if some types will
13/// not be literal transactions.
14/// TODO: Rename to something like Transaction Extension Features
15pub trait CTVHash {
16    /// Uses BIP-119 Logic to compute a CTV Hash
17    fn get_ctv_hash(&self, input_index: u32) -> sha256::Hash;
18    /// Gets the total amount a transaction creates in outputs.
19    fn total_amount(&self) -> Amount;
20}
21impl CTVHash for bitcoin::Transaction {
22    fn get_ctv_hash(&self, input_index: u32) -> sha256::Hash {
23        let mut ctv_hash = sha256::Hash::engine();
24        self.version.consensus_encode(&mut ctv_hash).unwrap();
25        self.lock_time.consensus_encode(&mut ctv_hash).unwrap();
26        (self.input.len() as u32)
27            .consensus_encode(&mut ctv_hash)
28            .unwrap();
29        {
30            let mut enc = sha256::Hash::engine();
31            for seq in self.input.iter().map(|i| i.sequence) {
32                seq.consensus_encode(&mut enc).unwrap();
33            }
34            sha256::Hash::from_engine(enc)
35                .into_inner()
36                .consensus_encode(&mut ctv_hash)
37                .unwrap();
38        }
39
40        (self.output.len() as u32)
41            .consensus_encode(&mut ctv_hash)
42            .unwrap();
43
44        {
45            let mut enc = sha256::Hash::engine();
46            for out in self.output.iter() {
47                out.consensus_encode(&mut enc).unwrap();
48            }
49            sha256::Hash::from_engine(enc)
50                .into_inner()
51                .consensus_encode(&mut ctv_hash)
52                .unwrap();
53        }
54        input_index.consensus_encode(&mut ctv_hash).unwrap();
55        sha256::Hash::from_engine(ctv_hash)
56    }
57
58    fn total_amount(&self) -> Amount {
59        Amount::from_sat(self.output.iter().fold(0, |a, b| a + b.value))
60    }
61}