-
Notifications
You must be signed in to change notification settings - Fork 20.1k
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
base: master
Are you sure you want to change the base?
Conversation
bc22287
to
95524bb
Compare
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. |
@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 |
ff4dba2
to
955384a
Compare
e3834ac
to
20ea148
Compare
core/vm/operations_acl.go
Outdated
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 { |
There was a problem hiding this comment.
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.
94389ba
to
8578fb7
Compare
core/vm/operations_acl.go
Outdated
|
||
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) |
There was a problem hiding this comment.
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
}
core/vm/operations_acl.go
Outdated
} | ||
|
||
func gasEip7702CodeCheck(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { | ||
addr := common.Address(stack.peek().Bytes20()) |
There was a problem hiding this comment.
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)
hello, I run [email protected] agaist this branch, still some failed test cases, 3 cases related:
|
Lint is failing atm |
core/state_transition.go
Outdated
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) { |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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 :)
We still need to add the setCodeTxType to |
be25225
to
1b5460c
Compare
20f3ad4
to
f5eae8d
Compare
Reading up on the spec, I typed up some questions. Maybe this should have been posted in a different forum Nonce bumps
So, if my auth's are Prestate:
Would result in EDIT: Yes, correct Dos-abilityHow large can we make a transaction, and how costly is it to validate? Delegate of delegate of delegate
What happens when we execute code at Recursive delegation
What happens when we execute code at either NOTE: This PR only resolves one step, so in
There are basically three ways this can play out:
SlotsSo, storage slots on EOAs. This will create storage slots on EOAs. Since the Delegate to empty
Isn't this special case undistinguishable from the general "delegate to empty code" case? Wouldn't a Attacking a multi-auth transactionLet's consider a transaction with multiple auths. tx
Once this transaction is public, an attacker can craft a transaction to include before tx
When
tx
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 OtherThe
There seems to be some confusion about whether nonces are reusable, but step
??? Changes permanent !?
Sounds strange to me -- there's no such invariant. The only invariant somewhat similar is that a
This is strangely worded. Since all delegations are undone after the transaction ends, what does this mean? 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 Change since then seems to be:
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 { |
There was a problem hiding this comment.
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.
Spec: EIP-7702: Set EOA account code