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

Deterministic ordering when Add'ing to capability contract #15738

Closed
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 33 additions & 8 deletions deployment/keystone/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (

"github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms"
"github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock"

"github.com/smartcontractkit/chainlink/deployment"

"google.golang.org/protobuf/proto"
Expand Down Expand Up @@ -536,6 +537,11 @@ func RegisterNOPS(ctx context.Context, lggr logger.Logger, req RegisterNOPSReque
})
}
}
// order nops by name + admin address
sort.SliceStable(nops, func(i, j int) bool {
return strings.Compare(nops[i].Name, nops[j].Name) < 0 || nops[i].Admin.Cmp(nops[j].Admin) < 0
})

if len(nops) == 0 {
lggr.Debug("no new node operators to register")
return resp, nil
Expand Down Expand Up @@ -743,6 +749,9 @@ func RegisterNodes(lggr logger.Logger, req *RegisterNodesRequest) (*RegisterNode
for _, v := range nodeIDToParams {
uniqueNodeParams = append(uniqueNodeParams, v)
}
sort.SliceStable(uniqueNodeParams, func(i, j int) bool {
return bytes.Compare(uniqueNodeParams[i].P2pId[:], uniqueNodeParams[j].P2pId[:]) < 0
})
lggr.Debugw("unique node params to add", "count", len(uniqueNodeParams), "params", uniqueNodeParams)
tx, err := registry.AddNodes(registryChain.DeployerKey, uniqueNodeParams)
if err != nil {
Expand Down Expand Up @@ -801,6 +810,12 @@ type RegisterDonsResponse struct {
DonInfos map[string]kcr.CapabilitiesRegistryDONInfo
}

type p2pSortedDONToRegister struct {
DONToRegister
p2pIds [][32]byte
p2pSortedHash string
}

func sortedHash(p2pids [][32]byte) string {
sha256Hash := sha256.New()
sort.Slice(p2pids, func(i, j int) bool {
Expand Down Expand Up @@ -834,6 +849,7 @@ func RegisterDons(lggr logger.Logger, req RegisterDonsRequest) (*RegisterDonsRes
}
lggr.Infow("fetched existing DONs...", "len", len(donInfos), "lenByNodesHash", len(existingDONs))

p2pSortedDONsToRegister := make([]p2pSortedDONToRegister, 0)
for _, don := range req.DonsToRegister {
var p2pIds [][32]byte
for _, n := range don.Nodes {
Expand All @@ -847,11 +863,20 @@ func RegisterDons(lggr logger.Logger, req RegisterDonsRequest) (*RegisterDonsRes
p2pIds = append(p2pIds, p2pID)
}

p2pSortedHash := sortedHash(p2pIds)
p2pIdsToDon[p2pSortedHash] = don.Name
p2pSortedDONsToRegister = append(p2pSortedDONsToRegister, p2pSortedDONToRegister{
don, p2pIds, sortedHash(p2pIds),
})
}
// sort by p2p sorted hash to ensure deterministic order
sort.SliceStable(p2pSortedDONsToRegister, func(i, j int) bool {
return p2pSortedDONsToRegister[i].p2pSortedHash < p2pSortedDONsToRegister[j].p2pSortedHash
})

for _, don := range p2pSortedDONsToRegister {
p2pIdsToDon[don.p2pSortedHash] = don.Name

if _, ok := existingDONs[p2pSortedHash]; ok {
lggr.Debugw("don already exists, ignoring", "don", don, "p2p sorted hash", p2pSortedHash)
if _, ok := existingDONs[don.p2pSortedHash]; ok {
lggr.Debugw("don already exists, ignoring", "don", don, "p2p sorted hash", don.p2pSortedHash)
continue
}

Expand All @@ -866,7 +891,7 @@ func RegisterDons(lggr logger.Logger, req RegisterDonsRequest) (*RegisterDonsRes
wfSupported = true
}
// TODO: accept configuration from external source for each (don,capability)
capCfg := DefaultCapConfig(cap.CapabilityType, len(p2pIds))
capCfg := DefaultCapConfig(cap.CapabilityType, len(don.p2pIds))
cfgb, err := proto.Marshal(capCfg)
if err != nil {
return nil, fmt.Errorf("failed to marshal capability config for %v: %w", cap, err)
Expand All @@ -877,16 +902,16 @@ func RegisterDons(lggr logger.Logger, req RegisterDonsRequest) (*RegisterDonsRes
})
}

tx, err := registry.AddDON(registryChain.DeployerKey, p2pIds, cfgs, true, wfSupported, don.F)
tx, err := registry.AddDON(registryChain.DeployerKey, don.p2pIds, cfgs, true, wfSupported, don.F)
if err != nil {
err = DecodeErr(kcr.CapabilitiesRegistryABI, err)
return nil, fmt.Errorf("failed to call AddDON for don '%s' p2p2Id hash %s capability %v: %w", don.Name, p2pSortedHash, cfgs, err)
return nil, fmt.Errorf("failed to call AddDON for don '%s' p2p2Id hash %s capability %v: %w", don.Name, don.p2pSortedHash, cfgs, err)
}
_, err = registryChain.Confirm(tx)
if err != nil {
return nil, fmt.Errorf("failed to confirm AddDON transaction %s for don %s: %w", tx.Hash().String(), don.Name, err)
}
lggr.Debugw("registered DON", "don", don.Name, "p2p sorted hash", p2pSortedHash, "cgs", cfgs, "wfSupported", wfSupported, "f", don.F)
lggr.Debugw("registered DON", "don", don.Name, "p2p sorted hash", don.p2pSortedHash, "cgs", cfgs, "wfSupported", wfSupported, "f", don.F)
addedDons++
}
lggr.Debugf("Registered all DONs (new=%d), waiting for registry to update", addedDons)
Expand Down
Loading