Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cache the block header hash #2924

Merged
merged 1 commit into from
Sep 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion blockchain/src/block_production/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,13 +218,14 @@ impl BlockProducer {
body_root: body.hash(),
diff_root,
history_root,
..Default::default()
};

let justification = if let Some(skip_block_proof) = skip_block_proof {
MicroJustification::Skip(skip_block_proof)
} else {
// Signs the block header using the signing key.
let hash = header.hash::<Blake2bHash>();
let hash = header.hash();
let signature = self.signing_key.sign(hash.as_slice());
MicroJustification::Micro(signature)
};
Expand Down Expand Up @@ -343,6 +344,7 @@ impl BlockProducer {
history_root: Blake2bHash::default(),
validators,
next_batch_initial_punished_set,
..Default::default()
};

// Create the body for the macro block.
Expand Down
26 changes: 7 additions & 19 deletions blockchain/src/blockchain/push.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ impl Blockchain {
/// block can be trusted.
fn do_push(
this: RwLockUpgradableReadGuard<Self>,
block: Block,
mut block: Block,
trusted: bool,
diff: Option<TrieDiff>,
chunks: Vec<TrieChunkWithStart>,
Expand All @@ -64,9 +64,10 @@ impl Blockchain {
let read_txn = this.read_transaction();

// Check if we already know this block.
let block_hash = block.hash_cached();
if this
.chain_store
.get_chain_info(&block.hash(), false, Some(&read_txn))
.get_chain_info(&block_hash, false, Some(&read_txn))
.is_ok()
{
return Ok((PushResult::Known, Ok(ChunksPushResult::EmptyChunks)));
Expand Down Expand Up @@ -124,23 +125,10 @@ impl Blockchain {
// Extend, rebranch or just store the block depending on the chain ordering.
let result = match chain_order {
ChainOrdering::Extend => {
return Blockchain::extend(
this,
chain_info.head.hash(),
chain_info,
prev_info,
diff,
chunks,
);
return Blockchain::extend(this, block_hash, chain_info, prev_info, diff, chunks);
}
ChainOrdering::Superior => {
return Blockchain::rebranch(
this,
chain_info.head.hash(),
chain_info,
diff,
chunks,
);
return Blockchain::rebranch(this, block_hash, chain_info, diff, chunks);
}
ChainOrdering::Inferior => {
debug!(block = %chain_info.head, "Storing block - on inferior chain");
Expand All @@ -154,10 +142,10 @@ impl Blockchain {

let mut txn = this.write_transaction();
this.chain_store
.put_chain_info(&mut txn, &chain_info.head.hash(), &chain_info, true);
.put_chain_info(&mut txn, &block_hash, &chain_info, true);
if let Some(diff) = &diff {
this.chain_store
.put_accounts_diff(&mut txn, &chain_info.head.hash(), diff);
.put_accounts_diff(&mut txn, &block_hash, diff);
}
txn.commit();

Expand Down
51 changes: 16 additions & 35 deletions blockchain/src/chain_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,26 +197,25 @@ impl ChainStore {
) -> Result<ChainInfo, BlockchainError> {
let txn = txn_option.or_new(&self.db);

let mut chain_info: ChainInfo = match txn.get(&self.chain_table, hash) {
Some(data) => data,
None => return Err(BlockchainError::BlockNotFound),
};
let mut chain_info = txn
.get(&self.chain_table, hash)
.ok_or(BlockchainError::BlockNotFound)?;

if include_body {
// Check tables according to the `chain_info.on_main_chain` flag
if chain_info.on_main_chain {
if let Some(pushed_block) = txn.get(&self.pushed_block_table, hash) {
pushed_block.populate_body(&mut chain_info.head, &self.history_store, &txn);
} else {
warn!("Block body requested but not present");
}
} else if let Some(full_block) = txn.get(&self.stored_block_table, hash) {
chain_info.head = full_block
let pushed_block = txn
.get(&self.pushed_block_table, hash)
.ok_or(BlockchainError::BlockNotFound)?;
pushed_block.populate_body(&mut chain_info.head, &self.history_store, &txn);
} else {
warn!("Block body requested but not present");
chain_info.head = txn
.get(&self.stored_block_table, hash)
.ok_or(BlockchainError::BlockNotFound)?;
}
}

chain_info.head.populate_cached_hash(hash.clone());

Ok(chain_info)
}

Expand Down Expand Up @@ -267,6 +266,8 @@ impl ChainStore {
}
}

chain_info.head.populate_cached_hash(block_hash);

Ok(chain_info)
}

Expand Down Expand Up @@ -354,28 +355,8 @@ impl ChainStore {
include_body: bool,
txn_option: Option<&MdbxReadTransaction>,
) -> Result<Block, BlockchainError> {
let txn = txn_option.or_new(&self.db);

let mut chain_info = txn
.get(&self.chain_table, hash)
.ok_or(BlockchainError::BlockNotFound)?;

if include_body {
if chain_info.on_main_chain {
let pushed_block = txn
.get(&self.pushed_block_table, hash)
.ok_or(BlockchainError::BlockNotFound)?;
pushed_block.populate_body(&mut chain_info.head, &self.history_store, &txn);
Ok(chain_info.head)
} else {
let full_block = txn
.get(&self.stored_block_table, hash)
.ok_or(BlockchainError::BlockNotFound)?;
Ok(full_block)
}
} else {
Ok(chain_info.head)
}
self.get_chain_info(hash, include_body, txn_option)
.map(|chain_info| chain_info.head)
}

pub fn get_block_at(
Expand Down
3 changes: 1 addition & 2 deletions blockchain/tests/block_production.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ use nimiq_blockchain_interface::{AbstractBlockchain, PushResult};
use nimiq_bls::KeyPair as BlsKeyPair;
use nimiq_database::{mdbx::MdbxDatabase, traits::WriteTransaction};
use nimiq_genesis::NetworkId;
use nimiq_hash::{Blake2bHash, Hash};
use nimiq_keys::{
Address, Ed25519PublicKey as SchnorrPublicKey, KeyPair as SchnorrKeyPair,
PrivateKey as SchnorrPrivateKey, SecureGenerate,
Expand Down Expand Up @@ -87,7 +86,7 @@ fn it_can_produce_micro_blocks() {
};
let mut header2 = header1.clone();
header2.timestamp += 1;
let hash2 = header2.hash::<Blake2bHash>();
let hash2 = header2.hash();
let justification2 = signing_key().sign(hash2.as_slice());
ForkProof::new(
validator_address(),
Expand Down
10 changes: 5 additions & 5 deletions blockchain/tests/history_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use nimiq_blockchain_interface::{AbstractBlockchain, PushResult};
use nimiq_bls::AggregateSignature;
use nimiq_database::traits::WriteTransaction;
use nimiq_genesis::NetworkId;
use nimiq_hash::{Blake2bHash, Blake2sHash, Hash, HashOutput};
use nimiq_hash::{Blake2sHash, HashOutput};
use nimiq_keys::{KeyPair, PrivateKey};
use nimiq_primitives::{policy::Policy, TendermintIdentifier, TendermintStep, TendermintVote};
use nimiq_serde::Deserialize;
Expand Down Expand Up @@ -99,8 +99,8 @@ fn do_fork(

// Builds the equivocation proof.
let signing_key = temp_producer1.producer.signing_key.clone();
let justification1 = signing_key.sign(MicroHeader::hash::<Blake2bHash>(&header_1a).as_bytes());
let justification2 = signing_key.sign(MicroHeader::hash::<Blake2bHash>(&header_2a).as_bytes());
let justification1 = signing_key.sign(MicroHeader::hash(&header_1a).as_bytes());
let justification2 = signing_key.sign(MicroHeader::hash(&header_2a).as_bytes());

ForkProof::new(
validator_address(),
Expand Down Expand Up @@ -135,8 +135,8 @@ fn do_double_proposal(
.clone()
.unwrap_macro()
.header;
let justification1 = signing_key.sign(MacroHeader::hash::<Blake2bHash>(&header1).as_bytes());
let justification2 = signing_key.sign(MacroHeader::hash::<Blake2bHash>(&header2).as_bytes());
let justification1 = signing_key.sign(MacroHeader::hash(&header1).as_bytes());
let justification2 = signing_key.sign(MacroHeader::hash(&header2).as_bytes());

// Produce the double proposal proof.
EquivocationProof::DoubleProposal(DoubleProposalProof::new(
Expand Down
4 changes: 3 additions & 1 deletion blockchain/tests/inherents.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use nimiq_blockchain::{Blockchain, BlockchainConfig};
use nimiq_blockchain_interface::AbstractBlockchain;
use nimiq_bls::AggregateSignature;
use nimiq_database::{mdbx::MdbxDatabase, traits::WriteTransaction};
use nimiq_hash::{Blake2bHash, Blake2sHash, Hash, HashOutput};
use nimiq_hash::{Blake2bHash, Blake2sHash, HashOutput};
use nimiq_keys::Address;
use nimiq_primitives::{
coin::Coin,
Expand Down Expand Up @@ -67,6 +67,7 @@ fn it_can_create_batch_finalization_inherents() {
history_root: Blake2bHash::default(),
validators: None,
next_batch_initial_punished_set,
..Default::default()
};

let reward_transactions =
Expand Down Expand Up @@ -256,6 +257,7 @@ fn it_can_penalize_delayed_batch() {
history_root: Blake2bHash::default(),
validators: None,
next_batch_initial_punished_set,
..Default::default()
};

let staking_contract = blockchain.get_staking_contract();
Expand Down
2 changes: 1 addition & 1 deletion blockchain/tests/push.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use nimiq_blockchain_interface::{
PushResult,
};
use nimiq_bls::AggregateSignature;
use nimiq_hash::{Blake2bHash, Blake2sHash, Hash, HashOutput};
use nimiq_hash::{Blake2bHash, Blake2sHash, HashOutput};
use nimiq_keys::KeyPair;
use nimiq_primitives::{
key_nibbles::KeyNibbles, networks::NetworkId, policy::Policy, TendermintIdentifier,
Expand Down
7 changes: 4 additions & 3 deletions consensus/src/sync/live/block_queue/queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ impl<N: Network> BlockQueue<N> {
/// Handles a block announcement.
fn check_announced_block(
&mut self,
block: Block,
mut block: Block,
block_source: BlockSource<N>,
) -> Option<QueuedBlock<N>> {
// Reject block if it includes a body when we didn't request one or vice versa.
Expand All @@ -160,11 +160,12 @@ impl<N: Network> BlockQueue<N> {

let blockchain = self.blockchain.read();

let block_hash = block.hash_cached();
let block_number = block.block_number();
let head_height = blockchain.block_number();

// Ignore blocks that we already know.
if let Ok(info) = blockchain.get_chain_info(&block.hash(), false) {
if let Ok(info) = blockchain.get_chain_info(&block_hash, false) {
if info.on_main_chain {
block_source.accept_block(&self.network)
} else {
Expand Down Expand Up @@ -200,7 +201,7 @@ impl<N: Network> BlockQueue<N> {
} else if parent_known {
// New head or fork block.
// Add block to pending blocks and return queued block for the stream.
if self.blocks_pending_push.insert(block.hash()) {
if self.blocks_pending_push.insert(block_hash) {
return Some(QueuedBlock::Head((block, block_source)));
}
} else if block_number > head_height + self.config.window_ahead_max {
Expand Down
2 changes: 1 addition & 1 deletion genesis-builder/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,7 @@ impl GenesisBuilder {
};

// Genesis hash
let genesis_hash = header.hash::<Blake2bHash>();
let genesis_hash = header.hash();

Ok(GenesisInfo {
block: Block::Macro(MacroBlock {
Expand Down
2 changes: 2 additions & 0 deletions light-blockchain/src/chain_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,7 @@ mod tests {
body_root: Blake2sHash::default(),
diff_root: Blake2bHash::default(),
history_root: hash_1,
..Default::default()
},
justification: Some(MicroJustification::Micro(Default::default())),
body: None,
Expand All @@ -401,6 +402,7 @@ mod tests {
body_root: Blake2sHash::default(),
diff_root: Blake2bHash::default(),
history_root: hash_2,
..Default::default()
},
justification: Some(MicroJustification::Micro(Default::default())),
body: None,
Expand Down
4 changes: 2 additions & 2 deletions light-blockchain/src/push.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use nimiq_block::{Block, ForkProof, MacroHeader, MicroBlock};
use nimiq_blockchain_interface::{
AbstractBlockchain, BlockchainEvent, ChainInfo, ChainOrdering, ForkEvent, PushError, PushResult,
};
use nimiq_hash::{Blake2bHash, Hash};
use nimiq_hash::Blake2bHash;
use nimiq_keys::Address;
use nimiq_primitives::policy::Policy;
use parking_lot::{RwLockUpgradableReadGuard, RwLockWriteGuard};
Expand Down Expand Up @@ -396,7 +396,7 @@ impl LightBlockchain {
.ok_or(PushError::InvalidSuccessor)?;

// Verify that the block is indeed the predecessor.
if header.hash::<Blake2bHash>() != prev_block.parent_election_hash {
if header.hash() != prev_block.parent_election_hash {
return Err(PushError::InvalidPredecessor);
}

Expand Down
1 change: 1 addition & 0 deletions mempool/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,7 @@ fn create_dummy_micro_block(transactions: Option<Vec<Transaction>>) -> Block {
body_root: Blake2sHash::default(),
diff_root: Blake2bHash::default(),
history_root: Blake2bHash::default(),
..Default::default()
};
let mut executed_txns: Vec<ExecutedTransaction> = Vec::new();

Expand Down
16 changes: 16 additions & 0 deletions primitives/block/src/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,22 @@ impl Block {
}
}

/// Returns the Blake2b hash of the block header and caches the result internally.
pub fn hash_cached(&mut self) -> Blake2bHash {
match self {
Block::Macro(block) => block.header.hash_cached(),
Block::Micro(block) => block.header.hash_cached(),
}
}

/// Populates the internal hash cache with the given `hash`.
pub fn populate_cached_hash(&mut self, hash: Blake2bHash) {
match self {
Block::Macro(block) => block.header.cached_hash = Some(hash),
Block::Micro(block) => block.header.cached_hash = Some(hash),
}
}

/// Returns a copy of the validators. Only returns Some if it is an election block.
pub fn validators(&self) -> Option<Validators> {
match self {
Expand Down
Loading
Loading