fix: resolve missing AES on delegate's witness after delegation - #1498
fix: resolve missing AES on delegate's witness after delegation#1498lenkan wants to merge 1 commit into
Conversation
Witnesses accept delegated events (dip/drt) before the delegator has anchored them, to avoid a deadlock in the delegation flow. However, the authorizer event seal (AES) was never back-filled once the delegator's anchoring event arrived, leaving the witness permanently showing "Not anchored" for the delegated identifier. Introduce a pending witness delegation escrow (pwde) that tracks delegated events accepted by a witness without an AES. A new processEscrowWitnessAnchors method, called from processEscrows, periodically checks whether the delegator's KEL now contains the anchoring seal and stores the AES when it does. Fixes WebOfTrust#1317
dhh1128
left a comment
There was a problem hiding this comment.
The escrow approach here is the right one — parking a witness-accepted delegated event in pwde and only setting the AES after confirming the delegator's KEL actually anchors it is how this should work, and it goes straight at #1317.
The blocker is that it fixes dip but not drt. The enrollment condition in Kever.logEvent (src/keri/core/eventing.py ~3150-3156, self.delpre and ilk != ixn and locallyWitnessed) fires for delegated rotations as well as inceptions, but processEscrowWitnessAnchors reads the delegator as delpre = eserder.ked.get('di') (~5393-5439), and a drt carries no di — the Kever derives a rotation's delegator from prior state (eventing.py ~2297-2298). So a drt hits if not delpre: continue, the AES is never filled, the witness stays on "Not anchored" (the #1317 symptom again), and the pwde entry never clears. The new test (tests/core/test_escrow.py:752) covers only dip. The disabled reference at eventing.py ~5697/~6038 already reads self.kevers[eserder.pre].delpre, which works for both; deriving the delegator that way, and falling back to ked['di'] only for dip, plus a drt case in the test, would cover it.
Next, processEscrowWitnessAnchors (eventing.py:5407-5439) has no timeout. Every other Kevery escrow prunes against a Timeout* constant — TimeoutPWE (eventing.py:3648) drives the eviction at 5975-5990 — but this one writes no datetime and exits only on success, an exception, or an indefinite continue, while fetchLastSealingEventByEventSeal (basing.py:1778) rescans the delegator KEL from sn 0 on every processEscrows pass. A delegate that names this witness and incepts or rotates many delegated AIDs without getting the delegator to anchor leaves a permanent entry each time, each one an O(KEL) rescan per cycle, and a witness isn't a watcher, so it won't fetch the delegator's KEL on its own to clear them. A dts stamp and a Timeout* prune would bound it; a fetch cue for the delegator KEL would help more.
Smaller: validateDelegation's eager branch (eventing.py ~3060-3090) already does the same fetchLastSealingEventByEventSeal + setAes, guarded by a fons acceptance check; it just skips the witness because it short-circuits on locallyWitnessed. This adds a second path that omits the fons guard, so a later change to the AES couple format or the acceptance rule could land on one and miss the other. Routing the witness case through the eager path, or mirroring its fons guard, would keep them from drifting — though a dedicated escrow may read more clearly, so your call.
I'm guessing at intent in a couple of spots, the drt derivation especially, so correct me where I've misread the flow.
Witnesses accept delegated events (dip/drt) before the delegator has anchored them, to avoid a deadlock in the delegation flow. However, the authorizer event seal (AES) was never back-filled once the delegator's anchoring event arrived, leaving the witness permanently showing "Not anchored" for the delegated identifier.
Introduce a pending witness delegation escrow (pwde) that tracks delegated events accepted by a witness without an AES. A new processEscrowWitnessAnchors method, called from processEscrows, periodically checks whether the delegator's KEL now contains the anchoring seal and stores the AES when it does.
Fixes #1317