Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CCIP Merge] Capabilities fix [CCIP-2943] #14048

Merged
merged 16 commits into from
Aug 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/odd-hats-repeat.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"chainlink": patch
---

#internal fix the mock trigger to ensure events are sent
4 changes: 4 additions & 0 deletions .mockery.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ packages:
github.com/smartcontractkit/chainlink/v2/core/bridges:
interfaces:
ORM:
github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types:
interfaces:
CCIPOracle:
OracleCreator:
github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types:
interfaces:
Dispatcher:
Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ THE SOFTWARE.


*All content residing under (1) “/contracts/src/v0.8/ccip”; (2)
“/core/gethwrappers/ccip”; (3) “/core/services/ocr2/plugins/ccip” are licensed
“/core/gethwrappers/ccip”; (3) “/core/services/ocr2/plugins/ccip”; (4) "/core/capabilities/ccip" are licensed
under “Business Source License 1.1” with a Change Date of May 23, 2027 and
Change License to “MIT License”

Expand Down
136 changes: 93 additions & 43 deletions core/capabilities/ccip/ccip_integration_tests/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@ import (
"encoding/hex"
"math/big"
"sort"
"strconv"
"testing"
"time"

"github.com/smartcontractkit/chainlink-ccip/chainconfig"
"github.com/smartcontractkit/chainlink-ccip/pluginconfig"
commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config"
"github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3"
"github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccip_integration_tests/integrationhelpers"
cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types"

Expand Down Expand Up @@ -53,9 +56,27 @@ const (
CapabilityLabelledName = "ccip"
CapabilityVersion = "v1.0.0"
NodeOperatorID = 1
// TODO: this is 8 hours now to match what is hardcoded in the exec plugin.
// Eventually this should drive what is set in the exec plugin.
FirstBlockAge = 8 * time.Hour

// These constants drive what is set in the plugin offchain configs.
FirstBlockAge = 8 * time.Hour
RemoteGasPriceBatchWriteFrequency = 30 * time.Minute
BatchGasLimit = 6_500_000
RelativeBoostPerWaitHour = 1.5
InflightCacheExpiry = 10 * time.Minute
RootSnoozeTime = 30 * time.Minute
BatchingStrategyID = 0
DeltaProgress = 30 * time.Second
DeltaResend = 10 * time.Second
DeltaInitial = 20 * time.Second
DeltaRound = 2 * time.Second
DeltaGrace = 2 * time.Second
DeltaCertifiedCommitRequest = 10 * time.Second
DeltaStage = 10 * time.Second
Rmax = 3
MaxDurationQuery = 50 * time.Millisecond
MaxDurationObservation = 5 * time.Second
MaxDurationShouldAcceptAttestedReport = 10 * time.Second
MaxDurationShouldTransmitAcceptedReport = 10 * time.Second
)

func e18Mult(amount uint64) *big.Int {
Expand Down Expand Up @@ -412,11 +433,18 @@ func AddChainConfig(
// Need to sort, otherwise _checkIsValidUniqueSubset onChain will fail
sortP2PIDS(p2pIDs)
// First Add ChainConfig that includes all p2pIDs as readers
chainConfig := integrationhelpers.SetupConfigInfo(chainSelector, p2pIDs, f, []byte(strconv.FormatUint(chainSelector, 10)))
encodedExtraChainConfig, err := chainconfig.EncodeChainConfig(chainconfig.ChainConfig{
GasPriceDeviationPPB: ccipocr3.NewBigIntFromInt64(1000),
DAGasPriceDeviationPPB: ccipocr3.NewBigIntFromInt64(0),
FinalityDepth: 10,
OptimisticConfirmations: 1,
})
require.NoError(t, err)
chainConfig := integrationhelpers.SetupConfigInfo(chainSelector, p2pIDs, f, encodedExtraChainConfig)
inputConfig := []ccip_config.CCIPConfigTypesChainConfigInfo{
chainConfig,
}
_, err := h.ccipConfig.ApplyChainConfigUpdates(h.owner, nil, inputConfig)
_, err = h.ccipConfig.ApplyChainConfigUpdates(h.owner, nil, inputConfig)
require.NoError(t, err)
h.backend.Commit()
return chainConfig
Expand All @@ -437,49 +465,71 @@ func (h *homeChain) AddDON(
for range oracles {
schedule = append(schedule, 1)
}
signers, transmitters, f, _, offchainConfigVersion, offchainConfig, err := ocr3confighelper.ContractSetConfigArgsForTests(
30*time.Second, // deltaProgress
10*time.Second, // deltaResend
20*time.Second, // deltaInitial
2*time.Second, // deltaRound
2*time.Second, // deltaGrace
10*time.Second, // deltaCertifiedCommitRequest TODO: whats a good value for this?
10*time.Second, // deltaStage
3, // rmax
schedule,
oracles,
[]byte{}, // empty offchain config
50*time.Millisecond, // maxDurationQuery
5*time.Second, // maxDurationObservation
10*time.Second, // maxDurationShouldAcceptAttestedReport
10*time.Second, // maxDurationShouldTransmitAcceptedReport
int(f),
[]byte{}) // empty OnChainConfig
require.NoError(t, err, "failed to create contract config")

tabi, err := ocr3_config_encoder.IOCR3ConfigEncoderMetaData.GetAbi()
require.NoError(t, err)

signersBytes := make([][]byte, len(signers))
for i, signer := range signers {
signersBytes[i] = signer
}

transmittersBytes := make([][]byte, len(transmitters))
for i, transmitter := range transmitters {
// anotherErr because linting doesn't want to shadow err
parsed, anotherErr := common.ParseHexOrString(string(transmitter))
require.NoError(t, anotherErr)
transmittersBytes[i] = parsed
}

// Add DON on capability registry contract
var ocr3Configs []ocr3_config_encoder.CCIPConfigTypesOCR3Config
for _, pluginType := range []cctypes.PluginType{cctypes.PluginTypeCCIPCommit, cctypes.PluginTypeCCIPExec} {
var encodedOffchainConfig []byte
var err2 error
if pluginType == cctypes.PluginTypeCCIPCommit {
encodedOffchainConfig, err2 = pluginconfig.EncodeCommitOffchainConfig(pluginconfig.CommitOffchainConfig{
RemoteGasPriceBatchWriteFrequency: *commonconfig.MustNewDuration(RemoteGasPriceBatchWriteFrequency),
// TODO: implement token price writes
// TokenPriceBatchWriteFrequency: *commonconfig.MustNewDuration(tokenPriceBatchWriteFrequency),
})
require.NoError(t, err2)
} else {
encodedOffchainConfig, err2 = pluginconfig.EncodeExecuteOffchainConfig(pluginconfig.ExecuteOffchainConfig{
BatchGasLimit: BatchGasLimit,
RelativeBoostPerWaitHour: RelativeBoostPerWaitHour,
MessageVisibilityInterval: *commonconfig.MustNewDuration(FirstBlockAge),
InflightCacheExpiry: *commonconfig.MustNewDuration(InflightCacheExpiry),
RootSnoozeTime: *commonconfig.MustNewDuration(RootSnoozeTime),
BatchingStrategyID: BatchingStrategyID,
})
require.NoError(t, err2)
}
signers, transmitters, configF, _, offchainConfigVersion, offchainConfig, err2 := ocr3confighelper.ContractSetConfigArgsForTests(
DeltaProgress,
DeltaResend,
DeltaInitial,
DeltaRound,
DeltaGrace,
DeltaCertifiedCommitRequest,
DeltaStage,
Rmax,
schedule,
oracles,
encodedOffchainConfig,
MaxDurationQuery,
MaxDurationObservation,
MaxDurationShouldAcceptAttestedReport,
MaxDurationShouldTransmitAcceptedReport,
int(f),
[]byte{}, // empty OnChainConfig
)
require.NoError(t, err2, "failed to create contract config")

signersBytes := make([][]byte, len(signers))
for i, signer := range signers {
signersBytes[i] = signer
}

transmittersBytes := make([][]byte, len(transmitters))
for i, transmitter := range transmitters {
// anotherErr because linting doesn't want to shadow err
parsed, anotherErr := common.ParseHexOrString(string(transmitter))
require.NoError(t, anotherErr)
transmittersBytes[i] = parsed
}

ocr3Configs = append(ocr3Configs, ocr3_config_encoder.CCIPConfigTypesOCR3Config{
PluginType: uint8(pluginType),
ChainSelector: chainSelector,
F: f,
F: configF,
OffchainConfigVersion: offchainConfigVersion,
OfframpAddress: uni.offramp.Address().Bytes(),
BootstrapP2PIds: [][32]byte{bootstrapP2PID},
Expand Down Expand Up @@ -522,13 +572,13 @@ func (h *homeChain) AddDON(
require.NotZero(t, donID, "failed to get donID from config set event")

var signerAddresses []common.Address
for _, signer := range signers {
signerAddresses = append(signerAddresses, common.BytesToAddress(signer))
for _, oracle := range oracles {
signerAddresses = append(signerAddresses, common.BytesToAddress(oracle.OnchainPublicKey))
}

var transmitterAddresses []common.Address
for _, transmitter := range transmitters {
transmitterAddresses = append(transmitterAddresses, common.HexToAddress(string(transmitter)))
for _, oracle := range oracles {
transmitterAddresses = append(transmitterAddresses, common.HexToAddress(string(oracle.TransmitAccount)))
}

// get the config digest from the ccip config contract and set config on the offramp.
Expand Down
23 changes: 19 additions & 4 deletions core/capabilities/ccip/ccip_integration_tests/home_chain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (

libocrtypes "github.com/smartcontractkit/libocr/ragep2p/types"

"github.com/smartcontractkit/chainlink-ccip/chainconfig"
ccipreader "github.com/smartcontractkit/chainlink-ccip/pkg/reader"

cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3"
Expand All @@ -35,15 +36,22 @@ func TestHomeChainReader(t *testing.T) {
p2pIDs := integrationhelpers.P2pIDsFromInts(arr)
uni.AddCapability(p2pIDs)
//==============================Apply configs to Capability Contract=================================
chainAConf := integrationhelpers.SetupConfigInfo(integrationhelpers.ChainA, p2pIDs, integrationhelpers.FChainA, []byte("ChainA"))
chainBConf := integrationhelpers.SetupConfigInfo(integrationhelpers.ChainB, p2pIDs[1:], integrationhelpers.FChainB, []byte("ChainB"))
chainCConf := integrationhelpers.SetupConfigInfo(integrationhelpers.ChainC, p2pIDs[2:], integrationhelpers.FChainC, []byte("ChainC"))
encodedChainConfig, err := chainconfig.EncodeChainConfig(chainconfig.ChainConfig{
GasPriceDeviationPPB: cciptypes.NewBigIntFromInt64(1000),
DAGasPriceDeviationPPB: cciptypes.NewBigIntFromInt64(1_000_000),
FinalityDepth: -1,
OptimisticConfirmations: 1,
})
require.NoError(t, err)
chainAConf := integrationhelpers.SetupConfigInfo(integrationhelpers.ChainA, p2pIDs, integrationhelpers.FChainA, encodedChainConfig)
chainBConf := integrationhelpers.SetupConfigInfo(integrationhelpers.ChainB, p2pIDs[1:], integrationhelpers.FChainB, encodedChainConfig)
chainCConf := integrationhelpers.SetupConfigInfo(integrationhelpers.ChainC, p2pIDs[2:], integrationhelpers.FChainC, encodedChainConfig)
inputConfig := []capcfg.CCIPConfigTypesChainConfigInfo{
chainAConf,
chainBConf,
chainCConf,
}
_, err := uni.CcipCfg.ApplyChainConfigUpdates(uni.Transactor, nil, inputConfig)
_, err = uni.CcipCfg.ApplyChainConfigUpdates(uni.Transactor, nil, inputConfig)
require.NoError(t, err)
uni.Backend.Commit()
//================================Setup HomeChainReader===============================
Expand All @@ -63,6 +71,7 @@ func TestHomeChainReader(t *testing.T) {
expectedChainConfigs[cciptypes.ChainSelector(c.ChainSelector)] = ccipreader.ChainConfig{
FChain: int(c.ChainConfig.FChain),
SupportedNodes: toPeerIDs(c.ChainConfig.Readers),
Config: mustDecodeChainConfig(t, c.ChainConfig.Config),
}
}
configs, err := homeChain.GetAllChainConfigs()
Expand All @@ -86,3 +95,9 @@ func toPeerIDs(readers [][32]byte) mapset.Set[libocrtypes.PeerID] {
}
return peerIDs
}

func mustDecodeChainConfig(t *testing.T, encodedChainConfig []byte) chainconfig.ChainConfig {
chainConfig, err := chainconfig.DecodeChainConfig(encodedChainConfig)
require.NoError(t, err)
return chainConfig
}
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ const (
CcipCapabilityVersion = "v1.0"
)

var CapabilityID = fmt.Sprintf("%s@%s", CcipCapabilityLabelledName, CcipCapabilityVersion)

type TestUniverse struct {
Transactor *bind.TransactOpts
Backend *backends.SimulatedBackend
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"testing"
"time"

coretypes "github.com/smartcontractkit/chainlink-common/pkg/types/core/mocks"
"github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/validate"

"github.com/ethereum/go-ethereum/accounts/abi/bind"
Expand Down Expand Up @@ -131,9 +132,10 @@ func setupNodeOCR3(
CSAETHKeystore: kStore,
}
relayerFactory := chainlink.RelayerFactory{
Logger: lggr,
LoopRegistry: plugins.NewLoopRegistry(lggr.Named("LoopRegistry"), cfg.Tracing()),
GRPCOpts: loop.GRPCOpts{},
Logger: lggr,
LoopRegistry: plugins.NewLoopRegistry(lggr.Named("LoopRegistry"), cfg.Tracing()),
GRPCOpts: loop.GRPCOpts{},
CapabilitiesRegistry: coretypes.NewCapabilitiesRegistry(t),
}
initOps := []chainlink.CoreRelayerChainInitFunc{chainlink.InitEVM(testutils.Context(t), relayerFactory, evmOpts)}
rci, err := chainlink.NewCoreRelayerChainInteroperators(initOps...)
Expand Down
22 changes: 15 additions & 7 deletions core/capabilities/ccip/configs/evm/chain_writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,13 @@ var (
offrampABI = evmtypes.MustGetABI(evm_2_evm_multi_offramp.EVM2EVMMultiOffRampABI)
)

func MustChainWriterConfig(fromAddress common.Address, maxGasPrice *assets.Wei) []byte {
rawConfig := ChainWriterConfigRaw(fromAddress, maxGasPrice)
func MustChainWriterConfig(
fromAddress common.Address,
maxGasPrice *assets.Wei,
commitGasLimit,
execBatchGasLimit uint64,
) []byte {
rawConfig := ChainWriterConfigRaw(fromAddress, maxGasPrice, commitGasLimit, execBatchGasLimit)
encoded, err := json.Marshal(rawConfig)
if err != nil {
panic(fmt.Errorf("failed to marshal ChainWriterConfig: %w", err))
Expand All @@ -31,7 +36,12 @@ func MustChainWriterConfig(fromAddress common.Address, maxGasPrice *assets.Wei)
}

// ChainWriterConfigRaw returns a ChainWriterConfig that can be used to transmit commit and execute reports.
func ChainWriterConfigRaw(fromAddress common.Address, maxGasPrice *assets.Wei) evmrelaytypes.ChainWriterConfig {
func ChainWriterConfigRaw(
fromAddress common.Address,
maxGasPrice *assets.Wei,
commitGasLimit,
execBatchGasLimit uint64,
) evmrelaytypes.ChainWriterConfig {
return evmrelaytypes.ChainWriterConfig{
Contracts: map[string]*evmrelaytypes.ContractConfig{
consts.ContractNameOffRamp: {
Expand All @@ -40,14 +50,12 @@ func ChainWriterConfigRaw(fromAddress common.Address, maxGasPrice *assets.Wei) e
consts.MethodCommit: {
ChainSpecificName: mustGetMethodName("commit", offrampABI),
FromAddress: fromAddress,
// TODO: inject this into the method, should be fetched from the OCR config.
GasLimit: 500_000,
GasLimit: commitGasLimit,
},
consts.MethodExecute: {
ChainSpecificName: mustGetMethodName("execute", offrampABI),
FromAddress: fromAddress,
// TODO: inject this into the method, should be fetched from the OCR config.
GasLimit: 6_500_000,
GasLimit: execBatchGasLimit,
},
},
},
Expand Down
Loading
Loading