Skip to content

Commit

Permalink
Remove direct offramp access from exec plugin (#241)
Browse files Browse the repository at this point in the history
  • Loading branch information
jarnaud authored Nov 2, 2023
1 parent 8c468ff commit 0c738f2
Show file tree
Hide file tree
Showing 8 changed files with 169 additions and 37 deletions.
1 change: 0 additions & 1 deletion core/services/ocr2/plugins/ccip/execution_plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,6 @@ func jobSpecToExecPluginConfig(lggr logger.Logger, jb job.Job, chainSet evm.Lega
destLP: destChain.LogPoller(),
onRampReader: onRampReader,
destReader: ccipdata.NewLogPollerReader(destChain.LogPoller(), execLggr, destChain.Client()),
offRamp: offRamp,
commitStoreReader: commitStoreReader,
offRampReader: offRampReader,
sourcePriceRegistry: sourcePriceRegistry,
Expand Down
10 changes: 5 additions & 5 deletions core/services/ocr2/plugins/ccip/execution_reporting_plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ type ExecutionPluginStaticConfig struct {
onRampReader ccipdata.OnRampReader
destReader ccipdata.Reader
offRampReader ccipdata.OffRampReader
offRamp evm_2_evm_offramp.EVM2EVMOffRampInterface
commitStoreReader ccipdata.CommitStoreReader
sourcePriceRegistry ccipdata.PriceRegistryReader
sourceWrappedNativeToken common.Address
Expand Down Expand Up @@ -237,7 +236,7 @@ func (r *ExecutionReportingPlugin) getExecutableObservations(ctx context.Context
// always be the lower bound of what would be available on chain
// since we already account for inflight txs.
getAllowedTokenAmount := cache.LazyFetch(func() (evm_2_evm_offramp.RateLimiterTokenBucket, error) {
return r.config.offRamp.CurrentRateLimiterState(&bind.CallOpts{Context: ctx})
return r.config.offRampReader.CurrentRateLimiterState(&bind.CallOpts{Context: ctx})
})
sourceToDestTokens, supportedDestTokens, err := r.sourceDestinationTokens(ctx)
if err != nil {
Expand Down Expand Up @@ -393,7 +392,8 @@ func (r *ExecutionReportingPlugin) destPoolRateLimits(ctx context.Context, commi
return nil, fmt.Errorf("new custom dest token pool %s: %w", poolAddress, err)
}

rateLimiterState, err := tokenPool.CurrentOffRampRateLimiterState(&bind.CallOpts{Context: ctx}, r.config.offRamp.Address())
offRampAddr := r.config.offRampReader.Address()
rateLimiterState, err := tokenPool.CurrentOffRampRateLimiterState(&bind.CallOpts{Context: ctx}, offRampAddr)
if err != nil {
return nil, fmt.Errorf("get rate off ramp rate limiter state: %w", err)
}
Expand Down Expand Up @@ -483,7 +483,7 @@ func (r *ExecutionReportingPlugin) buildBatch(
} else {
// Nothing inflight take from chain.
// Chain holds existing nonce.
nonce, err := r.config.offRamp.GetSenderNonce(nil, msg.Sender)
nonce, err := r.config.offRampReader.GetSenderNonce(nil, msg.Sender)
if err != nil {
lggr.Errorw("unable to get sender nonce", "err", err, "seqNr", msg.SequenceNumber)
continue
Expand Down Expand Up @@ -1040,7 +1040,7 @@ func (r *ExecutionReportingPlugin) isStaleReport(messages []internal.EVM2EVMMess
// If the first message is executed already, this execution report is stale.
// Note the default execution state, including for arbitrary seq number not yet committed
// is ExecutionStateUntouched.
msgState, err := r.config.offRamp.GetExecutionState(nil, messages[0].SequenceNumber)
msgState, err := r.config.offRampReader.GetExecutionState(nil, messages[0].SequenceNumber)
if err != nil {
return true, err
}
Expand Down
64 changes: 34 additions & 30 deletions core/services/ocr2/plugins/ccip/execution_reporting_plugin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import (

lpMocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller/mocks"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/custom_token_pool"
mock_contracts "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/mocks"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/cache"
Expand Down Expand Up @@ -109,10 +108,6 @@ func TestExecutionReportingPlugin_Observation(t *testing.T) {
Return(tc.unexpiredReports, nil).Maybe()
p.config.commitStoreReader = commitStoreReader

offRamp, _ := testhelpers.NewFakeOffRamp(t)
offRamp.SetRateLimiterState(tc.rateLimiterState)
p.config.offRamp = offRamp

destReader := ccipdata.NewMockReader(t)
destReader.On("LatestBlock", ctx).Return(int64(1234), nil).Maybe()
p.config.destReader = destReader
Expand All @@ -123,15 +118,22 @@ func TestExecutionReportingPlugin_Observation(t *testing.T) {
Data: ccipdata.ExecutionStateChanged{SequenceNumber: seqNum},
})
}
offRampReader := ccipdata.NewMockOffRampReader(t)
offRampReader.On("GetExecutionStateChangesBetweenSeqNums", ctx, mock.Anything, mock.Anything, 0).

offRamp, _ := testhelpers.NewFakeOffRamp(t)
offRamp.SetRateLimiterState(tc.rateLimiterState)

mockOffRampReader := ccipdata.NewMockOffRampReader(t)
mockOffRampReader.On("GetExecutionStateChangesBetweenSeqNums", ctx, mock.Anything, mock.Anything, 0).
Return(executionEvents, nil).Maybe()
p.config.offRampReader = offRampReader
mockOffRampReader.On("CurrentRateLimiterState", mock.Anything).Return(tc.rateLimiterState, nil).Maybe()
mockOffRampReader.On("Address").Return(offRamp.Address()).Maybe()
mockOffRampReader.On("GetSenderNonce", mock.Anything, mock.Anything).Return(offRamp.GetSenderNonce(nil, utils.RandomAddress())).Maybe()
p.config.offRampReader = mockOffRampReader

sourceReader := ccipdata.NewMockOnRampReader(t)
sourceReader.On("GetSendRequestsBetweenSeqNums", ctx, mock.Anything, mock.Anything, 0).
mockOnRampReader := ccipdata.NewMockOnRampReader(t)
mockOnRampReader.On("GetSendRequestsBetweenSeqNums", ctx, mock.Anything, mock.Anything, 0).
Return(tc.sendRequests, nil).Maybe()
p.config.onRampReader = sourceReader
p.config.onRampReader = mockOnRampReader

cachedDestTokens := cache.NewMockAutoSync[cache.CachedTokens](t)
cachedDestTokens.On("Get", ctx).Return(cache.CachedTokens{
Expand Down Expand Up @@ -255,20 +257,18 @@ func TestExecutionReportingPlugin_ShouldAcceptFinalizedReport(t *testing.T) {
encodedReport, err := ccipdata.EncodeExecutionReport(report)
require.NoError(t, err)

mockOffRamp, _ := testhelpers.NewFakeOffRamp(t)
mockOffRampReader := ccipdata.NewMockOffRampReader(t)
mockOffRampReader.On("DecodeExecutionReport", encodedReport).Return(report, nil)

plugin := ExecutionReportingPlugin{
config: ExecutionPluginStaticConfig{
offRamp: mockOffRamp,
offRampReader: mockOffRampReader,
},
lggr: logger.TestLogger(t),
inflightReports: newInflightExecReportsContainer(models.MustMakeDuration(1 * time.Hour).Duration()),
}

mockedExecState := mockOffRamp.On("GetExecutionState", mock.Anything, uint64(12)).Return(uint8(ccipdata.ExecutionStateUntouched), nil).Once()

offRampReader := ccipdata.NewMockOffRampReader(t)
plugin.config.offRampReader = offRampReader
offRampReader.On("DecodeExecutionReport", encodedReport).Return(report, nil)
mockedExecState := mockOffRampReader.On("GetExecutionState", mock.Anything, uint64(12)).Return(uint8(ccipdata.ExecutionStateUntouched), nil).Once()

should, err := plugin.ShouldAcceptFinalizedReport(testutils.Context(t), ocrtypes.ReportTimestamp{}, encodedReport)
require.NoError(t, err)
Expand Down Expand Up @@ -304,24 +304,21 @@ func TestExecutionReportingPlugin_ShouldTransmitAcceptedReport(t *testing.T) {
encodedReport, err := ccipdata.EncodeExecutionReport(report)
require.NoError(t, err)

mockOffRamp := &mock_contracts.EVM2EVMOffRampInterface{}
mockCommitStore := ccipdata.NewMockCommitStoreReader(t)
mockCommitStoreReader := ccipdata.NewMockCommitStoreReader(t)

mockOffRampReader := ccipdata.NewMockOffRampReader(t)
mockOffRampReader.On("DecodeExecutionReport", encodedReport).Return(report, nil)
mockedExecState := mockOffRampReader.On("GetExecutionState", mock.Anything, uint64(12)).Return(uint8(ccipdata.ExecutionStateUntouched), nil).Once()

plugin := ExecutionReportingPlugin{
config: ExecutionPluginStaticConfig{
offRamp: mockOffRamp,
commitStoreReader: mockCommitStore,
commitStoreReader: mockCommitStoreReader,
offRampReader: mockOffRampReader,
},
lggr: logger.TestLogger(t),
inflightReports: newInflightExecReportsContainer(models.MustMakeDuration(1 * time.Hour).Duration()),
}

mockedExecState := mockOffRamp.On("GetExecutionState", mock.Anything, uint64(12)).Return(uint8(ccipdata.ExecutionStateUntouched), nil).Once()

offRampReader := ccipdata.NewMockOffRampReader(t)
plugin.config.offRampReader = offRampReader
offRampReader.On("DecodeExecutionReport", encodedReport).Return(report, nil)

should, err := plugin.ShouldTransmitAcceptedReport(testutils.Context(t), ocrtypes.ReportTimestamp{}, encodedReport)
require.NoError(t, err)
assert.Equal(t, true, should)
Expand Down Expand Up @@ -628,9 +625,13 @@ func TestExecutionReportingPlugin_buildBatch(t *testing.T) {
gasPriceEstimator.On("EstimateMsgCostUSD", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(big.NewInt(0), nil)
}

// Mock calls to reader.
mockOffRampReader := ccipdata.NewMockOffRampReader(t)
mockOffRampReader.On("GetSenderNonce", mock.Anything, sender1).Return(uint64(0), nil).Maybe()

plugin := ExecutionReportingPlugin{
config: ExecutionPluginStaticConfig{
offRamp: offRamp,
offRampReader: mockOffRampReader,
},
destWrappedNative: destNative,
offchainConfig: ccipdata.ExecOffchainConfig{
Expand Down Expand Up @@ -872,7 +873,10 @@ func TestExecutionReportingPlugin_destPoolRateLimits(t *testing.T) {

offRamp, offRampAddr := testhelpers.NewFakeOffRamp(t)
offRamp.SetTokenPools(tc.destPools)
p.config.offRamp = offRamp

mockOffRampReader := ccipdata.NewMockOffRampReader(t)
mockOffRampReader.On("Address").Return(offRampAddr, nil).Maybe()
p.config.offRampReader = mockOffRampReader

p.customTokenPoolFactory = func(ctx context.Context, poolAddress common.Address, _ bind.ContractBackend) (custom_token_pool.CustomTokenPoolInterface, error) {
mp := &mockPool{}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"time"

"github.com/Masterminds/semver/v3"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/pkg/errors"
Expand Down Expand Up @@ -113,6 +114,11 @@ type OffRampReader interface {
OffchainConfig() ExecOffchainConfig
OnchainConfig() ExecOnchainConfig
GasPriceEstimator() prices.GasPriceEstimatorExec

// Required for the execution plugin.
GetSenderNonce(opts *bind.CallOpts, sender common.Address) (uint64, error)
CurrentRateLimiterState(opts *bind.CallOpts) (evm_2_evm_offramp.RateLimiterTokenBucket, error)
GetExecutionState(opts *bind.CallOpts, sequenceNumber uint64) (uint8, error)
}

// MessageExecutionState defines the execution states of CCIP messages.
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_offramp"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_offramp_1_0_0"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router"
"github.com/smartcontractkit/chainlink/v2/core/logger"
Expand Down Expand Up @@ -99,6 +100,28 @@ type OffRampV1_0_0 struct {
onchainConfig ExecOnchainConfig
}

func (o *OffRampV1_0_0) GetExecutionState(opts *bind.CallOpts, sequenceNumber uint64) (uint8, error) {
return o.offRamp.GetExecutionState(opts, sequenceNumber)
}

func (o *OffRampV1_0_0) GetSenderNonce(opts *bind.CallOpts, sender common.Address) (uint64, error) {
return o.offRamp.GetSenderNonce(opts, sender)
}

func (o *OffRampV1_0_0) CurrentRateLimiterState(opts *bind.CallOpts) (evm_2_evm_offramp.RateLimiterTokenBucket, error) {
state, err := o.offRamp.CurrentRateLimiterState(opts)
if err != nil {
return *new(evm_2_evm_offramp.RateLimiterTokenBucket), err
}
return evm_2_evm_offramp.RateLimiterTokenBucket{
Tokens: state.Tokens,
LastUpdated: state.LastUpdated,
IsEnabled: state.IsEnabled,
Capacity: state.Capacity,
Rate: state.Rate,
}, nil
}

func (o *OffRampV1_0_0) GetDestinationToken(ctx context.Context, address common.Address) (common.Address, error) {
return o.offRamp.GetDestinationToken(&bind.CallOpts{Context: ctx}, address)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"time"

"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/pkg/errors"

Expand Down Expand Up @@ -83,6 +84,10 @@ type OffRampV1_2_0 struct {
onchainConfig ExecOnchainConfig
}

func (o *OffRampV1_2_0) CurrentRateLimiterState(opts *bind.CallOpts) (evm_2_evm_offramp.RateLimiterTokenBucket, error) {
return o.offRamp.CurrentRateLimiterState(opts)
}

func (o *OffRampV1_2_0) ChangeConfig(onchainConfig []byte, offchainConfig []byte) (common.Address, common.Address, error) {
onchainConfigParsed, err := abihelpers.DecodeAbiStruct[ExecOnchainConfigV1_2_0](onchainConfig)
if err != nil {
Expand Down
Loading

0 comments on commit 0c738f2

Please sign in to comment.