Skip to content

Commit f1651a8

Browse files
committed
WIP
1 parent 4c69cf8 commit f1651a8

10 files changed

Lines changed: 192 additions & 17 deletions

File tree

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ EMULATOR_ARGS := --flow-network-id=flow-emulator \
2323
--coa-address=$(EMULATOR_COA_ADDRESS) \
2424
--coa-key=$(EMULATOR_COA_KEY) \
2525
--wallet-api-key=2619878f0e2ff438d17835c2a4561cb87b4d24d72d12ec34569acd0dd4af7c21 \
26-
--gas-price=0 \
26+
--gas-price=100 \
2727
--log-writer=console \
2828
--tx-state-validation=local-index \
2929
--profiler-enabled=true \

api/api.go

Lines changed: 13 additions & 1 deletion
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,
@@ -1007,7 +1010,16 @@ func (b *BlockChainAPI) Coinbase(ctx context.Context) (common.Address, error) {
10071010

10081011
// GasPrice returns a suggestion for a gas price for legacy transactions.
10091012
func (b *BlockChainAPI) GasPrice(ctx context.Context) (*hexutil.Big, error) {
1010-
return (*hexutil.Big)(b.config.GasPrice), nil
1013+
feeParams, err := b.feeParameters.Get()
1014+
if err != nil {
1015+
return nil, err
1016+
}
1017+
1018+
surgeFactor := uint64(feeParams.SurgeFactor)
1019+
multiplier := new(big.Int).Exp(big.NewInt(10), big.NewInt(int64(8)), nil)
1020+
gp := b.config.GasPrice.Uint64()
1021+
gasPrice := new(big.Int).SetUint64(uint64(gp * surgeFactor))
1022+
return (*hexutil.Big)(new(big.Int).Div(gasPrice, multiplier)), nil
10111023
}
10121024

10131025
// GetUncleCountByBlockHash returns number of uncles in the block for the given block hash

bootstrap/bootstrap.go

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,13 @@ 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
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
6061
}
6162

6263
type Publishers struct {
@@ -191,6 +192,7 @@ func (b *Bootstrap) StartEventIngestion(ctx context.Context) error {
191192
b.storages.Receipts,
192193
b.storages.Transactions,
193194
b.storages.Traces,
195+
b.storages.FeeParameters,
194196
b.publishers.Block,
195197
b.publishers.Logs,
196198
b.logger,
@@ -314,6 +316,7 @@ func (b *Bootstrap) StartAPIServer(ctx context.Context) error {
314316
b.storages.Blocks,
315317
b.storages.Transactions,
316318
b.storages.Receipts,
319+
b.storages.FeeParameters,
317320
rateLimiter,
318321
b.collector,
319322
indexingResumedHeight,
@@ -645,6 +648,13 @@ func setupStorage(
645648
// // TODO(JanezP): verify storage account owner is correct
646649
// }
647650

651+
feeParameters := pebble.NewFeeParameters(store)
652+
if _, err = feeParameters.Get(); errors.Is(err, errs.ErrEntityNotFound) {
653+
if err := feeParameters.Store(models.DefaultFeeParameters, batch); err != nil {
654+
return nil, nil, fmt.Errorf("failed to bootstrap fee parameters: %w", err)
655+
}
656+
}
657+
648658
if batch.Count() > 0 {
649659
err = batch.Commit(pebbleDB.Sync)
650660
if err != nil {
@@ -653,12 +663,13 @@ func setupStorage(
653663
}
654664

655665
return db, &Storages{
656-
Storage: store,
657-
Blocks: blocks,
658-
Registers: registerStore,
659-
Transactions: pebble.NewTransactions(store),
660-
Receipts: pebble.NewReceipts(store),
661-
Traces: pebble.NewTraces(store),
666+
Storage: store,
667+
Blocks: blocks,
668+
Registers: registerStore,
669+
Transactions: pebble.NewTransactions(store),
670+
Receipts: pebble.NewReceipts(store),
671+
Traces: pebble.NewTraces(store),
672+
FeeParameters: feeParameters,
662673
}, nil
663674
}
664675

models/events.go

Lines changed: 27 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 {
@@ -42,6 +52,7 @@ type CadenceEvents struct {
4252
transactions []Transaction // transactions in the EVM block
4353
txEventPayloads []events.TransactionEventPayload // EVM.TransactionExecuted event payloads
4454
receipts []*Receipt // receipts for transactions
55+
feeParameters *FeeParameters // updates to Flow fees parameters
4556
}
4657

4758
// NewCadenceEvents decodes the events into evm types.
@@ -124,6 +135,15 @@ func decodeCadenceEvents(events flow.BlockEvents) (*CadenceEvents, error) {
124135
e.txEventPayloads = append(e.txEventPayloads, *txEventPayload)
125136
e.receipts = append(e.receipts, receipt)
126137
}
138+
139+
if isFeeParametersChangedEvent(val) {
140+
feeParameters, err := decodeFeeParametersChangedEvent(val)
141+
if err != nil {
142+
return nil, err
143+
}
144+
145+
e.feeParameters = feeParameters
146+
}
127147
}
128148

129149
// safety check, we have a missing block in the events
@@ -182,6 +202,11 @@ func (c *CadenceEvents) Receipts() []*Receipt {
182202
return c.receipts
183203
}
184204

205+
// FeeParameters returns any updates to the Flow fees parameters.
206+
func (c *CadenceEvents) FeeParameters() *FeeParameters {
207+
return c.feeParameters
208+
}
209+
185210
// Empty checks if there is an EVM block included in the events.
186211
// If there are no evm block or transactions events this is a heartbeat event.
187212
func (c *CadenceEvents) Empty() bool {

models/fee_parameters.go

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

services/ingestion/engine.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ type Engine struct {
4848
receipts storage.ReceiptIndexer
4949
transactions storage.TransactionIndexer
5050
traces storage.TraceIndexer
51+
feeParameters storage.FeeParametersIndexer
5152
log zerolog.Logger
5253
evmLastHeight *models.SequentialHeight
5354
blocksPublisher *models.Publisher[*models.Block]
@@ -65,6 +66,7 @@ func NewEventIngestionEngine(
6566
receipts storage.ReceiptIndexer,
6667
transactions storage.TransactionIndexer,
6768
traces storage.TraceIndexer,
69+
feeParameters storage.FeeParametersIndexer,
6870
blocksPublisher *models.Publisher[*models.Block],
6971
logsPublisher *models.Publisher[[]*gethTypes.Log],
7072
log zerolog.Logger,
@@ -84,6 +86,7 @@ func NewEventIngestionEngine(
8486
receipts: receipts,
8587
transactions: transactions,
8688
traces: traces,
89+
feeParameters: feeParameters,
8790
log: log,
8891
blocksPublisher: blocksPublisher,
8992
logsPublisher: logsPublisher,
@@ -217,6 +220,10 @@ func (e *Engine) processEvents(events *models.CadenceEvents) error {
217220

218221
// indexEvents will replay the evm transactions using the block events and index all results.
219222
func (e *Engine) indexEvents(events *models.CadenceEvents, batch *pebbleDB.Batch) error {
223+
if events.FeeParameters() != nil {
224+
e.feeParameters.Store(events.FeeParameters(), batch)
225+
}
226+
220227
// if heartbeat interval with no data still update the cadence height
221228
if events.Empty() {
222229
if err := e.blocks.SetLatestCadenceHeight(events.CadenceHeight(), batch); err != nil {

services/ingestion/event_subscriber.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -556,7 +556,9 @@ func (r *RPCEventSubscriber) recover(
556556
// A.{evm}.EVM.BlockExecuted and A.{evm}.EVM.TransactionExecuted,
557557
// where {evm} is EVM deployed contract address, which depends on the chain ID we configure.
558558
func blocksFilter(chainId flowGo.ChainID) flow.EventFilter {
559-
evmAddress := common.Address(systemcontracts.SystemContractsForChain(chainId).EVMContract.Address)
559+
contracts := systemcontracts.SystemContractsForChain(chainId)
560+
flowFeesAddress := common.Address(contracts.FlowFees.Address)
561+
evmAddress := common.Address(contracts.EVMContract.Address)
560562

561563
blockExecutedEvent := common.NewAddressLocation(
562564
nil,
@@ -570,10 +572,17 @@ func blocksFilter(chainId flowGo.ChainID) flow.EventFilter {
570572
string(events.EventTypeTransactionExecuted),
571573
).ID()
572574

575+
feeParametersChangedEvent := common.NewAddressLocation(
576+
nil,
577+
flowFeesAddress,
578+
"FlowFees.FeeParametersChanged",
579+
).ID()
580+
573581
return flow.EventFilter{
574582
EventTypes: []string{
575583
blockExecutedEvent,
576584
transactionExecutedEvent,
585+
feeParametersChangedEvent,
577586
},
578587
}
579588
}

storage/index.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,3 +102,9 @@ type TraceIndexer interface {
102102
// GetTransaction will retrieve transaction trace by the transaction ID.
103103
GetTransaction(ID common.Hash) (json.RawMessage, error)
104104
}
105+
106+
type FeeParametersIndexer interface {
107+
Store(feeParameters *models.FeeParameters, batch *pebble.Batch) error
108+
109+
Get() (*models.FeeParameters, error)
110+
}

storage/pebble/fee_parameters.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package pebble
2+
3+
import (
4+
"fmt"
5+
"sync"
6+
7+
"github.com/cockroachdb/pebble"
8+
"github.com/onflow/flow-evm-gateway/models"
9+
"github.com/onflow/flow-evm-gateway/storage"
10+
)
11+
12+
var _ storage.FeeParametersIndexer = &FeeParameters{}
13+
14+
type FeeParameters struct {
15+
store *Storage
16+
mu sync.Mutex
17+
}
18+
19+
func NewFeeParameters(store *Storage) *FeeParameters {
20+
return &FeeParameters{
21+
store: store,
22+
}
23+
}
24+
25+
func (f *FeeParameters) Store(feeParameters *models.FeeParameters, batch *pebble.Batch) error {
26+
f.mu.Lock()
27+
defer f.mu.Unlock()
28+
29+
val, err := feeParameters.ToBytes()
30+
if err != nil {
31+
return err
32+
}
33+
34+
if err := f.store.set(feeParametersKey, nil, val, batch); err != nil {
35+
return fmt.Errorf("failed to store fee parameters %s: %w", feeParameters, err)
36+
}
37+
38+
return nil
39+
}
40+
41+
func (f *FeeParameters) Get() (*models.FeeParameters, error) {
42+
f.mu.Lock()
43+
defer f.mu.Unlock()
44+
45+
data, err := f.store.get(feeParametersKey, nil)
46+
if err != nil {
47+
return nil, fmt.Errorf("failed to get fee parameters: %w", err)
48+
}
49+
50+
feeParameters, err := models.NewFeeParametersFromBytes(data)
51+
if err != nil {
52+
return nil, err
53+
}
54+
55+
return feeParameters, nil
56+
}

storage/pebble/keys.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ const (
2727
// registers
2828
registerKeyMarker = byte(50)
2929

30+
// fee parameters keys
31+
feeParametersKey = byte(60)
32+
3033
// special keys
3134
latestEVMHeightKey = byte(100)
3235
latestCadenceHeightKey = byte(102)

0 commit comments

Comments
 (0)