Repository navigation
rpc: getblocktemplate mintime is one past the tip median - #1078
Conversation
mintime was the tip's median time past. A block must be above that median (time-too-old), so a template stamped at mintime was invalid. Core's GetMinimumTime starts from MTP + 1; this fixes that lower bound. Core's extra floor at retarget heights (previous block time minus 600) is not part of this change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
c666c9b to
68866bc
Compare
There was a problem hiding this comment.
Summary
getblocktemplate mintime is one past the tip median, which is the consensus floor (time > MTP, reject time-too-old). The saturating_add(1) sits on the whole if, so genesis is incremented once. At height 0 the median window is that single header, so median_time_past(0) equals genesis time. The test pins both a 101-block tip and genesis. The old assignment (the median, or genesis time) fails it.
mintime is only the JSON field. generatetoaddress and generateblock stamp generate_block_time, which is already max(now, MTP+1). Esplora GET /block-template calls the same gbt_template.
curtime stays max(tip_time+1, now). On a chain that already satisfied time > parent MTP, the tip median is at most the tip timestamp, so mintime = MTP+1 is at most tip_time+1. A clock behind the median still leaves curtime at least tip_time+1.
Core's retarget floor max(MTP+1, prev_time-600) is template policy on every network. A block below that floor is a consensus failure only on testnet4 and on regtest with -test=bip94. This node has neither. Regtest here keeps a 2016-block interval and no_pow_retargeting, so it does not retarget every block. On mainnet, testnet3, signet, and default regtest, MTP+1 is the consensus minimum. The changelog already says that floor is out of scope. The comment on the assignment names Core GetMinimumTime, which also applies prev_time - 600 at retarget heights. The changelog is the accurate description of what this change includes.
Proposal mode still accepts time == median (time < mtp in check_block_proposal_with). A stamp at the new mintime is above the median, so it passes proposal and submitblock. A stamp exactly at the median still passes proposal and fails submitblock. That split is unchanged and called out in the PR body.
The test checks the JSON number and does not submit a block stamped at mintime. It would fail on the old median, so that extra submit is optional. mintime is a u32. Saturating add leaves u32::MAX only when no greater u32 time exists, and that number stays exact in JSON.
Issue counts by severity
- bugs: 0
- suggestions: 1
- nits: 1
The comment named GetMinimumTime, which also applies a retarget-height floor. This change takes only the MTP + 1 part. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@rearden-grok Thanks.
Please re-review the latest commit (3f933f0). |
Summary
getblocktemplatereturned the tip's median time asmintime. A block can't carry that time (time-too-old: it must be above the median). Core returnsGetMinimumTime, which is MTP + 1.Core also raises
mintimetoprev_time - 600at retarget heights (its BIP94-ready template policy, applied on every network). That floor isn't part of this fix.Related, not changed here: proposal mode (
check_block_proposal_withinchain.rs) deliberately accepts a block time equal to the median (<where Core uses<=; the comment there explains why). A proposal stamped at the median therefore passes whilesubmitblockrejects it. The relaxation may date from whenmintimewas the median; I've left it for a separate change.Evidence
Regtest, same chain on both nodes:
mintime(tip MTP = M)submitblockof a block stamped at rbitcoin'smintimetime-too-oldon both nodesgetblocktemplate_mintime_is_one_past_the_tip_median(mature tip and genesis).left: 1792357196, right: 1792357197.cargo test --workspace, andci-os-smoke.shpass locally.Merge Danger
Door: two-way
Blast Radius: RPC
Only the
mintimefield changes, ingetblocktemplateand the EsploraGET /block-templateJSON that shares it.curtimeand the rest of the template are unchanged.🤖 Generated with Claude Code