zkrollup 0.0.1

zkrollup implementation
Documentation
use crate::{merkle_tree::MerkleProof, poseidon::FieldHasher};

use super::{FftField, PublicKey, RngCore, SecretKey, SigUtils, Signature, UserData};
use zkstd::common::*;

#[derive(Clone, Debug, PartialEq, Eq, Default, Encode, Decode)]
pub(crate) struct RollupTransactionInfo<P: RedDSA, H: FieldHasher<P::Range, 2>, const N: usize> {
    pub(crate) transaction: Transaction<P>,
    pub(crate) pre_root: P::Range,
    pub(crate) post_root: P::Range,
    pub(crate) pre_sender: UserData<P>,
    pub(crate) pre_receiver: UserData<P>,
    pub(crate) pre_sender_proof: MerkleProof<P::Range, H, N>,
    pub(crate) pre_receiver_proof: MerkleProof<P::Range, H, N>,
    pub(crate) post_sender_proof: MerkleProof<P::Range, H, N>,
    pub(crate) post_receiver_proof: MerkleProof<P::Range, H, N>,
    pub(crate) is_withdrawal: bool,
}

#[derive(Default, Clone, Copy, Debug, PartialEq, Eq, Decode, Encode)]
pub struct Transaction<P: RedDSA>(pub(crate) Signature, pub(crate) TransactionData<P>);

impl<P: RedDSA> Transaction<P> {
    pub fn to_field_element(self) -> P::Range {
        let mut field = [0_u8; 64];
        field.copy_from_slice(&self.to_bytes()[0..64]);
        P::Range::from_bytes_wide(&field)
    }
}

#[derive(Default, Clone, Copy, Debug, PartialEq, Eq, Decode, Encode)]
pub struct TransactionData<P: RedDSA> {
    pub(crate) sender_address: PublicKey<P>,
    pub(crate) receiver_address: PublicKey<P>,
    pub(crate) amount: u64,
}

impl<P: RedDSA> TransactionData<P> {
    pub fn new(sender_address: PublicKey<P>, receiver_address: PublicKey<P>, amount: u64) -> Self {
        Self {
            sender_address,
            receiver_address,
            amount,
        }
    }

    pub fn signed(self, secret_key: SecretKey<P>, rand: impl RngCore) -> Transaction<P> {
        let sig = secret_key.sign(&self.to_bytes(), rand);
        Transaction(sig, self)
    }
}

impl<P: RedDSA> SigUtils<136> for Transaction<P> {
    fn from_bytes(bytes: [u8; 136]) -> Option<Self> {
        let mut signature = [0_u8; 64];
        let mut transaction_data = [0_u8; 72];

        signature.copy_from_slice(&bytes[0..64]);
        transaction_data.copy_from_slice(&bytes[64..]);
        Some(Self(
            Signature::from_bytes(signature).unwrap(),
            TransactionData::from_bytes(transaction_data).unwrap(),
        ))
    }

    fn to_bytes(self) -> [u8; 136] {
        let mut bytes = [0u8; 136];
        bytes[0..64].copy_from_slice(&self.0.to_bytes());
        bytes[64..].copy_from_slice(&self.1.to_bytes());
        bytes
    }
}

impl<P: RedDSA> SigUtils<72> for TransactionData<P> {
    fn from_bytes(bytes: [u8; 72]) -> Option<Self> {
        let mut sender_address = [0_u8; 32];
        let mut receiver_address = [0_u8; 32];
        let mut amount = [0_u8; 8];

        sender_address.copy_from_slice(&bytes[0..32]);
        receiver_address.copy_from_slice(&bytes[32..64]);
        amount.copy_from_slice(&bytes[64..]);
        Some(Self {
            sender_address: PublicKey::from_bytes(sender_address).unwrap(),
            receiver_address: PublicKey::from_bytes(receiver_address).unwrap(),
            amount: u64::from_le_bytes(amount),
        })
    }

    fn to_bytes(self) -> [u8; 72] {
        let mut bytes = [0u8; 72];
        bytes[0..32].copy_from_slice(&self.sender_address.to_bytes());
        bytes[32..64].copy_from_slice(&self.receiver_address.to_bytes());
        bytes[64..].copy_from_slice(&self.amount.to_le_bytes());
        bytes
    }
}