Skip to content

Commit

Permalink
[CAPPL-303] Add commands to deploy the workflow registry
Browse files Browse the repository at this point in the history
  • Loading branch information
cedric-cordenier committed Dec 17, 2024
1 parent b76f9b3 commit 2b82ead
Show file tree
Hide file tree
Showing 11 changed files with 462 additions and 0 deletions.
33 changes: 33 additions & 0 deletions deployment/keystone/changeset/internal/test/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,47 @@ import (
"github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry"
kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry"
workflow_registry "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/workflow/generated/workflow_registry_wrapper"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey"
)

type SetupTestWorkflowRegistryResponse struct {
Registry *workflow_registry.WorkflowRegistry
Chain deployment.Chain
RegistrySelector uint64
AddressBook deployment.AddressBook
}

func SetupTestWorkflowRegistry(t *testing.T, lggr logger.Logger, chainSel uint64) *SetupTestWorkflowRegistryResponse {
chain := testChain(t)

deployer, err := kslib.NewWorkflowRegistryDeployer()
require.NoError(t, err)
resp, err := deployer.Deploy(kslib.DeployRequest{Chain: chain})
require.NoError(t, err)

addressBook := deployment.NewMemoryAddressBookFromMap(
map[uint64]map[string]deployment.TypeAndVersion{
chainSel: map[string]deployment.TypeAndVersion{
resp.Address.Hex(): resp.Tv,
},
},
)

return &SetupTestWorkflowRegistryResponse{
Registry: deployer.Contract(),
Chain: chain,
RegistrySelector: chain.Selector,
AddressBook: addressBook,
}
}

type Don struct {
Name string
P2PIDs []p2pkey.PeerID
CapabilityConfigs []internal.CapabilityConfig
}

