mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-19 10:22:23 +00:00
Extract ABI encoding&decoding into file; use ABI instead of manual bit parsing
This commit is contained in:
parent
144e9f9d59
commit
587a6ac534
5 changed files with 167 additions and 131 deletions
106
core/rip7560_abi.go
Normal file
106
core/rip7560_abi.go
Normal file
|
|
@ -0,0 +1,106 @@
|
||||||
|
package core
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"math/big"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const AcceptAccountMethodSig = uint64(0x1256ebd1) // acceptAccount(uint256,uint256)
|
||||||
|
const AcceptPaymasterMethodSig = uint64(0x03be8439) // acceptPaymaster(uint256,uint256,bytes)
|
||||||
|
const SigFailAccountMethodSig = uint64(0x7715fac2) // sigFailAccount(uint256,uint256)
|
||||||
|
const PaymasterMaxContextSize = 65536
|
||||||
|
|
||||||
|
func abiEncodeValidateTransaction(tx *types.Rip7560AccountAbstractionTx, signingHash common.Hash) ([]byte, error) {
|
||||||
|
jsondata := `[
|
||||||
|
{"type":"function","name":"validateTransaction","inputs": [{"name": "version","type": "uint256"},{"name": "txHash","type": "bytes32"},{"name": "transaction","type": "bytes"}]}
|
||||||
|
]`
|
||||||
|
|
||||||
|
jsonAbi, err := abi.JSON(strings.NewReader(jsondata))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
txAbiEncoding, err := tx.AbiEncode()
|
||||||
|
validateTransactionData, err := jsonAbi.Pack("validateTransaction", big.NewInt(0), signingHash, txAbiEncoding)
|
||||||
|
return validateTransactionData, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func abiEncodeValidatePaymasterTransaction(tx *types.Rip7560AccountAbstractionTx, signingHash common.Hash) ([]byte, error) {
|
||||||
|
jsondata := `[
|
||||||
|
{"type":"function","name":"validatePaymasterTransaction","inputs": [{"name": "version","type": "uint256"},{"name": "txHash","type": "bytes32"},{"name": "transaction","type": "bytes"}]}
|
||||||
|
]`
|
||||||
|
|
||||||
|
jsonAbi, err := abi.JSON(strings.NewReader(jsondata))
|
||||||
|
txAbiEncoding, err := tx.AbiEncode()
|
||||||
|
data, err := jsonAbi.Pack("validatePaymasterTransaction", big.NewInt(0), signingHash, txAbiEncoding)
|
||||||
|
return data, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func abiEncodePostPaymasterTransaction(context []byte) ([]byte, error) {
|
||||||
|
jsondata := `[
|
||||||
|
{"type":"function","name":"postPaymasterTransaction","inputs": [{"name": "success","type": "bool"},{"name": "actualGasCost","type": "uint256"},{"name": "context","type": "bytes"}]}
|
||||||
|
]`
|
||||||
|
jsonAbi, err := abi.JSON(strings.NewReader(jsondata))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
postOpData, err := jsonAbi.Pack("postPaymasterTransaction", true, big.NewInt(0), context)
|
||||||
|
return postOpData, err
|
||||||
|
}
|
||||||
|
|
||||||
|
type AcceptAccountData struct {
|
||||||
|
ValidAfter *big.Int
|
||||||
|
ValidUntil *big.Int
|
||||||
|
}
|
||||||
|
|
||||||
|
type AcceptPaymasterData struct {
|
||||||
|
ValidAfter *big.Int
|
||||||
|
ValidUntil *big.Int
|
||||||
|
Context []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func abiDecodeAcceptAccount(input []byte) (*AcceptAccountData, error) {
|
||||||
|
// this is not a true ABI of the "acceptAccount" function
|
||||||
|
// this ABI swaps inputs and outputs as there is no suitable "abi.decode" function
|
||||||
|
jsondata := `[
|
||||||
|
{"type":"function","name":"acceptAccount","outputs": [{"name": "validAfter","type": "uint256"},{"name": "validUntil","type": "uint256"}]}
|
||||||
|
]`
|
||||||
|
jsonAbi, err := abi.JSON(strings.NewReader(jsondata))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
methodSelector := new(big.Int).SetBytes(input[:4]).Uint64()
|
||||||
|
if methodSelector != AcceptAccountMethodSig {
|
||||||
|
if methodSelector == SigFailAccountMethodSig {
|
||||||
|
return nil, errors.New("account signature error")
|
||||||
|
}
|
||||||
|
return nil, errors.New("account did not return correct MAGIC_VALUE")
|
||||||
|
}
|
||||||
|
acceptAccountData := &AcceptAccountData{}
|
||||||
|
err = jsonAbi.UnpackIntoInterface(acceptAccountData, "acceptAccount", input[4:])
|
||||||
|
return acceptAccountData, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func abiDecodeAcceptPaymaster(input []byte) (*AcceptPaymasterData, error) {
|
||||||
|
jsondata := `[
|
||||||
|
{"type":"function","name":"acceptPaymaster","outputs": [{"name": "validAfter","type": "uint256"},{"name": "validUntil","type": "uint256"},{"name": "context","type": "bytes"}]}
|
||||||
|
]`
|
||||||
|
jsonAbi, err := abi.JSON(strings.NewReader(jsondata))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
methodSelector := new(big.Int).SetBytes(input[:4]).Uint64()
|
||||||
|
if methodSelector != AcceptPaymasterMethodSig {
|
||||||
|
return nil, errors.New("paymaster did not return correct MAGIC_VALUE")
|
||||||
|
}
|
||||||
|
acceptPaymasterData := &AcceptPaymasterData{}
|
||||||
|
err = jsonAbi.UnpackIntoInterface(acceptPaymasterData, "acceptPaymaster", input[4:])
|
||||||
|
if len(acceptPaymasterData.Context) > PaymasterMaxContextSize {
|
||||||
|
return nil, errors.New("paymaster return data: context too large")
|
||||||
|
}
|
||||||
|
return acceptPaymasterData, err
|
||||||
|
}
|
||||||
|
|
@ -3,7 +3,6 @@ package core
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/ethereum/go-ethereum/accounts/abi"
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/core/tracing"
|
"github.com/ethereum/go-ethereum/core/tracing"
|
||||||
|
|
@ -12,14 +11,8 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/holiman/uint256"
|
"github.com/holiman/uint256"
|
||||||
"math/big"
|
"math/big"
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const MAGIC_VALUE_SENDER = uint64(0x1256ebd1) // acceptAccount(uint256,uint256)
|
|
||||||
const MAGIC_VALUE_PAYMASTER = uint64(0x03be8439) // acceptPaymaster(uint256,uint256,bytes)
|
|
||||||
const MAGIC_VALUE_SIGFAIL = uint64(0x7715fac2) // sigFailAccount(uint256,uint256)
|
|
||||||
const PAYMASTER_MAX_CONTEXT_SIZE = 65536
|
|
||||||
|
|
||||||
var AA_ENTRY_POINT = common.HexToAddress("0x0000000000000000000000000000000000007560")
|
var AA_ENTRY_POINT = common.HexToAddress("0x0000000000000000000000000000000000007560")
|
||||||
var AA_SENDER_CREATOR = common.HexToAddress("0x00000000000000000000000000000000ffff7560")
|
var AA_SENDER_CREATOR = common.HexToAddress("0x00000000000000000000000000000000ffff7560")
|
||||||
|
|
||||||
|
|
@ -31,33 +24,6 @@ func PackValidationData(authorizerMagic uint64, validUntil, validAfter uint64) [
|
||||||
return common.LeftPadBytes(t.Bytes(), 32)
|
return common.LeftPadBytes(t.Bytes(), 32)
|
||||||
}
|
}
|
||||||
|
|
||||||
func UnpackValidationData(validationData []byte) (authorizerMagic uint64, validUntil uint64, validAfter uint64) {
|
|
||||||
authorizerMagic = new(big.Int).SetBytes(validationData[:4]).Uint64()
|
|
||||||
validAfter = new(big.Int).SetBytes(validationData[4:36]).Uint64()
|
|
||||||
validUntil = new(big.Int).SetBytes(validationData[36:68]).Uint64()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func UnpackPaymasterValidationReturn(paymasterValidationReturn []byte) (authorizerMagic uint64, validUntil uint64, validAfter uint64, context []byte, err error) {
|
|
||||||
if len(paymasterValidationReturn) < 100 {
|
|
||||||
return 0, 0, 0, nil, errors.New("paymaster return data: too short")
|
|
||||||
}
|
|
||||||
authorizerMagic = new(big.Int).SetBytes(paymasterValidationReturn[:4]).Uint64()
|
|
||||||
validAfter = new(big.Int).SetBytes(paymasterValidationReturn[4:36]).Uint64()
|
|
||||||
validUntil = new(big.Int).SetBytes(paymasterValidationReturn[36:68]).Uint64()
|
|
||||||
contextDataLength := paymasterValidationReturn[100:132]
|
|
||||||
contextLen := new(big.Int).SetBytes(contextDataLength)
|
|
||||||
if uint64(len(paymasterValidationReturn)) < 96+contextLen.Uint64() {
|
|
||||||
return 0, 0, 0, nil, errors.New("paymaster return data: unable to decode context")
|
|
||||||
}
|
|
||||||
if contextLen.Cmp(big.NewInt(PAYMASTER_MAX_CONTEXT_SIZE)) > 0 {
|
|
||||||
return 0, 0, 0, nil, errors.New("paymaster return data: context too large")
|
|
||||||
}
|
|
||||||
|
|
||||||
context = paymasterValidationReturn[132 : 132+contextLen.Uint64()]
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
type EntryPointCall struct {
|
type EntryPointCall struct {
|
||||||
caller common.Address
|
caller common.Address
|
||||||
input []byte
|
input []byte
|
||||||
|
|
@ -276,11 +242,13 @@ func ApplyRip7560ValidationPhases(chainConfig *params.ChainConfig, bc ChainConte
|
||||||
if resultAccountValidation.Err != nil {
|
if resultAccountValidation.Err != nil {
|
||||||
return nil, resultAccountValidation.Err
|
return nil, resultAccountValidation.Err
|
||||||
}
|
}
|
||||||
validAfter, validUntil, err := vpr.validateAccountEntryPointCall()
|
aad, err := vpr.validateAccountEntryPointCall()
|
||||||
|
// clear the EntryPoint calls array after parsing
|
||||||
|
vpr.EpCalls = make([]*EntryPointCall, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
err = validateValidityTimeRange(header.Time, validAfter, validUntil)
|
err = validateValidityTimeRange(header.Time, aad.ValidAfter.Uint64(), aad.ValidUntil.Uint64())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -298,8 +266,8 @@ func ApplyRip7560ValidationPhases(chainConfig *params.ChainConfig, bc ChainConte
|
||||||
vpr.DeploymentUsedGas = deploymentUsedGas
|
vpr.DeploymentUsedGas = deploymentUsedGas
|
||||||
vpr.ValidationUsedGas = resultAccountValidation.UsedGas
|
vpr.ValidationUsedGas = resultAccountValidation.UsedGas
|
||||||
vpr.PmValidationUsedGas = pmValidationUsedGas
|
vpr.PmValidationUsedGas = pmValidationUsedGas
|
||||||
vpr.SenderValidAfter = validAfter
|
vpr.SenderValidAfter = aad.ValidAfter.Uint64()
|
||||||
vpr.SenderValidUntil = validUntil
|
vpr.SenderValidUntil = aad.ValidUntil.Uint64()
|
||||||
vpr.PmValidAfter = pmValidAfter
|
vpr.PmValidAfter = pmValidAfter
|
||||||
vpr.PmValidUntil = pmValidUntil
|
vpr.PmValidUntil = pmValidUntil
|
||||||
statedb.Finalise(true)
|
statedb.Finalise(true)
|
||||||
|
|
@ -310,36 +278,31 @@ func ApplyRip7560ValidationPhases(chainConfig *params.ChainConfig, bc ChainConte
|
||||||
func applyPaymasterValidationFrame(vpr *ValidationPhaseResult, tx *types.Transaction, chainConfig *params.ChainConfig, signingHash common.Hash, evm *vm.EVM, gp *GasPool, statedb *state.StateDB, header *types.Header) ([]byte, uint64, uint64, uint64, error) {
|
func applyPaymasterValidationFrame(vpr *ValidationPhaseResult, tx *types.Transaction, chainConfig *params.ChainConfig, signingHash common.Hash, evm *vm.EVM, gp *GasPool, statedb *state.StateDB, header *types.Header) ([]byte, uint64, uint64, uint64, error) {
|
||||||
/*** Paymaster Validation Frame ***/
|
/*** Paymaster Validation Frame ***/
|
||||||
var pmValidationUsedGas uint64
|
var pmValidationUsedGas uint64
|
||||||
var paymasterContext []byte
|
|
||||||
var pmValidAfter uint64
|
|
||||||
var pmValidUntil uint64
|
|
||||||
paymasterMsg, err := preparePaymasterValidationMessage(tx, chainConfig, signingHash)
|
paymasterMsg, err := preparePaymasterValidationMessage(tx, chainConfig, signingHash)
|
||||||
|
if paymasterMsg == nil || err != nil {
|
||||||
|
return nil, 0, 0, 0, err
|
||||||
|
}
|
||||||
|
vpr.PmUsed = true
|
||||||
|
resultPm, err := ApplyMessage(evm, paymasterMsg, gp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, 0, 0, err
|
return nil, 0, 0, 0, err
|
||||||
}
|
}
|
||||||
if paymasterMsg != nil {
|
if resultPm.Failed() {
|
||||||
vpr.PmUsed = true
|
return nil, 0, 0, 0, resultPm.Err
|
||||||
resultPm, err := ApplyMessage(evm, paymasterMsg, gp)
|
|
||||||
if err != nil {
|
|
||||||
return nil, 0, 0, 0, err
|
|
||||||
}
|
|
||||||
if resultPm.Failed() {
|
|
||||||
return nil, 0, 0, 0, resultPm.Err
|
|
||||||
}
|
|
||||||
if resultPm.Failed() {
|
|
||||||
return nil, 0, 0, 0, errors.New("paymaster validation failed - invalid transaction")
|
|
||||||
}
|
|
||||||
pmValidationUsedGas = resultPm.UsedGas
|
|
||||||
paymasterContext, pmValidAfter, pmValidUntil, err = vpr.validatePaymasterEntryPointCall()
|
|
||||||
if err != nil {
|
|
||||||
return nil, 0, 0, 0, err
|
|
||||||
}
|
|
||||||
err = validateValidityTimeRange(header.Time, pmValidAfter, pmValidUntil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, 0, 0, 0, err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return paymasterContext, pmValidationUsedGas, pmValidAfter, pmValidUntil, nil
|
if resultPm.Failed() {
|
||||||
|
return nil, 0, 0, 0, errors.New("paymaster validation failed - invalid transaction")
|
||||||
|
}
|
||||||
|
pmValidationUsedGas = resultPm.UsedGas
|
||||||
|
apd, err := vpr.validatePaymasterEntryPointCall()
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, 0, 0, err
|
||||||
|
}
|
||||||
|
err = validateValidityTimeRange(header.Time, apd.ValidAfter.Uint64(), apd.ValidUntil.Uint64())
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, 0, 0, err
|
||||||
|
}
|
||||||
|
return apd.Context, pmValidationUsedGas, apd.ValidAfter.Uint64(), apd.ValidUntil.Uint64(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func applyPaymasterPostOpFrame(vpr *ValidationPhaseResult, executionResult *ExecutionResult, evm *vm.EVM, gp *GasPool, statedb *state.StateDB, header *types.Header) (*ExecutionResult, error) {
|
func applyPaymasterPostOpFrame(vpr *ValidationPhaseResult, executionResult *ExecutionResult, evm *vm.EVM, gp *GasPool, statedb *state.StateDB, header *types.Header) (*ExecutionResult, error) {
|
||||||
|
|
@ -430,16 +393,10 @@ func prepareDeployerMessage(baseTx *types.Transaction, config *params.ChainConfi
|
||||||
|
|
||||||
func prepareAccountValidationMessage(baseTx *types.Transaction, chainConfig *params.ChainConfig, signingHash common.Hash, deploymentUsedGas uint64) (*Message, error) {
|
func prepareAccountValidationMessage(baseTx *types.Transaction, chainConfig *params.ChainConfig, signingHash common.Hash, deploymentUsedGas uint64) (*Message, error) {
|
||||||
tx := baseTx.Rip7560TransactionData()
|
tx := baseTx.Rip7560TransactionData()
|
||||||
jsondata := `[
|
data, err := abiEncodeValidateTransaction(tx, signingHash)
|
||||||
{"type":"function","name":"validateTransaction","inputs": [{"name": "version","type": "uint256"},{"name": "txHash","type": "bytes32"},{"name": "transaction","type": "bytes"}]}
|
|
||||||
]`
|
|
||||||
|
|
||||||
validateTransactionAbi, err := abi.JSON(strings.NewReader(jsondata))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
txAbiEncoding, err := tx.AbiEncode()
|
|
||||||
validateTransactionData, err := validateTransactionAbi.Pack("validateTransaction", big.NewInt(0), signingHash, txAbiEncoding)
|
|
||||||
return &Message{
|
return &Message{
|
||||||
From: AA_ENTRY_POINT,
|
From: AA_ENTRY_POINT,
|
||||||
To: tx.Sender,
|
To: tx.Sender,
|
||||||
|
|
@ -448,7 +405,7 @@ func prepareAccountValidationMessage(baseTx *types.Transaction, chainConfig *par
|
||||||
GasPrice: tx.GasFeeCap,
|
GasPrice: tx.GasFeeCap,
|
||||||
GasFeeCap: tx.GasFeeCap,
|
GasFeeCap: tx.GasFeeCap,
|
||||||
GasTipCap: tx.GasTipCap,
|
GasTipCap: tx.GasTipCap,
|
||||||
Data: validateTransactionData,
|
Data: data,
|
||||||
AccessList: make(types.AccessList, 0),
|
AccessList: make(types.AccessList, 0),
|
||||||
SkipAccountChecks: true,
|
SkipAccountChecks: true,
|
||||||
IsRip7560Frame: true,
|
IsRip7560Frame: true,
|
||||||
|
|
@ -460,14 +417,7 @@ func preparePaymasterValidationMessage(baseTx *types.Transaction, config *params
|
||||||
if tx.Paymaster == nil || tx.Paymaster.Cmp(common.Address{}) == 0 {
|
if tx.Paymaster == nil || tx.Paymaster.Cmp(common.Address{}) == 0 {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
jsondata := `[
|
data, err := abiEncodeValidatePaymasterTransaction(tx, signingHash)
|
||||||
{"type":"function","name":"validatePaymasterTransaction","inputs": [{"name": "version","type": "uint256"},{"name": "txHash","type": "bytes32"},{"name": "transaction","type": "bytes"}]}
|
|
||||||
]`
|
|
||||||
|
|
||||||
validateTransactionAbi, err := abi.JSON(strings.NewReader(jsondata))
|
|
||||||
txAbiEncoding, err := tx.AbiEncode()
|
|
||||||
data, err := validateTransactionAbi.Pack("validatePaymasterTransaction", big.NewInt(0), signingHash, txAbiEncoding)
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -507,16 +457,8 @@ func preparePostOpMessage(vpr *ValidationPhaseResult, chainConfig *params.ChainC
|
||||||
if len(vpr.PaymasterContext) == 0 {
|
if len(vpr.PaymasterContext) == 0 {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
tx := vpr.Tx.Rip7560TransactionData()
|
tx := vpr.Tx.Rip7560TransactionData()
|
||||||
jsondata := `[
|
postOpData, err := abiEncodePostPaymasterTransaction(vpr.PaymasterContext)
|
||||||
{"type":"function","name":"postPaymasterTransaction","inputs": [{"name": "success","type": "bool"},{"name": "actualGasCost","type": "uint256"},{"name": "context","type": "bytes"}]}
|
|
||||||
]`
|
|
||||||
postPaymasterTransactionAbi, err := abi.JSON(strings.NewReader(jsondata))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
postOpData, err := postPaymasterTransactionAbi.Pack("postPaymasterTransaction", true, big.NewInt(0), vpr.PaymasterContext)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -535,50 +477,38 @@ func preparePostOpMessage(vpr *ValidationPhaseResult, chainConfig *params.ChainC
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (vpr *ValidationPhaseResult) validateAccountEntryPointCall() (uint64, uint64, error) {
|
func (vpr *ValidationPhaseResult) validateAccountEntryPointCall() (*AcceptAccountData, error) {
|
||||||
if len(vpr.EpCalls) == 0 {
|
if len(vpr.EpCalls) == 0 {
|
||||||
return 0, 0, errors.New("validation did not call the EntryPoint callback")
|
return nil, errors.New("account validation did not call the EntryPoint callback")
|
||||||
}
|
}
|
||||||
if (!vpr.PmUsed && len(vpr.EpCalls) > 1) || (vpr.PmUsed && len(vpr.EpCalls) > 2) {
|
if len(vpr.EpCalls) > 1 {
|
||||||
return 0, 0, errors.New("validation illegally called the EntryPoint callback multiple times")
|
return nil, errors.New("account validation illegally called the EntryPoint callback multiple times")
|
||||||
}
|
}
|
||||||
epCall := vpr.EpCalls[0]
|
epCall := vpr.EpCalls[0]
|
||||||
|
|
||||||
if len(epCall.input) != 68 {
|
if len(epCall.input) != 68 {
|
||||||
return 0, 0, errors.New("invalid account return data length")
|
return nil, errors.New("invalid account return data length")
|
||||||
}
|
}
|
||||||
magicExpected, validUntil, validAfter := UnpackValidationData(epCall.input)
|
return abiDecodeAcceptAccount(epCall.input)
|
||||||
//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_SIGFAIL {
|
|
||||||
return 0, 0, errors.New("account signature error")
|
|
||||||
}
|
|
||||||
return 0, 0, errors.New("account did not return correct MAGIC_VALUE")
|
|
||||||
}
|
|
||||||
return validAfter, validUntil, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (vpr *ValidationPhaseResult) validatePaymasterEntryPointCall() (context []byte, validAfter, validUntil uint64, error error) {
|
func (vpr *ValidationPhaseResult) validatePaymasterEntryPointCall() (*AcceptPaymasterData, error) {
|
||||||
if len(vpr.EpCalls) < 2 {
|
if len(vpr.EpCalls) == 0 {
|
||||||
return nil, 0, 0, errors.New("validation did not call the EntryPoint callback")
|
return nil, errors.New("paymaster validation did not call the EntryPoint callback")
|
||||||
}
|
}
|
||||||
if vpr.PmUsed && len(vpr.EpCalls) > 2 {
|
if vpr.PmUsed && len(vpr.EpCalls) > 1 {
|
||||||
return nil, 0, 0, errors.New("validation illegally called the EntryPoint callback multiple times")
|
return nil, errors.New("paymaster validation illegally called the EntryPoint callback multiple times")
|
||||||
}
|
}
|
||||||
epCall := vpr.EpCalls[1]
|
epCall := vpr.EpCalls[0]
|
||||||
|
|
||||||
if len(epCall.input) < 100 {
|
if len(epCall.input) < 100 {
|
||||||
return nil, 0, 0, errors.New("invalid paymaster callback data length")
|
return nil, errors.New("invalid paymaster callback data length")
|
||||||
}
|
}
|
||||||
magicExpected, validUntil, validAfter, context, err := UnpackPaymasterValidationReturn(epCall.input)
|
apd, err := abiDecodeAcceptPaymaster(epCall.input)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, 0, err
|
return nil, err
|
||||||
}
|
}
|
||||||
//, := UnpackValidationData(validationData)
|
return apd, nil
|
||||||
if magicExpected != MAGIC_VALUE_PAYMASTER {
|
|
||||||
return nil, 0, 0, errors.New("paymaster did not return correct MAGIC_VALUE")
|
|
||||||
}
|
|
||||||
return context, validAfter, validUntil, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateValidityTimeRange(time uint64, validAfter uint64, validUntil uint64) error {
|
func validateValidityTimeRange(time uint64, validAfter uint64, validUntil uint64) error {
|
||||||
|
|
|
||||||
|
|
@ -70,10 +70,10 @@ func TestPaymasterValidationFailure_contextTooLarge(t *testing.T) {
|
||||||
// then we return the total length of above (context itself is uninitialized string of max+1 zeroes)
|
// then we return the total length of above (context itself is uninitialized string of max+1 zeroes)
|
||||||
pmCode := createCode(
|
pmCode := createCode(
|
||||||
//vm.PUSH1, 1, vm.PUSH0, vm.RETURN,
|
//vm.PUSH1, 1, vm.PUSH0, vm.RETURN,
|
||||||
copyToMemory(core.PackValidationData(core.MAGIC_VALUE_PAYMASTER, 0, 0), 0),
|
copyToMemory(core.PackValidationData(core.AcceptPaymasterMethodSig, 0, 0), 0),
|
||||||
copyToMemory(asBytes32(64), 32),
|
copyToMemory(asBytes32(64), 32),
|
||||||
copyToMemory(asBytes32(core.PAYMASTER_MAX_CONTEXT_SIZE+1), 64),
|
copyToMemory(asBytes32(core.PaymasterMaxContextSize+1), 64),
|
||||||
push(core.PAYMASTER_MAX_CONTEXT_SIZE+96+1), vm.PUSH0, vm.RETURN)
|
push(core.PaymasterMaxContextSize+96+1), vm.PUSH0, vm.RETURN)
|
||||||
|
|
||||||
handleTransaction(newTestContextBuilder(t).withCode(DEFAULT_SENDER, createAccountCode(), 0).
|
handleTransaction(newTestContextBuilder(t).withCode(DEFAULT_SENDER, createAccountCode(), 0).
|
||||||
withCode(DEFAULT_PAYMASTER.String(), pmCode, DEFAULT_BALANCE), types.Rip7560AccountAbstractionTx{
|
withCode(DEFAULT_PAYMASTER.String(), pmCode, DEFAULT_BALANCE), types.Rip7560AccountAbstractionTx{
|
||||||
|
|
@ -86,7 +86,7 @@ func TestPaymasterValidationFailure_contextTooLarge(t *testing.T) {
|
||||||
|
|
||||||
func TestPaymasterValidationFailure_validAfter(t *testing.T) {
|
func TestPaymasterValidationFailure_validAfter(t *testing.T) {
|
||||||
handleTransaction(newTestContextBuilder(t).withCode(DEFAULT_SENDER, createAccountCode(), 0).
|
handleTransaction(newTestContextBuilder(t).withCode(DEFAULT_SENDER, createAccountCode(), 0).
|
||||||
withCode(DEFAULT_PAYMASTER.String(), returnWithData(paymasterReturnValue(core.MAGIC_VALUE_PAYMASTER, 300, 200, []byte{})), DEFAULT_BALANCE), types.Rip7560AccountAbstractionTx{
|
withCode(DEFAULT_PAYMASTER.String(), returnWithData(paymasterReturnValue(core.AcceptPaymasterMethodSig, 300, 200, []byte{})), DEFAULT_BALANCE), types.Rip7560AccountAbstractionTx{
|
||||||
ValidationGasLimit: 1000000000,
|
ValidationGasLimit: 1000000000,
|
||||||
PaymasterValidationGasLimit: 1000000000,
|
PaymasterValidationGasLimit: 1000000000,
|
||||||
GasFeeCap: big.NewInt(1000000000),
|
GasFeeCap: big.NewInt(1000000000),
|
||||||
|
|
@ -96,7 +96,7 @@ func TestPaymasterValidationFailure_validAfter(t *testing.T) {
|
||||||
|
|
||||||
func TestPaymasterValidationFailure_validUntil(t *testing.T) {
|
func TestPaymasterValidationFailure_validUntil(t *testing.T) {
|
||||||
handleTransaction(newTestContextBuilder(t).withCode(DEFAULT_SENDER, createAccountCode(), 0).
|
handleTransaction(newTestContextBuilder(t).withCode(DEFAULT_SENDER, createAccountCode(), 0).
|
||||||
withCode(DEFAULT_PAYMASTER.String(), returnWithData(paymasterReturnValue(core.MAGIC_VALUE_PAYMASTER, 1, 0, []byte{})), DEFAULT_BALANCE), types.Rip7560AccountAbstractionTx{
|
withCode(DEFAULT_PAYMASTER.String(), returnWithData(paymasterReturnValue(core.AcceptPaymasterMethodSig, 1, 0, []byte{})), DEFAULT_BALANCE), types.Rip7560AccountAbstractionTx{
|
||||||
ValidationGasLimit: 1000000000,
|
ValidationGasLimit: 1000000000,
|
||||||
PaymasterValidationGasLimit: 1000000000,
|
PaymasterValidationGasLimit: 1000000000,
|
||||||
GasFeeCap: big.NewInt(1000000000),
|
GasFeeCap: big.NewInt(1000000000),
|
||||||
|
|
@ -106,7 +106,7 @@ func TestPaymasterValidationFailure_validUntil(t *testing.T) {
|
||||||
|
|
||||||
func TestPaymasterValidation_ok(t *testing.T) {
|
func TestPaymasterValidation_ok(t *testing.T) {
|
||||||
handleTransaction(newTestContextBuilder(t).withCode(DEFAULT_SENDER, createAccountCode(), 0).
|
handleTransaction(newTestContextBuilder(t).withCode(DEFAULT_SENDER, createAccountCode(), 0).
|
||||||
withCode(DEFAULT_PAYMASTER.String(), returnWithData(paymasterReturnValue(core.MAGIC_VALUE_PAYMASTER, 0, 0, []byte{})), DEFAULT_BALANCE), types.Rip7560AccountAbstractionTx{
|
withCode(DEFAULT_PAYMASTER.String(), returnWithData(paymasterReturnValue(core.AcceptPaymasterMethodSig, 0, 0, []byte{})), DEFAULT_BALANCE), types.Rip7560AccountAbstractionTx{
|
||||||
ValidationGasLimit: 1000000000,
|
ValidationGasLimit: 1000000000,
|
||||||
PaymasterValidationGasLimit: 1000000000,
|
PaymasterValidationGasLimit: 1000000000,
|
||||||
GasFeeCap: big.NewInt(1000000000),
|
GasFeeCap: big.NewInt(1000000000),
|
||||||
|
|
|
||||||
|
|
@ -158,7 +158,7 @@ func returnWithData(data []byte) []byte {
|
||||||
}
|
}
|
||||||
|
|
||||||
func createAccountCode() []byte {
|
func createAccountCode() []byte {
|
||||||
return returnWithData(core.PackValidationData(core.MAGIC_VALUE_SENDER, 0, 0))
|
return returnWithData(core.PackValidationData(core.AcceptAccountMethodSig, 0, 0))
|
||||||
}
|
}
|
||||||
|
|
||||||
// create EVM code from OpCode, byte and []bytes
|
// create EVM code from OpCode, byte and []bytes
|
||||||
|
|
|
||||||
|
|
@ -21,11 +21,11 @@ func TestPackValidationData(t *testing.T) {
|
||||||
assert.Equal(t, packed.Text(16), new(big.Int).SetBytes(core.PackValidationData(0x1234, 1, 2)).Text(16))
|
assert.Equal(t, packed.Text(16), new(big.Int).SetBytes(core.PackValidationData(0x1234, 1, 2)).Text(16))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUnpackValidationData(t *testing.T) {
|
// func TestUnpackValidationData(t *testing.T) {
|
||||||
packed := core.PackValidationData(0xdead, 0xcafe, 0xface)
|
// packed := core.PackValidationData(0xdead, 0xcafe, 0xface)
|
||||||
magic, until, after := core.UnpackValidationData(packed)
|
// magic, until, after := core.UnpackValidationData(packed)
|
||||||
assert.Equal(t, []uint64{0xdead, 0xcafe, 0xface}, []uint64{magic, until, after})
|
// assert.Equal(t, []uint64{0xdead, 0xcafe, 0xface}, []uint64{magic, until, after})
|
||||||
}
|
// }
|
||||||
|
|
||||||
func TestValidationFailure_OOG(t *testing.T) {
|
func TestValidationFailure_OOG(t *testing.T) {
|
||||||
|
|
||||||
|
|
@ -44,7 +44,7 @@ func TestValidationFailure_no_balance(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestValidationFailure_sigerror(t *testing.T) {
|
func TestValidationFailure_sigerror(t *testing.T) {
|
||||||
handleTransaction(newTestContextBuilder(t).withCode(DEFAULT_SENDER, returnWithData(core.PackValidationData(core.MAGIC_VALUE_SIGFAIL, 0, 0)), DEFAULT_BALANCE), types.Rip7560AccountAbstractionTx{
|
handleTransaction(newTestContextBuilder(t).withCode(DEFAULT_SENDER, returnWithData(core.PackValidationData(core.SigFailAccountMethodSig, 0, 0)), DEFAULT_BALANCE), types.Rip7560AccountAbstractionTx{
|
||||||
ValidationGasLimit: uint64(1000000000),
|
ValidationGasLimit: uint64(1000000000),
|
||||||
GasFeeCap: big.NewInt(1000000000),
|
GasFeeCap: big.NewInt(1000000000),
|
||||||
}, "account signature error")
|
}, "account signature error")
|
||||||
|
|
@ -53,7 +53,7 @@ func TestValidationFailure_sigerror(t *testing.T) {
|
||||||
func TestValidationFailure_validAfter(t *testing.T) {
|
func TestValidationFailure_validAfter(t *testing.T) {
|
||||||
|
|
||||||
handleTransaction(newTestContextBuilder(t).withCode(DEFAULT_SENDER,
|
handleTransaction(newTestContextBuilder(t).withCode(DEFAULT_SENDER,
|
||||||
returnWithData(core.PackValidationData(core.MAGIC_VALUE_SENDER, 300, 200)), DEFAULT_BALANCE), types.Rip7560AccountAbstractionTx{
|
returnWithData(core.PackValidationData(core.AcceptAccountMethodSig, 300, 200)), DEFAULT_BALANCE), types.Rip7560AccountAbstractionTx{
|
||||||
ValidationGasLimit: uint64(1000000000),
|
ValidationGasLimit: uint64(1000000000),
|
||||||
GasFeeCap: big.NewInt(1000000000),
|
GasFeeCap: big.NewInt(1000000000),
|
||||||
}, "RIP-7560 transaction validity not reached yet")
|
}, "RIP-7560 transaction validity not reached yet")
|
||||||
|
|
@ -62,7 +62,7 @@ func TestValidationFailure_validAfter(t *testing.T) {
|
||||||
func TestValidationFailure_validUntil(t *testing.T) {
|
func TestValidationFailure_validUntil(t *testing.T) {
|
||||||
|
|
||||||
handleTransaction(newTestContextBuilder(t).withCode(DEFAULT_SENDER,
|
handleTransaction(newTestContextBuilder(t).withCode(DEFAULT_SENDER,
|
||||||
returnWithData(core.PackValidationData(core.MAGIC_VALUE_SENDER, 1, 0)), DEFAULT_BALANCE), types.Rip7560AccountAbstractionTx{
|
returnWithData(core.PackValidationData(core.AcceptAccountMethodSig, 1, 0)), DEFAULT_BALANCE), types.Rip7560AccountAbstractionTx{
|
||||||
ValidationGasLimit: uint64(1000000000),
|
ValidationGasLimit: uint64(1000000000),
|
||||||
GasFeeCap: big.NewInt(1000000000),
|
GasFeeCap: big.NewInt(1000000000),
|
||||||
}, "RIP-7560 transaction validity expired")
|
}, "RIP-7560 transaction validity expired")
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue