Skip to content

Commit

Permalink
[chore] Add script to deploy CapabilityRegistry with hardcoded config
Browse files Browse the repository at this point in the history
  • Loading branch information
cedric-cordenier committed Jun 19, 2024
1 parent b7f4dc3 commit 493d72b
Show file tree
Hide file tree
Showing 4 changed files with 388 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .changeset/thick-lemons-beam.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"chainlink": minor
---

#internal Add script to provision capability registry
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/bin/bash

go run main.go \
deploy-and-initialize-capabilities-registry \
--chainid=11155111 \
--ethurl=$ETH_URL \
--accountkey=$ACCOUNT_KEY \
--craddress=$CR_ADDRESS \ // 0x0d36aAC2Fd9d6d1C1F59251be6A2B337af27C52B
1 change: 1 addition & 0 deletions core/scripts/keystone/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ func main() {
src.NewDeployJobSpecsCommand(),
src.NewGenerateCribClusterOverridesCommand(),
src.NewDeleteJobsCommand(),
src.NewDeployAndInitializeCapabilitiesRegistryCommand(),
}

commandsList := func(commands []command) string {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,374 @@
package src

import (
"context"
"encoding/hex"
"flag"
"fmt"
"log"
"os"
"strings"

"github.com/ethereum/go-ethereum/common"
ragetypes "github.com/smartcontractkit/libocr/ragep2p/types"
"google.golang.org/protobuf/proto"

"github.com/ethereum/go-ethereum/accounts/abi/bind"

helpers "github.com/smartcontractkit/chainlink/core/scripts/common"
remotetypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types"
kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry"
)

type peer struct {
PeerID string
Signer string
}

var (
workflowDonPeers = []peer{
{
PeerID: "12D3KooWBCF1XT5Wi8FzfgNCqRL76Swv8TRU3TiD4QiJm8NMNX7N",
Signer: "0x9639dCc7D0ca4468B5f684ef89F12F0B365c9F6d",
},
{
PeerID: "12D3KooWG1AyvwmCpZ93J8pBQUE1SuzrjDXnT4BeouncHR3jWLCG",
Signer: "0x8f0fAE64f5f75067833ed5deDC2804B62b21383d",
},
{
PeerID: "12D3KooWGeUKZBRMbx27FUTgBwZa9Ap9Ym92mywwpuqkEtz8XWyv",
Signer: "0xf09A863D920840c13277e76F43CFBdfB22b8FB7C",
},
{
PeerID: "12D3KooW9zYWQv3STmDeNDidyzxsJSTxoCTLicafgfeEz9nhwhC4",
Signer: "0x7eD90b519bC3054a575C464dBf39946b53Ff90EF",
},
{
PeerID: "12D3KooWG1AeBnSJH2mdcDusXQVye2jqodZ6pftTH98HH6xvrE97",
Signer: "0x8F572978673d711b2F061EB7d514BD46EAD6668A",
},
{
PeerID: "12D3KooWBf3PrkhNoPEmp7iV291YnPuuTsgEDHTscLajxoDvwHGA",
Signer: "0x21eF07Dfaf8f7C10CB0d53D18b641ee690541f9D",
},
{
PeerID: "12D3KooWP3FrMTFXXRU2tBC8aYvEBgUX6qhcH9q2JZCUi9Wvc2GX",
Signer: "0x7Fa21F6f716CFaF8f249564D72Ce727253186C89",
},
}
triggerDonPeers = []peer{
{
PeerID: "12D3KooWBaiTbbRwwt2fbNifiL7Ew9tn3vds9AJE3Nf3eaVBX36m",
Signer: "0x9CcE7293a4Cc2621b61193135A95928735e4795F",
},
{
PeerID: "12D3KooWS7JSY9fzSfWgbCE1S3W2LNY6ZVpRuun74moVBkKj6utE",
Signer: "0x3c775F20bCB2108C1A818741Ce332Bb5fe0dB925",
},
{
PeerID: "12D3KooWMMTDXcWhpVnwrdAer1jnVARTmnr3RyT3v7Djg8ZuoBh9",
Signer: "0x50314239e2CF05555ceeD53E7F47eB2A8Eab0dbB",
},
{
PeerID: "12D3KooWGzVXsKxXsF4zLgxSDM8Gzx1ywq2pZef4PrHMKuVg4K3P",
Signer: "0xd76A4f98898c3b9A72b244476d7337b50D54BCd8",
},
{
PeerID: "12D3KooWSyjmmzjVtCzwN7bXzZQFmWiJRuVcKBerNjVgL7HdLJBW",
Signer: "0x656A873f6895b8a03Fb112dE927d43FA54B2c92A",
},
{
PeerID: "12D3KooWLGz9gzhrNsvyM6XnXS3JRkZoQdEzuAvysovnSChNK5ZK",
Signer: "0x5d1e87d87bF2e0cD4Ea64F381a2dbF45e5f0a553",
},
{
PeerID: "12D3KooWAvZnvknFAfSiUYjATyhzEJLTeKvAzpcLELHi4ogM3GET",
Signer: "0x91d9b0062265514f012Eb8fABA59372fD9520f56",
},
}
targetDonPeers = []peer{
{
PeerID: "12D3KooWJrthXtnPHw7xyHFAxo6NxifYTvc8igKYaA6wRRRqtsMb",
Signer: "0x3F82750353Ea7a051ec9bA011BC628284f9a5327",
},
{
PeerID: "12D3KooWFQekP9sGex4XhqEJav5EScjTpDVtDqJFg1JvrePBCEGJ",
Signer: "0xc23545876A208AA0443B1b8d552c7be4FF4b53F0",
},
{
PeerID: "12D3KooWFLEq4hYtdyKWwe47dXGEbSiHMZhmr5xLSJNhpfiEz8NF",
Signer: "0x82601Fa43d8B1dC1d4eB640451aC86a7CDA37011",
},
{
PeerID: "12D3KooWN2hztiXNNS1jMQTTvvPRYcarK1C7T3Mdqk4x4gwyo5WS",
Signer: "0x1a684B3d8f917fe496b7B1A8b29EDDAED64F649f",
},
}
)

type deployAndInitializeCapabilitiesRegistryCommand struct{}

func NewDeployAndInitializeCapabilitiesRegistryCommand() *deployAndInitializeCapabilitiesRegistryCommand {
return &deployAndInitializeCapabilitiesRegistryCommand{}
}

func (c *deployAndInitializeCapabilitiesRegistryCommand) Name() string {
return "deploy-and-initialize-capabilities-registry"
}

func peerIDToB(peerID string) ([32]byte, error) {
var peerIDB ragetypes.PeerID
err := peerIDB.UnmarshalText([]byte(peerID))
if err != nil {
return [32]byte{}, err
}

return peerIDB, nil
}

func peers(ps []peer) ([][32]byte, error) {
out := [][32]byte{}
for _, p := range ps {
b, err := peerIDToB(p.PeerID)
if err != nil {
return nil, err
}

out = append(out, b)
}

return out, nil
}

func peerToNode(nopID uint32, p peer) (kcr.CapabilitiesRegistryNodeParams, error) {
peerIDB, err := peerIDToB(p.PeerID)
if err != nil {
return kcr.CapabilitiesRegistryNodeParams{}, fmt.Errorf("failed to convert peerID: %w", err)
}

sig := strings.TrimPrefix(p.Signer, "0x")
signerB, err := hex.DecodeString(sig)
if err != nil {
return kcr.CapabilitiesRegistryNodeParams{}, fmt.Errorf("failed to convert signer: %w", err)
}

var sigb [32]byte
copy(sigb[:], signerB)

return kcr.CapabilitiesRegistryNodeParams{
NodeOperatorId: nopID,
P2pId: peerIDB,
Signer: sigb,
}, nil
}

// Run expects the following environment variables to be set:
//
// 1. Deploys the CapabilitiesRegistry contract
// 2. Configures it with a hardcode DON setup, as used by our staging environment.
func (c *deployAndInitializeCapabilitiesRegistryCommand) Run(args []string) {
ctx := context.Background()

fs := flag.NewFlagSet(c.Name(), flag.ExitOnError)
// create flags for all of the env vars then set the env vars to normalize the interface
// this is a bit of a hack but it's the easiest way to make this work
ethUrl := fs.String("ethurl", "", "URL of the Ethereum node")
chainID := fs.Int64("chainid", 11155111, "chain ID of the Ethereum network to deploy to")
accountKey := fs.String("accountkey", "", "private key of the account to deploy from")
capabilityRegistryAddress := fs.String("craddress", "", "address of the capability registry")

err := fs.Parse(args)
if err != nil ||
*ethUrl == "" || ethUrl == nil ||
*chainID == 0 || chainID == nil ||
*accountKey == "" || accountKey == nil {
fs.Usage()
os.Exit(1)
}

os.Setenv("ETH_URL", *ethUrl)
os.Setenv("ETH_CHAIN_ID", fmt.Sprintf("%d", *chainID))
os.Setenv("ACCOUNT_KEY", *accountKey)

env := helpers.SetupEnv(false)

var reg *kcr.CapabilitiesRegistry
if *capabilityRegistryAddress == "" {
reg = deployCapabilitiesRegistry(env)
} else {
addr := common.HexToAddress(*capabilityRegistryAddress)
r, innerErr := kcr.NewCapabilitiesRegistry(addr, env.Ec)
if err != nil {
panic(innerErr)
}

reg = r
}

streamsTrigger := kcr.CapabilitiesRegistryCapability{
LabelledName: "streams-trigger",
Version: "1.0.0",
CapabilityType: uint8(0), // trigger
}
sid, err := reg.GetHashedCapabilityId(&bind.CallOpts{}, streamsTrigger.LabelledName, streamsTrigger.Version)
if err != nil {
panic(err)
}

writeChain := kcr.CapabilitiesRegistryCapability{
LabelledName: "write_ethereum-testnet-sepolia",
Version: "1.0.0",
CapabilityType: uint8(3), // target
}
wid, err := reg.GetHashedCapabilityId(&bind.CallOpts{}, writeChain.LabelledName, writeChain.Version)
if err != nil {
log.Printf("failed to call GetHashedCapabilityId: %s", err)
}

ocr := kcr.CapabilitiesRegistryCapability{
LabelledName: "offchain_reporting",
Version: "1.0.0",
CapabilityType: uint8(2), // consensus
}
ocrid, err := reg.GetHashedCapabilityId(&bind.CallOpts{}, ocr.LabelledName, ocr.Version)
if err != nil {
log.Printf("failed to call GetHashedCapabilityId: %s", err)
}

tx, err := reg.AddCapabilities(env.Owner, []kcr.CapabilitiesRegistryCapability{
streamsTrigger,
writeChain,
ocr,
})
if err != nil {
log.Printf("failed to call AddCapabilities: %s", err)
}

helpers.ConfirmTXMined(ctx, env.Ec, tx, env.ChainID)

tx, err = reg.AddNodeOperators(env.Owner, []kcr.CapabilitiesRegistryNodeOperator{
{
Admin: env.Owner.From,
Name: "STAGING_NODE_OPERATOR",
},
})
if err != nil {
log.Printf("failed to AddNodeOperators: %s", err)
}

receipt := helpers.ConfirmTXMined(ctx, env.Ec, tx, env.ChainID)

recLog, err := reg.ParseNodeOperatorAdded(*receipt.Logs[0])
if err != nil {
panic(err)
}

nopID := recLog.NodeOperatorId
nodes := []kcr.CapabilitiesRegistryNodeParams{}
for _, wfPeer := range workflowDonPeers {
n, innerErr := peerToNode(nopID, wfPeer)
if innerErr != nil {
panic(innerErr)
}

n.HashedCapabilityIds = [][32]byte{ocrid}
nodes = append(nodes, n)
}

for _, triggerPeer := range triggerDonPeers {
n, innerErr := peerToNode(nopID, triggerPeer)
if innerErr != nil {
panic(innerErr)
}

n.HashedCapabilityIds = [][32]byte{sid}
nodes = append(nodes, n)
}

for _, targetPeer := range targetDonPeers {
n, innerErr := peerToNode(nopID, targetPeer)
if innerErr != nil {
panic(innerErr)
}

n.HashedCapabilityIds = [][32]byte{wid}
nodes = append(nodes, n)
}

tx, err = reg.AddNodes(env.Owner, nodes)
if err != nil {
log.Printf("failed to AddNodes: %s", err)
}

helpers.ConfirmTXMined(ctx, env.Ec, tx, env.ChainID)

// workflow DON
ps, err := peers(workflowDonPeers)
if err != nil {
panic(err)
}

cfgs := []kcr.CapabilitiesRegistryCapabilityConfiguration{
{
CapabilityId: ocrid,
},
}
_, err = reg.AddDON(env.Owner, ps, cfgs, false, true, 2)
if err != nil {
log.Printf("workflowDON: failed to AddDON: %s", err)
}

// trigger DON
ps, err = peers(triggerDonPeers)
if err != nil {
panic(err)
}

config := &remotetypes.RemoteTriggerConfig{
RegistrationRefreshMs: 20000,
RegistrationExpiryMs: 60000,
// F + 1
MinResponsesToAggregate: uint32(1) + 1,
}
configb, err := proto.Marshal(config)
if err != nil {
panic(err)
}
cfgs = []kcr.CapabilitiesRegistryCapabilityConfiguration{
{
CapabilityId: sid,
Config: configb,
},
}
_, err = reg.AddDON(env.Owner, ps, cfgs, true, false, 1)
if err != nil {
log.Printf("triggerDON: failed to AddDON: %s", err)
}

// target DON
ps, err = peers(targetDonPeers)
if err != nil {
panic(err)
}

cfgs = []kcr.CapabilitiesRegistryCapabilityConfiguration{
{
CapabilityId: wid,
},
}
_, err = reg.AddDON(env.Owner, ps, cfgs, true, false, 1)
if err != nil {
log.Printf("targetDON: failed to AddDON: %s", err)
}
}

func deployCapabilitiesRegistry(env helpers.Environment) *kcr.CapabilitiesRegistry {
_, tx, contract, err := kcr.DeployCapabilitiesRegistry(env.Owner, env.Ec)
if err != nil {
panic(err)
}

addr := helpers.ConfirmContractDeployed(context.Background(), env.Ec, tx, env.ChainID)
fmt.Printf("CapabilitiesRegistry address: %s", addr)
return contract
}

0 comments on commit 493d72b

Please sign in to comment.