From 702d157aef8a766def35b1f29fee3165849ed5d8 Mon Sep 17 00:00:00 2001 From: Dror Tirosh Date: Mon, 1 Jul 2024 12:56:48 +0300 Subject: [PATCH] test nonce --- core/state_processor_rip7560.go | 28 ++++++++++++++++++++++++++-- core/types/tx_rip7560.go | 7 ++++--- tests/rip7560/validation_test.go | 13 +++++++++++-- 3 files changed, 41 insertions(+), 7 deletions(-) diff --git a/core/state_processor_rip7560.go b/core/state_processor_rip7560.go index 23bced3307..27eb35a2ef 100644 --- a/core/state_processor_rip7560.go +++ b/core/state_processor_rip7560.go @@ -88,11 +88,16 @@ func handleRip7560Transactions(transactions []*types.Transaction, index int, sta aatx := tx.Rip7560TransactionData() statedb.SetTxContext(tx.Hash(), index+i) - err := BuyGasRip7560Transaction(aatx, statedb) - var vpr *ValidationPhaseResult + err := CheckNonceRip7560(aatx, statedb) if err != nil { return nil, nil, nil, err } + err = BuyGasRip7560Transaction(aatx, statedb) + if err != nil { + return nil, nil, nil, err + } + + var vpr *ValidationPhaseResult vpr, err = ApplyRip7560ValidationPhases(chainConfig, bc, coinbase, gp, statedb, header, tx, cfg) if err != nil { return nil, nil, nil, err @@ -142,6 +147,24 @@ func BuyGasRip7560Transaction(st *types.Rip7560AccountAbstractionTx, state vm.St return nil } +// precheck nonce of transaction. +// (standard preCheck function check both nonce and no-code of account) +func CheckNonceRip7560(tx *types.Rip7560AccountAbstractionTx, st *state.StateDB) error { + // Make sure this transaction's nonce is correct. + stNonce := st.GetNonce(*tx.Sender) + if msgNonce := tx.Nonce; stNonce < msgNonce { + return fmt.Errorf("%w: address %v, tx: %d state: %d", ErrNonceTooHigh, + tx.Sender.Hex(), msgNonce, stNonce) + } else if stNonce > msgNonce { + return fmt.Errorf("%w: address %v, tx: %d state: %d", ErrNonceTooLow, + tx.Sender.Hex(), msgNonce, stNonce) + } else if stNonce+1 < stNonce { + return fmt.Errorf("%w: address %v, nonce: %d", ErrNonceMax, + tx.Sender.Hex(), stNonce) + } + return nil +} + func ApplyRip7560ValidationPhases(chainConfig *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, cfg vm.Config) (*ValidationPhaseResult, error) { blockContext := NewEVMBlockContext(header, bc, author) txContext := vm.TxContext{ @@ -333,6 +356,7 @@ func prepareAccountValidationMessage(baseTx *types.Transaction, chainConfig *par return &Message{ From: chainConfig.EntryPointAddress, To: tx.Sender, + Nonce: tx.Nonce, Value: big.NewInt(0), GasLimit: tx.ValidationGas - deploymentUsedGas, GasPrice: tx.GasFeeCap, diff --git a/core/types/tx_rip7560.go b/core/types/tx_rip7560.go index 96855be3a4..76443ac078 100644 --- a/core/types/tx_rip7560.go +++ b/core/types/tx_rip7560.go @@ -55,9 +55,10 @@ type Rip7560AccountAbstractionTx struct { // copy creates a deep copy of the transaction data and initializes all fields. func (tx *Rip7560AccountAbstractionTx) copy() TxData { cpy := &Rip7560AccountAbstractionTx{ - To: copyAddressPtr(tx.To), - Data: common.CopyBytes(tx.Data), - Gas: tx.Gas, + To: copyAddressPtr(tx.To), + Data: common.CopyBytes(tx.Data), + Nonce: tx.Nonce, + Gas: tx.Gas, // These are copied below. AccessList: make(AccessList, len(tx.AccessList)), Value: new(big.Int), diff --git a/tests/rip7560/validation_test.go b/tests/rip7560/validation_test.go index cddb45a7fc..cd44610b1c 100644 --- a/tests/rip7560/validation_test.go +++ b/tests/rip7560/validation_test.go @@ -16,8 +16,9 @@ import ( func TestPackValidationData(t *testing.T) { //assert.Equal(t, make([]byte, 32), packValidationData(0, 0, 0)) //assert.Equal(t, new(big.Int).SetInt64(0x1234).Text(16), new(big.Int).SetBytes(packValidationData(0x1234, 0, 0)).Text(16)) - // ------------------------------------ bbbbbbbbbbbb-aaaaaaaaaaa-mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm - packed, _ := new(big.Int).SetString("0000000000020000000000010000000000000000000000000000000000001234", 16) + // --------------- after 6bytes before 6 bytes magic 20 bytes + validationData := "000000000002" + "000000000001" + "0000000000000000000000000000000000001234" + packed, _ := new(big.Int).SetString(validationData, 16) assert.Equal(t, packed.Text(16), new(big.Int).SetBytes(core.PackValidationData(0x1234, 1, 2)).Text(16)) } @@ -71,6 +72,14 @@ func TestValidation_ok_paid(t *testing.T) { maxCost.Mul(maxCost, aatx.GasFeeCap) } +func TestValidationFailure_account_nonce(t *testing.T) { + handleTransaction(newTestContextBuilder(t).withCode(DEFAULT_SENDER, createAccountCode(), DEFAULT_BALANCE), types.Rip7560AccountAbstractionTx{ + Nonce: 1234, + ValidationGas: uint64(1000000000), + GasFeeCap: big.NewInt(1000000000), + }, "nonce too high: address 0x1111111111222222222233333333334444444444, tx: 1234 state: 0") +} + func TestValidationFailure_account_revert(t *testing.T) { handleTransaction(newTestContextBuilder(t).withCode(DEFAULT_SENDER, createCode(vm.PUSH0, vm.DUP1, vm.REVERT), DEFAULT_BALANCE), types.Rip7560AccountAbstractionTx{