Merge pull request #14 from eth-infinitism/test-deployer-flows

AA-379 Test deployer flows
This commit is contained in:
shahafn 2024-07-11 17:14:04 +03:00 committed by GitHub
commit 2312c4fdde
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 142 additions and 15 deletions

View file

@ -177,8 +177,9 @@ func CheckNonceRip7560(tx *types.Rip7560AccountAbstractionTx, st *state.StateDB)
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)
sender := tx.Rip7560TransactionData().Sender
txContext := vm.TxContext{
Origin: *tx.Rip7560TransactionData().Sender,
Origin: *sender,
GasPrice: tx.GasFeeCap(),
}
evm := vm.NewEVM(blockContext, txContext, statedb, chainConfig, cfg)
@ -186,16 +187,25 @@ func ApplyRip7560ValidationPhases(chainConfig *params.ChainConfig, bc ChainConte
deployerMsg := prepareDeployerMessage(tx, chainConfig)
var deploymentUsedGas uint64
if deployerMsg != nil {
resultDeployer, err := ApplyMessage(evm, deployerMsg, gp)
var err error
var resultDeployer *ExecutionResult
if statedb.GetCodeSize(*sender) != 0 {
err = errors.New("sender already deployed")
} else {
resultDeployer, err = ApplyMessage(evm, deployerMsg, gp)
}
if err == nil && resultDeployer != nil {
err = resultDeployer.Err
deploymentUsedGas = resultDeployer.UsedGas
}
if err == nil && statedb.GetCodeSize(*sender) == 0 {
err = errors.New("sender not deployed")
}
if err != nil {
return nil, err
// TODO: bubble up the inner error message to the user, if possible
return nil, fmt.Errorf("account deployment failed: %v", err)
}
statedb.IntermediateRoot(true)
if resultDeployer.Failed() {
// TODO: bubble up the inner error message to the user, if possible
return nil, errors.New("account deployment failed - invalid transaction")
}
deploymentUsedGas = resultDeployer.UsedGas
}
/*** Account Validation Frame ***/
@ -338,19 +348,18 @@ func ApplyRip7560ExecutionPhase(config *params.ChainConfig, vpr *ValidationPhase
func prepareDeployerMessage(baseTx *types.Transaction, config *params.ChainConfig) *Message {
tx := baseTx.Rip7560TransactionData()
if len(tx.DeployerData) < 20 {
if tx.Deployer == nil {
return nil
}
var deployerAddress common.Address = [20]byte(tx.DeployerData[0:20])
return &Message{
From: config.DeployerCallerAddress,
To: &deployerAddress,
To: tx.Deployer,
Value: big.NewInt(0),
GasLimit: tx.ValidationGas,
GasPrice: tx.GasFeeCap,
GasFeeCap: tx.GasFeeCap,
GasTipCap: tx.GasTipCap,
Data: tx.DeployerData[20:],
Data: tx.DeployerData,
AccessList: make(types.AccessList, 0),
SkipAccountChecks: true,
IsRip7560Frame: true,

View file

@ -0,0 +1,88 @@
package rip7560
import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"math/big"
"testing"
)
var DEPLOYER = common.HexToAddress("0xddddddddddeeeeeeeeeeddddddddddeeeeeeeeee")
func TestValidationFailure_deployerRevert(t *testing.T) {
handleTransaction(newTestContextBuilder(t).
withCode(DEFAULT_SENDER, []byte{}, DEFAULT_BALANCE).
withCode(DEPLOYER.Hex(), revertWithData([]byte{}), 0),
types.Rip7560AccountAbstractionTx{
Deployer: &DEPLOYER,
ValidationGas: 1000000000,
GasFeeCap: big.NewInt(1000000000),
}, "account deployment failed: execution reverted")
}
func TestValidationFailure_deployerOOG(t *testing.T) {
handleTransaction(newTestContextBuilder(t).
withCode(DEFAULT_SENDER, []byte{}, DEFAULT_BALANCE).
withCode(DEPLOYER.Hex(), revertWithData([]byte{}), 0),
types.Rip7560AccountAbstractionTx{
Deployer: &DEPLOYER,
ValidationGas: 1,
GasFeeCap: big.NewInt(1000000000),
}, "account deployment failed: out of gas")
}
func TestValidationFailure_senderNotDeployed(t *testing.T) {
handleTransaction(newTestContextBuilder(t).
withCode(DEFAULT_SENDER, []byte{}, DEFAULT_BALANCE).
withCode(DEPLOYER.Hex(), returnWithData([]byte{}), 0),
types.Rip7560AccountAbstractionTx{
Deployer: &DEPLOYER,
ValidationGas: 1000000000,
GasFeeCap: big.NewInt(1000000000),
}, "account deployment failed: sender not deployed")
}
func TestValidationFailure_senderAlreadyDeployed(t *testing.T) {
accountCode := revertWithData([]byte{})
deployerCode := create2(accountCode)
sender := create2_addr(DEPLOYER, accountCode)
handleTransaction(newTestContextBuilder(t).
withCode(sender.Hex(), accountCode, DEFAULT_BALANCE).
withCode(DEPLOYER.Hex(), deployerCode, 0),
types.Rip7560AccountAbstractionTx{
Sender: &sender,
Deployer: &DEPLOYER,
ValidationGas: 1000000000,
GasFeeCap: big.NewInt(1000000000),
}, "account deployment failed: sender already deployed")
}
func TestValidationFailure_senderReverts(t *testing.T) {
accountCode := revertWithData([]byte{})
deployerCode := createCode(create2(accountCode), returnWithData([]byte{}))
sender := create2_addr(DEPLOYER, accountCode)
handleTransaction(newTestContextBuilder(t).
withCode(sender.Hex(), []byte{}, DEFAULT_BALANCE).
withCode(DEPLOYER.Hex(), deployerCode, 0),
types.Rip7560AccountAbstractionTx{
Sender: &sender,
Deployer: &DEPLOYER,
ValidationGas: 1000000000,
GasFeeCap: big.NewInt(1000000000),
}, "execution reverted")
}
func TestValidation_deployer_ok(t *testing.T) {
accountCode := createAccountCode()
deployerCode := createCode(create2(accountCode), returnWithData([]byte{}))
sender := create2_addr(DEPLOYER, accountCode)
handleTransaction(newTestContextBuilder(t).
withCode(sender.Hex(), []byte{}, DEFAULT_BALANCE).
withCode(DEPLOYER.Hex(), deployerCode, 0),
types.Rip7560AccountAbstractionTx{
Sender: &sender,
Deployer: &DEPLOYER,
ValidationGas: 1000000000,
GasFeeCap: big.NewInt(1000000000),
}, "ok")
}

View file

@ -8,6 +8,7 @@ import (
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/internal/ethapi"
"github.com/status-im/keycard-go/hexutils"
"math/big"
@ -45,6 +46,31 @@ func newTestContextBuilder(t *testing.T) *testContextBuilder {
}
}
// return a contract code that will deploy the given code
func create2_contract(deployedCode []byte) []byte {
return returnWithData(deployedCode)
}
// return the generated address when deploying the given code
func create2_addr(deployer common.Address, deployedCode []byte) common.Address {
contractCode := create2_contract(deployedCode)
data := createCode(0xff, deployer.Bytes(), common.Hash{}, crypto.Keccak256(contractCode))
return common.BytesToAddress(crypto.Keccak256(data))
}
// generate code to call create2
// note: parameter is the deployed code, not the full contract code
// always use zero value and zero salt.
func create2(deployedCode []byte) []byte {
contractCode := create2_contract(deployedCode)
return createCode(
copyToMemory(contractCode, 0),
push(0), push(len(contractCode)), push(0), push(0), vm.CREATE2,
)
}
func (tb *testContextBuilder) build() *testContext {
genesis := core.DeveloperGenesisBlock(10_000_000, &common.Address{})
genesis.Timestamp = 100
@ -69,7 +95,6 @@ func (tt *testContextBuilder) withAccount(addr string, balance int64) *testConte
tt.genesisAlloc[common.HexToAddress(addr)] = types.Account{Balance: big.NewInt(balance)}
return tt
}
func (tt *testContextBuilder) withCode(addr string, code []byte, balance int64) *testContextBuilder {
if len(code) == 0 {
tt.genesisAlloc[common.HexToAddress(addr)] = types.Account{
@ -113,8 +138,9 @@ func copyToMemory(data []byte, offset uint) []byte {
}
if len(data) > 0 {
PUSHn := byte(int(vm.PUSH0) + len(data))
ret = append(ret, createCode(PUSHn, data, vm.PUSH2, uint16(offset), vm.MSTORE)...)
//push data up, as EVM is big-endian
v := common.RightPadBytes(data, 32)
ret = append(ret, createCode(vm.PUSH32, v, vm.PUSH2, uint16(offset), vm.MSTORE)...)
}
return ret
}
@ -160,6 +186,10 @@ func createCode(items ...interface{}) []byte {
panic(fmt.Errorf("int defaults to int8 (byte). use int16, etc: %v", v))
}
buffer.WriteByte(byte(v))
case common.Hash:
buffer.Write(v.Bytes())
case common.Address:
buffer.Write(v.Bytes())
default:
// should be a compile-time error...
panic(fmt.Errorf("unsupported type: %T", v))