Skip to content

Introduce integer ReturnValueTest variant and use it to coerce blocktime value string in TimeCondition#764

Closed
cygnusv wants to merge 291 commits intonucypher:signing-epicfrom
cygnusv:str-timelock
Closed

Introduce integer ReturnValueTest variant and use it to coerce blocktime value string in TimeCondition#764
cygnusv wants to merge 291 commits intonucypher:signing-epicfrom
cygnusv:str-timelock

Conversation

@cygnusv
Copy link
Copy Markdown
Member

@cygnusv cygnusv commented Feb 19, 2026

Type of PR:

  • Bugfix
  • Feature
  • Documentation
  • Other

Required reviews:

  • 1
  • 2
  • 3

What this does:

High-level summary

We fixed backend errors when returnValueTest.value was given as an integer string (e.g. "1701428400") for conditions that compare against an integer (e.g. blocktime). Rather than coercing integer-shaped strings for all blockchain params (which would assume intent everywhere), we introduced a variant return-value-test schema that only coerces such strings where the comparison is known to be integer-based. TimeCondition now uses this variant, so string values like "1701428400" are accepted and serialized as numbers. The generic blockchain return-value-test schema is unchanged and does not coerce; only conditions that explicitly use the integer variant (currently TimeCondition) get string-to-number coercion for value.

Relevant API changes

  • New exports (for use in integer-based conditions or tests):
    • From context: integerStringSchema, integerBlockchainParamOrContextParamSchema.
    • From return-value-test (and re-exported from shared): blockchainIntegerReturnValueTestSchema, BlockchainIntegerReturnValueTestProps.
  • TimeCondition: No constructor or method signature changes. Behavior change: returnValueTest.value may be an integer string (e.g. "1701428400"); it is validated and serialized (e.g. via toObj()) as a number. Number and bigint inputs are unchanged.
  • No breaking changes: Existing callers passing value as number or bigint are unchanged. Code using the generic blockchainReturnValueTestSchema and passing integer strings will now see those values remain strings in the parsed result (previously they were coerced globally; that coercion is now limited to the integer variant).

Issues fixed/closed:

Fixes issue seen by an adopter after integrating TACo and accidentally passing a string integer to a TimeCondition. taco-web didn't complain and only the nodes did, which returned with the following error:

Error
Threshold of responses not met; TACo decryption failed with errors:
{
"0xb15d5A4e2be34f4bE154A1b08a94Ab920FfD8A41":"(<class 'nucypher.network.concurrency.ThresholdDecryptionClient.ThresholdDecryptionRequestFailed'>, ThresholdDecryptionRequestFailed('Node 0xb15d5A4e2be34f4bE154A1b08a94Ab920FfD8A41 raised Invalid condition grammar: Invalid condition grammar: {\\'returnValueTest\\': [\"Invalid return value comparison type \\'<class \\'str\\'>\\'; must be an integer\"]}'), <traceback object at 0x7047b80692c0>)",
"0x48C8039c32F4c6f5cb206A5911C8Ae814929C16B":"(<class 'nucypher.network.concurrency.ThresholdDecryptionClient.ThresholdDecryptionRequestFailed'>, ThresholdDecryptionRequestFailed('Node 0x48C8039c32F4c6f5cb206A5911C8Ae814929C16B raised Invalid condition grammar: Invalid condition grammar: {\\'returnValueTest\\': [\"Invalid return value comparison type \\'<class \\'str\\'>\\'; must be an integer\"]}'), <traceback object at 0x7047b8bfa200>)",
"0x210eeAC07542F815ebB6FD6689637D8cA2689392":"(<class 'nucypher.network.concurrency.ThresholdDecryptionClient.ThresholdDecryptionRequestFailed'>, ThresholdDecryptionRequestFailed('Node 0x210eeAC07542F815ebB6FD6689637D8cA2689392 raised Invalid condition grammar: Invalid condition grammar: {\\'returnValueTest\\': [\"Invalid return value comparison type \\'<class \\'str\\'>\\'; must be an integer\"]}'), <traceback object at 0x7047b8264780>)"
}

Why it's needed:

Explain how this PR fits in the greater context of the NuCypher Network. E.g.,
if this PR address a nucypher/productdev issue, let reviewers know!

Notes for reviewers:

What should reviewers focus on? Is there a particular commit/function/section
of your PR that requires more attention from reviewers?

theref and others added 30 commits July 8, 2025 13:54
- Update signUserOp test calls to include provider parameter as first argument
- Add comprehensive mocks for SigningCoordinatorAgent methods (getParticipants, getThreshold)
- Fix test expectations to match new porter API that takes signing requests and threshold
- Remove 'type' field assertions from test results to align with updated response format
- Skip integration test temporarily due to SigningCoordinator contract deployment requirements
- All unit tests now pass with the enhanced signing functionality
- Reorder imports in sign.ts and test files for consistency
- Remove 'type' field from SignResult type definition to match updated API
- Apply prettier formatting to import statements
- modify SignResult.aggregatedSignature type to allow undefined
- only return aggregated signature when no signature decoding errors exist
- export SignResult and SigningOptions types to enable sharing across packages
- remove debug console.log statement and TODO comment
…nature on errors

- change test expectation for signature decoding errors to expect undefined aggregatedSignature
- remove unused parameters in mock functions for cleaner test setup
…ckage

- remove duplicated SignResult and SigningOptions type definitions
- add comment noting types are now imported from @nucypher/shared
- improve code formatting and consistency
- import SignResult and SigningOptions from @nucypher/shared instead of local types
- consolidate multiple imports from shared package into single import statement
- improve code formatting and add missing trailing comma
- remove duplicate test case for different account types
- standardize on EIP-4337 0.8.0 account abstraction version
- streamline test descriptions for clarity
- change domain from lynx to TESTNET for consistency
- update ritual ID and chain ID for correct test environment
- standardize on EIP-4337 0.8.0 account abstraction version
- conditionally skip integration tests when not in CI environment
…tions

- reorder signUserOp function parameters for better logical grouping
- move domain and cohortId before chainId and userOp
- update parameter order: (provider, domain, cohortId, chainId, userOp, aaVersion, options, context, porterUris)
- fix test calls to match new parameter order in unit tests and integration tests
- add console.log for debugging porter signUserOp options usage
- change signUserOp method to use 'data' instead of 'params' for POST request
- aligns with other Porter methods that send data in request body
- fixes 400 Bad Request error when signing user operations
- update test expectations to match new base64-encoded signing request format
- tests now expect btoa(JSON.stringify(...)) instead of JSON.stringify(...)
- change signing request structure to match Python implementation
- use snake_case field names (cohort_id, chain_id, signature_type)
- serialize userOp as 'data' field instead of direct embedding
- update tests to match new request format
- Use sorted JSON keys for user operations to match Python implementation
- Update signing request structure with proper field names
- Add error logging for debugging Porter API responses
- Update tests to match new request format
- Add UserOperation type, UserOperationSignatureRequest class, and convertUserOperationToPython utility to shared/src/types.ts
- Export new types and classes in shared/src/index.ts
- Update taco/src/types.ts to re-export UserOperation from shared package
- Eliminates duplication of UserOperation type definitions across packages
- Fix Porter client to use POST data instead of query params for /sign endpoint
- Fix SigningCoordinator.getThreshold() to use signingCohorts(cohortId).threshold
- Update signUserOp() to use shared conversion utilities and proper base64 encoding
- Update tests to use shared conversion function and correct signature_type 'userOp'
- Remove console.log statements and simplify integration test
- All functionality now uses centralized types from shared package
- Updated SignResponse type to match new API response format with separated signatures and errors
- Enhanced PorterClient.sign() with better error handling and response structure validation
- Added debug logging to signing integration test
- Fixed signer key mapping from operator to provider in signUserOp
- Removed debug code for porter ursulas endpoint
- Remove private key security risk and use dummy address
- Switch to Ethereum Sepolia testnet (chain ID 11155111)
- Update RPC provider URL to publicnode.com
- Change ritual ID to 1
- Fix test skip condition for CI environment
- Fix UserOperationSignatureRequest constructor to accept objects instead of strings
- Remove double JSON stringification that caused address encoding errors
- Update convertUserOperationToPython to handle null/empty values properly
- Fix test expectations to match new data format and provider addresses
- Resolve AddressEncoder errors by ensuring proper hex address format

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Update test expectations to use JSON.stringify for user_op field serialization
- Rename digest field to messageHash in SignResult interface and all related code
- Implement strict address validation that fails fast on invalid checksums
- Fix Porter test mock response structure to match API format
- Update integration test to use properly checksummed addresses

