Skip to content

Commit c3f360f

Browse files
authored
fix(relayer): remove RPC dependency on CCIPProvider creation (#658)
* chore: test * fix: clientProvider for CCIPProvider * chore: test * fix: remove failure * fix: NewTONAccessor param
1 parent d9e5efc commit c3f360f

6 files changed

Lines changed: 101 additions & 37 deletions

File tree

integration-tests/deployment/ccip/cs_deployer_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -423,7 +423,7 @@ func TestDeployContractsAndSetOCR3ConfigWithDeployerAPI(t *testing.T) {
423423
)
424424
require.NoError(t, err)
425425
addrCodec := codec.NewAddressCodec()
426-
accessor, err := chainaccessor.NewTONAccessor(lggr, ccipocr3.ChainSelector(tonSelector), tonChain.Client, lp, addrCodec)
426+
accessor, err := chainaccessor.NewTONAccessor(lggr, ccipocr3.ChainSelector(tonSelector), clientProvider, lp, addrCodec)
427427
require.NoError(t, err)
428428

429429
state, err := tonstate.LoadOnchainState(env)

integration-tests/deployment/ccip/cs_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ func TestDeployCCIP(t *testing.T) {
194194
)
195195
require.NoError(t, err)
196196
addrCodec := codec.NewAddressCodec()
197-
accessor, err := chainaccessor.NewTONAccessor(lggr, ccipocr3.ChainSelector(chainSelector), tonChain.Client, lp, addrCodec)
197+
accessor, err := chainaccessor.NewTONAccessor(lggr, ccipocr3.ChainSelector(chainSelector), clientProvider, lp, addrCodec)
198198
require.NoError(t, err)
199199

200200
ctx := t.Context()

pkg/ccip/chainaccessor/config.go

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -109,12 +109,16 @@ func (a *TONAccessor) GetOffRampConfig(ctx context.Context, block *ton.BlockIDEx
109109
if err != nil {
110110
return ccipocr3.OfframpConfig{}, err
111111
}
112-
config, err := tvm.CallGetter(ctx, a.client, block, addr, offramp.GetConfig)
112+
client, err := a.clientProvider(ctx)
113+
if err != nil {
114+
return ccipocr3.OfframpConfig{}, fmt.Errorf("failed to get TON client: %w", err)
115+
}
116+
config, err := tvm.CallGetter(ctx, client, block, addr, offramp.GetConfig)
113117
if err != nil {
114118
return ccipocr3.OfframpConfig{}, err
115119
}
116120

117-
ocr3Base, err := tvm.CallGetter(ctx, a.client, block, addr, offramp.GetOCR3Config)
121+
ocr3Base, err := tvm.CallGetter(ctx, client, block, addr, offramp.GetOCR3Config)
118122
if err != nil {
119123
return ccipocr3.OfframpConfig{}, err
120124
}
@@ -156,8 +160,12 @@ func (a *TONAccessor) GetOffRampSourceChainConfigs(ctx context.Context, block *t
156160
return nil, err
157161
}
158162

163+
client, err := a.clientProvider(ctx)
164+
if err != nil {
165+
return nil, fmt.Errorf("failed to get TON client: %w", err)
166+
}
159167
var sourceConfigsGot offrampview.SourceChainConfigMap
160-
if err = sourceConfigsGot.Fetch(ctx, a.client, block, addr); err != nil {
168+
if err = sourceConfigsGot.Fetch(ctx, client, block, addr); err != nil {
161169
return nil, fmt.Errorf("failed to fetch source chain configs: %w", err)
162170
}
163171

@@ -214,7 +222,11 @@ func (a *TONAccessor) GetOffRampSourceChainConfig(ctx context.Context, block *to
214222
return ccipocr3.SourceChainConfig{}, err
215223
}
216224

217-
config, err := tvm.CallGetter(ctx, a.client, block, addr, offramp.GetSourceChainConfig, uint64(sourceChainSelector))
225+
client, err := a.clientProvider(ctx)
226+
if err != nil {
227+
return ccipocr3.SourceChainConfig{}, fmt.Errorf("failed to get TON client: %w", err)
228+
}
229+
config, err := tvm.CallGetter(ctx, client, block, addr, offramp.GetSourceChainConfig, uint64(sourceChainSelector))
218230
if err != nil {
219231
// Handle ERROR_SOURCE_CHAIN_NOT_ENABLED=266 case for non-existent source chain
220232
var execError ton.ContractExecError
@@ -249,7 +261,11 @@ func (a *TONAccessor) GetFeeQuoterStaticConfig(ctx context.Context, block *ton.B
249261
if err != nil {
250262
return ccipocr3.FeeQuoterStaticConfig{}, err
251263
}
252-
cfg, err := tvm.CallGetter(ctx, a.client, block, addr, feequoter.GetStaticConfig)
264+
client, err := a.clientProvider(ctx)
265+
if err != nil {
266+
return ccipocr3.FeeQuoterStaticConfig{}, fmt.Errorf("failed to get TON client: %w", err)
267+
}
268+
cfg, err := tvm.CallGetter(ctx, client, block, addr, feequoter.GetStaticConfig)
253269
if err != nil {
254270
return ccipocr3.FeeQuoterStaticConfig{}, err
255271
}
@@ -270,7 +286,12 @@ func (a *TONAccessor) GetOnRampDynamicConfig(ctx context.Context, block *ton.Blo
270286
if err != nil {
271287
return ccipocr3.OnRampDynamicConfig{}, err
272288
}
273-
cfg, err := tvm.CallGetter(ctx, a.client, block, addr, onramp.GetDynamicConfig)
289+
client, err := a.clientProvider(ctx)
290+
if err != nil {
291+
return ccipocr3.OnRampDynamicConfig{}, fmt.Errorf("failed to get TON client: %w", err)
292+
}
293+
294+
cfg, err := tvm.CallGetter(ctx, client, block, addr, onramp.GetDynamicConfig)
274295
if err != nil {
275296
return ccipocr3.OnRampDynamicConfig{}, err
276297
}
@@ -302,7 +323,11 @@ func (a *TONAccessor) GetOnRampDestChainConfig(ctx context.Context, block *ton.B
302323
return ccipocr3.OnRampDestChainConfig{}, err
303324
}
304325

305-
cfg, err := tvm.CallGetter(ctx, a.client, block, addr, onramp.GetDestChainConfig, uint64(dest))
326+
client, err := a.clientProvider(ctx)
327+
if err != nil {
328+
return ccipocr3.OnRampDestChainConfig{}, fmt.Errorf("failed to get TON client: %w", err)
329+
}
330+
cfg, err := tvm.CallGetter(ctx, client, block, addr, onramp.GetDestChainConfig, uint64(dest))
306331
if err != nil {
307332
return ccipocr3.OnRampDestChainConfig{}, err
308333
}
@@ -325,7 +350,11 @@ func (a *TONAccessor) GetCurseInfo(ctx context.Context, block *ton.BlockIDExt, d
325350
if err != nil {
326351
return ccipocr3.CurseInfo{}, fmt.Errorf("could not get OffRamp address from accessor bindings: %w", err)
327352
}
328-
cursedSubjects, err := tvm.CallGetter(ctx, a.client, block, addr, offramp.GetCursedSubjects)
353+
client, err := a.clientProvider(ctx)
354+
if err != nil {
355+
return ccipocr3.CurseInfo{}, fmt.Errorf("failed to get TON client: %w", err)
356+
}
357+
cursedSubjects, err := tvm.CallGetter(ctx, client, block, addr, offramp.GetCursedSubjects)
329358
if err != nil {
330359
return ccipocr3.CurseInfo{}, fmt.Errorf("could not get cursed subjects: %w", err)
331360
}

pkg/ccip/chainaccessor/ton_accessor.go

Lines changed: 52 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,10 @@ const (
6262
)
6363

6464
type TONAccessor struct {
65-
lggr logger.Logger
66-
chainSelector ccipocr3.ChainSelector
67-
client ton.APIClientWrapped
68-
logPoller logpoller.Service
65+
lggr logger.Logger
66+
chainSelector ccipocr3.ChainSelector
67+
clientProvider func(context.Context) (ton.APIClientWrapped, error)
68+
logPoller logpoller.Service
6969
// Note: we might need to update this in the future to map[string][]address.Address
7070
// to support multi-bind addresses for the price aggregator contract: smartcontractkit/chainlink-ccip@main/pkg/contractreader/extended.go#L77-L79
7171
bindings map[string]*address.Address
@@ -78,27 +78,31 @@ var _ ccipocr3.ChainAccessor = (*TONAccessor)(nil)
7878
func NewTONAccessor(
7979
lggr logger.Logger,
8080
chainSelector ccipocr3.ChainSelector,
81-
client ton.APIClientWrapped,
81+
clientProvider func(context.Context) (ton.APIClientWrapped, error),
8282
logPoller logpoller.Service,
8383
addrCodec ccipocr3.ChainSpecificAddressCodec,
8484
) (ccipocr3.ChainAccessor, error) {
8585
sLggr := logger.Sugared(lggr).Named("TONAccessor").Named(chainSelector.String())
8686
return &TONAccessor{
87-
lggr: sLggr,
88-
chainSelector: chainSelector,
89-
client: client,
90-
logPoller: logPoller,
91-
bindings: make(map[string]*address.Address),
92-
bindingsMu: sync.RWMutex{},
93-
addrCodec: addrCodec,
87+
lggr: sLggr,
88+
chainSelector: chainSelector,
89+
clientProvider: clientProvider,
90+
logPoller: logPoller,
91+
bindings: make(map[string]*address.Address),
92+
bindingsMu: sync.RWMutex{},
93+
addrCodec: addrCodec,
9494
}, nil
9595
}
9696

9797
// getCurrentMasterchainBlock retrieves and validates the current masterchain block.
9898
// It ensures the returned block belongs to the masterchain (workchain -1) to prevent
9999
// a compromised TON node from injecting base workchain data.
100100
func (a *TONAccessor) getCurrentMasterchainBlock(ctx context.Context) (*ton.BlockIDExt, error) {
101-
block, err := a.client.CurrentMasterchainInfo(ctx)
101+
client, err := a.clientProvider(ctx)
102+
if err != nil {
103+
return nil, fmt.Errorf("failed to get TON client: %w", err)
104+
}
105+
block, err := client.CurrentMasterchainInfo(ctx)
102106
if err != nil {
103107
return nil, fmt.Errorf("failed to get current masterchain info: %w", err)
104108
}
@@ -411,7 +415,12 @@ func (a *TONAccessor) GetExpectedNextSequenceNumber(ctx context.Context, dest cc
411415
if err != nil {
412416
return 0, fmt.Errorf("failed to get current block: %w", err)
413417
}
414-
result, err := a.client.RunGetMethod(ctx, block, addr, "expectedNextSequenceNumber", uint64(dest))
418+
419+
client, err := a.clientProvider(ctx)
420+
if err != nil {
421+
return 0, fmt.Errorf("failed to get TON client: %w", err)
422+
}
423+
result, err := client.RunGetMethod(ctx, block, addr, "expectedNextSequenceNumber", uint64(dest))
415424
if err != nil {
416425
return 0, err
417426
}
@@ -448,8 +457,12 @@ func (a *TONAccessor) GetTokenPriceUSD(ctx context.Context, rawTokenAddress ccip
448457
if err != nil {
449458
return ccipocr3.TimestampedUnixBig{}, fmt.Errorf("failed to get current block: %w", err)
450459
}
460+
client, err := a.clientProvider(ctx)
461+
if err != nil {
462+
return ccipocr3.TimestampedUnixBig{}, fmt.Errorf("failed to get TON client: %w", err)
463+
}
451464

452-
timestampedPrice, err := tvm.CallGetter(ctx, a.client, block, addr, feequoter.GetTokenPrice, tokenAddress)
465+
timestampedPrice, err := tvm.CallGetter(ctx, client, block, addr, feequoter.GetTokenPrice, tokenAddress)
453466
if err != nil {
454467
return ccipocr3.TimestampedUnixBig{}, err
455468
}
@@ -468,7 +481,13 @@ func (a *TONAccessor) GetFeeQuoterDestChainConfig(ctx context.Context, dest ccip
468481
if err != nil {
469482
return ccipocr3.FeeQuoterDestChainConfig{}, fmt.Errorf("failed to get current block: %w", err)
470483
}
471-
cfg, err := tvm.CallGetter(ctx, a.client, block, addr, feequoter.GetDestChainConfig, uint64(dest))
484+
485+
client, err := a.clientProvider(ctx)
486+
if err != nil {
487+
return ccipocr3.FeeQuoterDestChainConfig{}, fmt.Errorf("failed to get TON client: %w", err)
488+
}
489+
490+
cfg, err := tvm.CallGetter(ctx, client, block, addr, feequoter.GetDestChainConfig, uint64(dest))
472491
if err != nil {
473492
return ccipocr3.FeeQuoterDestChainConfig{}, err
474493
}
@@ -780,8 +799,13 @@ func (a *TONAccessor) GetChainFeePriceUpdate(ctx context.Context, selectors []cc
780799
return nil, fmt.Errorf("failed to get current block: %w", err)
781800
}
782801

802+
client, err := a.clientProvider(ctx)
803+
if err != nil {
804+
return nil, fmt.Errorf("failed to get TON client: %w", err)
805+
}
806+
783807
for _, selector := range selectors {
784-
gasPrice, err := tvm.CallGetter(ctx, a.client, block, addr, feequoter.GetDestinationChainGasPrice, uint64(selector))
808+
gasPrice, err := tvm.CallGetter(ctx, client, block, addr, feequoter.GetDestinationChainGasPrice, uint64(selector))
785809
// The plugin is built with EVM behaviour in mind: if a value doesn't exist the zero value is returned
786810
var execError ton.ContractExecError
787811
if errors.As(err, &execError) && execError.Code == int32(feequoter.ErrorUnknownDestChainSelector) {
@@ -829,7 +853,11 @@ func (a *TONAccessor) GetLatestPriceSeqNr(ctx context.Context) (ccipocr3.SeqNum,
829853
if err != nil {
830854
return 0, fmt.Errorf("failed to get current block: %w", err)
831855
}
832-
result, err := a.client.RunGetMethod(ctx, block, addr, "latestPriceSequenceNumber")
856+
client, err := a.clientProvider(ctx)
857+
if err != nil {
858+
return 0, fmt.Errorf("failed to get TON client: %w", err)
859+
}
860+
result, err := client.RunGetMethod(ctx, block, addr, "latestPriceSequenceNumber")
833861
if err != nil {
834862
return 0, err
835863
}
@@ -873,6 +901,11 @@ func (a *TONAccessor) GetFeeQuoterTokenUpdates(
873901
return nil, fmt.Errorf("failed to get current block: %w", err)
874902
}
875903

904+
client, err := a.clientProvider(ctx)
905+
if err != nil {
906+
return nil, fmt.Errorf("failed to get TON client: %w", err)
907+
}
908+
876909
prices := make(map[ccipocr3.UnknownEncodedAddress]ccipocr3.TimestampedUnixBig, len(tokens))
877910
for _, token := range tokens {
878911
strAddr, err2 := a.addrCodec.AddressBytesToString(token)
@@ -884,7 +917,7 @@ func (a *TONAccessor) GetFeeQuoterTokenUpdates(
884917
return nil, fmt.Errorf("failed to ParseAddr %s for encodedTokens: %w", strAddr, err2)
885918
}
886919

887-
tokenPrice, err := tvm.CallGetter(ctx, a.client, block, addr, feequoter.GetTokenPrice, addrParsed)
920+
tokenPrice, err := tvm.CallGetter(ctx, client, block, addr, feequoter.GetTokenPrice, addrParsed)
888921
if err != nil {
889922
// The plugin is built with EVM behaviour in mind: if a value doesn't exist the zero value is returned
890923
var execError ton.ContractExecError

pkg/ccip/provider/provider.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ type Provider struct {
4242
func NewCCIPProvider(
4343
lggr logger.Logger,
4444
chainSelector ccipocr3.ChainSelector,
45-
client ton.APIClientWrapped,
45+
clientProvider func(context.Context) (ton.APIClientWrapped, error),
4646
txm txm.TxManager,
4747
logPoller logpoller.Service,
4848
cargs commontypes.CCIPProviderArgs,
@@ -96,7 +96,7 @@ func NewCCIPProvider(
9696
SourceChainExtraDataCodec: codec.NewExtraDataDecoder(),
9797
}
9898

99-
ca, err := chainaccessor.NewTONAccessor(lggr, chainSelector, client, logPoller, c.ChainSpecificAddressCodec)
99+
ca, err := chainaccessor.NewTONAccessor(lggr, chainSelector, clientProvider, logPoller, c.ChainSpecificAddressCodec)
100100
if err != nil {
101101
return nil, fmt.Errorf("failed to create TON Accessor: %w", err)
102102
}

pkg/relay/relay.go

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"strconv"
99

1010
"github.com/xssnick/tonutils-go/tlb"
11+
"github.com/xssnick/tonutils-go/ton"
1112

1213
chain_selectors "github.com/smartcontractkit/chain-selectors"
1314

@@ -125,18 +126,19 @@ func (r *Relayer) NewCCIPProvider(ctx context.Context, cargs commontypes.CCIPPro
125126
return nil, fmt.Errorf("invalid chain ID %d: could not find chain selector: %w", chainID, err)
126127
}
127128

128-
// TODO: pass GetClient through? So we don't pin provider to a single client
129-
130-
client, err := r.chain.GetClient(ctx)
131-
if err != nil {
132-
return nil, fmt.Errorf("failed to fetch TON client: %w", err)
129+
clientProvider := func(ctx context.Context) (ton.APIClientWrapped, error) {
130+
cl, cerr := r.chain.GetClient(ctx)
131+
if cerr != nil {
132+
return nil, cerr
133+
}
134+
return cl, nil
133135
}
134136

135137
// TODO: check if rargs.ContractID is offramp address ?
136138
return provider.NewCCIPProvider(
137139
r.lggr,
138140
ccipocr3.ChainSelector(chainSelector),
139-
client,
141+
clientProvider,
140142
r.chain.TxManager(),
141143
r.chain.LogPoller(),
142144
cargs,

0 commit comments

Comments
 (0)