blockchain/Block: proper hash usage

This commit is contained in:
aggstam
2023-09-19 16:54:35 +03:00
parent e5081d55ce
commit 989d049452
6 changed files with 54 additions and 59 deletions

View File

@@ -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())
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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();

View File

@@ -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

View File

@@ -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) =