-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[CAPPL-303] Add commands to deploy the workflow registry
- Loading branch information
1 parent
b76f9b3
commit 4606111
Showing
12 changed files
with
602 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
38
deployment/keystone/changeset/workflowregistry/deploy_test.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
} |
86 changes: 86 additions & 0 deletions
86
deployment/keystone/changeset/workflowregistry/strategies.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
package workflowregistry | ||
|
||
import ( | ||
"math/big" | ||
|
||
"github.com/ethereum/go-ethereum/accounts/abi/bind" | ||
"github.com/ethereum/go-ethereum/common" | ||
"github.com/ethereum/go-ethereum/core/types" | ||
|
||
"github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" | ||
"github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" | ||
"github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" | ||
|
||
"github.com/smartcontractkit/chainlink/deployment" | ||
"github.com/smartcontractkit/chainlink/deployment/common/proposalutils" | ||
kslib "github.com/smartcontractkit/chainlink/deployment/keystone" | ||
"github.com/smartcontractkit/chainlink/deployment/keystone/changeset" | ||
) | ||
|
||
type strategy interface { | ||
Apply(callFn func(opts *bind.TransactOpts) (*types.Transaction, error)) (deployment.ChangesetOutput, error) | ||
} | ||
|
||
type simpleTransaction struct { | ||
chain deployment.Chain | ||
} | ||
|
||
func (s *simpleTransaction) Apply(callFn func(opts *bind.TransactOpts) (*types.Transaction, error)) (deployment.ChangesetOutput, error) { | ||
tx, err := callFn(s.chain.DeployerKey) | ||
if err != nil { | ||
return deployment.ChangesetOutput{}, err | ||
} | ||
|
||
_, err = s.chain.Confirm(tx) | ||
return deployment.ChangesetOutput{}, err | ||
} | ||
|
||
type mcmsTransaction struct { | ||
Config *changeset.MCMSConfig | ||
Description string | ||
Address common.Address | ||
ChainSel uint64 | ||
ContractSet *kslib.ContractSet | ||
} | ||
|
||
func (m *mcmsTransaction) Apply(callFn func(opts *bind.TransactOpts) (*types.Transaction, error)) (deployment.ChangesetOutput, error) { | ||
opts := deployment.SimTransactOpts() | ||
|
||
tx, err := callFn(opts) | ||
if err != nil { | ||
return deployment.ChangesetOutput{}, err | ||
} | ||
|
||
op := timelock.BatchChainOperation{ | ||
ChainIdentifier: mcms.ChainIdentifier(m.ChainSel), | ||
Batch: []mcms.Operation{ | ||
{ | ||
Data: tx.Data(), | ||
To: m.Address, | ||
Value: big.NewInt(0), | ||
}, | ||
}, | ||
} | ||
|
||
timelocksPerChain := map[uint64]common.Address{ | ||
m.ChainSel: m.ContractSet.Timelock.Address(), | ||
} | ||
proposerMCMSes := map[uint64]*gethwrappers.ManyChainMultiSig{ | ||
m.ChainSel: m.ContractSet.ProposerMcm, | ||
} | ||
|
||
proposal, err := proposalutils.BuildProposalFromBatches( | ||
timelocksPerChain, | ||
proposerMCMSes, | ||
[]timelock.BatchChainOperation{op}, | ||
m.Description, | ||
m.Config.MinDuration, | ||
) | ||
if err != nil { | ||
return deployment.ChangesetOutput{}, err | ||
} | ||
|
||
return deployment.ChangesetOutput{ | ||
Proposals: []timelock.MCMSWithTimelockProposal{*proposal}, | ||
}, nil | ||
} |
81 changes: 81 additions & 0 deletions
81
deployment/keystone/changeset/workflowregistry/update_allowed_dons.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
package workflowregistry | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
|
||
"github.com/ethereum/go-ethereum/accounts/abi/bind" | ||
"github.com/ethereum/go-ethereum/core/types" | ||
|
||
"github.com/smartcontractkit/chainlink/deployment" | ||
|
||
kslib "github.com/smartcontractkit/chainlink/deployment/keystone" | ||
"github.com/smartcontractkit/chainlink/deployment/keystone/changeset" | ||
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 | ||
|
||
MCMSConfig *changeset.MCMSConfig | ||
} | ||
|
||
func (r *UpdateAllowedDonsRequest) Validate() error { | ||
if len(r.DonIDs) == 0 { | ||
return errors.New("Must provide at least one DonID") | ||
} | ||
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 | ||
} | ||
|
||
resp, err := kslib.GetContractSets(env.Logger, &kslib.GetContractSetsRequest{ | ||
Chains: env.Chains, | ||
AddressBook: env.ExistingAddresses, | ||
}) | ||
if err != nil { | ||
return deployment.ChangesetOutput{}, fmt.Errorf("failed to get contract sets: %w", err) | ||
} | ||
|
||
cs := resp.ContractSets[req.RegistryChainSel] | ||
if cs.WorkflowRegistry == nil { | ||
return deployment.ChangesetOutput{}, errors.New("could not find workflow registry") | ||
} | ||
registry := cs.WorkflowRegistry | ||
|
||
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 s strategy | ||
if req.MCMSConfig != nil { | ||
s = &mcmsTransaction{ | ||
Config: req.MCMSConfig, | ||
Description: "proposal to update allowed dons", | ||
Address: registry.Address(), | ||
ChainSel: chain.Selector, | ||
ContractSet: &cs, | ||
} | ||
} else { | ||
s = &simpleTransaction{ | ||
chain: chain, | ||
} | ||
} | ||
|
||
return s.Apply(func(opts *bind.TransactOpts) (*types.Transaction, error) { | ||
tx, err := registry.UpdateAllowedDONs(chain.DeployerKey, req.DonIDs, req.Allowed) | ||
if err != nil { | ||
err = kslib.DecodeErr(workflow_registry.WorkflowRegistryABI, err) | ||
} | ||
return tx, err | ||
}) | ||
} |
69 changes: 69 additions & 0 deletions
69
deployment/keystone/changeset/workflowregistry/update_allowed_dons_test.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
} |
Oops, something went wrong.