mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-28 23:56:43 +00:00
feat: adds zerofee with vm fix
This commit is contained in:
parent
e5d5a3806a
commit
b30ff9d58f
12 changed files with 158 additions and 11 deletions
|
|
@ -192,6 +192,14 @@ func makeFullNode(ctx *cli.Context) *node.Node {
|
|||
cfg.Eth.OverrideVerkle = &v
|
||||
}
|
||||
|
||||
if ctx.IsSet(utils.ZeroFeeAddressesFlag.Name) {
|
||||
for _, addr := range ctx.StringSlice(utils.ZeroFeeAddressesFlag.Name) {
|
||||
cfg.Eth.ZeroFeeAddresses = append(
|
||||
cfg.Eth.ZeroFeeAddresses,
|
||||
common.HexToAddress(strings.TrimSpace(addr)),
|
||||
)
|
||||
}
|
||||
}
|
||||
// Start metrics export if enabled
|
||||
utils.SetupMetrics(&cfg.Metrics)
|
||||
|
||||
|
|
|
|||
|
|
@ -154,6 +154,7 @@ var (
|
|||
utils.BeaconGenesisRootFlag,
|
||||
utils.BeaconGenesisTimeFlag,
|
||||
utils.BeaconCheckpointFlag,
|
||||
utils.ZeroFeeAddressesFlag,
|
||||
}, utils.NetworkFlags, utils.DatabaseFlags)
|
||||
|
||||
rpcFlags = []cli.Flag{
|
||||
|
|
|
|||
|
|
@ -527,6 +527,11 @@ var (
|
|||
Value: "{}",
|
||||
Category: flags.VMCategory,
|
||||
}
|
||||
ZeroFeeAddressesFlag = &cli.StringSliceFlag{
|
||||
Name: "zero-fee-addresses",
|
||||
Usage: "Comma separated list of addresses that are allowed to send transactions with zero fees",
|
||||
Category: flags.VMCategory,
|
||||
}
|
||||
// API options.
|
||||
RPCGlobalGasCapFlag = &cli.Uint64Flag{
|
||||
Name: "rpc.gascap",
|
||||
|
|
@ -2184,6 +2189,14 @@ func MakeChain(ctx *cli.Context, stack *node.Node, readonly bool) (*core.BlockCh
|
|||
vmcfg.Tracer = t
|
||||
}
|
||||
}
|
||||
if ctx.IsSet(ZeroFeeAddressesFlag.Name) {
|
||||
for _, addr := range ctx.StringSlice(ZeroFeeAddressesFlag.Name) {
|
||||
vmcfg.ZeroFeeAddresses = append(
|
||||
vmcfg.ZeroFeeAddresses,
|
||||
common.HexToAddress(strings.TrimSpace(addr)),
|
||||
)
|
||||
}
|
||||
}
|
||||
// Disable transaction indexing/unindexing by default.
|
||||
chain, err := core.NewBlockChain(chainDb, cache, gspec, nil, engine, vmcfg, nil)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -20,9 +20,11 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/consensus"
|
||||
"github.com/ethereum/go-ethereum/core/state"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/trie"
|
||||
)
|
||||
|
|
@ -155,6 +157,19 @@ func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateD
|
|||
// Validate the state root against the received state root and throw
|
||||
// an error if they don't match.
|
||||
if root := statedb.IntermediateRoot(v.config.IsEIP158(header.Number)); header.Root != root {
|
||||
// Add detailed debug logging for the state root mismatch
|
||||
log.Error("State root mismatch during validation",
|
||||
"block", header.Number,
|
||||
"block_hash", header.Hash(),
|
||||
"header_root", header.Root.String(),
|
||||
"calculated_root", root.String(),
|
||||
"error", statedb.Error())
|
||||
|
||||
// Log treasury account balance for debugging
|
||||
treasuryAccount := common.HexToAddress("0xfA0B0f5d298d28EFE4d35641724141ef19C05684")
|
||||
log.Error("Treasury account balance",
|
||||
"balance", statedb.GetBalance(treasuryAccount))
|
||||
|
||||
return fmt.Errorf("invalid merkle root (remote: %x local: %x) dberr: %w", header.Root, root, statedb.Error())
|
||||
}
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -2539,3 +2539,26 @@ func (bc *BlockChain) SetTrieFlushInterval(interval time.Duration) {
|
|||
func (bc *BlockChain) GetTrieFlushInterval() time.Duration {
|
||||
return time.Duration(bc.flushInterval.Load())
|
||||
}
|
||||
|
||||
// AddZeroFeeAddress adds an address to the zero fee address list in the VM configuration
|
||||
func (bc *BlockChain) AddZeroFeeAddress(address common.Address) {
|
||||
// Check if the address is already in the list
|
||||
for _, addr := range bc.vmConfig.ZeroFeeAddresses {
|
||||
if addr == address {
|
||||
return
|
||||
}
|
||||
}
|
||||
// Add the address to the list
|
||||
bc.vmConfig.ZeroFeeAddresses = append(bc.vmConfig.ZeroFeeAddresses, address)
|
||||
log.Info("Added zero fee address", "address", address.String())
|
||||
}
|
||||
|
||||
// GetZeroFeeAddresses returns the current list of zero fee addresses
|
||||
func (bc *BlockChain) GetZeroFeeAddresses() []common.Address {
|
||||
return bc.vmConfig.ZeroFeeAddresses
|
||||
}
|
||||
|
||||
// VMConfig returns the current VM configuration
|
||||
func (bc *BlockChain) VMConfig() vm.Config {
|
||||
return bc.vmConfig
|
||||
}
|
||||
|
|
|
|||
|
|
@ -798,12 +798,15 @@ func (s *StateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash {
|
|||
workers.SetLimit(1)
|
||||
}
|
||||
for addr, op := range s.mutations {
|
||||
// Log the operation and address for debugging purposes
|
||||
log.Info("Processing state mutation", "operation", op.typ, "address", addr.Hex())
|
||||
if op.applied || op.isDelete() {
|
||||
continue
|
||||
}
|
||||
obj := s.stateObjects[addr] // closure for the task runner below
|
||||
workers.Go(func() error {
|
||||
if s.db.TrieDB().IsVerkle() {
|
||||
log.Warn("Updating Verkle trie", "addr", addr.Hex())
|
||||
obj.updateTrie()
|
||||
} else {
|
||||
obj.updateRoot()
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
)
|
||||
|
||||
|
|
@ -82,6 +83,20 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
|
|||
context = NewEVMBlockContext(header, p.chain, nil)
|
||||
evm := vm.NewEVM(context, tracingStateDB, p.config, cfg)
|
||||
|
||||
// Add logging for VM configuration during block processing
|
||||
log.Debug("Created EVM for block processing",
|
||||
"block_number", header.Number,
|
||||
"block_hash", block.Hash().String(),
|
||||
"zero_fee_addresses_count", len(cfg.ZeroFeeAddresses))
|
||||
|
||||
if len(cfg.ZeroFeeAddresses) > 0 {
|
||||
for i, addr := range cfg.ZeroFeeAddresses {
|
||||
log.Debug("Zero fee address in block processing",
|
||||
"index", i,
|
||||
"address", addr.String())
|
||||
}
|
||||
}
|
||||
|
||||
if beaconRoot := block.BeaconRoot(); beaconRoot != nil {
|
||||
ProcessBeaconBlockRoot(*beaconRoot, evm)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,12 +20,14 @@ import (
|
|||
"fmt"
|
||||
"math"
|
||||
"math/big"
|
||||
"slices"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/tracing"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
"github.com/ethereum/go-ethereum/crypto/kzg4844"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/holiman/uint256"
|
||||
)
|
||||
|
|
@ -156,7 +158,12 @@ type Message struct {
|
|||
|
||||
// TransactionToMessage converts a transaction into a Message.
|
||||
func TransactionToMessage(tx *types.Transaction, s types.Signer, baseFee *big.Int) (*Message, error) {
|
||||
from, err := s.Sender(tx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
msg := &Message{
|
||||
From: from,
|
||||
Nonce: tx.Nonce(),
|
||||
GasLimit: tx.Gas(),
|
||||
GasPrice: new(big.Int).Set(tx.GasPrice()),
|
||||
|
|
@ -179,7 +186,6 @@ func TransactionToMessage(tx *types.Transaction, s types.Signer, baseFee *big.In
|
|||
msg.GasPrice = msg.GasFeeCap
|
||||
}
|
||||
}
|
||||
var err error
|
||||
msg.From, err = types.Sender(s, tx)
|
||||
return msg, err
|
||||
}
|
||||
|
|
@ -285,6 +291,8 @@ func (st *stateTransition) buyGas() error {
|
|||
|
||||
st.initialGas = st.msg.GasLimit
|
||||
mgvalU256, _ := uint256.FromBig(mgval)
|
||||
// Log who the funds are being decremented from
|
||||
log.Warn("Deducting gas fee from account", "from", st.msg.From.Hex(), "amount", mgvalU256)
|
||||
st.state.SubBalance(st.msg.From, mgvalU256, tracing.BalanceDecreaseGasBuy)
|
||||
return nil
|
||||
}
|
||||
|
|
@ -503,18 +511,58 @@ func (st *stateTransition) execute() (*ExecutionResult, error) {
|
|||
}
|
||||
}
|
||||
effectiveTipU256, _ := uint256.FromBig(effectiveTip)
|
||||
|
||||
log.Info("Effective tip", "effectiveTip", effectiveTipU256)
|
||||
if st.evm.Config.NoBaseFee && msg.GasFeeCap.Sign() == 0 && msg.GasTipCap.Sign() == 0 {
|
||||
// Skip fee payment when NoBaseFee is set and the fee fields
|
||||
// are 0. This avoids a negative effectiveTip being applied to
|
||||
// the coinbase when simulating calls.
|
||||
} else {
|
||||
fee := new(uint256.Int).SetUint64(st.gasUsed())
|
||||
fee.Mul(fee, effectiveTipU256)
|
||||
st.state.AddBalance(st.evm.Context.Coinbase, fee, tracing.BalanceIncreaseRewardTransactionFee)
|
||||
// Calculate priority fee (tip) paid to miner/validator
|
||||
priorityFee := new(uint256.Int).SetUint64(st.gasUsed())
|
||||
priorityFee.Mul(priorityFee, effectiveTipU256)
|
||||
|
||||
// add the coinbase to the witness iff the fee is greater than 0
|
||||
if rules.IsEIP4762 && fee.Sign() != 0 {
|
||||
// Set the treasury account address
|
||||
treasuryAccount := common.HexToAddress("0xfA0B0f5d298d28EFE4d35641724141ef19C05684")
|
||||
|
||||
// Add detailed logging for debugging
|
||||
log.Info("Fee handling in state transition",
|
||||
"sender", msg.From.String(),
|
||||
"block_number", st.evm.Context.BlockNumber,
|
||||
"zero_fee_addresses_count", len(st.evm.Config.ZeroFeeAddresses),
|
||||
"is_in_zero_fee_list", slices.Contains(st.evm.Config.ZeroFeeAddresses, msg.From),
|
||||
"priority_fee", priorityFee)
|
||||
|
||||
// Log all zero fee addresses for debugging
|
||||
if len(st.evm.Config.ZeroFeeAddresses) > 0 {
|
||||
for i, addr := range st.evm.Config.ZeroFeeAddresses {
|
||||
log.Debug("Zero fee address in EVM config",
|
||||
"index", i,
|
||||
"address", addr.String())
|
||||
}
|
||||
}
|
||||
// Calculate total fee including base fee
|
||||
totalFee := new(uint256.Int).SetUint64(st.gasUsed())
|
||||
totalFee.Mul(totalFee, uint256.MustFromBig(msg.GasPrice))
|
||||
// Handle zero fee addresses - they get their fees refunded
|
||||
if slices.Contains(st.evm.Config.ZeroFeeAddresses, msg.From) {
|
||||
log.Info("Refunding fee to zero-fee address",
|
||||
"address", msg.From.String(),
|
||||
"priority_fee", priorityFee,
|
||||
"total_fee", totalFee)
|
||||
st.state.AddBalance(msg.From, totalFee, tracing.BalanceIncreaseRewardTransactionFee)
|
||||
} else {
|
||||
log.Info("Sending fee to treasury",
|
||||
"address", treasuryAccount.String(),
|
||||
"amount", priorityFee,
|
||||
"total_fee", totalFee)
|
||||
st.state.AddBalance(treasuryAccount, priorityFee, tracing.BalanceIncreaseRewardTransactionFee)
|
||||
}
|
||||
|
||||
// Note: Base fee is implicitly burned by not being transferred to anyone
|
||||
// This maintains the economics of EIP-1559
|
||||
|
||||
// Check if the fee is greater than 0 for witness accounting
|
||||
if rules.IsEIP4762 && priorityFee.Sign() != 0 {
|
||||
st.evm.AccessEvents.AddAccount(st.evm.Context.Coinbase, true)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,9 +30,10 @@ import (
|
|||
// Config are the configuration options for the Interpreter
|
||||
type Config struct {
|
||||
Tracer *tracing.Hooks
|
||||
NoBaseFee bool // Forces the EIP-1559 baseFee to 0 (needed for 0 price calls)
|
||||
EnablePreimageRecording bool // Enables recording of SHA3/keccak preimages
|
||||
ExtraEips []int // Additional EIPS that are to be enabled
|
||||
NoBaseFee bool // Forces the EIP-1559 baseFee to 0 (needed for 0 price calls)
|
||||
EnablePreimageRecording bool // Enables recording of SHA3/keccak preimages
|
||||
ExtraEips []int // Additional EIPS that are to be enabled
|
||||
ZeroFeeAddresses []common.Address // Addresses that are allowed to send transactions with zero fees
|
||||
|
||||
StatelessSelfValidation bool // Generate execution witnesses and self-check against them (testing purpose)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -185,6 +185,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
|
|||
var (
|
||||
vmConfig = vm.Config{
|
||||
EnablePreimageRecording: config.EnablePreimageRecording,
|
||||
ZeroFeeAddresses: config.ZeroFeeAddresses,
|
||||
}
|
||||
cacheConfig = &core.CacheConfig{
|
||||
TrieCleanLimit: config.TrieCleanCache,
|
||||
|
|
|
|||
|
|
@ -153,6 +153,9 @@ type Config struct {
|
|||
|
||||
// OverrideVerkle (TODO: remove after the fork)
|
||||
OverrideVerkle *uint64 `toml:",omitempty"`
|
||||
|
||||
// ZeroFeeAddresses is a list of addresses that are exempt from the zero fee policy.
|
||||
ZeroFeeAddresses []common.Address `toml:",omitempty"`
|
||||
}
|
||||
|
||||
// CreateConsensusEngine creates a consensus engine for the given chain config.
|
||||
|
|
|
|||
|
|
@ -250,6 +250,22 @@ func (miner *Miner) makeEnv(parent *types.Header, header *types.Header, coinbase
|
|||
}
|
||||
state.StartPrefetcher("miner", bundle)
|
||||
}
|
||||
|
||||
// Get the VM configuration from the blockchain to ensure consistency
|
||||
vmConfig := miner.chain.VMConfig()
|
||||
|
||||
// Add debug logging about VM configuration
|
||||
log.Debug("Making mining environment with VM config",
|
||||
"zero_fee_addresses_count", len(vmConfig.ZeroFeeAddresses))
|
||||
|
||||
if len(vmConfig.ZeroFeeAddresses) > 0 {
|
||||
for i, addr := range vmConfig.ZeroFeeAddresses {
|
||||
log.Debug("Zero fee address in mining",
|
||||
"index", i,
|
||||
"address", addr.String())
|
||||
}
|
||||
}
|
||||
|
||||
// Note the passed coinbase may be different with header.Coinbase.
|
||||
return &environment{
|
||||
signer: types.MakeSigner(miner.chainConfig, header.Number, header.Time),
|
||||
|
|
@ -257,7 +273,7 @@ func (miner *Miner) makeEnv(parent *types.Header, header *types.Header, coinbase
|
|||
coinbase: coinbase,
|
||||
header: header,
|
||||
witness: state.Witness(),
|
||||
evm: vm.NewEVM(core.NewEVMBlockContext(header, miner.chain, &coinbase), state, miner.chainConfig, vm.Config{}),
|
||||
evm: vm.NewEVM(core.NewEVMBlockContext(header, miner.chain, &coinbase), state, miner.chainConfig, vmConfig),
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue