feat(evm): endorsers return the delta, the initiator stops building one - #2229
Open
atharrva01 wants to merge 3 commits into
Open
Conversation
The v0.17.0 upgrade updated the tracked modules and missed this one, so nothing under x/token/services/network/evm builds until go.mod is tidy. Signed-off-by: atharrva01 <atharvaborade568@gmail.com>
LFDT-Panurus#2180 enabled containedctx and fixed the ttx occurrence. The evm module is a separate Go module and was not linted in that pass, so make lint has been failing on it since. Neither field can be dropped. Ledger.ctx exists because driver.GetStateFnc passes no context to GetState, and fakeContext.ctx exists because it implements view.Context, whose Context() method has to return one. Signed-off-by: atharrva01 <atharvaborade568@gmail.com>
The initiator ran the full validator on every request through the same DeltaFactory as the responder, to get a digest to verify signatures against and a delta to put in the transaction. That is the work this flow delegates, and it bought nothing: the contract's rule is that a threshold of registered endorsers signed the digest, so a quorum wanting to apply something else would never need the initiator. It did cost something. The delta covers the public parameters hash and version, so an initiator reading parameters on the other side of an update from its endorsers computed a different digest and discarded every signature as an unknown signer. Its ledger read had the same shape: a lagging node failed to build a delta and never contacted an endorser at all. EndorseResponse now carries the delta the endorser signed, the way a Fabric proposal response carries the RWSet. The initiator binds each delta to the anchor it asked about, checks the invariants, recovers the signature over that delta's digest, and groups by delta so a divergent endorser is outvoted rather than fatal. A shortfall where more than one delta was seen reports ErrDivergentDeltas next to ErrInsufficientEndorsements, since that is a determinism failure and not an availability one. Raised by Angelo in the sync of 2026-08-14. Signed-off-by: atharrva01 <atharvaborade568@gmail.com>
atharrva01
added a commit
to atharrva01/panurus
that referenced
this pull request
Aug 14, 2026
The initiator no longer builds a StateDelta (LFDT-Panurus#2229): only the endorser's DeltaFactory does, and that is where the aligned metadata lists actually come from. "The driver" was accurate before that change and misleading after it. Signed-off-by: atharrva01 <atharvaborade568@gmail.com>
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.
Stacked on #2228 (the diff here will shrink to just the endorsement commit once that merges).
The initiator built its own StateDelta before contacting any endorser, running the request through
the same DeltaFactory as the responder. That is validation work, and validating is exactly what this
flow delegates to endorsers, so every client repeated what N endorsers were already doing, plus a
getTokenread per input.It also cost liveness in a way that was hard to diagnose. The delta covers the public parameters hash
and version, and the digest covers the whole struct, so an initiator reading parameters on the other
side of an update from its endorsers computed a different digest and discarded every signature as an
unknown signer. Its ledger read had the same shape: a node lagging behind failed to build a delta at
all and never contacted an endorser, for a request every endorser would have signed.
It bought no security property either way. The contract only checks that a threshold of registered
endorsers signed the digest, so a quorum that wanted to apply something else would never need the
initiator's cooperation.
EndorseResponsenow carries the delta the endorser built, next to its signature, the way a Fabricproposal response carries the RWSet. The initiator binds each returned delta to the anchor it asked
about, checks the StateDelta invariants, recovers the signature over that delta's own digest, and
groups by delta so one endorser translating differently is outvoted instead of failing the whole
transaction. A shortfall where more than one delta was seen reports that explicitly, since that is a
determinism bug in the translator, not endorsers being unavailable.
Verified: unit tests and
-raceacross the module, the Week 4 gate (drives the real initiator andresponders over in-memory sessions, pinned to the committed Solidity fixture) unchanged, all 55 forge
tests, and the fungible integration suite against real Besu, twice.