lssa/common/src/block.rs

99 lines
2.7 KiB
Rust
Raw Normal View History

2025-09-25 11:53:42 +03:00
use borsh::{BorshDeserialize, BorshSerialize};
2025-10-17 16:07:59 -03:00
use sha2::{Digest, Sha256, digest::FixedOutput};
2024-10-10 14:09:31 +03:00
2025-10-17 16:07:59 -03:00
use crate::transaction::EncodedTransaction;
pub type HashType = [u8; 32];
#[derive(Debug, Clone)]
2025-11-26 00:27:20 +03:00
/// Our own hasher.
2025-10-17 16:07:59 -03:00
/// Currently it is SHA256 hasher wrapper. May change in a future.
pub struct OwnHasher {}
impl OwnHasher {
fn hash(data: &[u8]) -> HashType {
let mut hasher = Sha256::new();
hasher.update(data);
<HashType>::from(hasher.finalize_fixed())
}
}
2024-10-10 14:09:31 +03:00
pub type BlockHash = [u8; 32];
pub type BlockId = u64;
2025-08-28 12:00:04 +03:00
pub type TimeStamp = u64;
2024-10-10 14:09:31 +03:00
2025-08-12 12:18:13 -03:00
#[derive(Debug, Clone)]
2025-08-28 12:00:04 +03:00
pub struct BlockHeader {
2024-10-10 14:09:31 +03:00
pub block_id: BlockId,
pub prev_block_hash: BlockHash,
2024-10-10 14:09:31 +03:00
pub hash: BlockHash,
2025-08-28 12:00:04 +03:00
pub timestamp: TimeStamp,
2025-09-03 10:29:51 +03:00
pub signature: nssa::Signature,
2025-08-28 12:00:04 +03:00
}
#[derive(Debug, Clone)]
pub struct BlockBody {
2025-09-08 10:11:04 +03:00
pub transactions: Vec<EncodedTransaction>,
2025-08-28 12:00:04 +03:00
}
#[derive(Debug, Clone)]
pub struct Block {
pub header: BlockHeader,
pub body: BlockBody,
2024-10-10 14:09:31 +03:00
}
2024-11-25 07:26:16 +02:00
2025-09-25 11:53:42 +03:00
#[derive(Debug, PartialEq, Eq, BorshSerialize, BorshDeserialize)]
2024-11-25 07:26:16 +02:00
pub struct HashableBlockData {
pub block_id: BlockId,
pub prev_block_hash: BlockHash,
2025-08-28 12:00:04 +03:00
pub timestamp: TimeStamp,
2025-09-08 10:11:04 +03:00
pub transactions: Vec<EncodedTransaction>,
2024-11-25 07:26:16 +02:00
}
2025-09-03 10:29:51 +03:00
impl HashableBlockData {
pub fn into_block(self, signing_key: &nssa::PrivateKey) -> Block {
2025-09-25 11:53:42 +03:00
let data_bytes = borsh::to_vec(&self).unwrap();
2025-09-03 10:29:51 +03:00
let signature = nssa::Signature::new(signing_key, &data_bytes);
let hash = OwnHasher::hash(&data_bytes);
Block {
2025-08-28 12:00:04 +03:00
header: BlockHeader {
2025-09-03 10:29:51 +03:00
block_id: self.block_id,
prev_block_hash: self.prev_block_hash,
2025-08-28 12:00:04 +03:00
hash,
2025-09-03 10:29:51 +03:00
timestamp: self.timestamp,
signature,
2025-08-28 12:00:04 +03:00
},
body: BlockBody {
2025-09-03 10:29:51 +03:00
transactions: self.transactions,
2025-08-28 12:00:04 +03:00
},
2024-11-25 07:26:16 +02:00
}
}
}
2025-08-12 12:18:13 -03:00
impl From<Block> for HashableBlockData {
fn from(value: Block) -> Self {
Self {
2025-09-02 10:17:00 +03:00
block_id: value.header.block_id,
prev_block_hash: value.header.prev_block_hash,
timestamp: value.header.timestamp,
transactions: value.body.transactions,
2025-08-12 12:18:13 -03:00
}
}
}
#[cfg(test)]
mod tests {
use crate::{block::HashableBlockData, test_utils};
#[test]
2025-08-12 23:31:41 -03:00
fn test_encoding_roundtrip() {
2025-08-12 12:18:13 -03:00
let transactions = vec![test_utils::produce_dummy_empty_transaction()];
let block = test_utils::produce_dummy_block(1, Some([1; 32]), transactions);
let hashable = HashableBlockData::from(block);
2025-09-25 11:53:42 +03:00
let bytes = borsh::to_vec(&hashable).unwrap();
let block_from_bytes = borsh::from_slice::<HashableBlockData>(&bytes).unwrap();
2025-08-12 23:31:41 -03:00
assert_eq!(hashable, block_from_bytes);
2025-08-12 12:18:13 -03:00
}
}