mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-19 10:22:23 +00:00
feat: add BlockTxCount limit and BlockPayloadSize limit (#584)
* update consensus/errors.go * update core/error.go * update core/types/block.go * update rollup/rcfg/config.go * update params/config.go * update core/block_validator.go * fix * update miner/worker.go * fix
This commit is contained in:
parent
c70a901ed3
commit
b639349788
7 changed files with 73 additions and 0 deletions
|
|
@ -38,4 +38,7 @@ var (
|
||||||
// ErrInvalidTerminalBlock is returned if a block is invalid wrt. the terminal
|
// ErrInvalidTerminalBlock is returned if a block is invalid wrt. the terminal
|
||||||
// total difficulty.
|
// total difficulty.
|
||||||
ErrInvalidTerminalBlock = errors.New("invalid terminal block")
|
ErrInvalidTerminalBlock = errors.New("invalid terminal block")
|
||||||
|
|
||||||
|
// ErrInvalidTxCount is returned if a block contains too many transactions.
|
||||||
|
ErrInvalidTxCount = errors.New("invalid transaction count")
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,14 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error {
|
||||||
if v.bc.HasBlockAndState(block.Hash(), block.NumberU64()) {
|
if v.bc.HasBlockAndState(block.Hash(), block.NumberU64()) {
|
||||||
return ErrKnownBlock
|
return ErrKnownBlock
|
||||||
}
|
}
|
||||||
|
// Check if block tx count is is smaller than the max count
|
||||||
|
if !v.config.Scroll.IsValidTxCount(len(block.Transactions())) {
|
||||||
|
return consensus.ErrInvalidTxCount
|
||||||
|
}
|
||||||
|
// Check if block payload size is smaller than the max size
|
||||||
|
if !v.config.Scroll.IsValidBlockSize(block.PayloadSize()) {
|
||||||
|
return ErrInvalidBlockPayloadSize
|
||||||
|
}
|
||||||
|
|
||||||
// Header validity is known at this point. Here we verify that uncles, transactions
|
// Header validity is known at this point. Here we verify that uncles, transactions
|
||||||
// and withdrawals given in the block body match the header.
|
// and withdrawals given in the block body match the header.
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,9 @@ var (
|
||||||
// ErrKnownBlock is returned when a block to import is already known locally.
|
// ErrKnownBlock is returned when a block to import is already known locally.
|
||||||
ErrKnownBlock = errors.New("block already known")
|
ErrKnownBlock = errors.New("block already known")
|
||||||
|
|
||||||
|
// ErrInvalidBlockPayloadSize is returned when a block to import has an oversized payload.
|
||||||
|
ErrInvalidBlockPayloadSize = errors.New("invalid block payload size")
|
||||||
|
|
||||||
// ErrBannedHash is returned if a block to import is on the banned list.
|
// ErrBannedHash is returned if a block to import is on the banned list.
|
||||||
ErrBannedHash = errors.New("banned hash")
|
ErrBannedHash = errors.New("banned hash")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -415,6 +415,18 @@ func (b *Block) Size() uint64 {
|
||||||
return uint64(c)
|
return uint64(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PayloadSize returns the encoded storage size sum of all transactions in a block.
|
||||||
|
func (b *Block) PayloadSize() uint64 {
|
||||||
|
// add up all txs sizes
|
||||||
|
var totalSize uint64
|
||||||
|
for _, tx := range b.transactions {
|
||||||
|
if !tx.IsL1MessageTx() {
|
||||||
|
totalSize += tx.Size()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return totalSize
|
||||||
|
}
|
||||||
|
|
||||||
// SanityCheck can be used to prevent that unbounded fields are
|
// SanityCheck can be used to prevent that unbounded fields are
|
||||||
// stuffed with junk data to add processing overhead
|
// stuffed with junk data to add processing overhead
|
||||||
func (b *Block) SanityCheck() error {
|
func (b *Block) SanityCheck() error {
|
||||||
|
|
|
||||||
|
|
@ -85,6 +85,7 @@ type environment struct {
|
||||||
signer types.Signer
|
signer types.Signer
|
||||||
state *state.StateDB // apply state changes here
|
state *state.StateDB // apply state changes here
|
||||||
tcount int // tx count in cycle
|
tcount int // tx count in cycle
|
||||||
|
blockSize uint64 // approximate size of tx payload in bytes
|
||||||
gasPool *core.GasPool // available gas used to pack transactions
|
gasPool *core.GasPool // available gas used to pack transactions
|
||||||
coinbase common.Address
|
coinbase common.Address
|
||||||
|
|
||||||
|
|
@ -722,6 +723,7 @@ func (w *worker) makeEnv(parent *types.Header, header *types.Header, coinbase co
|
||||||
}
|
}
|
||||||
// Keep track of transactions which return errors so they can be removed
|
// Keep track of transactions which return errors so they can be removed
|
||||||
env.tcount = 0
|
env.tcount = 0
|
||||||
|
env.blockSize = 0
|
||||||
return env, nil
|
return env, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -834,6 +836,18 @@ func (w *worker) commitTransactions(env *environment, txs *transactionsByPriceAn
|
||||||
txs.Pop()
|
txs.Pop()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
// If we have collected enough transactions then we're done
|
||||||
|
// Originally we only limit l2txs count, but now strictly limit total txs number.
|
||||||
|
// log.Info("w.chainConfig", "w.chainConfig.Scroll", w.chainConfig.Scroll)
|
||||||
|
if !w.chainConfig.Scroll.IsValidTxCount(env.tcount + 1) {
|
||||||
|
log.Trace("Transaction count limit reached", "have", env.tcount, "want", w.chainConfig.Scroll.MaxTxPerBlock)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if !tx.IsL1MessageTx() && !w.chainConfig.Scroll.IsValidBlockSize(env.blockSize+tx.Size()) {
|
||||||
|
log.Trace("Block size limit reached", "have", env.blockSize, "want", w.chainConfig.Scroll.MaxTxPayloadBytesPerBlock, "tx", tx.Size())
|
||||||
|
txs.Pop() // skip transactions from this account
|
||||||
|
continue
|
||||||
|
}
|
||||||
// Error may be ignored here. The error has already been checked
|
// Error may be ignored here. The error has already been checked
|
||||||
// during transaction acceptance is the transaction pool.
|
// during transaction acceptance is the transaction pool.
|
||||||
from, _ := types.Sender(env.signer, tx)
|
from, _ := types.Sender(env.signer, tx)
|
||||||
|
|
@ -861,6 +875,12 @@ func (w *worker) commitTransactions(env *environment, txs *transactionsByPriceAn
|
||||||
env.tcount++
|
env.tcount++
|
||||||
txs.Shift()
|
txs.Shift()
|
||||||
|
|
||||||
|
if tx.IsL1MessageTx() {
|
||||||
|
} else {
|
||||||
|
// only consider block size limit for L2 transactions
|
||||||
|
env.blockSize += tx.Size()
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// Transaction is regarded as invalid, drop all consecutive transactions from
|
// Transaction is regarded as invalid, drop all consecutive transactions from
|
||||||
// the same sender because of `nonce-too-high` clause.
|
// the same sender because of `nonce-too-high` clause.
|
||||||
|
|
|
||||||
|
|
@ -333,6 +333,28 @@ type ChainConfig struct {
|
||||||
Ethash *EthashConfig `json:"ethash,omitempty"`
|
Ethash *EthashConfig `json:"ethash,omitempty"`
|
||||||
Clique *CliqueConfig `json:"clique,omitempty"`
|
Clique *CliqueConfig `json:"clique,omitempty"`
|
||||||
IsDevMode bool `json:"isDev,omitempty"`
|
IsDevMode bool `json:"isDev,omitempty"`
|
||||||
|
|
||||||
|
// Scroll genesis extension: enable scroll rollup-related traces & state transition
|
||||||
|
Scroll ScrollConfig `json:"scroll,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ScrollConfig struct {
|
||||||
|
// Maximum number of transactions per block [optional]
|
||||||
|
MaxTxPerBlock *int `json:"maxTxPerBlock,omitempty"`
|
||||||
|
|
||||||
|
// Maximum tx payload size of blocks that we produce [optional]
|
||||||
|
MaxTxPayloadBytesPerBlock *int `json:"maxTxPayloadBytesPerBlock,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsValidTxCount returns whether the given block's transaction count is below the limit.
|
||||||
|
// This limit corresponds to the number of ECDSA signature checks that we can fit into the zkEVM.
|
||||||
|
func (s ScrollConfig) IsValidTxCount(count int) bool {
|
||||||
|
return s.MaxTxPerBlock == nil || count <= *s.MaxTxPerBlock
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsValidBlockSize returns whether the given block's transaction payload size is below the limit.
|
||||||
|
func (s ScrollConfig) IsValidBlockSize(size uint64) bool {
|
||||||
|
return s.MaxTxPayloadBytesPerBlock == nil || size <= uint64(*s.MaxTxPayloadBytesPerBlock)
|
||||||
}
|
}
|
||||||
|
|
||||||
// EthashConfig is the consensus engine configs for proof-of-work based sealing.
|
// EthashConfig is the consensus engine configs for proof-of-work based sealing.
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,11 @@ import (
|
||||||
// TODO:
|
// TODO:
|
||||||
// verify in consensus layer when decentralizing sequencer
|
// verify in consensus layer when decentralizing sequencer
|
||||||
|
|
||||||
|
var (
|
||||||
|
ScrollMaxTxPerBlock = 100
|
||||||
|
ScrollMaxTxPayloadBytesPerBlock = 120 * 1024
|
||||||
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// L2MessageQueueAddress is the address of the L2MessageQueue
|
// L2MessageQueueAddress is the address of the L2MessageQueue
|
||||||
// predeploy
|
// predeploy
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue