Skip to content

feat: within-step dedup + Presets.throughput (F7) - #22

Merged
halaprix merged 2 commits into
mainfrom
feat/f7-dedup-presets
Jul 23, 2026
Merged

halaprix merged 2 commits into
mainfrom
feat/f7-dedup-presets

Conversation

@halaprix

Copy link
Copy Markdown
Owner

Summary

Implements spec F7 (1.2.0):

  • Opt-in dedupe (default false): within-step, cross-task merging of eligible calls, strictly pre-bisection. Key = (target.toLowerCase(), lowercased calldata, canonicalOutputSignature) with the spec's canon verbatim — order-preserving, tuple-component names included (named vs unnamed tuples never collide), overloads resolved by selector so identical calldata with different decoders is never merged (the first-decoder-wins corruption the key exists to prevent — regression-tested with adversarial overload pairings).
  • Eligibility per call: only TypedCallSpec-compiled calls (internal DEDUPE_ELIGIBLE, default true, per-call dedupe: false opt-out); legacy StepCalls never merge — Presets.throughput cannot change legacy-task semantics (tested with the full preset spread). Keying failures make a call ineligible (dedup introduces no new failure modes).
  • Fan-out copies success AND failure to every subscriber — bisection per-call terminals included; multi-subscriber failures get per-subscriber DominoCallError instances with each subscriber's own key (shared cause identity preserved) so no cross-task mutable sharing or wrong metadata.
  • Presets.throughput = { maxConcurrentBatches: 5, adaptiveBatching: true, dedupe: true } as const exported.
  • Off-path purity: no key computation, no allocations, byte-identical routing when dedupe is off (1:N mapping degrades to 1:1). Counting-executor hit-rate section added to benchmarks.md (empirically verified numbers).

Test evidence

256/256 (16 dedup tests incl. the spec's conflicting-output-ABIs two-wire-calls case, adversarial overload regression, bytes hex-case merge, bisection interplay), compat-vs-dist 38/38, full gate build-first. Gzip 13.0KB (<15KB).

Spec: spec.md § 1.2.0 F7 + Presets.

halaprix added 2 commits July 23, 2026 20:08
Merge dedup-eligible calls that share (target.toLowerCase(), calldata,
canonicalOutputSignature) within one step, across tasks, before the wire
list reaches batching/bisection (src/core/engine.ts). Eligibility is
per-call: TypedCallSpec calls default eligible (opt out with
dedupe: false), legacy hand-authored StepCalls never carry the internal
DEDUPE_ELIGIBLE stamp and so are never merged, regardless of the run's own
dedupe option. Conflicting output ABIs for identical calldata are kept as
separate wire calls (canonicalOutputSignature diverges), preventing
first-decoder-wins corruption. A merged group's single wire result (success
or a bisection-terminal failure alike) fans out to every subscribing
(taskIndex, key) via a new mapping data structure in the step engine.

DEDUPE_ELIGIBLE relocates from defineTask.ts to internal.ts so the engine
can read it without a cross-layer import. Adds `dedupe?: boolean` to
BatchOptions (default false, zero cost on the default path) and
Presets.throughput (src/core/presets.ts), re-exported from index.ts.

Adds src/__tests__/dedup.test.ts (13 tests) and a hit-rate section in
docs/benchmarks.md with empirically-verified counting-executor numbers;
bundle-size badge updated to the measured 12.8KB gzip.
…r identity, calldata case (external review)

Three fixes on top of the F7 dedup key/fan-out:

