Skip to content

fix: align Python SDK consumers with the resolution-kernel train - #109

Open
kirilaa wants to merge 8 commits into
v0.19-devfrom
fix/train-consensus-reads
Open

fix: align Python SDK consumers with the resolution-kernel train#109
kirilaa wants to merge 8 commits into
v0.19-devfrom
fix/train-consensus-reads

Conversation

@kirilaa

@kirilaa kirilaa commented Aug 25, 2026

Copy link
Copy Markdown

Delivery context

Depends-On: genlayerlabs/genlayer-consensus#1307
Depends-On: genlayerlabs/genlayer-node#1800

Problem and outcome

This SDK line targets the resolution-kernel/v0.6 train. Older deployments use their matching SDK; TransactionStatus.READY_TO_FINALIZE is removed.

Contract networks use the train's exact decision-bound surfaces. Current Studio remains an independently released consumer: it keeps its native decision-free appeal methods and does not need Studio parity work for this train to land.

Consumer contract

  • Ordinary transactions expose a stored-state lifecycle.
  • The advanced lifecycle exposes stored/projected status, resolution action/source, decision identity, and evaluation time.
  • If current Studio explicitly reports that the lifecycle RPC is missing, the SDK returns only what its transaction surface proves: projected status repeats stored status, resolution is NoOp/Unspecified, and decision identity is inactive. Other RPC errors are propagated.
  • Current Studio uses native submitAppeal(bytes32) and topUpAndSubmitAppeal(bytes32, FeesDistribution); callers provide the appeal value explicitly, and decision guards/quotes are rejected as unsupported.
  • Network appeal and finalization calls remain exact-decision bound.
  • Omitted rotation budgets fund default_consensus_max_rotations for every appeal round; explicit arrays, including [0], remain authoritative.
  • There are no old/new deployment probes or compatibility tests.

Implementation and validation

  • Isolated unit suite excluding live smoke: 190 passing.
  • Focused fee/contract suite: 53 passing.
  • Black: clean.
  • API docs regenerated.
  • git diff --check: clean.
  • The full unfiltered pytest invocation additionally selects live E2E/smoke tests and failed only because no local Studio/testnet endpoint was available; no unit failure remained.

Current head: f2c1e8a1247d07936501284ea6a08c5d0ab99737.

The exact composed behavior is qualified by genlayerlabs/genlayer-e2e#748.

The train withdraws reads this SDK is built on, and none of them fail in a
way a caller would notice:

  - getTransactionData(txId, timestamp) is gone. It answered with a status
    PROJECTED at a caller-supplied clock; the chain now keeps the stored
    record and the projection apart, behind getStoredTransactionData(txId)
    and getTransactionLifecycle. This is what the py lane traceback rooted
    at, and it is a hard failure -- web3 cannot find the function.
  - activeValidators() and activeValidatorsCount() are gone. Committee
    capacity is 1,543 seats and an address[] that long overruns the
    return-size limit, so the joined registry is only readable in slices.
  - validatorView() dropped its left/right/parent tree links, so the tuple
    went from twelve fields to nine.
  - ReadyToFinalize was removed from TransactionStatus at ordinal 11 and
    the three above it shifted down. Left alone, a ValidatorsTimeout
    transaction decoded as READY_TO_FINALIZE -- no error, the wrong answer.
  - previousStatus was dropped from the Transaction struct that
    getTransactionAllData returns, so status sits at index 2 and the rest
    moved up one slot.

The transaction read now detects rather than assumes: chains are upgraded
independently, so it picks whichever of the two reads the chain's own ABI
offers. Both return the same 23-field struct -- only field [0] was renamed
currentTimestamp to observedAt -- so the positional decode is untouched.

active_validators() pages the joined registry: validatorsJoinedCount()
bounds the walk and getValidatorsJoined(start, size) returns each page. The
count is read first so a registry that grows underneath the walk cannot
spin the loop, and a short page means it shrank instead. Page size is 64,
matching genlayer-node's walk over the same registry.

TransactionStatus keeps its READY_TO_FINALIZE member, because the node
still reports that state. What changed is that no chain value decodes to
it, so the name-to-number map no longer carries an ordinal for it: 11
belongs to VALIDATORS_TIMEOUT now, and there is no free number that would
not collide.
@coderabbitai

coderabbitai Bot commented Aug 25, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 94529687-7417-4431-91e7-397e2952d56c

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@MuncleUscles MuncleUscles changed the title fix: read the consensus surfaces the resolution-kernel train exposes fix: align Python SDK consumers with the resolution-kernel train Aug 27, 2026
kirilaa and others added 3 commits August 27, 2026 23:54
The train adaptation routed every appeal action through the resolution-kernel
lifecycle reads. Studio chains (localnet and studionet, which share chain id
61999) run the studio-embedded consensus, which predates the train: its
ConsensusData exposes neither getTransactionLifecycle nor
estimateLatestAppealCharge, and its ConsensusMain, refetched from the simulator
RPC, still declares submitAppeal(bytes32). The decision-guarded encoding
therefore aborted with "value has 2 items when 1 were expected" before the call
was ever sent.

The sibling genlayer-js defect failed the studio suites of e2e run 33112369501.
This mirrors its fix, genlayer-js 04a0bde: guard each affected action on the
studio chain check that transactions.actions.get_transaction already uses, and
reinstate the pre-train behaviour recovered from the v0.19-dev base.

- appeal_transaction encodes submitAppeal(bytes32) against the chain's own
  ConsensusMain ABI.
- top_up_and_submit_appeal encodes
  topUpAndSubmitAppeal(bytes32, FeesDistribution) without a decision id.
- get_appeal_quote, get_appeal_charge and get_min_appeal_bond report the missing
  quote surface with the error the base already raised on studio.
- Both appeal writes keep the base value semantics: the pre-train resolver read
  the bond through FeeManager/RoundsStorage, which studio chains never
  configure, so an omitted value raises the base message verbatim. A call that
  binds to no decision cannot honour a decision guard, so expected_decision_id
  is refused there.

can_appeal and the rounds-storage reads already returned their base error on
studio: their missing-contract guards run before any train read, so they are
left alone. This SDK has no finalizeTransaction, resolveTransactions or
finalizeDecisions surface to adapt.

The train path is unchanged for non-studio chains. The appeal tests that pin it
now build a train chain client, since the shared helper defaulted to the studio
chain id.
Expose materialized transaction progress as a small state-discriminated lifecycle, make receipt waits target stored decisions or finalization, and keep projection/action/source/decision identity in the explicit advanced read.\n\nRemove the old public status compatibility surface and normalize advanced protocol names, decimal decision IDs, and evaluation timestamps across local and contract-backed networks.\n\nValidation: 189 offline unit tests with 13 old-deployment tests excluded; 12 Asimov smoke tests; focused lifecycle tests; E2E collection; docs; Black; build and installed-wheel smoke.
@MuncleUscles
MuncleUscles marked this pull request as ready for review August 28, 2026 13:39

@MuncleUscles MuncleUscles left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the decision-bound train calls, native current-Studio appeal behavior, and method-not-found-only lifecycle fallback on this exact head. Unit coverage, formatting, and generated docs are green. Approving; composed behavior remains gated by the stack E2E.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants