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

all: implement eip-7702 set code tx #30078

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

lightclient
Copy link
Member

@lightclient lightclient commented Jun 26, 2024

Spec: EIP-7702: Set EOA account code

Add a new transaction type that adds a list of [chain_id, address, nonce, y_parity, r, s] authorization tuples. For each tuple, write a delegation designator (0xef0100 ++ address) to the signing account’s code. All code reading operations must load the code pointed to by the designator.

@lightclient lightclient force-pushed the eip-7702 branch 2 times, most recently from bc22287 to 95524bb Compare June 26, 2024 23:31
@rjl493456442
Copy link
Member

Should we propose another EIP to revamp EIP158? Otherwise, as we discussed previously, the leftover storage of an "empty" EOA could be cleared at the end of block.

@lightclient
Copy link
Member Author

@rjl493456442 I think the proposal which will get accepted for devnet-2 and on will avoid the 158 problem, so it's probably okay to just let it play out. ethereum/EIPs#8677

evm.StateDB.AddAddressToAccessList(addr)
// Check if code is a delegation and if so, charge for resolution
cost := params.ColdAccountAccessCostEIP2929 - params.WarmStorageReadCostEIP2929
if addr, ok := types.ParseDelegation(evm.StateDB.GetCode(addr)); ok {
Copy link
Contributor

Choose a reason for hiding this comment

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

shouldn't delegation resolution costs (warm or cold) be paid each time? irrespective of whether addr is in access list or not.

@lightclient lightclient force-pushed the eip-7702 branch 4 times, most recently from 94389ba to 8578fb7 Compare September 9, 2024 20:24
core/state_transition.go Outdated Show resolved Hide resolved
core/state_transition.go Outdated Show resolved Hide resolved

func gasExtCodeCopyEIP7702(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
// memory expansion first (dynamic part of pre-2929 implementation)
gas, err := gasExtCodeCopy(evm, contract, stack, mem, memorySize)
Copy link
Contributor

@buddh0 buddh0 Sep 19, 2024

Choose a reason for hiding this comment

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

reuse func gasExtCodeCopyEIP2929?

	// memory expansion first (dynamic part of pre-2929 implementation)
	gas, err := gasExtCodeCopy(evm, contract, stack, mem, memorySize)
	if err != nil {
		return 0, err
	}
	addr := common.Address(stack.peek().Bytes20())
	// Check slot presence in the access list
	if !evm.StateDB.AddressInAccessList(addr) {
		evm.StateDB.AddAddressToAccessList(addr)
		var overflow bool
		// We charge (cold-warm), since 'warm' is already charged as constantGas
		if gas, overflow = math.SafeAdd(gas, params.ColdAccountAccessCostEIP2929-params.WarmStorageReadCostEIP2929); overflow {
			return 0, ErrGasUintOverflow
		}
	}

-->

// memory expansion first (dynamic part of pre-2929 implementation)
gas, err := gasExtCodeCopyEIP2929(evm, contract, stack, mem, memorySize)
if err != nil {
	return 0, err
}

}

func gasEip7702CodeCheck(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
addr := common.Address(stack.peek().Bytes20())
Copy link
Contributor

@buddh0 buddh0 Sep 19, 2024

Choose a reason for hiding this comment

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

reuse gasEip2929AccountCheck?

	addr := common.Address(stack.peek().Bytes20())
	cost := uint64(0)
	// fmt.Println("checking", addr, evm.StateDB.AddressInAccessList(addr))
	// Check slot presence in the access list
	if !evm.StateDB.AddressInAccessList(addr) {
		// If the caller cannot afford the cost, this change will be rolled back
		evm.StateDB.AddAddressToAccessList(addr)
		// The warm storage read cost is already charged as constantGas
		cost = params.ColdAccountAccessCostEIP2929 - params.WarmStorageReadCostEIP2929
	}

--->

cost, _ :=gasEip2929AccountCheck(evm, contract, stack, mem, memorySize)

Kya123iu

This comment was marked as spam.

@buddh0
Copy link
Contributor

buddh0 commented Oct 8, 2024

hello, I run [email protected] agaist this branch, still some failed test cases, 3 cases related:
ext_code_on_self_set_code
set_code_to_self_caller
set_code_to_tstore_reentry
is there something missed? @lightclient

    --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/ext_code_on_self_set_code.json (0.01s)
        --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/ext_code_on_self_set_code.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_ext_code_on_self_set_code[fork_Prague-state_test-balance_0] (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/ext_code_on_self_set_code.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_ext_code_on_self_set_code[fork_Prague-state_test-balance_0]/Prague/0/hash/trie (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/ext_code_on_self_set_code.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_ext_code_on_self_set_code[fork_Prague-state_test-balance_0]/Prague/0/hash/snap (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/ext_code_on_self_set_code.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_ext_code_on_self_set_code[fork_Prague-state_test-balance_0]/Prague/0/path/trie (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/ext_code_on_self_set_code.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_ext_code_on_self_set_code[fork_Prague-state_test-balance_0]/Prague/0/path/snap (0.00s)
        --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/ext_code_on_self_set_code.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_ext_code_on_self_set_code[fork_Prague-state_test-balance_1] (0.01s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/ext_code_on_self_set_code.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_ext_code_on_self_set_code[fork_Prague-state_test-balance_1]/Prague/0/hash/trie (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/ext_code_on_self_set_code.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_ext_code_on_self_set_code[fork_Prague-state_test-balance_1]/Prague/0/hash/snap (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/ext_code_on_self_set_code.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_ext_code_on_self_set_code[fork_Prague-state_test-balance_1]/Prague/0/path/trie (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/ext_code_on_self_set_code.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_ext_code_on_self_set_code[fork_Prague-state_test-balance_1]/Prague/0/path/snap (0.00s)
    --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_self_caller.json (0.03s)
        --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_self_caller.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_self_caller[fork_Prague-call_opcode_CALL-evm_code_type_LEGACY-state_test-value_0] (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_self_caller.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_self_caller[fork_Prague-call_opcode_CALL-evm_code_type_LEGACY-state_test-value_0]/Prague/0/hash/trie (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_self_caller.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_self_caller[fork_Prague-call_opcode_CALL-evm_code_type_LEGACY-state_test-value_0]/Prague/0/hash/snap (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_self_caller.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_self_caller[fork_Prague-call_opcode_CALL-evm_code_type_LEGACY-state_test-value_0]/Prague/0/path/trie (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_self_caller.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_self_caller[fork_Prague-call_opcode_CALL-evm_code_type_LEGACY-state_test-value_0]/Prague/0/path/snap (0.00s)
        --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_self_caller.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_self_caller[fork_Prague-call_opcode_CALL-evm_code_type_LEGACY-state_test-value_1] (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_self_caller.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_self_caller[fork_Prague-call_opcode_CALL-evm_code_type_LEGACY-state_test-value_1]/Prague/0/hash/trie (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_self_caller.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_self_caller[fork_Prague-call_opcode_CALL-evm_code_type_LEGACY-state_test-value_1]/Prague/0/hash/snap (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_self_caller.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_self_caller[fork_Prague-call_opcode_CALL-evm_code_type_LEGACY-state_test-value_1]/Prague/0/path/trie (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_self_caller.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_self_caller[fork_Prague-call_opcode_CALL-evm_code_type_LEGACY-state_test-value_1]/Prague/0/path/snap (0.00s)
        --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_self_caller.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_self_caller[fork_Prague-call_opcode_CALLCODE-evm_code_type_LEGACY-state_test-value_0] (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_self_caller.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_self_caller[fork_Prague-call_opcode_CALLCODE-evm_code_type_LEGACY-state_test-value_0]/Prague/0/hash/trie (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_self_caller.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_self_caller[fork_Prague-call_opcode_CALLCODE-evm_code_type_LEGACY-state_test-value_0]/Prague/0/hash/snap (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_self_caller.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_self_caller[fork_Prague-call_opcode_CALLCODE-evm_code_type_LEGACY-state_test-value_0]/Prague/0/path/trie (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_self_caller.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_self_caller[fork_Prague-call_opcode_CALLCODE-evm_code_type_LEGACY-state_test-value_0]/Prague/0/path/snap (0.00s)
        --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_self_caller.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_self_caller[fork_Prague-call_opcode_CALLCODE-evm_code_type_LEGACY-state_test-value_1] (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_self_caller.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_self_caller[fork_Prague-call_opcode_CALLCODE-evm_code_type_LEGACY-state_test-value_1]/Prague/0/hash/trie (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_self_caller.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_self_caller[fork_Prague-call_opcode_CALLCODE-evm_code_type_LEGACY-state_test-value_1]/Prague/0/hash/snap (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_self_caller.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_self_caller[fork_Prague-call_opcode_CALLCODE-evm_code_type_LEGACY-state_test-value_1]/Prague/0/path/trie (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_self_caller.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_self_caller[fork_Prague-call_opcode_CALLCODE-evm_code_type_LEGACY-state_test-value_1]/Prague/0/path/snap (0.00s)
        --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_self_caller.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_self_caller[fork_Prague-call_opcode_DELEGATECALL-evm_code_type_LEGACY-state_test-value_0] (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_self_caller.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_self_caller[fork_Prague-call_opcode_DELEGATECALL-evm_code_type_LEGACY-state_test-value_0]/Prague/0/hash/trie (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_self_caller.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_self_caller[fork_Prague-call_opcode_DELEGATECALL-evm_code_type_LEGACY-state_test-value_0]/Prague/0/hash/snap (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_self_caller.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_self_caller[fork_Prague-call_opcode_DELEGATECALL-evm_code_type_LEGACY-state_test-value_0]/Prague/0/path/trie (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_self_caller.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_self_caller[fork_Prague-call_opcode_DELEGATECALL-evm_code_type_LEGACY-state_test-value_0]/Prague/0/path/snap (0.00s)
        --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_self_caller.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_self_caller[fork_Prague-call_opcode_DELEGATECALL-evm_code_type_LEGACY-state_test-value_1] (0.01s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_self_caller.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_self_caller[fork_Prague-call_opcode_DELEGATECALL-evm_code_type_LEGACY-state_test-value_1]/Prague/0/hash/trie (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_self_caller.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_self_caller[fork_Prague-call_opcode_DELEGATECALL-evm_code_type_LEGACY-state_test-value_1]/Prague/0/hash/snap (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_self_caller.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_self_caller[fork_Prague-call_opcode_DELEGATECALL-evm_code_type_LEGACY-state_test-value_1]/Prague/0/path/trie (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_self_caller.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_self_caller[fork_Prague-call_opcode_DELEGATECALL-evm_code_type_LEGACY-state_test-value_1]/Prague/0/path/snap (0.00s)
        --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_self_caller.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_self_caller[fork_Prague-call_opcode_STATICCALL-evm_code_type_LEGACY-state_test-value_0] (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_self_caller.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_self_caller[fork_Prague-call_opcode_STATICCALL-evm_code_type_LEGACY-state_test-value_0]/Prague/0/hash/trie (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_self_caller.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_self_caller[fork_Prague-call_opcode_STATICCALL-evm_code_type_LEGACY-state_test-value_0]/Prague/0/hash/snap (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_self_caller.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_self_caller[fork_Prague-call_opcode_STATICCALL-evm_code_type_LEGACY-state_test-value_0]/Prague/0/path/trie (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_self_caller.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_self_caller[fork_Prague-call_opcode_STATICCALL-evm_code_type_LEGACY-state_test-value_0]/Prague/0/path/snap (0.00s)
        --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_self_caller.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_self_caller[fork_Prague-call_opcode_STATICCALL-evm_code_type_LEGACY-state_test-value_1] (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_self_caller.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_self_caller[fork_Prague-call_opcode_STATICCALL-evm_code_type_LEGACY-state_test-value_1]/Prague/0/hash/trie (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_self_caller.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_self_caller[fork_Prague-call_opcode_STATICCALL-evm_code_type_LEGACY-state_test-value_1]/Prague/0/hash/snap (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_self_caller.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_self_caller[fork_Prague-call_opcode_STATICCALL-evm_code_type_LEGACY-state_test-value_1]/Prague/0/path/trie (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_self_caller.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_self_caller[fork_Prague-call_opcode_STATICCALL-evm_code_type_LEGACY-state_test-value_1]/Prague/0/path/snap (0.00s)
    --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_tstore_reentry.json (0.07s)
        --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_tstore_reentry.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_tstore_reentry[fork_Prague-call_opcode_CALL-evm_code_type_LEGACY-state_test-return_opcode_RETURN] (0.01s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_tstore_reentry.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_tstore_reentry[fork_Prague-call_opcode_CALL-evm_code_type_LEGACY-state_test-return_opcode_RETURN]/Prague/0/hash/trie (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_tstore_reentry.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_tstore_reentry[fork_Prague-call_opcode_CALL-evm_code_type_LEGACY-state_test-return_opcode_RETURN]/Prague/0/hash/snap (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_tstore_reentry.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_tstore_reentry[fork_Prague-call_opcode_CALL-evm_code_type_LEGACY-state_test-return_opcode_RETURN]/Prague/0/path/trie (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_tstore_reentry.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_tstore_reentry[fork_Prague-call_opcode_CALL-evm_code_type_LEGACY-state_test-return_opcode_RETURN]/Prague/0/path/snap (0.00s)
        --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_tstore_reentry.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_tstore_reentry[fork_Prague-call_opcode_CALL-evm_code_type_LEGACY-state_test-return_opcode_REVERT] (0.01s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_tstore_reentry.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_tstore_reentry[fork_Prague-call_opcode_CALL-evm_code_type_LEGACY-state_test-return_opcode_REVERT]/Prague/0/hash/trie (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_tstore_reentry.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_tstore_reentry[fork_Prague-call_opcode_CALL-evm_code_type_LEGACY-state_test-return_opcode_REVERT]/Prague/0/hash/snap (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_tstore_reentry.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_tstore_reentry[fork_Prague-call_opcode_CALL-evm_code_type_LEGACY-state_test-return_opcode_REVERT]/Prague/0/path/trie (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_tstore_reentry.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_tstore_reentry[fork_Prague-call_opcode_CALL-evm_code_type_LEGACY-state_test-return_opcode_REVERT]/Prague/0/path/snap (0.00s)
        --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_tstore_reentry.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_tstore_reentry[fork_Prague-call_opcode_CALLCODE-evm_code_type_LEGACY-state_test-return_opcode_RETURN] (0.01s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_tstore_reentry.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_tstore_reentry[fork_Prague-call_opcode_CALLCODE-evm_code_type_LEGACY-state_test-return_opcode_RETURN]/Prague/0/hash/trie (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_tstore_reentry.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_tstore_reentry[fork_Prague-call_opcode_CALLCODE-evm_code_type_LEGACY-state_test-return_opcode_RETURN]/Prague/0/hash/snap (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_tstore_reentry.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_tstore_reentry[fork_Prague-call_opcode_CALLCODE-evm_code_type_LEGACY-state_test-return_opcode_RETURN]/Prague/0/path/trie (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_tstore_reentry.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_tstore_reentry[fork_Prague-call_opcode_CALLCODE-evm_code_type_LEGACY-state_test-return_opcode_RETURN]/Prague/0/path/snap (0.00s)
        --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_tstore_reentry.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_tstore_reentry[fork_Prague-call_opcode_CALLCODE-evm_code_type_LEGACY-state_test-return_opcode_REVERT] (0.01s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_tstore_reentry.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_tstore_reentry[fork_Prague-call_opcode_CALLCODE-evm_code_type_LEGACY-state_test-return_opcode_REVERT]/Prague/0/hash/trie (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_tstore_reentry.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_tstore_reentry[fork_Prague-call_opcode_CALLCODE-evm_code_type_LEGACY-state_test-return_opcode_REVERT]/Prague/0/hash/snap (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_tstore_reentry.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_tstore_reentry[fork_Prague-call_opcode_CALLCODE-evm_code_type_LEGACY-state_test-return_opcode_REVERT]/Prague/0/path/trie (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_tstore_reentry.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_tstore_reentry[fork_Prague-call_opcode_CALLCODE-evm_code_type_LEGACY-state_test-return_opcode_REVERT]/Prague/0/path/snap (0.00s)
        --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_tstore_reentry.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_tstore_reentry[fork_Prague-call_opcode_DELEGATECALL-evm_code_type_LEGACY-state_test-return_opcode_RETURN] (0.01s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_tstore_reentry.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_tstore_reentry[fork_Prague-call_opcode_DELEGATECALL-evm_code_type_LEGACY-state_test-return_opcode_RETURN]/Prague/0/hash/trie (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_tstore_reentry.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_tstore_reentry[fork_Prague-call_opcode_DELEGATECALL-evm_code_type_LEGACY-state_test-return_opcode_RETURN]/Prague/0/hash/snap (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_tstore_reentry.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_tstore_reentry[fork_Prague-call_opcode_DELEGATECALL-evm_code_type_LEGACY-state_test-return_opcode_RETURN]/Prague/0/path/trie (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_tstore_reentry.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_tstore_reentry[fork_Prague-call_opcode_DELEGATECALL-evm_code_type_LEGACY-state_test-return_opcode_RETURN]/Prague/0/path/snap (0.01s)
        --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_tstore_reentry.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_tstore_reentry[fork_Prague-call_opcode_DELEGATECALL-evm_code_type_LEGACY-state_test-return_opcode_REVERT] (0.01s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_tstore_reentry.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_tstore_reentry[fork_Prague-call_opcode_DELEGATECALL-evm_code_type_LEGACY-state_test-return_opcode_REVERT]/Prague/0/hash/trie (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_tstore_reentry.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_tstore_reentry[fork_Prague-call_opcode_DELEGATECALL-evm_code_type_LEGACY-state_test-return_opcode_REVERT]/Prague/0/hash/snap (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_tstore_reentry.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_tstore_reentry[fork_Prague-call_opcode_DELEGATECALL-evm_code_type_LEGACY-state_test-return_opcode_REVERT]/Prague/0/path/trie (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_tstore_reentry.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_tstore_reentry[fork_Prague-call_opcode_DELEGATECALL-evm_code_type_LEGACY-state_test-return_opcode_REVERT]/Prague/0/path/snap (0.00s)
        --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_tstore_reentry.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_tstore_reentry[fork_Prague-call_opcode_STATICCALL-evm_code_type_LEGACY-state_test-return_opcode_RETURN] (0.01s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_tstore_reentry.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_tstore_reentry[fork_Prague-call_opcode_STATICCALL-evm_code_type_LEGACY-state_test-return_opcode_RETURN]/Prague/0/hash/trie (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_tstore_reentry.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_tstore_reentry[fork_Prague-call_opcode_STATICCALL-evm_code_type_LEGACY-state_test-return_opcode_RETURN]/Prague/0/hash/snap (0.01s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_tstore_reentry.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_tstore_reentry[fork_Prague-call_opcode_STATICCALL-evm_code_type_LEGACY-state_test-return_opcode_RETURN]/Prague/0/path/trie (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_tstore_reentry.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_tstore_reentry[fork_Prague-call_opcode_STATICCALL-evm_code_type_LEGACY-state_test-return_opcode_RETURN]/Prague/0/path/snap (0.00s)
        --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_tstore_reentry.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_tstore_reentry[fork_Prague-call_opcode_STATICCALL-evm_code_type_LEGACY-state_test-return_opcode_REVERT] (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_tstore_reentry.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_tstore_reentry[fork_Prague-call_opcode_STATICCALL-evm_code_type_LEGACY-state_test-return_opcode_REVERT]/Prague/0/hash/trie (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_tstore_reentry.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_tstore_reentry[fork_Prague-call_opcode_STATICCALL-evm_code_type_LEGACY-state_test-return_opcode_REVERT]/Prague/0/hash/snap (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_tstore_reentry.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_tstore_reentry[fork_Prague-call_opcode_STATICCALL-evm_code_type_LEGACY-state_test-return_opcode_REVERT]/Prague/0/path/trie (0.00s)
            --- FAIL: TestExecutionSpecState/prague/eip7702_set_code_tx/set_code_txs/set_code_to_tstore_reentry.json/tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_to_tstore_reentry[fork_Prague-call_opcode_STATICCALL-evm_code_type_LEGACY-state_test-return_opcode_REVERT]/Prague/0/path/snap (0.00s)

@MariusVanDerWijden
Copy link
Member

Lint is failing atm

codeHash := st.state.GetCodeHash(msg.From)
if codeHash != (common.Hash{}) && codeHash != types.EmptyCodeHash {
code := st.state.GetCode(msg.From)
if 0 < len(code) && !bytes.HasPrefix(code, types.DelegationPrefix) {
Copy link
Member

Choose a reason for hiding this comment

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

Ah this is where I got that check from. @holiman commented on my EOF branch that we shouldn't do 0 < len(code) but rather len(code) > 0. Now the delegation prefix of 0xfe0100 also makes sense

Copy link
Member Author

Choose a reason for hiding this comment

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

why is it better swapped?

Copy link
Contributor

Choose a reason for hiding this comment

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

So, first of all, neither is wrong, per se.

Using variable < constant is how we typically do it in go-ethereum, and I think it's more standard across the board.

I think the reason it's more common is that it's closer to most languages.

It's below five degrees outside!

I.e: it < 5 .

Whereas you wouldn't not say:

Five degrees is warmer than it is outside!

Your code is now saying

If zero is smaller than the length of the code ...

As opposed to

If the length of the code is larger than zero ..


There's an argument that can be made for doing it the opposite way, particularly when it comes to equality-check.
if 0 == x vs if x == 0. If the programmer makes a typo, then if 0=x will be a compilation failure, whereas if x=0 will not. I don't think it's particularly relevant in our code.

@@ -439,15 +445,55 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
// - reset transient storage(eip 1153)
st.state.Prepare(rules, msg.From, st.evm.Context.Coinbase, msg.To, vm.ActivePrecompiles(rules), msg.AccessList)

if !contractCreation {
Copy link
Member

Choose a reason for hiding this comment

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

Aha this is also where the other weird change in my PR came from cc @holiman

}
// Check the authority account 1) doesn't have code or has exisiting
// delegation 2) matches the auth's nonce
st.state.AddAddressToAccessList(authority)
Copy link
Member

Choose a reason for hiding this comment

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

Might be nothing, but shouldn't we add the address to the access list after the nonce overflow check? afaict, you moved the nonce overflow check to L471 while it is the second step in the eip, so if the nonce is set to 2**64 -1 we will add the authority to the access list, while other clients might not. cc @marioevz we should create a test for that

Copy link
Member

Choose a reason for hiding this comment

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

We don't have an explicit test for this, but we do call the authorization signer account during the transaction where the authorization failed due to the overflow nonce check here:
https://github.com/ethereum/execution-spec-tests/blob/f5799c8b89235718239f05e552e52e8c597763fb/tests/prague/eip7702_set_code_tx/test_set_code_txs.py#L2408-L2413
However if this did not catch the issue, would we need to add something like an EXTCODE* instead of calling?

Copy link
Member Author

@lightclient lightclient Oct 15, 2024

Choose a reason for hiding this comment

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

I think there is a test for this and the move to L476 fixed it :)

@MariusVanDerWijden
Copy link
Member

We still need to add the setCodeTxType to accounts/external/backend.go::SignTx and internal/ethapi/transaction_args.go::ToTransaction

@lightclient lightclient force-pushed the eip-7702 branch 2 times, most recently from be25225 to 1b5460c Compare October 15, 2024 17:54
@lightclient lightclient marked this pull request as ready for review October 15, 2024 17:57
@lightclient lightclient force-pushed the eip-7702 branch 2 times, most recently from 20f3ad4 to f5eae8d Compare October 15, 2024 18:01
@holiman
Copy link
Contributor

holiman commented Oct 16, 2024

Reading up on the spec, I typed up some questions. Maybe this should have been posted in a different forum


Nonce bumps

After incrementing the sender’s nonce

So, if my auth's are

Prestate: Addr X: nonce 5
tx (nonce: 5, addr X)

  • auth1: auth X, nonce 6, address Y
  • auth2: auth X, nonce 7, address Z
  • auth3: auth X, nonce 8, address Y

Would result in Addr X: nonce 8 delegated to code @ Y. So nonce for X goes from 5 to 8 with this tx, correct?

EDIT: Yes, correct


Dos-ability

How large can we make a transaction, and how costly is it to validate?
I.e, how many signature recoveries, if we assume that the final auth invalidates the transaction?
THe PER_AUTH_BASE_COST of 12500 is only paid for valid transactions. Perhaps we should specify a
max "risk appetite" that geth is willing to spend. If the tx is more expensive than, e.g. 200K gas,
then it might be a DoS and not worth the risk of validating (and thus discard)?


Delegate of delegate of delegate

  • auth1: auth X, address Y
    • This sets X code to 0xef0100 || Y
  • auth2: auth Z, address X
    • This sets Z to 0xef0100 || X

What happens when we execute code at Z? Do we resolve it N steps until we reach a final non-delegation?
Are there tests for this?

Recursive delegation

  • auth1: auth X, address Y
    • This sets X code to 0xef0100 || Y
  • auth2: auth Y, address X
    • This sets Y to 0xef0100 || X

What happens when we execute code at either X or Y? If we follow resolves, we will spin indefinitely.
Are there tests for this?

NOTE: This PR only resolves one step, so in

  • Delegate of delegate of delegate
    • Executing X would resolve code at Y
    • Executing Z would resolve invalid code 0xef0100.. at X.

There are basically three ways this can play out:

  1. Recursively resolve,
  2. Resolve one step, but return original code
  3. Resolve one step, but return overwritten code (what this PR does)

Slots

So, storage slots on EOAs. This will create storage slots on EOAs. Since the authority nonce will be bumped, the auth account will never be empty, so empty-delete is not a problem.
Are these slots useful? Do we really want them, or should they be cleared?

Delegate to empty

As a special case, if address is 0x0000000000000000000000000000000000000000

Isn't this special case undistinguishable from the general "delegate to empty code" case? Wouldn't a delegate to 0x00..0 and delegate to 0x00..1 behave identically?


Attacking a multi-auth transaction

Let's consider a transaction with multiple auths.

tx TX_A from sender:

  • auth1: auth X, nonce x, address A
  • auth2: auth Y, nonce y, address B
  • auth3: auth Z, nonce z, address C

Once this transaction is public, an attacker can craft a transaction to include before TX_A.

tx TX_B from evil:

  • auth1: auth X, nonce x, address A

When TX_B is executed, the nonce of A is increased. When TX_A is executed, the first auth will be (silently) ignored, according to the spec:

If any of the above steps fail, immediately stop processing that tuple and continue to the next tuple in the list.

tx TX_A from sender is now:

  • auth1: auth X, nonce x, address A
  • auth2: auth Y, nonce y, address B
  • auth3: auth Z, nonce z, address C

OBS Any multi-auth transaction is subject to such an attack: whereby any or all of the bundled authorizations can be made moot, without invalidating the transaction.

Furthermore this is possible even on an single-auth transaction. In the case where tx.origin sets the code of self, this is not a problem (since the auth nonce is not valid until the tx.origin nonce has been incremented once). But whenever the tx.origin != auth, the auth can be made moot by an attacker.


Other

The Security Considerations seems to be written as if auth nonce does not increase, that is, auths are reusable:

Replay protection (e.g., a nonce) should be implemented by the delegate and signed over. Without it, a malicious actor can reuse a signature, repeating its effects.

There seems to be some confusion about whether nonces are reusable, but step 6 in the spec says

Verify the nonce of authority is equal to nonce. In case authority does not exist in the trie, verify that nonce is equal to 0.

???


Changes permanent !?

This EIP breaks the invariant that an account balance can only decrease as a result of transactions originating from that account.

Sounds strange to me -- there's no such invariant. The only invariant somewhat similar is that a tx.sender account balance can only increase after the outer tx cost has been paid (no more can be charged after that. With this EIP, it can, since the tx.sender can issue CALLs).


If transaction execution results in failure (any exceptional condition or code reverting), setting delegation designations is not rolled back.

This is strangely worded. Since all delegations are undone after the transaction ends, what does this mean?
EDIT: The eip title is, literally "Add a new tx type that sets the code for an EOA during execution" (emphasis mine). Are these changes permanent?

Eaerlier, this setting of code was temporary. Meaning that whoever who sent the transaction was the one who could to a degree decide what state he wanted to replace. If they control account X, they can decide to temporarily set some code there, and exec code on their own behalf. They could also combine other auths, and "synthesise" the env which their transaction interacted with.

Change since then seems to be:

  • make the auth nonce mandatory. Nice for security!
  • make setting the code global/persisten. This is a huge change! This totally throws previous guarantees about code immutability out the window. This heralds a new era of upgradable contracts. Contracts which change from one transaction to the next, without any form of selfdestruct in-between! Total shapeshifters!

Seems like a gigantic change which should be headlined was just silently slipped into the EIP !

Co-authored-by: lightclient <[email protected]>
Co-authored-by: Mario Vega <[email protected]>
// Set code txs are defined to use 0 and 1 as their recovery
// id, add 27 to become equivalent to unprotected Homestead signatures.
V = new(big.Int).Add(V, big.NewInt(27))
if tx.ChainId().Cmp(s.chainId) != 0 {
Copy link
Contributor

Choose a reason for hiding this comment

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

chain id 0 is not allowed here, which is not consistent with here.

@lightclient
Copy link
Member Author

lightclient commented Oct 18, 2024

@holiman added a test for t8n in 7d7573e.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants