diff --git a/node-data/src/ledger.rs b/node-data/src/ledger.rs index dd0477fda1..eba2584324 100644 --- a/node-data/src/ledger.rs +++ b/node-data/src/ledger.rs @@ -10,6 +10,9 @@ pub use header::{Header, Seed}; mod block; pub use block::{Block, BlockWithLabel, Hash, Label}; +mod transaction; +pub use transaction::{SpentTransaction, Transaction}; + use crate::bls::{self, PublicKeyBytes}; use crate::message::payload::{RatificationResult, Vote}; use crate::Serializable; @@ -19,78 +22,11 @@ use rusk_abi::hash::Hasher; use sha3::Digest; use std::io::{self, Read, Write}; -use execution_core::{ - transfer::Transaction as PhoenixTransaction, BlsPublicKey, -}; +use execution_core::BlsPublicKey; #[cfg(any(feature = "faker", test))] use fake::{Dummy, Fake, Faker}; -#[derive(Debug, Clone)] -pub struct Transaction { - pub version: u32, - pub r#type: u32, - pub inner: PhoenixTransaction, -} - -impl From for Transaction { - fn from(value: PhoenixTransaction) -> Self { - Self { - inner: value, - r#type: 1, - version: 1, - } - } -} - -#[derive(Debug, Clone)] -pub struct SpentTransaction { - pub inner: Transaction, - pub block_height: u64, - pub gas_spent: u64, - pub err: Option, -} - -impl Transaction { - /// Computes the hash of the transaction. - /// - /// This method returns the [hash](rusk_abi::hash()) of the entire - /// transaction in its serialized form - /// - /// ### Returns - /// An array of 32 bytes representing the hash of the transaction. - pub fn hash(&self) -> [u8; 32] { - Hasher::digest(self.inner.to_var_bytes()).to_bytes() - } - - /// Computes the transaction ID. - /// - /// The transaction ID is a unique identifier for the transaction. - /// Unlike the [`hash()`](#method.hash) method, which is computed over the - /// entire transaction, the transaction ID is derived from specific - /// fields of the transaction and serves as a unique identifier of the - /// transaction itself. - /// - /// ### Returns - /// An array of 32 bytes representing the transaction ID. - pub fn id(&self) -> [u8; 32] { - Hasher::digest(self.inner.to_hash_input_bytes()).to_bytes() - } - - pub fn gas_price(&self) -> u64 { - self.inner.payload().fee().gas_price - } - pub fn to_nullifiers(&self) -> Vec<[u8; 32]> { - self.inner - .payload() - .tx_skeleton() - .nullifiers() - .iter() - .map(|n| n.to_bytes()) - .collect() - } -} - #[derive(Debug, Clone, Copy, Default, Eq, PartialEq)] #[cfg_attr(any(feature = "faker", test), derive(Dummy))] pub struct Attestation { @@ -158,24 +94,6 @@ impl Default for Signature { } } -impl PartialEq for Transaction { - fn eq(&self, other: &Self) -> bool { - self.r#type == other.r#type - && self.version == other.version - && self.id() == other.id() - } -} - -impl Eq for Transaction {} - -impl PartialEq for SpentTransaction { - fn eq(&self, other: &Self) -> bool { - self.inner == other.inner && self.gas_spent == other.gas_spent - } -} - -impl Eq for SpentTransaction {} - /// Includes a failed attestation and the key of the expected block /// generator pub type IterationInfo = (Attestation, PublicKeyBytes); @@ -235,11 +153,8 @@ pub fn to_str(bytes: &[u8; N]) -> String { pub mod faker { use super::*; use crate::bls::PublicKeyBytes; - use execution_core::transfer::{ContractCall, Fee, Payload}; - use execution_core::{ - BlsScalar, JubJubScalar, Note, PublicKey, SecretKey, TxSkeleton, - }; use rand::Rng; + use transaction::faker::gen_dummy_tx; impl Dummy for Block { /// Creates a block with 3 transactions and random header. @@ -255,24 +170,6 @@ pub mod faker { } } - impl Dummy for Transaction { - fn dummy_with_rng(_config: &T, _rng: &mut R) -> Self { - gen_dummy_tx(1_000_000) - } - } - - impl Dummy for SpentTransaction { - fn dummy_with_rng(_config: &T, _rng: &mut R) -> Self { - let tx = gen_dummy_tx(1_000_000); - SpentTransaction { - inner: tx, - block_height: 0, - gas_spent: 3, - err: Some("error".to_string()), - } - } - } - impl Dummy for PublicKeyBytes { fn dummy_with_rng(_config: &T, rng: &mut R) -> Self { let rand_val = rng.gen::<[u8; 32]>(); @@ -311,42 +208,4 @@ pub mod faker { IterationsInfo { att_list } } } - - /// Generates a decodable transaction from a fixed blob with a specified - /// gas price. - pub fn gen_dummy_tx(gas_price: u64) -> Transaction { - let pk = PublicKey::from(&SecretKey::new( - JubJubScalar::from(42u64), - JubJubScalar::from(42u64), - )); - let gas_limit = 1; - - let fee = Fee::deterministic( - &JubJubScalar::from(5u64), - &pk, - gas_limit, - gas_price, - &[JubJubScalar::from(9u64), JubJubScalar::from(10u64)], - ); - - let tx_skeleton = TxSkeleton { - root: BlsScalar::from(12345u64), - nullifiers: vec![ - BlsScalar::from(1u64), - BlsScalar::from(2u64), - BlsScalar::from(3u64), - ], - outputs: [Note::empty(), Note::empty()], - max_fee: gas_price * gas_limit, - deposit: 0, - }; - - let contract_call = - ContractCall::new([21; 32], "some_method", &()).unwrap(); - - let payload = Payload::new(tx_skeleton, fee, Some(contract_call)); - let proof = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; - - PhoenixTransaction::new(payload, proof).into() - } } diff --git a/node-data/src/ledger/transaction.rs b/node-data/src/ledger/transaction.rs new file mode 100644 index 0000000000..d3275fd37d --- /dev/null +++ b/node-data/src/ledger/transaction.rs @@ -0,0 +1,158 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. +// +// Copyright (c) DUSK NETWORK. All rights reserved. + +use super::*; + +use execution_core::transfer::Transaction as PhoenixTransaction; + +#[derive(Debug, Clone)] +pub struct Transaction { + pub version: u32, + pub r#type: u32, + pub inner: PhoenixTransaction, +} + +impl From for Transaction { + fn from(value: PhoenixTransaction) -> Self { + Self { + inner: value, + r#type: 1, + version: 1, + } + } +} + +#[derive(Debug, Clone)] +pub struct SpentTransaction { + pub inner: Transaction, + pub block_height: u64, + pub gas_spent: u64, + pub err: Option, +} + +impl Transaction { + /// Computes the hash of the transaction. + /// + /// This method returns the [hash](rusk_abi::hash()) of the entire + /// transaction in its serialized form + /// + /// ### Returns + /// An array of 32 bytes representing the hash of the transaction. + pub fn hash(&self) -> [u8; 32] { + Hasher::digest(self.inner.to_var_bytes()).to_bytes() + } + + /// Computes the transaction ID. + /// + /// The transaction ID is a unique identifier for the transaction. + /// Unlike the [`hash()`](#method.hash) method, which is computed over the + /// entire transaction, the transaction ID is derived from specific + /// fields of the transaction and serves as a unique identifier of the + /// transaction itself. + /// + /// ### Returns + /// An array of 32 bytes representing the transaction ID. + pub fn id(&self) -> [u8; 32] { + Hasher::digest(self.inner.to_hash_input_bytes()).to_bytes() + } + + pub fn gas_price(&self) -> u64 { + self.inner.payload().fee().gas_price + } + pub fn to_nullifiers(&self) -> Vec<[u8; 32]> { + self.inner + .payload() + .tx_skeleton() + .nullifiers() + .iter() + .map(|n| n.to_bytes()) + .collect() + } +} + +impl PartialEq for Transaction { + fn eq(&self, other: &Self) -> bool { + self.r#type == other.r#type + && self.version == other.version + && self.id() == other.id() + } +} + +impl Eq for Transaction {} + +impl PartialEq for SpentTransaction { + fn eq(&self, other: &Self) -> bool { + self.inner == other.inner && self.gas_spent == other.gas_spent + } +} + +impl Eq for SpentTransaction {} + +#[cfg(any(feature = "faker", test))] +pub mod faker { + use super::*; + use execution_core::transfer::{ContractCall, Fee, Payload}; + use execution_core::{ + BlsScalar, JubJubScalar, Note, PublicKey, SecretKey, TxSkeleton, + }; + use rand::Rng; + + impl Dummy for Transaction { + fn dummy_with_rng(_config: &T, _rng: &mut R) -> Self { + gen_dummy_tx(1_000_000) + } + } + + impl Dummy for SpentTransaction { + fn dummy_with_rng(_config: &T, _rng: &mut R) -> Self { + let tx = gen_dummy_tx(1_000_000); + SpentTransaction { + inner: tx, + block_height: 0, + gas_spent: 3, + err: Some("error".to_string()), + } + } + } + + /// Generates a decodable transaction from a fixed blob with a specified + /// gas price. + pub fn gen_dummy_tx(gas_price: u64) -> Transaction { + let pk = PublicKey::from(&SecretKey::new( + JubJubScalar::from(42u64), + JubJubScalar::from(42u64), + )); + let gas_limit = 1; + + let fee = Fee::deterministic( + &JubJubScalar::from(5u64), + &pk, + gas_limit, + gas_price, + &[JubJubScalar::from(9u64), JubJubScalar::from(10u64)], + ); + + let tx_skeleton = TxSkeleton { + root: BlsScalar::from(12345u64), + nullifiers: vec![ + BlsScalar::from(1u64), + BlsScalar::from(2u64), + BlsScalar::from(3u64), + ], + outputs: [Note::empty(), Note::empty()], + max_fee: gas_price * gas_limit, + deposit: 0, + }; + + let contract_call = + ContractCall::new([21; 32], "some_method", &()).unwrap(); + + let payload = Payload::new(tx_skeleton, fee, Some(contract_call)); + let proof = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; + + PhoenixTransaction::new(payload, proof).into() + } +}