Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unify preCheck function #2224

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 39 additions & 15 deletions core/parallel_executor.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
package core

import (
cmath "github.com/PlatONnetwork/PlatON-Go/common/math"
"fmt"
"math/big"
"runtime"
"sync"
"time"

cmath "github.com/PlatONnetwork/PlatON-Go/common/math"

"github.com/PlatONnetwork/PlatON-Go/x/gov"

"github.com/PlatONnetwork/PlatON-Go/crypto"

"github.com/panjf2000/ants/v2"

"github.com/PlatONnetwork/PlatON-Go/common"
"github.com/PlatONnetwork/PlatON-Go/core/state"
"github.com/PlatONnetwork/PlatON-Go/core/types"
"github.com/PlatONnetwork/PlatON-Go/core/vm"
Expand Down Expand Up @@ -148,41 +151,62 @@ func (exe *Executor) ExecuteTransactions(ctx *ParallelContext) error {
return nil
}

// 并行交易执行前,需要对交易进行 preCheck
// 由于并行交易模块和StateTransition模块相对独立,所以无法复用StateTransition的preCheck,后续两个模块的preCheck需要及时同步
func (exe *Executor) preCheck(msg types.Message, fromObj *state.ParallelStateObject, baseFee *big.Int, gte150 bool) error {
// check nonce
if fromObj.GetNonce() < msg.Nonce() {
return ErrNonceTooHigh
} else if fromObj.GetNonce() > msg.Nonce() {
return ErrNonceTooLow
stNonce := fromObj.GetNonce()
if msgNonce := msg.Nonce(); stNonce < msgNonce {
return fmt.Errorf("%w: address %v, tx: %d state: %d", ErrNonceTooHigh,
msg.From().Hex(), msgNonce, stNonce)
} else if stNonce > msgNonce {
return fmt.Errorf("%w: address %v, tx: %d state: %d", ErrNonceTooLow,
msg.From().Hex(), msgNonce, stNonce)
} else if stNonce+1 < stNonce {
return fmt.Errorf("%w: address %v, nonce: %d", ErrNonceMax,
msg.From().Hex(), stNonce)
}

// Make sure the sender is an EOA
if codeHash := fromObj.GetCodeHash(); codeHash != emptyCodeHash && codeHash != (common.Hash{}) {
return fmt.Errorf("%w: address %v, codehash: %s", ErrSenderNoEOA,
msg.From().Hex(), codeHash)
}

// check balance
mgval := new(big.Int).Mul(new(big.Int).SetUint64(msg.Gas()), msg.GasPrice())
mgval := new(big.Int).SetUint64(msg.Gas())
mgval = mgval.Mul(mgval, msg.GasPrice())
balanceCheck := mgval
if gte150 {
balanceCheck = new(big.Int).SetUint64(msg.Gas())
balanceCheck = balanceCheck.Mul(balanceCheck, msg.GasFeeCap())
balanceCheck.Add(balanceCheck, msg.Value())
}
if fromObj.GetBalance().Cmp(balanceCheck) < 0 {
return errInsufficientBalanceForGas
if have, want := fromObj.GetBalance(), balanceCheck; have.Cmp(want) < 0 {
return fmt.Errorf("%w: address %v have %v want %v", ErrInsufficientFunds, msg.From().Hex(), have, want)
}

// Make sure that transaction gasFeeCap is greater than the baseFee (post london)
if gte150 {
// Skip the checks if gas fields are zero and baseFee was explicitly disabled (eth_call)
if !exe.vmCfg.NoBaseFee || msg.GasFeeCap().BitLen() > 0 || msg.GasTipCap().BitLen() > 0 {
if msg.GasFeeCap().BitLen() > 256 {
return ErrFeeCapVeryHigh
if l := msg.GasFeeCap().BitLen(); l > 256 {
return fmt.Errorf("%w: address %v, maxFeePerGas bit length: %d", ErrFeeCapVeryHigh,
msg.From().Hex(), l)
}
if msg.GasTipCap().BitLen() > 256 {
return ErrTipVeryHigh
if l := msg.GasTipCap().BitLen(); l > 256 {
return fmt.Errorf("%w: address %v, maxPriorityFeePerGas bit length: %d", ErrTipVeryHigh,
msg.From().Hex(), l)
}
if msg.GasFeeCap().Cmp(msg.GasTipCap()) < 0 {
return ErrTipAboveFeeCap
return fmt.Errorf("%w: address %v, maxPriorityFeePerGas: %s, maxFeePerGas: %s", ErrTipAboveFeeCap,
msg.From().Hex(), msg.GasTipCap(), msg.GasFeeCap())
}
// This will panic if baseFee is nil, but basefee presence is verified
// as part of header validation.
if msg.GasFeeCap().Cmp(baseFee) < 0 {
return ErrFeeCapTooLow
return fmt.Errorf("%w: address %v, maxFeePerGas: %s baseFee: %s", ErrFeeCapTooLow,
msg.From().Hex(), msg.GasFeeCap(), baseFee)
}
}
}
Expand Down Expand Up @@ -226,7 +250,7 @@ func (exe *Executor) executeParallelTx(ctx *ParallelContext, idx int, intrinsicG
log.Trace("Execute parallel tx", "baseFee", ctx.header.BaseFee, "gasTipCap", msg.GasTipCap(), "gasFeeCap", msg.GasFeeCap(), "gasPrice", msg.GasPrice(), "effectiveTip", effectiveTip, "intrinsicGas", intrinsicGas)
cost := new(big.Int).Add(msg.Value(), fee)
if fromObj.GetBalance().Cmp(cost) < 0 {
ctx.buildTransferFailedResult(idx, errInsufficientBalanceForGas, true)
ctx.buildTransferFailedResult(idx, ErrInsufficientFunds, true)
return
}

Expand Down
6 changes: 6 additions & 0 deletions core/state/parallel_state_object.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package state

import (
"math/big"

"github.com/PlatONnetwork/PlatON-Go/common"
)

type ParallelStateObject struct {
Expand Down Expand Up @@ -44,6 +46,10 @@ func (parallelObject *ParallelStateObject) SubBalance(amount *big.Int) {
parallelObject.stateObject.setBalance(new(big.Int).Sub(parallelObject.stateObject.Balance(), amount))
}

func (parallelObject *ParallelStateObject) GetCodeHash() common.Hash {
return common.BytesToHash(parallelObject.stateObject.CodeHash())
}

func (parallelObject *ParallelStateObject) UpdateRoot() {
parallelObject.stateObject.updateRoot(parallelObject.stateObject.db.db)
}
6 changes: 1 addition & 5 deletions core/state_transition.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ package core

import (
"context"
"errors"
"fmt"
"math"
"math/big"
Expand All @@ -37,10 +36,7 @@ import (
"github.com/PlatONnetwork/PlatON-Go/params"
)

var (
errInsufficientBalanceForGas = errors.New("insufficient balance to pay for gas")
emptyCodeHash = crypto.Keccak256Hash(nil)
)
var emptyCodeHash = crypto.Keccak256Hash(nil)

/*
The State Transitioning Model
Expand Down
13 changes: 9 additions & 4 deletions internal/ethapi/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,20 @@ import (
"context"
"errors"
"fmt"
"github.com/PlatONnetwork/PlatON-Go/consensus/misc"
"github.com/PlatONnetwork/PlatON-Go/eth/tracers/logger"
"math/big"
"strings"
"time"

"github.com/PlatONnetwork/PlatON-Go/consensus/misc"
"github.com/PlatONnetwork/PlatON-Go/eth/tracers/logger"

ctypes "github.com/PlatONnetwork/PlatON-Go/consensus/cbft/types"

"github.com/PlatONnetwork/PlatON-Go/core/state"

"github.com/PlatONnetwork/PlatON-Go/accounts/abi"

"strings"
"github.com/davecgh/go-spew/spew"

"github.com/PlatONnetwork/PlatON-Go/accounts"
"github.com/PlatONnetwork/PlatON-Go/accounts/keystore"
Expand All @@ -48,7 +50,6 @@ import (
"github.com/PlatONnetwork/PlatON-Go/params"
"github.com/PlatONnetwork/PlatON-Go/rlp"
"github.com/PlatONnetwork/PlatON-Go/rpc"
"github.com/davecgh/go-spew/spew"
)

// PublicEthereumAPI provides an API to access Ethereum related information.
Expand Down Expand Up @@ -1660,6 +1661,10 @@ func (s *PublicTransactionPoolAPI) sign(addr common.Address, tx *types.Transacti

// SubmitTransaction is a helper function that submits tx to txPool and logs a message.
func SubmitTransaction(ctx context.Context, b Backend, tx *types.Transaction) (common.Hash, error) {
head := b.CurrentHeader()
if !b.ChainConfig().IsPauli(head.Number) && tx.Type() != types.LegacyTxType {
return common.Hash{}, types.ErrTxTypeNotSupported
}
// If the transaction fee cap is already specified, ensure the
// fee of the given transaction is _reasonable_.
if err := checkTxFee(tx.GasPrice(), tx.Gas(), b.RPCTxFeeCap()); err != nil {
Expand Down
Loading