Skip to content

Commit

Permalink
Merge branch 'master' into pairings
Browse files Browse the repository at this point in the history
  • Loading branch information
pirapira committed Dec 4, 2017
2 parents a849495 + 3b4501d commit 099e668
Show file tree
Hide file tree
Showing 8 changed files with 80 additions and 149 deletions.
5 changes: 5 additions & 0 deletions EIPS/eip-1.md
Original file line number Diff line number Diff line change
Expand Up @@ -254,3 +254,8 @@ February 1, 2016: EIP 1 has added editors, made draft improvements to process, a
[README.md]: README.md "wikilink"
[Bitcoin's BIP-0001]: https://github.com/bitcoin/bips
[Python's PEP-0001]: https://www.python.org/dev/peps/

Copyright
---------

Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
2 changes: 1 addition & 1 deletion EIPS/eip-100.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Title: Change difficulty adjustment to target mean block time including uncles
Author: Vitalik Buterin
Type: Standard Track
Category: Core
Status: Accepted
Status: Final
Created: 2016-04-28
```

Expand Down
1 change: 1 addition & 0 deletions EIPS/eip-140.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Reserved for https://github.com/ethereum/EIPs/pull/206
4 changes: 2 additions & 2 deletions EIPS/eip-196.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
## Preamble

EIP: 213
EIP: 196
Title: Precompiled contracts for addition and scalar multiplication
on the elliptic curve alt_bn128
Author: Christian Reitwiessner<[email protected]>
Expand All @@ -15,7 +15,7 @@ Precompiled contracts for elliptic curve operations are required in order to per

## Abstract

This EIP suggests to add precompiled contracts for addition and scalar multiplication on a specific pairing-friendly elliptic curve. This can in turn be combined with [EIP-212](./eip-212.md) to verify zkSNARKs in Ethereum smart contracts. The general benefit of zkSNARKs for Ethereum is that it will increase the privacy for users (because of the Zero-Knowledge property) and might also be a scalability solution (because of the succinctness and efficient verifiability property).
This EIP suggests to add precompiled contracts for addition and scalar multiplication on a specific pairing-friendly elliptic curve. This can in turn be combined with [EIP-197](./eip-197.md) to verify zkSNARKs in Ethereum smart contracts. The general benefit of zkSNARKs for Ethereum is that it will increase the privacy for users (because of the Zero-Knowledge property) and might also be a scalability solution (because of the succinctness and efficient verifiability property).

## Motivation

Expand Down
143 changes: 1 addition & 142 deletions EIPS/eip-197.md
Original file line number Diff line number Diff line change
@@ -1,142 +1 @@
## Preamble

EIP: 197
Title: Precompiled contracts for optimal ate pairing check
on the elliptic curve alt_bn128
Author: Vitalik Buterin <[email protected]>, Christian Reitwiessner <[email protected]>
Type: Standard Track
Category: Core
Status: Draft
Created: 2017-02-06

## Simple Summary

Precompiled contracts for elliptic curve pairing operations are required in order to perform zkSNARK verification within the block gas limit.

## Abstract

This EIP suggests to add precompiled contracts for a pairing function on a specific pairing-friendly elliptic curve. This can in turn be combined with [EIP-196](./eip-196.md) to verify zkSNARKs in Ethereum smart contracts. The general benefit of zkSNARKs for Ethereum is that it will increase the privacy for users (because of the Zero-Knowledge property) and might also be a scalability solution (because of the succinctness and efficient verifiability property).

## Motivation

Current smart contract executions on Ethereum are fully transparent, which makes them unsuitable for several use-cases that involve private information like the location, identity or history of past transactions. The technology of zkSNARKs could be a solution to this problem. While the Ethereum Virtual Machine can make use of zkSNARKs in theory, they are currently too expensive
to fit the block gas limit. Because of that, this EIP proposes to specify certain parameters for some elementary primitives that enable zkSNARKs so that they can be implemented more efficiently and the gas cost be reduced.

Note that fixing these parameters will in no way limit the use-cases for zkSNARKs, it will even allow for incorporating some advances in zkSNARK research without the need for a further hard fork.

Pairing functions can be used to perform a limited form of multiplicatively homomorphic operations, which are necessary for current zkSNARKs. This precompile can be used to run such computations within the block gas limit. This precompiled contract only specifies a certain check, and not an evaluation of a pairing function. The reason is that the codomain of a pairing function is a rather complex field which could provide encoding problems and all known uses of pairing function in zkSNARKs only require the specified check.

## Specification

For blocks where `block.number >= BYZANTIUM_FORK_BLKNUM`, add a precompiled contracts for a bilinear function on groups on the elliptic curve "alt_bn128". We will define the precompiled contract in terms of a discrete logarithm. The discrete logarithm is of course assumed to be hard to compute, but we will give an equivalent specification that makes use of elliptic curve pairing functions which can be efficiently computed below.

Address: 0x8

For a cyclic group `G` (written additively) of prime order `q` let `log_P: G -> F_q` be the discrete logarithm on this group with respect to a generator `P`, i.e. `log_P(x)` is the smallest non-negative integer `n` such that `n * P = x`.

The precompiled contract is defined as follows, where the two groups `G_1` and `G_2` and their generators `P_1` and `P_2` are defined below. Both generators have the same prime order `q` and the actual choice of the generators does not matter, as long as they have order `q`.

```
Input: (a1, b1, a2, b2, ..., ak, bk) from (G_1 x G_2)^k
Output: If the length of the input is incorrect or any of the inputs are not elements of
the respective group or are not encoded correctly, the call fails.
Otherwise, return one if
log_P1(a1) * log_P2(b1) + ... + log_P1(ak) * log_P2(bk) = 0
(in F_q) and zero else.
```

Note that `k` is determined from the length of the input. Following the section on the encoding below,
`k` is the length of the input divided by `192`. If the input length is not a multiple of `192`,
the call fails. Empty input is valid and results in returning one.

In order to check that an input is an element of `G_1`, verifying the encoding of the coordinates and checking that they satisfy the curve equation (or is the encoding of infinity) is sufficient. For `G_2`, in addition to that, the order of the element has to be checked to be equal to the group order `q = 21888242871839275222246405745257275088548364400416034343698204186575808495617`.

### Definition of the groups

The groups `G_1` and `G_2` are cyclic groups of prime order `q = 21888242871839275222246405745257275088548364400416034343698204186575808495617` on the elliptic curve `alt_bn128` defined by the curve equation
`Y^2 = X^3 + 3`.

The group `G_1` is a cyclic group on the above curve over the field `F_p` with `p = 21888242871839275222246405745257275088696311157297823662689037894645226208583` with generator `P1 = (1, 2)`.

The group `G_2` is a cyclic group on the same elliptic curve over a different field `F_p^2 = F_p[i] / (i^2 + 1)` (p is the same as above) with generator
```
P2 = (
11559732032986387107991004021392285783925812861821192530917403151452391805634 * i +
10857046999023057135944570762232829481370756359578518086990519993285655852781,
4082367875863433681332203403145435568316851327593401208105741076214120093531 * i +
8495653923123431417604973247489272438418190587263600148770280649306958101930
)
```

Note that `G_2` is the only group of order `q` of that elliptic curve over the field `F_p^2`.


### Encoding

Elements of `F_p` are encoded as 32 byte big-endian numbers. An encoding value of `p` or larger is invalid.

Elements `a * i + b` of `F_p^2` are encoded as two elements of `F_p`, `(a, b)`.

Elliptic curve points are encoded as a Jacobian pair `(X, Y)` where the point at infinity is encoded as `(0, 0)`.

Note that the number `k` is derived from the input length.

The length of the returned data is always exactly 32 bytes and encoded as a 32 byte big-endian number.

### Gas costs

The gas costs of the precompiled contract are `80 000 * k + 100 000`, where `k` is the number of
points or, equivalently, the length of the input divided by 192.

## Rationale

The specific curve `alt_bn128` was chosen because it is particularly well-suited for zkSNARKs, or, more specifically their verification building block of pairing functions. Furthermore, by choosing this curve, we can use synergy effects with ZCash and re-use some of their components and artifacts.

The feature of adding curve and field parameters to the inputs was considered but ultimately rejected since it complicates the specification: The gas costs are much harder to determine and it would be possible to call the contracts on something which is not an actual elliptic curve or does not admit an efficient pairing implementation.

A non-compact point encoding was chosen since it still allows to perform some operations in the smart contract itself (inclusion of the full y coordinate) and two encoded points can be compared for equality (no third projective coordinate).

The encoding of field elements in `F_p^2` was chosen in this order to be in line with the big endian encoding of the elements themselves.

## Backwards Compatibility

As with the introduction of any precompiled contract, contracts that already use the given addresses will change their semantics. Because of that, the addresses are taken from the "reserved range" below 256.

## Test Cases

To be written.

## Implementation

The precompiled contract can be implemented using elliptic curve pairing functions, more specifically, an optimal ate pairing on the alt_bn128 curve, which can be implemented efficiently. In order to see that, first note that a pairing function `e: G_1 x G_2 -> G_T` fulfills the following properties (`G_1` and `G_2` are written additively, `G_T` is written multiplicatively):

(1) `e(m * P1, n * P2) = e(P1, P2)^(m * n)`
(2) `e` is non-degenerate

Now observe that
```
log_P1(a1) * log_P2(b1) + ... + log_P1(ak) * log_P2(bk) = 0 (in F_q)
```
if and only if
```
e(P1, P2)^(log_P1(a1) * log_P2(b1) + ... + log_P1(ak) * log_P2(bk)) = 1 (in G_T)
```

Furthermore, the left hand side of this equation is equal to
```
e(log_P1(a1) * P1, log_P2(b1) * P2) * ... * e(log_P1(ak) * P1, log_P2(bk) * P2)
= e(a1, b1) * ... * e(ak, bk)
```

And thus, the precompiled contract can be implemented by verifying that
`e(a1, b1) * ... * e(ak, bk) = 1`

Implementations are available here:

- [libff](https://github.com/scipr-lab/libff/blob/master/libff/algebra/curves/alt_bn128/alt_bn128_g1.hpp) (C++)
- [bn](https://github.com/zcash/bn/blob/master/src/groups/mod.rs) (Rust)
- [Python](https://github.com/ethereum/py_pairing/blob/master/py_ecc/bn128/bn128_pairing.py)

## Copyright

Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
Reserved for https://github.com/ethereum/EIPs/pull/212
66 changes: 66 additions & 0 deletions EIPS/eip-211.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
## Preamble

EIP: 211
Title: New opcodes: RETURNDATASIZE and RETURNDATACOPY
Author: Christian Reitwiessner <[email protected]>
Type: Standard Track
Category Core
Status: Final
Created: 2017-02-13
Requires:
Replaces: 5/8


## Simple Summary

A mechanism to allow returning arbitrary-length data inside the EVM has been requested for quite a while now. Existing proposals always had very intricate problems associated with charging gas. This proposal solves the same problem while at the same time, it has a very simple gas charging mechanism and requires minimal changes to the call opcodes. Its workings are very similar to the way calldata is handled already; after a call, return data is kept inside a virtual buffer from which the caller can copy it (or parts thereof) into memory. At the next call, the buffer is overwritten. This mechanism is 100% backwards compatible.

## Abstract

Please see summary.

## Motivation

In some situations, it is vital for a function to be able to return data whose length cannot be anticipated before the call. In principle, this can be solved without alterations to the EVM, for example by splitting the call into two calls where the first is used to compute only the size. All of these mechanisms, though, are very expensive in at least some situations. A very useful example of such a worst-case situation is a generic forwarding contract; a contract that takes call data, potentially makes some checks and then forwards it as is to another contract. The return data should of course be transferred in a similar way to the original caller. Since the contract is generic and does not know about the contract it calls, there is no way to determine the size of the output without adapting the called contract accordingly or trying a logarithmic number of calls.

Compiler implementors are advised to reserve a zero-length area for return data if the size of the return data is unknown before the call and then use `RETURNDATACOPY` in conjunction with `RETURNDATASIZE` to actually retrieve the data.

Note that this proposal also makes the EIP that proposes to allow to return data in case of an intentional state reversion ([EIP-140](./eip-140.md)) much more useful. Since the size of the failure data might be larger than the regular return data (or even unknown), it is possible to retrieve the failure data after the CALL opcode has signalled a failure, even if the regular output area is not large enough to hold the data.

## Specification

If `block.number >= BYZANTIUM_FORK_BLKNUM`, add two new opcodes and amend the semantics of any opcode that creates a new call frame (like `CALL`, `CREATE`, `DELEGATECALL`, ...) called call-like opcodes in the following. It is assumed that the EVM (to be more specific: an EVM call frame) has a new internal buffer of variable size, called the return data buffer. This buffer is created empty for each new call frame. Upon executing any call-like opcode, the buffer is cleared (its size is set to zero). After executing a call-like opcode, the complete return data (or failure data, see [EIP-140](./eip-140.md)) of the call is stored in the return data buffer (of the caller), and its size changed accordingly. As an exception, `CREATE` and `CREATE2` are considered to return the empty buffer in the success case and the failure data in the failure case. If the call-like opcode is executed but does not really instantiate a call frame (for example due to insufficient funds for a value transfer or if the called contract does not exist), the return data buffer is empty.

As an optimization, it is possible to share the return data buffer across call frames because at most one will be non-empty at any time.

`RETURNDATASIZE`: `0x3d`

Pushes the size of the return data buffer onto the stack.
Gas costs: 2 (same as `CALLDATASIZE`)

`RETURNDATACOPY`: `0x3e`

This opcode has similar semantics to `CALLDATACOPY`, but instead of copying data from the call data, it copies data from the return data buffer. Furthermore, accessing the return data buffer beyond its size results in a failure; i.e. if `start + length` overflows or results in a value larger than `RETURNDATASIZE`, the current call stops in an out-of-gas condition. In particular, reading 0 bytes from the end of the buffer will read 0 bytes; reading 0 bytes from one-byte out of the buffer causes an exception.

Gas costs: `3 + 3 * ceil(amount / 32)` (same as `CALLDATACOPY`)

## Rationale

Other solutions that would allow returning dynamic data were considered, but they all had to deduct the gas from the call opcode and thus were both complicated to implement and specify ([5/8](https://github.com/ethereum/EIPs/issues/8)). Since this proposal is very similar to the way calldata is handled, it fits nicely into the concept. Furthermore, the eWASM architecture already handles return data in exactly the same way.

Note that the EVM implementation needs to keep the return data until the next call or the return from the current call. Since this resource was already paid for as part of the memory of the callee, it should not be a problem. Implementations may either choose to keep the full memory of the callee alive until the next call or copy only the return data to a special memory area.

Keeping the memory of the callee until the next call-like opcode does not increase the peak memory usage in the following sense; any memory allocation in the caller's frame that happens after the return from the call can be moved before the call without a change in gas costs, but will add this allocation to the peak allocation.

The number values of the opcodes were allocated in the same nibble block that also contains `CALLDATASIZE` and `CALLDATACOPY`.

## Backwards Compatibility

This proposal introduces two new opcodes and stays fully backwards compatible apart from that.

## Test Cases

## Implementation

## Copyright
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
2 changes: 1 addition & 1 deletion EIPS/eip-55.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def checksum_encode(addr): # Takes a 20-byte binary address as input
return '0x'+o

def test(addrstr):
assert(addrstr == checksum_encode2(bytes.fromhex(addrstr[2:])))
assert(addrstr == checksum_encode(bytes.fromhex(addrstr[2:])))

test('0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed')
test('0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359')
Expand Down
6 changes: 3 additions & 3 deletions EIPS/eip-609.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,15 @@ This specifies the changes included in the hard fork named Byzantium.
- Block >= 4,370,000 on Mainnet
- Block >= 1,700,000 on Ropsten testnet
- Included EIPs:
- EIP 100 (Change difficulty adjustment to target mean block time including uncles)
- [EIP 100](./eip-100.md) (Change difficulty adjustment to target mean block time including uncles)
- EIP 140 (REVERT instruction in the Ethereum Virtual Machine)
- EIP 196 (Precompiled contracts for addition and scalar multiplication on the elliptic curve alt_bn128)
- EIP 197 (Precompiled contracts for optimal ate pairing check on the elliptic curve alt_bn128)
- EIP 198 (Precompiled contract for bigint modular exponentiation)
- EIP 211 (New opcodes: RETURNDATASIZE and RETURNDATACOPY)
- EIP 214 (New opcode STATICCALL)
- EIP 649 (Difficulty Bomb Delay and Block Reward Reduction)
- EIP 658 (Embedding transaction return data in receipts)
- [EIP 649](./eip-649.md) (Difficulty Bomb Delay and Block Reward Reduction)
- [EIP 658](./eip-658.md) (Embedding transaction status code in receipts)

## References

Expand Down

0 comments on commit 099e668

Please sign in to comment.