Skip to content

Commit

Permalink
Add a submit old field to the getblocktemplate RPC during long polling
Browse files Browse the repository at this point in the history
  • Loading branch information
teor2345 committed Dec 14, 2022
1 parent a6062e6 commit 780a753
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 3 deletions.
20 changes: 18 additions & 2 deletions zebra-rpc/src/methods/get_block_template_rpcs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ where

// The loop returns the server long poll ID,
// which should be different to the client long poll ID.
let (server_long_poll_id, chain_tip_and_local_time, mempool_txs) = loop {
let (server_long_poll_id, chain_tip_and_local_time, mempool_txs, submit_old) = loop {
// Check if we are synced to the tip.
// The result of this check can change during long polling.
//
Expand Down Expand Up @@ -397,7 +397,22 @@ where
// - the server long poll ID is different to the client long poll ID, or
// - the previous loop iteration waited until the max time.
if Some(&server_long_poll_id) != client_long_poll_id.as_ref() || max_time_reached {
break (server_long_poll_id, chain_tip_and_local_time, mempool_txs);
let mut submit_old = client_long_poll_id
.as_ref()
.map(|old_long_poll_id| server_long_poll_id.submit_old(old_long_poll_id));

// On testnet, the max time changes the block difficulty,
// so old shares are invalid.
if max_time_reached {
submit_old = Some(false);
}

break (
server_long_poll_id,
chain_tip_and_local_time,
mempool_txs,
submit_old,
);
}

// - Polling wait conditions
Expand Down Expand Up @@ -549,6 +564,7 @@ where
coinbase_txn,
&mempool_txs,
default_roots,
submit_old,
);

Ok(response)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,14 +135,28 @@ pub struct GetBlockTemplate {
/// Zebra adjusts the minimum and current times for testnet minimum difficulty blocks,
/// so we need to tell miners what the maximum valid time is.
///
/// This field is not in the Zcash RPC reference yet.
/// This field is not in `zcashd` or the Zcash RPC reference yet.
///
/// Currently, some miners just use `min_time` or `cur_time`. Others calculate `max_time` from the
/// fixed 90 minute consensus rule, or a smaller fixed interval (like 1000s).
/// Some miners don't check the maximum time. This can cause invalid blocks after network downtime,
/// a significant drop in the hash rate, or after the testnet minimum difficulty interval.
#[serde(rename = "maxtime")]
pub max_time: DateTime32,

/// > only relevant for long poll responses:
/// > indicates if work received prior to this response remains potentially valid (default)
/// > and should have its shares submitted;
/// > if false, the miner may wish to discard its share queue
///
/// <https://en.bitcoin.it/wiki/BIP_0022#Optional:_Long_Polling>
///
/// This field is not in `zcashd` or the Zcash RPC reference yet.
///
/// In Zebra, `submit_old` is `false` when the tip block or max time is reached,
/// and `true` if only the mempool transactions have changed.
#[serde(rename = "submitold")]
pub submit_old: Option<bool>,
}

impl GetBlockTemplate {
Expand All @@ -156,6 +170,7 @@ impl GetBlockTemplate {
coinbase_txn: TransactionTemplate<amount::NegativeOrZero>,
mempool_txs: &[VerifiedUnminedTx],
default_roots: DefaultRoots,
submit_old: Option<bool>,
) -> Self {
// Convert transactions into TransactionTemplates
let mempool_txs = mempool_txs.iter().map(Into::into).collect();
Expand Down Expand Up @@ -212,6 +227,8 @@ impl GetBlockTemplate {
height: next_block_height.0,

max_time: chain_tip_and_local_time.max_time,

submit_old,
}
}
}
17 changes: 17 additions & 0 deletions zebra-rpc/src/methods/get_block_template_rpcs/types/long_poll.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,23 @@ pub struct LongPollId {
pub mempool_transaction_content_checksum: u32,
}

impl LongPollId {
/// Returns `true` if shares using `old_long_poll_id` can be submitted in response to the
/// template for `self`:
/// <https://en.bitcoin.it/wiki/BIP_0022#Optional:_Long_Polling>
///
/// Old shares may be valid if only the mempool transactions have changed,
/// because newer transactions don't have to be included in the old shares.
///
/// But if the chain tip has changed, the block header has changed, so old shares are invalid.
/// (And if the max time has changed on testnet, the block header has changed.)
pub fn submit_old(&self, old_long_poll_id: &LongPollId) -> bool {
self.tip_height == old_long_poll_id.tip_height
&& self.tip_hash_checksum == old_long_poll_id.tip_hash_checksum
&& self.max_timestamp == old_long_poll_id.max_timestamp
}
}

/// Update `checksum` from `item`, so changes in `item` are likely to also change `checksum`.
///
/// This checksum is not cryptographically secure.
Expand Down

0 comments on commit 780a753

Please sign in to comment.