File size: 4,866 Bytes
1b950d4
ed2bd8a
1b950d4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ed2bd8a
1b950d4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ed2bd8a
 
1b950d4
 
ed2bd8a
 
1b950d4
 
 
 
 
 
 
 
 
 
 
 
 
 
ed2bd8a
 
 
1b950d4
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# 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:

1. `OnTxStart` was missing the `from common.Address` parameter
   `TxStartHook` requires, and used a value `tracing.VMContext` instead of
   the required pointer `*tracing.VMContext`.
2. `OnEnter`'s `value` parameter was typed `*uint256.Int`; `EnterHook`
   requires `*big.Int`.
3. `OnFault` didn't match `FaultHook` at all -- the real signature is
   `func(pc uint64, op byte, gas, cost uint64, scope OpContext, depth int,
   err error)`, missing the `scope OpContext` parameter entirely and in a
   different parameter order (pasted had `depth` first; 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.go` imported `kay-sentinel/raw/transcript` (hyphenated
  module name); this repo's actual module is `kaysentinel` (see `go.mod`).
  Fixed to `kaysentinel/raw/transcript`.
- `engine.go`'s comparison method was unexported
  (`compareSemanticFields`), making it uncallable from outside package
  `validation` -- presumably an oversight for something meant to be a
  differential-testing API. Exported as `CompareSemanticFields`.
- Noted, not fixed: `SemanticEvent` only 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

```bash
go build ./raw/... ./validation/... ./multiplexer/...
go vet   ./raw/... ./validation/... ./multiplexer/...
```

Both clean. Beyond that, an actual end-to-end run:

- Registered two `HookSink`s on a `BroadcastSink`: one that records into an
  `ExecutionTranscript`, one that deliberately panics on `OnEnter`.
- Drove a fake transaction through `bus.Hooks()`. Confirmed: the panicking
  sink's panic was caught, recorded as a `PanicReport` naming 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 `EventNormalizer` and
  `DifferentialValidator`: 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.