Răsfoiți Sursa

blockchain: replaced header tree with just its root

skoupidi 2 ani în urmă
părinte
comite
4f9c104206

+ 1 - 1
bin/darkfid/genesis_block_localnet

@@ -1 +1 @@
-AYa7rEMKSzoYLxJbN6SG6cSGu/o02E70pmtKI+XwxiWxAAAAAFDcE2YAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAjlJf8EOkzdyMqN8KwdSaz84CHYXrzOze3Djz8YkKFTwAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AYa7rEMKSzoYLxJbN6SG6cSGu/o02E70pmtKI+XwxiWxAAAAAKPqE2YAAAAAAAAAAAAAAAA7PNtvmfHqHEnjNnAS1ULkbCEM4uIYpCgNuv5kw2ETCAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

+ 1 - 1
bin/darkfid/genesis_block_mainnet

@@ -1 +1 @@
-AYa7rEMKSzoYLxJbN6SG6cSGu/o02E70pmtKI+XwxiWxAAAAAFDcE2YAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAjlJf8EOkzdyMqN8KwdSaz84CHYXrzOze3Djz8YkKFTwAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AYa7rEMKSzoYLxJbN6SG6cSGu/o02E70pmtKI+XwxiWxAAAAAKPqE2YAAAAAAAAAAAAAAAA7PNtvmfHqHEnjNnAS1ULkbCEM4uIYpCgNuv5kw2ETCAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

+ 1 - 1
bin/darkfid/genesis_block_testnet

@@ -1 +1 @@
-AYa7rEMKSzoYLxJbN6SG6cSGu/o02E70pmtKI+XwxiWxAAAAAFDcE2YAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAjlJf8EOkzdyMqN8KwdSaz84CHYXrzOze3Djz8YkKFTwAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AYa7rEMKSzoYLxJbN6SG6cSGu/o02E70pmtKI+XwxiWxAAAAAKPqE2YAAAAAAAAAAAAAAAA7PNtvmfHqHEnjNnAS1ULkbCEM4uIYpCgNuv5kw2ETCAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

+ 23 - 3
src/blockchain/block_store.rs

@@ -111,21 +111,41 @@ impl BlockInfo {
     }
 
     /// Append a transaction to the block. Also adds it to the Merkle tree.
+    /// Note: when we append a tx we rebuild the whole tree, so its preferable
+    /// to append them all at once using `append_txs`.
     pub fn append_tx(&mut self, tx: Transaction) {
-        append_tx_to_merkle_tree(&mut self.header.tree, &tx);
+        let mut tree = MerkleTree::new(1);
+        // Append existing block transactions to the tree
+        for block_tx in &self.txs {
+            append_tx_to_merkle_tree(&mut tree, block_tx);
+        }
+        // Append the new transaction
+        append_tx_to_merkle_tree(&mut tree, &tx);
         self.txs.push(tx);
+        // Grab the tree root and store it in the header
+        self.header.root = tree.root(0).unwrap();
     }
 
     /// Append a vector of transactions to the block. Also adds them to the
     /// Merkle tree.
+    /// Note: when we append txs we rebuild the whole tree, so its preferable
+    /// to append them all at once.
     pub fn append_txs(&mut self, txs: Vec<Transaction>) {
+        let mut tree = MerkleTree::new(1);
+        // Append existing block transactions to the tree
+        for block_tx in &self.txs {
+            append_tx_to_merkle_tree(&mut tree, block_tx);
+        }
+        // Append the new transactions
         for tx in txs {
-            self.append_tx(tx);
+            append_tx_to_merkle_tree(&mut tree, &tx);
+            self.txs.push(tx);
         }
+        // Grab the tree root and store it in the header
+        self.header.root = tree.root(0).unwrap();
     }
 
     /// Sign block header using provided secret key
-    // TODO: sign more stuff?
     pub fn sign(&mut self, secret_key: &SecretKey) {
         self.signature = secret_key.sign(self.hash().inner());
     }

+ 10 - 11
src/blockchain/header_store.rs

@@ -18,7 +18,11 @@
 
 use std::fmt;
 
-use darkfi_sdk::{blockchain::block_version, crypto::MerkleTree, AsHex};
+use darkfi_sdk::{
+    blockchain::block_version,
+    crypto::{MerkleNode, MerkleTree},
+    AsHex,
+};
 
 #[cfg(feature = "async-serial")]
 use darkfi_serial::async_trait;
@@ -66,15 +70,15 @@ pub struct Header {
     pub timestamp: Timestamp,
     /// The block's nonce. This value changes arbitrarily with mining.
     pub nonce: u64,
-    /// Merkle tree of the transactions hashes contained in this block
-    pub tree: MerkleTree,
+    /// Merkle tree root of the transactions hashes contained in this block
+    pub root: MerkleNode,
 }
 
 impl Header {
     pub fn new(previous: HeaderHash, height: u32, timestamp: Timestamp, nonce: u64) -> Self {
         let version = block_version(height);
-        let tree = MerkleTree::new(1);
-        Self { version, previous, height, timestamp, nonce, tree }
+        let root = MerkleTree::new(1).root(0).unwrap();
+        Self { version, previous, height, timestamp, nonce, root }
     }
 
     /// Compute the header's hash
@@ -84,12 +88,7 @@ impl Header {
         // Blake3 hasher .update() method never fails.
         // This call returns a Result due to how the Write trait is specified.
         // Calling unwrap() here should be safe.
-        self.version.encode(&mut hasher).expect("blake3 hasher");
-        self.previous.encode(&mut hasher).expect("blake3 hasher");
-        self.height.encode(&mut hasher).expect("blake3 hasher");
-        self.timestamp.encode(&mut hasher).expect("blake3 hasher");
-        self.nonce.encode(&mut hasher).expect("blake3 hasher");
-        self.tree.root(0).unwrap().encode(&mut hasher).expect("blake3 hasher");
+        self.encode(&mut hasher).expect("blake3 hasher");
 
         HeaderHash(hasher.finalize().into())
     }

+ 7 - 5
src/validator/verification.rs

@@ -95,7 +95,7 @@ pub async fn verify_genesis_block(overlay: &BlockchainOverlayPtr, block: &BlockI
 
     // Append producer transaction to the tree and check tree matches header one
     append_tx_to_merkle_tree(&mut tree, producer_tx);
-    if tree != block.header.tree {
+    if tree.root(0).unwrap() != block.header.root {
         error!(target: "validator::verification::verify_genesis_block", "Genesis Merkle tree is invalid");
         return Err(Error::BlockIsInvalid(block_hash))
     }
@@ -208,14 +208,16 @@ pub async fn verify_block(
         &mut tree,
     )
     .await?;
-    verify_producer_signature(block, &public_key)?;
 
-    // Verify tree matches header one
-    if tree != block.header.tree {
-        error!(target: "validator::verification::verify_block", "Block Merkle tree is invalid");
+    // Verify transactions merkle tree root matches header one
+    if tree.root(0).unwrap() != block.header.root {
+        error!(target: "validator::verification::verify_block", "Block Merkle tree root is invalid");
         return Err(Error::BlockIsInvalid(block_hash.as_string()))
     }
 
+    // Verify producer signature
+    verify_producer_signature(block, &public_key)?;
+
     // Insert block
     overlay.lock().unwrap().add_block(block)?;