From 57c863dc306b584405593fb4751263e240111417 Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Tue, 26 May 2020 10:04:23 +0200 Subject: [PATCH 1/8] EIP-2315: update jumpsub gascost and add back testcases (#2669) --- EIPS/eip-2315.md | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/EIPS/eip-2315.md b/EIPS/eip-2315.md index 6ab9a5360dc585..517e3d77621a93 100644 --- a/EIPS/eip-2315.md +++ b/EIPS/eip-2315.md @@ -80,7 +80,7 @@ Bytecode: `0x6004b300b2b7` | Pc | Op | Cost | Stack | RStack | |-------|-------------|------|-----------|-----------| | 0 | PUSH1 | 3 | [] | [] | -| 2 | JUMPSUB | 5 | [4] | [] | +| 2 | JUMPSUB | 8 | [4] | [] | | 5 | RETURNSUB | 2 | [] | [ 2] | | 3 | STOP | 0 | [] | [] | @@ -92,9 +92,9 @@ Bytecode: `0x6800000000000000000cb300b26011b3b7b2b7` | Pc | Op | Cost | Stack | RStack | |-------|-------------|------|-----------|-----------| | 0 | PUSH9 | 3 | [] | [] | -| 10 | JUMPSUB | 5 | [12] | [] | +| 10 | JUMPSUB | 8 | [12] | [] | | 13 | PUSH1 | 3 | [] | [10] | -| 15 | JUMPSUB | 5 | [17] | [10] | +| 15 | JUMPSUB | 8 | [17] | [10] | | 18 | RETURNSUB | 2 | [] | [10,15] | | 16 | RETURNSUB | 2 | [] | [10] | | 11 | STOP | 0 | [] | [] | @@ -110,7 +110,7 @@ Bytecode: `0x6801000000000000000cb300b26011b3b7b2b7 ` | Pc | Op | Cost | Stack | RStack | |-------|-------------|------|-----------|-----------| | 0 | PUSH9 | 3 | [] | [] | -| 10 | JUMPSUB | 5 |[18446744073709551628] | [] | +| 10 | JUMPSUB | 8 |[18446744073709551628] | [] | ``` Error: at pc=10, op=JUMPSUB: evm: invalid jump destination @@ -143,12 +143,25 @@ Bytecode: `0x600556b2b75b6003b3` | 2 | JUMP | 8 | [5] | [] | | 5 | JUMPDEST | 1 | [] | [] | | 6 | PUSH1 | 3 | [] | [] | -| 8 | JUMPSUB | 5 | [3] | [] | -| 3 | BEGINSUB | 1 | [] | [ 8] | +| 8 | JUMPSUB | 8 | [3] | [] | | 4 | RETURNSUB | 2 | [] | [ 8] | | 9 | STOP | 0 | [] | [] | -Consumed gas: `26` +Consumed gas: `25` + +### Error on "walk-into-subroutine" + +In this example, the code 'walks' into a subroutine, which is not allowed, and causes an error + +| Pc | Op | Cost | Stack | RStack | +|-------|-------------|------|-----------|-----------| +| 0 | BEGINSUB | 1 | [] | [] | + + +``` +Error: at pc=0, op=BEGINSUB: invalid subroutine entry +``` +**Note 5**: The content of the error message, (`invalid subroutine entry`) is implementation-specific. ## Implementations @@ -162,7 +175,7 @@ The changes for the current version are trivial. ### Costs and Codes -We suggest that the cost of `JUMPSUB` be _low_, and `RETURNSUB` be _verylow_. +We suggest that the cost of `BEGINSUB` be _base_, `JUMPSUB` be _mid_, and `RETURNSUB` be _verylow_. Measurement will tell. We suggest the following opcodes: ``` @@ -171,6 +184,8 @@ We suggest that the cost of `JUMPSUB` be _low_, and `RETURNSUB` be _verylow_. 0xb7 RETURNSUB ``` +**Note 6**: Although specified at _base_, the cost of `BEGINSUB` does not matter in practice, since `BEGINSUB` never executes without error. + ## Security Considerations These changes do introduce new flow control instructions, so any software which does static/dynamic analysis of evm-code From 4cc3816b9567090b2b4118392631ef8546103723 Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Tue, 26 May 2020 21:32:24 +0200 Subject: [PATCH 2/8] Mark EIP-695 as Final (#2432) --- EIPS/eip-695.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/EIPS/eip-695.md b/EIPS/eip-695.md index db00a279ed14f0..8806e4adbb25c1 100644 --- a/EIPS/eip-695.md +++ b/EIPS/eip-695.md @@ -5,8 +5,7 @@ author: Isaac Ardis , Wei Tang (@sorpaas), Fan Torchz (@t discussions-to: https://ethereum-magicians.org/t/eip-695-create-eth-chainid-method-for-json-rpc/1845 type: Standards Track category: Interface -status: Last Call -review-period-end: 2019-07-20 +status: Final created: 2017-08-21 requires: 155, 1474 --- From 477a1920d9ad41a6acc6e94c433a021ba0b510c8 Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Fri, 29 May 2020 17:00:56 +0200 Subject: [PATCH 3/8] 2315: changes in gascosts (#2676) --- EIPS/eip-2315.md | 66 ++++++++++++++++++++++++++++-------------------- 1 file changed, 39 insertions(+), 27 deletions(-) diff --git a/EIPS/eip-2315.md b/EIPS/eip-2315.md index 517e3d77621a93..ab41c5e37ec097 100644 --- a/EIPS/eip-2315.md +++ b/EIPS/eip-2315.md @@ -76,59 +76,62 @@ This should jump into a subroutine, back out and stop. Bytecode: `0x6004b300b2b7` - | Pc | Op | Cost | Stack | RStack | |-------|-------------|------|-----------|-----------| | 0 | PUSH1 | 3 | [] | [] | -| 2 | JUMPSUB | 8 | [4] | [] | -| 5 | RETURNSUB | 2 | [] | [ 2] | +| 2 | JUMPSUB | 10 | [4] | [] | +| 5 | RETURNSUB | 5 | [] | [ 2] | | 3 | STOP | 0 | [] | [] | +Output: 0x +Consumed gas: `18` + ### Two levels of subroutines This should execute fine, going into one two depths of subroutines + Bytecode: `0x6800000000000000000cb300b26011b3b7b2b7` | Pc | Op | Cost | Stack | RStack | |-------|-------------|------|-----------|-----------| | 0 | PUSH9 | 3 | [] | [] | -| 10 | JUMPSUB | 8 | [12] | [] | +| 10 | JUMPSUB | 10 | [12] | [] | | 13 | PUSH1 | 3 | [] | [10] | -| 15 | JUMPSUB | 8 | [17] | [10] | -| 18 | RETURNSUB | 2 | [] | [10,15] | -| 16 | RETURNSUB | 2 | [] | [10] | +| 15 | JUMPSUB | 10 | [17] | [10] | +| 18 | RETURNSUB | 5 | [] | [10,15] | +| 16 | RETURNSUB | 5 | [] | [10] | | 11 | STOP | 0 | [] | [] | +Consumed gas: `36` ### Failure 1: invalid jump -This should fail, since the given `location` is outside of the code-range. The code is the same as previous example, -except that the pushed `location` is `0x01000000000000000c` instead of `0x0c`. +This should fail, since the given location is outside of the code-range. The code is the same as previous example, +except that the pushed location is `0x01000000000000000c` instead of `0x0c`. -Bytecode: `0x6801000000000000000cb300b26011b3b7b2b7 ` +Bytecode: `0x6801000000000000000cb300b26011b3b7b2b7` | Pc | Op | Cost | Stack | RStack | |-------|-------------|------|-----------|-----------| | 0 | PUSH9 | 3 | [] | [] | -| 10 | JUMPSUB | 8 |[18446744073709551628] | [] | +| 10 | JUMPSUB | 10 |[18446744073709551628] | [] | ``` -Error: at pc=10, op=JUMPSUB: evm: invalid jump destination +Error: at pc=10, op=JUMPSUB: invalid jump destination ``` ### Failure 2: shallow `return stack` -This should fail at first opcode, due to shallow `return stack` +This should fail at first opcode, due to shallow `return_stack` Bytecode: `0xb75858` (`RETURNSUB`, `PC`, `PC`) - | Pc | Op | Cost | Stack | RStack | |-------|-------------|------|-----------|-----------| -| 0 | RETURNSUB | 2 | [] | [] | +| 0 | RETURNSUB | 5 | [] | [] | ``` -Error: at pc=0, op=RETURNSUB: evm: invalid retsub +Error: at pc=0, op=RETURNSUB: invalid retsub ``` ### Subroutine at end of code @@ -143,40 +146,51 @@ Bytecode: `0x600556b2b75b6003b3` | 2 | JUMP | 8 | [5] | [] | | 5 | JUMPDEST | 1 | [] | [] | | 6 | PUSH1 | 3 | [] | [] | -| 8 | JUMPSUB | 8 | [3] | [] | -| 4 | RETURNSUB | 2 | [] | [ 8] | +| 8 | JUMPSUB | 10 | [3] | [] | +| 4 | RETURNSUB | 5 | [] | [ 8] | | 9 | STOP | 0 | [] | [] | -Consumed gas: `25` +Consumed gas: `30` ### Error on "walk-into-subroutine" In this example, the code 'walks' into a subroutine, which is not allowed, and causes an error +Bytecode: `0xb2b700` + + | Pc | Op | Cost | Stack | RStack | |-------|-------------|------|-----------|-----------| -| 0 | BEGINSUB | 1 | [] | [] | - +| 0 | BEGINSUB | 2 | [] | [] | ``` Error: at pc=0, op=BEGINSUB: invalid subroutine entry ``` + **Note 5**: The content of the error message, (`invalid subroutine entry`) is implementation-specific. ## Implementations -Three clients have implemented the previous version of proposal: +Three clients have implemented this (or an earlier version of) this proposal: - [geth](https://github.com/ethereum/go-ethereum/pull/20619) . - [besu](https://github.com/hyperledger/besu/pull/717), and - [openethereum](https://github.com/openethereum/openethereum/pull/11629). -The changes for the current version are trivial. ### Costs and Codes -We suggest that the cost of `BEGINSUB` be _base_, `JUMPSUB` be _mid_, and `RETURNSUB` be _verylow_. - Measurement will tell. We suggest the following opcodes: +We suggest that the cost of + +- `BEGINSUB` be _base_ (`2`) + - Although formally specified, the cost of `BEGINSUB` does not matter in practice, since `BEGINSUB` never executes without error. +- `JUMPSUB` be _high_ (`10`) + - This is the same as `JUMPI`, and `2` more than `JUMP`. +- `RETURNSUB` be _low_ (`5`). + +Benchmarking might be needed to tell if the costs are well-balanced. + +We suggest the following opcodes: ``` 0xb2 BEGINSUB @@ -184,8 +198,6 @@ We suggest that the cost of `BEGINSUB` be _base_, `JUMPSUB` be _mid_, and `RETUR 0xb7 RETURNSUB ``` -**Note 6**: Although specified at _base_, the cost of `BEGINSUB` does not matter in practice, since `BEGINSUB` never executes without error. - ## Security Considerations These changes do introduce new flow control instructions, so any software which does static/dynamic analysis of evm-code From e8accf22cdc5562d6982c560080c6cd6b7f94867 Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Fri, 29 May 2020 23:06:28 +0200 Subject: [PATCH 4/8] EIP2315: update opcodes (#2682) --- EIPS/eip-2315.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/EIPS/eip-2315.md b/EIPS/eip-2315.md index ab41c5e37ec097..390306a0847056 100644 --- a/EIPS/eip-2315.md +++ b/EIPS/eip-2315.md @@ -74,7 +74,7 @@ These changes do not affect the semantics of existing EVM code. This should jump into a subroutine, back out and stop. -Bytecode: `0x6004b300b2b7` +Bytecode: `0x60045e005c5d` (`PUSH1 0x04, JUMPSUB, STOP, BEGINSUB, RETURNSUB`) | Pc | Op | Cost | Stack | RStack | |-------|-------------|------|-----------|-----------| @@ -90,7 +90,7 @@ Consumed gas: `18` This should execute fine, going into one two depths of subroutines -Bytecode: `0x6800000000000000000cb300b26011b3b7b2b7` +Bytecode: `0x6800000000000000000c5e005c60115e5d5c5d` (`PUSH9 0x00000000000000000c, JUMPSUB, STOP, BEGINSUB, PUSH1 0x11, JUMPSUB, RETURNSUB, BEGINSUB, RETURNSUB`) | Pc | Op | Cost | Stack | RStack | |-------|-------------|------|-----------|-----------| @@ -109,7 +109,7 @@ Consumed gas: `36` This should fail, since the given location is outside of the code-range. The code is the same as previous example, except that the pushed location is `0x01000000000000000c` instead of `0x0c`. -Bytecode: `0x6801000000000000000cb300b26011b3b7b2b7` +Bytecode: `0x6801000000000000000c5e005c60115e5d5c5d` (`PUSH9 0x01000000000000000c, JUMPSUB, STOP, BEGINSUB, PUSH1 0x11, JUMPSUB, RETURNSUB, BEGINSUB, RETURNSUB`) | Pc | Op | Cost | Stack | RStack | |-------|-------------|------|-----------|-----------| @@ -124,7 +124,7 @@ Error: at pc=10, op=JUMPSUB: invalid jump destination This should fail at first opcode, due to shallow `return_stack` -Bytecode: `0xb75858` (`RETURNSUB`, `PC`, `PC`) +Bytecode: `0x5d5858` (`RETURNSUB, PC, PC`) | Pc | Op | Cost | Stack | RStack | |-------|-------------|------|-----------|-----------| @@ -138,7 +138,7 @@ Error: at pc=0, op=RETURNSUB: invalid retsub In this example. the JUMPSUB is on the last byte of code. When the subroutine returns, it should hit the 'virtual stop' _after_ the bytecode, and not exit with error -Bytecode: `0x600556b2b75b6003b3` +Bytecode: `0x6005565c5d5b60035e` (`PUSH1 0x05, JUMP, BEGINSUB, RETURNSUB, JUMPDEST, PUSH1 0x03, JUMPSUB`) | Pc | Op | Cost | Stack | RStack | |-------|-------------|------|-----------|-----------| @@ -156,7 +156,7 @@ Consumed gas: `30` In this example, the code 'walks' into a subroutine, which is not allowed, and causes an error -Bytecode: `0xb2b700` +Bytecode: `0x5c5d00` (`BEGINSUB, RETURNSUB, STOP`) | Pc | Op | Cost | Stack | RStack | @@ -193,9 +193,9 @@ Benchmarking might be needed to tell if the costs are well-balanced. We suggest the following opcodes: ``` -0xb2 BEGINSUB -0xb3 JUMPSUB -0xb7 RETURNSUB +0x5c BEGINSUB +0x5d RETURNSUB +0x5e JUMPSUB ``` ## Security Considerations From 5edff4ae6ff62c7e0bbfad624fc3d0ba7dc84392 Mon Sep 17 00:00:00 2001 From: Alexander Date: Mon, 1 Jun 2020 17:55:43 +0300 Subject: [PATCH 5/8] BLS12-381 curve operations (#2537) * draft * Update eip-x.md * add ABI * also mention encoding of boolean vars in pairing * add point decompression * fix decompression, add gas price * expand on square root extraction and checks * Cleanup title * Fix typo and remove optional header fields * set EIP number * hm, html verifier is not satisfied... * update on ABI, costs and subgroup checks * add more information about field-to-curve * add links to implementations * spellcheck * mapping costs are underetmined yet * add mapping operations cost * whoops, spellcheck! * updates: test vectors, prefixes * more explicit pairing output * gas consumption in case of error * fix multiplication -> multiexp * split mapping into two separate ones * spellcheck * update link to Go implementation * add addresses Co-authored-by: Kobi Gurkan --- EIPS/eip-2537.md | 324 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 324 insertions(+) create mode 100644 EIPS/eip-2537.md diff --git a/EIPS/eip-2537.md b/EIPS/eip-2537.md new file mode 100644 index 00000000000000..abd219255a4c8b --- /dev/null +++ b/EIPS/eip-2537.md @@ -0,0 +1,324 @@ +--- +eip: 2537 +title: Precompile for BLS12-381 curve operations +author: Alex Vlasov (@shamatar) +discussions-to: https://ethereum-magicians.org/t/eip2537-bls12-precompile-discussion-thread/4187 +status: Draft +type: Standards Track +category: Core +created: 2020-02-21 +--- + + + +## Simple Summary + + +This precompile adds operation on BLS12-381 curve as a precompile in a set necessary to *efficiently* perform operations such as BLS signature verification and perform SNARKs verifications. + +## Abstract + + +If `block.number >= X` we introduce *nine* separate precompiles to perform the following operations: + +- BLS12_G1ADD - to perform point addition on a curve defined over prime field +- BLS12_G1MUL - to perform point multiplication on a curve defined over prime field +- BLS12_G1MULTIEXP - to perform multiexponentiation on a curve defined over prime field +- BLS12_G2ADD - to perform point addition on a curve twist defined over quadratic extension of the base field +- BLS12_G2MUL - to perform point multiplication on a curve twist defined over quadratic extension of the base field +- BLS12_G2MULTIEXP - to perform multiexponentiation on a curve twist defined over quadratic extension of the base field +- BLS12_PAIRING - to perform a pairing operations between a set of *pairs* of (G1, G2) points +- BLS12_MAP_FP_TO_G1 - maps base field element into the G1 point +- BLS12_MAP_FP2_TO_G2 - maps extension field element into the G2 point + +Mapping functions are implemented according to [IEFT specification](https://github.com/cfrg/draft-irtf-cfrg-hash-to-curve/blob/master/draft-irtf-cfrg-hash-to-curve.md#deterministic-mappings-mappings) version `v7`(!) using an simplified SWU method. It does NOT perform mapping of the byte string into field element that can be implemented in many different ways and can be efficiently performed in EVM, but only does field arithmetic to map field element into curve point. Such functionality is required for signature schemes. + +Multiexponentiation operation is included to efficiently aggregate public keys or individual signer's signatures during BLS signature verification. + +### Proposed addresses table + +|Precompile |Address | +|---|---| +|BLS12_G1ADD | 0x0a | +|BLS12_G1MUL | 0x0b | +|BLS12_G1MULTIEXP | 0x0c | +|BLS12_G2ADD | 0x0d | +|BLS12_G2MUL | 0x0e | +|BLS12_G2MULTIEXP | 0x0f | +|BLS12_PAIRING | 0x10 | +|BLS12_MAP_FP_TO_G1 | 0x11 | +|BLS12_MAP_FP2_TO_G2 | 0x12 | + +## Motivation + + +Motivation of this precompile is to add a cryptographic primitive that allows to get 120+ bits of security for operations over pairing friendly curve compared to the existing BN254 precompile that only provides 80 bits of security. + +## Specification + + +Curve parameters: + +BLS12 curve is fully defined by the following set of parameters (coefficient `A=0` for all BLS12 curves): + +``` +Base field modulus = 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab +B coefficient = 0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004 +Main subgroup order = 0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001 +Extension tower +Fp2 construction: +Fp quadratic non-residue = 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaaa +Fp6/Fp12 construction: +Fp2 cubic non-residue c0 = 0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +Fp2 cubic non-residue c1 = 0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +Twist parameters: +Twist type: M +B coefficient for twist c0 = 0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004 +B coefficient for twist c1 = 0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004 +Generators: +G1: +X = 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb +Y = 0x08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 +G2: +X c0 = 0x024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8 +X c1 = 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e +Y c0 = 0x0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801 +Y c1 = 0x0606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be +Pairing parameters: +|x| (miller loop scalar) = 0xd201000000010000 +x is negative = true +``` + +One should note that base field modulus 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`. + +#### 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. + +Base field element (Fp) is encoded as `64` bytes by performing BigEndian encoding of the corresponding (unsigned) integer (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]`). 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 formal 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). + +If encodings do not follow this spec anywhere during parsing in the precompile 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. + +##### Point of infinity encoding: + +Also referred as "zero point". For BLS12 curves point with coordinates `(0, 0)` (formal zeroes in Fp or Fp2) is *not* on the curve, so encoding of such point `(0, 0)` is used as a convention to encode point of infinity. + +##### Encoding of scalars for multiplication operation: + +Scalar for multiplication operation is encoded as `32` bytes by performing BigEndian encoding of the corresponding (unsigned) integer. Corresponding integer is **not** required to be less than or equal than main subgroup size. + +#### ABI for operations + +##### ABI for G1 addition + +G1 addition call expects `256` bytes as an input that is interpreted as byte concatenation of two G1 points (`128` bytes each). Output is an encoding of addition operation result - single G1 point (`128` 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 + +##### 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). + +Error cases: +- Point being not on the curve must result in error +- Field elements encoding rules apply (obviously) +- 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). + +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 + +##### 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). + +Error cases: +- Either of points being not on the curve must result in error +- Field elements encoding rules apply (obviously) +- 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 + +##### 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). + +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 + +##### 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: +- `128` bytes of G1 point encoding +- `256` bytes of G2 point encoding + +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 multiplicative identity in a pairing target field and `0x00` otherwise. + +Error cases: +- Invalid encoding of any boolean variable must result in error +- 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 + +##### ABI for mapping Fp element to G1 point + +Field-to-curve call expects `64` bytes an an input that is interpreted as a an element of the base field. Output of this call is `128` bytes and is G1 point following respective encoding rules. + +Error cases: +- Input has invalid length +- Input is not a valid field element + +##### ABI for mapping Fp2 element to G2 point + +Field-to-curve call expects `128` bytes an 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. + +Error cases: +- Input has invalid length +- Input is not a valid field element + +#### Prevention of DDoS on error handling + +This precompile performs extensive computations and in case of any errors during execution it MUST consume all gas from the the gas schedule for the corresponding operation. + +#### Gas schedule + +Assuming a constant `30 MGas/second` following prices are suggested. + +##### G1 addition + +`600` gas + +##### G1 multiplication + +`12000` gas + +##### G2 addition + +`4500` gas + +##### G2 multiplication + +`55000` gas + +##### G1/G2 Multiexponentiation + +Multiexponentiations are expected to be performed by the Peppinger algorithm (we can also say that is **must** be performed by Peppinger algorithm to have a speedup that results in a discount over naive implementation by multiplying each pair separately and adding the results). For this case there was a table prepared for discount in case of `k <= 128` points in the multiexponentiation with a discount cup `max_discount` for `k > 128`. + +To avoid non-integer arithmetic call cost is calculated as `k * multiplication_cost * discount / multiplier` where `multiplier = 1000`, `k` is a number of (scalar, point) pairs for the call, `multiplication_cost` is a corresponding single multiplication call cost for G1/G2. + +Discounts table as a vector of pairs `[k, discount]`: + +``` +[[1, 1200], [2, 888], [3, 764], [4, 641], [5, 594], [6, 547], [7, 500], [8, 453], [9, 438], [10, 423], [11, 408], [12, 394], [13, 379], [14, 364], [15, 349], [16, 334], [17, 330], [18, 326], [19, 322], [20, 318], [21, 314], [22, 310], [23, 306], [24, 302], [25, 298], [26, 294], [27, 289], [28, 285], [29, 281], [30, 277], [31, 273], [32, 269], [33, 268], [34, 266], [35, 265], [36, 263], [37, 262], [38, 260], [39, 259], [40, 257], [41, 256], [42, 254], [43, 253], [44, 251], [45, 250], [46, 248], [47, 247], [48, 245], [49, 244], [50, 242], [51, 241], [52, 239], [53, 238], [54, 236], [55, 235], [56, 233], [57, 232], [58, 231], [59, 229], [60, 228], [61, 226], [62, 225], [63, 223], [64, 222], [65, 221], [66, 220], [67, 219], [68, 219], [69, 218], [70, 217], [71, 216], [72, 216], [73, 215], [74, 214], [75, 213], [76, 213], [77, 212], [78, 211], [79, 211], [80, 210], [81, 209], [82, 208], [83, 208], [84, 207], [85, 206], [86, 205], [87, 205], [88, 204], [89, 203], [90, 202], [91, 202], [92, 201], [93, 200], [94, 199], [95, 199], [96, 198], [97, 197], [98, 196], [99, 196], [100, 195], [101, 194], [102, 193], [103, 193], [104, 192], [105, 191], [106, 191], [107, 190], [108, 189], [109, 188], [110, 188], [111, 187], [112, 186], [113, 185], [114, 185], [115, 184], [116, 183], [117, 182], [118, 182], [119, 181], [120, 180], [121, 179], [122, 179], [123, 178], [124, 177], [125, 176], [126, 176], [127, 175], [128, 174]] +``` + +`max_discount = 174` + +##### Pairing operaiton + +Cost of the pairing operation is `23000*k + 115000` where `k` is a number of pairs. + +##### Fp-to-G1 mappign operation + +Fp -> G1 mapping is `5500` gas. + +##### Fp2-to-G2 mappign operation + +Fp2 -> G2 mapping is `110000` gas + +## Rationale + +Motivation section covers a total motivation to have operations over BLS12-381 curve available. We also extend a rationale for move specific fine points. + +#### Multiexponentiation as a separate call + +Explicit separate multiexponentiation operation that allows one to save execution time (so gas) by both the algorithm used (namely Peppinger algorithm) and (usually forgotten) by the fact that `CALL` operation in Ethereum is expensive (at the time of writing), so one would have to pay non-negigible overhead if e.g. for multiexponentiation of `100` points would have to call the multipication precompile `100` times and addition for `99` times (roughly `138600` would be saved). + +## Backwards Compatibility + +There are no backward compatibility questions. + +## Important notes + +### Subgroup checks + +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 `double-and-add` multiplication method that has a clear "worst case" (all bits are equal to one). For pairing operation it's expected that implementation uses faster subgroup check, e.g. by using 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 + +Set of parameters for SWU mapping method is provided by [IETF](https://github.com/cfrg/draft-irtf-cfrg-hash-to-curve/blob/master/draft-irtf-cfrg-hash-to-curve.md#suites-for-bls12-381-suites-bls12381). + +One should pay particular attention to the following fine points during implementation: +- SWU method [itself](https://github.com/cfrg/draft-irtf-cfrg-hash-to-curve/blob/master/draft-irtf-cfrg-hash-to-curve.md#simplified-swu-for-ab--0-simple-swu-ab0) +- [Cofactor cleanup](https://github.com/cfrg/draft-irtf-cfrg-hash-to-curve/blob/master/draft-irtf-cfrg-hash-to-curve.md#clearing-the-cofactor-cofactor-clearing) + +Once again, [hash to field](https://github.com/cfrg/draft-irtf-cfrg-hash-to-curve/blob/master/draft-irtf-cfrg-hash-to-curve.md#hashing-to-a-finite-field-hashtofield) is NOT a part of this EIP as it can be implemented in EVM and with different strategies. + +## Test Cases + + +Due to the large test parameters space we first provide properties that various operations must satisfy. We use additive notation for point operations, capital letters (`P`, `Q`) for points, small letters (`a`, `b`) for scalars. Generator for G1 is labeled as `G`, generator for G2 is labeled as `H`, otherwise we assume random point on a curve in a correct subgroup. `0` means either scalar zero or point of infinity. `1` means either scalar one or multiplicative identity. `group_order` is a main subgroup order. `e(P, Q)` means pairing operation where `P` is in G1, `Q` is in G2. + +Requeired properties for basic ops (add/multiply): + +- Commutativity: `P + Q = Q + P` +- Additive negation: `P + (-P) = 0` +- Doubling `P + P = 2*P` +- Subgroup check: `group_order * P = 0` +- Trivial multiplication check: `1 * P = P` +- Multiplication by zero: `0 * P = 0` +- Multiplication by the unnormalized scalar `(scalar + group_order) * P = scalar * P` + +Required properties for pairing operation: +- Degeneracy `e(P, 0*Q) = e(0*P, Q) = 1` +- Bilinearity `e(a*P, b*Q) = e(a*b*P, Q) = e(P, a*b*Q)` (internal test, not visible through ABI) + +Test vector for all operations are expanded in this `csv` files in [repo](https://github.com/matter-labs/eip1962/tree/master/src/test/test_vectors/eip2537). + +## Implementation + +There is a various choice of existing implementations of the curve operations. It may require extra work to add an ABI: +- BLS12-381 code bases for Eth 2.0 clients + - Chia's library in [C++](https://github.com/Chia-Network/bls-signatures) + - Milagro in [various languages](https://github.com/apache/incubator-milagro) +- EIP1962 code bases with fixed parameters + - [Rust](https://github.com/matter-labs/eip1962) + - [Go](https://github.com/kilic/eip2537) + - [C++](https://github.com/matter-labs/eip1962_cpp) +- Original implementation by zCash in [Rust](https://github.com/zcash/librustzcash/tree/master/pairing) +- [MCL library](https://github.com/herumi/mcl) and it's bindings in other languages + +## Security Considerations + +Strictly following the spec will eliminate security implications or consensus implications in a contrast to the previous BN254 precompile. + +Important topic is a "constant time" property for performed operations. We explicitly state that this precompile **IS NOT REQUIRED** to perform all the operations using constant time algorithms. + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). From ec3a75972947e594909cacc10cc822d7e050e1d1 Mon Sep 17 00:00:00 2001 From: Micah Zoltu Date: Tue, 2 Jun 2020 02:48:07 +0800 Subject: [PATCH 6/8] Automatically merged updates to draft EIP(s) 1559 (#2635) Hi, I'm a bot! This change was automatically merged because: - It only modifies existing Draft or Last Call EIP(s) - The PR was approved or written by at least one author of each modified EIP - The build is passing --- EIPS/eip-1559.md | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/EIPS/eip-1559.md b/EIPS/eip-1559.md index 62c9548604b4a3..96f9613245f978 100644 --- a/EIPS/eip-1559.md +++ b/EIPS/eip-1559.md @@ -45,14 +45,23 @@ The transition to this gas price system will occur in two phases, in the first p **Parameters** * `INITIAL_FORK_BLKNUM`: TBD -* `BASEFEE_MAX_CHANGE_DENOMINATOR`: 8 -* `TARGET_GAS_USED`: 10,000,000 -* `MAX_GAS_EIP1559`: 16,000,000 -* `EIP1559_DECAY_RANGE`: `MAX_GAS_EIP1559 / 20` == `800,000` -* `FINAL_FORK_BLKNUM`: `INITIAL_FORK_BLKNUM + EIP1559_DECAY_RANGE` -* `EIP1559_GAS_INCREMENT_AMOUNT`: `(MAX_GAS_EIP1559 / 2) / EIP1559_DECAY_RANGE` == `10` +* `MIGRATION_DURATION_IN_BLOCKS`: 800,000 +* `FINAL_FORK_BLKNUM`: `INITIAL_FORK_BLKNUM + MIGRATION_DURATION_IN_BLOCKS` +* `EIP1559_INITIAL_GAS_TARGET`: `BLOCK_GAS_TARGET / 2` +* `LEGACY_INITIAL_GAS_LIMIT`: `BLOCK_GAS_TARGET - EIP1559_GAS_TARGET` +* `EIP1559_GAS_TARGET`: + ``` + if CURRENT_BLKNUM >= FINAL_FORK_BLOKNUM then + BLOCK_GAS_TARGET + elif CURRNT_BLKNUM < INITIAL_FORK_BLKNUM then + 0 + else + EIP1559_INITIAL_GAS_TARGET + LEGACY_INITIAL_GAS_LIMIT * (CURRENT_BLKNUM - INITIAL_FORK_BLKNUM) / MIGRATION_DURATION_IN_BLOCKS + ``` +* `LEGACY_GAS_LIMIT`: `BLOCK_GAS_TARGET - EIP1559_GAS_TARGET` +* `EIP1559_GAS_LIMIT`: `EIP1559_GAS_TARGET * 2` +* `BASEFEE_MAX_CHANGE_DENOMINATOR`: `8` * `INITIAL_BASEFEE` : 1,000,000,000 wei (1 gwei) -* `PER_TX_GASLIMIT`: 8,000,000 **Proposal** @@ -60,13 +69,12 @@ For all blocks where `block.number >= INITIAL_FORK_BLKNUM`: For the gas limit: -* `MAX_GAS_EIP1559` acts as the hard in-protocol gas limit, instead of the gas limit calculated using the previously existing formulas -* The `GASLIMIT` field in the block header is the gas limit for the EIP1559 gas pool, and over the transition period this value increases until it reaches `MAX_GAS_EIP1559` at `FINAL_FORK_BLKNUM` -* The gas limit for the legacy gas pool is `MAX_GAS_EIP1559 - GASLIMIT`, as `GASLIMIT` increases towards `MAX_GAS_EIP1559` gas is moved from the legacy pool into the EIP1559 pool until all of the gas is in the EIP1559 pool -* At `block.number == INITIAL_FORK_BLKNUM`, let `GASLIMIT = (MAX_GAS_EIP1559 / 2)` so that the gas maximum is split evenly between the legacy and EIP1559 gas pools -* As `block.number` increases towards `FINAL_FORK_BLKNUM`, at every block we shift `EIP1559_GAS_INCREMENT_AMOUNT` from the legacy pool into the EIP1559 gas pool -* At `block.number >= FINAL_FORK_BLKNUM` the entire `MAX_GAS_EIP1559` is assigned to the EIP1559 gas pool and the legacy pool is empty -* We enforce a maximum gas usage on individual transactions: `PER_TX_GASLIMIT` +* The field in the block header previously referred to as `GASLIMIT` will now be referred to colloquially as `GAS_TARGET`. Its value will still be controlled by miners in the same way as previously. It represents the total gas available to the legacy gas pool as well as the target gas of the EIP1559 gas pool. +* `EIP1559_GAS_LIMIT` is the space available for EIP1559 transactions (EIP1559 gas pool) and it is a function of `BLOCK_GAS_TARGET` and blocks since `INITIAL_FORK_BLKNUM`. It becomes equal to `BLOCK_GAS_TARGET * 2` for blocks >= `FINAL_FORK_BLKNUM` +* The gas limit for the legacy gas pool is `BLOCK_GAS_TARGET - EIP1559_GAS_TARGET`. As `EIP1559_GAS_TARGET` increases towards `BLOCK_GAS_TARGET`, gas is moved from the legacy pool into the EIP1559 pool until all of the gas is in the EIP1559 pool +* At `block.number == INITIAL_FORK_BLKNUM`, let `EIP1559_GAS_LIMIT = (GASLIMIT / 2)` so that the gas maximum is split evenly between the legacy and EIP1559 gas pools +* As `block.number` increases towards `FINAL_FORK_BLKNUM`, at every block we shift `1/MIGRATION_DURATION_IN_BLOCKS` gas from the legacy pool into the EIP1559 gas pool (effectively doubling it as it moves, since the EIP1559 gas target is half of the limit) +* At `block.number >= FINAL_FORK_BLKNUM` the entire `BLOCK_GAS_TARGET` is assigned to the EIP1559 gas pool and the legacy pool is 0 For the gas price: From 4caaba240bc062bc4ef58d40094dc58b9e488cc5 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 3 Jun 2020 00:22:07 +0100 Subject: [PATCH 7/8] Fix spelling mistakes detected by newer codespell (#2683) * Add iam to codespell-whitelist (used as a variable name) * Allow french spelling in the whitelist * Allow ACN (australian company number) in the whitelist * Fix misspellings --- .codespell-whitelist | 3 +++ EIPS/eip-107.md | 2 +- EIPS/eip-1581.md | 2 +- EIPS/eip-1613.md | 2 +- EIPS/eip-1930.md | 2 +- EIPS/eip-2333.md | 2 +- EIPS/eip-758.md | 2 +- 7 files changed, 9 insertions(+), 6 deletions(-) diff --git a/.codespell-whitelist b/.codespell-whitelist index 21c9c7e4ce907a..ce96dc07405aa7 100644 --- a/.codespell-whitelist +++ b/.codespell-whitelist @@ -5,3 +5,6 @@ readded crate developper ist +iam +espace +acn diff --git a/EIPS/eip-107.md b/EIPS/eip-107.md index 67caa48d96d459..d6a79c2b53cf3e 100644 --- a/EIPS/eip-107.md +++ b/EIPS/eip-107.md @@ -95,7 +95,7 @@ Rationale The design for that proposal was chosen for its simplicity and security. A previous idea was to use an oauth-like protocol in order for the user to accept or deny a transaction request. It would have required deeper code change in the node and some geth contributors argues that such change did not fit into geth code base as it would have required dapp aware code. The current design, instead has a very simple implementation (self contained html file that can be shared across node's implementation) and its safeness is guarantess by browsers' cross domain policies. -The use of iframe/ window was required to have both security and user friendliness. The invisble iframe allows the dapp to execute read only calls without the need for user input, and the window ensures user approval before making a call. While we could have made it without the window mode by making the iframe confirmation use the native browser ```window.confirm``` dialog, this would have prevented the use of a more elegant confirmation popup that the current design allows. It also happens to be that the ```window.confirm``` is not safe in some browsers, as it gives focus to the accept option and can be triggered automatically (https://bugs.chromium.org/p/chromium/issues/detail?id=260653). +The use of iframe/ window was required to have both security and user friendliness. The invisible iframe allows the dapp to execute read only calls without the need for user input, and the window ensures user approval before making a call. While we could have made it without the window mode by making the iframe confirmation use the native browser ```window.confirm``` dialog, this would have prevented the use of a more elegant confirmation popup that the current design allows. It also happens to be that the ```window.confirm``` is not safe in some browsers, as it gives focus to the accept option and can be triggered automatically (https://bugs.chromium.org/p/chromium/issues/detail?id=260653). Implementations diff --git a/EIPS/eip-1581.md b/EIPS/eip-1581.md index e49d8e76f382dd..1c5808fc5d8200 100644 --- a/EIPS/eip-1581.md +++ b/EIPS/eip-1581.md @@ -10,7 +10,7 @@ created: 2018-11-13 --- ## Simple Summary -This EIP describes a derivation path structure for [BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) wallets to be used for non-wallet keypairs. +This EIP describes a derivation path structure for [BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) wallets to be used for non-wallet key pairs. ## Abstract BIP32 defines a way to generate hierarchical trees of keys which can be derived from a common master key. BIP32 and [BIP44](https://https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki) defines the usage of these keys as wallets. In this EIP we describe the usage of such keys outside the scope of the blockchain defining a logical tree for key usage which can coexist (and thus share the same master) with existing BIP44 compatible wallets. diff --git a/EIPS/eip-1613.md b/EIPS/eip-1613.md index a5a45fe576a63d..41360e7b437dbd 100644 --- a/EIPS/eip-1613.md +++ b/EIPS/eip-1613.md @@ -86,7 +86,7 @@ Glossary of terms used in the processes below: * `RelayHub` - the RelayHub singleton contract, used by everyone. * `Recipient` - a contract implementing `RelayRecipient`, accepting relayed transactions from the RelayHub contract and paying for the incoming transactions. -* `Sender` - an external address with a valid keypair but no ETH to pay for gas. +* `Sender` - an external address with a valid key pair but no ETH to pay for gas. * `Relay` - a node holding ETH in an external address, listed in RelayHub and relaying transactions from Senders to RelayHub for a fee. ![Sequence Diagram](https://bit.ly/2WZqM23) diff --git a/EIPS/eip-1930.md b/EIPS/eip-1930.md index 3e611128572a08..9c20100888fe61 100644 --- a/EIPS/eip-1930.md +++ b/EIPS/eip-1930.md @@ -88,7 +88,7 @@ This is an issue for contracts that require external call to only fails if they But this is also true for simple use case, like checking if a contract implement an interface via EIP-165. Indeed as specified by such EIP, the ```supporstInterface``` method is bounded to use 30,000 gas so that it is theorically possible to ensure that the throw is not a result of a lack of gas. Unfortunately due to how the different CALL opcodes behave contracts can't simply rely on the gas value specified. They have to ensure by other means that there is enough gas for the call. -Indeed, if the caller do not ensure that 30,000 gas or more is provided to the callee, the callee might throw because of a lack of gas (and not because it does not support the interface), and the parent call will be given up to 476 gas to continue. This would result in the caller interepreting wrongly that the callee is not implementing the interface in question. +Indeed, if the caller do not ensure that 30,000 gas or more is provided to the callee, the callee might throw because of a lack of gas (and not because it does not support the interface), and the parent call will be given up to 476 gas to continue. This would result in the caller interpreting wrongly that the callee is not implementing the interface in question. While such requirement can be enforced by checking the gas left according to EIP-150 and the precise gas required before the call (see solution presented in that [bug report](https://web.solidified.io/contract/5b4769b1e6c0d80014f3ea4e/bug/5c83d86ac2dd6600116381f9) or after the call (see the native meta transaction implementation [here](https://github.com/pixowl/thesandbox-contracts/blob/623f4d4ca10644dcee145bcbd9296579a1543d3d/src/Sand/erc20/ERC20MetaTxExtension.sol#L176), it would be much better if the EVM allowed us to strictly specify how much gas is to be given to the CALL so contract implementations do not need to follow [EIP-150](https://eips.ethereum.org/EIPS/eip-150) behavior and the current gas pricing so closely. diff --git a/EIPS/eip-2333.md b/EIPS/eip-2333.md index 261a0653a85989..d74fc3c6bcb6e3 100644 --- a/EIPS/eip-2333.md +++ b/EIPS/eip-2333.md @@ -68,7 +68,7 @@ Every key generated via the key derivation process derives a child key via a set ##### Outputs -* `lamport_SK`, an array of 255 32-octet stings +* `lamport_SK`, an array of 255 32-octet strings ##### Definitions diff --git a/EIPS/eip-758.md b/EIPS/eip-758.md index 5cc85bb6f2a86c..eb71ae5febc725 100644 --- a/EIPS/eip-758.md +++ b/EIPS/eip-758.md @@ -69,7 +69,7 @@ Suppose the caller then submits a transaction via `eth_sendTransaction` or `eth_ } ``` -The caller receives notifications about their transactions in two cases: first when a transaction is sealed, and again (with an extra `"removed": true` field) if a transaction is affected by a chain reorganization. Notifications are sent to the client for all transactions submitted from the client that are sealed _after_ subscribing. If `from`, `to`, or `hasReturnData` is specified, then only those matching the filter criteria will generate notificaitons. As with other subscriptions, the caller can send an `eth_unsubscribe` RPC request to stop receiving push notifications: +The caller receives notifications about their transactions in two cases: first when a transaction is sealed, and again (with an extra `"removed": true` field) if a transaction is affected by a chain reorganization. Notifications are sent to the client for all transactions submitted from the client that are sealed _after_ subscribing. If `from`, `to`, or `hasReturnData` is specified, then only those matching the filter criteria will generate notifications. As with other subscriptions, the caller can send an `eth_unsubscribe` RPC request to stop receiving push notifications: ```json {"jsonrpc": "2.0", "id": 2, "method": "eth_unsubscribe", "params": ["0x00000000000000000000000000000b0b"]} From db94b47f674c81a865f1fe4c120649e7cf86b2e4 Mon Sep 17 00:00:00 2001 From: Erik Marks <25517051+rekmarks@users.noreply.github.com> Date: Wed, 3 Jun 2020 00:57:33 -0700 Subject: [PATCH 8/8] Fix 2537 spelling (#2691) --- EIPS/eip-2537.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EIPS/eip-2537.md b/EIPS/eip-2537.md index abd219255a4c8b..05a4df449f00b8 100644 --- a/EIPS/eip-2537.md +++ b/EIPS/eip-2537.md @@ -240,7 +240,7 @@ Discounts table as a vector of pairs `[k, discount]`: `max_discount = 174` -##### Pairing operaiton +##### Pairing operation Cost of the pairing operation is `23000*k + 115000` where `k` is a number of pairs.