mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-19 18:32:23 +00:00
Merge pull request #12 from eth-infinitism/test-flows
AA-343 Test account flows, align with RIP
This commit is contained in:
commit
1fc0bd420e
5 changed files with 179 additions and 67 deletions
|
|
@ -1,7 +1,6 @@
|
||||||
package core
|
package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/ethereum/go-ethereum/accounts/abi"
|
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||||
|
|
@ -15,6 +14,36 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const MAGIC_VALUE_SENDER = uint64(0xbf45c166)
|
||||||
|
const MAGIC_VALUE_PAYMASTER = uint64(0xe0e6183a)
|
||||||
|
const MAGIC_VALUE_SIGFAIL = uint64(0x31665494)
|
||||||
|
const PAYMASTER_MAX_CONTEXT_SIZE = 65536
|
||||||
|
|
||||||
|
func PackValidationData(authorizerMagic uint64, validUntil, validAfter uint64) []byte {
|
||||||
|
|
||||||
|
t := new(big.Int).SetUint64(uint64(validAfter))
|
||||||
|
t = t.Lsh(t, 48).Add(t, new(big.Int).SetUint64(validUntil&0xffffff))
|
||||||
|
t = t.Lsh(t, 160).Add(t, new(big.Int).SetUint64(uint64(authorizerMagic)))
|
||||||
|
return common.LeftPadBytes(t.Bytes(), 32)
|
||||||
|
}
|
||||||
|
|
||||||
|
func UnpackValidationData(validationData []byte) (authorizerMagic uint64, validUntil, validAfter uint64) {
|
||||||
|
|
||||||
|
t := new(big.Int).SetBytes(validationData)
|
||||||
|
authorizerMagic = t.Uint64()
|
||||||
|
validUntil = t.Rsh(t, 160).Uint64() & 0xffffff
|
||||||
|
validAfter = t.Rsh(t, 48).Uint64()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func UnpackPaymasterValidationReturn(paymasterValidationReturn []byte) (validationData, context []byte) {
|
||||||
|
validationData = paymasterValidationReturn[0:32]
|
||||||
|
//2nd bytes32 is ignored (its an offset value)
|
||||||
|
contextLen := new(big.Int).SetBytes(paymasterValidationReturn[64:96])
|
||||||
|
context = paymasterValidationReturn[96 : 96+contextLen.Uint64()]
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
type ValidationPhaseResult struct {
|
type ValidationPhaseResult struct {
|
||||||
TxIndex int
|
TxIndex int
|
||||||
Tx *types.Transaction
|
Tx *types.Transaction
|
||||||
|
|
@ -59,11 +88,16 @@ func handleRip7560Transactions(transactions []*types.Transaction, index int, sta
|
||||||
|
|
||||||
aatx := tx.Rip7560TransactionData()
|
aatx := tx.Rip7560TransactionData()
|
||||||
statedb.SetTxContext(tx.Hash(), index+i)
|
statedb.SetTxContext(tx.Hash(), index+i)
|
||||||
err := BuyGasRip7560Transaction(aatx, statedb)
|
err := CheckNonceRip7560(aatx, statedb)
|
||||||
var vpr *ValidationPhaseResult
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, err
|
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)
|
vpr, err = ApplyRip7560ValidationPhases(chainConfig, bc, coinbase, gp, statedb, header, tx, cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, err
|
return nil, nil, nil, err
|
||||||
|
|
@ -113,6 +147,24 @@ func BuyGasRip7560Transaction(st *types.Rip7560AccountAbstractionTx, state vm.St
|
||||||
return nil
|
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) {
|
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)
|
blockContext := NewEVMBlockContext(header, bc, author)
|
||||||
txContext := vm.TxContext{
|
txContext := vm.TxContext{
|
||||||
|
|
@ -399,45 +451,30 @@ func preparePostOpMessage(vpr *ValidationPhaseResult, chainConfig *params.ChainC
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateAccountReturnData(data []byte) (uint64, uint64, error) {
|
func validateAccountReturnData(data []byte) (uint64, uint64, error) {
|
||||||
MAGIC_VALUE_SENDER := uint32(0xbf45c166)
|
|
||||||
if len(data) != 32 {
|
if len(data) != 32 {
|
||||||
return 0, 0, errors.New("invalid account return data length")
|
return 0, 0, errors.New("invalid account return data length")
|
||||||
}
|
}
|
||||||
magicExpected := binary.BigEndian.Uint32(data[:4])
|
magicExpected, validUntil, validAfter := UnpackValidationData(data)
|
||||||
|
//todo: we check first 8 bytes of the 20-byte address (the rest is expected to be zeros)
|
||||||
if magicExpected != MAGIC_VALUE_SENDER {
|
if magicExpected != MAGIC_VALUE_SENDER {
|
||||||
|
if magicExpected == MAGIC_VALUE_SIGFAIL {
|
||||||
|
return 0, 0, errors.New("account signature error")
|
||||||
|
}
|
||||||
return 0, 0, errors.New("account did not return correct MAGIC_VALUE")
|
return 0, 0, errors.New("account did not return correct MAGIC_VALUE")
|
||||||
}
|
}
|
||||||
validAfter := binary.BigEndian.Uint64(data[4:12])
|
|
||||||
validUntil := binary.BigEndian.Uint64(data[12:20])
|
|
||||||
return validAfter, validUntil, nil
|
return validAfter, validUntil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func validatePaymasterReturnData(data []byte) ([]byte, uint64, uint64, error) {
|
func validatePaymasterReturnData(data []byte) (context []byte, validAfter, validUntil uint64, error error) {
|
||||||
MAGIC_VALUE_PAYMASTER := uint32(0xe0e6183a)
|
if len(data) < 32 {
|
||||||
if len(data) < 4 {
|
|
||||||
return nil, 0, 0, errors.New("invalid paymaster return data length")
|
return nil, 0, 0, errors.New("invalid paymaster return data length")
|
||||||
}
|
}
|
||||||
magicExpected := binary.BigEndian.Uint32(data[:4])
|
validationData, context := UnpackPaymasterValidationReturn(data)
|
||||||
|
magicExpected, validAfter, validUntil := UnpackValidationData(validationData)
|
||||||
if magicExpected != MAGIC_VALUE_PAYMASTER {
|
if magicExpected != MAGIC_VALUE_PAYMASTER {
|
||||||
return nil, 0, 0, errors.New("paymaster did not return correct MAGIC_VALUE")
|
return nil, 0, 0, errors.New("paymaster did not return correct MAGIC_VALUE")
|
||||||
}
|
}
|
||||||
|
return context, validAfter, validUntil, nil
|
||||||
jsondata := `[
|
|
||||||
{"type":"function","name":"validatePaymasterTransaction","outputs": [{"name": "context","type": "bytes"},{"name": "validUntil","type": "uint256"},{"name": "validAfter","type": "uint256"}]}
|
|
||||||
]`
|
|
||||||
validatePaymasterTransactionAbi, err := abi.JSON(strings.NewReader(jsondata))
|
|
||||||
if err != nil {
|
|
||||||
// todo: wrap error message
|
|
||||||
return nil, 0, 0, err
|
|
||||||
}
|
|
||||||
decodedPmReturnData, err := validatePaymasterTransactionAbi.Unpack("validatePaymasterTransaction", data[4:])
|
|
||||||
if err != nil {
|
|
||||||
return nil, 0, 0, err
|
|
||||||
}
|
|
||||||
context := decodedPmReturnData[0].([]byte)
|
|
||||||
validAfter := decodedPmReturnData[1].(*big.Int)
|
|
||||||
validUntil := decodedPmReturnData[2].(*big.Int)
|
|
||||||
return context, validAfter.Uint64(), validUntil.Uint64(), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateValidityTimeRange(time uint64, validAfter uint64, validUntil uint64) error {
|
func validateValidityTimeRange(time uint64, validAfter uint64, validUntil uint64) error {
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,7 @@ func (tx *Rip7560AccountAbstractionTx) copy() TxData {
|
||||||
cpy := &Rip7560AccountAbstractionTx{
|
cpy := &Rip7560AccountAbstractionTx{
|
||||||
To: copyAddressPtr(tx.To),
|
To: copyAddressPtr(tx.To),
|
||||||
Data: common.CopyBytes(tx.Data),
|
Data: common.CopyBytes(tx.Data),
|
||||||
|
Nonce: tx.Nonce,
|
||||||
Gas: tx.Gas,
|
Gas: tx.Gas,
|
||||||
// These are copied below.
|
// These are copied below.
|
||||||
AccessList: make(AccessList, len(tx.AccessList)),
|
AccessList: make(AccessList, len(tx.AccessList)),
|
||||||
|
|
|
||||||
|
|
@ -48,9 +48,7 @@ func TestProcess1(t *testing.T) {
|
||||||
Data: []byte{1, 2, 3},
|
Data: []byte{1, 2, 3},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
if err != nil {
|
assert.NoError(t, err)
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// run a set of AA transactions, with a legacy TXs before and after.
|
// run a set of AA transactions, with a legacy TXs before and after.
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const DEFAULT_SENDER = "0x1111111111222222222233333333334444444444"
|
const DEFAULT_SENDER = "0x1111111111222222222233333333334444444444"
|
||||||
|
const DEFAULT_BALANCE = 1 << 62
|
||||||
|
|
||||||
type testContext struct {
|
type testContext struct {
|
||||||
genesisAlloc types.GenesisAlloc
|
genesisAlloc types.GenesisAlloc
|
||||||
|
|
@ -45,6 +46,7 @@ func newTestContextBuilder(t *testing.T) *testContextBuilder {
|
||||||
|
|
||||||
func (tb *testContextBuilder) build() *testContext {
|
func (tb *testContextBuilder) build() *testContext {
|
||||||
genesis := core.DeveloperGenesisBlock(10_000_000, &common.Address{})
|
genesis := core.DeveloperGenesisBlock(10_000_000, &common.Address{})
|
||||||
|
genesis.Timestamp = 100
|
||||||
genesisBlock := genesis.ToBlock()
|
genesisBlock := genesis.ToBlock()
|
||||||
gaspool := new(core.GasPool).AddGas(genesisBlock.GasLimit())
|
gaspool := new(core.GasPool).AddGas(genesisBlock.GasLimit())
|
||||||
|
|
||||||
|
|
@ -83,26 +85,18 @@ func (tt *testContextBuilder) withCode(addr string, code []byte, balance int64)
|
||||||
|
|
||||||
// generate the code to return the given byte array (up to 32 bytes)
|
// generate the code to return the given byte array (up to 32 bytes)
|
||||||
func returnData(data []byte) []byte {
|
func returnData(data []byte) []byte {
|
||||||
//couldn't get geth to support PUSH0 ...
|
|
||||||
datalen := len(data)
|
datalen := len(data)
|
||||||
if datalen == 0 {
|
|
||||||
data = []byte{0}
|
|
||||||
}
|
|
||||||
if datalen > 32 {
|
if datalen > 32 {
|
||||||
panic(fmt.Errorf("data length is too big %v", data))
|
panic(fmt.Errorf("data length is too big %v", data))
|
||||||
}
|
}
|
||||||
|
|
||||||
PUSHn := byte(int(vm.PUSH0) + datalen)
|
PUSHn := byte(int(vm.PUSH0) + datalen)
|
||||||
ret := createCode(PUSHn, data, vm.PUSH1, 0, vm.MSTORE, vm.PUSH1, 32, vm.PUSH1, 0, vm.RETURN)
|
ret := createCode(PUSHn, data, vm.PUSH0, vm.MSTORE, vm.PUSH1, datalen, vm.PUSH1, 0, vm.RETURN)
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
// create bytecode for account
|
|
||||||
func createAccountCode() []byte {
|
func createAccountCode() []byte {
|
||||||
magic := big.NewInt(0xbf45c166)
|
return returnData(core.PackValidationData(core.MAGIC_VALUE_SENDER, 0, 0))
|
||||||
magic.Lsh(magic, 256-32)
|
|
||||||
|
|
||||||
return returnData(magic.Bytes())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// create EVM code from OpCode, byte and []bytes
|
// create EVM code from OpCode, byte and []bytes
|
||||||
|
|
|
||||||
|
|
@ -13,51 +13,132 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestValidation_OOG(t *testing.T) {
|
func TestPackValidationData(t *testing.T) {
|
||||||
magic := big.NewInt(0xbf45c166)
|
// --------------- after 6bytes before 6 bytes magic 20 bytes
|
||||||
magic.Lsh(magic, 256-32)
|
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))
|
||||||
|
}
|
||||||
|
|
||||||
validatePhase(newTestContextBuilder(t).withCode(DEFAULT_SENDER, returnData(magic.Bytes()), 0), types.Rip7560AccountAbstractionTx{
|
func TestUnpackValidationData(t *testing.T) {
|
||||||
|
packed := core.PackValidationData(0xdead, 0xcafe, 0xface)
|
||||||
|
magic, until, after := core.UnpackValidationData(packed)
|
||||||
|
assert.Equal(t, []uint64{0xdead, 0xcafe, 0xface}, []uint64{magic, until, after})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestValidationFailure_OOG(t *testing.T) {
|
||||||
|
|
||||||
|
handleTransaction(newTestContextBuilder(t).withCode(DEFAULT_SENDER, createAccountCode(), DEFAULT_BALANCE), types.Rip7560AccountAbstractionTx{
|
||||||
ValidationGas: uint64(1),
|
ValidationGas: uint64(1),
|
||||||
GasFeeCap: big.NewInt(1000000000),
|
GasFeeCap: big.NewInt(1000000000),
|
||||||
}, "out of gas")
|
}, "out of gas")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestValidation_ok(t *testing.T) {
|
func TestValidationFailure_no_balance(t *testing.T) {
|
||||||
|
|
||||||
validatePhase(newTestContextBuilder(t).withCode(DEFAULT_SENDER, createAccountCode(), 0), types.Rip7560AccountAbstractionTx{
|
handleTransaction(newTestContextBuilder(t).withCode(DEFAULT_SENDER, createAccountCode(), 1), types.Rip7560AccountAbstractionTx{
|
||||||
ValidationGas: uint64(1000000000),
|
ValidationGas: uint64(1),
|
||||||
GasFeeCap: big.NewInt(1000000000),
|
GasFeeCap: big.NewInt(1000000000),
|
||||||
}, "")
|
}, "insufficient funds for gas * price + value: address 0x1111111111222222222233333333334444444444 have 1 want 1000000000")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestValidation_account_revert(t *testing.T) {
|
func TestValidationFailure_sigerror(t *testing.T) {
|
||||||
validatePhase(newTestContextBuilder(t).withCode(DEFAULT_SENDER,
|
handleTransaction(newTestContextBuilder(t).withCode(DEFAULT_SENDER, returnData(core.PackValidationData(core.MAGIC_VALUE_SIGFAIL, 0, 0)), DEFAULT_BALANCE), types.Rip7560AccountAbstractionTx{
|
||||||
createCode(vm.PUSH1, 0, vm.DUP1, vm.REVERT), 0), types.Rip7560AccountAbstractionTx{
|
ValidationGas: uint64(1000000000),
|
||||||
|
GasFeeCap: big.NewInt(1000000000),
|
||||||
|
}, "account signature error")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestValidationFailure_validAfter(t *testing.T) {
|
||||||
|
|
||||||
|
handleTransaction(newTestContextBuilder(t).withCode(DEFAULT_SENDER,
|
||||||
|
returnData(core.PackValidationData(core.MAGIC_VALUE_SENDER, 300, 200)), DEFAULT_BALANCE), types.Rip7560AccountAbstractionTx{
|
||||||
|
ValidationGas: uint64(1000000000),
|
||||||
|
GasFeeCap: big.NewInt(1000000000),
|
||||||
|
}, "RIP-7560 transaction validity not reached yet")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestValidationFailure_validUntil(t *testing.T) {
|
||||||
|
|
||||||
|
handleTransaction(newTestContextBuilder(t).withCode(DEFAULT_SENDER,
|
||||||
|
returnData(core.PackValidationData(core.MAGIC_VALUE_SENDER, 1, 0)), DEFAULT_BALANCE), types.Rip7560AccountAbstractionTx{
|
||||||
|
ValidationGas: uint64(1000000000),
|
||||||
|
GasFeeCap: big.NewInt(1000000000),
|
||||||
|
}, "RIP-7560 transaction validity expired")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestValidation_ok(t *testing.T) {
|
||||||
|
|
||||||
|
handleTransaction(newTestContextBuilder(t).withCode(DEFAULT_SENDER, createAccountCode(), DEFAULT_BALANCE), types.Rip7560AccountAbstractionTx{
|
||||||
|
ValidationGas: uint64(1000000000),
|
||||||
|
GasFeeCap: big.NewInt(1000000000),
|
||||||
|
}, "ok")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestValidation_ok_paid(t *testing.T) {
|
||||||
|
|
||||||
|
aatx := types.Rip7560AccountAbstractionTx{
|
||||||
|
ValidationGas: uint64(1000000000),
|
||||||
|
GasFeeCap: big.NewInt(1000000000),
|
||||||
|
}
|
||||||
|
tb := newTestContextBuilder(t).withCode(DEFAULT_SENDER, createAccountCode(), DEFAULT_BALANCE)
|
||||||
|
handleTransaction(tb, aatx, "ok")
|
||||||
|
|
||||||
|
maxCost := new(big.Int).SetUint64(aatx.ValidationGas + aatx.PaymasterGas + aatx.Gas)
|
||||||
|
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{
|
||||||
ValidationGas: uint64(1000000000),
|
ValidationGas: uint64(1000000000),
|
||||||
GasFeeCap: big.NewInt(1000000000),
|
GasFeeCap: big.NewInt(1000000000),
|
||||||
}, "execution reverted")
|
}, "execution reverted")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestValidation_account_no_return_value(t *testing.T) {
|
func TestValidationFailure_account_out_of_range(t *testing.T) {
|
||||||
validatePhase(newTestContextBuilder(t).withCode(DEFAULT_SENDER, []byte{
|
handleTransaction(newTestContextBuilder(t).withCode(DEFAULT_SENDER,
|
||||||
byte(vm.PUSH1), 0, byte(vm.DUP1), byte(vm.RETURN),
|
createCode(vm.PUSH0, vm.DUP1, vm.REVERT), DEFAULT_BALANCE), types.Rip7560AccountAbstractionTx{
|
||||||
}, 0), types.Rip7560AccountAbstractionTx{
|
ValidationGas: uint64(1000000000),
|
||||||
|
GasFeeCap: big.NewInt(1000000000),
|
||||||
|
}, "execution reverted")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestValidationFailure_account_wrong_return_length(t *testing.T) {
|
||||||
|
handleTransaction(newTestContextBuilder(t).withCode(DEFAULT_SENDER,
|
||||||
|
returnData([]byte{1, 2, 3}), DEFAULT_BALANCE), types.Rip7560AccountAbstractionTx{
|
||||||
ValidationGas: uint64(1000000000),
|
ValidationGas: uint64(1000000000),
|
||||||
GasFeeCap: big.NewInt(1000000000),
|
GasFeeCap: big.NewInt(1000000000),
|
||||||
}, "invalid account return data length")
|
}, "invalid account return data length")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestValidation_account_wrong_return_value(t *testing.T) {
|
func TestValidationFailure_account_no_return_value(t *testing.T) {
|
||||||
validatePhase(newTestContextBuilder(t).withCode(DEFAULT_SENDER,
|
handleTransaction(newTestContextBuilder(t).withCode(DEFAULT_SENDER,
|
||||||
returnData(createCode(1)),
|
returnData([]byte{}), DEFAULT_BALANCE), types.Rip7560AccountAbstractionTx{
|
||||||
0), types.Rip7560AccountAbstractionTx{
|
ValidationGas: uint64(1000000000),
|
||||||
|
GasFeeCap: big.NewInt(1000000000),
|
||||||
|
}, "invalid account return data length")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestValidationFailure_account_wrong_return_value(t *testing.T) {
|
||||||
|
// create buffer of 32 byte array
|
||||||
|
handleTransaction(newTestContextBuilder(t).withCode(DEFAULT_SENDER,
|
||||||
|
returnData(make([]byte, 32)),
|
||||||
|
DEFAULT_BALANCE), types.Rip7560AccountAbstractionTx{
|
||||||
ValidationGas: uint64(1000000000),
|
ValidationGas: uint64(1000000000),
|
||||||
GasFeeCap: big.NewInt(1000000000),
|
GasFeeCap: big.NewInt(1000000000),
|
||||||
}, "account did not return correct MAGIC_VALUE")
|
}, "account did not return correct MAGIC_VALUE")
|
||||||
}
|
}
|
||||||
|
|
||||||
func validatePhase(tb *testContextBuilder, aatx types.Rip7560AccountAbstractionTx, expectedErr string) {
|
func handleTransaction(tb *testContextBuilder, aatx types.Rip7560AccountAbstractionTx, expectedErr string) {
|
||||||
t := tb.build()
|
t := tb.build()
|
||||||
if aatx.Sender == nil {
|
if aatx.Sender == nil {
|
||||||
//pre-deployed sender account
|
//pre-deployed sender account
|
||||||
|
|
@ -69,9 +150,10 @@ func validatePhase(tb *testContextBuilder, aatx types.Rip7560AccountAbstractionT
|
||||||
var state = tests.MakePreState(rawdb.NewMemoryDatabase(), t.genesisAlloc, false, rawdb.HashScheme)
|
var state = tests.MakePreState(rawdb.NewMemoryDatabase(), t.genesisAlloc, false, rawdb.HashScheme)
|
||||||
defer state.Close()
|
defer state.Close()
|
||||||
|
|
||||||
_, err := core.ApplyRip7560ValidationPhases(t.genesis.Config, t.chainContext, &common.Address{}, t.gaspool, state.StateDB, t.genesisBlock.Header(), tx, vm.Config{})
|
state.StateDB.SetTxContext(tx.Hash(), 0)
|
||||||
// err string or empty if nil
|
_, _, _, err := core.HandleRip7560Transactions([]*types.Transaction{tx}, 0, state.StateDB, &common.Address{}, t.genesisBlock.Header(), t.gaspool, t.genesis.Config, t.chainContext, vm.Config{})
|
||||||
errStr := ""
|
|
||||||
|
errStr := "ok"
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errStr = err.Error()
|
errStr = err.Error()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue