Skip to content

Commit

Permalink
node-data: move ledger::transaction in its own module
Browse files Browse the repository at this point in the history
  • Loading branch information
herr-seppia committed Jul 3, 2024
1 parent 17fe925 commit 114a6f1
Show file tree
Hide file tree
Showing 2 changed files with 163 additions and 146 deletions.
151 changes: 5 additions & 146 deletions node-data/src/ledger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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<PhoenixTransaction> 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<String>,
}

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 {
Expand Down Expand Up @@ -158,24 +94,6 @@ impl Default for Signature {
}
}

impl PartialEq<Self> 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<Self> 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);
Expand Down Expand Up @@ -235,11 +153,8 @@ pub fn to_str<const N: usize>(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<T> Dummy<T> for Block {
/// Creates a block with 3 transactions and random header.
Expand All @@ -255,24 +170,6 @@ pub mod faker {
}
}

impl<T> Dummy<T> for Transaction {
fn dummy_with_rng<R: Rng + ?Sized>(_config: &T, _rng: &mut R) -> Self {
gen_dummy_tx(1_000_000)
}
}

impl<T> Dummy<T> for SpentTransaction {
fn dummy_with_rng<R: Rng + ?Sized>(_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<T> Dummy<T> for PublicKeyBytes {
fn dummy_with_rng<R: Rng + ?Sized>(_config: &T, rng: &mut R) -> Self {
let rand_val = rng.gen::<[u8; 32]>();
Expand Down Expand Up @@ -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()
}
}
158 changes: 158 additions & 0 deletions node-data/src/ledger/transaction.rs
Original file line number Diff line number Diff line change
@@ -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<PhoenixTransaction> 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<String>,
}

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<Self> 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<Self> 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<T> Dummy<T> for Transaction {
fn dummy_with_rng<R: Rng + ?Sized>(_config: &T, _rng: &mut R) -> Self {
gen_dummy_tx(1_000_000)
}
}

impl<T> Dummy<T> for SpentTransaction {
fn dummy_with_rng<R: Rng + ?Sized>(_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()
}
}

0 comments on commit 114a6f1

Please sign in to comment.