naom/primitives/
block.rs

1#![allow(unused)]
2use crate::constants::{MAX_BLOCK_SIZE, NETWORK_VERSION};
3use crate::crypto::sha3_256::{self, Sha3_256};
4use crate::crypto::sign_ed25519::PublicKey;
5use crate::primitives::asset::Asset;
6use crate::primitives::transaction::{Transaction, TxIn, TxOut};
7use bincode::{deserialize, serialize};
8use bytes::Bytes;
9use serde::{Deserialize, Serialize};
10use std::convert::TryInto;
11
12use rand::distributions::Alphanumeric;
13use rand::{thread_rng, Rng};
14
15use merkle_log::{MemoryStore, MerkleLog, Store};
16
17/// Block header, which contains a smaller footprint view of the block.
18/// Hash records are assumed to be 256 bit
19#[derive(Clone, Debug, Serialize, Deserialize)]
20pub struct BlockHeader {
21    pub version: u32,
22    pub bits: usize,
23    pub nonce_and_mining_tx_hash: (Vec<u8>, String),
24    pub b_num: u64,
25    pub seed_value: Vec<u8>, // for commercial
26    pub previous_hash: Option<String>,
27    pub txs_merkle_root_and_hash: (String, String),
28}
29
30impl Default for BlockHeader {
31    fn default() -> Self {
32        Self::new()
33    }
34}
35
36impl BlockHeader {
37    /// Creates a new BlockHeader
38    pub fn new() -> BlockHeader {
39        BlockHeader {
40            version: NETWORK_VERSION,
41            bits: 0,
42            nonce_and_mining_tx_hash: Default::default(),
43            b_num: 0,
44            seed_value: Vec::new(),
45            previous_hash: None,
46            txs_merkle_root_and_hash: Default::default(),
47        }
48    }
49
50    /// Checks whether a BlockHeader is empty
51    pub fn is_null(&self) -> bool {
52        self.bits == 0
53    }
54}
55
56/// A block, a collection of transactions for processing
57#[derive(Clone, Debug, Serialize, Deserialize)]
58pub struct Block {
59    pub header: BlockHeader,
60    pub transactions: Vec<String>,
61}
62
63impl Default for Block {
64    fn default() -> Self {
65        Self::new()
66    }
67}
68
69impl Block {
70    /// Creates a new instance of a block
71    pub fn new() -> Block {
72        Block {
73            header: BlockHeader::new(),
74            transactions: Vec::new(),
75        }
76    }
77
78    /// Sets the internal number of bits based on length
79    pub fn set_bits(&mut self) {
80        let bytes = Bytes::from(serialize(&self).unwrap());
81        self.header.bits = bytes.len();
82    }
83
84    /// Checks whether a block has hit its maximum size
85    pub fn is_full(&self) -> bool {
86        let bytes = Bytes::from(serialize(&self).unwrap());
87        bytes.len() >= MAX_BLOCK_SIZE
88    }
89
90    /// Get the merkle root for the current set of transactions
91    pub async fn set_txs_merkle_root_and_hash(&mut self) {
92        let merkle_root = build_hex_merkle_root(&self.transactions).await;
93        let txs_hash = build_hex_txs_hash(&self.transactions);
94
95        self.header.txs_merkle_root_and_hash = (merkle_root, txs_hash);
96    }
97}
98
99/*---- FUNCTIONS ----*/
100
101/// Converts a dynamic array into a static 32 bit
102///
103/// ### Arguments
104///
105/// * `bytes`   - Bytes to cast
106pub fn from_slice(bytes: &[u8]) -> [u8; 32] {
107    let mut array = [0; 32];
108    let bytes = &bytes[..array.len()]; // panics if not enough data
109    array.copy_from_slice(bytes);
110    array
111}
112
113/// Generates a random transaction hash for testing
114pub fn gen_random_hash() -> String {
115    let rand_2: String = thread_rng()
116        .sample_iter(&Alphanumeric)
117        .take(32)
118        .map(char::from)
119        .collect();
120    hex::encode(sha3_256::digest(rand_2.as_bytes()))
121}
122
123/// Builds hex encoded sha3 hash of the passed transactions
124///
125/// ### Arguments
126///
127/// * `transactions`    - Transactions to construct a merkle tree for
128pub fn build_hex_txs_hash(transactions: &[String]) -> String {
129    let txs = serialize(transactions).unwrap();
130    hex::encode(sha3_256::digest(&txs))
131}
132
133/// Builds hex encoded merkle root of the passed transactions
134///
135/// ### Arguments
136///
137/// * `transactions`    - Transactions to construct a merkle tree for
138pub async fn build_hex_merkle_root(transactions: &[String]) -> String {
139    let merkle_result = build_merkle_tree(transactions).await;
140    let merkle_root = merkle_result.map(|(t, _)| hex::encode(t.root()));
141    merkle_root.unwrap_or_default()
142}
143
144/// Builds a merkle tree of the passed transactions
145///
146/// ### Arguments
147///
148/// * `transactions`    - Transactions to construct a merkle tree for
149pub async fn build_merkle_tree(
150    transactions: &[String],
151) -> Option<(MerkleLog<Sha3_256>, MemoryStore)> {
152    let mut store = MemoryStore::default();
153
154    if let Some((first_entry, other_entries)) = transactions.split_first() {
155        let mut log = MerkleLog::<Sha3_256>::new(&first_entry, &mut store)
156            .await
157            .unwrap();
158
159        for entry in other_entries {
160            log.append(entry, &mut store).await.unwrap();
161        }
162
163        return Some((log, store));
164    }
165
166    None
167}
168
169/*---- TESTS ----*/
170
171#[cfg(test)]
172mod tests {
173    use super::*;
174
175    #[actix_rt::test]
176    /// Ensures that the merkle root is set to a valid empty string when no tx's are present
177    async fn should_construct_merkle_root_with_no_tx() {
178        let mut block = Block::new();
179        block.set_txs_merkle_root_and_hash().await;
180
181        assert_eq!(
182            block.header.txs_merkle_root_and_hash,
183            (
184                String::new(),
185                "48dda5bbe9171a6656206ec56c595c5834b6cf38c5fe71bcb44fe43833aee9df".to_owned()
186            )
187        );
188    }
189
190    #[actix_rt::test]
191    /// Ensures that a static set of tx produces a valid merkle root hash
192    async fn should_construct_a_valid_merkle_root() {
193        let mut block = Block::new();
194        block.transactions = vec![
195            "f479fc771c19c64b14b1b9e446ccccf36b6d705c891eb9a7662c82134e362732".to_string(),
196            "ac24e4c5dc8d0a29cac34ddcf7902bc2f2e8a98ec376def02c06db267d0f5477".to_string(),
197            "4d04366cb153bdcc11b97a9d1176fc889eafc63edbd2c010a6a62a4f9232d156".to_string(),
198            "6486b86af39db28e4f61c7b484e0869ad478e8cb2475b91e92d1b721b70d1746".to_string(),
199            "03b45b843d60b1e43241553c9aeb95fed82cc1bbb599c6c066ddaa75709b3186".to_string(),
200            "8d0250ea0864ac426fe4f4142dae721c74da732476de83d424e1ba0b638238a7".to_string(),
201            "f57e38fb8499b7c2b3d4cf75a24a5dd8a8f7b46f28b9671eb8168ffb93a85424".to_string(),
202            "e0acad209b680e61c3ef4624d9a61b32a5e7e3f0691a8f8d41fd50b1c946e338".to_string(),
203        ];
204
205        block.set_txs_merkle_root_and_hash().await;
206        assert_eq!(
207            block.header.txs_merkle_root_and_hash,
208            (
209                "49adba4740eb78c38318bbe2951a3c49e8a5bda6b892870bdcbe0713cf1e0af2".to_owned(),
210                "2bf86b48530112f14cbc516f2f7085cdc886a88b475d52e9eaa8cef526479e0f".to_owned()
211            )
212        );
213    }
214
215    #[actix_rt::test]
216    /// Ensures that a tx's entry in the merkle tree can be successfully proven
217    async fn should_produce_valid_merkle_proof() {
218        let mut transactions = vec![
219            "f479fc771c19c64b14b1b9e446ccccf36b6d705c891eb9a7662c82134e362732".to_string(),
220            "ac24e4c5dc8d0a29cac34ddcf7902bc2f2e8a98ec376def02c06db267d0f5477".to_string(),
221            "4d04366cb153bdcc11b97a9d1176fc889eafc63edbd2c010a6a62a4f9232d156".to_string(),
222            "6486b86af39db28e4f61c7b484e0869ad478e8cb2475b91e92d1b721b70d1746".to_string(),
223            "03b45b843d60b1e43241553c9aeb95fed82cc1bbb599c6c066ddaa75709b3186".to_string(),
224            "8d0250ea0864ac426fe4f4142dae721c74da732476de83d424e1bab638238a7".to_string(),
225            "f57e38fb8499b7c2b3d4cf75a24a5dd8a8f7b46f28b9671eb8168ffb93a85424".to_string(),
226            "e0acad209b680e61c3ef4624d9a61b32a5e7e3f0691a8f8d41fd50b1c946e338".to_string(),
227        ];
228
229        let (mtree, store) = build_merkle_tree(&transactions).await.unwrap();
230        let check_entry = sha3_256::digest(transactions[0].as_bytes());
231        let proof = mtree
232            .prove(0, &from_slice(&check_entry), &store)
233            .await
234            .unwrap();
235
236        assert!(mtree.verify(0, &from_slice(&check_entry), &proof));
237    }
238}