Skip to content

Commit edfa90c

Browse files
committed
Merge branch 'mpeter/track-surge-factor' into mpeter/surge-factor-for-soft-finality
2 parents fed891a + 407106e commit edfa90c

17 files changed

Lines changed: 860 additions & 64 deletions

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,8 @@ generate:
9797
mockery --dir=storage --name=BlockIndexer --output=storage/mocks
9898
mockery --dir=storage --name=ReceiptIndexer --output=storage/mocks
9999
mockery --dir=storage --name=TransactionIndexer --output=storage/mocks
100-
mockery --dir=storage --name=AccountIndexer --output=storage/mocks
101100
mockery --dir=storage --name=TraceIndexer --output=storage/mocks
101+
mockery --dir=storage --name=FeeParametersIndexer --output=storage/mocks
102102
mockery --all --dir=services/traces --output=services/traces/mocks
103103
mockery --all --dir=services/ingestion --output=services/ingestion/mocks
104104
mockery --dir=models --name=Engine --output=models/mocks

api/api.go

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ type BlockChainAPI struct {
8585
blocks storage.BlockIndexer
8686
transactions storage.TransactionIndexer
8787
receipts storage.ReceiptIndexer
88+
feeParameters storage.FeeParametersIndexer
8889
indexingResumedHeight uint64
8990
rateLimiter RateLimiter
9091
collector metrics.Collector
@@ -97,6 +98,7 @@ func NewBlockChainAPI(
9798
blocks storage.BlockIndexer,
9899
transactions storage.TransactionIndexer,
99100
receipts storage.ReceiptIndexer,
101+
feeParameters storage.FeeParametersIndexer,
100102
rateLimiter RateLimiter,
101103
collector metrics.Collector,
102104
indexingResumedHeight uint64,
@@ -108,6 +110,7 @@ func NewBlockChainAPI(
108110
blocks: blocks,
109111
transactions: transactions,
110112
receipts: receipts,
113+
feeParameters: feeParameters,
111114
indexingResumedHeight: indexingResumedHeight,
112115
rateLimiter: rateLimiter,
113116
collector: collector,
@@ -179,7 +182,12 @@ func (b *BlockChainAPI) SendRawTransaction(
179182
return common.Hash{}, err
180183
}
181184

182-
id, err := b.evm.SendRawTransaction(ctx, input)
185+
feeParams, err := b.feeParameters.Get()
186+
if err != nil {
187+
return common.Hash{}, err
188+
}
189+
190+
id, err := b.evm.SendRawTransaction(ctx, input, feeParams)
183191
if err != nil {
184192
return handleError[common.Hash](err, l, b.collector)
185193
}
@@ -805,12 +813,6 @@ func (b *BlockChainAPI) FeeHistory(
805813
)
806814

807815
maxCount := min(uint64(blockCount), lastBlockNumber)
808-
809-
blockRewards := make([]*hexutil.Big, len(rewardPercentiles))
810-
for i := range rewardPercentiles {
811-
blockRewards[i] = (*hexutil.Big)(b.config.GasPrice)
812-
}
813-
814816
for i := maxCount; i >= uint64(1); i-- {
815817
// If the requested block count is 5, and the last block number
816818
// is 20, then we need the blocks [16, 17, 18, 19, 20] in this
@@ -827,6 +829,21 @@ func (b *BlockChainAPI) FeeHistory(
827829

828830
baseFees = append(baseFees, (*hexutil.Big)(models.BaseFeePerGas))
829831

832+
blockRewards := make([]*hexutil.Big, len(rewardPercentiles))
833+
feeParams, err := b.feeParameters.Get()
834+
if err != nil {
835+
b.logger.Warn().
836+
Uint64("height", blockHeight).
837+
Err(err).
838+
Msg("failed to get fee parameters for block in fee history")
839+
840+
continue
841+
}
842+
gasPrice := feeParams.CalculateGasPrice(b.config.GasPrice)
843+
for i := range rewardPercentiles {
844+
blockRewards[i] = (*hexutil.Big)(gasPrice)
845+
}
846+
830847
rewards = append(rewards, blockRewards)
831848

832849
gasUsedRatio := float64(block.TotalGasUsed) / float64(BlockGasLimit)
@@ -1007,7 +1024,13 @@ func (b *BlockChainAPI) Coinbase(ctx context.Context) (common.Address, error) {
10071024

10081025
// GasPrice returns a suggestion for a gas price for legacy transactions.
10091026
func (b *BlockChainAPI) GasPrice(ctx context.Context) (*hexutil.Big, error) {
1010-
return (*hexutil.Big)(b.config.GasPrice), nil
1027+
feeParams, err := b.feeParameters.Get()
1028+
if err != nil {
1029+
b.logger.Warn().Err(err).Msg("fee parameters unavailable; falling back to base gas price")
1030+
return (*hexutil.Big)(b.config.GasPrice), nil
1031+
}
1032+
gasPrice := feeParams.CalculateGasPrice(b.config.GasPrice)
1033+
return (*hexutil.Big)(gasPrice), nil
10111034
}
10121035

10131036
// GetUncleCountByBlockHash returns number of uncles in the block for the given block hash
@@ -1048,7 +1071,13 @@ func (b *BlockChainAPI) GetUncleByBlockNumberAndIndex(
10481071

10491072
// MaxPriorityFeePerGas returns a suggestion for a gas tip cap for dynamic fee transactions.
10501073
func (b *BlockChainAPI) MaxPriorityFeePerGas(ctx context.Context) (*hexutil.Big, error) {
1051-
return (*hexutil.Big)(b.config.GasPrice), nil
1074+
feeParams, err := b.feeParameters.Get()
1075+
if err != nil {
1076+
b.logger.Warn().Err(err).Msg("fee parameters unavailable; falling back to base gas price")
1077+
return (*hexutil.Big)(b.config.GasPrice), nil
1078+
}
1079+
gasPrice := feeParams.CalculateGasPrice(b.config.GasPrice)
1080+
return (*hexutil.Big)(gasPrice), nil
10521081
}
10531082

10541083
// Mining returns true if client is actively mining new blocks.

bootstrap/bootstrap.go

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,14 @@ const (
5151
)
5252

5353
type Storages struct {
54-
Storage *pebble.Storage
55-
Registers *pebble.RegisterStorage
56-
Blocks storage.BlockIndexer
57-
Transactions storage.TransactionIndexer
58-
Receipts storage.ReceiptIndexer
59-
Traces storage.TraceIndexer
60-
EventsHash *pebble.EventsHash
54+
Storage *pebble.Storage
55+
Registers *pebble.RegisterStorage
56+
Blocks storage.BlockIndexer
57+
Transactions storage.TransactionIndexer
58+
Receipts storage.ReceiptIndexer
59+
Traces storage.TraceIndexer
60+
FeeParameters storage.FeeParametersIndexer
61+
EventsHash *pebble.EventsHash
6162
}
6263

6364
type Publishers struct {
@@ -205,16 +206,25 @@ func (b *Bootstrap) StartEventIngestion(ctx context.Context) error {
205206
ValidateResults: true,
206207
}
207208

209+
feeParamsSubscriber := ingestion.NewFeeParamsEventSubscriber(
210+
b.logger,
211+
b.client,
212+
chainID,
213+
nextCadenceHeight,
214+
)
215+
208216
// initialize event ingestion engine
209217
b.events = ingestion.NewEventIngestionEngine(
210218
subscriber,
219+
feeParamsSubscriber,
211220
blocksProvider,
212221
b.storages.Storage,
213222
b.storages.Registers,
214223
b.storages.Blocks,
215224
b.storages.Receipts,
216225
b.storages.Transactions,
217226
b.storages.Traces,
227+
b.storages.FeeParameters,
218228
b.publishers.Block,
219229
b.publishers.Logs,
220230
b.logger,
@@ -338,6 +348,7 @@ func (b *Bootstrap) StartAPIServer(ctx context.Context) error {
338348
b.storages.Blocks,
339349
b.storages.Transactions,
340350
b.storages.Receipts,
351+
b.storages.FeeParameters,
341352
rateLimiter,
342353
b.collector,
343354
indexingResumedHeight,
@@ -680,6 +691,15 @@ func setupStorage(
680691
// // TODO(JanezP): verify storage account owner is correct
681692
// }
682693

694+
feeParameters := pebble.NewFeeParameters(store)
695+
if _, err = feeParameters.Get(); errors.Is(err, errs.ErrEntityNotFound) {
696+
if err := feeParameters.Store(models.DefaultFeeParameters, batch); err != nil {
697+
return nil, nil, fmt.Errorf("failed to bootstrap fee parameters: %w", err)
698+
}
699+
} else if err != nil {
700+
return nil, nil, fmt.Errorf("failed to load latest fee parameters: %w", err)
701+
}
702+
683703
if batch.Count() > 0 {
684704
err = batch.Commit(pebbleDB.Sync)
685705
if err != nil {
@@ -688,13 +708,14 @@ func setupStorage(
688708
}
689709

690710
return db, &Storages{
691-
Storage: store,
692-
Blocks: blocks,
693-
Registers: registerStore,
694-
Transactions: pebble.NewTransactions(store),
695-
Receipts: pebble.NewReceipts(store),
696-
Traces: pebble.NewTraces(store),
697-
EventsHash: eventsHash,
711+
Storage: store,
712+
Blocks: blocks,
713+
Registers: registerStore,
714+
Transactions: pebble.NewTransactions(store),
715+
Receipts: pebble.NewReceipts(store),
716+
Traces: pebble.NewTraces(store),
717+
FeeParameters: feeParameters,
718+
EventsHash: eventsHash,
698719
}, nil
699720
}
700721

models/events.go

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@ import (
1313
)
1414

1515
const (
16-
BlockExecutedQualifiedIdentifier = string(events.EventTypeBlockExecuted)
17-
TransactionExecutedQualifiedIdentifier = string(events.EventTypeTransactionExecuted)
16+
BlockExecutedQualifiedIdentifier = string(events.EventTypeBlockExecuted)
17+
TransactionExecutedQualifiedIdentifier = string(events.EventTypeTransactionExecuted)
18+
FeeParametersChangedQualifiedIdentifier = "FlowFees.FeeParametersChanged"
1819
)
1920

2021
// isBlockExecutedEvent checks whether the given event contains block executed data.
@@ -33,6 +34,15 @@ func isTransactionExecutedEvent(event cadence.Event) bool {
3334
return event.EventType.QualifiedIdentifier == TransactionExecutedQualifiedIdentifier
3435
}
3536

37+
// isFeeParametersChangedEvent checks whether the given event contains updates
38+
// to Flow fees parameters.
39+
func isFeeParametersChangedEvent(event cadence.Event) bool {
40+
if event.EventType == nil {
41+
return false
42+
}
43+
return event.EventType.QualifiedIdentifier == FeeParametersChangedQualifiedIdentifier
44+
}
45+
3646
// CadenceEvents contains Flow emitted events containing one or zero evm block executed event,
3747
// and multiple or zero evm transaction events.
3848
type CadenceEvents struct {
@@ -254,3 +264,34 @@ func NewBlockEventsError(err error) BlockEvents {
254264
Err: err,
255265
}
256266
}
267+
268+
type FeeParamsEvents struct {
269+
FeeParameters *FeeParameters // updates to Flow fees parameters
270+
Err error
271+
}
272+
273+
func NewFeeParamsEvents(events flow.BlockEvents) *FeeParamsEvents {
274+
for _, event := range events.Events {
275+
val := event.Value
276+
if isFeeParametersChangedEvent(val) {
277+
feeParameters, err := decodeFeeParametersChangedEvent(val)
278+
return &FeeParamsEvents{
279+
FeeParameters: feeParameters,
280+
Err: err,
281+
}
282+
}
283+
}
284+
285+
return &FeeParamsEvents{
286+
Err: fmt.Errorf(
287+
"could not find any %s events",
288+
FeeParametersChangedQualifiedIdentifier,
289+
),
290+
}
291+
}
292+
293+
func NewFeeParamsEventsError(err error) *FeeParamsEvents {
294+
return &FeeParamsEvents{
295+
Err: err,
296+
}
297+
}

models/fee_parameters.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package models
2+
3+
import (
4+
"fmt"
5+
"math/big"
6+
7+
"github.com/ethereum/go-ethereum/rlp"
8+
"github.com/onflow/cadence"
9+
)
10+
11+
const feeParamsPrecision = 100_000_000
12+
13+
var surgeFactorScale = big.NewInt(feeParamsPrecision)
14+
15+
var DefaultFeeParameters = &FeeParameters{
16+
SurgeFactor: cadence.UFix64(feeParamsPrecision),
17+
InclusionEffortCost: cadence.UFix64(feeParamsPrecision),
18+
ExecutionEffortCost: cadence.UFix64(feeParamsPrecision),
19+
}
20+
21+
type FeeParameters struct {
22+
SurgeFactor cadence.UFix64 `cadence:"surgeFactor"`
23+
InclusionEffortCost cadence.UFix64 `cadence:"inclusionEffortCost"`
24+
ExecutionEffortCost cadence.UFix64 `cadence:"executionEffortCost"`
25+
}
26+
27+
func (f *FeeParameters) ToBytes() ([]byte, error) {
28+
return rlp.EncodeToBytes(f)
29+
}
30+
31+
func (f *FeeParameters) CalculateGasPrice(currentGasPrice *big.Int) *big.Int {
32+
if currentGasPrice == nil {
33+
return new(big.Int) // zero
34+
}
35+
36+
// gasPrice = (currentGasPrice * surgeFactor) / feeParamsPrecision
37+
surgeFactor := new(big.Int).SetUint64(uint64(f.SurgeFactor))
38+
gasPrice := new(big.Int).Mul(currentGasPrice, surgeFactor)
39+
return new(big.Int).Quo(gasPrice, surgeFactorScale)
40+
}
41+
42+
func NewFeeParametersFromBytes(data []byte) (*FeeParameters, error) {
43+
feeParameters := &FeeParameters{}
44+
if err := rlp.DecodeBytes(data, feeParameters); err != nil {
45+
return nil, err
46+
}
47+
48+
return feeParameters, nil
49+
}
50+
51+
func decodeFeeParametersChangedEvent(event cadence.Event) (*FeeParameters, error) {
52+
feeParameters := &FeeParameters{}
53+
if err := cadence.DecodeFields(event, feeParameters); err != nil {
54+
return nil, fmt.Errorf(
55+
"failed to Cadence-decode FlowFees.FeeParametersChanged event [%s]: %w",
56+
event.String(),
57+
err,
58+
)
59+
}
60+
61+
return feeParameters, nil
62+
}

0 commit comments

Comments
 (0)