docs(privacy): reattribute clock bug's deeper cause to logos-execution-zone

The spel-framework dispatcher filter that drops the clock account is real, but
ValidatedStateDiff::from_public_transaction never checks that a program's output
accounts match the caller-declared message.account_ids, unlike the privacy
circuit's own account_identities.len() == states_iter.len() check. That absence
is why the drop went unnoticed by every pre-existing public AMM test. Update
findings.md's conclusion and add a dated correction to privacy-test-matrix.md
attributing this second, independent gap to logos-execution-zone.
This commit is contained in:
Marvin Jones
2026-07-15 14:22:14 -04:00
parent 9a6b3646ad
commit a7b95ddb4b
2 changed files with 22 additions and 2 deletions
+2 -2
View File
@@ -74,7 +74,7 @@ In this task, we extend testing for LEZ programs to cover privacy features:
# LEZ programs
## AMM program (unusual issues)
## AMM program
| Function tested | Test name | Category | Description of objective | Result |
|---|---|---|---|---|
@@ -162,4 +162,4 @@ Privacy coverage for LEZ program tests is greatly improved from the added tests.
- Privacy transactions have issues with chain calls in which multiple calls affect the same private account. This issue can be mitigated by adopting account diff paradigm instead of the current "account state replacement" that we currently use.
Additional observation:
AMM's chained-call privacy tests were blocked by the clock account being `DEFAULT_PROGRAM_ID`-owned in the test fixture, which trips a `spel-framework` dispatcher bug (upstream in `logos-co/spel`, confirmed present through v0.6.0) that silently drops any default-owned, non-default, unclaimed account from a program's output. Fixed by giving the fixture's clock account a non-default owner; see the AMM section. The dispatcher bug itself remains open upstream.
AMM's chained-call privacy tests were blocked by the clock account being `DEFAULT_PROGRAM_ID`-owned in the test fixture, which trips a `spel-framework` dispatcher filter (upstream in `logos-co/spel`) that silently drops any default-owned, non-default, unclaimed account from a program's output. Fixed by giving the fixture's clock account a non-default owner; see the AMM section. But the deeper bug is in `logos-execution-zone` itself: `ValidatedStateDiff::from_public_transaction` never checks that the accounts touched in a program's output match the caller-declared `message.account_ids` — no count, no membership check, nothing like the privacy circuit's own `account_identities.len() == states_iter.len()` assertion. That's why the `spel-framework` drop went unnoticed by every pre-existing public AMM test: the public path has no validation capable of catching a silently-dropped account at all. Both remain open upstream.
+20
View File
@@ -551,6 +551,26 @@ merge point from `logos-co/release/v0.5.0` (commit `73fc462`) shows the filter a
there too, before any of the fork's own commits. **This is an upstream `logos-co/spel` bug**,
inherited unchanged by the pinned fork — report it against the former, not the latter.
**Correction — there's a second, independent bug in `logos-execution-zone` itself (2026-07-15)**:
the "not a `lez_core`/circuit bug" claim above is too narrow. `ValidatedStateDiff::
from_public_transaction` (`lee/state_machine/src/validated_state_diff.rs`) never checks that the
accounts touched in a program's output match the caller-declared `message.account_ids` — no count
check, no membership check, nothing analogous to the privacy circuit's own `account_identities.
len() == states_iter.len()` assertion in `compute_circuit_output`. The reconciliation loop just
does `state_diff.insert(pre.account_id, post.account().clone())` for whatever pairs the program's
output happens to contain, however many that is, and returns `Ok(...)` regardless.
That absence is why the `spel-framework` drop went unnoticed by every one of this repo's ~34
pre-existing public AMM tests: the public path has no validation capable of catching a
silently-dropped account at all, so a bug with zero privacy dimension to it hid behind passing
public tests until the privacy circuit's stricter, positional bookkeeping happened to expose it.
Two independent upstream defects, not one: `spel-framework`'s over-broad filter (which creates the
drop) and `logos-execution-zone`'s missing account-accounting check on the public path (which lets
any such drop — from this or any future bug — go completely undetected). The latter is arguably
the more consequential of the two, since it's a general soundness gap independent of clock, AMM,
or privacy entirely. Both should be reported upstream; report the `lee` gap against
`logos-co/logos-execution-zone`, not `logos-co/spel`.
### ✅ Fixed for these tests (2026-07-15) — test-fixture clock ownership, not a circuit workaround
The immediate blocker for all five `CHAIN`-dimension AMM privacy tests below was that