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

Allow to hydrate contract from the capability registry view #15309

Merged
merged 9 commits into from
Nov 25, 2024
82 changes: 82 additions & 0 deletions deployment/common/changeset/capability_registry.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package changeset

import (
"fmt"

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

"github.com/smartcontractkit/chainlink/deployment"
"github.com/smartcontractkit/chainlink/deployment/common/view/v1_0"
"github.com/smartcontractkit/chainlink/deployment/keystone"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry"
)

type HydrateConfig struct {
ChainID uint64
}

// HydrateCapabilityRegistry deploys a new capabilities registry contract and hydrates it with the provided data.
func HydrateCapabilityRegistry(v v1_0.CapabilityRegistryView, env deployment.Environment, cfg HydrateConfig) (*deployment.ContractDeploy[*capabilities_registry.CapabilitiesRegistry], error) {
chainSelector, err := chainsel.SelectorFromChainId(cfg.ChainID)
if err != nil {
return nil, fmt.Errorf("failed to get chain selector from chain id: %w", err)
}
chain, ok := env.Chains[chainSelector]
if !ok {
return nil, fmt.Errorf("chain with id %d not found", cfg.ChainID)
}
deployedContract, err := deployment.DeployContract(
env.Logger, chain, env.ExistingAddresses,
func(chain deployment.Chain) deployment.ContractDeploy[*capabilities_registry.CapabilitiesRegistry] {
crAddr, tx, cr, err2 := capabilities_registry.DeployCapabilitiesRegistry(
chain.DeployerKey,
chain.Client,
)
return deployment.ContractDeploy[*capabilities_registry.CapabilitiesRegistry]{
Address: crAddr, Contract: cr, Tx: tx, Err: err2,
Tv: deployment.NewTypeAndVersion("CapabilitiesRegistry", deployment.Version1_0_0),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these values come from the contract itself

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

nopsParams := v.NopsToNopsParams()
tx, err := deployedContract.Contract.AddNodeOperators(chain.DeployerKey, nopsParams)
if _, err = deployment.ConfirmIfNoError(chain, tx, keystone.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err)); err != nil {
return nil, fmt.Errorf("failed to add node operators: %w", err)
}

capabilitiesParams := v.CapabilitiesToCapabilitiesParams()
tx, err = deployedContract.Contract.AddCapabilities(chain.DeployerKey, capabilitiesParams)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

need to add both nops & capabilities before adding nodes b/c FK constraints in the contract enforce the nop id and hash capabilities values already exist

if _, err = deployment.ConfirmIfNoError(chain, tx, keystone.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err)); err != nil {
return nil, fmt.Errorf("failed to add capabilities: %w", err)
}

nodesParams, err := v.NodesToNodesParams()
if err != nil {
return nil, fmt.Errorf("failed to convert nodes to nodes params: %w", err)
}
tx, err = deployedContract.Contract.AddNodes(chain.DeployerKey, nodesParams)
if _, err = deployment.ConfirmIfNoError(chain, tx, keystone.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err)); err != nil {
return nil, fmt.Errorf("failed to add nodes: %w", err)
}

for _, don := range v.Dons {
cfgs, err := v.CapabilityConfigToCapabilityConfigParams(don)
if err != nil {
return nil, fmt.Errorf("failed to convert capability configurations to capability configuration params: %w", err)
}
var peerIds [][32]byte
for _, id := range don.NodeP2PIds {
peerIds = append(peerIds, id)
}
tx, err = deployedContract.Contract.AddDON(chain.DeployerKey, peerIds, cfgs, don.IsPublic, don.AcceptsWorkflows, don.F)
if _, err = deployment.ConfirmIfNoError(chain, tx, keystone.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err)); err != nil {
return nil, fmt.Errorf("failed to add don: %w", err)
}
}

return deployedContract, nil
}
55 changes: 55 additions & 0 deletions deployment/common/changeset/capability_registry_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package changeset

import (
"encoding/json"
"os"
"testing"

"github.com/stretchr/testify/require"
"go.uber.org/zap/zapcore"

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

"github.com/smartcontractkit/chainlink/deployment/common/view/v1_0"
"github.com/smartcontractkit/chainlink/deployment/environment/memory"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry"
"github.com/smartcontractkit/chainlink/v2/core/logger"
)

func TestHydrateCapabilityRegistry(t *testing.T) {
b, err := os.ReadFile("testdata/capability_registry_view.json")
require.NoError(t, err)
require.NotEmpty(t, b)
var capabilityRegistryView v1_0.CapabilityRegistryView
require.NoError(t, json.Unmarshal(b, &capabilityRegistryView))

chainID := chainsel.TEST_90000001.EvmChainID + 1
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why + 1?
i think there are multiple TEST selectors if you simply want one that is not 90000001

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Used +1 based on how chains are generated here.

cfg := HydrateConfig{ChainID: chainID}
env := memory.NewMemoryEnvironment(t, logger.TestLogger(t), zapcore.InfoLevel, memory.MemoryEnvironmentConfig{
Bootstraps: 1,
Chains: 2,
Nodes: 4,
})
hydrated, err := HydrateCapabilityRegistry(capabilityRegistryView, env, cfg)
require.NoError(t, err)
require.NotNil(t, hydrated)

chainSelector, err := chainsel.SelectorFromChainId(chainID)
require.NoError(t, err)
chain, ok := env.Chains[chainSelector]
require.True(t, ok)
capabilityRegistry, err := capabilities_registry.NewCapabilitiesRegistry(hydrated.Address, chain.Client)
require.NoError(t, err)
require.NotNil(t, capabilityRegistry)
capView, err := v1_0.GenerateCapabilityRegistryView(capabilityRegistry)
require.NoError(t, err)

// Setting address/owner values to be the same in order to compare the views
capView.Address = capabilityRegistryView.Address
capView.Owner = capabilityRegistryView.Owner
b1, err := capabilityRegistryView.MarshalJSON()
require.NoError(t, err)
b2, err := capView.MarshalJSON()
require.NoError(t, err)
require.Equal(t, string(b1), string(b2))
}
Loading
Loading