Skip to content

Commit 06262c0

Browse files
authored
[CAL][12] - Implement Sync in default accessor (#1031)
1 parent c6fdc20 commit 06262c0

File tree

7 files changed

+197
-103
lines changed

7 files changed

+197
-103
lines changed

pkg/chainaccessor/default_accessor.go

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,36 @@ func (l *DefaultAccessor) GetChainFeeComponents(ctx context.Context) (cciptypes.
7676
return *fc, nil
7777
}
7878

79-
func (l *DefaultAccessor) Sync(ctx context.Context, contracts cciptypes.ContractAddresses) error {
80-
// TODO(NONEVM-1865): implement
81-
panic("implement me")
79+
func (l *DefaultAccessor) Sync(
80+
ctx context.Context,
81+
contractName string,
82+
contractAddress cciptypes.UnknownAddress,
83+
) error {
84+
lggr := logutil.WithContextValues(ctx, l.lggr)
85+
addressStr, err := l.addrCodec.AddressBytesToString(contractAddress, l.chainSelector)
86+
if err != nil {
87+
return fmt.Errorf("unable to convert address bytes to string: %w, address: %v", err, contractAddress)
88+
}
89+
90+
contract := types.BoundContract{
91+
Address: addressStr,
92+
Name: contractName,
93+
}
94+
95+
lggr.Debugw("Binding contract",
96+
"chainSelector", l.chainSelector,
97+
"contractName", contractName,
98+
"address", addressStr,
99+
)
100+
// Bind the contract address to the reader.
101+
// If the same address exists -> no-op
102+
// If the address is changed -> updates the address, overwrites the existing one
103+
// If the contract not bound -> binds to the new address
104+
if err := l.contractReader.Bind(ctx, []types.BoundContract{contract}); err != nil {
105+
return fmt.Errorf("unable to bind %s %s for chain %d: %w", contractName, addressStr, l.chainSelector, err)
106+
}
107+
108+
return nil
82109
}
83110

84111
func (l *DefaultAccessor) MsgsBetweenSeqNums(

pkg/reader/ccip.go

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -527,8 +527,6 @@ func (r *ccipChainReader) buildSigners(signers []signer) []cciptypes.RemoteSigne
527527
}
528528

529529
func (r *ccipChainReader) GetRMNRemoteConfig(ctx context.Context) (cciptypes.RemoteConfig, error) {
530-
lggr := logutil.WithContextValues(ctx, r.lggr)
531-
532530
if err := validateReaderExistence(r.contractReaders, r.destChain); err != nil {
533531
return cciptypes.RemoteConfig{}, fmt.Errorf("validate dest=%d extended reader existence: %w", r.destChain, err)
534532
}
@@ -549,7 +547,7 @@ func (r *ccipChainReader) GetRMNRemoteConfig(ctx context.Context) (cciptypes.Rem
549547
return cciptypes.RemoteConfig{}, fmt.Errorf("get RMNRemote proxy contract address: %w", err)
550548
}
551549

552-
rmnRemoteAddress, err := r.getRMNRemoteAddress(ctx, lggr, r.destChain, proxyContractAddress)
550+
rmnRemoteAddress, err := r.getRMNRemoteAddress(ctx, r.destChain, proxyContractAddress)
553551
if err != nil {
554552
return cciptypes.RemoteConfig{}, fmt.Errorf("get RMNRemote address: %w", err)
555553
}
@@ -794,21 +792,14 @@ func (r *ccipChainReader) Sync(ctx context.Context, contracts ContractAddresses)
794792
return nil
795793
}
796794

797-
// the extended reader will do nothing if the contract is already bound.
798-
_, err := bindReaderContract(
799-
ctx,
800-
lggr,
801-
r.contractReaders,
802-
chainSelector,
803-
boundContract.name,
804-
boundContract.address,
805-
r.addrCodec)
806-
if err != nil {
807-
if errors.Is(err, ErrContractReaderNotFound) {
808-
// don't support this chain, nothing to do.
809-
return nil
810-
}
795+
chainAccessor, err := getChainAccessor(r.accessors, chainSelector)
796+
if err != nil && errors.Is(err, ErrChainAccessorNotFound) {
797+
// don't support this chain, nothing to do.
798+
return nil
799+
}
811800

801+
err = chainAccessor.Sync(ctx, boundContract.name, boundContract.address)
802+
if err != nil {
812803
return fmt.Errorf("bind reader contract %s on chain %s: %w", boundContract.name, chainSelector, err)
813804
}
814805

@@ -1129,12 +1120,15 @@ type versionedConfig struct {
11291120
//nolint:lll
11301121
func (r *ccipChainReader) getRMNRemoteAddress(
11311122
ctx context.Context,
1132-
lggr logger.Logger,
11331123
chain cciptypes.ChainSelector,
11341124
rmnRemoteProxyAddress []byte) ([]byte, error) {
1135-
_, err := bindReaderContract(ctx, lggr, r.contractReaders, chain, consts.ContractNameRMNProxy, rmnRemoteProxyAddress, r.addrCodec)
1125+
chainAccessor, err := getChainAccessor(r.accessors, chain)
1126+
if err != nil {
1127+
return nil, fmt.Errorf("unable to getChainAccessor: %w", err)
1128+
}
1129+
err = chainAccessor.Sync(ctx, consts.ContractNameRMNProxy, rmnRemoteProxyAddress)
11361130
if err != nil {
1137-
return nil, fmt.Errorf("bind RMN proxy contract: %w", err)
1131+
return nil, fmt.Errorf("sync RMN proxy contract: %w", err)
11381132
}
11391133

11401134
// Get the address from cache instead of making a contract call

pkg/reader/ccip_interface.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
)
1717

1818
var (
19+
ErrChainAccessorNotFound = errors.New("chain accessor not found")
1920
ErrContractReaderNotFound = errors.New("contract reader not found")
2021
ErrContractWriterNotFound = errors.New("contract writer not found")
2122
)

pkg/reader/ccip_test.go

Lines changed: 107 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -151,11 +151,20 @@ func TestCCIPChainReader_Sync_HappyPath_BindsContractsSuccessfully(t *testing.T)
151151
s1Onramp := []byte{0x1}
152152
s2Onramp := []byte{0x2}
153153
destNonceMgr := []byte{0x3}
154+
offRamp := []byte{0x4}
154155

155156
mockAddrCodec := internal.NewMockAddressCodecHex(t)
156157
destNonceMgrAddrStr, err := mockAddrCodec.AddressBytesToString(destNonceMgr, destChain)
157158
require.NoError(t, err)
159+
offRampAddrStr, err := mockAddrCodec.AddressBytesToString(offRamp, destChain)
160+
require.NoError(t, err)
158161
destExtended := reader_mocks.NewMockExtended(t)
162+
destExtended.EXPECT().Bind(mock.Anything, []types.BoundContract{
163+
{
164+
Name: consts.ContractNameOffRamp,
165+
Address: offRampAddrStr,
166+
},
167+
}).Return(nil)
159168
destExtended.EXPECT().Bind(mock.Anything, []types.BoundContract{
160169
{
161170
Name: consts.ContractNameNonceManager,
@@ -187,17 +196,26 @@ func TestCCIPChainReader_Sync_HappyPath_BindsContractsSuccessfully(t *testing.T)
187196
defer source1Extended.AssertExpectations(t)
188197
defer source2Extended.AssertExpectations(t)
189198

190-
ccipReader := &ccipChainReader{
191-
contractReaders: map[cciptypes.ChainSelector]contractreader.Extended{
199+
cw := writer_mocks.NewMockContractWriter(t)
200+
contractWriters := make(map[cciptypes.ChainSelector]types.ContractWriter)
201+
contractWriters[destChain] = cw
202+
contractWriters[sourceChain1] = cw
203+
contractWriters[sourceChain2] = cw
204+
205+
ccipReader, err := newCCIPChainReaderInternal(
206+
ctx,
207+
logger.Test(t),
208+
map[cciptypes.ChainSelector]contractreader.ContractReaderFacade{
192209
destChain: destExtended,
193210
sourceChain1: source1Extended,
194211
sourceChain2: source2Extended,
195212
},
196-
donAddressBook: addressbook.NewBook(),
197-
destChain: destChain,
198-
lggr: logger.Test(t),
199-
addrCodec: mockAddrCodec,
200-
}
213+
contractWriters,
214+
destChain,
215+
offRamp,
216+
mockAddrCodec,
217+
)
218+
require.NoError(t, err)
201219

202220
contracts := ContractAddresses{
203221
consts.ContractNameOnRamp: {
@@ -211,6 +229,8 @@ func TestCCIPChainReader_Sync_HappyPath_BindsContractsSuccessfully(t *testing.T)
211229

212230
err = ccipReader.Sync(ctx, contracts)
213231
require.NoError(t, err)
232+
err = ccipReader.Close()
233+
require.NoError(t, err)
214234
}
215235

216236
func TestCCIPChainReader_Sync_HappyPath_SkipsEmptyAddress(t *testing.T) {
@@ -219,6 +239,7 @@ func TestCCIPChainReader_Sync_HappyPath_SkipsEmptyAddress(t *testing.T) {
219239
sourceChain1 := cciptypes.ChainSelector(2)
220240
sourceChain2 := cciptypes.ChainSelector(3)
221241
s1Onramp := []byte{0x1}
242+
offRamp := []byte{0x4}
222243

223244
// empty address, should get skipped
224245
s2Onramp := []byte{}
@@ -228,6 +249,14 @@ func TestCCIPChainReader_Sync_HappyPath_SkipsEmptyAddress(t *testing.T) {
228249
mockAddrCodec := internal.NewMockAddressCodecHex(t)
229250
destNonceMgrAddrStr, err := mockAddrCodec.AddressBytesToString(destNonceMgr, destChain)
230251
require.NoError(t, err)
252+
offRampAddrStr, err := mockAddrCodec.AddressBytesToString(offRamp, destChain)
253+
require.NoError(t, err)
254+
destExtended.EXPECT().Bind(mock.Anything, []types.BoundContract{
255+
{
256+
Name: consts.ContractNameOffRamp,
257+
Address: offRampAddrStr,
258+
},
259+
}).Return(nil)
231260
destExtended.EXPECT().Bind(mock.Anything, []types.BoundContract{
232261
{
233262
Name: consts.ContractNameNonceManager,
@@ -252,17 +281,26 @@ func TestCCIPChainReader_Sync_HappyPath_SkipsEmptyAddress(t *testing.T) {
252281
defer source1Extended.AssertExpectations(t)
253282
defer source2Extended.AssertExpectations(t)
254283

255-
ccipReader := &ccipChainReader{
256-
contractReaders: map[cciptypes.ChainSelector]contractreader.Extended{
284+
cw := writer_mocks.NewMockContractWriter(t)
285+
contractWriters := make(map[cciptypes.ChainSelector]types.ContractWriter)
286+
contractWriters[destChain] = cw
287+
contractWriters[sourceChain1] = cw
288+
contractWriters[sourceChain2] = cw
289+
290+
ccipReader, err := newCCIPChainReaderInternal(
291+
ctx,
292+
logger.Test(t),
293+
map[cciptypes.ChainSelector]contractreader.ContractReaderFacade{
257294
destChain: destExtended,
258295
sourceChain1: source1Extended,
259296
sourceChain2: source2Extended,
260297
},
261-
donAddressBook: addressbook.NewBook(),
262-
destChain: destChain,
263-
lggr: logger.Test(t),
264-
addrCodec: mockAddrCodec,
265-
}
298+
contractWriters,
299+
destChain,
300+
offRamp,
301+
mockAddrCodec,
302+
)
303+
require.NoError(t, err)
266304

267305
contracts := ContractAddresses{
268306
consts.ContractNameOnRamp: {
@@ -276,6 +314,8 @@ func TestCCIPChainReader_Sync_HappyPath_SkipsEmptyAddress(t *testing.T) {
276314

277315
err = ccipReader.Sync(ctx, contracts)
278316
require.NoError(t, err)
317+
err = ccipReader.Close()
318+
require.NoError(t, err)
279319
}
280320

281321
func TestCCIPChainReader_Sync_HappyPath_DontSupportAllChains(t *testing.T) {
@@ -286,11 +326,20 @@ func TestCCIPChainReader_Sync_HappyPath_DontSupportAllChains(t *testing.T) {
286326
s1Onramp := []byte{0x1}
287327
s2Onramp := []byte{0x2}
288328
destNonceMgr := []byte{0x3}
329+
offRamp := []byte{0x4}
289330
destExtended := reader_mocks.NewMockExtended(t)
290331
mockAddrCodec := internal.NewMockAddressCodecHex(t)
291332

292333
destNonceMgrAddrStr, err := mockAddrCodec.AddressBytesToString(destNonceMgr, destChain)
293334
require.NoError(t, err)
335+
offRampAddrStr, err := mockAddrCodec.AddressBytesToString(offRamp, destChain)
336+
require.NoError(t, err)
337+
destExtended.EXPECT().Bind(mock.Anything, []types.BoundContract{
338+
{
339+
Name: consts.ContractNameOffRamp,
340+
Address: offRampAddrStr,
341+
},
342+
}).Return(nil)
294343
destExtended.EXPECT().Bind(mock.Anything, []types.BoundContract{
295344
{
296345
Name: consts.ContractNameNonceManager,
@@ -312,16 +361,24 @@ func TestCCIPChainReader_Sync_HappyPath_DontSupportAllChains(t *testing.T) {
312361
defer destExtended.AssertExpectations(t)
313362
defer source2Extended.AssertExpectations(t)
314363

315-
ccipReader := &ccipChainReader{
316-
contractReaders: map[cciptypes.ChainSelector]contractreader.Extended{
364+
cw := writer_mocks.NewMockContractWriter(t)
365+
contractWriters := make(map[cciptypes.ChainSelector]types.ContractWriter)
366+
contractWriters[destChain] = cw
367+
contractWriters[sourceChain2] = cw
368+
369+
ccipReader, err := newCCIPChainReaderInternal(
370+
ctx,
371+
logger.Test(t),
372+
map[cciptypes.ChainSelector]contractreader.ContractReaderFacade{
317373
destChain: destExtended,
318374
sourceChain2: source2Extended,
319375
},
320-
donAddressBook: addressbook.NewBook(),
321-
destChain: destChain,
322-
lggr: logger.Test(t),
323-
addrCodec: mockAddrCodec,
324-
}
376+
contractWriters,
377+
destChain,
378+
offRamp,
379+
mockAddrCodec,
380+
)
381+
require.NoError(t, err)
325382

326383
contracts := ContractAddresses{
327384
consts.ContractNameOnRamp: {
@@ -335,6 +392,8 @@ func TestCCIPChainReader_Sync_HappyPath_DontSupportAllChains(t *testing.T) {
335392

336393
err = ccipReader.Sync(ctx, contracts)
337394
require.NoError(t, err)
395+
err = ccipReader.Close()
396+
require.NoError(t, err)
338397
}
339398

340399
func TestCCIPChainReader_Sync_BindError(t *testing.T) {
@@ -345,11 +404,20 @@ func TestCCIPChainReader_Sync_BindError(t *testing.T) {
345404
s1Onramp := []byte{0x1}
346405
s2Onramp := []byte{0x2}
347406
destNonceMgr := []byte{0x3}
407+
offRamp := []byte{0x4}
348408

349409
mockAddrCodec := internal.NewMockAddressCodecHex(t)
350410
destNonceMgrAddrStr, err := mockAddrCodec.AddressBytesToString(destNonceMgr, destChain)
351411
require.NoError(t, err)
412+
offRampAddrStr, err := mockAddrCodec.AddressBytesToString(offRamp, destChain)
413+
require.NoError(t, err)
352414
destExtended := reader_mocks.NewMockExtended(t)
415+
destExtended.EXPECT().Bind(mock.Anything, []types.BoundContract{
416+
{
417+
Name: consts.ContractNameOffRamp,
418+
Address: offRampAddrStr,
419+
},
420+
}).Return(nil)
353421
destExtended.EXPECT().Bind(mock.Anything, []types.BoundContract{
354422
{
355423
Name: consts.ContractNameNonceManager,
@@ -382,17 +450,26 @@ func TestCCIPChainReader_Sync_BindError(t *testing.T) {
382450
defer source1Extended.AssertExpectations(t)
383451
defer source2Extended.AssertExpectations(t)
384452

385-
ccipReader := &ccipChainReader{
386-
contractReaders: map[cciptypes.ChainSelector]contractreader.Extended{
453+
cw := writer_mocks.NewMockContractWriter(t)
454+
contractWriters := make(map[cciptypes.ChainSelector]types.ContractWriter)
455+
contractWriters[destChain] = cw
456+
contractWriters[sourceChain1] = cw
457+
contractWriters[sourceChain2] = cw
458+
459+
ccipReader, err := newCCIPChainReaderInternal(
460+
ctx,
461+
logger.Test(t),
462+
map[cciptypes.ChainSelector]contractreader.ContractReaderFacade{
387463
destChain: destExtended,
388464
sourceChain1: source1Extended,
389465
sourceChain2: source2Extended,
390466
},
391-
donAddressBook: addressbook.NewBook(),
392-
destChain: destChain,
393-
lggr: logger.Test(t),
394-
addrCodec: mockAddrCodec,
395-
}
467+
contractWriters,
468+
destChain,
469+
offRamp,
470+
mockAddrCodec,
471+
)
472+
require.NoError(t, err)
396473

397474
contracts := ContractAddresses{
398475
consts.ContractNameOnRamp: {
@@ -407,6 +484,8 @@ func TestCCIPChainReader_Sync_BindError(t *testing.T) {
407484
err = ccipReader.Sync(ctx, contracts)
408485
require.Error(t, err)
409486
require.ErrorIs(t, err, expectedErr)
487+
err = ccipReader.Close()
488+
require.NoError(t, err)
410489
}
411490

412491
// The round1 version returns NoBindingFound errors for onramp contracts to simulate

0 commit comments

Comments
 (0)