Transcript rewrite + Multiplexer + Differential Validation
This replaces the earlier tagged-union raw/transcript/transcript.go
(nativeEvent/tracePayload + StreamProjection + deterministic hash) with a
flat, single-struct RawEvent design, per an explicit decision to trade
away the deterministic hash and immutable-projection guarantees for lower
per-event allocation cost. If you want the hash/projection version back,
it's recoverable from git history (commit ed2bd8a).
What was extended beyond the pasted draft
The pasted RawEvent/EventKind only covered TxStart/TxEnd/Enter/Exit/ Fault/BalanceChange, with only AppendEnter/AppendExit actually
implemented. That's not enough to capture what EMES-V1
(docs/emes_profile.md) needs to reconstruct an SSR -- nonce, code, and
storage mutations, self-destruct, and account creation were missing
entirely. This version adds KindNonceChange, KindCodeChange,
KindStorageChange, KindSelfDestruct, KindAccountCreated and their
Append* methods, following the same flat-struct design.
One inconsistency kept rather than silently fixed: the original design's
stated goal was eliminating string allocations, but RawEvent.ErrType is
still a string. Noted in the source rather than either silently dropping
error type info or silently ignoring the stated goal.
Bugs found and fixed (multiplexer/broadcast.go)
Checked against the real core/tracing/hooks.go (not assumed), three
signature mismatches:
OnTxStartwas missing thefrom common.AddressparameterTxStartHookrequires, and used a valuetracing.VMContextinstead of the required pointer*tracing.VMContext.OnEnter'svalueparameter was typed*uint256.Int;EnterHookrequires*big.Int.OnFaultdidn't matchFaultHookat all -- the real signature isfunc(pc uint64, op byte, gas, cost uint64, scope OpContext, depth int, err error), missing thescope OpContextparameter entirely and in a different parameter order (pasted haddepthfirst; the real hook has it second-to-last).
Also: the pasted BroadcastSink.WiringToGethHooks() only implemented
OnEnter and left the rest as a comment ("mirror this exact wrapper
structure"). All five remaining hooks (OnTxStart, OnTxEnd, OnExit,
OnFault, OnBalanceChange) are now actually implemented, not left as a
placeholder, and the method was renamed Hooks() for consistency with
tracer.Tracer.Hooks() elsewhere in this repo.
Other fixes (validation/normalizer.go, validation/engine.go)
normalizer.goimportedkay-sentinel/raw/transcript(hyphenated module name); this repo's actual module iskaysentinel(seego.mod). Fixed tokaysentinel/raw/transcript.engine.go's comparison method was unexported (compareSemanticFields), making it uncallable from outside packagevalidation-- presumably an oversight for something meant to be a differential-testing API. Exported asCompareSemanticFields.- Noted, not fixed:
SemanticEventonly carries the fields shown (Sequence/Opcode/Depth/From/To/Value/GasUsed/Reverted/ErrType), so a differential check can't currently catch a mismatch in, say, a specific storage slot's before/after value -- only that some event of a given Kind/Sequence differs on the fields that do exist.
Verification performed
go build ./raw/... ./validation/... ./multiplexer/...
go vet ./raw/... ./validation/... ./multiplexer/...
Both clean. Beyond that, an actual end-to-end run:
- Registered two
HookSinks on aBroadcastSink: one that records into anExecutionTranscript, one that deliberately panics onOnEnter. - Drove a fake transaction through
bus.Hooks(). Confirmed: the panicking sink's panic was caught, recorded as aPanicReportnaming the right sink and callback, and did not propagate (strictMode=false) -- and confirmed it was evicted: a second round of hook calls produced no new panic and no new report, proving eviction actually removes the sink rather than just logging and continuing to call it. - The recording sink's transcript was fed through
EventNormalizerandDifferentialValidator: comparing a stream against itself matched on every event, and a deliberately injected field mismatch (Depth: 99) was correctly caught and reported with the expected tabular diff format.
Status
Compiles, vets clean, and the panic-isolation + differential-validation
behavior was actually exercised, not just compiled. Not yet wired into
tracer.Tracer from the earlier EMES-V1 work -- this and that tracer are
currently two separate, non-integrated ways of collecting events from
Geth's tracing.Hooks. Deciding whether to merge them or keep both for
different purposes (e.g. this one for a legacy-vs-new differential period)
is an open decision, not resolved here.