Skip to content

Commit 04edb47

Browse files
authored
fix: preconf RPC CORS headers (#752)
1 parent cf71760 commit 04edb47

9 files changed

Lines changed: 340 additions & 232 deletions

File tree

tools/preconf-rpc/blocktracker/blocktracker.go

Lines changed: 42 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@ package blocktracker
22

33
import (
44
"context"
5+
"errors"
56
"log/slog"
67
"math/big"
8+
"sync"
79
"sync/atomic"
810
"time"
911

@@ -22,7 +24,7 @@ type blockTracker struct {
2224
blocks *lru.Cache[uint64, *types.Block]
2325
client EthClient
2426
log *slog.Logger
25-
checkTrigger chan struct{}
27+
checkCond *sync.Cond
2628
}
2729

2830
func NewBlockTracker(client EthClient, log *slog.Logger) (*blockTracker, error) {
@@ -36,7 +38,7 @@ func NewBlockTracker(client EthClient, log *slog.Logger) (*blockTracker, error)
3638
blocks: cache,
3739
client: client,
3840
log: log,
39-
checkTrigger: make(chan struct{}, 1),
41+
checkCond: sync.NewCond(&sync.Mutex{}),
4042
}, nil
4143
}
4244

@@ -63,8 +65,8 @@ func (b *blockTracker) Start(ctx context.Context) <-chan struct{} {
6365
}
6466
_ = b.blocks.Add(blockNo, block)
6567
b.latestBlockNo.Store(block.NumberU64())
66-
b.log.Debug("New block detected", "number", block.NumberU64(), "hash", block.Hash().Hex())
6768
b.triggerCheck()
69+
b.log.Debug("New block detected", "number", block.NumberU64(), "hash", block.Hash().Hex())
6870
}
6971
}
7072
}
@@ -73,48 +75,66 @@ func (b *blockTracker) Start(ctx context.Context) <-chan struct{} {
7375
}
7476

7577
func (b *blockTracker) triggerCheck() {
76-
select {
77-
case b.checkTrigger <- struct{}{}:
78-
default:
79-
// Non-blocking send, if channel is full, we skip
80-
}
78+
b.checkCond.L.Lock()
79+
b.checkCond.Broadcast()
80+
b.checkCond.L.Unlock()
8181
}
8282

8383
func (b *blockTracker) LatestBlockNumber() uint64 {
8484
return b.latestBlockNo.Load()
8585
}
8686

