Remove code related to EOA-based RIP-7560 transactions

This commit is contained in:
Alex Forshtat 2024-04-30 15:14:21 +02:00 committed by Dror Tirosh
parent bcca728d62
commit 75fd756a25
6 changed files with 116 additions and 96 deletions

View file

@ -27,7 +27,6 @@ type ValidationPhaseResult struct {
SenderValidUntil uint64 SenderValidUntil uint64
PmValidAfter uint64 PmValidAfter uint64
PmValidUntil uint64 PmValidUntil uint64
IsEOA bool
} }
// HandleRip7560Transactions apply state changes of all sequential RIP-7560 transactions and return // HandleRip7560Transactions apply state changes of all sequential RIP-7560 transactions and return
@ -38,22 +37,13 @@ func HandleRip7560Transactions(transactions []*types.Transaction, index int, sta
receipts := make([]*types.Receipt, 0) receipts := make([]*types.Receipt, 0)
allLogs := make([]*types.Log, 0) allLogs := make([]*types.Log, 0)
i := index iTransactions, iReceipts, iLogs, err := handleRip7560Transactions(transactions, index, statedb, coinbase, header, gp, chainConfig, bc, cfg)
for { if err != nil {
if i >= len(transactions) { return nil, nil, nil, err
break
}
if transactions[i].Type() != types.Rip7560Type {
break
}
iTransactions, iReceipts, iLogs, err := handleRip7560Transactions(transactions, index, statedb, coinbase, header, gp, chainConfig, bc, cfg)
if err != nil {
return nil, nil, nil, err
}
validatedTransactions = append(validatedTransactions, iTransactions...)
receipts = append(receipts, iReceipts...)
allLogs = append(allLogs, iLogs...)
} }
validatedTransactions = append(validatedTransactions, iTransactions...)
receipts = append(receipts, iReceipts...)
allLogs = append(allLogs, iLogs...)
return validatedTransactions, receipts, allLogs, nil return validatedTransactions, receipts, allLogs, nil
} }
@ -62,47 +52,31 @@ func handleRip7560Transactions(transactions []*types.Transaction, index int, sta
validatedTransactions := make([]*types.Transaction, 0) validatedTransactions := make([]*types.Transaction, 0)
receipts := make([]*types.Receipt, 0) receipts := make([]*types.Receipt, 0)
allLogs := make([]*types.Log, 0) allLogs := make([]*types.Log, 0)
signer := types.MakeSigner(chainConfig, header.Number, header.Time)
for i, tx := range transactions[index:] { for i, tx := range transactions[index:] {
if tx.Type() != types.Rip7560Type { if tx.Type() != types.Rip7560Type {
break break
} }
aatx := tx.Rip7560TransactionData() aatx := tx.Rip7560TransactionData()
isEoa, err := isTransactionEOA(tx, statedb, signer) statedb.SetTxContext(tx.Hash(), index+i)
err := BuyGasRip7560Transaction(aatx, statedb)
var vpr *ValidationPhaseResult
if err != nil { if err != nil {
return nil, nil, nil, err return nil, nil, nil, err
} }
statedb.SetTxContext(tx.Hash(), index+i) vpr, err = ApplyRip7560ValidationPhases(chainConfig, bc, coinbase, gp, statedb, header, tx, cfg)
err = BuyGasRip7560Transaction(aatx, statedb) if err != nil {
var vpr *ValidationPhaseResult return nil, nil, nil, err
if isEoa {
blockContext := NewEVMBlockContext(header, bc, coinbase)
tmpMsg, err := TransactionToMessage(tx, signer, header.BaseFee)
txContext := NewEVMTxContext(tmpMsg)
evm := vm.NewEVM(blockContext, txContext, statedb, chainConfig, cfg)
//signer := types.MakeSigner(chainConfig, header.Number, header.Time)
signingHash := signer.Hash(tx)
vpr, err = validateRip7560TransactionFromEOA(tx, signingHash, statedb, evm, coinbase, header, gp, chainConfig)
if err != nil {
return nil, nil, nil, err
}
} else {
if err != nil {
return nil, nil, nil, err
}
vpr, err = ApplyRip7560ValidationPhases(chainConfig, bc, coinbase, gp, statedb, header, tx, cfg)
if err != nil {
return nil, nil, nil, err
}
} }
validationPhaseResults = append(validationPhaseResults, vpr) validationPhaseResults = append(validationPhaseResults, vpr)
validatedTransactions = append(validatedTransactions, tx) validatedTransactions = append(validatedTransactions, tx)
}
for i, vpr := range validationPhaseResults { // This is the line separating the Validation and Execution phases
// It should be separated to implement the mempool-friendly AA RIP (number not assigned yet)
// for i, vpr := range validationPhaseResults
// TODO: this will miss all validation phase events - pass in 'vpr' // TODO: this will miss all validation phase events - pass in 'vpr'
statedb.SetTxContext(vpr.Tx.Hash(), i) // statedb.SetTxContext(vpr.Tx.Hash(), i)
receipt, err := ApplyRip7560ExecutionPhase(chainConfig, vpr, bc, coinbase, gp, statedb, header, cfg) receipt, err := ApplyRip7560ExecutionPhase(chainConfig, vpr, bc, coinbase, gp, statedb, header, cfg)
@ -139,49 +113,6 @@ func BuyGasRip7560Transaction(st *types.Rip7560AccountAbstractionTx, state vm.St
return nil return nil
} }
// TODO: not needed with subtype - only use to validate transaction, maybe
func isTransactionEOA(tx *types.Transaction, statedb *state.StateDB, signer types.Signer) (bool, error) {
aatx := tx.Rip7560TransactionData()
senderHasCode := statedb.GetCodeSize(*aatx.Sender) != 0 || len(aatx.DeployerData) != 0
if senderHasCode {
return false, nil
}
address, err := signer.Sender(tx)
if err != nil {
return false, err
}
if address.Cmp(*tx.Rip7560TransactionData().Sender) != 0 {
return false, errors.New("recovered signature does not match the claimed EOA sender")
}
return true, nil
}
func validateRip7560TransactionFromEOA(tx *types.Transaction, signingHash common.Hash, statedb *state.StateDB, evm *vm.EVM, coinbase *common.Address, header *types.Header, gp *GasPool, chainConfig *params.ChainConfig) (*ValidationPhaseResult, error) {
// TODO: paymaste is actually optional for eoa-type-4 -> check paymaster data len()
paymasterContext, pmValidationUsedGas, pmValidAfter, pmValidUntil, err := applyPaymasterValidationFrame(tx, chainConfig, signingHash, evm, gp, statedb, header)
if err != nil {
return nil, err
}
err = validateValidityTimeRange(header.Time, pmValidAfter, pmValidUntil)
if err != nil {
return nil, err
}
vpr := &ValidationPhaseResult{
Tx: tx,
TxHash: tx.Hash(),
PaymasterContext: paymasterContext,
DeploymentUsedGas: 0,
ValidationUsedGas: 0,
PmValidationUsedGas: pmValidationUsedGas,
SenderValidAfter: 0,
SenderValidUntil: 0,
PmValidAfter: pmValidAfter,
PmValidUntil: pmValidUntil,
IsEOA: true,
}
return vpr, nil
}
func ApplyRip7560FrameMessage(evm *vm.EVM, msg *Message, gp *GasPool) (*ExecutionResult, error) { func ApplyRip7560FrameMessage(evm *vm.EVM, msg *Message, gp *GasPool) (*ExecutionResult, error) {
return NewRip7560StateTransition(evm, msg, gp).TransitionDb() return NewRip7560StateTransition(evm, msg, gp).TransitionDb()
} }
@ -311,7 +242,6 @@ func ApplyRip7560ValidationPhases(chainConfig *params.ChainConfig, bc ChainConte
SenderValidUntil: validUntil, SenderValidUntil: validUntil,
PmValidAfter: pmValidAfter, PmValidAfter: pmValidAfter,
PmValidUntil: pmValidUntil, PmValidUntil: pmValidUntil,
IsEOA: false,
} }
return vpr, nil return vpr, nil
@ -373,15 +303,7 @@ func ApplyRip7560ExecutionPhase(config *params.ChainConfig, vpr *ValidationPhase
txContext.Origin = *vpr.Tx.Rip7560TransactionData().Sender txContext.Origin = *vpr.Tx.Rip7560TransactionData().Sender
evm := vm.NewEVM(blockContext, txContext, statedb, config, cfg) evm := vm.NewEVM(blockContext, txContext, statedb, config, cfg)
var accountExecutionMsg *Message accountExecutionMsg := prepareAccountExecutionMessage(vpr.Tx, evm.ChainConfig())
if vpr.IsEOA {
accountExecutionMsg, err = prepareEOATargetExecutionMessage(vpr.Tx)
if err != nil {
return nil, err
}
} else {
accountExecutionMsg = prepareAccountExecutionMessage(vpr.Tx, evm.ChainConfig())
}
executionResult, err := ApplyRip7560FrameMessage(evm, accountExecutionMsg, gp) executionResult, err := ApplyRip7560FrameMessage(evm, accountExecutionMsg, gp)
if err != nil { if err != nil {
return nil, err return nil, err

View file

@ -207,6 +207,8 @@ func (tx *Transaction) decodeTyped(b []byte) (TxData, error) {
inner = new(DynamicFeeTx) inner = new(DynamicFeeTx)
case BlobTxType: case BlobTxType:
inner = new(BlobTx) inner = new(BlobTx)
case Rip7560Type:
inner = new(Rip7560AccountAbstractionTx)
default: default:
return nil, ErrTxTypeNotSupported return nil, ErrTxTypeNotSupported
} }

View file

@ -40,6 +40,8 @@ type sigCache struct {
func MakeSigner(config *params.ChainConfig, blockNumber *big.Int, blockTime uint64) Signer { func MakeSigner(config *params.ChainConfig, blockNumber *big.Int, blockTime uint64) Signer {
var signer Signer var signer Signer
switch { switch {
case config.IsRIP7560(blockNumber):
signer = NewRIP7560Signer(config.ChainID)
case config.IsCancun(blockNumber, blockTime): case config.IsCancun(blockNumber, blockTime):
signer = NewCancunSigner(config.ChainID) signer = NewCancunSigner(config.ChainID)
case config.IsLondon(blockNumber): case config.IsLondon(blockNumber):

View file

@ -0,0 +1,47 @@
package types
import (
"github.com/ethereum/go-ethereum/common"
"math/big"
)
type rip7560Signer struct{ londonSigner }
func NewRIP7560Signer(chainId *big.Int) Signer {
return rip7560Signer{londonSigner{eip2930Signer{NewEIP155Signer(chainId)}}}
}
func (s rip7560Signer) Sender(tx *Transaction) (common.Address, error) {
if tx.Type() != Rip7560Type {
return s.londonSigner.Sender(tx)
}
return [20]byte{}, nil
}
// Hash returns the hash to be signed by the sender.
// It does not uniquely identify the transaction.
func (s rip7560Signer) Hash(tx *Transaction) common.Hash {
if tx.Type() != Rip7560Type {
return s.londonSigner.Hash(tx)
}
aatx := tx.Rip7560TransactionData()
return prefixedRlpHash(
tx.Type(),
[]interface{}{
s.chainId,
tx.GasTipCap(),
tx.GasFeeCap(),
tx.Gas(),
//tx.To(),
tx.Data(),
tx.AccessList(),
aatx.Sender,
aatx.PaymasterData,
aatx.DeployerData,
aatx.BuilderFee,
aatx.ValidationGas,
aatx.PaymasterGas,
aatx.BigNonce,
})
}

View file

@ -74,6 +74,17 @@ type TransactionArgs struct {
// This configures whether blobs are allowed to be passed. // This configures whether blobs are allowed to be passed.
blobSidecarAllowed bool blobSidecarAllowed bool
// Introduced by RIP-7560 Transaction
Subtype *hexutil.Uint64
Sender *common.Address `json:"sender"`
Signature *hexutil.Bytes
PaymasterData *hexutil.Bytes `json:"paymasterData"`
DeployerData *hexutil.Bytes
BuilderFee *hexutil.Big
ValidationGas *hexutil.Uint64
PaymasterGas *hexutil.Uint64
BigNonce *hexutil.Big // AA nonce is 256 bits wide
} }
// from retrieves the transaction sender address. // from retrieves the transaction sender address.
@ -472,6 +483,34 @@ func (args *TransactionArgs) ToMessage(baseFee *big.Int) *core.Message {
func (args *TransactionArgs) ToTransaction() *types.Transaction { func (args *TransactionArgs) ToTransaction() *types.Transaction {
var data types.TxData var data types.TxData
switch { switch {
case args.Sender != nil:
al := types.AccessList{}
if args.AccessList != nil {
al = *args.AccessList
}
aatx := types.Rip7560AccountAbstractionTx{
Subtype: byte(*args.Subtype),
To: &common.Address{},
ChainID: (*big.Int)(args.ChainID),
Gas: uint64(*args.Gas),
GasFeeCap: (*big.Int)(args.MaxFeePerGas),
GasTipCap: (*big.Int)(args.MaxPriorityFeePerGas),
Value: (*big.Int)(args.Value),
Data: args.data(),
AccessList: al,
// RIP-7560 parameters
Sender: args.Sender,
Signature: *args.Signature,
PaymasterData: *args.PaymasterData,
DeployerData: *args.DeployerData,
BuilderFee: (*big.Int)(args.BuilderFee),
ValidationGas: uint64(*args.ValidationGas),
PaymasterGas: uint64(*args.PaymasterGas),
BigNonce: (*big.Int)(args.BigNonce),
}
data = &aatx
hash := types.NewTx(data).Hash()
log.Error("RIP-7560 transaction created", "sender", aatx.Sender.Hex(), "hash", hash)
case args.BlobHashes != nil: case args.BlobHashes != nil:
al := types.AccessList{} al := types.AccessList{}
if args.AccessList != nil { if args.AccessList != nil {

View file

@ -173,6 +173,7 @@ var (
EIP150Block: big.NewInt(0), EIP150Block: big.NewInt(0),
EIP155Block: big.NewInt(0), EIP155Block: big.NewInt(0),
EIP158Block: big.NewInt(0), EIP158Block: big.NewInt(0),
RIP7560Block: big.NewInt(0),
ByzantiumBlock: big.NewInt(0), ByzantiumBlock: big.NewInt(0),
ConstantinopleBlock: big.NewInt(0), ConstantinopleBlock: big.NewInt(0),
PetersburgBlock: big.NewInt(0), PetersburgBlock: big.NewInt(0),
@ -336,6 +337,8 @@ type ChainConfig struct {
EIP155Block *big.Int `json:"eip155Block,omitempty"` // EIP155 HF block EIP155Block *big.Int `json:"eip155Block,omitempty"` // EIP155 HF block
EIP158Block *big.Int `json:"eip158Block,omitempty"` // EIP158 HF block EIP158Block *big.Int `json:"eip158Block,omitempty"` // EIP158 HF block
RIP7560Block *big.Int `json:"rip7560block,omitempty"` // RIP7560 HF block
ByzantiumBlock *big.Int `json:"byzantiumBlock,omitempty"` // Byzantium switch block (nil = no fork, 0 = already on byzantium) ByzantiumBlock *big.Int `json:"byzantiumBlock,omitempty"` // Byzantium switch block (nil = no fork, 0 = already on byzantium)
ConstantinopleBlock *big.Int `json:"constantinopleBlock,omitempty"` // Constantinople switch block (nil = no fork, 0 = already activated) ConstantinopleBlock *big.Int `json:"constantinopleBlock,omitempty"` // Constantinople switch block (nil = no fork, 0 = already activated)
PetersburgBlock *big.Int `json:"petersburgBlock,omitempty"` // Petersburg switch block (nil = same as Constantinople) PetersburgBlock *big.Int `json:"petersburgBlock,omitempty"` // Petersburg switch block (nil = same as Constantinople)
@ -586,6 +589,11 @@ func (c *ChainConfig) IsVerkle(num *big.Int, time uint64) bool {
return c.IsLondon(num) && isTimestampForked(c.VerkleTime, time) return c.IsLondon(num) && isTimestampForked(c.VerkleTime, time)
} }
// IsRIP7560 returns whether num is either equal to the RIP7560 fork block or greater.
func (c *ChainConfig) IsRIP7560(num *big.Int) bool {
return isBlockForked(c.RIP7560Block, num)
}
// CheckCompatible checks whether scheduled fork transitions have been imported // CheckCompatible checks whether scheduled fork transitions have been imported
// with a mismatching chain configuration. // with a mismatching chain configuration.
func (c *ChainConfig) CheckCompatible(newcfg *ChainConfig, height uint64, time uint64) *ConfigCompatError { func (c *ChainConfig) CheckCompatible(newcfg *ChainConfig, height uint64, time uint64) *ConfigCompatError {