Skip to content

Commit b1cd210

Browse files
committed
Add proposer tips
1 parent fdf9605 commit b1cd210

File tree

5 files changed

+106
-47
lines changed

5 files changed

+106
-47
lines changed

db/db.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ CREATE TABLE IF NOT EXISTS t_pools_metrics_summary (
3232
f_epoch_lost_balace_gwei BIGINT,
3333
f_epoch_effective_balance_gwei BIGINT,
3434
f_mev_rewards_wei BIGINT,
35+
f_proposer_tips_wei BIGINT,
3536
3637
f_n_scheduled_blocks BIGINT,
3738
f_n_proposed_blocks BIGINT,
@@ -98,8 +99,9 @@ INSERT INTO t_pools_metrics_summary(
9899
f_epoch_effective_balance_gwei,
99100
f_epoch_earned_balance_gwei,
100101
f_epoch_lost_balace_gwei,
101-
f_mev_rewards_wei)
102-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
102+
f_mev_rewards_wei,
103+
f_proposer_tips_wei)
104+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
103105
ON CONFLICT (f_epoch, f_pool)
104106
DO UPDATE SET
105107
f_timestamp=EXCLUDED.f_timestamp,
@@ -115,7 +117,8 @@ DO UPDATE SET
115117
f_epoch_effective_balance_gwei=EXCLUDED.f_epoch_effective_balance_gwei,
116118
f_epoch_earned_balance_gwei=EXCLUDED.f_epoch_earned_balance_gwei,
117119
f_epoch_lost_balace_gwei=EXCLUDED.f_epoch_lost_balace_gwei,
118-
f_mev_rewards_wei=EXCLUDED.f_mev_rewards_wei
120+
f_mev_rewards_wei=EXCLUDED.f_mev_rewards_wei,
121+
f_proposer_tips_wei=EXCLUDED.f_proposer_tips_wei
119122
`
120123

121124
// TODO: Add f_epoch_timestamp
@@ -236,6 +239,7 @@ func (a *Database) StoreValidatorPerformance(validatorPerformance schemas.Valida
236239
validatorPerformance.EarnedBalance.Int64(),
237240
validatorPerformance.LosedBalance.Int64(),
238241
validatorPerformance.MEVRewards.Int64(),
242+
validatorPerformance.ProposerTips.Int64(),
239243
)
240244

241245
if err != nil {

metrics/beaconstate.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ func (p *BeaconState) Run(
5454
prevBeaconState *spec.VersionedBeaconState,
5555
valKeyToIndex map[string]uint64,
5656
relayRewards *big.Int,
57-
validatorIndexToWithdrawalAmount map[uint64]*big.Int) error {
57+
validatorIndexToWithdrawalAmount map[uint64]*big.Int,
58+
proposerTips map[uint64]*big.Int) error {
5859

5960
if currentBeaconState == nil || prevBeaconState == nil {
6061
return errors.New("current or previous beacon state is nil")
@@ -97,6 +98,12 @@ func (p *BeaconState) Run(
9798
metrics.NOfActiveValidators = uint64(len(activeValidatorIndexes))
9899
metrics.MEVRewards = relayRewards
99100

101+
aggregatedProposerTips := big.NewInt(0)
102+
for _, activeValidatorIndex := range activeValidatorIndexes {
103+
aggregatedProposerTips.Add(aggregatedProposerTips, proposerTips[activeValidatorIndex])
104+
}
105+
metrics.ProposerTips = aggregatedProposerTips
106+
100107
syncCommitteeKeys := BLSPubKeyToByte(GetCurrentSyncCommittee(currentBeaconState))
101108
syncCommitteeIndexes := GetIndexesFromKeys(syncCommitteeKeys, valKeyToIndex)
102109
poolSyncIndexes := GetValidatorsIn(syncCommitteeIndexes, activeValidatorIndexes)

metrics/blockdata.go

Lines changed: 71 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,14 @@ import (
1616
"github.com/bilinearlabs/eth-metrics/config"
1717
"github.com/ethereum/go-ethereum/core/types"
1818
"github.com/ethereum/go-ethereum/ethclient"
19+
"github.com/ethereum/go-ethereum/rlp"
1920
"github.com/pkg/errors"
2021
log "github.com/sirupsen/logrus"
2122
)
2223

2324
type EpochBlockData struct {
24-
Withdrawals map[uint64]*big.Int
25+
Withdrawals map[uint64]*big.Int
26+
ProposerTips map[uint64]*big.Int
2527
}
2628

2729
type BlockData struct {
@@ -49,7 +51,8 @@ func (b *BlockData) GetEpochBlockData(epoch uint64) (*EpochBlockData, error) {
4951
log.Info("Fetching block data for epoch: ", epoch)
5052

5153
data := &EpochBlockData{
52-
Withdrawals: make(map[uint64]*big.Int),
54+
Withdrawals: make(map[uint64]*big.Int),
55+
ProposerTips: make(map[uint64]*big.Int),
5356
}
5457

5558
firstSlot := epoch * b.networkParameters.slotsInEpoch
@@ -76,12 +79,16 @@ func (b *BlockData) GetEpochBlockData(epoch uint64) (*EpochBlockData, error) {
7679

7780
b.extractWithdrawals(block, data.Withdrawals)
7881

79-
// Extract transaction fees (add when needed)
82+
// Extract transaction fees
8083
proposerTip, err := b.GetProposerTip(block)
8184
if err != nil {
8285
return nil, errors.Wrap(err, "error getting proposer tip")
8386
}
84-
// TODO get proposer index of this block and add to data
87+
proposerIndex := b.GetProposerIndex(block)
88+
if _, ok := data.ProposerTips[proposerIndex]; !ok {
89+
data.ProposerTips[proposerIndex] = big.NewInt(0)
90+
}
91+
data.ProposerTips[proposerIndex].Add(data.ProposerTips[proposerIndex], proposerTip)
8592
}
8693

8794
return data, nil
@@ -101,27 +108,36 @@ func (b *BlockData) extractWithdrawals(beaconBlock *spec.VersionedSignedBeaconBl
101108
func (b *BlockData) GetProposerTip(beaconBlock *spec.VersionedSignedBeaconBlock) (*big.Int, error) {
102109
blockNumber := b.GetBlockNumber(beaconBlock)
103110
rawTxs := b.GetBlockTransactions(beaconBlock)
104-
header, receipts, err := b.getBlockHeaderAndReceipts(blockNumber, rawTxs)
111+
retryOpts := []retry.Option{
112+
retry.Attempts(5),
113+
retry.Delay(5 * time.Second),
114+
}
115+
header, err := b.getBlockHeader(blockNumber, retryOpts)
105116
if err != nil {
106117
return nil, errors.Wrap(err, "error getting block header and receipts")
107118
}
108119
baseFeePerGasBytes := b.GetBaseFeePerGas(beaconBlock)
109120
baseFeePerGas := new(big.Int).SetBytes(baseFeePerGasBytes[:])
110121

111122
tips := big.NewInt(0)
112-
for i, rawTx := range rawTxs {
113-
var tx *types.Transaction
114-
err = tx.UnmarshalBinary(rawTx)
123+
for _, rawTx := range rawTxs {
124+
println(rawTx)
125+
txReceipt, err := b.getTransactionReceipt(rawTx, retryOpts)
126+
if err != nil {
127+
return nil, errors.Wrap(err, "error getting block receipt")
128+
}
129+
var tx types.Transaction
130+
err = rlp.DecodeBytes(rawTx, &tx)
115131
if err != nil {
116132
return nil, errors.Wrap(err, "error unmarshalling transaction")
117133
}
118-
if tx.Hash() != receipts[i].TxHash {
134+
if tx.Hash() != txReceipt.TxHash {
119135
return nil, errors.New("transaction hash mismatch")
120136
}
121137

122138
tipFee := new(big.Int)
123139
gasPrice := tx.GasPrice()
124-
gasUsed := big.NewInt(int64(receipts[i].GasUsed))
140+
gasUsed := big.NewInt(int64(txReceipt.GasUsed))
125141

126142
switch tx.Type() {
127143
case 0, 1:
@@ -139,25 +155,21 @@ func (b *BlockData) GetProposerTip(beaconBlock *spec.VersionedSignedBeaconBlock)
139155
default:
140156
return nil, errors.Errorf("unknown transaction type: %d, hash: %s", tx.Type(), tx.Hash().String())
141157
}
158+
tips.Add(tips, tipFee)
142159
}
143160
burnt := new(big.Int).Mul(big.NewInt(int64(b.GetGasUsed(beaconBlock))), baseFeePerGas)
144161
proposerReward := new(big.Int).Sub(tips, burnt)
145162
return proposerReward, nil
146163
}
147164

148-
func (b *BlockData) getBlockHeaderAndReceipts(
165+
func (b *BlockData) getBlockHeader(
149166
blockNumber uint64,
150-
rawTxs []bellatrix.Transaction,
151-
) (*types.Header, []*types.Receipt, error) {
152-
167+
retryOpts []retry.Option,
168+
) (*types.Header, error) {
153169
var header *types.Header
154170
var err error
155171

156172
blockNumberBig := new(big.Int).SetUint64(blockNumber)
157-
retryOpts := []retry.Option{
158-
retry.Attempts(5),
159-
retry.Delay(5 * time.Second),
160-
}
161173

162174
err = retry.Do(func() error {
163175
header, err = b.executionClient.HeaderByNumber(context.Background(), blockNumberBig)
@@ -168,32 +180,33 @@ func (b *BlockData) getBlockHeaderAndReceipts(
168180
return nil
169181
}, retryOpts...)
170182
if err != nil {
171-
return nil, nil, errors.Wrap(err, "error getting header for block "+blockNumberBig.String())
183+
return nil, errors.Wrap(err, "error getting header for block "+blockNumberBig.String())
172184
}
173185

174-
var receipts []*types.Receipt = make([]*types.Receipt, 0)
175-
for _, rawTx := range rawTxs {
176-
var tx *types.Transaction
177-
err = tx.UnmarshalBinary(rawTx)
178-
if err != nil {
179-
return nil, nil, errors.Wrap(err, "error unmarshalling transaction")
180-
}
181-
var receipt *types.Receipt
182-
err = retry.Do(func() error {
183-
receipt, err = b.executionClient.TransactionReceipt(context.Background(), tx.Hash())
184-
if err != nil {
185-
log.Warnf("error getting transaction receipt for tx %s: %s. Retrying...", tx.Hash().String(), err)
186-
return errors.Wrap(err, "error getting transaction receipt for block")
187-
}
188-
return nil
189-
}, retryOpts...)
186+
return header, nil
187+
}
188+
189+
func (b *BlockData) getTransactionReceipt(rawTx []byte, retryOpts []retry.Option) (*types.Receipt, error) {
190+
var tx types.Transaction
191+
err := tx.UnmarshalBinary(rawTx)
192+
if err != nil {
193+
return nil, errors.Wrap(err, "error unmarshalling transaction")
194+
}
195+
var receipt *types.Receipt
196+
err = retry.Do(func() error {
197+
receipt, err = b.executionClient.TransactionReceipt(context.Background(), tx.Hash())
190198
if err != nil {
191-
return nil, nil, errors.Wrap(err, "error getting transaction receipt for block "+blockNumberBig.String())
199+
log.Warnf("error getting transaction receipt for tx %s: %s. Retrying...", tx.Hash().String(), err)
200+
return errors.Wrap(err, "error getting transaction receipt")
192201
}
193-
receipts = append(receipts, receipt)
202+
return nil
203+
}, retryOpts...)
204+
205+
if err != nil {
206+
return nil, errors.Wrap(err, "error getting transaction receipt for tx "+tx.Hash().String())
194207
}
195208

196-
return header, receipts, nil
209+
return receipt, nil
197210
}
198211

199212
func (b *BlockData) GetBlockWithdrawals(beaconBlock *spec.VersionedSignedBeaconBlock) []*capella.Withdrawal {
@@ -304,3 +317,23 @@ func (b *BlockData) GetGasUsed(beaconBlock *spec.VersionedSignedBeaconBlock) uin
304317
}
305318
return gasUsed
306319
}
320+
321+
func (b *BlockData) GetProposerIndex(beaconBlock *spec.VersionedSignedBeaconBlock) uint64 {
322+
var proposerIndex uint64
323+
if beaconBlock.Altair != nil {
324+
proposerIndex = uint64(beaconBlock.Altair.Message.ProposerIndex)
325+
} else if beaconBlock.Bellatrix != nil {
326+
proposerIndex = uint64(beaconBlock.Bellatrix.Message.ProposerIndex)
327+
} else if beaconBlock.Capella != nil {
328+
proposerIndex = uint64(beaconBlock.Capella.Message.ProposerIndex)
329+
} else if beaconBlock.Deneb != nil {
330+
proposerIndex = uint64(beaconBlock.Deneb.Message.ProposerIndex)
331+
} else if beaconBlock.Electra != nil {
332+
proposerIndex = uint64(beaconBlock.Electra.Message.ProposerIndex)
333+
} else if beaconBlock.Fulu != nil {
334+
proposerIndex = uint64(beaconBlock.Fulu.Message.ProposerIndex)
335+
} else {
336+
log.Fatal("Beacon block was empty")
337+
}
338+
return proposerIndex
339+
}

metrics/metrics.go

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,14 @@ import (
1010
"strings"
1111
"time"
1212

13+
nethttp "net/http"
14+
1315
"github.com/attestantio/go-eth2-client/api"
1416
"github.com/attestantio/go-eth2-client/http"
1517
"github.com/attestantio/go-eth2-client/spec"
1618
"github.com/ethereum/go-ethereum/common/hexutil"
1719
"github.com/ethereum/go-ethereum/ethclient"
20+
"github.com/ethereum/go-ethereum/rpc"
1821
"github.com/rs/zerolog"
1922

2023
"github.com/bilinearlabs/eth-metrics/config"
@@ -138,11 +141,21 @@ func NewMetrics(
138141
log.Info("Slots per epoch: ", slotsPerEpoch)
139142
log.Info("Seconds per slot: ", secondsPerSlot)
140143

141-
executionClient, err := ethclient.Dial(config.Eth1Address)
144+
rcpClient, err := rpc.DialOptions(
145+
context.Background(),
146+
config.Eth1Address,
147+
rpc.WithHTTPAuth(func(h nethttp.Header) error {
148+
h.Set("Authorization", "Basic "+encodedCredentials)
149+
return nil
150+
}),
151+
rpc.WithHTTPClient(&nethttp.Client{Timeout: 60 * time.Second}),
152+
)
142153
if err != nil {
143154
return nil, errors.Wrap(err, "error dialing execution client")
144155
}
145156

157+
executionClient := ethclient.NewClient(rcpClient)
158+
146159
networkParameters := &NetworkParameters{
147160
genesisSeconds: uint64(genesis.Data.GenesisTime.Unix()),
148161
slotsInEpoch: slotsPerEpoch,
@@ -351,11 +364,12 @@ func (a *Metrics) ProcessEpoch(
351364
}
352365

353366
// Get withdrawals from all blocks of the epoch
354-
blockData, err := a.blockData.GetEpochBlockData(currentEpoch)
367+
epochBlockData, err := a.blockData.GetEpochBlockData(currentEpoch)
355368
if err != nil {
356-
return nil, errors.Wrap(err, "error getting epoch withdrawals")
369+
return nil, errors.Wrap(err, "error getting epoch block data")
357370
}
358-
validatorIndexToWithdrawalAmount := blockData.Withdrawals
371+
validatorIndexToWithdrawalAmount := epochBlockData.Withdrawals
372+
proposerTips := epochBlockData.ProposerTips
359373

360374
err = a.networkStats.Run(currentEpoch, currentBeaconState)
361375
if err != nil {
@@ -370,7 +384,7 @@ func (a *Metrics) ProcessEpoch(
370384
if reward, ok := relayRewardsPerPool[poolName]; ok {
371385
relayRewards.Add(relayRewards, reward)
372386
}
373-
err = a.beaconState.Run(pubKeys, poolName, currentBeaconState, prevBeaconState, valKeyToIndex, relayRewards, validatorIndexToWithdrawalAmount)
387+
err = a.beaconState.Run(pubKeys, poolName, currentBeaconState, prevBeaconState, valKeyToIndex, relayRewards, validatorIndexToWithdrawalAmount, proposerTips)
374388
if err != nil {
375389
return nil, errors.Wrap(err, "error running beacon state")
376390
}

schemas/schemas.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ type ValidatorPerformanceMetrics struct {
2727
TotalRewards *big.Int
2828
DeltaEpochBalance *big.Int
2929
MEVRewards *big.Int
30+
ProposerTips *big.Int
3031
}
3132

3233
type ValidatorStatusMetrics struct {

0 commit comments

Comments
 (0)