Bound per-call typed-data value visits - #9
Merged
Merged
Conversation
Count atomic, array and struct visits across both roots, including repeated paths through shared values. Use the same inclusive 262144-visit guard in the optional policy walk and refuse with E_COMPLEXITY before further work. The threshold preserves the complete-JSON interoperability floor without calling signer policy or changing accepted encodings. Document the counting proof and limits: this is not a byte-work, wall-clock, peak-memory or arbitrary-JavaScript safety guarantee. Add boundary, alias, policy, reset and genuine-BLS regression checks; retain all frozen fixtures. Refs: #6 Reported-by: ichbindas <54631150+ichbindas@users.noreply.github.com>
There was a problem hiding this comment.
🟢 Approval recommended
No unresolved approval blockers are identified.
Pull request overview
Adds an inclusive per-call 262,144 typed-value visit guard while preserving existing encoding and policy behavior.
Changes:
- Tracks roots, fields, arrays, structs, atomic values, and shared references.
- Propagates
E_COMPLEXITYthrough hashing and verification. - Adds boundary tests and documents the guard and limitations.
File summaries
| File | Description |
|---|---|
src/typed-data/hash.ts |
Implements shared per-call visit budgeting. |
src/typed-data/hash.test.ts |
Tests visit accounting and boundaries. |
src/bls/sig.test.ts |
Verifies resource-error propagation. |
docs/typed-data-v1.md |
Documents counting and floor preservation. |
CHANGELOG.md |
Records the new guard. |
Review details
- Files reviewed: 5/5 changed files
- Comments generated: 0
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
HDauven
marked this pull request as ready for review
September 14, 2026 23:52
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Resolves #6; follow-up to merged #8 and the shared-value work report.
Add an inclusive 262,144 typed-value visits per call reference guard. A visit is processing one root, field value or array element—an atomic value, array container or struct, including empty structs. Shared references are charged on every path; structs are not double-counted when emitting their hashes.
TypedDataError/E_COMPLEXITYas a resource exception, not a failed-signature result. Ordinary signer-floor refusals remainE_POLICY_LIMIT.Why this threshold: every visited occurrence in a complete, otherwise-valid JSON payload has its own serialized value-token/opening-delimiter byte. The sole implicit domain-contract visit can use the unvisited top-level opening delimiter. Therefore inputs within the existing 262,144-byte compact-JSON interoperability floor cannot exhaust this visit budget. The argument includes alias-preserving copies with identical expanded JSON values; lossy/custom JavaScript serialization cannot establish that guarantee.
This is a reference resource refusal, not a universal validity ceiling. Some previously accepted above-floor work is now refused; accepted encodings remain unchanged. No exported function signature, dependency, signing string, normalization or fixture change.
Limits and review focus
The counter bounds visits, not per-value bytes, wall-clock time, peak memory, arbitrary getters/proxies, or policy serialization of unused metadata. No hostile-object snapshot framework is introduced. Transport controls and broader resource decisions remain separate. The accepted approach is implementation-local guards, not a universal ceiling; together with merged #8, this PR completes #6's agreed traversal-bounds scope.
Please review the visit accounting (including both roots, array containers and empty structs), per-call reset, JSON-floor argument and resource-error propagation.
Validation
Fresh on exact head
a4756af009c8905e08dc3f5ff64681231f0096e5, directly based onc6f3c19:npm run ci: build/coverage and 191 library tests /5 files pass. Its separate, unchanged application-approval example also passes 16 real-BLS/SQLite checks; SQLite is example-test infrastructure, not a hashing dependency.Retained checks on this same commit/tree:
E_COMPLEXITYabove the visit limit for structs and arrays. Existing wide-array/large-string and policy-separation assertions remain intact.Draft for review. No Wallet/Connect source changes, new browser/extension signing E2E, package publication, registry-backed consumer locks or protocol-freeze claim. Local author validation is not independent approval or remote CI.
Reported-by: ichbindas 54631150+ichbindas@users.noreply.github.com