diff --git a/script/research/pow/src/main.rs b/script/research/pow/src/main.rs index d0ac3af9e..d36326747 100644 --- a/script/research/pow/src/main.rs +++ b/script/research/pow/src/main.rs @@ -108,11 +108,10 @@ impl Block { fn hash(&self) -> Result { 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()) } diff --git a/src/blockchain/block_store.rs b/src/blockchain/block_store.rs index 6e43450ff..fb9f106fa 100644 --- a/src/blockchain/block_store.rs +++ b/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 { - 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 { + 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 { - 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 { + /// Compute the block's full hash + pub fn full_hash(&self) -> Result { 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 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)> { 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> { 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); } diff --git a/src/blockchain/header_store.rs b/src/blockchain/header_store.rs index 66139ae0e..d7d386f12 100644 --- a/src/blockchain/header_store.rs +++ b/src/blockchain/header_store.rs @@ -66,7 +66,15 @@ impl Header { /// Compute the header's hash pub fn hash(&self) -> Result { 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)> { @@ -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> { 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); } diff --git a/src/blockchain/mod.rs b/src/blockchain/mod.rs index 0be8dc3be..65e45593c 100644 --- a/src/blockchain/mod.rs +++ b/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(); diff --git a/src/contract/consensus/tests/stake_unstake.rs b/src/contract/consensus/tests/stake_unstake.rs index 6e376d92b..234098b72 100644 --- a/src/contract/consensus/tests/stake_unstake.rs +++ b/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 diff --git a/src/contract/test-harness/src/consensus_genesis_stake.rs b/src/contract/test-harness/src/consensus_genesis_stake.rs index fedce4889..de079bce5 100644 --- a/src/contract/test-harness/src/consensus_genesis_stake.rs +++ b/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) =