17
17
package core
18
18
19
19
import (
20
+ "bytes"
20
21
"fmt"
21
22
"math"
22
23
"math/big"
@@ -27,6 +28,7 @@ import (
27
28
"github.com/ethereum/go-ethereum/core/types"
28
29
"github.com/ethereum/go-ethereum/core/vm"
29
30
"github.com/ethereum/go-ethereum/crypto/kzg4844"
31
+ "github.com/ethereum/go-ethereum/crypto/secp256k1"
30
32
"github.com/ethereum/go-ethereum/params"
31
33
"github.com/holiman/uint256"
32
34
)
@@ -68,7 +70,7 @@ func (result *ExecutionResult) Revert() []byte {
68
70
}
69
71
70
72
// IntrinsicGas computes the 'intrinsic gas' for a message with the given data.
71
- func IntrinsicGas (data []byte , accessList types.AccessList , isContractCreation , isHomestead , isEIP2028 , isEIP3860 bool ) (uint64 , error ) {
73
+ func IntrinsicGas (data []byte , accessList types.AccessList , authList types. AuthorizationList , isContractCreation , isHomestead , isEIP2028 , isEIP3860 bool ) (uint64 , error ) {
72
74
// Set the starting gas for the raw transaction
73
75
var gas uint64
74
76
if isContractCreation && isHomestead {
@@ -114,6 +116,9 @@ func IntrinsicGas(data []byte, accessList types.AccessList, isContractCreation,
114
116
gas += uint64 (len (accessList )) * params .TxAccessListAddressGas
115
117
gas += uint64 (accessList .StorageKeys ()) * params .TxAccessListStorageKeyGas
116
118
}
119
+ if authList != nil {
120
+ gas += uint64 (len (authList )) * params .CallNewAccountGas
121
+ }
117
122
return gas , nil
118
123
}
119
124
@@ -141,6 +146,7 @@ type Message struct {
141
146
AccessList types.AccessList
142
147
BlobGasFeeCap * big.Int
143
148
BlobHashes []common.Hash
149
+ AuthList types.AuthorizationList
144
150
145
151
// When SkipNonceChecks is true, the message nonce is not checked against the
146
152
// account nonce in state.
@@ -163,6 +169,7 @@ func TransactionToMessage(tx *types.Transaction, s types.Signer, baseFee *big.In
163
169
Value : tx .Value (),
164
170
Data : tx .Data (),
165
171
AccessList : tx .AccessList (),
172
+ AuthList : tx .AuthList (),
166
173
SkipNonceChecks : false ,
167
174
SkipFromEOACheck : false ,
168
175
BlobHashes : tx .BlobHashes (),
@@ -300,10 +307,10 @@ func (st *StateTransition) preCheck() error {
300
307
}
301
308
if ! msg .SkipFromEOACheck {
302
309
// Make sure the sender is an EOA
303
- codeHash := st .state .GetCodeHash (msg .From )
304
- if codeHash != (common. Hash {} ) && codeHash != types . EmptyCodeHash {
310
+ code := st .state .GetCode (msg .From )
311
+ if 0 < len ( code ) && ! bytes . HasPrefix ( code , [] byte { 0xef , 0x01 , 0x00 }) {
305
312
return fmt .Errorf ("%w: address %v, codehash: %s" , ErrSenderNoEOA ,
306
- msg .From .Hex (), codeHash )
313
+ msg .From .Hex (), st . state . GetCodeHash ( msg . From ) )
307
314
}
308
315
}
309
316
// Make sure that transaction gasFeeCap is greater than the baseFee (post london)
@@ -363,6 +370,27 @@ func (st *StateTransition) preCheck() error {
363
370
}
364
371
}
365
372
}
373
+
374
+ // Check that auth list isn't empty.
375
+ if msg .AuthList != nil && len (msg .AuthList ) == 0 {
376
+ return fmt .Errorf ("%w: address %v" , ErrEmptyAuthList , msg .From .Hex ())
377
+ }
378
+
379
+ // TODO: remove after this spec change is merged:
380
+ // https://github.com/ethereum/EIPs/pull/8845
381
+ if msg .AuthList != nil {
382
+ var (
383
+ secp256k1N = secp256k1 .S256 ().Params ().N
384
+ secp256k1halfN = new (big.Int ).Div (secp256k1N , big .NewInt (2 ))
385
+ )
386
+ for _ , auth := range msg .AuthList {
387
+ if auth .V .Cmp (common .Big1 ) > 0 || auth .S .Cmp (secp256k1halfN ) > 0 {
388
+ w := fmt .Errorf ("set code transaction with invalid auth signature" )
389
+ return fmt .Errorf ("%w: address %v" , w , msg .From .Hex ())
390
+ }
391
+ }
392
+ }
393
+
366
394
return st .buyGas ()
367
395
}
368
396
@@ -400,7 +428,7 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
400
428
)
401
429
402
430
// Check clauses 4-5, subtract intrinsic gas if everything is correct
403
- gas , err := IntrinsicGas (msg .Data , msg .AccessList , contractCreation , rules .IsHomestead , rules .IsIstanbul , rules .IsShanghai )
431
+ gas , err := IntrinsicGas (msg .Data , msg .AccessList , msg . AuthList , contractCreation , rules .IsHomestead , rules .IsIstanbul , rules .IsShanghai )
404
432
if err != nil {
405
433
return nil , err
406
434
}
@@ -439,15 +467,49 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
439
467
// - reset transient storage(eip 1153)
440
468
st .state .Prepare (rules , msg .From , st .evm .Context .Coinbase , msg .To , vm .ActivePrecompiles (rules ), msg .AccessList )
441
469
470
+ if ! contractCreation {
471
+ // Increment the nonce for the next transaction
472
+ st .state .SetNonce (msg .From , st .state .GetNonce (sender .Address ())+ 1 )
473
+ }
474
+
475
+ // Check authorizations list validity.
476
+ if msg .AuthList != nil {
477
+ for _ , auth := range msg .AuthList {
478
+ // Verify chain ID is 0 or equal to current chain ID.
479
+ if auth .ChainID .Sign () != 0 && st .evm .ChainConfig ().ChainID .Cmp (auth .ChainID ) != 0 {
480
+ continue
481
+ }
482
+ authority , err := auth .Authority ()
483
+ if err != nil {
484
+ continue
485
+ }
486
+ // Check the authority account 1) doesn't have code or has exisiting
487
+ // delegation 2) matches the auth's nonce
488
+ st .state .AddAddressToAccessList (authority )
489
+ code := st .state .GetCode (authority )
490
+ if _ , ok := types .ParseDelegation (code ); len (code ) != 0 && ! ok {
491
+ continue
492
+ }
493
+ if have := st .state .GetNonce (authority ); have != auth .Nonce {
494
+ continue
495
+ }
496
+ // If the account already exists in state, refund the new account cost
497
+ // charged in the initrinsic calculation.
498
+ if exists := st .state .Exist (authority ); exists {
499
+ st .state .AddRefund (params .CallNewAccountGas - params .TxAuthTupleGas )
500
+ }
501
+ st .state .SetNonce (authority , auth .Nonce + 1 )
502
+ st .state .SetCode (authority , types .AddressToDelegation (auth .Address ))
503
+ }
504
+ }
505
+
442
506
var (
443
507
ret []byte
444
508
vmerr error // vm errors do not effect consensus and are therefore not assigned to err
445
509
)
446
510
if contractCreation {
447
511
ret , _ , st .gasRemaining , vmerr = st .evm .Create (sender , msg .Data , st .gasRemaining , value )
448
512
} else {
449
- // Increment the nonce for the next transaction
450
- st .state .SetNonce (msg .From , st .state .GetNonce (sender .Address ())+ 1 )
451
513
ret , st .gasRemaining , vmerr = st .evm .Call (sender , st .to (), msg .Data , st .gasRemaining , value )
452
514
}
453
515
0 commit comments