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
161 changes: 160 additions & 1 deletion deployment/common/view/v1_0/capreg.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@ import (

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

"github.com/smartcontractkit/chainlink/deployment"
"github.com/smartcontractkit/chainlink/deployment/common/view/types"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey"
)

Expand Down Expand Up @@ -140,6 +142,163 @@ func (v CapabilityRegistryView) DonDenormalizedView() ([]DonDenormalizedView, er
return out, nil
}

type HydrateConfig struct {
lggr logger.Logger
ChainID uint64
}

func (v CapabilityRegistryView) Hydrate(env deployment.Environment, cfg HydrateConfig) (*deployment.ContractDeploy[*capabilities_registry.CapabilitiesRegistry], error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

the views packages should all be readonly. Anything that writes onchain should be in a changeset. You can add a common/changeset if you want though, after #15288 there will already be a directory for that you can use

chain, ok := env.Chains[cfg.ChainID]
if !ok {
return nil, fmt.Errorf("chain with id %d not found", cfg.ChainID)
}
deployedContract, err := deployment.DeployContract(
cfg.lggr, 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),
}
},
)
if err != nil {
return nil, fmt.Errorf("failed to deploy contract: %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, err); err != nil {
return nil, fmt.Errorf("failed to add nodes: %w", err)
}

capabilitiesParams := v.capabilitiesToCapabilitiesParams()
tx, err = deployedContract.Contract.AddCapabilities(chain.DeployerKey, capabilitiesParams)
if _, err = deployment.ConfirmIfNoError(chain, tx, err); err != nil {
return nil, fmt.Errorf("failed to add capabilities: %w", err)
}

nopsParams := v.nopsToNopsParams()
for _, nop := range v.Nops {
nopsParams = append(nopsParams, capabilities_registry.CapabilitiesRegistryNodeOperator{
Admin: nop.Admin,
Name: nop.Name,
})
}
tx, err = deployedContract.Contract.AddNodeOperators(chain.DeployerKey, nopsParams)
if _, err = deployment.ConfirmIfNoError(chain, tx, err); err != nil {
return nil, fmt.Errorf("failed to add node operators: %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, err); err != nil {
return nil, fmt.Errorf("failed to add don: %w", err)
}
}

return deployedContract, nil
}

func (v CapabilityRegistryView) nodesToNodesParams() ([]capabilities_registry.CapabilitiesRegistryNodeParams, error) {
var nodesParams []capabilities_registry.CapabilitiesRegistryNodeParams
for _, node := range v.Nodes {
signer, err := hexTo32Bytes(node.Signer)
if err != nil {
return nil, err
}
encryptionPubKey, err := hexTo32Bytes(node.EncryptionPublicKey)
if err != nil {
return nil, err
}
capIDs := make([][32]byte, len(node.CapabilityIDs))
for i, id := range node.CapabilityIDs {
cid, err := hexTo32Bytes(id)
if err != nil {
return nil, err
}
capIDs[i] = cid
}
nodesParams = append(nodesParams, capabilities_registry.CapabilitiesRegistryNodeParams{
Signer: signer,
P2pId: node.P2pId,
EncryptionPublicKey: encryptionPubKey,
NodeOperatorId: node.NodeOperatorID,
HashedCapabilityIds: capIDs,
})
}

return nodesParams, nil
}

func (v CapabilityRegistryView) capabilitiesToCapabilitiesParams() []capabilities_registry.CapabilitiesRegistryCapability {
var capabilitiesParams []capabilities_registry.CapabilitiesRegistryCapability
for _, capability := range v.Capabilities {
capabilitiesParams = append(capabilitiesParams, capabilities_registry.CapabilitiesRegistryCapability{
LabelledName: capability.LabelledName,
Version: capability.Version,
CapabilityType: capability.CapabilityType,
ResponseType: capability.ResponseType,
ConfigurationContract: capability.ConfigurationContract,
})
}
return capabilitiesParams
}

func (v CapabilityRegistryView) nopsToNopsParams() []capabilities_registry.CapabilitiesRegistryNodeOperator {
var nopsParams []capabilities_registry.CapabilitiesRegistryNodeOperator
for _, nop := range v.Nops {
nopsParams = append(nopsParams, capabilities_registry.CapabilitiesRegistryNodeOperator{
Admin: nop.Admin,
Name: nop.Name,
})
}
return nopsParams
}

func (v CapabilityRegistryView) capabilityConfigToCapabilityConfigParams(don DonView) ([]capabilities_registry.CapabilitiesRegistryCapabilityConfiguration, error) {
var cfgs []capabilities_registry.CapabilitiesRegistryCapabilityConfiguration
for _, cfg := range don.CapabilityConfigurations {
cid, err := hexTo32Bytes(cfg.ID)
if err != nil {
return nil, err
}
config, err := hex.DecodeString(cfg.Config)
if err != nil {
return nil, err
}
cfgs = append(cfgs, capabilities_registry.CapabilitiesRegistryCapabilityConfiguration{
CapabilityId: cid,
Config: config,
})
}
return cfgs, nil
}

func hexTo32Bytes(val string) ([32]byte, error) {
var out [32]byte
b, err := hex.DecodeString(val)
if err != nil {
return out, err
}
copy(out[:], b)
return out, nil
}

// CapabilityView is a serialization-friendly view of a capability in the capabilities registry.
type CapabilityView struct {
ID string `json:"id"` // hex 32 bytes
Expand Down Expand Up @@ -272,7 +431,7 @@ func NewNodeView(n capabilities_registry.INodeInfoProviderNodeInfo) NodeView {
ConfigCount: n.ConfigCount,
WorkflowDONID: n.WorkflowDONId,
Signer: hex.EncodeToString(n.Signer[:]),
P2pId: p2pkey.PeerID(n.P2pId),
P2pId: n.P2pId,
EncryptionPublicKey: hex.EncodeToString(n.EncryptionPublicKey[:]),
},
NodeOperatorID: n.NodeOperatorId,
Expand Down
Loading