Co-Authored-By: Kieran <kieranprasch@gmail.com>
…pt pattern

- Remove complex try-catch blocks and manual error checking in signUserOp
- Use direct destructuring of errors from Porter response
- Trust Porter's response structure instead of adding validation overhead
- Update tests to match new error handling pattern
- Follow same approach as tacoDecrypt for consistent error handling
- Add async forSigningCohort static method to build context from signing cohort conditions
- Fix import ordering and add missing ethers import
- Update integration test to use new signing context method with await
- Add tests for happy path scenario with valid cohort conditions
- Add error handling tests for network failures and invalid responses
- Add tests for invalid hex decoding and JSON parsing errors
- Add tests for complex compound condition structures
- Add tests for invalid condition schema validation
- Fix hex decoding in forSigningCohort method to handle contract responses
…ash validation

- Remove returnAggregated option from SigningOptions type
- Remove unused options parameter from signUserOp method
- Add validation to ensure all Ursulas return same message hash
- Throw error if message hashes don't match across signatures
…ash validation test

- Remove returnAggregated options from existing tests
- Add test case to verify error thrown when message hashes don't match
- Update test calls to match new signUserOp signature
…erface

- Remove SigningOptions import as no longer needed
- Remove options parameter from signUserOp function signature
- Update porter.signUserOp call to remove options parameter
theref and others added 24 commits January 19, 2026 16:26
Update comments to reflect current limits:
- max 5 operands in compound condition
- max 20 condition variables in sequential condition
- max 4 nested levels (previously 2)

Also increase ECDSA test chunkSize from 3 to 5.
Updates reflect toTokenBaseUnits operator and increased sequential
condition limit from 5 to 20.
Add a new create2 operation to the variable operation system that
computes Ethereum CREATE2 addresses locally, eliminating RPC calls
to factory contracts for counterfactual address resolution.

The operation takes an object value with deployerAddress and
bytecodeHash fields, both supporting context variable resolution.
This enables full Account Abstraction address derivation pipelines.

Implements taco-web equivalent of nucypher/nucypher#3703.
Move create2ValueSchema from context.ts to variable-operation.ts and
remove it from the paramOrContextParamSchema union. This prevents
non-create2 operations from accepting create2-shaped values.

Also tighten validation: deployerAddress and bytecodeHash now require
0x-prefixed hex strings instead of any plain string.
Remove OBJECT_VALUE_OPERATIONS exclusion list so create2 is covered
by the regression backstop test for operations requiring a value.
Use toContain assertion since create2 produces multiple errors.
…ema and the create2 operation schema.

Revert change to test since no longer needed.
Add parametrized test ensuring all non-unary, non-create2 operations
reject create2-shaped object values.
via [HAPI](https://hapi.run)

Co-Authored-By: HAPI <noreply@hapi.run>
via [HAPI](https://hapi.run)

Co-Authored-By: HAPI <noreply@hapi.run>
via [HAPI](https://hapi.run)

Co-Authored-By: HAPI <noreply@hapi.run>
We will use it specifically for certain ReturnValueTypes
@codecov-commenter
Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
⚠️ Please upload report for BASE (signing-epic@c6571fb). Learn more about missing BASE report.

Additional details and impacted files
@@               Coverage Diff               @@
##             signing-epic     #764   +/-   ##
===============================================
  Coverage                ?   90.20%           
===============================================
  Files                   ?       97           
  Lines                   ?     8584           
  Branches                ?      306           
===============================================
  Hits                    ?     7743           
  Misses                  ?      838           
  Partials                ?        3           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@derekpierre derekpierre marked this pull request as draft February 24, 2026 21:58
@derekpierre
Copy link
Copy Markdown
Member

derekpierre commented Feb 24, 2026

Converted to draft after conversation I had with @cygnusv about a potential alternative strategy.

@derekpierre derekpierre deleted the branch nucypher:signing-epic April 21, 2026 12:31
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.

6 participants