Skip to content
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

Update EIP-2537: Editorial #8274

Merged
merged 8 commits into from
Mar 12, 2024
Merged
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 61 additions & 47 deletions EIPS/eip-2537.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ If `block.number >= X` we introduce *nine* separate precompiles to perform the f
- BLS12_G2MUL - to perform point multiplication in G2 (curve over quadratic extension of the base prime field) with a gas cost of `45000` gas
- BLS12_G2MULTIEXP - to perform multiexponentiation in G2 (curve over quadratic extension of the base prime field) with a gas cost formula defined in the corresponding section
- BLS12_PAIRING - to perform a pairing operations between a set of *pairs* of (G1, G2) points a gas cost formula defined in the corresponding section
- BLS12_MAP_FP_TO_G1 - maps base field element into the G1 point with a gast cost of `5500` gas
- BLS12_MAP_FP_TO_G1 - maps base field element into the G1 point with a gas cost of `5500` gas
- BLS12_MAP_FP2_TO_G2 - maps extension field element into the G2 point with a gas cost of `75000` gas

A mapping functions specification is included as a separate [document](../assets/eip-2537/field_to_curve.md). This mapping function does NOT perform mapping of the byte string into a field element (as it can be implemented in many different ways and can be efficiently performed in EVM), but only does field arithmetic to map a field element into a curve point. Such functionality is required for signature schemes.
Expand Down Expand Up @@ -53,12 +53,14 @@ Curve parameters:
The BLS12 curve is fully defined by the following set of parameters (coefficient `A=0` for all BLS12 curves):

```
Base field modulus = 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab
Base field modulus = p = 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab
Fp - finite field of size p
Curve Fp equation: Y^2 = X^3+B (mod p)
B coefficient = 0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004
Main subgroup order = 0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001
Main subgroup order = q =0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001
Extension tower
Fp2 construction:
Fp quadratic non-residue = 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaaa
Fp quadratic non-residue = nr2 = 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaaa
Fp6/Fp12 construction:
Fp2 cubic non-residue c0 = 0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
Fp2 cubic non-residue c1 = 0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
Expand All @@ -67,10 +69,10 @@ Twist type: M
B coefficient for twist c0 = 0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004
B coefficient for twist c1 = 0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004
Generators:
G1:
H1:
Copy link
Contributor

Choose a reason for hiding this comment

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

why H and not G?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Just to resolve ambiguity. Because G1 is used for a group of points.

X = 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb
Y = 0x08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1
G2:
H2:
X c0 = 0x024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8
X c1 = 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e
Y c0 = 0x0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801
Expand All @@ -80,33 +82,43 @@ Pairing parameters:
x is negative = true
```

One should note that the base field modulus is equal to `3 mod 4` that allows an efficient square root extraction, although as described below, the gas cost of decompression is larger than the gas cost of supplying decompressed point data in `calldata`.
One should note that base field modulus `p` is equal to `3 mod 4` that allows an efficient square root extraction, although as described below gas cost of decompression is larger than gas cost of supplying decompressed point data in `calldata`.

### Fields and Groups

Field Fp is defined as the finite field of size `p` with elements represented as integers between 0 and p-1 (both inclusive).

Field Fp2 is defined as `Fp[X]/(X^2-nr2)` with elements `el = c0 + c1 * v`, where `v` is the formal square root of `nr2` represented as integer pairs `(c0,c1)`.

Group G1 is defined as a set of Fp pairs (points) `(x,y)` such that either `(x,y)` is `(0,0)` or `x,y` satisfy the curve Fp equation.

Group G2 is defined as a set of Fp2 pairs (points) `(x',y')` such that either `(x,y)` is `(0,0)` or `(x',y')` satisfy the curve Fp2 equation.

### Fine points and encoding of base elements

#### Field elements encoding:

To encode points involved in the operation one has to encode elements of the base field and the extension field.
In order to produce inputs to an operation, one encodes elements of the base field and the extension field.

A base field element (Fp) is encoded as `64` bytes by performing BigEndian encoding of the corresponding (unsigned) integer. Due to the size of `p`, the top `16` bytes are always zeroes. `64` bytes are chosen to have `32` byte aligned ABI (representable as e.g. `bytes32[2]` or `uint256[2]`). The corresponding integer **must** be less than field modulus.
A base field element (Fp) is encoded as `64` bytes by performing the BigEndian encoding of the corresponding (unsigned) integer. Due to the size of `p`, the top `16` bytes are always zeroes. `64` bytes are chosen to have `32` byte aligned ABI (representable as e.g. `bytes32[2]` or `uint256[2]` with the latter assuming the BigEndian encoding). The corresponding integer **must** be less than field modulus.

For elements of the quadratic extension field (Fp2), encoding is byte concatenation of individual encoding of the coefficients totaling in `128` bytes for a total encoding. For an Fp2 element in a form `el = c0 + c1 * v` where `v` is the formal square root of a quadratic non-residue and `c0` and `c1` are Fp elements the corresponding byte encoding will be `encode(c0) || encode(c1)` where `||` means byte concatenation (or one can use `bytes32[4]` or `uint256[4]` in terms of Solidity types).

*Note on the top `16` bytes being zero*: it is required that the encoded element is "in a field" that means strictly `< modulus`. In BigEndian encoding it automatically means that for a modulus that is just `381` bit long top `16` bytes in `64` bytes encoding are zeroes and it **must** be checked if only a subslice of input data is used for actual decoding.
*Note on the top `16` bytes being zero*: it is required that an encoded element is "in a field", which means strictly `< modulus`. In BigEndian encoding it automatically means that for a modulus that is just `381` bit long the top `16` bytes in `64` bytes encoding are zeroes and this **must** be checked even if only a subslice of input data is used for actual decoding.

If encodings do not follow this spec anywhere during parsing in the precompile the precompile *must* return an error.
On inputs that can not be a valid encodings of field elements the precompile *must* return an error.

#### Encoding of points in G1/G2:

Points in either G1 (in base field) or in G2 (in extension field) are encoded as byte concatenation of encodings of the `x` and `y` affine coordinates. Total encoding length for G1 point is thus `128` bytes and for G2 point is `256` bytes.
Points of G1 and G2 are encoded as byte concatenation of the respective encodings of the `x` and `y` coordinates. Total encoding length for a G1 point is thus `128` bytes and for a G2 point is `256` bytes.

#### Point of infinity encoding:

Also referred to as "zero point". For BLS12 curves, the point with coordinates `(0, 0)` (zeroes in Fp or Fp2) is *not* on the curve, so a sequence of `128` resp. `256` zero bytes, which naively would decode as `(0, 0)` is instead used by convention to encode the point of infinity of G1 resp. G2.
Also referred to as the "zero point". For BLS12 curves, the point with coordinates `(0, 0)` (zeroes in Fp or Fp2) is *not* on the curve, so a sequence of `128` resp. `256` zero bytes, which naively would decode as `(0, 0)` is instead used by convention to encode the point of infinity of G1 resp. G2.

#### Encoding of scalars for multiplication operation:

The scalar for multiplication operation is encoded as `32` bytes by performing BigEndian encoding of the corresponding (unsigned) integer. The corresponding integer is **not** required to be less than or equal than main subgroup size.
A scalar for the multiplication operation is encoded as `32` bytes by performing BigEndian encoding of the corresponding (unsigned) integer. The corresponding integer is **not** required to be less than or equal than main subgroup order `q`.

#### Behavior on empty inputs:

Expand All @@ -120,96 +132,97 @@ G1 addition call expects `256` bytes as an input that is interpreted as byte con

Error cases:

- Either of points being not on the curve must result in error
- Field elements encoding rules apply (obviously)
- Invalid coordinate encoding
- Either of points not in G1 (i.e. neither on a curve nor the infinity point)
- Input has invalid length

#### ABI for G1 multiplication

G1 multiplication call expects `160` bytes as an input that is interpreted as byte concatenation of encoding of G1 point (`128` bytes) and encoding of a scalar value (`32` bytes). Output is an encoding of multiplication operation result - single G1 point (`128` bytes).
G1 multiplication call expects `160` bytes as an input that is interpreted as byte concatenation of encoding of a G1 point (`128` bytes) and encoding of a scalar value (`32` bytes). Output is an encoding of the multiplication operation result - a single G1 point (`128` bytes).

Error cases:

- Point being not on the curve must result in error
- Field elements encoding rules apply (obviously)
- Invalid coordinate encoding
- The point not in G1 (i.e. neither on a curve nor the infinity point)
- Input has invalid length

#### ABI for G1 multiexponentiation

G1 multiexponentiation call expects `160*k` bytes as an input that is interpreted as byte concatenation of `k` slices each of them being a byte concatenation of encoding of G1 point (`128` bytes) and encoding of a scalar value (`32` bytes). Output is an encoding of multiexponentiation operation result - single G1 point (`128` bytes).
G1 multiexponentiation call expects `160*k` (`k` being a **positive** integer) bytes as an input that is interpreted as byte concatenation of `k` slices each of them being a byte concatenation of encoding of a G1 point (`128` bytes) and encoding of a scalar value (`32` bytes). Output is an encoding of multiexponentiation operation result - a single G1 point (`128` bytes).

Error cases:

- Any of G1 points being not on the curve must result in error
- Field elements encoding rules apply (obviously)
- Input has invalid length
- Input is empty
- Invalid coordinate encoding
- Any point not in G1 (i.e. neither on a curve nor the infinity point)
- Input has invalid length

#### ABI for G2 addition

G2 addition call expects `512` bytes as an input that is interpreted as byte concatenation of two G2 points (`256` bytes each). Output is an encoding of addition operation result - single G2 point (`256` bytes).
G2 addition call expects `512` bytes as an input that is interpreted as byte concatenation of two G2 points (`256` bytes each). Output is an encoding of addition operation result - a single G2 point (`256` bytes).

Error cases:

- Either of points being not on the curve must result in error
- Field elements encoding rules apply (obviously)
- Input has invalid length
- Invalid coordinate encoding
- Either of points not in G2 (i.e. neither on a curve nor the infinity point)
- Input has invalid length

#### ABI for G2 multiplication

G2 multiplication call expects `288` bytes as an input that is interpreted as byte concatenation of encoding of G2 point (`256` bytes) and encoding of a scalar value (`32` bytes). Output is an encoding of multiplication operation result - single G2 point (`256` bytes).

Error cases:

- Point being not on the curve must result in error
- Field elements encoding rules apply (obviously)
- Input has invalid length
- Invalid coordinate encoding
- Either of points not in G1 (i.e. neither on a curve nor the infinity point)
- Input has invalid length


#### ABI for G2 multiexponentiation

G2 multiexponentiation call expects `288*k` bytes as an input that is interpreted as byte concatenation of `k` slices each of them being a byte concatenation of encoding of G2 point (`256` bytes) and encoding of a scalar value (`32` bytes). Output is an encoding of multiexponentiation operation result - single G2 point (`256` bytes).
G2 multiexponentiation call expects `288*k` bytes as an input that is interpreted as byte concatenation of `k` slices each of them being a byte concatenation of encoding of G2 point (`256` bytes) and encoding of a scalar value (`32` bytes). Output is an encoding of multiexponentiation operation result - a single G2 point (`256` bytes).

Error cases:

- Any of G2 points being not on the curve must result in error
- Field elements encoding rules apply (obviously)
- Input has invalid length
- Input is empty
- Invalid coordinate encoding
- Any point not in G2 (i.e. neither on a curve nor the infinity point)
- Input has invalid length

#### ABI for pairing

Pairing call expects `384*k` bytes as an inputs that is interpreted as byte concatenation of `k` slices. Each slice has the following structure:
Pairing call expects `384*k` (`k` being a **positive** integer) bytes as an inputs that is interpreted as byte concatenation of `k` slices. Each slice has the following structure:

- `128` bytes of G1 point encoding
- `256` bytes of G2 point encoding

Each point is expected to be in the subgroup of order `q`.

Output is a `32` bytes where first `31` bytes are equal to `0x00` and the last byte is `0x01` if pairing result is equal to the multiplicative identity in a pairing target field and `0x00` otherwise.

Error cases:

- Any of G1 or G2 points being not on the curve must result in error
- Any of G1 or G2 points are not in the correct subgroup
- Field elements encoding rules apply (obviously)
- Input has invalid length
- Input is empty
- Invalid coordinate encoding
- Any of points being not on the respective curve
- Any of points is not in the correct subgroup
- Input has invalid length

#### ABI for mapping Fp element to G1 point

Field-to-curve call expects `64` bytes as an input that is interpreted as an element of the base field. Output of this call is `128` bytes and is G1 point following respective encoding rules.
Field-to-curve call expects `64` bytes as an input that is interpreted as an element of Fp. Output of this call is `128` bytes and is an encoded G1 point.

Error cases:

- Input has invalid length
- Input is not a valid field element
- Input is not correctly encoded

#### ABI for mapping Fp2 element to G2 point

Field-to-curve call expects `128` bytes as an input that is interpreted as a an element of the quadratic extension field. Output of this call is `256` bytes and is G2 point following respective encoding rules.
Field-to-curve call expects `128` bytes as an input that is interpreted as a an element of Fp2. Output of this call is `256` bytes and is an encoded G2 point.

Error cases:

- Input has invalid length
- Input is not a valid field element
- Input is not correctly encoded


### Gas burning on error

Expand Down Expand Up @@ -320,7 +333,8 @@ There are no backward compatibility questions.

### Subgroup checks

A subgroup check **is mandatory** during the pairing call. Implementations *should* use fast subgroup checks: at the time of writing, multiplication gas cost is based on the `double-and-add` multiplication method that has a clear "worst case" (all bits are equal to one). For pairing operations, it is expected that implementations use faster subgroup checks, e.g. by using the wNAF multiplication method for elliptic curves that is ~ `40%` cheaper with windows size equal to 4. (Tested empirically. Savings are due to lower hamming weight of the group order and even lower hamming weight for wNAF. Concretely, subgroup check for both G1 and G2 points in a pair are around `35000` combined).
The subgroup check for point `H` verifies that `H` multiplied by scalar `q` yields the infinity point on the respective curve.
Copy link
Contributor

Choose a reason for hiding this comment

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

rather than use this naive expensive subgroup check (in particular for G2) I'd rather suggest to point to https://eprint.iacr.org/2021/1130.pdf

Copy link
Contributor Author

@khovratovich khovratovich Mar 1, 2024

Choose a reason for hiding this comment

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

Can we provide complexity estimates for this method? What is the value of u?

Copy link
Contributor

Choose a reason for hiding this comment

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

it's all in the paper. 'u' is the seed for generating BLS12-381 and pretty short ( -0xd201000000010000)

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, you should not require "check by multiplication" only. Whether we should require fast subgroup checks or not is a separate question

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Reformulated the text with your link @asanso

The check **is mandatory** during the pairing call. Implementations *should* use fast subgroup checks: at the time of writing, multiplication gas cost is based on the `double-and-add` multiplication method that has a clear "worst case" (all bits are equal to one). For pairing operations, it is expected that implementations use faster subgroup checks, e.g. by using the wNAF multiplication method for elliptic curves that is ~ `40%` cheaper with windows size equal to 4. (Tested empirically. Savings are due to lower hamming weight of the group order and even lower hamming weight for wNAF. Concretely, subgroup check for both G1 and G2 points in a pair are around `35000` combined).

### Field to curve mapping

Expand Down
Loading