ソースを参照

blockchain/Block: proper hash usage

aggstam 2 年 前
コミット
989d049452

+ 4 - 5
script/research/pow/src/main.rs

@@ -108,11 +108,10 @@ impl Block {
     fn hash(&self) -> Result<blake2b_simd::Hash> {
         let mut hasher = blake2b_simd::Params::new().hash_length(HASH_LEN).to_state();
 
-        let mut len: usize = 0;
-        len += self.header.encode(&mut hasher)?;
-        len += self.header.txtree.root(0).unwrap().encode(&mut hasher)?;
-        len += self.txs.len().encode(&mut hasher)?;
-        len.encode(&mut hasher)?;
+        self.header.nonce.encode(&mut hasher)?;
+        self.header.previous_hash.encode(&mut hasher)?;
+        self.header.timestamp.encode(&mut hasher)?;
+        self.header.txtree.root(0).unwrap().encode(&mut hasher)?;
 
         Ok(hasher.finalize())
     }

+ 24 - 34
src/blockchain/block_store.rs

@@ -52,11 +52,17 @@ impl Block {
         Self { header, txs, signature }
     }
 
-    /// Compute the block's blockchain hash
-    pub fn hash(&self) -> Result<blake3::Hash> {
-        let mut hasher = blake3::Hasher::new();
-        self.encode(&mut hasher)?;
-        Ok(hasher.finalize())
+    /// A block's hash is the same as the hash of its header
+    pub fn hash(&self) -> blake3::Hash {
+        self.header
+    }
+
+    /// Generate a `Block` from a `BlockInfo`
+    pub fn from_block_info(block_info: &BlockInfo) -> Result<Self> {
+        let header = block_info.header.hash()?;
+        let txs = block_info.txs.iter().map(|x| blake3::hash(&serialize(x))).collect();
+        let signature = block_info.signature;
+        Ok(Self { header, txs, signature })
     }
 }
 
@@ -107,22 +113,15 @@ impl BlockInfo {
         Self { header, txs, signature, slots }
     }
 
-    /// Compute the block's blockchain hash
+    /// A block's hash is the same as the hash of its header
     pub fn hash(&self) -> Result<blake3::Hash> {
-        let block: Block = self.clone().into();
-        block.hash()
+        self.header.hash()
     }
 
-    /// Compute the block's hash used for mining
-    pub fn mining_hash(&self) -> Result<blake3::Hash> {
+    /// Compute the block's full hash
+    pub fn full_hash(&self) -> Result<blake3::Hash> {
         let mut hasher = blake3::Hasher::new();
-
-        let mut len: usize = 0;
-        len += self.header.encode(&mut hasher)?;
-        len += self.header.tree.root(0).unwrap().encode(&mut hasher)?;
-        len += self.txs.len().encode(&mut hasher)?;
-        len.encode(&mut hasher)?;
-
+        self.encode(&mut hasher)?;
         Ok(hasher.finalize())
     }
 
@@ -149,13 +148,6 @@ impl BlockInfo {
     }
 }
 
-impl From<BlockInfo> for Block {
-    fn from(block_info: BlockInfo) -> Self {
-        let txs = block_info.txs.iter().map(|x| blake3::hash(&serialize(x))).collect();
-        Self { header: block_info.header.hash().unwrap(), txs, signature: block_info.signature }
-    }
-}
-
 /// [`Block`] sled tree
 const SLED_BLOCK_TREE: &[u8] = b"_blocks";
 
@@ -180,17 +172,16 @@ impl BlockStore {
 
     /// Generate the sled batch corresponding to an insert, so caller
     /// can handle the write operation.
-    /// The blocks are hashed with BLAKE3 and this block hash is used as
-    /// the key, while value is the serialized [`Block`] itself.
+    /// The block's hash() function output is used as the key,
+    /// while value is the serialized [`Block`] itself.
     /// On success, the function returns the block hashes in the same order.
     pub fn insert_batch(&self, blocks: &[Block]) -> Result<(sled::Batch, Vec<blake3::Hash>)> {
         let mut ret = Vec::with_capacity(blocks.len());
         let mut batch = sled::Batch::default();
 
         for block in blocks {
-            let serialized = serialize(block);
-            let blockhash = blake3::hash(&serialized);
-            batch.insert(blockhash.as_bytes(), serialized);
+            let blockhash = block.hash();
+            batch.insert(blockhash.as_bytes(), serialize(block));
             ret.push(blockhash);
         }
 
@@ -250,17 +241,16 @@ impl BlockStoreOverlay {
     }
 
     /// Insert a slice of [`Block`] into the overlay.
-    /// The block are hashed with BLAKE3 and this block hash is used as
-    /// the key, while value is the serialized [`Block`] itself.
+    /// The block's hash() function output is used as the key,
+    /// while value is the serialized [`Block`] itself.
     /// On success, the function returns the block hashes in the same order.
     pub fn insert(&self, blocks: &[Block]) -> Result<Vec<blake3::Hash>> {
         let mut ret = Vec::with_capacity(blocks.len());
         let mut lock = self.0.lock().unwrap();
 
         for block in blocks {
-            let serialized = serialize(block);
-            let blockhash = blake3::hash(&serialized);
-            lock.insert(SLED_BLOCK_TREE, blockhash.as_bytes(), &serialized)?;
+            let blockhash = block.hash();
+            lock.insert(SLED_BLOCK_TREE, blockhash.as_bytes(), &serialize(block))?;
             ret.push(blockhash);
         }
 

+ 17 - 11
src/blockchain/header_store.rs

@@ -66,7 +66,15 @@ impl Header {
     /// Compute the header's hash
     pub fn hash(&self) -> Result<blake3::Hash> {
         let mut hasher = blake3::Hasher::new();
-        self.encode(&mut hasher)?;
+
+        self.version.encode(&mut hasher)?;
+        self.previous.encode(&mut hasher)?;
+        self.epoch.encode(&mut hasher)?;
+        self.height.encode(&mut hasher)?;
+        self.timestamp.encode(&mut hasher)?;
+        self.nonce.encode(&mut hasher)?;
+        self.tree.root(0).unwrap().encode(&mut hasher)?;
+
         Ok(hasher.finalize())
     }
 }
@@ -108,8 +116,8 @@ impl HeaderStore {
 
     /// Generate the sled batch corresponding to an insert, so caller
     /// can handle the write operation.
-    /// The headers are hashed with BLAKE3 and this header hash is used as
-    /// the key, while value is the serialized [`Header`] itself.
+    /// The header's hash() function output is used as the key,
+    /// while value is the serialized [`Header`] itself.
     /// On success, the function returns the header hashes in the same
     /// order, along with the corresponding operation batch.
     pub fn insert_batch(&self, headers: &[Header]) -> Result<(sled::Batch, Vec<blake3::Hash>)> {
@@ -117,9 +125,8 @@ impl HeaderStore {
         let mut batch = sled::Batch::default();
 
         for header in headers {
-            let serialized = serialize(header);
-            let headerhash = blake3::hash(&serialized);
-            batch.insert(headerhash.as_bytes(), serialized);
+            let headerhash = header.hash()?;
+            batch.insert(headerhash.as_bytes(), serialize(header));
             ret.push(headerhash);
         }
 
@@ -179,17 +186,16 @@ impl HeaderStoreOverlay {
     }
 
     /// Insert a slice of [`Header`] into the overlay.
-    /// The headers are hashed with BLAKE3 and this headerhash is used as
-    /// the key, while value is the serialized [`Header`] itself.
+    /// The header's hash() function output is used as the key,
+    /// while value is the serialized [`Header`] itself.
     /// On success, the function returns the header hashes in the same order.
     pub fn insert(&self, headers: &[Header]) -> Result<Vec<blake3::Hash>> {
         let mut ret = Vec::with_capacity(headers.len());
         let mut lock = self.0.lock().unwrap();
 
         for header in headers {
-            let serialized = serialize(header);
-            let headerhash = blake3::hash(&serialized);
-            lock.insert(SLED_HEADER_TREE, headerhash.as_bytes(), &serialized)?;
+            let headerhash = header.hash()?;
+            lock.insert(SLED_HEADER_TREE, headerhash.as_bytes(), &serialize(header))?;
             ret.push(headerhash);
         }
 

+ 4 - 4
src/blockchain/mod.rs

@@ -126,7 +126,7 @@ impl Blockchain {
         batches.push(headers_batch);
 
         // Store block
-        let blk: Block = Block::from(block.clone());
+        let blk: Block = Block::from_block_info(block)?;
         let (bocks_batch, block_hashes) = self.blocks.insert_batch(&[blk])?;
         let block_hash = block_hashes[0];
         let block_hash_vec = [block_hash];
@@ -219,7 +219,7 @@ impl Blockchain {
             // Retrieve extra stuff based on block version
             let mut block_slots = vec![];
             if header.version > 0 {
-                let slots = self.blocks_slots.get(&[block.hash()?], true)?;
+                let slots = self.blocks_slots.get(&[block.hash()], true)?;
                 let slots = slots[0].clone().unwrap();
                 let slots = self.slots.get(&slots, true)?;
                 block_slots = slots.iter().map(|x| x.clone().unwrap()).collect();
@@ -484,7 +484,7 @@ impl BlockchainOverlay {
         self.headers.insert(&[block.header.clone()])?;
 
         // Store block
-        let blk: Block = Block::from(block.clone());
+        let blk: Block = Block::from_block_info(block)?;
         let block_hash = self.blocks.insert(&[blk])?[0];
         let block_hash_vec = [block_hash];
 
@@ -564,7 +564,7 @@ impl BlockchainOverlay {
             // Retrieve extra stuff based on block version
             let mut block_slots = vec![];
             if header.version > 0 {
-                let slots = self.blocks_slots.get(&[block.hash()?], true)?;
+                let slots = self.blocks_slots.get(&[block.hash()], true)?;
                 let slots = slots[0].clone().unwrap();
                 let slots = self.slots.get(&slots, true)?;
                 block_slots = slots.iter().map(|x| x.clone().unwrap()).collect();

+ 4 - 4
src/contract/consensus/tests/stake_unstake.rs

@@ -61,7 +61,7 @@ fn consensus_contract_stake_unstake() -> Result<()> {
 
         // Now Alice can stake her owncoin
         let alice_staked_oc =
-            th.execute_stake(&HOLDERS, &Holder::Alice, current_slot, &alice_oc, 28).await?;
+            th.execute_stake(&HOLDERS, &Holder::Alice, current_slot, &alice_oc, 181).await?;
 
         // We progress after grace period
         current_slot += (calculate_grace_period() * EPOCH_LENGTH) + EPOCH_LENGTH;
@@ -98,7 +98,7 @@ fn consensus_contract_stake_unstake() -> Result<()> {
 
         // Now Alice can stake her unstaked owncoin again to try some mallicious cases
         let alice_staked_oc = th
-            .execute_stake(&HOLDERS, &Holder::Alice, current_slot, &alice_unstaked_oc, 92)
+            .execute_stake(&HOLDERS, &Holder::Alice, current_slot, &alice_unstaked_oc, 148)
             .await?;
 
         // Alice tries to stake her coin again
@@ -106,7 +106,7 @@ fn consensus_contract_stake_unstake() -> Result<()> {
         info!(target: "consensus", "[Malicious] Checking staking coin again");
         info!(target: "consensus", "[Malicious] ===========================");
         let (stake_tx, _, _) = th
-            .stake(&Holder::Alice, current_slot, &alice_unstaked_oc, pallas::Base::from(92))
+            .stake(&Holder::Alice, current_slot, &alice_unstaked_oc, pallas::Base::from(148))
             .await?;
         th.execute_erroneous_txs(
             TxAction::ConsensusStake,
@@ -188,7 +188,7 @@ fn consensus_contract_stake_unstake() -> Result<()> {
 
         // Now Alice can stake her unstaked owncoin again
         let alice_staked_oc = th
-            .execute_stake(&HOLDERS, &Holder::Alice, current_slot, &alice_unstaked_oc, 77)
+            .execute_stake(&HOLDERS, &Holder::Alice, current_slot, &alice_unstaked_oc, 86)
             .await?;
 
         // We progress after grace period

+ 1 - 1
src/contract/test-harness/src/consensus_genesis_stake.rs

@@ -62,7 +62,7 @@ impl TestHarness {
             pallas::Scalar::random(&mut OsRng),
             pallas::Base::random(&mut OsRng),
             pallas::Scalar::random(&mut OsRng),
-            pallas::Base::from(41),
+            pallas::Base::from(62),
         )?;
 
         let (genesis_stake_params, genesis_stake_proofs) =