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

Add EIP: Deactivate/Reactivate a Delegated EOA's Key #9193

Merged
merged 22 commits into from
Jan 5, 2025
Merged
Changes from 1 commit
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
Prev Previous commit
Next Next commit
shorten title and description
  • Loading branch information
colinlyguo committed Dec 27, 2024
commit 9c7667a2af7dc506b0af6732f9a21fe83600d706
6 changes: 3 additions & 3 deletions EIPS/eip-7851.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
eip: 7851
title: Private key deactivation and reactivation of EOAs with delegated code
description: Introduce a new precompiled contract that enables Externally Owned Accounts (EOAs) with delegated code to deactivate and reactivate their private keys.
title: EOA private key deactivation/reactivation
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
title: EOA private key deactivation/reactivation
title: Delegated EOA's private key deactivation/reactivation

may be doesn't fit the title length constraint...

Copy link
Contributor Author

@colinlyguo colinlyguo Jan 5, 2025

Choose a reason for hiding this comment

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

yes. While the added delegated seems necessary, what about Deactivate/Reactivate a Delegated EOA's Key?

Copy link
Contributor

Choose a reason for hiding this comment

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

yes sounds good

Choose a reason for hiding this comment

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

EIPS/eip-7851.md

description: Introduce a precompiled contract for EOAs with delegated code to deactivate/reactivate private keys.
author: Liyi Guo (@colinlyguo)
discussions-to: https://ethereum-magicians.org/t/eip-7851-private-key-deactivation-and-reactivation-of-eoas-with-delegated-code/22344
status: Draft
Expand All @@ -13,7 +13,7 @@

## Abstract

This EIP introduces a precompiled contract that enables EOAs with delegated control to smart contracts via [EIP-7702](./eip-7702) to deactivate/reactivate their private keys. This design does not require additional storage fields or account state changes. By leveraging delegated code, reactivation can be performed securely through mechanisms such as social recovery.
This EIP introduces a precompiled contract that enables Externally Owned Accounts (EOAs) with delegated control to smart contracts via [EIP-7702](./eip-7702) to deactivate/reactivate their private keys. This design does not require additional storage fields or account state changes. By leveraging delegated code, reactivation can be performed securely through mechanisms such as social recovery.

## Motivation

Expand Down Expand Up @@ -42,39 +42,39 @@
### Precompiled contract

A new precompiled contract is introduced at address `PRECOMPILE_ADDRESS`. For each call, it consumes `PRECOMPILE_GAS_COST` gas, and the precompiled contract executes the following steps:
- The precompiled contract checks that the caller is an EOA with delegated code (i.e., its account code begins with the prefix `0xef0100`, as defined in [EIP-7702](./eip-7702)). If the code does not conform to the required prefix, the contract MUST terminate without making any state changes.

Check failure on line 45 in EIPS/eip-7851.md

View workflow job for this annotation

GitHub Actions / Markdown Linter

Lists should be surrounded by blank lines [Context: "- The precompiled contract che..."]

EIPS/eip-7851.md:45 MD032/blanks-around-lists Lists should be surrounded by blank lines [Context: "- The precompiled contract che..."]

Check failure on line 45 in EIPS/eip-7851.md

View workflow job for this annotation

GitHub Actions / Markdown Linter

Lists should be surrounded by blank lines [Context: "- The precompiled contract che..."]

EIPS/eip-7851.md:45 MD032/blanks-around-lists Lists should be surrounded by blank lines [Context: "- The precompiled contract che..."]
Copy link
Member

Choose a reason for hiding this comment

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

"Terminate" here means just "stop" the call to this precompile without making any state changes? (One could also "revert", thus the item put on stack when using the CALL* opcodes to this precompile would put 0 on stack if these conditions are not met (so no state changes are done?))

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for the clarification, the error case of precompile is updated as: "Returns a precompile contract error and consumes all provided gas" (refer to 0f2aaba).

The handling logic is consistent with other precompiles mentioned in https://www.evm.codes/precompiled. Also, consuming all gas for invalid calls (reducing DoS attack vectors) looks reasonable.

For the error return, I searched client implementation in geth and found it handled outside by CALL, STATICCALL, CALLCODE, DELEGATECALL. When precompiles return an error, it will be returned to CALL, and CALL will set return value as 0. But formal documents would help clarify this for sure.

- The precompile determines the current state of the delegated code based on its byte length:
- If the delegated code is 24 bytes (`0xef0100 || address || 0x00`), it removes the last byte (`0x00`), transitioning to the active state (`0xef0100 || address`).
- If the delegated code is 23 bytes (`0xef0100 || address`), it appends `0x00`, transitioning to the deactivated state (`0xef0100 || address || 0x00`).
- The updated delegated code is saved as the new account code for the EOA.
Copy link
Member

Choose a reason for hiding this comment

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

I think a rule should be added here. In case that we are updating the delegated code, but we are running in "static" mode (so a call chain after using STATICCALL) this should abort (revert, no state-changes).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yes. you're right! I added the STATICCALL error case in this commit: 0f2aaba



### Transaction validation

Check failure on line 52 in EIPS/eip-7851.md

View workflow job for this annotation

GitHub Actions / Markdown Linter

Headings should be surrounded by blank lines [Expected: 1; Actual: 0; Below] [Context: "### Transaction validation"]

EIPS/eip-7851.md:52 MD022/blanks-around-headings/blanks-around-headers Headings should be surrounded by blank lines [Expected: 1; Actual: 0; Below] [Context: "### Transaction validation"]

Check failure on line 52 in EIPS/eip-7851.md

View workflow job for this annotation

GitHub Actions / Markdown Linter

Headings should be surrounded by blank lines [Expected: 1; Actual: 0; Below] [Context: "### Transaction validation"]

EIPS/eip-7851.md:52 MD022/blanks-around-headings/blanks-around-headers Headings should be surrounded by blank lines [Expected: 1; Actual: 0; Below] [Context: "### Transaction validation"]
colinlyguo marked this conversation as resolved.
Show resolved Hide resolved
If the account is verified as an EOA with a delegated code (begins with the prefix `0xef0100`), transactions signed by the private key MUST be rejected if the delegated code is in the deactivated state (i.e., `24` bytes long).

### Gas cost

Check failure on line 55 in EIPS/eip-7851.md

View workflow job for this annotation

GitHub Actions / Markdown Linter

Headings should be surrounded by blank lines [Expected: 1; Actual: 0; Below] [Context: "### Gas cost"]

EIPS/eip-7851.md:55 MD022/blanks-around-headings/blanks-around-headers Headings should be surrounded by blank lines [Expected: 1; Actual: 0; Below] [Context: "### Gas cost"]

Check failure on line 55 in EIPS/eip-7851.md

View workflow job for this annotation

GitHub Actions / Markdown Linter

Headings should be surrounded by blank lines [Expected: 1; Actual: 0; Below] [Context: "### Gas cost"]

EIPS/eip-7851.md:55 MD022/blanks-around-headings/blanks-around-headers Headings should be surrounded by blank lines [Expected: 1; Actual: 0; Below] [Context: "### Gas cost"]
No changes to the base transaction gas cost (`21000`) are required, as the additional valid check for the deactivation status is minimal compared with [EIP-7702](./eip-7702) transactions. Thus it is reasonable to include them in the base gas cost.

## Rationale

### Using a precompiled contract

Check failure on line 60 in EIPS/eip-7851.md

View workflow job for this annotation

GitHub Actions / Markdown Linter

Headings should be surrounded by blank lines [Expected: 1; Actual: 0; Below] [Context: "### Using a precompiled contract"]

EIPS/eip-7851.md:60 MD022/blanks-around-headings/blanks-around-headers Headings should be surrounded by blank lines [Expected: 1; Actual: 0; Below] [Context: "### Using a precompiled contract"]

Check failure on line 60 in EIPS/eip-7851.md

View workflow job for this annotation

GitHub Actions / Markdown Linter

