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-7503: Move to Draft #9080

Merged
merged 3 commits into from
Dec 19, 2024
Merged
Changes from all 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
138 changes: 120 additions & 18 deletions EIPS/eip-7503.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@
eip: 7503
title: Zero-Knowledge Wormholes
description: Enable minting of secretly burnt Ethers as a native privacy solution for Ethereum
author: Keyvan Kambakhsh (@keyvank), Hamid Bateni (@irnb), Amir Kahoori <[email protected]>, Nobitex Labs <[email protected]>
author: Keyvan Kambakhsh (@keyvank), Hamid Bateni (@irnb), Amir Kahoori <[email protected]>, Nobitex Labs <[email protected]>, 0xwormhole (@0xwormhole)
discussions-to: https://ethereum-magicians.org/t/eip-7503-zero-knowledge-wormholes-private-proof-of-burn-ppob/15456
status: Stagnant
status: Draft
type: Standards Track
category: Core
created: 2023-08-14
requires: 2718, 4844, 7708
---

## Abstract
Expand All @@ -25,6 +26,60 @@

## Specification

### Parameters

* `MAGIC_ADDRESS`: `0xfe` (one byte)
* `MAGIC_NULLIFIER`: `0x01` (one byte)
* `MAGIC_POW`: `0x02` (one byte)
* `MAGIC_CHANGE`: `0x0404040404040404040404040404040404040404040404040404040404040404`
* `POW_LOG_DIFFICULTY`: `24`
* `MAX_DEPOSIT`: `32 * 10**18` wei
* `WormholeTxType`: `TBD`
* `WORMHOLE_NULLIFIER_ADDRESS`: `TBD`
* `RECEIPT_PREFIX`: `TBD` (datatype `List[bool]`)

- - -

We define a new [EIP-2718](./eip-2718.md) transaction type, where `TransactionType` is `WormholeTxType` and the `TransactionPayload` format is as follows:

`[chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, to, data, access_list, root_beacon_block_number, proof]`

Verifying this type of transaction requires confirming that:

1. The proof is a zero-knowledge proof:
* Private inputs: `secret`, `main_index`, `main_branch`, `privacy_pool_index`, `privacy_pool_branch`, `deposit_value`, `deposit_sender`, `change_value_salt`, `change_value`
* Public inputs: `beacon_block_root`, `nullifier`, `privacy_pool_root`, `withdraw_value`, `change_value_hash`
* Function: verify all of the following conditions
* `verify_merkle_branch(root=beacon_block_root, index=RECEIPT_PREFIX + main_index, leaf=make_receipt_hash(deposit_sender, deposit_value, change_value_salt, secret), branch=main_branch)`
* `verify_merkle_branch(root=privacy_pool_root, index=privacy_pool_index, leaf=make_receipt_hash(deposit_sender, deposit_value, change_value_salt, secret), branch=privacy_pool_branch)`
* `nullifier=sha256(MAGIC_NULLIFIER + secret)`
* `sha256(MAGIC_POW + secret) % 2**POW_LOG_DIFFICULTY == 0`
* `change_value_salt = sha256(change_value_salt, change_value)`
* `change_value + withdraw_value = deposit_value` (all values are unsigned int, also need to confirm that there is no overflow)
* `deposit_value <= MAX_DEPOSIT`
2. `SLOAD(WORMHOLE_NULLIFIER_ADDRESS, proof.nullifier) = 0`
3. `get_beacon_block_root(root_beacon_block_number) == proof.beacon_block_root`

We define `make_receipt_hash` as follows:

```
def make_receipt_hash(deposit_sender: Address, value: uint256, change_value_salt: bytes32, secret: bytes32):
if deposit_sender != 0:
to_address = sha256(MAGIC_ADDRESS + secret)[12:]
topics = [MAGIC_EIP_7708, deposit_sender, to_address]
logdata = int_to_bytes32(value)
else:
topics = [MAGIC_CHANGE, hash(change_value_salt, value)]
logdata = bytes([])
return get_ssz_root_hash(Log(topics=topics, data=logdata))
```

The hash of the transaction (excluding proof) should be included in the randomness for generating the zero-knowledge proof. This ensures the proof serves as a signature.

