Skip to content

Commit

Permalink
feat(keystone): enable multiple OCR contracts per chain
Browse files Browse the repository at this point in the history
  • Loading branch information
MStreet3 committed Dec 23, 2024
1 parent 7314c07 commit 0cdba03
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 10 deletions.
2 changes: 2 additions & 0 deletions deployment/keystone/changeset/deploy_ocr3.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ var _ deployment.ChangeSet[ConfigureOCR3Config] = ConfigureOCR3Contract
type ConfigureOCR3Config struct {
ChainSel uint64
NodeIDs []string
Address *string // hex encoded address of the OCR3 contract to configure
OCR3Config *kslib.OracleConfig
DryRun bool
WriteGeneratedConfig io.Writer // if not nil, write the generated config to this writer as JSON [OCR2OracleConfig]
Expand All @@ -54,6 +55,7 @@ func ConfigureOCR3Contract(env deployment.Environment, cfg ConfigureOCR3Config)
ChainSel: cfg.ChainSel,
NodeIDs: cfg.NodeIDs,
OCR3Config: cfg.OCR3Config,
Address: cfg.Address,
DryRun: cfg.DryRun,
UseMCMS: cfg.UseMCMS(),
})
Expand Down
46 changes: 39 additions & 7 deletions deployment/keystone/changeset/internal/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (

capabilities_registry "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0"
kf "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/forwarder_1_0_0"
ocr3_capability "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/ocr3_capability_1_0_0"

"github.com/smartcontractkit/chainlink-common/pkg/logger"
)
Expand Down Expand Up @@ -321,12 +322,13 @@ func ConfigureOCR3Contract(env *deployment.Environment, chainSel uint64, dons []
if !ok {
return fmt.Errorf("failed to get contract set for chain %d", chainSel)
}
contract := contracts.OCR3
if contract == nil {
return fmt.Errorf("no ocr3 contract found for chain %d", chainSel)

contract, err := getOCR3Contract(contracts.OCR3, nil)
if err != nil {
return fmt.Errorf("failed to get OCR3 contract: %w", err)
}

_, err := configureOCR3contract(configureOCR3Request{
_, err = configureOCR3contract(configureOCR3Request{
cfg: cfg,
chain: registryChain,
contract: contract,
Expand All @@ -349,6 +351,7 @@ type ConfigureOCR3Resp struct {
type ConfigureOCR3Config struct {
ChainSel uint64
NodeIDs []string
Address *string // hex encoded address of the OCR3 contract to configure
OCR3Config *OracleConfig
DryRun bool

Expand Down Expand Up @@ -377,10 +380,12 @@ func ConfigureOCR3ContractFromJD(env *deployment.Environment, cfg ConfigureOCR3C
if !ok {
return nil, fmt.Errorf("failed to get contract set for chain %d", cfg.ChainSel)
}
contract := contracts.OCR3
if contract == nil {
return nil, fmt.Errorf("no ocr3 contract found for chain %d", cfg.ChainSel)

contract, err := getOCR3Contract(contracts.OCR3, cfg.Address)
if err != nil {
return nil, fmt.Errorf("failed to get OCR3 contract: %w", err)
}

nodes, err := deployment.NodeInfo(cfg.NodeIDs, env.Offchain)
if err != nil {
return nil, err
Expand Down Expand Up @@ -963,3 +968,30 @@ func configureForwarder(lggr logger.Logger, chain deployment.Chain, contractSet
}
return opMap, nil
}

// getOCR3Contract returns the OCR3 contract from the contract set. By default, it returns the only
// contract in the set if there is no address specified. If an address is specified, it returns the
// contract with that address. If the address is specified but not found in the contract set, it returns
// an error.
func getOCR3Contract(contracts map[string]*ocr3_capability.OCR3Capability, addr *string) (*ocr3_capability.OCR3Capability, error) {
// Fail if the OCR3 contract address is unspecified and there are multiple OCR3 contracts
if addr == nil && len(contracts) > 1 {
return nil, errors.New("OCR contract address is unspecified")
}

// Use the first OCR3 contract if the address is unspecified
if addr == nil && len(contracts) == 1 {
// use the first OCR3 contract
for _, c := range contracts {
return c, nil
}
}

// Select the OCR3 contract by address
if contract, ok := contracts[*addr]; ok {
return contract, nil
}

// Fail if the OCR3 contract address is specified but not found in the contract set
return nil, fmt.Errorf("OCR3 contract address %s not found in contract set", *addr)
}
11 changes: 8 additions & 3 deletions deployment/keystone/changeset/internal/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ type GetContractSetsResponse struct {

type ContractSet struct {
commonchangeset.MCMSWithTimelockState
OCR3 *ocr3_capability.OCR3Capability
OCR3 map[string]*ocr3_capability.OCR3Capability
Forwarder *forwarder.KeystoneForwarder
CapabilitiesRegistry *capabilities_registry.CapabilitiesRegistry
WorkflowRegistry *workflow_registry.WorkflowRegistry
Expand All @@ -37,7 +37,9 @@ type ContractSet struct {
func (cs ContractSet) TransferableContracts() []common.Address {
var out []common.Address
if cs.OCR3 != nil {
out = append(out, cs.OCR3.Address())
for _, ocr := range cs.OCR3 {
out = append(out, ocr.Address())
}
}
if cs.Forwarder != nil {
out = append(out, cs.Forwarder.Address())
Expand Down Expand Up @@ -109,7 +111,10 @@ func loadContractSet(lggr logger.Logger, chain deployment.Chain, addresses map[s
if err != nil {
return nil, fmt.Errorf("failed to create OCR3Capability contract from address %s: %w", addr, err)
}
out.OCR3 = c
if out.OCR3 == nil {
out.OCR3 = make(map[string]*ocr3_capability.OCR3Capability)
}
out.OCR3[addr] = c
case WorkflowRegistry:
c, err := workflow_registry.NewWorkflowRegistry(common.HexToAddress(addr), chain.Client)
if err != nil {
Expand Down

0 comments on commit 0cdba03

Please sign in to comment.