Headings should be surrounded by blank lines [Expected: 1; Actual: 0; Below] [Context: "### Using a precompiled contract"]

EIPS/eip-7851.md:60 MD022/blanks-around-headings/blanks-around-headers Headings should be surrounded by blank lines [Expected: 1; Actual: 0; Below] [Context: "### Using a precompiled contract"]
Alternative methods for implementing this feature include:
- Adding a new transaction type: A new transaction type could deactivate/reactive EOA private keys. This would complicate reactivation, as the contract would need to serve as the authorizer for reactivation, increasing protocol complexity.

Check failure on line 62 in EIPS/eip-7851.md

View workflow job for this annotation

GitHub Actions / Markdown Linter

Lists should be surrounded by blank lines [Context: "- Adding a new transaction typ..."]

EIPS/eip-7851.md:62 MD032/blanks-around-lists Lists should be surrounded by blank lines [Context: "- Adding a new transaction typ..."]

Check failure on line 62 in EIPS/eip-7851.md

View workflow job for this annotation

GitHub Actions / Markdown Linter

Lists should be surrounded by blank lines [Context: "- Adding a new transaction typ..."]

EIPS/eip-7851.md:62 MD032/blanks-around-lists Lists should be surrounded by blank lines [Context: "- Adding a new transaction typ..."]
- Deploying a regular smart contract: A regular deployed contract could track the `deactivated` status of each `address`. This approach would break the base transaction gas cost of `21000` in transaction validation, as accessing the `deactivated` status would require additional address and storage lookups, increasing gas usage.

### In-protocol reactivation

Check failure on line 65 in EIPS/eip-7851.md

View workflow job for this annotation

GitHub Actions / Markdown Linter

Headings should be surrounded by blank lines [Expected: 1; Actual: 0; Below] [Context: "### In-protocol reactivation"]

EIPS/eip-7851.md:65 MD022/blanks-around-headings/blanks-around-headers Headings should be surrounded by blank lines [Expected: 1; Actual: 0; Below] [Context: "### In-protocol reactivation"]

Check failure on line 65 in EIPS/eip-7851.md

View workflow job for this annotation

GitHub Actions / Markdown Linter

Headings should be surrounded by blank lines [Expected: 1; Actual: 0; Below] [Context: "### In-protocol reactivation"]

EIPS/eip-7851.md:65 MD022/blanks-around-headings/blanks-around-headers Headings should be surrounded by blank lines [Expected: 1; Actual: 0; Below] [Context: "### In-protocol reactivation"]
This approach ensures maximum compatibility with future migrations. EOAs can reactivate their private keys, delegate their accounts to an [EIP-7701](./eip7701) contract, and then deactivate their private keys again. This avoids the limitations of upgradable contracts. e.g., to remove legacy proxy contracts when EOF contracts become available, thereby reducing gas overhead, one can reactivate the EOA and delegate to an EOF proxy contract.

### `5000` Gas `PRECOMPILE_GAS_COST`

Check failure on line 68 in EIPS/eip-7851.md

View workflow job for this annotation

GitHub Actions / Markdown Linter

Headings should be surrounded by blank lines [Expected: 1; Actual: 0; Below] [Context: "### `5000` Gas `PRECOMPILE_GAS_COST`"]

EIPS/eip-7851.md:68 MD022/blanks-around-headings/blanks-around-headers Headings should be surrounded by blank lines [Expected: 1; Actual: 0; Below] [Context: "### `5000` Gas `PRECOMPILE_GAS_COST`"]

Check failure on line 68 in EIPS/eip-7851.md

View workflow job for this annotation

GitHub Actions / Markdown Linter

Headings should be surrounded by blank lines [Expected: 1; Actual: 0; Below] [Context: "### `5000` Gas `PRECOMPILE_GAS_COST`"]

EIPS/eip-7851.md:68 MD022/blanks-around-headings/blanks-around-headers Headings should be surrounded by blank lines [Expected: 1; Actual: 0; Below] [Context: "### `5000` Gas `PRECOMPILE_GAS_COST`"]
The `5000` gas cost is sufficient to cover validation, computation, and storage updates for the delegated code.

