Skip to content

Add hinted P-384 Nitro attestation verification for Fusaka#28

Open
leanthebean wants to merge 2 commits into
base:mainfrom
leanthebean:hinted_p384
Open

Add hinted P-384 Nitro attestation verification for Fusaka#28
leanthebean wants to merge 2 commits into
base:mainfrom
leanthebean:hinted_p384

Conversation

@leanthebean
Copy link
Copy Markdown

@leanthebean leanthebean commented Jun 3, 2026

Summary

Adds a hinted P-384 verification path for AWS Nitro Enclave attestations so the full on-chain verification flow can fit under the Fusaka per-transaction gas cap without requiring a new P-384 precompile or a ZK proof system.

The core change is to make P-384 modular inversions hint-aware. Instead of computing each inverse on-chain with 384-bit MODEXP, the caller supplies the inverse as calldata and the contract verifies it before use:

b * inv == 1 mod m

Malformed, truncated, or surplus hints revert. The hints are public and fully constrained, so they are liveness-critical but not trust-critical.

What Changed

  • Adds P384Verifier, an external verifier wrapper used by both cert and attestation validation.
  • Patches the upstream ECDSA384 implementation in the solidity-lib submodule fork to support verifyWithHints.
  • Updates CertManager to use hinted P-384 verification for CA certs, client / leaf certs, and certificate caching.
  • Updates NitroValidator to use hinted verification for the final COSE attestation document signature.
  • Disables expensive unhinted runtime paths:
    • verifyCACert
    • verifyClientCert
    • validateAttestation
  • Adds off-chain reference tooling for generating hints and preparing calldata:
    • tools/p384_hints.js
    • tools/hinted_attestation_calls.js
    • tools/nitro_attestation_input.js
  • Adds a Base Sepolia demo script:
    • script/BaseSepoliaDemo.s.sol
  • Adds detailed design/audit documentation:
    • docs/hinted-p384-nitro-attestation.md

Verification Flow

The AWS Nitro root CA is pinned in CertManager at deployment and is not signature-verified on-chain.

For the bundled real attestation fixture, the cold path is:

tx action
1 verify + cache regional CA
2 verify + cache zonal CA
3 verify + cache issuer / instance CA
4 verify + cache client / leaf cert
5 validate Nitro attestation document

Once the CA chain and leaf cert are cached and unexpired, the warm path is one
transaction:

tx action
1 validate Nitro attestation document

The cache is keyed by keccak256(cert) and reused globally on-chain until certificate expiry.

Measured Gas

Measured from successful Base Sepolia receipts after Fusaka upgrade. These numbers exclude one-time deployments.

tx action hint bytes Base Sepolia gas used
1 cache regional CA 27,456 6,825,140
2 cache zonal CA 27,408 7,053,669
3 cache issuer / instance CA 27,408 6,813,103
4 cache client / leaf cert 27,504 6,825,004
5 validate Nitro attestation document 27,312 13,775,541
metric value
cold verification total 41,292,457
max verification tx 13,775,541
warm validation tx 13,775,541
per-tx cap 16,777,216
headroom under cap 3,001,675

Representative Base Sepolia tx hashes:

  • cold document validation:
    0x2cb00a86b943a29cda28be89ad990d9ca29c502c8350ba1ab89e726d44d6702e
  • warm document validation:
    0x0563932374215073fd92f8d79920af0f5d79be25c92d26bab910de8bb16a21c7

Audit Notes

The cryptographic trust delta is intentionally narrow:

  • only modular inversion is made hint-aware;
  • every supplied inverse is checked before use;
  • scalar inverses use the group order n;
  • point arithmetic inverses use the field prime p;
  • hint streams must be consumed exactly;
  • truncated hints revert with inverse hint underflow;
  • surplus hints revert with unused inverse hints;
  • malformed hints revert with bad inverse hint.

The rest of the P-384 verifier path remains the upstream ECDSA384 logic: scalar bounds, on-curve checks, Strauss-Shamir ladder, low-s handling, and final x_R == r acceptance behavior.

Testing

Passing locally:

forge fmt --check src script test
node --check tools/p384_hints.js
node --check tools/hinted_attestation_calls.js
node --check tools/nitro_attestation_input.js
forge build src script --sizes
forge test

The Forge suite covers:

  • full cold + warm hinted attestation sequence;
  • malformed, truncated, and surplus hint rejection;
  • wrong parent hash rejection;
  • expired cached cert rejection;
  • CA/client role mismatch rejection;
  • missing warm cache rejection;
  • invalid final attestation signature rejection;
  • disabled unhinted entrypoints;
  • deployable contract size checks;
  • off-chain hint generator parity with the Solidity collector.

Caveats

  • Hint calldata is around 27 KB per P-384 signature. This affects L1 data availability fees on OP Stack chains, but does not affect whether the transaction fits the execution gas cap.
  • The included Base Sepolia demo uses CertManagerDemo with an expiry grace window for an old real attestation fixture. Production deployments should use strictCertManager validity checks.
  • The off-chain generator is a reference implementation. Production services should generate the same deterministic hint streams in their own transaction-preparation flow, likely in Go or Rust.

@leanthebean leanthebean changed the title Hinted p384 Add hinted P-384 Nitro attestation verification for Fusaka Jun 3, 2026
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