Skip to content
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
4 changes: 4 additions & 0 deletions core/block_validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ func NewBlockValidator(config *params.ChainConfig, blockchain *BlockChain, engin
// header's transaction and uncle roots. The headers are assumed to be already
// validated at this point.
func (v *BlockValidator) ValidateBody(block *types.Block) error {
// check EIP-7934 RLP-encoded block size cap
if v.config.IsOsaka(block.Number()) && block.Size() > params.MaxBlockSize {
return ErrBlockOversized
}
// Check whether the block's known, and if not, that it's linkable
if v.bc.HasBlockAndFullState(block.Hash(), block.NumberU64()) {
return ErrKnownBlock
Comment thread
gzliudan marked this conversation as resolved.
Expand Down
45 changes: 45 additions & 0 deletions core/block_validator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package core

import (
"math/big"
"testing"
"time"

Expand All @@ -25,6 +26,7 @@ import (
"github.com/XinFinOrg/XDPoSChain/core/types"
"github.com/XinFinOrg/XDPoSChain/core/vm"
"github.com/XinFinOrg/XDPoSChain/params"
"github.com/XinFinOrg/XDPoSChain/trie"
)

// Tests that simple header verification works, for both good and bad blocks.
Expand Down Expand Up @@ -76,3 +78,46 @@ func TestHeaderVerification(t *testing.T) {
chain.InsertChain(blocks[i : i+1])
}
}

func TestValidateBodyBlockOversizedOsakaByBlockNumber(t *testing.T) {
testdb := rawdb.NewMemoryDatabase()
cfg := *params.TestChainConfig
cfg.OsakaBlock = big.NewInt(2)
gspec := &Genesis{Config: &cfg}
genesis := gspec.MustCommit(testdb)

chain, err := NewBlockChain(testdb, nil, gspec, ethash.NewFaker(), vm.Config{})
if err != nil {
t.Fatal(err)
}
defer chain.Stop()

validator := NewBlockValidator(&cfg, chain, ethash.NewFaker())
oversizedData := make([]byte, params.MaxBlockSize+1024)
tx := types.NewTx(&types.LegacyTx{
Nonce: 0,
Gas: params.TxGas,
GasPrice: big.NewInt(1),
Data: oversizedData,
})

newOversizedBlock := func(number uint64, ts uint64) *types.Block {
header := &types.Header{
ParentHash: genesis.Hash(),
Number: new(big.Int).SetUint64(number),
Time: ts,
GasLimit: 30_000_000,
}
return types.NewBlock(header, &types.Body{Transactions: []*types.Transaction{tx}}, nil, trie.NewStackTrie(nil))
}

preOsaka := newOversizedBlock(1, ^uint64(0))
if err := validator.ValidateBody(preOsaka); err == ErrBlockOversized {
t.Fatalf("pre-Osaka block should not trigger ErrBlockOversized")
}

postOsaka := newOversizedBlock(2, 0)
if err := validator.ValidateBody(postOsaka); err != ErrBlockOversized {
t.Fatalf("post-Osaka oversized block mismatch: have %v, want %v", err, ErrBlockOversized)
}
}
4 changes: 4 additions & 0 deletions core/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ var (

// ErrNoGenesis is returned when there is no Genesis Block.
ErrNoGenesis = errors.New("genesis not found in chain")

// ErrBlockOversized is returned if the size of the RLP-encoded block
// exceeds the cap established by EIP-7934
ErrBlockOversized = errors.New("block RLP-encoded size exceeds maximum")
)

// List of evm-call-message pre-checking errors. All state transtion messages will
Expand Down
26 changes: 26 additions & 0 deletions miner/worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ const (
chainSideChanSize = 10

txMatchGasLimit = 40000000

// Block size is capped by the protocol at params.MaxBlockSize. During
// production keep a safety margin for auxiliary fields added to the block.
maxBlockSizeBufferZone = 1_000_000
Comment thread
gzliudan marked this conversation as resolved.
)

var (
Expand Down Expand Up @@ -90,6 +94,7 @@ type Work struct {
signer types.Signer
state *state.StateDB // apply state changes here
tcount int // tx count in cycle
size uint64 // size of the block we are building
evm *vm.EVM

parentState *state.StateDB
Expand All @@ -108,6 +113,15 @@ type Work struct {
createdAt time.Time
}

// txFitsSize reports whether the transaction fits into the block size limit.
func (w *Work) txFitsSize(tx *types.Transaction) bool {
Comment thread
gzliudan marked this conversation as resolved.
// this Osaka-specific cap is not enforced pre-fork
if w.config.IsOsaka(w.header.Number) {
return w.size+tx.Size() < params.MaxBlockSize-maxBlockSizeBufferZone
}
return true
}

type Result struct {
Work *Work
Block *types.Block
Expand Down Expand Up @@ -712,6 +726,7 @@ func (w *worker) makeCurrent(parent *types.Block, header *types.Header) error {
config: w.chainConfig,
signer: types.MakeSigner(w.chainConfig, header.Number),
state: state,
size: uint64(header.Size()),
parentState: state.Copy(),
Comment thread
gzliudan marked this conversation as resolved.
tradingState: XDCxState,
lendingState: lendingState,
Expand Down Expand Up @@ -1080,6 +1095,10 @@ func (w *Work) commitTransactions(mux *event.TypeMux, balanceFee map[common.Addr
var coalescedLogs []*types.Log
// first priority for special Txs
for _, tx := range specialTxs {
if !w.txFitsSize(tx) {
log.Debug("Skipping oversized transaction", "hash", tx.Hash(), "size", tx.Size())
continue
}
Comment on lines 1097 to +1101
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Miner-side enforcement of the new Osaka block-size cap isn’t covered by tests in this PR. Since miner/worker_test.go exists and this change affects transaction selection behavior, please add a unit test that activates Osaka and asserts oversized transactions are skipped (and that normal-sized transactions are still included).

Copilot uses AI. Check for mistakes.
to := tx.To()
if w.header.Number.Uint64() >= common.DenylistHFNumber {
from := tx.From()
Expand Down Expand Up @@ -1193,6 +1212,12 @@ func (w *Work) commitTransactions(mux *event.TypeMux, balanceFee map[common.Addr
break
}
tx := resolvedTx
// if inclusion of the transaction would put the block size over the
// maximum we allow, don't add any more txs to the payload.
if !w.txFitsSize(tx) {
log.Debug("Skipping oversized transaction", "hash", tx.Hash(), "size", tx.Size())
break
Comment thread
gzliudan marked this conversation as resolved.
}
to := tx.To()
if w.header.Number.Uint64() >= common.DenylistHFNumber {
from := tx.From()
Expand Down Expand Up @@ -1330,6 +1355,7 @@ func (w *Work) commitTransaction(balanceFee map[common.Address]*big.Int, tx *typ
}
w.txs = append(w.txs, tx)
w.receipts = append(w.receipts, receipt)
w.size += tx.Size()

return receipt.Logs, tokenFeeUsed, gas, nil
}
2 changes: 2 additions & 0 deletions params/protocol_params.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,8 @@ const (
Bn256PairingPerPointGasIstanbul uint64 = 34000 // Per-point price for an elliptic curve pairing check

HistoryServeWindow = 8191 // Number of blocks to serve historical block hashes for, EIP-2935.

MaxBlockSize uint64 = 8_388_608 // maximum size of an RLP-encoded block
)

var (
Expand Down
Loading