Skip to content

Commit 4fb6dd1

Browse files
committed
Separate receipts req and process, add tests
1 parent 2e073d0 commit 4fb6dd1

File tree

4 files changed

+6745
-71
lines changed

4 files changed

+6745
-71
lines changed

db/db_test.go

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,23 +16,27 @@ func Test_GetMissingEpochs(t *testing.T) {
1616
db.CreateTables()
1717

1818
db.StoreValidatorPerformance(schemas.ValidatorPerformanceMetrics{
19-
Time: time.Now(),
20-
Epoch: 100,
21-
EarnedBalance: big.NewInt(100),
22-
LosedBalance: big.NewInt(100),
23-
MEVRewards: big.NewInt(100),
19+
Time: time.Now(),
20+
Epoch: 100,
21+
EarnedBalance: big.NewInt(100),
22+
LosedBalance: big.NewInt(100),
23+
EffectiveBalance: big.NewInt(100),
24+
MEVRewards: big.NewInt(100),
25+
ProposerTips: big.NewInt(100),
2426
})
2527

2628
epochs, err := db.GetMissingEpochs(200, 4)
2729
require.NoError(t, err)
2830
require.Equal(t, []uint64{197, 198, 199, 200}, epochs)
2931

3032
db.StoreValidatorPerformance(schemas.ValidatorPerformanceMetrics{
31-
Time: time.Now(),
32-
Epoch: 197,
33-
EarnedBalance: big.NewInt(100),
34-
LosedBalance: big.NewInt(100),
35-
MEVRewards: big.NewInt(100),
33+
Time: time.Now(),
34+
Epoch: 197,
35+
EarnedBalance: big.NewInt(100),
36+
LosedBalance: big.NewInt(100),
37+
EffectiveBalance: big.NewInt(100),
38+
MEVRewards: big.NewInt(100),
39+
ProposerTips: big.NewInt(100),
3640
})
3741

3842
epochs, err = db.GetMissingEpochs(200, 4)

metrics/blockdata.go

Lines changed: 89 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,27 @@ func (b *BlockData) GetEpochBlockData(epoch uint64) (*EpochBlockData, error) {
7878

7979
block := beaconBlock.Data
8080

81-
b.extractWithdrawals(block, data.Withdrawals)
81+
b.ExtractWithdrawals(block, data.Withdrawals)
8282

8383
// Extract transaction fees
84-
proposerTip, err := b.GetProposerTip(block)
84+
blockNumber := b.GetBlockNumber(block)
85+
86+
retryOpts := []retry.Option{
87+
retry.Attempts(5),
88+
retry.Delay(5 * time.Second),
89+
}
90+
91+
header, err := b.getBlockHeader(blockNumber, retryOpts)
92+
if err != nil {
93+
return nil, errors.Wrap(err, "error getting block header and receipts")
94+
}
95+
rawTxs := b.GetBlockTransactions(block)
96+
receipts, err := b.getBlockReceipts(rawTxs, retryOpts)
97+
if err != nil {
98+
return nil, errors.Wrap(err, "error getting block receipts")
99+
}
100+
101+
proposerTip, err := b.GetProposerTip(block, header, receipts)
85102
if err != nil {
86103
return nil, errors.Wrap(err, "error getting proposer tip")
87104
}
@@ -95,7 +112,7 @@ func (b *BlockData) GetEpochBlockData(epoch uint64) (*EpochBlockData, error) {
95112
return data, nil
96113
}
97114

98-
func (b *BlockData) extractWithdrawals(beaconBlock *spec.VersionedSignedBeaconBlock, withdrawals map[uint64]*big.Int) {
115+
func (b *BlockData) ExtractWithdrawals(beaconBlock *spec.VersionedSignedBeaconBlock, withdrawals map[uint64]*big.Int) {
99116
blockWithdrawals := b.GetBlockWithdrawals(beaconBlock)
100117
for _, withdrawal := range blockWithdrawals {
101118
idx := uint64(withdrawal.ValidatorIndex)
@@ -106,74 +123,53 @@ func (b *BlockData) extractWithdrawals(beaconBlock *spec.VersionedSignedBeaconBl
106123
}
107124
}
108125

109-
func (b *BlockData) GetProposerTip(beaconBlock *spec.VersionedSignedBeaconBlock) (*big.Int, error) {
110-
blockNumber := b.GetBlockNumber(beaconBlock)
126+
func (b *BlockData) GetProposerTip(
127+
beaconBlock *spec.VersionedSignedBeaconBlock,
128+
header *types.Header,
129+
receipts []*types.Receipt,
130+
) (*big.Int, error) {
111131
rawTxs := b.GetBlockTransactions(beaconBlock)
112-
retryOpts := []retry.Option{
113-
retry.Attempts(5),
114-
retry.Delay(5 * time.Second),
115-
}
116-
header, err := b.getBlockHeader(blockNumber, retryOpts)
117-
if err != nil {
118-
return nil, errors.Wrap(err, "error getting block header and receipts")
119-
}
132+
120133
baseFeePerGasBytes := b.GetBaseFeePerGas(beaconBlock)
121134
baseFeePerGas := new(big.Int).SetBytes(baseFeePerGasBytes[:])
122135

123136
tips := big.NewInt(0)
124137

125-
var g errgroup.Group
126-
var mu sync.Mutex
127-
// Limit concurrent requests
128-
g.SetLimit(10)
138+
for i, rawTx := range rawTxs {
139+
var tx types.Transaction
140+
err := tx.UnmarshalBinary(rawTx)
141+
if err != nil {
142+
return nil, errors.Wrap(err, "error unmarshalling transaction")
143+
}
144+
txReceipt := receipts[i]
129145

130-
for _, rawTx := range rawTxs {
131-
g.Go(func() error {
132-
var tx types.Transaction
133-
err = tx.UnmarshalBinary(rawTx)
134-
if err != nil {
135-
return errors.Wrap(err, "error unmarshalling transaction")
136-
}
137-
txReceipt, err := b.getTransactionReceipt(&tx, retryOpts)
138-
if err != nil {
139-
return errors.Wrap(err, "error getting block receipt")
140-
}
141-
if err != nil {
142-
return errors.Wrap(err, "error unmarshalling transaction")
143-
}
144-
if tx.Hash() != txReceipt.TxHash {
145-
return errors.New("transaction hash mismatch")
146-
}
146+
if tx.Hash() != txReceipt.TxHash {
147+
return nil, errors.New("transaction hash mismatch")
148+
}
147149

148-
tipFee := new(big.Int)
149-
gasPrice := tx.GasPrice()
150-
gasUsed := big.NewInt(int64(txReceipt.GasUsed))
151-
152-
switch tx.Type() {
153-
case 0, 1:
154-
tipFee.Mul(gasPrice, gasUsed)
155-
case 2, 3, 4:
156-
tip := new(big.Int).Add(tx.GasTipCap(), header.BaseFee)
157-
gasFeeCap := tx.GasFeeCap()
158-
var usedGasPrice *big.Int
159-
if gasFeeCap.Cmp(tip) < 0 {
160-
usedGasPrice = gasFeeCap
161-
} else {
162-
usedGasPrice = tip
163-
}
164-
tipFee = new(big.Int).Mul(usedGasPrice, gasUsed)
165-
default:
166-
return errors.Errorf("unknown transaction type: %d, hash: %s", tx.Type(), tx.Hash().String())
150+
tipFee := new(big.Int)
151+
gasPrice := tx.GasPrice()
152+
gasUsed := big.NewInt(int64(txReceipt.GasUsed))
153+
154+
switch tx.Type() {
155+
case 0, 1:
156+
tipFee.Mul(gasPrice, gasUsed)
157+
case 2, 3, 4:
158+
tip := new(big.Int).Add(tx.GasTipCap(), header.BaseFee)
159+
gasFeeCap := tx.GasFeeCap()
160+
var usedGasPrice *big.Int
161+
if gasFeeCap.Cmp(tip) < 0 {
162+
usedGasPrice = gasFeeCap
163+
} else {
164+
usedGasPrice = tip
167165
}
168-
mu.Lock()
169-
tips.Add(tips, tipFee)
170-
mu.Unlock()
171-
return nil
172-
})
173-
}
174-
if err := g.Wait(); err != nil {
175-
return nil, errors.Wrap(err, "error getting proposer tip")
166+
tipFee = new(big.Int).Mul(usedGasPrice, gasUsed)
167+
default:
168+
return nil, errors.Errorf("unknown transaction type: %d, hash: %s", tx.Type(), tx.Hash().String())
169+
}
170+
tips.Add(tips, tipFee)
176171
}
172+
177173
burnt := new(big.Int).Mul(big.NewInt(int64(b.GetGasUsed(beaconBlock))), baseFeePerGas)
178174
proposerReward := new(big.Int).Sub(tips, burnt)
179175
return proposerReward, nil
@@ -203,6 +199,38 @@ func (b *BlockData) getBlockHeader(
203199
return header, nil
204200
}
205201

202+
func (b *BlockData) getBlockReceipts(rawTxs []bellatrix.Transaction, retryOpts []retry.Option) ([]*types.Receipt, error) {
203+
receipts := make([]*types.Receipt, len(rawTxs))
204+
var err error
205+
206+
var g errgroup.Group
207+
var mu sync.Mutex
208+
// Limit concurrent requests
209+
g.SetLimit(10)
210+
211+
for i, rawTx := range rawTxs {
212+
g.Go(func() error {
213+
var tx types.Transaction
214+
err = tx.UnmarshalBinary(rawTx)
215+
if err != nil {
216+
return errors.Wrap(err, "error unmarshalling transaction")
217+
}
218+
receipt, err := b.getTransactionReceipt(&tx, retryOpts)
219+
if err != nil {
220+
return errors.Wrap(err, "error getting transaction receipt")
221+
}
222+
mu.Lock()
223+
receipts[i] = receipt
224+
mu.Unlock()
225+
return nil
226+
})
227+
}
228+
if err := g.Wait(); err != nil {
229+
return nil, errors.Wrap(err, "error getting block receipts")
230+
}
231+
return receipts, nil
232+
}
233+
206234
func (b *BlockData) getTransactionReceipt(tx *types.Transaction, retryOpts []retry.Option) (*types.Receipt, error) {
207235
var receipt *types.Receipt
208236
var err error

metrics/blockdata_test.go

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
package metrics
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"io"
7+
"math/big"
8+
"os"
9+
"path/filepath"
10+
"testing"
11+
12+
"github.com/attestantio/go-eth2-client/spec"
13+
"github.com/ethereum/go-ethereum/core/types"
14+
"github.com/pkg/errors"
15+
"github.com/stretchr/testify/assert"
16+
)
17+
18+
func Test_GetProposerTip(t *testing.T) {
19+
bd := &BlockData{
20+
networkParameters: &NetworkParameters{
21+
slotsInEpoch: 32,
22+
},
23+
}
24+
25+
blockData, err := LoadBlockData(5214302)
26+
if err != nil {
27+
t.Fatalf("error loading block data: %s", err)
28+
}
29+
30+
proposerTip, err := bd.GetProposerTip(blockData.BeaconBlock, blockData.Header, blockData.Receipts)
31+
if err != nil {
32+
t.Fatalf("error getting proposer tip: %s", err)
33+
}
34+
tip := big.NewInt(38657065851824731)
35+
assert.Equal(t, proposerTip, tip)
36+
}
37+
38+
func Test_ExtractWithdrawals(t *testing.T) {
39+
bd := &BlockData{
40+
networkParameters: &NetworkParameters{
41+
slotsInEpoch: 32,
42+
},
43+
}
44+
45+
blockData, err := LoadBlockData(5214302)
46+
if err != nil {
47+
t.Fatalf("error loading block data: %s", err)
48+
}
49+
50+
withdrawals := make(map[uint64]*big.Int)
51+
bd.ExtractWithdrawals(blockData.BeaconBlock, withdrawals)
52+
assert.Equal(t, withdrawals, map[uint64]*big.Int{
53+
416729: big.NewInt(1701196),
54+
416730: big.NewInt(1731482),
55+
416731: big.NewInt(1683530),
56+
416732: big.NewInt(1765666),
57+
416733: big.NewInt(1753893),
58+
416734: big.NewInt(45764133),
59+
416735: big.NewInt(1740038),
60+
416736: big.NewInt(1736192),
61+
416737: big.NewInt(1732742),
62+
416738: big.NewInt(1776043),
63+
416739: big.NewInt(1746233),
64+
416740: big.NewInt(1713045),
65+
416741: big.NewInt(1761575),
66+
416742: big.NewInt(1719014),
67+
416743: big.NewInt(1735415),
68+
416744: big.NewInt(1714423),
69+
})
70+
}
71+
72+
type MockBlockData struct {
73+
BeaconBlock *spec.VersionedSignedBeaconBlock `json:"consensus_block"`
74+
Header *types.Header `json:"execution_header"`
75+
Receipts []*types.Receipt `json:"execution_receipts"`
76+
}
77+
78+
func LoadBlockData(slot uint64) (*MockBlockData, error) {
79+
path := filepath.Join("../mock", fmt.Sprintf("fullblock_slot_%d.json", slot))
80+
jsonFile, err := os.Open(path)
81+
if err != nil {
82+
return nil, errors.Wrap(err, "could not open json file")
83+
}
84+
defer jsonFile.Close()
85+
86+
byteValue, err := io.ReadAll(jsonFile)
87+
if err != nil {
88+
return nil, errors.Wrap(err, "could not read json file")
89+
}
90+
91+
var blockData MockBlockData
92+
93+
err = json.Unmarshal(byteValue, &blockData)
94+
if err != nil {
95+
return nil, errors.Wrap(err, "could not unmarshal json file")
96+
}
97+
98+
return &blockData, nil
99+
}

0 commit comments

Comments
 (0)