From b877f2ae813b00b5d35f3830a42168ad9eef4ebe Mon Sep 17 00:00:00 2001 From: connorwstein Date: Tue, 3 Oct 2023 12:21:37 -0400 Subject: [PATCH] Filter testing --- .../internal/ccipdata/commit_store_reader.go | 15 +--- .../ccipdata/commit_store_reader_test.go | 48 ++++++++++++ .../internal/ccipdata/commit_store_v1_0_0.go | 5 +- .../internal/ccipdata/commit_store_v1_2_0.go | 1 - .../ccip/internal/ccipdata/offramp_reader.go | 23 ++---- .../internal/ccipdata/offramp_reader_test.go | 1 + .../ccipdata/offramp_reader_v1_0_0_test.go | 33 ++++++--- .../ccip/internal/ccipdata/offramp_v1_0_0.go | 74 +++++++++---------- .../ccip/internal/ccipdata/offramp_v1_2_0.go | 9 +-- .../ccip/internal/ccipdata/onramp_reader.go | 6 +- .../ccipdata/price_registry_reader.go | 8 +- .../ccipdata/price_registry_reader_test.go | 20 +++++ .../ccipdata/price_registry_v1_0_0.go | 4 +- .../plugins/ccip/internal/ccipdata/reader.go | 6 ++ .../internal/ccipdata/usdc_reader_test.go | 15 +++- core/services/relay/evm/ccip.go | 11 ++- 16 files changed, 171 insertions(+), 108 deletions(-) create mode 100644 core/services/ocr2/plugins/ccip/internal/ccipdata/commit_store_reader_test.go create mode 100644 core/services/ocr2/plugins/ccip/internal/ccipdata/offramp_reader_test.go create mode 100644 core/services/ocr2/plugins/ccip/internal/ccipdata/price_registry_reader_test.go diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/commit_store_reader.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/commit_store_reader.go index 70281df912..0a3c6da897 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/commit_store_reader.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/commit_store_reader.go @@ -17,7 +17,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/abihelpers" ccipconfig "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/config" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/prices" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" ) type CommitStoreInterval struct { @@ -64,34 +63,22 @@ type OffchainConfig struct { } type CommitStoreReader interface { + Closer GetExpectedNextSequenceNumber(context context.Context) (uint64, error) - GetLatestPriceEpochAndRound(context context.Context) (uint64, error) - // GetAcceptedCommitReportsGteSeqNum returns all the accepted commit reports that have sequence number greater than or equal to the provided. GetAcceptedCommitReportsGteSeqNum(ctx context.Context, seqNum uint64, confs int) ([]Event[CommitStoreReport], error) - // GetAcceptedCommitReportsGteTimestamp returns all the commit reports with timestamp greater than or equal to the provided. GetAcceptedCommitReportsGteTimestamp(ctx context.Context, ts time.Time, confs int) ([]Event[CommitStoreReport], error) - IsDown(ctx context.Context) bool - IsBlessed(ctx context.Context, root [32]byte) (bool, error) - // Notifies the reader that the config has changed onchain ConfigChanged(onchainConfig []byte, offchainConfig []byte) (common.Address, error) - OffchainConfig() OffchainConfig - GasPriceEstimator() prices.GasPriceEstimatorCommit - EncodeCommitReport(report CommitStoreReport) ([]byte, error) - DecodeCommitReport(report []byte) (CommitStoreReport, error) - Verify(ctx context.Context, report ExecReport) bool - - Close(qopts ...pg.QOpt) error } func NewCommitStoreReader(lggr logger.Logger, address common.Address, ec client.Client, lp logpoller.LogPoller, estimator gas.EvmFeeEstimator) (CommitStoreReader, error) { diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/commit_store_reader_test.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/commit_store_reader_test.go new file mode 100644 index 0000000000..829e6949d3 --- /dev/null +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/commit_store_reader_test.go @@ -0,0 +1,48 @@ +package ccipdata + +import ( + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" + lpmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller/mocks" + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +func assertFilterRegistration(t *testing.T, lp *lpmocks.LogPoller, buildCloser func(lp *lpmocks.LogPoller, addr common.Address) Closer, numFilter int) { + // Expected filter properties for a closer: + // - Should be the same filter set registered that is unregistered + // - Should be registered to the address specified + // - Number of events specific to this component should be registered + addr := common.HexToAddress("0x1234") + var filters []logpoller.Filter + lp.On("RegisterFilter", mock.Anything).Run(func(args mock.Arguments) { + f := args.Get(0).(logpoller.Filter) + require.Equal(t, len(f.Addresses), 1) + require.Equal(t, f.Addresses[0], addr) + filters = append(filters, f) + }).Return(nil).Times(numFilter) + c := buildCloser(lp, addr) + for _, filter := range filters { + lp.On("UnregisterFilter", filter.Name).Return(nil) + } + require.NoError(t, c.Close()) + lp.AssertExpectations(t) +} + +func TestCommitFilters(t *testing.T) { + assertFilterRegistration(t, new(lpmocks.LogPoller), func(lp *lpmocks.LogPoller, addr common.Address) Closer { + c, err := NewCommitStoreV1_0_0(logger.TestLogger(t), addr, new(mocks.Client), lp, nil) + require.NoError(t, err) + return c + }, 1) + assertFilterRegistration(t, new(lpmocks.LogPoller), func(lp *lpmocks.LogPoller, addr common.Address) Closer { + c, err := NewCommitStoreV1_2_0(logger.TestLogger(t), addr, new(mocks.Client), lp, nil) + require.NoError(t, err) + return c + }, 1) +} diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/commit_store_v1_0_0.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/commit_store_v1_0_0.go index ccbb1215c1..d38ebd26d7 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/commit_store_v1_0_0.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/commit_store_v1_0_0.go @@ -26,6 +26,7 @@ import ( const ( EXEC_REPORT_ACCEPTS = "Exec report accepts" + ReportAccepted = "ReportAccepted" ) var _ CommitStoreReader = &CommitStoreV1_0_0{} @@ -297,8 +298,8 @@ func NewCommitStoreV1_0_0(lggr logger.Logger, addr common.Address, ec client.Cli return nil, err } commitStoreABI := abihelpers.MustParseABI(commit_store.CommitStoreABI) - eventSig := abihelpers.MustGetEventID("ReportAccepted", commitStoreABI) - commitReportArgs := abihelpers.MustGetEventInputs("ReportAccepted", commitStoreABI) + eventSig := abihelpers.MustGetEventID(ReportAccepted, commitStoreABI) + commitReportArgs := abihelpers.MustGetEventInputs(ReportAccepted, commitStoreABI) var filters = []logpoller.Filter{ { Name: logpoller.FilterName(EXEC_REPORT_ACCEPTS, addr.String()), diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/commit_store_v1_2_0.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/commit_store_v1_2_0.go index c8af6a2afd..00d05ba6d7 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/commit_store_v1_2_0.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/commit_store_v1_2_0.go @@ -111,6 +111,5 @@ func NewCommitStoreV1_2_0(lggr logger.Logger, addr common.Address, ec client.Cli if err != nil { return nil, err } - // TODO: try and read initial config return &CommitStoreV1_2_0{CommitStoreV1_0_0: commitStoreV100}, nil } diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/offramp_reader.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/offramp_reader.go index 44f4bf0f0c..a23cb75edd 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/offramp_reader.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/offramp_reader.go @@ -20,7 +20,6 @@ import ( ccipconfig "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/config" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/prices" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/store/models" ) @@ -123,37 +122,24 @@ type ExecReport struct { } type OffRampReader interface { + Closer // Will error if messages are not a compatible verion EncodeExecutionReport(report ExecReport) ([]byte, error) - DecodeExecutionReport(report []byte) (ExecReport, error) - // GetExecutionStateChangesBetweenSeqNums returns all the execution state change events for the provided message sequence numbers (inclusive). GetExecutionStateChangesBetweenSeqNums(ctx context.Context, seqNumMin, seqNumMax uint64, confs int) ([]Event[ExecutionStateChanged], error) - GetDestinationTokens(ctx context.Context) ([]common.Address, error) - GetPoolByDestToken(ctx context.Context, address common.Address) (common.Address, error) - GetDestinationToken(ctx context.Context, address common.Address) (common.Address, error) - GetSupportedTokens(ctx context.Context) ([]common.Address, error) - Address() common.Address - - // TODO Needed for cachign, maybe caching should move behind the readers? + // TODO Needed for caching, maybe caching should move behind the readers? TokenEvents() []common.Hash - // Notifies the reader that the config has changed onchain ConfigChanged(onchainConfig []byte, offchainConfig []byte) (common.Address, common.Address, error) - OffchainConfig() ExecOffchainConfig - OnchainConfig() ExecOnchainConfig - GasPriceEstimator() prices.GasPriceEstimatorExec - - Close(qopts ...pg.QOpt) error } // MessageExecutionState defines the execution states of CCIP messages. @@ -173,12 +159,13 @@ func NewOffRampReader(lggr logger.Logger, addr common.Address, srcClient, destCl } switch version.String() { case "1.0.0", "1.1.0": - return NewOffRampV1_0_0(lggr, addr, destClient, lp, estimator, srcClient) + return NewOffRampV1_0_0(lggr, addr, destClient, lp, estimator) case "1.2.0": - return NewOffRampV1_2_0(lggr, addr, destClient, lp, estimator, srcClient) + return NewOffRampV1_2_0(lggr, addr, destClient, lp, estimator) default: return nil, errors.Errorf("unsupported offramp verison %v", version.String()) } + // TODO can validate it points to the correct onramp version using srcClinet } func ExecReportToEthTxMeta(typ ccipconfig.ContractType, ver semver.Version) (func(report []byte) (*txmgr.TxMeta, error), error) { diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/offramp_reader_test.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/offramp_reader_test.go new file mode 100644 index 0000000000..d470a06c71 --- /dev/null +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/offramp_reader_test.go @@ -0,0 +1 @@ +package ccipdata diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/offramp_reader_v1_0_0_test.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/offramp_reader_v1_0_0_test.go index 19d8662c1d..941a76d932 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/offramp_reader_v1_0_0_test.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/offramp_reader_v1_0_0_test.go @@ -4,30 +4,43 @@ import ( "math/big" "testing" + "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_offramp" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks" + lpmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller/mocks" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal" ) func TestExecutionReportEncoding(t *testing.T) { // Note could consider some fancier testing here (fuzz/property) // but I think that would essentially be testing geth's abi library // as our encode/decode is a thin wrapper around that. - report := evm_2_evm_offramp.InternalExecutionReport{ - Messages: []evm_2_evm_offramp.InternalEVM2EVMMessage{}, + report := ExecReport{ + Messages: []internal.EVM2EVMMessage{}, OffchainTokenData: [][][]byte{{}}, Proofs: [][32]byte{testutils.Random32Byte()}, ProofFlagBits: big.NewInt(133), } - encodeExecutionReport, err := EncodeExecutionReport(evm_2_evm_offramp.InternalExecutionReport{ - Messages: report.Messages, - OffchainTokenData: report.OffchainTokenData, - Proofs: report.Proofs, - ProofFlagBits: report.ProofFlagBits, - }) + offRamp := &OffRampV1_0_0{} + encodeExecutionReport, err := offRamp.EncodeExecutionReport(report) require.NoError(t, err) - decodeCommitReport, err := DecodeExecutionReport(encodeExecutionReport) + decodeCommitReport, err := offRamp.DecodeExecutionReport(encodeExecutionReport) require.NoError(t, err) require.Equal(t, report, decodeCommitReport) } + +func TestOffRampFilters(t *testing.T) { + assertFilterRegistration(t, new(lpmocks.LogPoller), func(lp *lpmocks.LogPoller, addr common.Address) Closer { + c, err := NewOffRampV1_0_0(logger.TestLogger(t), addr, new(mocks.Client), lp, nil) + require.NoError(t, err) + return c + }, 3) + assertFilterRegistration(t, new(lpmocks.LogPoller), func(lp *lpmocks.LogPoller, addr common.Address) Closer { + c, err := NewOffRampV1_2_0(logger.TestLogger(t), addr, new(mocks.Client), lp, nil) + require.NoError(t, err) + return c + }, 3) +} diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/offramp_v1_0_0.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/offramp_v1_0_0.go index 3df0abb365..badeb329fa 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/offramp_v1_0_0.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/offramp_v1_0_0.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "math/big" + "time" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -45,6 +46,8 @@ type OffRampV1_0_0 struct { ec client.Client filters []logpoller.Filter estimator gas.EvmFeeEstimator + offchainConfig ExecOffchainConfig + onchainConfig ExecOnchainConfig gasPriceEstimator prices.GasPriceEstimatorExec executionReportArgs abi.Arguments eventIndex int @@ -52,28 +55,23 @@ type OffRampV1_0_0 struct { } func (o *OffRampV1_0_0) GetDestinationToken(ctx context.Context, address common.Address) (common.Address, error) { - //TODO implement me - panic("implement me") + return o.offRamp.GetDestinationToken(&bind.CallOpts{Context: ctx}, address) } func (o *OffRampV1_0_0) GetSupportedTokens(ctx context.Context) ([]common.Address, error) { - //TODO implement me - panic("implement me") + return o.offRamp.GetSupportedTokens(&bind.CallOpts{Context: ctx}) } func (o *OffRampV1_0_0) GetPoolByDestToken(ctx context.Context, address common.Address) (common.Address, error) { - //TODO implement me - panic("implement me") + return o.offRamp.GetPoolByDestToken(&bind.CallOpts{Context: ctx}, address) } func (o *OffRampV1_0_0) OffchainConfig() ExecOffchainConfig { - //TODO implement me - panic("implement me") + return o.offchainConfig } func (o *OffRampV1_0_0) OnchainConfig() ExecOnchainConfig { - //TODO implement me - panic("implement me") + return o.onchainConfig } func (o *OffRampV1_0_0) GasPriceEstimator() prices.GasPriceEstimatorExec { @@ -102,6 +100,17 @@ func (o *OffRampV1_0_0) ConfigChanged(onchainConfig []byte, offchainConfig []byt if err != nil { return common.Address{}, common.Address{}, err } + o.offchainConfig = ExecOffchainConfig{ + SourceFinalityDepth: offchainConfigParsed.SourceFinalityDepth, + DestFinalityDepth: offchainConfigParsed.DestFinalityDepth, + DestOptimisticConfirmations: offchainConfigParsed.DestOptimisticConfirmations, + BatchGasLimit: offchainConfigParsed.BatchGasLimit, + RelativeBoostPerWaitHour: offchainConfigParsed.RelativeBoostPerWaitHour, + MaxGasPrice: offchainConfigParsed.MaxGasPrice, + InflightCacheExpiry: offchainConfigParsed.InflightCacheExpiry, + RootSnoozeTime: offchainConfigParsed.RootSnoozeTime, + } + o.onchainConfig = ExecOnchainConfig{PermissionLessExecutionThresholdSeconds: time.Second * time.Duration(onchainConfigParsed.PermissionLessExecutionThresholdSeconds)} o.gasPriceEstimator = prices.NewExecGasPriceEstimator(o.estimator, big.NewInt(int64(offchainConfigParsed.MaxGasPrice)), 0) o.lggr.Infow("Starting exec plugin", "offchainConfig", onchainConfigParsed, @@ -224,22 +233,23 @@ func decodeExecReportV1_0_0(args abi.Arguments, report []byte) (ExecReport, erro Amount: tokenAndAmount.Amount, }) } - // TODO messages = append(messages, internal.EVM2EVMMessage{ SequenceNumber: msg.SequenceNumber, - GasLimit: nil, - Nonce: 0, + GasLimit: msg.GasLimit, + Nonce: msg.Nonce, MessageId: msg.MessageId, - SourceChainSelector: 0, - Sender: common.Address{}, - Receiver: common.Address{}, - Strict: false, - FeeToken: common.Address{}, - FeeTokenAmount: nil, - Data: nil, + SourceChainSelector: msg.SourceChainSelector, + Sender: msg.Sender, + Receiver: msg.Receiver, + Strict: msg.Strict, + FeeToken: msg.FeeToken, + FeeTokenAmount: msg.FeeTokenAmount, + Data: msg.Data, TokenAmounts: tokensAndAmounts, - SourceTokenData: nil, - Hash: [32]byte{}, // TODO + SourceTokenData: msg.SourceTokenData, + // TODO: Not needed for plugins, but should be recomputed for consistentcy. + // Requires the offramp knowing about onramp version + Hash: [32]byte{}, }) } @@ -263,7 +273,7 @@ func (o *OffRampV1_0_0) TokenEvents() []common.Hash { return []common.Hash{abihelpers.MustGetEventID("PoolAdded", offRampABI), abihelpers.MustGetEventID("PoolRemoved", offRampABI)} } -func NewOffRampV1_0_0(lggr logger.Logger, addr common.Address, ec client.Client, lp logpoller.LogPoller, estimator gas.EvmFeeEstimator, srcClient client.Client) (*OffRampV1_0_0, error) { +func NewOffRampV1_0_0(lggr logger.Logger, addr common.Address, ec client.Client, lp logpoller.LogPoller, estimator gas.EvmFeeEstimator) (*OffRampV1_0_0, error) { offRamp, err := evm_2_evm_offramp.NewEVM2EVMOffRamp(addr, ec) if err != nil { return nil, err @@ -292,22 +302,6 @@ func NewOffRampV1_0_0(lggr logger.Logger, addr common.Address, ec client.Client, if err := logpollerutil.RegisterLpFilters(lp, filters); err != nil { return nil, err } - s, err := offRamp.GetStaticConfig(nil) - if err != nil { - return nil, err - } - // Must point to the correct version onramp - contractType, version, err := ccipconfig.TypeAndVersion(s.OnRamp, srcClient) - if err != nil { - return nil, err - } - if contractType != ccipconfig.EVM2EVMOnRamp || version.String() != "1.0.0" { - return nil, errors.Errorf("offramp points to invalid onramp %v expected 1.0.0", version.String()) - } - onRamp, err := evm_2_evm_onramp_1_0_0.NewEVM2EVMOnRamp(s.OnRamp, srcClient) - if err != nil { - return nil, err - } - return &OffRampV1_0_0{offRamp: offRamp, onRamp: onRamp, addr: addr, lggr: lggr, lp: lp, filters: filters, + return &OffRampV1_0_0{offRamp: offRamp, addr: addr, lggr: lggr, lp: lp, filters: filters, estimator: estimator, executionReportArgs: executionReportArgs, eventSig: stateChanged, eventIndex: executionStateChangedSequenceNumberIndex}, nil } diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/offramp_v1_2_0.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/offramp_v1_2_0.go index e7a51f2eaa..f026b7c483 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/offramp_v1_2_0.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/offramp_v1_2_0.go @@ -17,7 +17,7 @@ import ( var _ OffRampReader = &OffRampV1_2_0{} -// In 1.2 we have a different estimator +// In 1.2 we have a different estimator impl type OffRampV1_2_0 struct { *OffRampV1_0_0 gasPriceEstimator prices.GasPriceEstimatorExec @@ -48,13 +48,12 @@ func (o *OffRampV1_2_0) ConfigChanged(onchainConfig []byte, offchainConfig []byt return onchainConfigParsed.PriceRegistry, destWrappedNative, nil } -func NewOffRampV1_2_0(lggr logger.Logger, addr common.Address, ec client.Client, lp logpoller.LogPoller, estimator gas.EvmFeeEstimator, srcClient client.Client) (*OffRampV1_2_0, error) { - v100, err := NewOffRampV1_0_0(lggr, addr, ec, lp, estimator, srcClient) +func NewOffRampV1_2_0(lggr logger.Logger, addr common.Address, ec client.Client, lp logpoller.LogPoller, estimator gas.EvmFeeEstimator) (*OffRampV1_2_0, error) { + v100, err := NewOffRampV1_0_0(lggr, addr, ec, lp, estimator) if err != nil { return nil, err } return &OffRampV1_2_0{ - OffRampV1_0_0: v100, - gasPriceEstimator: nil, + OffRampV1_0_0: v100, }, nil } diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/onramp_reader.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/onramp_reader.go index 5aa3e64ed9..2c47c189f8 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/onramp_reader.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/onramp_reader.go @@ -28,18 +28,14 @@ const ( //go:generate mockery --quiet --name OnRampReader --output . --filename onramp_reader_mock.go --inpackage --case=underscore type OnRampReader interface { + Closer // GetSendRequestsGteSeqNum returns all the message send requests with sequence number greater than or equal to the provided. // If checkFinalityTags is set to true then confs param is ignored, the latest finalized block is used in the query. GetSendRequestsGteSeqNum(ctx context.Context, seqNum uint64, confs int) ([]Event[internal.EVM2EVMMessage], error) - // GetSendRequestsBetweenSeqNums returns all the message send requests in the provided sequence numbers range (inclusive). GetSendRequestsBetweenSeqNums(ctx context.Context, seqNumMin, seqNumMax uint64, confs int) ([]Event[internal.EVM2EVMMessage], error) - // Get router configured in the onRamp RouterAddress() common.Address - - // Reader cleanup i.e. unsubscribe from logs - Close(opt ...pg.QOpt) error } // NewOnRampReader determines the appropriate version of the onramp and returns a reader for it diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/price_registry_reader.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/price_registry_reader.go index f7ad1782bf..944d88ac15 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/price_registry_reader.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/price_registry_reader.go @@ -42,21 +42,15 @@ type GasPriceUpdate struct { } type PriceRegistryReader interface { + Close(qopts ...pg.QOpt) error // GetTokenPriceUpdatesCreatedAfter returns all the token price updates that happened after the provided timestamp. GetTokenPriceUpdatesCreatedAfter(ctx context.Context, ts time.Time, confs int) ([]Event[TokenPriceUpdate], error) - // GetGasPriceUpdatesCreatedAfter returns all the gas price updates that happened after the provided timestamp. GetGasPriceUpdatesCreatedAfter(ctx context.Context, chainSelector uint64, ts time.Time, confs int) ([]Event[GasPriceUpdate], error) - Address() common.Address - FeeTokenEvents() []common.Hash - GetFeeTokens(ctx context.Context) ([]common.Address, error) - GetTokenPrices(ctx context.Context, wantedTokens []common.Address) ([]TokenPriceUpdate, error) - - Close(qopts ...pg.QOpt) error } // NewPriceRegistryReader determines the appropriate version of the price registry and returns a reader for it. diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/price_registry_reader_test.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/price_registry_reader_test.go new file mode 100644 index 0000000000..7c6a51ecdf --- /dev/null +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/price_registry_reader_test.go @@ -0,0 +1,20 @@ +package ccipdata + +import ( + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks" + lpmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller/mocks" + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +func TestPriceRegistryFilters(t *testing.T) { + assertFilterRegistration(t, new(lpmocks.LogPoller), func(lp *lpmocks.LogPoller, addr common.Address) Closer { + c, err := NewPriceRegistryV1_0_0(logger.TestLogger(t), addr, lp, new(mocks.Client)) + require.NoError(t, err) + return c + }, 2) +} diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/price_registry_v1_0_0.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/price_registry_v1_0_0.go index 280df514c2..4e2516d62d 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/price_registry_v1_0_0.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/price_registry_v1_0_0.go @@ -120,7 +120,7 @@ func (p *PriceRegistryV1_0_0) GetGasPriceUpdatesCreatedAfter(ctx context.Context const ExecPluginLabel = "exec" -func NewPriceRegistryV1_0_0(lggr logger.Logger, priceRegistryAddr common.Address, lp logpoller.LogPoller, ec client.Client, qopts ...pg.QOpt) (*PriceRegistryV1_0_0, error) { +func NewPriceRegistryV1_0_0(lggr logger.Logger, priceRegistryAddr common.Address, lp logpoller.LogPoller, ec client.Client) (*PriceRegistryV1_0_0, error) { // TODO pass label priceRegistry, err := observability.NewObservedPriceRegistryV1_0_0(priceRegistryAddr, ExecPluginLabel, ec) if err != nil { @@ -147,7 +147,7 @@ func NewPriceRegistryV1_0_0(lggr logger.Logger, priceRegistryAddr common.Address EventSigs: []common.Hash{abihelpers.MustGetEventID("FeeTokenAdded", priceRegistryABI)}, Addresses: []common.Address{priceRegistryAddr}, }} - err = logpollerutil.RegisterLpFilters(lp, filters, qopts...) + err = logpollerutil.RegisterLpFilters(lp, filters) if err != nil { return nil, err } diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/reader.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/reader.go index 32f2ec6f49..ece0ca1c7a 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/reader.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/reader.go @@ -5,6 +5,8 @@ import ( "time" "github.com/ethereum/go-ethereum/common" + + "github.com/smartcontractkit/chainlink/v2/core/services/pg" ) type Event[T any] struct { @@ -19,6 +21,10 @@ type Meta struct { LogIndex uint } +type Closer interface { + Close(qopts ...pg.QOpt) error +} + // Client can be used to fetch CCIP related parsed on-chain data. // //go:generate mockery --quiet --name Reader --output . --filename reader_mock.go --inpackage --case=underscore diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/usdc_reader_test.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/usdc_reader_test.go index 88aa699382..d8e8db0ef6 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/usdc_reader_test.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/usdc_reader_test.go @@ -5,13 +5,14 @@ import ( "fmt" "testing" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller/mocks" + lpmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller/mocks" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/utils" ) @@ -25,7 +26,7 @@ func TestLogPollerClient_GetLastUSDCMessagePriorToLogIndexInTx(t *testing.T) { lggr := logger.TestLogger(t) t.Run("multiple found", func(t *testing.T) { - lp := mocks.NewLogPoller(t) + lp := lpmocks.NewLogPoller(t) lp.On("RegisterFilter", mock.Anything).Return(nil) u, err := NewUSDCReader(lggr, utils.RandomAddress(), lp) require.NoError(t, err) @@ -47,7 +48,7 @@ func TestLogPollerClient_GetLastUSDCMessagePriorToLogIndexInTx(t *testing.T) { }) t.Run("none found", func(t *testing.T) { - lp := mocks.NewLogPoller(t) + lp := lpmocks.NewLogPoller(t) lp.On("RegisterFilter", mock.Anything).Return(nil) u, err := NewUSDCReader(lggr, utils.RandomAddress(), lp) require.NoError(t, err) @@ -76,3 +77,11 @@ func TestParse(t *testing.T) { require.Equal(t, expectedPostParse, hexutil.Encode(parsedBody)) } + +func TestUSDCReaderFilters(t *testing.T) { + assertFilterRegistration(t, new(lpmocks.LogPoller), func(lp *lpmocks.LogPoller, addr common.Address) Closer { + c, err := NewUSDCReader(logger.TestLogger(t), addr, lp) + require.NoError(t, err) + return c + }, 1) +} diff --git a/core/services/relay/evm/ccip.go b/core/services/relay/evm/ccip.go index 4ded138f0c..f0ccdfe85f 100644 --- a/core/services/relay/evm/ccip.go +++ b/core/services/relay/evm/ccip.go @@ -73,7 +73,16 @@ func NewCCIPExecutionProvider(lggr logger.Logger, chainSet evm.Chain, rargs rela if err != nil { return nil, err } - contractTransmitter, err := newContractTransmitter(lggr, rargs, transmitterID, configWatcher, ks, ccip.ExecutionReportToEthTxMeta) + address := common.HexToAddress(relayOpts.ContractID) + typ, ver, err := ccipconfig.TypeAndVersion(address, chainSet.Client()) + if err != nil { + return nil, err + } + fn, err := ccip.ExecReportToEthTxMeta(typ, ver) + if err != nil { + return nil, err + } + contractTransmitter, err := newContractTransmitter(lggr, rargs, transmitterID, configWatcher, ks, fn) if err != nil { return nil, err }