This commit is contained in:
Marius van der Wijden 2026-05-11 08:26:39 -06:00 committed by GitHub
commit 2d32d542d2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 89 additions and 19 deletions

View file

@ -339,7 +339,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
for _, receipt := range receipts {
allLogs = append(allLogs, receipt.Logs...)
}
if err := core.ParseDepositLogs(&requests, allLogs, chainConfig); err != nil {
if err := core.ParseDepositLogs(&requests, allLogs, chainConfig, vmContext.BlockNumber, vmContext.Time); err != nil {
return nil, nil, nil, NewError(ErrorEVM, fmt.Errorf("could not parse requests logs: %v", err))
}
// EIP-7002

View file

@ -322,7 +322,7 @@ func (b *BlockGen) collectRequests(readonly bool) (requests [][]byte) {
for _, r := range b.receipts {
blockLogs = append(blockLogs, r.Logs...)
}
if err := ParseDepositLogs(&requests, blockLogs, b.cm.config); err != nil {
if err := ParseDepositLogs(&requests, blockLogs, b.cm.config, b.header.Number, b.header.Time); err != nil {
panic(fmt.Sprintf("failed to parse deposit log: %v", err))
}
// create EVM for system calls

View file

@ -144,7 +144,7 @@ func postExecution(ctx context.Context, config *params.ChainConfig, block *types
if config.IsPrague(block.Number(), block.Time()) {
requests = [][]byte{}
// EIP-6110
if err := ParseDepositLogs(&requests, allLogs, config); err != nil {
if err := ParseDepositLogs(&requests, allLogs, config, block.Number(), block.Time()); err != nil {
return requests, fmt.Errorf("failed to parse deposit logs: %w", err)
}
// EIP-7002
@ -348,21 +348,47 @@ func processRequestsSystemCall(requests *[][]byte, evm *vm.EVM, requestType byte
return nil
}
var depositTopic = common.HexToHash("0x649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c5")
// DepositTopic is the topic hash of the EIP-6110 DepositEvent.
var DepositTopic = common.HexToHash("0x649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c5")
// IsDepositLog reports whether the log is an EIP-6110 deposit event emitted
// by the given deposit contract address.
func IsDepositLog(log *types.Log, depositContract common.Address) bool {
return log.Address == depositContract && len(log.Topics) > 0 && log.Topics[0] == DepositTopic
}
// CountDepositLogs returns the number of EIP-6110 deposit events present in
// the given logs.
func CountDepositLogs(logs []*types.Log, depositContract common.Address) int {
count := 0
for _, log := range logs {
if IsDepositLog(log, depositContract) {
count++
}
}
return count
}
// ParseDepositLogs extracts the EIP-6110 deposit values from logs emitted by
// BeaconDepositContract.
func ParseDepositLogs(requests *[][]byte, logs []*types.Log, config *params.ChainConfig) error {
// BeaconDepositContract. From the Amsterdam fork onwards the number of
// deposits per block is capped to params.MaxDepositRequestsPerBlock by
// EIP-8254.
func ParseDepositLogs(requests *[][]byte, logs []*types.Log, config *params.ChainConfig, blockNumber *big.Int, blockTime uint64) error {
deposits := make([]byte, 1) // note: first byte is 0x00 (== deposit request type)
count := 0
for _, log := range logs {
if log.Address == config.DepositContractAddress && len(log.Topics) > 0 && log.Topics[0] == depositTopic {
if IsDepositLog(log, config.DepositContractAddress) {
request, err := types.DepositLogToRequest(log.Data)
if err != nil {
return fmt.Errorf("unable to parse deposit data: %v", err)
}
deposits = append(deposits, request...)
count++
}
}
if config.IsAmsterdam(blockNumber, blockTime) && count > params.MaxDepositRequestsPerBlock {
return fmt.Errorf("too many deposit requests in block: have %d, max %d", count, params.MaxDepositRequestsPerBlock)
}
if len(deposits) > 1 {
*requests = append(*requests, deposits)
}

View file

@ -398,7 +398,7 @@ func (sim *simulator) processBlock(ctx context.Context, block *simBlock, header,
if sim.chainConfig.IsPrague(header.Number, header.Time) {
requests = [][]byte{}
// EIP-6110
if err := core.ParseDepositLogs(&requests, allLogs, sim.chainConfig); err != nil {
if err := core.ParseDepositLogs(&requests, allLogs, sim.chainConfig, header.Number, header.Time); err != nil {
return nil, nil, nil, err
}
// EIP-7002

View file

@ -43,6 +43,10 @@ var (
errBlockInterruptedByNewHead = errors.New("new head arrived while building block")
errBlockInterruptedByRecommit = errors.New("recommit interrupt while building block")
errBlockInterruptedByTimeout = errors.New("timeout while building block")
// errDepositCapExceeded is returned when including a transaction would
// push the block over the EIP-8254 deposit-request cap.
errDepositCapExceeded = errors.New("deposit request cap exceeded")
)
// maxBlobsPerBlock returns the maximum number of blobs per block.
@ -66,11 +70,12 @@ type environment struct {
coinbase common.Address
evm *vm.EVM
header *types.Header
txs []*types.Transaction
receipts []*types.Receipt
sidecars []*types.BlobTxSidecar
blobs int
header *types.Header
txs []*types.Transaction
receipts []*types.Receipt
sidecars []*types.BlobTxSidecar
blobs int
depositRequests int // running count of EIP-6110 deposit requests, capped by EIP-8254
witness *stateless.Witness
}
@ -212,7 +217,7 @@ func (miner *Miner) generateWork(ctx context.Context, genParam *generateParams,
if miner.chainConfig.IsPrague(work.header.Number, work.header.Time) {
requests = [][]byte{}
// EIP-6110 deposits
if err := core.ParseDepositLogs(&requests, allLogs, miner.chainConfig); err != nil {
if err := core.ParseDepositLogs(&requests, allLogs, miner.chainConfig, work.header.Number, work.header.Time); err != nil {
return &newPayloadResult{err: err}
}
// EIP-7002
@ -372,10 +377,13 @@ func (miner *Miner) commitTransaction(ctx context.Context, env *environment, tx
if tx.Type() == types.BlobTxType {
return miner.commitBlobTransaction(env, tx)
}
receipt, err := miner.applyTransaction(env, tx)
receipt, snap, gp, err := miner.applyTransaction(env, tx)
if err != nil {
return err
}
if err := miner.checkDepositCap(env, receipt, snap, gp); err != nil {
return err
}
env.txs = append(env.txs, tx)
env.receipts = append(env.receipts, receipt)
env.size += tx.Size()
@ -396,10 +404,13 @@ func (miner *Miner) commitBlobTransaction(env *environment, tx *types.Transactio
if env.blobs+len(sc.Blobs) > maxBlobs {
return errors.New("max data blobs reached")
}
receipt, err := miner.applyTransaction(env, tx)
receipt, snap, gp, err := miner.applyTransaction(env, tx)
if err != nil {
return err
}
if err := miner.checkDepositCap(env, receipt, snap, gp); err != nil {
return err
}
txNoBlob := tx.WithoutBlobTxSidecar()
env.txs = append(env.txs, txNoBlob)
env.receipts = append(env.receipts, receipt)
@ -412,7 +423,9 @@ func (miner *Miner) commitBlobTransaction(env *environment, tx *types.Transactio
}
// applyTransaction runs the transaction. If execution fails, state and gas pool are reverted.
func (miner *Miner) applyTransaction(env *environment, tx *types.Transaction) (*types.Receipt, error) {
// On success the pre-execution snapshot/gas-pool checkpoint are returned so the
// caller can revert if a post-execution constraint (e.g. EIP-8254 deposit cap) fails.
func (miner *Miner) applyTransaction(env *environment, tx *types.Transaction) (*types.Receipt, int, *core.GasPool, error) {
var (
snap = env.state.Snapshot()
gp = env.gasPool.Snapshot()
@ -421,10 +434,32 @@ func (miner *Miner) applyTransaction(env *environment, tx *types.Transaction) (*
if err != nil {
env.state.RevertToSnapshot(snap)
env.gasPool.Set(gp)
return nil, err
return nil, 0, nil, err
}
env.header.GasUsed = env.gasPool.Used()
return receipt, nil
return receipt, snap, gp, nil
}
// checkDepositCap enforces the EIP-8254 cap on deposit requests per block.
// If including the receipt would push the running deposit count over
// params.MaxDepositRequestsPerBlock, the state and gas pool are reverted to
// the pre-execution checkpoint and errDepositCapExceeded is returned.
func (miner *Miner) checkDepositCap(env *environment, receipt *types.Receipt, snap int, gp *core.GasPool) error {
if !miner.chainConfig.IsAmsterdam(env.header.Number, env.header.Time) {
return nil
}
added := core.CountDepositLogs(receipt.Logs, miner.chainConfig.DepositContractAddress)
if added == 0 {
return nil
}
if env.depositRequests+added > params.MaxDepositRequestsPerBlock {
env.state.RevertToSnapshot(snap)
env.gasPool.Set(gp)
env.header.GasUsed = env.gasPool.Used()
return errDepositCapExceeded
}
env.depositRequests += added
return nil
}
func (miner *Miner) commitTransactions(ctx context.Context, env *environment, plainTxs, blobTxs *transactionsByPriceAndNonce, interrupt *atomic.Int32) error {
@ -522,6 +557,13 @@ func (miner *Miner) commitTransactions(ctx context.Context, env *environment, pl
err := miner.commitTransaction(ctx, env, tx)
switch {
case errors.Is(err, errDepositCapExceeded):
// EIP-8254: including this tx would push the block past the
// deposit-request cap. Skip this sender; subsequent senders may
// still produce non-deposit-bearing transactions that fit.
log.Trace("Skipping tx that would exceed deposit-request cap", "hash", ltx.Hash, "sender", from)
txs.Pop()
case errors.Is(err, core.ErrNonceTooLow):
// New head notification data race between the transaction pool and miner, shift
log.Trace("Skipping transaction with low nonce", "hash", ltx.Hash, "sender", from, "nonce", tx.Nonce())

View file

@ -186,6 +186,8 @@ const (
HistoryServeWindow = 8191 // Number of blocks to serve historical block hashes for, EIP-2935.
MaxBlockSize = 8_388_608 // maximum size of an RLP-encoded block
MaxDepositRequestsPerBlock = 8192 // Maximum number of EIP-6110 deposit requests per block, EIP-8254.
)
// Bls12381G1MultiExpDiscountTable is the gas discount table for BLS12-381 G1 multi exponentiation operation