If the transaction is confirmed, generate `proof.withdraw_value` ether at address `WORMHOLE_NULLIFIER_ADDRESS`. Then proceed with a normal call from this address using that value. Before the call, set `SSTORE(WORMHOLE_NULLIFIER_ADDRESS, proof.nullifier, 1)`, and emit a log event where `topics = [MAGIC_CHANGE, proof.change_value_hash]` and `logdata = bytes([])`.

## Rationale

In Elliptic-Curve based digital signatures, normally there is a secret scalar $s$, from which
a public-key is calculated (By multiplying the generator point with the scalar: $s \times G$). An
Ethereum EOA-address is the keccak hash of a public-key.
Expand All @@ -41,7 +96,7 @@
in case $r$ is a random value. So the funds sent to a random Ethereum address $r$ is unspendable, but
how can other people be sure that $r$ is indeed random and not the result of calculating $s \times G$?

A great source of randomness is a hash function. If the address is equal with the hash of a secret preimage
A great source of randomness is a hash function. If the address is equal with the hash of a secret preimage
$s$, we can conclude that the address is unspendable, since there isn't a polynomially bounded algorithm
to find $x$ where $keccak(x)=h(s)$. This is only true if the second hash function is a different hash
function, and it assumes it is impossible to find $x_1$ and $x_2$ such that $h_1(x_1)=h_2(x_2)$ in case
Expand All @@ -54,10 +109,7 @@
By revealing this to the Ethereum blockchain and providing something like a nullifier
(E.g. $h(s | 123)$ so that double minting of same burnt tokens are not possible), we can add a new
***minting*** functionality for ETH so that people can migrate their secretly burnt tokens to a
completely new address, without any trace on the blockchain. The target addresses can also be burn
addresses, keeping the re-minted funds in the anonymity pool.

## Rationale
completely new address, without any trace on the blockchain.

Cryptocurrency mixers like TornadoCash can successfully obfuscate Ethereum transactions, but it's
easy for the governments to ban usage of them. Anybody who has interactions with a mixer contract,
Expand All @@ -66,13 +118,22 @@
we only use plain EOA-to-EOA transfers. In order to have a "teleportation" mechanism we divide
the set of all Secp256k1 points $E(K)$ into two subsets/address-spaces:

- The spendable address-space: $\\{p \in \\{0,1\\}^{160} | \exists s : keccak(s \times G)=p \lor \exists c : keccak(c_{params})=p \\}$

Check failure on line 121 in EIPS/eip-7503.md

View workflow job for this annotation

GitHub Actions / Markdown Linter

Unordered list style [Expected: asterisk; Actual: dash]

EIPS/eip-7503.md:121:1 MD004/ul-style Unordered list style [Expected: asterisk; Actual: dash]
- The unspendable address-space: $\\{p \in \\{0,1\\}^{160} | \nexists s : keccak(s \times G)=p \land \nexists c : keccak(c_{params})=p \\}$

Check failure on line 122 in EIPS/eip-7503.md

View workflow job for this annotation

GitHub Actions / Markdown Linter

Unordered list style [Expected: asterisk; Actual: dash]

EIPS/eip-7503.md:122:1 MD004/ul-style Unordered list style [Expected: asterisk; Actual: dash]

The spendable/unspendable addresses are not distinguishable, so we can exploit this fact and define
a spendability rule for the money sent to addresses that can't be spent using regular elliptic-curve
signatures. Using the help of Zero-Knowledge proofs, we can hide the transaction trace and design
a new privacy protocol, which is what this EIP is proposing.
signatures.

Deposits are made by sending ether to an address `sha256(MAGIC_ADDRESS + secret)[12:]`, where you know the `secret`. This ensures that no one knows about the deposit unless you reveal it: a deposit onchain is not distinguishable from sending ether to a friend. Withdrawals use a zero-knowledge proof to prove knowledge of a previous deposit's `secret`.

A deposit can come from two places: a standard deposit by sending ether, or a change deposit. A change deposit is automatically generated when withdrawing funds from another deposit (standard or change). The entire deposited amount does not have to be withdrawn; for example, if 20 ether was deposited and only 12 is withdrawn, the system will make a new change deposit of 8 ether. The value of this change deposit is hashed, so someone looking at the chain cannot calculate `change deposit value + withdrawal value = old deposit value` and use the value to expose the original deposit.

