@@ -2,7 +2,11 @@ package rpc
22
33import (
44 "context"
5+ "fmt"
56 "math/big"
7+ "time"
8+
9+ "github.com/ethereum/go-ethereum"
610
711 "github.com/ethereum/go-ethereum/common"
812 "github.com/ethereum/go-ethereum/core/types"
@@ -11,21 +15,28 @@ import (
1115)
1216
1317type ExecutionClient struct {
14- name string
15- endpoint string
16- headers map [string ]string
17- rpcClient * rpc.Client
18- ethClient * ethclient.Client
18+ name string
19+ endpoint string
20+ headers map [string ]string
21+ rpcClient * rpc.Client
22+ ethClient * ethclient.Client
23+ concurrencyLimit int
24+ requestTimeout time.Duration
25+ concurrencyChan chan struct {}
1926}
2027
2128// NewExecutionClient is used to create a new execution client
2229func NewExecutionClient (name , url string , headers map [string ]string ) (* ExecutionClient , error ) {
2330 client := & ExecutionClient {
24- name : name ,
25- endpoint : url ,
26- headers : headers ,
31+ name : name ,
32+ endpoint : url ,
33+ headers : headers ,
34+ concurrencyLimit : 50 ,
35+ requestTimeout : 30 * time .Second ,
2736 }
2837
38+ client .concurrencyChan = make (chan struct {}, client .concurrencyLimit )
39+
2940 return client , nil
3041}
3142
@@ -49,6 +60,17 @@ func (ec *ExecutionClient) Initialize(ctx context.Context) error {
4960 return nil
5061}
5162
63+ func (ec * ExecutionClient ) enforceConcurrencyLimit (ctx context.Context ) func () {
64+ select {
65+ case <- ctx .Done ():
66+ return func () {}
67+ case ec .concurrencyChan <- struct {}{}:
68+ return func () {
69+ <- ec .concurrencyChan
70+ }
71+ }
72+ }
73+
5274func (ec * ExecutionClient ) GetEthClient () * ethclient.Client {
5375 return ec .ethClient
5476}
@@ -77,7 +99,7 @@ func (ec *ExecutionClient) GetNodeSyncing(ctx context.Context) (*SyncStatus, err
7799 return nil , err
78100 }
79101
80- if status == nil && err == nil {
102+ if status == nil {
81103 // Not syncing
82104 ss := & SyncStatus {}
83105 ss .IsSyncing = false
@@ -94,7 +116,10 @@ func (ec *ExecutionClient) GetNodeSyncing(ctx context.Context) (*SyncStatus, err
94116}
95117
96118func (ec * ExecutionClient ) GetLatestBlock (ctx context.Context ) (* types.Block , error ) {
97- block , err := ec .ethClient .BlockByNumber (ctx , nil )
119+ reqCtx , reqCtxCancel := context .WithTimeout (ctx , ec .requestTimeout )
120+ defer reqCtxCancel ()
121+
122+ block , err := ec .ethClient .BlockByNumber (reqCtx , nil )
98123 if err != nil {
99124 return nil , err
100125 }
@@ -103,7 +128,10 @@ func (ec *ExecutionClient) GetLatestBlock(ctx context.Context) (*types.Block, er
103128}
104129
105130func (ec * ExecutionClient ) GetBlockByHash (ctx context.Context , hash common.Hash ) (* types.Block , error ) {
106- block , err := ec .ethClient .BlockByHash (ctx , hash )
131+ reqCtx , reqCtxCancel := context .WithTimeout (ctx , ec .requestTimeout )
132+ defer reqCtxCancel ()
133+
134+ block , err := ec .ethClient .BlockByHash (reqCtx , hash )
107135 if err != nil {
108136 return nil , err
109137 }
@@ -112,17 +140,85 @@ func (ec *ExecutionClient) GetBlockByHash(ctx context.Context, hash common.Hash)
112140}
113141
114142func (ec * ExecutionClient ) GetNonceAt (ctx context.Context , wallet common.Address , blockNumber * big.Int ) (uint64 , error ) {
115- return ec .ethClient .NonceAt (ctx , wallet , blockNumber )
143+ closeFn := ec .enforceConcurrencyLimit (ctx )
144+ if closeFn == nil {
145+ return 0 , fmt .Errorf ("client busy" )
146+ }
147+
148+ defer closeFn ()
149+
150+ reqCtx , reqCtxCancel := context .WithTimeout (ctx , ec .requestTimeout )
151+ defer reqCtxCancel ()
152+
153+ return ec .ethClient .NonceAt (reqCtx , wallet , blockNumber )
116154}
117155
118156func (ec * ExecutionClient ) GetBalanceAt (ctx context.Context , wallet common.Address , blockNumber * big.Int ) (* big.Int , error ) {
119- return ec .ethClient .BalanceAt (ctx , wallet , blockNumber )
157+ closeFn := ec .enforceConcurrencyLimit (ctx )
158+ if closeFn == nil {
159+ return nil , fmt .Errorf ("client busy" )
160+ }
161+
162+ defer closeFn ()
163+
164+ reqCtx , reqCtxCancel := context .WithTimeout (ctx , ec .requestTimeout )
165+ defer reqCtxCancel ()
166+
167+ return ec .ethClient .BalanceAt (reqCtx , wallet , blockNumber )
120168}
121169
122170func (ec * ExecutionClient ) GetTransactionReceipt (ctx context.Context , txHash common.Hash ) (* types.Receipt , error ) {
123- return ec .ethClient .TransactionReceipt (ctx , txHash )
171+ closeFn := ec .enforceConcurrencyLimit (ctx )
172+ if closeFn == nil {
173+ return nil , fmt .Errorf ("client busy" )
174+ }
175+
176+ defer closeFn ()
177+
178+ reqCtx , reqCtxCancel := context .WithTimeout (ctx , ec .requestTimeout )
179+ defer reqCtxCancel ()
180+
181+ return ec .ethClient .TransactionReceipt (reqCtx , txHash )
182+ }
183+
184+ func (ec * ExecutionClient ) GetBlockReceipts (ctx context.Context , blockHash common.Hash ) ([]* types.Receipt , error ) {
185+ closeFn := ec .enforceConcurrencyLimit (ctx )
186+ if closeFn == nil {
187+ return nil , fmt .Errorf ("client busy" )
188+ }
189+
190+ defer closeFn ()
191+
192+ reqCtx , reqCtxCancel := context .WithTimeout (ctx , ec .requestTimeout )
193+ defer reqCtxCancel ()
194+
195+ return ec .ethClient .BlockReceipts (reqCtx , rpc.BlockNumberOrHash {
196+ BlockHash : & blockHash ,
197+ })
124198}
125199
126200func (ec * ExecutionClient ) SendTransaction (ctx context.Context , tx * types.Transaction ) error {
127- return ec .ethClient .SendTransaction (ctx , tx )
201+ closeFn := ec .enforceConcurrencyLimit (ctx )
202+ if closeFn == nil {
203+ return fmt .Errorf ("client busy" )
204+ }
205+
206+ defer closeFn ()
207+
208+ reqCtx , reqCtxCancel := context .WithTimeout (ctx , ec .requestTimeout )
209+ defer reqCtxCancel ()
210+
211+ return ec .ethClient .SendTransaction (reqCtx , tx )
212+ }
213+
214+ //nolint:gocritic // ignore
215+ func (ec * ExecutionClient ) GetEthCall (ctx context.Context , msg ethereum.CallMsg , blockNumber * big.Int ) ([]byte , error ) {
216+ closeFn := ec .enforceConcurrencyLimit (ctx )
217+ if closeFn == nil {
218+ return nil , fmt .Errorf ("client busy" )
219+ }
220+
221+ defer closeFn ()
222+
223+ return ec .ethClient .CallContract (ctx , msg , blockNumber )
128224}
0 commit comments