phoenix_core/
transaction.rs

1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at http://mozilla.org/MPL/2.0/.
4//
5// Copyright (c) DUSK NETWORK. All rights reserved.
6
7//! Transaction skeleton defining the minimum amount of data needed for a
8//! phoenix transaction.
9
10extern crate alloc;
11use alloc::vec::Vec;
12
13#[cfg(feature = "rkyv-impl")]
14use rkyv::{Archive, Deserialize, Serialize};
15
16use dusk_bls12_381::BlsScalar;
17use dusk_bytes::{DeserializableSlice, Error as BytesError, Serializable};
18
19use crate::{Note, OUTPUT_NOTES};
20
21/// A phoenix transaction, referred to as tx-skeleton in the specs.
22#[derive(Debug, Clone, PartialEq, Eq)]
23#[cfg_attr(
24    feature = "rkyv-impl",
25    derive(Archive, Serialize, Deserialize),
26    archive_attr(derive(bytecheck::CheckBytes))
27)]
28pub struct TxSkeleton {
29    /// The root of the transfer tree on top of which this transaction is
30    /// based.
31    pub root: BlsScalar,
32    /// The nullifiers of the old notes this transaction spends.
33    pub nullifiers: Vec<BlsScalar>,
34    /// The new output notes of this transaction.
35    pub outputs: [Note; OUTPUT_NOTES],
36    /// Describes the maximum fee to be paid for this transaction.
37    pub max_fee: u64,
38    /// A deposit is used to transferring funds to a contract
39    pub deposit: u64,
40}
41
42impl TxSkeleton {
43    /// Return input bytes to a hash function for the transaction.
44    #[must_use]
45    pub fn to_hash_input_bytes(&self) -> Vec<u8> {
46        let mut bytes = Vec::new();
47
48        bytes.extend(self.root.to_bytes());
49
50        for nullifier in &self.nullifiers {
51            bytes.extend(nullifier.to_bytes());
52        }
53        for note in &self.outputs {
54            bytes.extend(note.to_bytes());
55        }
56
57        bytes.extend(self.max_fee.to_bytes());
58        bytes.extend(self.deposit.to_bytes());
59
60        bytes
61    }
62
63    /// Serialize the transaction to a variable length byte buffer.
64    #[allow(unused_must_use)]
65    pub fn to_var_bytes(&self) -> Vec<u8> {
66        let mut bytes = Vec::new();
67
68        bytes.extend(self.root.to_bytes());
69
70        let num_nullifiers = self.nullifiers.len() as u64;
71        bytes.extend(num_nullifiers.to_bytes());
72        self.nullifiers.iter().for_each(|nullifier| {
73            bytes.extend(nullifier.to_bytes());
74        });
75
76        self.outputs.iter().for_each(|note| {
77            bytes.extend(note.to_bytes());
78        });
79
80        bytes.extend(self.max_fee.to_bytes());
81        bytes.extend(self.deposit.to_bytes());
82
83        bytes
84    }
85
86    /// Deserialize the transaction from a bytes buffer.
87    pub fn from_slice(buf: &[u8]) -> Result<Self, BytesError> {
88        let mut buffer = buf;
89        let root = BlsScalar::from_reader(&mut buffer)?;
90
91        let num_nullifiers = u64::from_reader(&mut buffer)?;
92        let mut nullifiers = Vec::with_capacity(num_nullifiers as usize);
93        for _ in 0..num_nullifiers {
94            nullifiers.push(BlsScalar::from_reader(&mut buffer)?);
95        }
96
97        let mut outputs = Vec::with_capacity(OUTPUT_NOTES);
98        for _ in 0..OUTPUT_NOTES {
99            outputs.push(Note::from_reader(&mut buffer)?);
100        }
101        let outputs: [Note; OUTPUT_NOTES] =
102            outputs.try_into().map_err(|_| BytesError::InvalidData)?;
103
104        let max_fee = u64::from_reader(&mut buffer)?;
105        let deposit = u64::from_reader(&mut buffer)?;
106
107        Ok(Self {
108            root,
109            nullifiers,
110            outputs,
111            max_fee,
112            deposit,
113        })
114    }
115
116    /// Returns the inputs to the transaction.
117    pub fn nullifiers(&self) -> &[BlsScalar] {
118        &self.nullifiers
119    }
120
121    /// Returns the outputs of the transaction.
122    pub fn outputs(&self) -> &[Note] {
123        &self.outputs
124    }
125
126    /// Returns the maximum fee of the transaction.
127    pub fn max_fee(&self) -> u64 {
128        self.max_fee
129    }
130
131    /// Returns the deposit of the transaction.
132    pub fn deposit(&self) -> u64 {
133        self.deposit
134    }
135}