-
Notifications
You must be signed in to change notification settings - Fork 182
FIP: secp256r1 (P-256) P256VERIFY precompile #1228
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
snissn
wants to merge
9
commits into
filecoin-project:master
Choose a base branch
from
snissn:secp256r1_precompile
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
4d001c8
FIP: add secp256r1 precompile draft
snissn 846b191
Update FIPS/fip-draft_secp256r1-precompile.md
snissn 4a80485
Assign FIP-0113
snissn f069121
Update FIPS/fip-0113.md
snissn b12177e
Update FIPS/fip-0113.md
snissn ee8d7fb
Reference EIP-7951 test vectors
snissn 4367911
Clarify FEVM gas accounting for P256VERIFY
snissn 042c8f8
Refine gas accounting wording
snissn 8e3ca6f
Track gas/vector/occupancy follow-ups
snissn File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,136 @@ | ||
| --- | ||
| fip: 0113 | ||
| title: secp256r1 (P-256) P256VERIFY Precompile for FEVM | ||
| author: "Aarav Mehta (@aaravm), Michael Seiler (@snissn)" | ||
| discussions-to: https://github.com/filecoin-project/FIPs/discussions/1227 | ||
| status: Draft | ||
| type: Technical | ||
| category: Core | ||
| created: 2026-01-20 | ||
| spec-sections: | ||
| --- | ||
|
|
||
| # FIP: secp256r1 (P-256) `P256VERIFY` Precompile for FEVM | ||
|
|
||
| ## Simple Summary | ||
| This proposal introduces a new FEVM precompile for efficient ECDSA signature verification over the secp256r1 (P-256) elliptic curve, as specified by Ethereum’s [EIP-7951](https://eips.ethereum.org/EIPS/eip-7951). This enables practical verification of signatures produced by common secure hardware and standards such as WebAuthn/passkeys, and improves compatibility with EVM ecosystems that already standardize on this interface. | ||
|
|
||
| ## Abstract | ||
| This FIP proposes adding a `P256VERIFY` precompile at Ethereum address `0x0000000000000000000000000000000000000100` (i.e., `0x0100`) to the FEVM. The precompile verifies an ECDSA signature `(r,s)` against a 32-byte message hash and an uncompressed public key `(x,y)` on the secp256r1 curve, returning `0x…01` on success and an empty byte array on failure. | ||
|
|
||
| For Filecoin’s purposes, **EIP-7951 and [RIP-7212](https://github.com/ethereum/RIPs/blob/master/RIPS/rip-7212.md) should be understood as addressing the same user-facing feature**: a `P256VERIFY` precompile at `0x0100`. At the EVM interface level they are equivalent: same address, same 160-byte input format, and same return values/failure behavior. The key difference is that EIP-7951 tightens validation/verification requirements (notably: a point-at-infinity check and a modular comparison `r' ≡ r (mod n)`), while Ethereum’s fixed *EVM gas schedule* for this precompile is not directly applicable to FEVM’s gas accounting model. | ||
|
|
||
| Accordingly, this FIP targets EIP-7951 semantics while remaining interface-compatible with RIP-7212-style callers. | ||
|
|
||
| ## Change Motivation | ||
| Many modern authentication and key-management systems rely on secp256r1, including WebAuthn/FIDO2 passkeys and device secure enclaves. Without a precompile, verifying secp256r1 signatures in Solidity is expensive, complex, and often impractical. | ||
|
|
||
| Adding a native precompile: | ||
| - Enables account abstraction patterns and authentication flows backed by passkeys and secure hardware. | ||
| - Improves portability of applications and libraries that already target EIP-7951 / RIP-7212 style verification. | ||
| - Provides a simpler alternative to custom signature schemes for user authentication in FEVM dApps. | ||
|
|
||
| EIP-7951 is now live on Ethereum mainnet (Fusaka, activated December 3, 2025; see announcement [here](https://blog.ethereum.org/2025/11/06/fusaka-mainnet-announcement)), making the `0x0100` interface an increasingly standard dependency in EVM tooling. Supporting the same interface in FEVM reduces friction for cross-chain portability and ecosystem reuse. | ||
|
|
||
| ## Specification | ||
|
|
||
| ### Precompile Address | ||
| This FIP adds the following precompile to the FEVM: | ||
|
|
||
| | Operation | Address | Description | | ||
| |------------|----------|----------------------------------------------| | ||
| | `P256VERIFY` | `0x0100` | secp256r1 (P-256) ECDSA signature verification | | ||
|
|
||
| The address `0x0100` MUST be treated as a reserved precompile address (i.e., it is not deployable via the EAM). | ||
|
|
||
| ### ABI | ||
|
|
||
| #### Input | ||
| The precompile expects exactly 160 bytes of input, interpreted as the concatenation: | ||
|
|
||
| `msg_hash(32) || r(32) || s(32) || pubkey_x(32) || pubkey_y(32)` | ||
|
|
||
| All values are unsigned, big-endian encoded. | ||
|
|
||
| The `msg_hash` is the 32-byte hash of the signed message (i.e., the precompile performs verification on a pre-hashed message). | ||
|
|
||
| #### Output | ||
| - If the signature is valid, the precompile returns 32 bytes equal to: | ||
| `0x0000000000000000000000000000000000000000000000000000000000000001` | ||
| - Otherwise (including malformed input), it returns an empty byte array. | ||
|
|
||
| The precompile MUST NOT revert under any circumstances due to malformed input or signature failure. | ||
|
|
||
| ### EIP-7951 / RIP-7212 Interface Compatibility | ||
| EIP-7951 intentionally retains the RIP-7212 interface. For FEVM, this means: | ||
| - Same address: `0x0100` | ||
| - Same input format: 160 bytes (`msg_hash || r || s || x || y`) | ||
| - Same output format: 32 bytes on success, empty bytes on failure | ||
| - Same return values and “no-revert” failure semantics | ||
|
|
||
| EIP-7951 additionally tightens validation/verification requirements (security fixes). Ethereum specifies a fixed EVM gas cost for the precompile; FEVM uses Filecoin gas accounting instead (see “Gas Accounting”). | ||
|
|
||
| ### Validation and Verification Rules | ||
| The precompile MUST implement the validation rules described in EIP-7951, including: | ||
| - Input length MUST be exactly 160 bytes. | ||
| - Signature components `r` and `s` MUST satisfy `0 < r < n` and `0 < s < n`, where `n` is the curve subgroup order. | ||
| - Public key coordinates `x` and `y` MUST satisfy `0 ≤ x < p` and `0 ≤ y < p`, where `p` is the base field modulus. | ||
| - The point `(x, y)` MUST be on the secp256r1 curve and MUST NOT be the point at infinity. | ||
| - Signature verification MUST follow ECDSA verification for secp256r1 and MUST be deterministic across implementations, including: | ||
| - Rejecting cases where the recovered point `R'` (in the ECDSA verification procedure) is the point at infinity. | ||
| - Comparing `r'` to `r` modulo `n` (i.e., `r' ≡ r (mod n)`). | ||
|
|
||
| ### Gas Accounting | ||
| FEVM gas accounting follows Filecoin mechanics (not Ethereum’s), as described in [FIP-0054](./fip-0054.md). | ||
snissn marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| EIP-7951 specifies an Ethereum gas cost for `P256VERIFY`, and RIP-7212 specifies a different Ethereum gas cost for the same interface. **FEVM does not adopt Ethereum’s fixed gas schedule for precompiles**, so this FIP does not specify an Ethereum-style gas number. Instead, it introduces the precompile and specifies its input/output semantics and validation behavior. | ||
|
|
||
| An implementation must not introduce a special syscall/pricelist gas charge for this operation. Execution is charged via FEVM’s normal instrumented Wasm instruction accounting, so the observed cost depends on the Wasm-level execution cost of the precompile implementation. | ||
|
|
||
| ## Design Rationale | ||
| This FIP adopts the EIP-7951/RIP-7212 `0x0100` interface to maximize compatibility with existing EVM tooling and contracts. | ||
|
|
||
| EIP-7951 supersedes RIP-7212 by keeping the same interface while fixing edge cases that can lead to incorrect or implementation-dependent behavior. This FIP therefore specifies EIP-7951’s stricter validation and verification rules while preserving full interface compatibility with RIP-7212-style callers. | ||
|
|
||
| The precompile performs verification (not public key recovery) because secp256r1 signing stacks commonly expose verification APIs and do not universally produce recovery identifiers. | ||
|
|
||
| ## Backwards Compatibility | ||
| This FIP introduces a new reserved precompile address at `0x0100`. Any existing contract calls to this address that previously executed deployed bytecode (if such bytecode exists) will instead execute the precompile after the upgrade. While creating a contract at this exact address is extremely unlikely in practice, it is possible (e.g., via `CREATE2`) prior to the address being reserved. | ||
|
|
||
| Contracts that do not use `0x0100` are unaffected. | ||
|
|
||
| ## Test Cases | ||
snissn marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| An implementation of this FIP SHOULD include: | ||
| - Unit tests using known-good secp256r1 ECDSA verification vectors (success and failure cases), including EIP-7951 test vectors from https://eips.ethereum.org/assets/eip-7951/test-vectors.json. | ||
| - Integration tests that invoke the precompile from Solidity, including: | ||
| - Valid signature verification returning `0x…01`. | ||
| - Invalid inputs returning empty output (without reverting). | ||
| - Calls with non-zero value, ensuring transfer semantics match FEVM precompile behavior. | ||
|
|
||
| ## Security Considerations | ||
| This precompile verifies signatures over untrusted inputs and MUST be implemented carefully to avoid consensus-critical discrepancies across clients. In particular: | ||
| - Validation MUST reject invalid encodings, out-of-range values, invalid points, and infinity edge cases in a deterministic manner. | ||
| - The precompile interface does not enforce non-malleability checks (e.g., “low-s” normalization); applications that require non-malleability SHOULD enforce it at a higher layer. | ||
| - Implementations are not required to be constant-time, but must be safe with respect to malformed input and must not panic or exhibit undefined behavior. | ||
|
|
||
| ## Incentive Considerations | ||
| This FIP introduces no changes to Filecoin consensus incentives. It enables new applications and authentication patterns in FEVM smart contracts. | ||
|
|
||
| ## Product Considerations | ||
| This precompile makes passkey/WebAuthn-backed authentication and device-secure signing practical for FEVM applications. It also improves compatibility with Ethereum ecosystems adopting the same precompile interface, reducing friction for developers porting contracts and libraries to Filecoin. | ||
|
|
||
| ## Implementation | ||
| Reference implementation is available and ready for review: | ||
| - builtin-actors: https://github.com/filecoin-project/builtin-actors/pull/1708 | ||
| - Lotus (integration test): TODO | ||
|
|
||
| Node implementations (e.g., Lotus, Forest) will need to consume the updated built-in actors bundle in a network upgrade. | ||
|
|
||
| ## TODO | ||
| - Decide the target network upgrade / actor bundle version for activation. | ||
snissn marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| - Benchmark gas for representative `P256VERIFY` calls under FEVM’s Wasm-instrumented gas accounting. | ||
| - Validate EIP-7951 test vectors against a deployed `0x0100` precompile once available in a target network. | ||
| - Check whether `0x0100` has been occupied on relevant networks prior to reserving it, and document findings. | ||
|
|
||
| ## Copyright | ||
| Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). | ||
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
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.
Uh oh!
There was an error while loading. Please reload this page.