Skip to content

Parallel-exec: route the per-tx writeset through one faithful path; remove normalizeWriteSet/calcState; carry serial-finalize signals on ExecutionResult #21138

Description

@mh0lt

Follow-up to #21136. The recurring parallel-exec-vs-serial divergences (SELFDESTRUCT/recreate, EIP-161 empty-removal, EIP-7708 burn logs, fork-transition, coinbase) all come from the post-execution wrapper re-deriving "what did this tx do" via the heuristic normalizeWriteSet(versionWritten-log) path and the calcState re-derivation, instead of using the faithful MakeWriteSet-style output that the validated worker already produces. ~half of genuine parallel-executor PRs over the last 2 months are this family. This issue is the consolidation that makes those bugs structurally impossible.

Target per-tx flow (incremental — does NOT require the full "IBS = pure transaction-state" rework)

  1. Parallel-execute txs (unchanged).
  2. Validate + serialize via BlockSTM (unchanged) — at this point we have a verified version. The validated worker's IBS already ran MakeWriteSet into a LightCollector → result.CollectorWrites = every dirty object's final state.
  3. Per-tx serial-finalize — done from data + the writeset, no reconstructed IBS:
    • per-tx delta = filterWritesByVersionMap(result.CollectorWrites, vmWrites) (faithful, pruned to the keys the tx actually touched — both filterWritesByVersionMap and CollectorWrites already exist).
    • accumulate tip serially → final coinbase / burnt balances → patch the writeset (read pre-block balance from sd).
    • EIP-161 empty-removal: a writeset entry that's {bal=0, nonce=0, empty codehash} → convert to a delete.
    • EIP-7708 transfer/burn logs: compute from the writeset + a self-destructed-addresses list carried on ExecutionResult (see below) — delete the minIBS + postApplyMessageFunc reconstruction (exec3_parallel.go ~line 2807; the minIBS exists only to SetBalance then LogSelfDestructedAccounts reads it).
    • SD storage cascade if still needed (or it falls out of the collector's final state).
  4. Pass the finished tx output to the commitment calculator: the one writeset → applyVersionedWrites writes it into SharedDomains/sd.mem (the public DB the calc reads from), AND VersionedWrites.TouchUpdates(updates) folds it into the calc's commitment.Updates. Calc reads post-block siblings from sd.mem via asOfStateReader.

Block-end finalize (block reward, withdrawals, EIP-4788/7002/7251 syscalls) genuinely runs state transitions and keeps a real IBS — it's outside the per-tx flow and not in scope here.

Concrete changes

  • ExecutionResult gains SelfDestructedAddresses []common.Address (regardless of residual balance) — populated by the worker; consumed by per-tx serial-finalize for EIP-7708 and (potentially) the SD storage cascade.
  • txResult.writes = filterWritesByVersionMap(result.CollectorWrites, be.blockIO.WriteSet(txIndex)) instead of normalizeWriteSet(...).
  • the commitment calc consumes txResult.writes.TouchUpdates(...) — delete calcState.ApplyWrites/FlushToUpdates.
  • delete normalizeWriteSet and resolveStorageWrites (the latter is already DEPRECATED dead code).
  • unify the per-tx and block-finalize collector paths (LightCollector vs versionedWriteCollector — one of them).
  • IBS.VersionedWrites(checkDirty) stays, used only for BlockSTM read/write dependency tracking — it must stop being the apply/commitment payload.

Validation gate before deleting anything

Remove the EXEC3_PARALLEL-gated SkipLoad/t.Skips from #21136 one by one — if the consolidated path is faithful, test_double_kill, test_dynamic_create2_selfdestruct_collision, the prague test_system_contract_deployment variants, tipInsideBlock, and TestEIP7708BurnLogWhenCoinbaseSelfDestructs should all pass without per-bug heuristics. That's the success criterion.

Eventual rework (separate, larger)

Extract the whole serial flow (MakeWriteSet → commitment fold → domain write → BAL) to run post-validation as the single path; serial becomes a 1-tx-at-a-time consumer of it; IBS becomes a pure per-tx transaction-state. This issue is the stepping stone.

Activity

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

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions