fix: read the consensus surfaces the resolution-kernel train exposes - #212
Draft
kirilaa wants to merge 2 commits into
Draft
fix: read the consensus surfaces the resolution-kernel train exposes#212kirilaa wants to merge 2 commits into
kirilaa wants to merge 2 commits into
Conversation
Four entrypoints the SDK calls were removed or reshaped by the train. The first one is what fails in E2E today, on the dev-env stack, before any scenario completes: getTransactionData(txId, timestamp) -> not found on ABI That read answered with a projection evaluated at a caller-supplied clock. The train splits the two apart: the stored record is getStoredTransactionData(txId) and the projection lives behind getTransactionLifecycle. Chains upgrade independently, so the transaction read now picks whichever the chain's OWN abi offers rather than assuming -- the dev-env harness builds its chain from the live deployment, so its abi is the train's while a testnet's is not. The stored record renames three fields. The decoder already normalised two of them (txData/txCalldata, numOfInitialValidators/initialRotations); it now also accepts observedAt for currentTimestamp, which it reads unconditionally, so an unrecognised name was a crash rather than a missing field. activeValidators() is gone because committee capacity is 1,543 and an address[] that long overruns the return-size limit. The joined registry is paged instead: read validatorsJoinedCount() first so a registry that grows underneath the walk cannot spin the loop, then getValidatorsJoined 64 at a time -- the size the paged reads are written around, and the one genlayer-node uses for the same walk. activeValidatorsCount() went with it, which took all of getEpochInfo() down with a single read. validatorView lost its registry tree pointers (left, right, parent), so the struct is resynced to the nine fields the train returns; both call sites read it by name, so nothing else moves. validatorsRoot() is removed from the abi as well -- nothing here calls it, and leaving a declaration for a function that no longer exists only invites a revert. The status map is renumbered with them. ReadyToFinalize stopped being a stored status -- readiness is the resolution kernel's verdict now -- and removing it at ordinal 11 shifts the three above it down. Left alone, a ValidatorsTimeout transaction decoded as "READY_TO_FINALIZE": no error, just the wrong answer. The enum member stays, because the node still reports that state; what changed is that no chain value decodes to it, so the name->number map is now partial and says so in its type. The repo's own tests pinned the old numbering and are re-pointed to the train's.
The earlier commit resynced validatorView and missed its two siblings, which return the same struct and drifted the same way: the train dropped the registry tree pointers (left, right, parent), so a twelve-field decode runs off the end of a nine-field return. It surfaces as a bounds error rather than a wrong value -- "Position 319 is out of bounds (0 < position < 288)" from validatorViewPrimed -- because the reader walks past the encoded tail.
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: trueThanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
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.
Depends-On: genlayerlabs/genlayer-consensus#1307
Observed break
The dev-env E2E stack fails before any scenario completes, inside the SDK:
genlayer-e2e run
32882620666
—
genlayer-explorer,genlayer-cliandgenlayer-walleton dev-env. Thestudio stack passes throughout, because
getTransactionDatashort-circuits onisStudioand never reaches the contract read.The harness builds its chain from the live deployment's ABIs, so the ABI it
hands the SDK is the train's. The SDK asks it for functions the train removed.
What the train changed
ConsensusData.getTransactionData(txId, timestamp)getStoredTransactionData(txId), projection isgetTransactionLifecycleStaking.activeValidators()Staking.activeValidatorsCount()getEpochInfo()with itStaking.validatorView(addr)left/right/parentgone)TransactionStatusordinalsReadyToFinalizeremoved at 11; 12/13/14 shift downactiveValidators()is gone because committee capacity is 1,543 and anaddress[]that long overruns the return-size limit.Approach
Transaction read is capability-detected. The chain's own ABI is already in
hand (
chain.consensusDataContract.abi), so the read picksgetStoredTransactionDatawhen the chain offers it and keeps the old call otherwise. A testnet on the
current deployment is unaffected.
Paged registry walk.
validatorsJoinedCount()first, so a registry thatgrows underneath the walk cannot spin the loop; then
getValidatorsJoined64at a time — the size the paged reads are written around, and the one
genlayer-node uses for the same walk. A short page means it shrank; stop and
let the next read see it settled.
Decoder. It already normalised
txData/txCalldataandnumOfInitialValidators/initialRotations; it now also acceptsobservedAtfor
currentTimestamp, which it reads unconditionally — so an unrecognisedname was a crash, not a missing field.
Status numbering.
ReadyToFinalizestopped being a stored status;readiness is the resolution kernel's verdict now. Left alone, a
ValidatorsTimeouttransaction decoded as"READY_TO_FINALIZE"— no error,just the wrong answer. The
TransactionStatusmember stays, because the nodestill reports that state; what changed is that no chain value decodes to it, so
the name→number map is genuinely partial and its type now says so.
Chain compatibility — the DXP question
Narrower than first written, after checking the pre-train ABIs directly.
Safe on both surfaces. The paged registry reads are not new: pre-train
StakingReadFacetalready exposesvalidatorsJoinedCountandgetValidatorsJoined, andactiveValidatorsCountis there too. SogetActiveValidators,getActiveValidatorsCountandgetEpochInfoworkagainst a current-deployment chain as well as the train.
activeValidators(the one that is gone on the train) lived on
StakingConfigpre-train, whichis why the old call worked there.
The transaction read degrades per-chain — it detects against the chain's
own ABI, so nothing changes for a testnet.
One hard pre-train break:
validatorView. The ABI here is now the train'snine fields, and a pre-train chain returns twelve —
left,right,parentstill lead the struct. Both call sites read by name, so a pre-train chain
decodes them from the wrong slots. There is no chain ABI to detect against for
this one:
STAKING_ABIis the SDK's own bundled copy.One semantic break: status ordinals. A pre-train chain's
11isReadyToFinalize; this maps it toValidatorsTimeout.Both are fine if
v2-devships alongside the train landing inv0.6-dev, andnot fine if this branch must keep serving today's testnets first. I have not
guessed — happy to add a probe for
validatorViewif DXP wants one.src/chains/*is untouched: it is generated fromgenlayer-networks, andnpm run check:chainsreports no drift.Validation
npm run build(incl. DTS),npm run lint,npx vitest run --typecheck(126 passed, 0 type errors),
npm run check:chains— all clean. The repo's owntransaction-enum tests pinned the old ordinals and are re-pointed to the
train's.
Acceptance
The dev-env E2E stack reaches its scenarios against the train. Lands with the
train, not before it — against current
v0.6-devconsensus these entrypointsstill exist.
Companion adaptations: genlayerlabs/genlayer-node#1800,
genlayerlabs/genlayer-dev-env#138, genlayerlabs/genlayer-cli#412.