fix: shelley systemStart must match the shifted byron startTime (devnet Plutus clock skew) - #186
Open
nau wants to merge 1 commit into
Open
fix: shelley systemStart must match the shifted byron startTime (devnet Plutus clock skew)#186nau wants to merge 1 commit into
nau wants to merge 1 commit into
Conversation
…Time When shiftStartTimeBehind backdates byron-genesis startTime (by one epoch with the default devnet settings) so the cluster boots directly in Conway, shelley-genesis systemStart was still written as the current time. The node derives its slot counter from the byron startTime but translates slots to POSIXTime for the Plutus script context from the shelley systemStart, so the two clocks disagreed by exactly the backdate (600s by default): every POSIXTime a Plutus script sees in txInfoValidRange is shifted by that amount against the slots the transaction was actually built and accepted with. Any validator that cross-checks the validity range against externally computed times then fails phase-2 validation on the devnet while passing against a consistent local evaluator and on public networks, where byron.startTime and shelley.systemStart always describe the same instant. Write systemStart from byronStartTime so both genesis files describe the same chain origin, matching public network genesis layouts.
Member
|
@nau Please check my comment in the issue #185 Ideally, the |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
When
shiftStartTimeBehindis enabled withconwayHardForkAtEpoch > 0(the default devnet configuration),ClusterStartService.setupFirstRunbackdates byron-genesisstartTimeby one epoch (600s with default parameters) so the cluster boots directly in Conway. However, shelley-genesissystemStartis still written as the unshifted current time.On every public Cardano network
byron.startTimeandshelley.systemStartdescribe the same instant. The devnet violates that invariant, and cardano-node ends up with two clocks that disagree by exactly the backdate:startTime. Verified on a live devnet:cardano-cli query tipslot is exactlywall_clock - byron_startTime.POSIXTimefortxInfoValidRangefrom shelleysystemStart. Verified from a node script failure dump: both bounds oftxInfoValidRangeequalshelley_systemStart + slot * 1s, including shelley's sub-second fraction, i.e. 600s later than the same slots under the byron anchor.Impact
Every
POSIXTimea Plutus script sees in its validity range is shifted ~600s into the future relative to the slots the transaction was built and phase-1-validated with. Scripts that only compare the range bounds to each other never notice. Scripts that cross-checktxInfoValidRangeagainst externally computed times (deadline validators, oracles that timestamp datum entries, anything doing off-chain/on-chain time agreement) fail phase-2 on the devnet withValidationTagMismatch (IsValid True) (FailedUnexpectedly ...), while the same transaction validates fine against a client-side evaluator and would validate on public networks.We hit this with a Bitcoin oracle contract that records
validity_range_end - block_timestampdeltas in its datum: the node recomputed the delta 600s larger than the datum value and rejected every update transaction. The failure is very confusing to debug because the transaction is phase-1 valid, the local evaluator saysIsValid True, and only the node's CEK evaluation disagrees.Concrete numbers from the failing devnet (yaci-cli 0.10.0-preview2, but the code path is unchanged on current master):
Fix
Write shelley
systemStartfrom the (possibly shifted)byronStartTimeinstead of a freshInstant.now(), so both genesis files describe the same chain origin, exactly as on public networks. The unshifted case is unchanged (byronStartTimeisInstant.now()there).Note the Yano companion service already enforces this invariant in the opposite direction after a time-travel bootstrap (
YanoCompanionServicesyncs byronstartTimeto the shifted shelleysystemStart), so this brings the plain devnet path in line with it.Verification
applications/clicompiles with the change (./gradlew compileJava).This issue was explored, diagnosed and the fix prepared by Claude (Claude Code), driven by @nau.
🤖 Generated with Claude Code