This EIP requires that [EIP-7708](./eip-7708.md) be in place along with an EIP to change receipts to SSZ format. This simplifies the proof as it only needs to verify a regular SHA256 Merkle branch verifying a log, there is no need to do verkle or RLP or other complex logic inside the proof. The log can be of two types: an EIP-7708 ETH transfer log, or a log generated by this EIP itself through the change mechanism.

The EIP also includes a privacy pool [^1] mechanism where you must provide a privacy pool root, which corresponds to a list of deposits, so you prove that your deposit is one of the deposits in that list. Since this second Merkle branch mechanism is integrated into the proof, the marginal cost for a user to use it is zero, ensuring maximum adoption and maximizing the chance that privacy will be used responsibly. The privacy pools paper explains in much more detail the value of this privacy pools mechanism, and the benefits of an ecosystem where almost all legitimate users use it.

The built-in PoW and 32 ETH limit prevent hash collision attacks: if an attacker can find collision `(x1, x2)` such that `create2_address(..., x1) = sha256(MAGIC_ADDRESS + x2)`, the attacker could extract their ether twice (but only twice). Such an attack requires approximately `2**80` hashes. Adding 24 bits of PoW increases the difficulty to `2**92`. This many hashes can be computed but is very difficult; currently, mining a Bitcoin block takes around `2**79` hashes, so those with the capabilities to attack this mechanism have a much more lucrative opportunity in Bitcoin mining.

### Scalability Implications

Expand All @@ -89,17 +150,15 @@

## Reference Implementation

A reference implementation is not ready yet, but here is a design:
To be determined (TBD).

- We will need to track all of the ETH transfers that are happening on the blockchain (Including those
initiated by smart-contracts), and add them to a ZK-friendly Sparse-Merkle-Tree. The amount sent should
also be included in the leaves.
- We will need a new transaction type responsible for minting Ethers. The initiator should provide a proof
(Along with a nullifier) that proves he owns one of the leaves in the merkle-tree that has specific amount
of ETHers
### ZK-SNARK Implementation

Alternatively, we can use the already maintained state-trie and provide merkle-patricia-trie proofs, showing
that there exists some amount of ETH in an unspendable account, and mint them.
Also TBD, but the implementation must meet the following conditions:

* Use a transparent setup; ideally reuse the [EIP-4844](./eip-4844.md) setup. Do not use Groth16 or other application-specific setups.
* The circuit should be directly verifiable without blindly trusting compilers like Circom. SHA256 is not too complicated and can be implemented using PLOOKUP with an 8-bit lookup table for arithmetic operations, which should suffice. There is no need to over-focus on prover efficiency.
* Elliptic curves must still be used; Stark is too large.

## Security Considerations

Expand All @@ -108,3 +167,46 @@
## Copyright

Copyright and related rights waived via [CC0](../LICENSE.md).

[^1]:
```csl-json
{

Check failure on line 173 in EIPS/eip-7503.md

View workflow job for this annotation

GitHub Actions / Markdown Linter

Code block style [Expected: fenced; Actual: indented]

EIPS/eip-7503.md:173 MD046/code-block-style Code block style [Expected: fenced; Actual: indented]
"type": "article",
"id": 1,
"author": [
{
"family": "Buterin",
"given": "Vitalik"
},
{
"family": "Illum",
"given": "Jacob"
},
{
"family": "Nadler",
"given": "Matthias"
},
{
"family": "Schär",
"given": "Fabian"
},
{
"family": "Soleimani",
"given": "Ameen"
}
],
"DOI": "10.2139/ssrn.4563364",
"title": "Blockchain Privacy and Regulatory Compliance: Towards a Practical Equilibrium",
"original-date": {
"date-parts": [
[2023, 9, 6]
]
},
"URL": "https://ssrn.com/abstract=4563364",
"custom": {
"additional-urls": [
"http://dx.doi.org/10.2139/ssrn.4563364"
]
}
}
```
Loading