87+
func (b *blockTracker) NextBlockNumber() (uint64, time.Duration, error) {
88+
block, found := b.blocks.Get(b.latestBlockNo.Load())
89+
if !found {
90+
return 0, 0, errors.New("latest block not found in cache")
91+
}
92+
blockTime := time.Unix(int64(block.Time()), 0)
93+
return b.latestBlockNo.Load() + 1, time.Until(blockTime.Add(12 * time.Second)), nil
94+
}
95+
8796
func (b *blockTracker) CheckTxnInclusion(
8897
ctx context.Context,
8998
txHash common.Hash,
9099
blockNumber uint64,
91100
) (bool, error) {
92-
WaitForBlock:
93-
for {
94-
select {
95-
case <-ctx.Done():
96-
return false, ctx.Err()
97-
case <-b.checkTrigger:
98-
if blockNumber <= b.latestBlockNo.Load() {
99-
break WaitForBlock
100-
}
101+
if blockNumber <= b.latestBlockNo.Load() {
102+
return b.checkTxnInclusion(ctx, txHash, blockNumber)
103+
}
104+
105+
waitCh := make(chan struct{})
106+
go func() {
107+
b.checkCond.L.Lock()
108+
defer b.checkCond.L.Unlock()
109+
for blockNumber > b.latestBlockNo.Load() {
110+
b.checkCond.Wait()
101111
}
112+
close(waitCh)
113+
}()
114+
115+
select {
116+
case <-ctx.Done():
117+
return false, ctx.Err()
118+
case <-waitCh:
119+
return b.checkTxnInclusion(ctx, txHash, blockNumber)
102120
}
121+
}
103122

123+
func (b *blockTracker) checkTxnInclusion(ctx context.Context, txHash common.Hash, blockNumber uint64) (bool, error) {
124+
var err error
104125
block, ok := b.blocks.Get(blockNumber)
105126
if !ok {
106-
block, err := b.client.BlockByNumber(ctx, big.NewInt(int64(blockNumber)))
127+
block, err = b.client.BlockByNumber(ctx, big.NewInt(int64(blockNumber)))
107128
if err != nil {
108129
b.log.Error("Failed to get block by number", "error", err, "blockNumber", blockNumber)
109130
return false, err
110131
}
111132
_ = b.blocks.Add(blockNumber, block)
112133
}
113134

114-
for _, tx := range block.Transactions() {
115-
if tx.Hash().Cmp(txHash) == 0 {
116-
return true, nil
117-
}
135+
if txn := block.Transaction(txHash); txn != nil {
136+
return true, nil
118137
}
138+
119139
return false, nil
120140
}

tools/preconf-rpc/blocktracker/blocktracker_test.go

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@ package blocktracker_test
33
import (
44
"context"
55
"hash"
6-
"log/slog"
76
"math/big"
7+
"os"
88
"testing"
9+
"time"
910

1011
"github.com/ethereum/go-ethereum/common"
1112
"github.com/ethereum/go-ethereum/core/types"
1213
"github.com/primev/mev-commit/tools/preconf-rpc/blocktracker"
14+
"github.com/primev/mev-commit/x/util"
1315
"golang.org/x/crypto/sha3"
1416
)
1517

@@ -74,7 +76,7 @@ func TestBlockTracker(t *testing.T) {
7476
blk1 := types.NewBlock(
7577
&types.Header{
7678
Number: big.NewInt(100),
77-
Time: 1622547800,
79+
Time: uint64(time.Now().Unix()),
7880
},
7981
&types.Body{Transactions: []*types.Transaction{tx1, tx2}},
8082
nil, // No receipts
@@ -84,7 +86,7 @@ func TestBlockTracker(t *testing.T) {
8486
blk2 := types.NewBlock(
8587
&types.Header{
8688
Number: big.NewInt(101),
87-
Time: 1622547900,
89+
Time: uint64(time.Now().Add(12 * time.Second).Unix()),
8890
},
8991
&types.Body{Transactions: []*types.Transaction{tx3}},
9092
nil, // No receipts
@@ -99,7 +101,7 @@ func TestBlockTracker(t *testing.T) {
99101
},
100102
}
101103

102-
tracker, err := blocktracker.NewBlockTracker(client, slog.Default())
104+
tracker, err := blocktracker.NewBlockTracker(client, util.NewTestLogger(os.Stdout))
103105
if err != nil {
104106
t.Fatalf("Failed to create block tracker: %v", err)
105107
}
@@ -112,6 +114,26 @@ func TestBlockTracker(t *testing.T) {
112114

113115
client.blockNumber <- 100
114116

117+
start := time.Now()
118+
for {
119+
bidBlockNo, duration, err := tracker.NextBlockNumber()
120+
if err == nil {
121+
if bidBlockNo != 101 {
122+
t.Fatalf("Expected next block number to be 101, got %d", bidBlockNo)
123+
}
124+
if duration <= 0 {
125+
t.Fatalf("Expected positive duration, got %v", duration)
126+
}
127+
break
128+
} else {
129+
t.Logf("Waiting for next block number: %v", err)
130+
}
131+
if time.Since(start) > 5*time.Second {
132+
t.Fatalf("Timeout waiting for next block number")
133+
}
134+
time.Sleep(100 * time.Millisecond)
135+
}
136+
115137
included, err := tracker.CheckTxnInclusion(ctx, tx1.Hash(), 100)
116138
if err != nil {
117139
t.Fatalf("Error checking transaction inclusion: %v", err)
@@ -128,6 +150,22 @@ func TestBlockTracker(t *testing.T) {
128150

129151
client.blockNumber <- 101
130152

153+
start = time.Now()
154+
for {
155+
bidBlockNo, duration, err := tracker.NextBlockNumber()
156+
if err == nil {
157+
if bidBlockNo == 102 && duration > 0 {
158+
break
159+
}
160+
} else {
161+
t.Logf("Waiting for next block number: %v", err)
162+
}
163+
if time.Since(start) > 5*time.Second {
164+
t.Fatalf("Timeout waiting for next block number")
165+
}
166+
time.Sleep(100 * time.Millisecond)
167+
}
168+
131169
included, err = tracker.CheckTxnInclusion(ctx, tx4.Hash(), 101)
132170
if err != nil {
133171
t.Fatalf("Error checking transaction inclusion: %v", err)

tools/preconf-rpc/handlers/handlers.go

Lines changed: 8 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import (
1212
"github.com/ethereum/go-ethereum/common/hexutil"
1313
"github.com/ethereum/go-ethereum/core/types"
1414
bidderapiv1 "github.com/primev/mev-commit/p2p/gen/go/bidderapi/v1"
15-
"github.com/primev/mev-commit/tools/preconf-rpc/pricer"
1615
"github.com/primev/mev-commit/tools/preconf-rpc/rpcserver"
1716
"github.com/primev/mev-commit/tools/preconf-rpc/sender"
1817
)
@@ -22,7 +21,7 @@ type Bidder interface {
2221
}
2322

2423
type Pricer interface {
25-
EstimatePrice(ctx context.Context) (*pricer.BlockPrices, error)
24+
EstimatePrice(ctx context.Context) map[int64]float64
2625
}
2726

2827
type Store interface {
@@ -135,14 +134,7 @@ func (h *rpcMethodHandler) RegisterMethods(server *rpcserver.JSONRPCServer) {
135134
return json.RawMessage(fmt.Sprintf(`{"timeInSecs": "%d"}`, timeToOptIn)), false, nil
136135
})
137136
server.RegisterHandler("mevcommit_estimateDeposit", func(ctx context.Context, params ...any) (json.RawMessage, bool, error) {
138-
blockPrices, err := h.pricer.EstimatePrice(ctx)
139-
if err != nil {
140-
h.logger.Error("Failed to estimate deposit price", "error", err)
141-
return nil, false, rpcserver.NewJSONErr(
142-
rpcserver.CodeCustomError,
143-
"failed to estimate deposit price",
144-
)
145-
}
137+
blockPrices := h.pricer.EstimatePrice(ctx)
146138
cost := getNextBlockPrice(blockPrices)
147139
result := map[string]interface{}{
148140
"bidAmount": cost.String(),
@@ -161,14 +153,7 @@ func (h *rpcMethodHandler) RegisterMethods(server *rpcserver.JSONRPCServer) {
161153
return resultJSON, false, nil
162154
})
163155
server.RegisterHandler("mevcommit_estimateBridge", func(ctx context.Context, params ...any) (json.RawMessage, bool, error) {
164-
blockPrices, err := h.pricer.EstimatePrice(ctx)
165-
if err != nil {
166-
h.logger.Error("Failed to estimate bridge price", "error", err)
167-
return nil, false, rpcserver.NewJSONErr(
168-
rpcserver.CodeCustomError,
169-
"failed to estimate bridge price",
170-
)
171-
}
156+
blockPrices := h.pricer.EstimatePrice(ctx)
172157
cost := getNextBlockPrice(blockPrices)
173158
bridgeCost := new(big.Int).Mul(cost, big.NewInt(2))
174159
result := map[string]interface{}{
@@ -192,15 +177,11 @@ func (h *rpcMethodHandler) RegisterMethods(server *rpcserver.JSONRPCServer) {
192177
server.RegisterHandler("mevcommit_getBalance", h.handleMevCommitGetBalance)
193178
}
194179

195-
func getNextBlockPrice(blockPrices *pricer.BlockPrices) *big.Int {
196-
for _, price := range blockPrices.Prices {
197-
if price.BlockNumber == blockPrices.CurrentBlockNumber+1 {
198-
for _, estimate := range price.EstimatedPrices {
199-
if estimate.Confidence == 99 {
200-
priceInWei := estimate.PriorityFeePerGasGwei * 1e9
201-
return new(big.Int).Mul(new(big.Int).SetUint64(uint64(priceInWei)), big.NewInt(21000))
202-
}
203-
}
180+
func getNextBlockPrice(blockPrices map[int64]float64) *big.Int {
181+
for confidence, price := range blockPrices {
182+
if confidence == 99 {
183+
priceInWei := price * 1e9 // Convert Gwei to Wei
184+
return new(big.Int).Mul(new(big.Int).SetUint64(uint64(priceInWei)), big.NewInt(21000))
204185
}
205186
}
206187

0 commit comments

Comments
 (0)