1. Ambiguous-overload keying (P1): the arity-based fallback could conflate
   two same-arity overloads' outputs (e.g. f(uint256) and f(address) both
   take one input), producing identical serialized signatures for ABIs that
   pair inputs to outputs differently — a real merge-corruption case.
   Replaced with selector-based resolution: a function selector is fixed by
   its own name+input-types alone, so matching the calldata's own 4-byte
   selector against each same-named candidate's own computed selector
   (viem's toFunctionSelector, re-exported from src/core/abi.ts) recovers
   the exact matched item unambiguously, with no arity heuristic and no
   fallback branch needed.

2. Failure fan-out (P2): a merged group's failure was routed as the SAME
   DominoCallError object to every subscriber, so its `.key` field read as
   whichever subscriber happened to be the wire representative for every
   OTHER subscriber. Entries with more than one subscriber now get a fresh
   DominoCallError per subscriber (retargetError in engine.ts) — same
   message/kind/data/target/functionName, `cause` reference shared (not
   re-wrapped), `key` set to that subscriber's own routing key.
   Single-subscriber entries (the default path) are unaffected.

3. Calldata case (P2): a bytes/bytesN arg's encoded segment preserves the
   caller's own hex casing verbatim (unlike an address), so two calls with
   the same bytes value but different hex-string casing keyed differently.
   The key now lowercases the encoded calldata before hashing; the call's
   own calldata/args sent to the executor are untouched.

Adds 3 regression tests to src/__tests__/dedup.test.ts (16 tests total):
conflicting overload pairing, per-subscriber error key metadata, and
bytes32-casing merge. Updates the two failure-fan-out tests' identity
assertions for the new per-subscriber clone semantics. Bundle-size badge
updated to the measured 13.0KB gzip.
@halaprix
halaprix merged commit ed9ad21 into main Jul 23, 2026
2 checks passed
@halaprix
halaprix deleted the feat/f7-dedup-presets branch July 23, 2026 18:26
halaprix added a commit that referenced this pull request Jul 24, 2026
* feat: within-step dedup + Presets.throughput (F7)

Merge dedup-eligible calls that share (target.toLowerCase(), calldata,
canonicalOutputSignature) within one step, across tasks, before the wire
list reaches batching/bisection (src/core/engine.ts). Eligibility is
per-call: TypedCallSpec calls default eligible (opt out with
dedupe: false), legacy hand-authored StepCalls never carry the internal
DEDUPE_ELIGIBLE stamp and so are never merged, regardless of the run's own
dedupe option. Conflicting output ABIs for identical calldata are kept as
separate wire calls (canonicalOutputSignature diverges), preventing
first-decoder-wins corruption. A merged group's single wire result (success
or a bisection-terminal failure alike) fans out to every subscribing
(taskIndex, key) via a new mapping data structure in the step engine.

DEDUPE_ELIGIBLE relocates from defineTask.ts to internal.ts so the engine
can read it without a cross-layer import. Adds `dedupe?: boolean` to
BatchOptions (default false, zero cost on the default path) and
Presets.throughput (src/core/presets.ts), re-exported from index.ts.

Adds src/__tests__/dedup.test.ts (13 tests) and a hit-rate section in
docs/benchmarks.md with empirically-verified counting-executor numbers;
bundle-size badge updated to the measured 12.8KB gzip.

* fix: F7 dedup — selector-based overload matching, per-subscriber error identity, calldata case (external review)

Three fixes on top of the F7 dedup key/fan-out:

1. Ambiguous-overload keying (P1): the arity-based fallback could conflate
   two same-arity overloads' outputs (e.g. f(uint256) and f(address) both
   take one input), producing identical serialized signatures for ABIs that
   pair inputs to outputs differently — a real merge-corruption case.
   Replaced with selector-based resolution: a function selector is fixed by
   its own name+input-types alone, so matching the calldata's own 4-byte
   selector against each same-named candidate's own computed selector
   (viem's toFunctionSelector, re-exported from src/core/abi.ts) recovers
   the exact matched item unambiguously, with no arity heuristic and no
   fallback branch needed.

2. Failure fan-out (P2): a merged group's failure was routed as the SAME
   DominoCallError object to every subscriber, so its `.key` field read as
   whichever subscriber happened to be the wire representative for every
   OTHER subscriber. Entries with more than one subscriber now get a fresh
   DominoCallError per subscriber (retargetError in engine.ts) — same
   message/kind/data/target/functionName, `cause` reference shared (not
   re-wrapped), `key` set to that subscriber's own routing key.
   Single-subscriber entries (the default path) are unaffected.

3. Calldata case (P2): a bytes/bytesN arg's encoded segment preserves the
   caller's own hex casing verbatim (unlike an address), so two calls with
   the same bytes value but different hex-string casing keyed differently.
   The key now lowercases the encoded calldata before hashing; the call's
   own calldata/args sent to the executor are untouched.

Adds 3 regression tests to src/__tests__/dedup.test.ts (16 tests total):
conflicting overload pairing, per-subscriber error key metadata, and
bytes32-casing merge. Updates the two failure-fan-out tests' identity
assertions for the new per-subscriber clone semantics. Bundle-size badge
updated to the measured 13.0KB gzip.

---------

Co-authored-by: halaprix <halaprix@users.noreply.github.com>
halaprix added a commit that referenced this pull request Jul 24, 2026
* feat: within-step dedup + Presets.throughput (F7)

Merge dedup-eligible calls that share (target.toLowerCase(), calldata,
canonicalOutputSignature) within one step, across tasks, before the wire
list reaches batching/bisection (src/core/engine.ts). Eligibility is
per-call: TypedCallSpec calls default eligible (opt out with
dedupe: false), legacy hand-authored StepCalls never carry the internal
DEDUPE_ELIGIBLE stamp and so are never merged, regardless of the run's own
dedupe option. Conflicting output ABIs for identical calldata are kept as
separate wire calls (canonicalOutputSignature diverges), preventing
first-decoder-wins corruption. A merged group's single wire result (success
or a bisection-terminal failure alike) fans out to every subscribing
(taskIndex, key) via a new mapping data structure in the step engine.

DEDUPE_ELIGIBLE relocates from defineTask.ts to internal.ts so the engine
can read it without a cross-layer import. Adds `dedupe?: boolean` to
BatchOptions (default false, zero cost on the default path) and
Presets.throughput (src/core/presets.ts), re-exported from index.ts.

Adds src/__tests__/dedup.test.ts (13 tests) and a hit-rate section in
docs/benchmarks.md with empirically-verified counting-executor numbers;
bundle-size badge updated to the measured 12.8KB gzip.

* fix: F7 dedup — selector-based overload matching, per-subscriber error identity, calldata case (external review)

Three fixes on top of the F7 dedup key/fan-out:

1. Ambiguous-overload keying (P1): the arity-based fallback could conflate
   two same-arity overloads' outputs (e.g. f(uint256) and f(address) both
   take one input), producing identical serialized signatures for ABIs that
   pair inputs to outputs differently — a real merge-corruption case.
   Replaced with selector-based resolution: a function selector is fixed by
   its own name+input-types alone, so matching the calldata's own 4-byte
   selector against each same-named candidate's own computed selector
   (viem's toFunctionSelector, re-exported from src/core/abi.ts) recovers
   the exact matched item unambiguously, with no arity heuristic and no
   fallback branch needed.

2. Failure fan-out (P2): a merged group's failure was routed as the SAME
   DominoCallError object to every subscriber, so its `.key` field read as
   whichever subscriber happened to be the wire representative for every
   OTHER subscriber. Entries with more than one subscriber now get a fresh
   DominoCallError per subscriber (retargetError in engine.ts) — same
   message/kind/data/target/functionName, `cause` reference shared (not
   re-wrapped), `key` set to that subscriber's own routing key.
   Single-subscriber entries (the default path) are unaffected.

3. Calldata case (P2): a bytes/bytesN arg's encoded segment preserves the
   caller's own hex casing verbatim (unlike an address), so two calls with
   the same bytes value but different hex-string casing keyed differently.
   The key now lowercases the encoded calldata before hashing; the call's
   own calldata/args sent to the executor are untouched.

Adds 3 regression tests to src/__tests__/dedup.test.ts (16 tests total):
conflicting overload pairing, per-subscriber error key metadata, and
bytes32-casing merge. Updates the two failure-fan-out tests' identity
assertions for the new per-subscriber clone semantics. Bundle-size badge
updated to the measured 13.0KB gzip.

---------

Co-authored-by: halaprix <halaprix@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant