fix(types): declare input_hash/output_hash on ReceiptPayload#19
Open
web3guru888 wants to merge 1 commit into
Open
fix(types): declare input_hash/output_hash on ReceiptPayload#19web3guru888 wants to merge 1 commit into
web3guru888 wants to merge 1 commit into
Conversation
In `proof_only` mode `ReceiptBuilder.build` redacts `inputs`/`output` to `None` and adds `input_hash`/`output_hash` SHA-256 digests (receipt.py:137-139), but those two keys were absent from the `ReceiptPayload` TypedDict. As a result type checkers could not see the keys a proof_only receipt actually carries (e.g. `receipt["input_hash"]` was a typing blind spot), and the discrepancy was hidden behind a `# type: ignore[return-value]` on the return statement. Declare both keys as optional schema members. To stay Python 3.10 compatible (the project targets `python = "^3.10"`, and `typing.NotRequired` is 3.11+ while `typing_extensions` is not a declared dependency), the optionality is expressed with the native TypedDict-inheritance idiom: a required base plus a `total=False` subclass — no new dependency. The `# type: ignore[return-value]` actually covered the `dict[str, Any] -> ReceiptPayload` builder boundary (the receipt is built incrementally as a plain dict so the conditional proof_only keys and the post-hoc payload_hmac can be appended), which is independent of the missing keys. Removing the comment alone re-surfaces that error, so it is replaced with an explicit, type-checked `cast(ReceiptPayload, receipt)` — a typed boundary assertion rather than blanket error suppression. The signing/chain bytes are unchanged (the dict is still signed without payload_hmac, exactly as before). Adds `TestReceiptPayloadSchema` regression coverage: the hash keys must be optional schema members (not required), every key a proof_only receipt emits must be declared, and private receipts must omit the optional keys. Signed-off-by: Robin Dey <robin@vbrl.ai>
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.
fix(types): declare
input_hash/output_hashonReceiptPayloadWhat
In
proof_onlymodeReceiptBuilder.buildredactsinputs/outputtoNoneand adds
input_hash/output_hashSHA-256 digests(
src/aevs/core/receipt.py:137-139):…but those two keys were absent from the
ReceiptPayloadTypedDict(
src/aevs/core/types.py). Type checkers therefore could not see the keys aproof_only receipt actually carries, and the gap was masked behind a
# type: ignore[return-value]on the return statement.The fix
Declare both keys as optional schema members:
They are optional because only
proof_onlyreceipts carry them —privateand
publicreceipts omit them entirely.Why the TypedDict-inheritance idiom (not
NotRequired)The project targets
python = "^3.10".typing.NotRequiredis 3.11+, andtyping_extensionsis not a declared dependency. The native, dependency-freeway to express per-key optionality on 3.10 is a required base TypedDict plus a
total=Falsesubclass — which is what this PR uses.ReceiptPayloadremainsthe single public name.
About the
# type: ignore[return-value]— a findingThe ignore did not stem from the missing keys. The receipt is built
incrementally as a
dict[str, Any](so the conditional proof_only keys and thepost-hoc
payload_hmaccan be appended), and mypy rejects returning adict[str, Any]where a TypedDict is expected:So simply deleting the comment re-surfaces that error (see
01-ignore-is-load-bearing-on-main.txt). It is replaced with an explicit,type-checked
cast(ReceiptPayload, receipt)— a typed boundary assertion atthe end of the builder rather than a blanket line-level error suppression. The
signing/chain bytes are unchanged: the dict is still canonicalized and
signed without
payload_hmacexactly as before, so existing signature/chaintests continue to pass byte-for-byte.
Tests
New
tests/test_receipt.py::TestReceiptPayloadSchema(5 cases):test_hash_fields_are_optional_schema_keysinput_hash/output_hash∈__optional_keys__test_hash_fields_are_not_required__required_keys__test_builder_keys_are_declared_in_schematest_proof_only_emits_the_optional_keystest_default_visibility_omits_optional_keysThe first and third fail on
main(keys absent from the schema); all pass withthis change (see
02-schema-tests-fail-before-fix.txt).Verification (
make check)pytest: 497 passed, 2 skipped (492 baseline + 5 new) —03-full-suite.txtruff check: clean —04-ruff.txtmypy --strict: clean, 22 files —05-mypy.txtCloses the type-checker blind spot for proof_only receipts.