### Alternative EOA migration approach

Check failure on line 71 in EIPS/eip-7851.md

View workflow job for this annotation

GitHub Actions / Markdown Linter

Headings should be surrounded by blank lines [Expected: 1; Actual: 0; Below] [Context: "### Alternative EOA migration approach"]

EIPS/eip-7851.md:71 MD022/blanks-around-headings/blanks-around-headers Headings should be surrounded by blank lines [Expected: 1; Actual: 0; Below] [Context: "### Alternative EOA migration approach"]

Check failure on line 71 in EIPS/eip-7851.md

View workflow job for this annotation

GitHub Actions / Markdown Linter

Headings should be surrounded by blank lines [Expected: 1; Actual: 0; Below] [Context: "### Alternative EOA migration approach"]

EIPS/eip-7851.md:71 MD022/blanks-around-headings/blanks-around-headers Headings should be surrounded by blank lines [Expected: 1; Actual: 0; Below] [Context: "### Alternative EOA migration approach"]
One alternative migration approach involves using a hard fork to edit all existing and new EOAs to upgradable smart contracts using EOA's ECDSA signatures. Users can then upgrade these smart contracts to achieve more granular permission control. However, this approach is incompatible with EOAs that have already delegated to smart contracts, as it overwrites the existing smart contract implementations. The EIP aims to fill this migration gap.

### Avoiding delegated code prefix modification

Check failure on line 74 in EIPS/eip-7851.md

View workflow job for this annotation

GitHub Actions / Markdown Linter

Headings should be surrounded by blank lines [Expected: 1; Actual: 0; Below] [Context: "### Avoiding delegated code prefix modification"]

EIPS/eip-7851.md:74 MD022/blanks-around-headings/blanks-around-headers Headings should be surrounded by blank lines [Expected: 1; Actual: 0; Below] [Context: "### Avoiding delegated code prefix modification"]

Check failure on line 74 in EIPS/eip-7851.md

View workflow job for this annotation

GitHub Actions / Markdown Linter

Headings should be surrounded by blank lines [Expected: 1; Actual: 0; Below] [Context: "### Avoiding delegated code prefix modification"]

EIPS/eip-7851.md:74 MD022/blanks-around-headings/blanks-around-headers Headings should be surrounded by blank lines [Expected: 1; Actual: 0; Below] [Context: "### Avoiding delegated code prefix modification"]
This EIP appends a byte (`0x00`) to the delegated code instead of modifying the prefix (`0xef0100`) of [EIP-7702](./eip-7702) to ensure forward compatibility. If future prefixes such as `0xef0101` are introduced, changing the prefix (e.g., to `0xef01ff`) makes it unclear which prefix to restore upon reactivation.

### Avoiding account state changes

Check failure on line 77 in EIPS/eip-7851.md

View workflow job for this annotation

GitHub Actions / Markdown Linter

Headings should be surrounded by blank lines [Expected: 1; Actual: 0; Below] [Context: "### Avoiding account state changes"]

EIPS/eip-7851.md:77 MD022/blanks-around-headings/blanks-around-headers Headings should be surrounded by blank lines [Expected: 1; Actual: 0; Below] [Context: "### Avoiding account state changes"]

Check failure on line 77 in EIPS/eip-7851.md

View workflow job for this annotation

GitHub Actions / Markdown Linter

Headings should be surrounded by blank lines [Expected: 1; Actual: 0; Below] [Context: "### Avoiding account state changes"]

EIPS/eip-7851.md:77 MD022/blanks-around-headings/blanks-around-headers Headings should be surrounded by blank lines [Expected: 1; Actual: 0; Below] [Context: "### Avoiding account state changes"]
Another alternative is to add a new field to the account state to store the `deactivated` status. However, this approach complicates the account state. It also brings changes in the account trie structure and RLP encoding used in networking, which complicates the implementation.

### Forwards compatibility for removing EOAs
Expand Down
Loading