lssa/common/src/transaction.rs

130 lines
3.6 KiB
Rust
Raw Normal View History

2025-09-25 11:53:42 +03:00
use borsh::{BorshDeserialize, BorshSerialize};
use log::info;
2025-07-21 18:46:50 -03:00
use serde::{Deserialize, Serialize};
2025-09-04 14:38:41 +03:00
use sha2::{Digest, digest::FixedOutput};
2024-10-10 14:09:31 +03:00
2025-10-17 15:29:09 -03:00
pub type TreeHashType = [u8; 32];
2024-12-22 16:14:52 +02:00
2025-09-08 10:11:04 +03:00
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum NSSATransaction {
Public(nssa::PublicTransaction),
PrivacyPreserving(nssa::PrivacyPreservingTransaction),
}
impl From<nssa::PublicTransaction> for NSSATransaction {
fn from(value: nssa::PublicTransaction) -> Self {
Self::Public(value)
}
}
impl From<nssa::PrivacyPreservingTransaction> for NSSATransaction {
fn from(value: nssa::PrivacyPreservingTransaction) -> Self {
Self::PrivacyPreserving(value)
}
}
2025-09-25 11:53:42 +03:00
#[derive(
Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq, BorshSerialize, BorshDeserialize,
)]
pub enum TxKind {
Public,
2025-08-28 12:00:04 +03:00
PrivacyPreserving,
}
2025-09-25 11:53:42 +03:00
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize)]
2024-10-10 14:09:31 +03:00
///General transaction object
2025-09-08 10:11:04 +03:00
pub struct EncodedTransaction {
pub tx_kind: TxKind,
2024-12-22 16:14:52 +02:00
///Encoded blobs of data
2025-08-28 12:00:04 +03:00
pub encoded_transaction_data: Vec<u8>,
}
2025-09-08 10:11:04 +03:00
impl From<NSSATransaction> for EncodedTransaction {
fn from(value: NSSATransaction) -> Self {
2025-08-28 12:00:04 +03:00
match value {
2025-09-08 10:11:04 +03:00
NSSATransaction::Public(tx) => Self {
2025-09-03 10:29:51 +03:00
tx_kind: TxKind::Public,
encoded_transaction_data: tx.to_bytes(),
},
2025-09-08 10:11:04 +03:00
NSSATransaction::PrivacyPreserving(tx) => Self {
2025-09-03 10:29:51 +03:00
tx_kind: TxKind::PrivacyPreserving,
encoded_transaction_data: tx.to_bytes(),
2025-08-28 12:00:04 +03:00
},
}
}
}
2025-09-08 10:11:04 +03:00
impl TryFrom<&EncodedTransaction> for NSSATransaction {
2025-08-28 12:00:04 +03:00
type Error = nssa::error::NssaError;
2025-09-08 10:11:04 +03:00
fn try_from(value: &EncodedTransaction) -> Result<Self, Self::Error> {
2025-08-28 12:00:04 +03:00
match value.tx_kind {
2025-09-03 10:29:51 +03:00
TxKind::Public => nssa::PublicTransaction::from_bytes(&value.encoded_transaction_data)
.map(|tx| tx.into()),
2025-08-28 12:00:04 +03:00
TxKind::PrivacyPreserving => {
2025-09-03 10:29:51 +03:00
nssa::PrivacyPreservingTransaction::from_bytes(&value.encoded_transaction_data)
.map(|tx| tx.into())
}
2025-08-28 12:00:04 +03:00
}
}
2024-12-22 16:14:52 +02:00
}
2025-09-08 10:11:04 +03:00
impl EncodedTransaction {
2025-07-10 12:52:48 -03:00
/// Computes and returns the SHA-256 hash of the JSON-serialized representation of `self`.
pub fn hash(&self) -> TreeHashType {
2025-09-25 11:53:42 +03:00
let bytes_to_hash = borsh::to_vec(&self).unwrap();
let mut hasher = sha2::Sha256::new();
hasher.update(&bytes_to_hash);
TreeHashType::from(hasher.finalize_fixed())
}
pub fn log(&self) {
info!("Transaction hash is {:?}", hex::encode(self.hash()));
info!("Transaction tx_kind is {:?}", self.tx_kind);
}
2024-12-30 09:10:04 +02:00
}
2025-07-10 12:09:01 -03:00
2025-07-14 09:37:00 -03:00
2025-07-10 12:09:01 -03:00
#[cfg(test)]
mod tests {
2025-09-04 14:38:41 +03:00
use sha2::{Digest, digest::FixedOutput};
2025-07-10 12:09:01 -03:00
2025-07-10 12:16:05 -03:00
use crate::{
2025-09-03 10:29:51 +03:00
TreeHashType,
2025-09-08 10:11:04 +03:00
transaction::{EncodedTransaction, TxKind},
2025-07-10 12:16:05 -03:00
};
2025-07-10 12:09:01 -03:00
2025-09-08 10:11:04 +03:00
fn test_transaction_body() -> EncodedTransaction {
EncodedTransaction {
2025-07-10 12:09:01 -03:00
tx_kind: TxKind::Public,
2025-09-03 10:29:51 +03:00
encoded_transaction_data: vec![1, 2, 3, 4],
2025-07-16 11:36:20 -03:00
}
}
#[test]
fn test_transaction_hash_is_sha256_of_json_bytes() {
let body = test_transaction_body();
2025-07-10 12:09:01 -03:00
let expected_hash = {
2025-09-25 11:53:42 +03:00
let data = borsh::to_vec(&body).unwrap();
2025-07-10 12:09:01 -03:00
let mut hasher = sha2::Sha256::new();
hasher.update(&data);
TreeHashType::from(hasher.finalize_fixed())
};
2025-07-16 11:36:20 -03:00
let hash = body.hash();
2025-07-10 12:09:01 -03:00
assert_eq!(expected_hash, hash);
}
2025-07-16 11:36:20 -03:00
#[test]
2025-09-03 10:29:51 +03:00
fn test_to_bytes_from_bytes() {
2025-07-16 11:36:20 -03:00
let body = test_transaction_body();
2025-09-25 11:53:42 +03:00
let body_bytes = borsh::to_vec(&body).unwrap();
let body_new = borsh::from_slice::<EncodedTransaction>(&body_bytes).unwrap();
2025-09-03 10:29:51 +03:00
assert_eq!(body, body_new);
}
2025-07-10 12:16:05 -03:00
}