Skip to content

Conversation

snissn
Copy link
Contributor

@snissn snissn commented Apr 11, 2025

Description

This PR introduces full support for EIP-2537 in the Filecoin EVM, implementing a suite of precompiled contracts that perform operations over the BLS12-381 elliptic curve. These precompiles enable efficient and secure cryptographic operations needed for BLS signature schemes, pairing-based proofs, and other advanced protocols. They mirror Ethereum’s spec exactly to ensure compatibility with existing tooling and cross-chain applications.

Each precompile validates input encoding, field membership, and subgroup properties as required by the EIP. Failure on malformed inputs is deterministic and burns all gas, consistent with Ethereum behavior.


New Operations

The following precompiled contracts are now available at their EIP-2537-defined addresses:

Precompile Address Description
BLS12_G1ADD 0x0b Add two G1 points
BLS12_G1MSM 0x0c Multi-scalar multiplication over G1
BLS12_G2ADD 0x0d Add two G2 points
BLS12_G2MSM 0x0e Multi-scalar multiplication over G2
BLS12_PAIRING_CHECK 0x0f Perform a bilinear pairing check
BLS12_MAP_FP_TO_G1 0x10 Map an Fp field element to a G1 curve point
BLS12_MAP_FP2_TO_G2 0x11 Map an Fp2 field element to a G2 curve point

All operations follow the ABI, encoding rules, and semantics outlined in the EIP.


Testing

The test suite ensures correctness, security, and spec compliance:

Success Cases

  • G1/G2 point addition, including identity and negation
  • MSM over G1/G2 with valid (point, scalar) pairs and edge cases
  • Mapping from Fp/Fp2 to G1/G2 with valid canonical field encodings
  • Pairing tests verifying bilinearity, identity, and non-degeneracy

Failure Cases

  • Invalid input lengths
  • Malformed field element encoding
  • Points not on curve
  • Points not in subgroup (where applicable)
  • Incomplete MSM or pairing input slices

🧪 Edge Behavior

  • Infinity points handled explicitly
  • Zero scalars in MSM yield valid identity outputs

Implementation Notes

  • Backed by blst, a battle-tested BLS12-381 library used across the Ethereum ecosystem
  • Precompiles are integrated into the EVM interpreter via the Filecoin System interface

Remaining TODOs

  • Solidity-based test coverage: While the Rust test suite exhaustively covers encoding, decoding, correctness, and failure behavior, we still need to add Solidity tests that invoke these precompiles via contracts.

This PR enhances FEVM’s cryptographic capabilities, aligning Filecoin with Ethereum’s tooling and enabling secure, high-performance applications that depend on BLS12-381.

@@ -230,6 +230,12 @@ pub(super) fn extract_g2_input(
/// Accepts a safe reference to a `blst_fp`; the only unsafe is localized to
/// the FFI call that writes the big-endian bytes.
pub(super) fn fp_to_bytes(out: &mut [u8], input: &blst_fp) {
debug_assert_eq!(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you just add this to check if we ever hit this condition? I think it would be reasonable to just keep this as an assert and fail the call if out buffer is inproperly sized. I know its a departure from revm but it seems more correct.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just removed this assert, since these values are chacked for anyways just below the debug_assert. 931ba51

@@ -303,7 +309,9 @@ fn decode_g1_on_curve(
// * An input is neither a point on the G1 elliptic curve nor the infinity point
//
// SAFETY: Out is a blst value.
if unsafe { !blst_p1_affine_on_curve(&out) } {
let on_curve = unsafe { blst_p1_affine_on_curve(&out) };
let is_inf = unsafe { blst_p1_affine_is_inf(&out) };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

blst_p1_affine_on_curve checks this (https://github.com/supranational/blst/blob/master/src/e1.c#L115) and revm implementation just does the one call. I don't see a good reason to introduce 2 ffi crossings unless you have a strong reason I am missing.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed: 931ba51

@@ -345,7 +353,9 @@ fn decode_g2_on_curve(
// * An input is neither a point on the G2 elliptic curve nor the infinity point
//
// SAFETY: Out is a blst value.
if unsafe { !blst_p2_affine_on_curve(&out) } {
let on_curve = unsafe { blst_p2_affine_on_curve(&out) };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as this

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed: 931ba51

Comment on lines 58 to 63
/// Note: While this function contains an unsafe block for BLST operations,
/// the function itself is safe because:
/// 1. Input types (&blst_fp2) are guaranteed safe by Rust's type system
/// 2. All possible input variants are covered by test vectors from EIP-2537
///
/// The unsafe block is used purely for FFI calls to the BLST library.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// Note: While this function contains an unsafe block for BLST operations,
/// the function itself is safe because:
/// 1. Input types (&blst_fp2) are guaranteed safe by Rust's type system
/// 2. All possible input variants are covered by test vectors from EIP-2537
///
/// The unsafe block is used purely for FFI calls to the BLST library.
/// Note: While this function contains an unsafe block for BLST operations,
/// the function itself is safe because:
/// 1. input types are all defined by blst and `repr(C)`
/// 2. blst behavior is assumed memory safe
/// 3. The unsafe block is used purely for FFI calls to the BLST library.

Please use this block throughout. I remove reference to inputs type (which was incorrect here) so that you can copy paste everywherre without worrying about fixing up.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed: b11a19b

@ZenGround0
Copy link
Contributor

@snissn #1669 (comment)

@github-project-automation github-project-automation bot moved this from ⌨️ In Progress to ✔️ Approved by reviewer in FilOz Aug 27, 2025
@ZenGround0 ZenGround0 enabled auto-merge August 27, 2025 22:35
@ZenGround0 ZenGround0 added this pull request to the merge queue Aug 27, 2025
Merged via the queue into filecoin-project:master with commit 747a3ed Aug 27, 2025
12 checks passed
@github-project-automation github-project-automation bot moved this from ⌨️ In Progress to 🎉 Done in nv27 Track Board Aug 27, 2025
@github-project-automation github-project-automation bot moved this from ✔️ Approved by reviewer to 🎉 Done in FilOz Aug 27, 2025
@BigLep
Copy link
Member

BigLep commented Sep 1, 2025

Validation in Lotus will be tracked in filecoin-project/lotus#13285

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: 🎉 Done
Status: 🎉 Done
Development

Successfully merging this pull request may close these issues.

6 participants