Skip to content

Commit 698ca1c

Browse files
committed
core,core/tracing,core/vm,eth/feemarket,params: add some rough logic around fee distribution at state_transition
1 parent cbbf671 commit 698ca1c

File tree

6 files changed

+106
-18
lines changed

6 files changed

+106
-18
lines changed

core/state_feemarket_tracker.go

+15-7
Original file line numberDiff line numberDiff line change
@@ -66,18 +66,20 @@ func (t *feeMarketTracker) Hooks() (*tracing.Hooks, error) {
6666
wrapped.OnExit = t.OnExit
6767
wrapped.OnLog = t.OnLog
6868

69-
journaledHooks, err := tracing.WrapWithJournal(&wrapped)
70-
if err != nil {
71-
return nil, err
72-
}
7369

74-
return journaledHooks, nil
70+
return &wrapped, nil
7571
}
7672

73+
// GetGasMap returns the gas map for the fee market
7774
func (t *feeMarketTracker) GetGasMap() map[common.Address]*uint256.Int {
7875
return t.gasTracker
7976
}
8077

78+
// GetAddressesToInvalidateCache returns the addresses to invalidate cache for the fee market
79+
func (t *feeMarketTracker) GetAddressesToInvalidateCache() []common.Address {
80+
return t.addressesToInvalidateCache
81+
}
82+
8183
func (t *feeMarketTracker) OnEnter(depth int, typ byte, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
8284
if t.hooks != nil && t.hooks.OnEnter != nil {
8385
t.hooks.OnEnter(depth, typ, from, to, input, gas, value)
@@ -99,6 +101,7 @@ func (t *feeMarketTracker) OnExit(depth int, output []byte, gasUsed uint64, err
99101
t.hooks.OnExit(depth, output, gasUsed, err, reverted)
100102
}
101103

104+
// TODO: do we care if the tx reverted? the gas cost happened either way
102105
if reverted || t.internalTxToAddress == (common.Address{}) {
103106
return
104107
}
@@ -129,15 +132,20 @@ func (t *feeMarketTracker) OnTxEnd(receipt *types.Receipt, err error) {
129132
t.hooks.OnTxEnd(receipt, err)
130133
}
131134

132-
if receipt == nil || receipt.Status == types.ReceiptStatusFailed {
135+
// Error happened during tx validation.
136+
if err != nil || receipt == nil {
133137
return
134138
}
135139

140+
// We want to track the gas used by the tx even if it failed.
136141
if t.txToAddress == (common.Address{}) {
137142
return
138143
}
139144

140-
t.gasTracker[t.txToAddress] = t.gasTracker[t.txToAddress].Add(t.gasTracker[t.txToAddress], uint256.NewInt(receipt.GasUsed))
145+
// As this is the actual TX gas used, we don't need to add it on top of the internal tx gas used
146+
t.gasTracker[t.txToAddress] = uint256.NewInt(receipt.GasUsed)
147+
148+
// TODO: shall we invalidate gas use for other addresses too? or mark this address as root level?
141149

142150
t.txToAddress = (common.Address{})
143151
}

core/state_transition.go

+82-11
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import (
2828
"github.com/ethereum/go-ethereum/core/types"
2929
"github.com/ethereum/go-ethereum/core/vm"
3030
"github.com/ethereum/go-ethereum/crypto/kzg4844"
31+
"github.com/ethereum/go-ethereum/log"
3132
"github.com/ethereum/go-ethereum/params"
3233
"github.com/holiman/uint256"
3334
)
@@ -458,36 +459,80 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
458459

459460
fee := new(uint256.Int).SetUint64(st.gasUsed())
460461
fee.Mul(fee, effectiveTipU256)
462+
461463
// consensus engine is satoshi
462464
if st.evm.ChainConfig().Satoshi != nil {
463-
464-
// Calculate full system reward
465-
totalSystemReward := new(uint256.Int).Set(fee)
466-
remainingSystemReward := new(uint256.Int).Set(totalSystemReward)
467-
468465
// Check if is a contract call
469466
if st.msg.To != nil && st.state.GetCodeSize(*st.msg.To) > 0 {
470467

471468
tracer := st.evm.Config.Tracer
472469
feeMarket := st.evm.Context.FeeMarket
473470
feeMarketTracker := *st.evm.TxContext.FeeMarketTracker
471+
feeMarketDenominator := st.evm.Context.FeeMarket.GetDenominator()
474472

475473
if tracer != nil && feeMarket != nil && feeMarketTracker != nil {
476-
// Try to access the gas usage stats
477-
gasUsageMap := feeMarketTracker.GetGasMap()
474+
// Invalidate cache for the addresses that are being tracked
475+
addressesToInvalidateCache := feeMarketTracker.GetAddressesToInvalidateCache()
476+
for _, addr := range addressesToInvalidateCache {
477+
feeMarket.InvalidateConfig(addr)
478+
}
479+
480+
feeConfigs := feeConfigs{}
478481

479-
for addr, gas := range gasUsageMap {
482+
// Get the gas usage map for the addresses that are being tracked
483+
gasUsageMap := feeMarketTracker.GetGasMap()
484+
for addr, gasUsed := range gasUsageMap {
480485
fmt.Println()
481-
fmt.Printf("🤡 TransitionDb -> Tracked addr: %v, gas: %v\n", addr, gas)
486+
fmt.Printf("🤡 TransitionDb -> Tracked addr: %v, gasUsed: %v\n", addr, gasUsed)
482487

483488
// Get discount configuration from fee market
484489
config, found := st.evm.Context.FeeMarket.GetConfig(addr, st.state)
485-
fmt.Println("🤡 TransitionDb -> read config:", found, config)
490+
if !found || !config.IsActive {
491+
continue
492+
}
493+
494+
// fmt.Println("🤡 TransitionDb -> read config:", found, config)
495+
496+
feeConfigs.addConfig(addr, gasUsed, config)
497+
}
498+
499+
// Calculate the total gas used by the configurations
500+
totalConfigGasUsed := feeConfigs.getConfigTotalGas()
501+
502+
for addr, feeConfig := range feeConfigs.configs {
503+
// The portion of the total gas used by this specific configuration
504+
configurationGasPercentage := uint256.NewInt(0).Div(feeConfig.gasUsed, totalConfigGasUsed)
505+
506+
// The portion of FeeMarketRewardGas that will be distributed to this configuration
507+
rewardsGas := uint256.NewInt(0).Mul(configurationGasPercentage, uint256.NewInt(params.FeeMarketRewardGas))
508+
509+
fmt.Println("🤡 1️⃣ TransitionDb -> Config:", addr, "configurationGasPercentage:", configurationGasPercentage, "rewardsGas:", rewardsGas)
510+
511+
// Calculate the reward amount for each reward in the configuration
512+
for _, reward := range feeConfig.configuration.Rewards {
513+
// Gas to reward for this specific address
514+
rewardGas := uint256.NewInt(0).Mul(rewardsGas, uint256.NewInt(0).Div(reward.RewardPercentage, feeMarketDenominator))
515+
516+
// TODO: handle overflow
517+
st.gasRemaining -= rewardGas.Uint64()
518+
519+
// Reward amount for this specific address
520+
rewardAmount := uint256.NewInt(0).Mul(rewardGas, effectiveTipU256)
521+
522+
fmt.Println("🤡 2️⃣ TransitionDb -> Reward:", reward.RewardAddress, "rewardGas:", rewardGas, "rewardAmount:", rewardAmount)
523+
524+
// Add fee reward to address
525+
st.state.AddBalance(reward.RewardAddress, rewardAmount, tracing.BalanceIncreaseFeeMarketReward)
526+
527+
log.Info("Add reward fee",
528+
"rewardAddress", reward.RewardAddress,
529+
"rewardAmount", rewardAmount)
530+
}
486531
}
487532
}
488533
}
489534

490-
st.state.AddBalance(consensus.SystemAddress, remainingSystemReward, tracing.BalanceIncreaseRewardTransactionFee)
535+
st.state.AddBalance(consensus.SystemAddress, fee, tracing.BalanceIncreaseRewardTransactionFee)
491536
// add extra blob fee reward
492537
if rules.IsCancun {
493538
blobFee := new(big.Int).SetUint64(st.blobGasUsed())
@@ -547,3 +592,29 @@ func (st *StateTransition) gasUsed() uint64 {
547592
func (st *StateTransition) blobGasUsed() uint64 {
548593
return uint64(len(st.msg.BlobHashes) * params.BlobTxBlobGasPerBlob)
549594
}
595+
596+
type feeConfig struct {
597+
gasUsed *uint256.Int
598+
configuration types.FeeMarketConfig
599+
}
600+
type feeConfigs struct {
601+
configs map[common.Address]feeConfig
602+
totalConfigGasUsed *uint256.Int
603+
// totalTxGasUsed *uint256.Int
604+
}
605+
606+
func (fc *feeConfigs) addConfig(addr common.Address, gasUsed *uint256.Int, configuration types.FeeMarketConfig) {
607+
fc.configs[addr] = feeConfig{
608+
gasUsed: gasUsed,
609+
configuration: configuration,
610+
}
611+
}
612+
613+
func (fc *feeConfigs) getConfigTotalGas() *uint256.Int {
614+
totalGasUsed := uint256.NewInt(0)
615+
for _, feeConfig := range fc.configs {
616+
totalGasUsed = totalGasUsed.Add(totalGasUsed, feeConfig.gasUsed)
617+
}
618+
fc.totalConfigGasUsed = totalGasUsed
619+
return fc.totalConfigGasUsed
620+
}

core/tracing/hooks.go

+2
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,8 @@ const (
320320
// BalanceIncreaseCoreDistributeReward is a balance change that increases the block validator's balance and
321321
// happens when Core is distributing rewards to validator.
322322
BalanceIncreaseCoreDistributeReward BalanceChangeReason = 181
323+
// BalanceIncreaseRewardTransactionFee is the reward for a transaction.
324+
BalanceIncreaseFeeMarketReward BalanceChangeReason = 182
323325
)
324326

325327
// GasChangeReason is used to indicate the reason for a gas change, useful

core/vm/interface.go

+2
Original file line numberDiff line numberDiff line change
@@ -117,4 +117,6 @@ type FeeMarketTrackerReader interface {
117117
Hooks() (*tracing.Hooks, error)
118118
// GetGasMap returns the gas map for the fee market.
119119
GetGasMap() map[common.Address]*uint256.Int
120+
// GetAddressesToInvalidateCache returns the addresses to invalidate cache for the fee market.
121+
GetAddressesToInvalidateCache() []common.Address
120122
}

eth/feemarket/storage.go

+4
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ func (p *StorageProvider) GetConfig(address common.Address, state FeeMarketState
6767
}
6868

6969
config, found = p.findConfigForAddress(address, state)
70+
if !config.IsValidConfig(GetDenominator()) {
71+
return types.FeeMarketConfig{}, false
72+
}
73+
7074
if found {
7175
p.configCache[address] = config // set in cache
7276
}

params/protocol_params.go

+1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ const (
3737
CallNewAccountGas uint64 = 25000 // Paid for CALL when the destination address didn't exist prior.
3838
TxGas uint64 = 21000 // Per transaction not creating a contract. NOTE: Not payable on data of calls between transactions.
3939
SystemTxsGas uint64 = 500000 // The gas reserved for system txs; only for satoshi consensus
40+
FeeMarketRewardGas uint64 = 100000 // The gas added for fee market rewards; only for satoshi consensus
4041
TxGasContractCreation uint64 = 53000 // Per transaction that creates a contract. NOTE: Not payable on data of calls between transactions.
4142
TxDataZeroGas uint64 = 4 // Per byte of data attached to a transaction that equals zero. NOTE: Not payable on data of calls between transactions.
4243
QuadCoeffDiv uint64 = 512 // Divisor for the quadratic particle of the memory cost equation.

0 commit comments

Comments
 (0)