Skip to content

Commit

Permalink
fix(miner): Avoid some duplicate block errors (#8150)
Browse files Browse the repository at this point in the history
* Update to the latest equihash solver code

* Wait for a new template after mining a block

* Remove an unused import

* Another solver update
  • Loading branch information
teor2345 authored Jan 12, 2024
1 parent b2e71f4 commit 54c702e
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 14 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1349,7 +1349,7 @@ dependencies = [
[[package]]
name = "equihash"
version = "0.2.0"
source = "git+https://github.com/ZcashFoundation/librustzcash.git?branch=equihash-solver-tromp#251098313920466958fcd05b25e151d4edd3a1b1"
source = "git+https://github.com/ZcashFoundation/librustzcash.git?branch=equihash-solver-tromp#aff6fac6cb9c7390565313733f0ba7d679166504"
dependencies = [
"blake2b_simd",
"byteorder",
Expand Down
54 changes: 41 additions & 13 deletions zebrad/src/components/miner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ use zebra_rpc::{
config::mining::Config,
methods::{
get_block_template_rpcs::{
constants::GET_BLOCK_TEMPLATE_MEMPOOL_LONG_POLL_INTERVAL,
get_block_template::{
self, proposal::TimeSource, proposal_block_from_template,
GetBlockTemplateCapability::*, GetBlockTemplateRequestMode::*,
Expand All @@ -45,6 +44,15 @@ use zebra_state::WatchReceiver;
/// The amount of time we wait between block template retries.
pub const BLOCK_TEMPLATE_WAIT_TIME: Duration = Duration::from_secs(20);

/// A rate-limit for block template refreshes.
pub const BLOCK_TEMPLATE_REFRESH_LIMIT: Duration = Duration::from_secs(2);

/// How long we wait after mining a block, before expecting a new template.
///
/// This should be slightly longer than `BLOCK_TEMPLATE_REFRESH_LIMIT` to allow for template
/// generation.
pub const BLOCK_MINING_WAIT_TIME: Duration = Duration::from_secs(3);

/// Initialize the miner based on its config, and spawn a task for it.
///
/// This method is CPU and memory-intensive. It uses 144 MB of RAM and one CPU core per configured
Expand Down Expand Up @@ -295,10 +303,7 @@ where
// If the blockchain is changing rapidly, limit how often we'll update the template.
// But if we're shutting down, do that immediately.
if !template_sender.is_closed() && !is_shutting_down() {
sleep(Duration::from_secs(
GET_BLOCK_TEMPLATE_MEMPOOL_LONG_POLL_INTERVAL,
))
.await;
sleep(BLOCK_TEMPLATE_REFRESH_LIMIT).await;
}
}

Expand Down Expand Up @@ -426,7 +431,7 @@ where
// If the blockchain is changing rapidly, limit how often we'll update the template.
// But if we're shutting down, do that immediately.
if template_receiver.has_changed().is_ok() && !is_shutting_down() {
sleep(Duration::from_secs(1)).await;
sleep(BLOCK_TEMPLATE_REFRESH_LIMIT).await;
}

continue;
Expand All @@ -437,19 +442,23 @@ where
// TODO: if there is a new template (`cancel_fn().is_err()`), and
// GetBlockTemplate.submit_old is false, return immediately, and skip submitting the
// blocks.
let mut any_success = false;
for block in blocks {
let data = block
.zcash_serialize_to_vec()
.expect("serializing to Vec never fails");

match rpc.submit_block(HexData(data), None).await {
Ok(success) => info!(
?height,
hash = ?block.hash(),
?solver_id,
?success,
"successfully mined a new block",
),
Ok(success) => {
info!(
?height,
hash = ?block.hash(),
?solver_id,
?success,
"successfully mined a new block",
);
any_success = true;
}
Err(error) => info!(
?height,
hash = ?block.hash(),
Expand All @@ -459,6 +468,25 @@ where
),
}
}

// Start re-mining quickly after a failed solution.
// If there's a new template, we'll use it, otherwise the existing one is ok.
if !any_success {
// If the blockchain is changing rapidly, limit how often we'll update the template.
// But if we're shutting down, do that immediately.
if template_receiver.has_changed().is_ok() && !is_shutting_down() {
sleep(BLOCK_TEMPLATE_REFRESH_LIMIT).await;
}
continue;
}

// Wait for the new block to verify, and the RPC task to pick up a new template.
// But don't wait too long, we could have mined on a fork.
tokio::select! {
shutdown_result = template_receiver.changed() => shutdown_result?,
_ = sleep(BLOCK_MINING_WAIT_TIME) => {}

}
}

Ok(())
Expand Down

0 comments on commit 54c702e

Please sign in to comment.