type SetupTestRegistryRequest struct {
P2pToCapabilities map[p2pkey.PeerID][]kcr.CapabilitiesRegistryCapability
NopToNodes map[kcr.CapabilitiesRegistryNodeOperator][]*internal.P2PSignerEnc
Expand Down
26 changes: 26 additions & 0 deletions deployment/keystone/changeset/workflowregistry/deploy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package workflowregistry

import (
"fmt"

"github.com/smartcontractkit/chainlink/deployment"
kslib "github.com/smartcontractkit/chainlink/deployment/keystone"
)

var _ deployment.ChangeSet[uint64] = Deploy

func Deploy(env deployment.Environment, registrySelector uint64) (deployment.ChangesetOutput, error) {
lggr := env.Logger
chain, ok := env.Chains[registrySelector]
if !ok {
return deployment.ChangesetOutput{}, fmt.Errorf("chain not found in environment")
}
ab := deployment.NewMemoryAddressBook()
wrResp, err := kslib.DeployWorkflowRegistry(chain, ab)
if err != nil {
return deployment.ChangesetOutput{}, fmt.Errorf("failed to deploy CapabilitiesRegistry: %w", err)
}
lggr.Infof("Deployed %s chain selector %d addr %s", wrResp.Tv.String(), chain.Selector, wrResp.Address.String())

return deployment.ChangesetOutput{AddressBook: ab}, nil
}
38 changes: 38 additions & 0 deletions deployment/keystone/changeset/workflowregistry/deploy_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package workflowregistry

import (
"testing"

"go.uber.org/zap/zapcore"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/smartcontractkit/chainlink-common/pkg/logger"
"github.com/smartcontractkit/chainlink/deployment/environment/memory"
)

func Test_Deploy(t *testing.T) {
t.Parallel()
lggr := logger.Test(t)
cfg := memory.MemoryEnvironmentConfig{
Nodes: 1, // nodes unused but required in config
Chains: 2,
}
env := memory.NewMemoryEnvironment(t, lggr, zapcore.DebugLevel, cfg)

registrySel := env.AllChainSelectors()[0]

resp, err := Deploy(env, registrySel)
require.NoError(t, err)
require.NotNil(t, resp)
// OCR3 should be deployed on chain 0
addrs, err := resp.AddressBook.AddressesForChain(registrySel)
require.NoError(t, err)
require.Len(t, addrs, 1)

// nothing on chain 1
require.NotEqual(t, registrySel, env.AllChainSelectors()[1])
oaddrs, _ := resp.AddressBook.AddressesForChain(env.AllChainSelectors()[1])
assert.Len(t, oaddrs, 0)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package workflowregistry

import (
"fmt"

"github.com/smartcontractkit/chainlink/deployment"

kslib "github.com/smartcontractkit/chainlink/deployment/keystone"
workflow_registry "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/workflow/generated/workflow_registry_wrapper"
)

var _ deployment.ChangeSet[*UpdateAllowedDonsRequest] = UpdateAllowedDons

type UpdateAllowedDonsRequest struct {
RegistryChainSel uint64
DonIDs []uint32
Allowed bool
}

func (r *UpdateAllowedDonsRequest) Validate() error {
return nil
}

// UpdateAllowedDons updates the list of DONs that workflows can be sent to.
func UpdateAllowedDons(env deployment.Environment, req *UpdateAllowedDonsRequest) (deployment.ChangesetOutput, error) {
if err := req.Validate(); err != nil {
return deployment.ChangesetOutput{}, err
}

registry, err := getWorkflowRegistry(env, req.RegistryChainSel)
if err != nil {
return deployment.ChangesetOutput{}, err
}

chain, ok := env.Chains[req.RegistryChainSel]
if !ok {
return deployment.ChangesetOutput{}, fmt.Errorf("registry chain selector %d does not exist in environment", req.RegistryChainSel)
}

tx, err := registry.UpdateAllowedDONs(chain.DeployerKey, req.DonIDs, req.Allowed)
if err != nil {
err = kslib.DecodeErr(workflow_registry.WorkflowRegistryABI, err)
return deployment.ChangesetOutput{}, fmt.Errorf("failed to call UpdateAllowedDons: %w", err)
}

_, err = chain.Confirm(tx)
if err != nil {
return deployment.ChangesetOutput{}, fmt.Errorf("failed to confirm UpdateAllowedDons")
}
return deployment.ChangesetOutput{}, nil
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package workflowregistry_test

import (
"testing"

"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/smartcontractkit/chainlink-common/pkg/logger"

chain_selectors "github.com/smartcontractkit/chain-selectors"

"github.com/smartcontractkit/chainlink/deployment"
kstest "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal/test"
"github.com/smartcontractkit/chainlink/deployment/keystone/changeset/workflowregistry"
)

func TestUpdateAllowedDons(t *testing.T) {
lggr := logger.Test(t)

chainSel := chain_selectors.ETHEREUM_TESTNET_SEPOLIA.Selector
resp := kstest.SetupTestWorkflowRegistry(t, lggr, chainSel)
registry := resp.Registry

dons, err := registry.GetAllAllowedDONs(&bind.CallOpts{})
require.NoError(t, err)

assert.Len(t, dons, 0)

env := deployment.Environment{
Logger: lggr,
Chains: map[uint64]deployment.Chain{
chainSel: resp.Chain,
},
ExistingAddresses: resp.AddressBook,
}

_, err = workflowregistry.UpdateAllowedDons(
env,
&workflowregistry.UpdateAllowedDonsRequest{
RegistryChainSel: chainSel,
DonIDs: []uint32{1},
Allowed: true,
},
)
require.NoError(t, err)

dons, err = registry.GetAllAllowedDONs(&bind.CallOpts{})
require.NoError(t, err)

assert.Len(t, dons, 1)
assert.Equal(t, dons[0], uint32(1))

_, err = workflowregistry.UpdateAllowedDons(
env,
&workflowregistry.UpdateAllowedDonsRequest{
RegistryChainSel: chainSel,
DonIDs: []uint32{1},
Allowed: false,
},
)
require.NoError(t, err)

dons, err = registry.GetAllAllowedDONs(&bind.CallOpts{})
require.NoError(t, err)

assert.Len(t, dons, 0)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package workflowregistry

import (
"errors"
"fmt"

"github.com/ethereum/go-ethereum/common"

"github.com/smartcontractkit/chainlink/deployment"

kslib "github.com/smartcontractkit/chainlink/deployment/keystone"
workflow_registry "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/workflow/generated/workflow_registry_wrapper"
)

var _ deployment.ChangeSet[*UpdateAuthorizedAddressesRequest] = UpdateAuthorizedAddresses

type UpdateAuthorizedAddressesRequest struct {
RegistryChainSel uint64

Addresses []string
Allowed bool
}

func (r *UpdateAuthorizedAddressesRequest) Validate() error {
if len(r.Addresses) == 0 {
return errors.New("Must provide at least 1 address")
}

return nil
}

func getWorkflowRegistry(env deployment.Environment, chainSel uint64) (*workflow_registry.WorkflowRegistry, error) {
resp, err := kslib.GetContractSets(env.Logger, &kslib.GetContractSetsRequest{
Chains: env.Chains,
AddressBook: env.ExistingAddresses,
})
if err != nil {
return nil, fmt.Errorf("failed to get contract sets: %w", err)
}

cs := resp.ContractSets[chainSel]
if cs.WorkflowRegistry == nil {
return nil, errors.New("could not find workflow registry")
}

return cs.WorkflowRegistry, nil
}

// UpdateAuthorizedAddresses updates the list of DONs that workflows can be sent to.
func UpdateAuthorizedAddresses(env deployment.Environment, req *UpdateAuthorizedAddressesRequest) (deployment.ChangesetOutput, error) {
if err := req.Validate(); err != nil {
return deployment.ChangesetOutput{}, err
}

registry, err := getWorkflowRegistry(env, req.RegistryChainSel)
if err != nil {
return deployment.ChangesetOutput{}, err
}

chain, ok := env.Chains[req.RegistryChainSel]
if !ok {
return deployment.ChangesetOutput{}, fmt.Errorf("registry chain selector %d does not exist in environment", req.RegistryChainSel)
}

var addr []common.Address
for _, a := range req.Addresses {
addr = append(addr, common.HexToAddress(a))
}

tx, err := registry.UpdateAuthorizedAddresses(chain.DeployerKey, addr, req.Allowed)
if err != nil {
err = kslib.DecodeErr(workflow_registry.WorkflowRegistryABI, err)
return deployment.ChangesetOutput{}, fmt.Errorf("failed to call UpdateAuthorizedAddresses: %w", err)
}

_, err = chain.Confirm(tx)
if err != nil {
return deployment.ChangesetOutput{}, fmt.Errorf("failed to confirm UpdateAuthorizedAddresses")
}

return deployment.ChangesetOutput{}, nil
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package workflowregistry_test

import (
"testing"

"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

chain_selectors "github.com/smartcontractkit/chain-selectors"

"github.com/smartcontractkit/chainlink-common/pkg/logger"

"github.com/smartcontractkit/chainlink/deployment"
kstest "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal/test"
"github.com/smartcontractkit/chainlink/deployment/keystone/changeset/workflowregistry"
)

func TestUpdateAuthorizedAddresses(t *testing.T) {
lggr := logger.Test(t)

chainSel := chain_selectors.ETHEREUM_TESTNET_SEPOLIA.Selector
resp := kstest.SetupTestWorkflowRegistry(t, lggr, chainSel)
registry := resp.Registry

dons, err := registry.GetAllAuthorizedAddresses(&bind.CallOpts{})
require.NoError(t, err)

assert.Len(t, dons, 0)

env := deployment.Environment{
Logger: lggr,
Chains: map[uint64]deployment.Chain{
chainSel: resp.Chain,
},
ExistingAddresses: resp.AddressBook,
}

addr := "0xc0ffee254729296a45a3885639AC7E10F9d54979"
_, err = workflowregistry.UpdateAuthorizedAddresses(
env,
&workflowregistry.UpdateAuthorizedAddressesRequest{
RegistryChainSel: chainSel,
Addresses: []string{addr},
Allowed: true,
},
)
require.NoError(t, err)

dons, err = registry.GetAllAuthorizedAddresses(&bind.CallOpts{})
require.NoError(t, err)

assert.Len(t, dons, 1)
assert.Equal(t, dons[0], common.HexToAddress(addr))

_, err = workflowregistry.UpdateAuthorizedAddresses(
env,
&workflowregistry.UpdateAuthorizedAddressesRequest{
RegistryChainSel: chainSel,
Addresses: []string{addr},
Allowed: false,
},
)
require.NoError(t, err)

dons, err = registry.GetAllAuthorizedAddresses(&bind.CallOpts{})
require.NoError(t, err)

assert.Len(t, dons, 0)
}
Loading

0 comments on commit 2b82ead

Please sign in to comment.