Skip to content
Open
Show file tree
Hide file tree
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
10 changes: 7 additions & 3 deletions build/devenv/cciptestinterfaces/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,10 +151,14 @@ type Chain interface {
GetRoundRobinUser() func() *bind.TransactOpts
}

type Signers struct {
Signers [][]byte
Threshold uint8
}

type OnChainCommittees struct {
CommitteeQualifier string
Signers [][]byte
Threshold uint8
CommitteeQualifier string
SignersBySourceChain map[uint64]Signers
}

// OnChainConfigurable defines methods that allows devenv to
Expand Down
32 changes: 30 additions & 2 deletions build/devenv/env.toml
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ cl_nodes_funding_link = 50


# Tertiary Verifier Setup
# Tertiary verifier secures/enables chain 1337 with 2/3, chain 2337 with 1/2, and chain 3337 with 1/1
[[verifier]]
image = "verifier:dev"
container_name = "tertiary-verifier-1"
Expand All @@ -114,6 +115,7 @@ cl_nodes_funding_link = 50
root_path = "../../"
committee_name = "tertiary"
node_index = 0
enabled_chains = ["1337", "2337"]
Comment thread
anedos-chainlink marked this conversation as resolved.
[verifier.db]
image = "postgres:16-alpine"
name = "tertiary-verifier-1-db"
Expand All @@ -128,12 +130,27 @@ cl_nodes_funding_link = 50
root_path = "../../"
committee_name = "tertiary"
node_index = 1
enabled_chains = ["1337", "2337"]
[verifier.db]
image = "postgres:16-alpine"
name = "tertiary-verifier-2-db"
port = 8437


[[verifier]]
image = "verifier:dev"
container_name = "tertiary-verifier-3"
port = 8650
source_code_path = "../verifier"
root_path = "../../"
committee_name = "tertiary"
node_index = 2
enabled_chains = ["1337", "3337"]
[verifier.db]
image = "postgres:16-alpine"
name = "tertiary-verifier-3-db"
port = 8438

[[token_verifier]]
mode = "standalone"
image = "token-verifier:dev"
Expand All @@ -142,7 +159,6 @@ cl_nodes_funding_link = 50
source_code_path = "../verifier"
root_path = "../../"


[[executor]]
image = "executor:dev"
port = 8101
Expand Down Expand Up @@ -368,6 +384,12 @@ URI = "postgresql://indexer:indexer@indexer-db:5432/indexer?sslmode=disable"
source_code_path = "../aggregator"
root_path = "../../"

# tertiary verifier is composed of a 3 committee verifiers and the 3 chains are secured with different thresholds
[aggregator.threshold_per_source]
1337 = 2
2337 = 1
3337 = 1

[aggregator.db]
image = "postgres:16-alpine"
host_port = 7434
Expand All @@ -388,6 +410,12 @@ URI = "postgresql://indexer:indexer@indexer-db:5432/indexer?sslmode=disable"
enabled = true
groups = ["verifiers"]

[[aggregator.api_clients]]
client_id = "tertiary-verifier-3"
description = "Development tertiary verifier 3"
enabled = true
groups = ["verifiers"]

[[aggregator.api_clients]]
client_id = "monitoring"
description = "Monitoring and infrastructure client"
Expand All @@ -399,7 +427,7 @@ URI = "postgresql://indexer:indexer@indexer-db:5432/indexer?sslmode=disable"
description = "Development Indexer"
enabled = true
groups = ["indexer"]
# Environment variables for sensitive configuration

[aggregator.env]
storage_connection_url = "postgresql://aggregator:aggregator@tertiary-aggregator-db:5432/aggregator?sslmode=disable"
redis_address = "tertiary-aggregator-redis:6379"
Expand Down
91 changes: 72 additions & 19 deletions build/devenv/environment.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"net/http"
"os"
"path/filepath"
"slices"
"strconv"
"strings"

Expand Down Expand Up @@ -317,25 +318,6 @@ func NewEnvironment() (in *Cfg, err error) {
/////////////////////////////
// START: Deploy contracts //
/////////////////////////////
var committees []cciptestinterfaces.OnChainCommittees
{
addrs := make(map[string][][]byte)

for _, ver := range in.Verifier {
// At this point, SigningKeyPublic must be assigned -- either by keygen either manually or by the CL node.
addrs[ver.CommitteeName] = append(addrs[ver.CommitteeName], hexutil.MustDecode(ver.SigningKeyPublic))
}

for committeeName, signers := range addrs {
committees = append(committees, cciptestinterfaces.OnChainCommittees{
CommitteeQualifier: committeeName,
Signers: signers,
// TODO: should this be pulled from the aggregator configuration, ThresholdPerSource?
// And if nothing in there, default to len(signers)?
Threshold: uint8(len(signers)),
})
}
}

var selectors []uint64
var e *deployment.Environment
Expand All @@ -348,6 +330,77 @@ func NewEnvironment() (in *Cfg, err error) {
}
L.Info().Any("Selectors", selectors).Msg("Deploying for chain selectors")

// store one entry per committee, with signers per source chain
var committees []cciptestinterfaces.OnChainCommittees
{
// Map aggregator inputs by committee name for threshold lookup
aggByCommittee := make(map[string]*services.AggregatorInput)
for _, agg := range in.Aggregator {
aggByCommittee[agg.CommitteeName] = agg
}

// Collect unique committee names from verifiers
committeeSet := make(map[string]bool)
for _, ver := range in.Verifier {
committeeSet[ver.CommitteeName] = true
}

// For each committee, build an OnChainCommittees entry with signers per source chain
for committeeName := range committeeSet {
signersBySourceChain := make(map[uint64]cciptestinterfaces.Signers)

for _, selector := range selectors {
// Determine signers for this committee on this selector
signers := make([][]byte, 0)
chainIDStr, err := chainsel.GetChainIDFromSelector(selector)
if err != nil {
return nil, fmt.Errorf("failed to get chain ID from selector %d: %w", selector, err)
}

for _, ver := range in.Verifier {
if ver.CommitteeName != committeeName {
continue
}
// If EnabledChains is empty, verifier secures all chains.
if len(ver.EnabledChains) == 0 {
signers = append(signers, hexutil.MustDecode(ver.SigningKeyPublic))
continue
}
// Otherwise include only if this verifier enabled this chain (compare chain ID strings)
if slices.Contains(ver.EnabledChains, chainIDStr) {
signers = append(signers, hexutil.MustDecode(ver.SigningKeyPublic))
}
}

// Determine threshold for this committee+source chain
var threshold uint8
agg := aggByCommittee[committeeName]
if agg != nil && agg.ThresholdPerSource != nil {
// ThresholdPerSource is keyed by chain id string
if t, ok := agg.ThresholdPerSource[chainIDStr]; ok {
threshold = t
} else {
// If threshold map is present but this source is missing, skip this entry (aggregator ignores it)
continue
}
} else {
// default: full quorum (all signers for that chain)
threshold = uint8(len(signers))
}

signersBySourceChain[selector] = cciptestinterfaces.Signers{
Signers: signers,
Threshold: threshold,
}
}

committees = append(committees, cciptestinterfaces.OnChainCommittees{
CommitteeQualifier: committeeName,
SignersBySourceChain: signersBySourceChain,
})
}
}

timeTrack.Record("[infra] deploying blockchains")
ds := datastore.NewMemoryDataStore()
for i, impl := range impls {
Expand Down
51 changes: 43 additions & 8 deletions build/devenv/evm/impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ const (

QuaternaryReceiverQualifier = "quaternary"

QuinaryReceiverQualifier = "quinary"

CustomExecutorQualifier = "custom"

CommitteeVerifierGasForVerification = 500_000
Expand Down Expand Up @@ -1089,6 +1091,15 @@ func toCommitteeVerifierParams(committees []cciptestinterfaces.OnChainCommittees
return params
}

// convert signer public key byte array to the EVM address string representations.
func signersBytesToStrings(bs [][]byte) []string {
s := make([]string, 0, len(bs))
for _, b := range bs {
s = append(s, common.BytesToAddress(b).String())
}
return s
}

func (m *CCIP17EVMConfig) DeployContractsForSelector(ctx context.Context, env *deployment.Environment, selector uint64, committees []cciptestinterfaces.OnChainCommittees) (datastore.DataStore, error) {
l := m.logger
l.Info().Msg("Configuring contracts for selector")
Expand Down Expand Up @@ -1256,6 +1267,20 @@ func (m *CCIP17EVMConfig) DeployContractsForSelector(ctx context.Context, env *d
OptionalThreshold: 1,
Qualifier: QuaternaryReceiverQualifier,
},
{
// single required verifier (tertiary), no optional verifiers, no optional threshold
// used to test NOP downsizing e2e
Version: semver.MustParse(mock_receiver.Deploy.Version()),
RequiredVerifiers: []datastore.AddressRef{
{
Type: datastore.ContractType(committee_verifier.ResolverType),
Version: semver.MustParse(committee_verifier.Deploy.Version()),
ChainSelector: selector,
Qualifier: TertiaryCommitteeVerifierQualifier,
},
},
Qualifier: QuinaryReceiverQualifier,
},
},
},
},
Expand Down Expand Up @@ -1456,20 +1481,27 @@ func (m *CCIP17EVMConfig) configureTokenForTransfer(
return nil
}

func toComitteeVerifier(selector uint64, committees []cciptestinterfaces.OnChainCommittees, remoteChainConfigs map[uint64]adapters.CommitteeVerifierRemoteChainConfig) []adapters.CommitteeVerifierConfig[datastore.AddressRef] {
func toCommitteeVerifier(selector uint64, committees []cciptestinterfaces.OnChainCommittees, remoteChainConfigs map[uint64]adapters.CommitteeVerifierRemoteChainConfig) []adapters.CommitteeVerifierConfig[datastore.AddressRef] {
// chainIDStr, _ := chainsel.GetChainIDFromSelector(selector)
// fmt.Printf("toCommitteeVerifier: creating committee verifiers for selector %d/%s\n", selector, chainIDStr)
committeeVerifiers := make([]adapters.CommitteeVerifierConfig[datastore.AddressRef], 0, len(committees))
for _, committee := range committees {
remoteChainConfigWithSignatureConfig := make(map[uint64]adapters.CommitteeVerifierRemoteChainConfig, len(remoteChainConfigs))
for remoteChainSelector, remoteChainConfig := range remoteChainConfigs {
signers := make([]string, 0, len(committee.Signers))
for _, signer := range committee.Signers {
signers = append(signers, common.BytesToAddress(signer).String())
// Check if this committee has signers for this source chain
signerData, ok := committee.SignersBySourceChain[remoteChainSelector]
if !ok {
continue
}
signers := signersBytesToStrings(signerData.Signers)
remoteChainConfig.SignatureConfig = adapters.CommitteeVerifierSignatureQuorumConfig{
Threshold: committee.Threshold,
Threshold: signerData.Threshold,
Signers: signers,
}
remoteChainConfigWithSignatureConfig[remoteChainSelector] = remoteChainConfig
// remoteChainIDStr, _ := chainsel.GetChainIDFromSelector(remoteChainSelector)
// fmt.Printf("committeeVerifiers[%s]: for source chain %d/%s -> %+v\n", committee.CommitteeQualifier, remoteChainSelector, remoteChainIDStr, remoteChainConfig.SignatureConfig)
// TODO set PayloadSizeBytes calculated from signers list
}
committeeVerifiers = append(committeeVerifiers, adapters.CommitteeVerifierConfig[datastore.AddressRef]{
CommitteeVerifier: []datastore.AddressRef{
Expand All @@ -1489,6 +1521,9 @@ func toComitteeVerifier(selector uint64, committees []cciptestinterfaces.OnChain
RemoteChains: remoteChainConfigWithSignatureConfig,
})
}

// fmt.Printf("committeeVerifiers:\n%+v\n", committeeVerifiers)

return committeeVerifiers
}

Expand Down Expand Up @@ -1575,8 +1610,8 @@ func (m *CCIP17EVMConfig) ConnectContractsWithSelectors(ctx context.Context, e *
committeeVerifierRemoteChainConfigs[rs] = adapters.CommitteeVerifierRemoteChainConfig{
AllowlistEnabled: false,
GasForVerification: CommitteeVerifierGasForVerification,
FeeUSDCents: 0, // TODO: set proper fee
PayloadSizeBytes: 0, // TODO: set proper payload size
FeeUSDCents: 50, // Copied from CLD/deploy_ccip.go
PayloadSizeBytes: 0, // will be set later after we gather the # of signatures
}
}

Expand Down Expand Up @@ -1604,7 +1639,7 @@ func (m *CCIP17EVMConfig) ConnectContractsWithSelectors(ctx context.Context, e *
Type: datastore.ContractType(routeroperations.ContractType),
Version: semver.MustParse(routeroperations.Deploy.Version()),
},
CommitteeVerifiers: toComitteeVerifier(selector, committees, committeeVerifierRemoteChainConfigs),
CommitteeVerifiers: toCommitteeVerifier(selector, committees, committeeVerifierRemoteChainConfigs),
},
},
})
Expand Down
6 changes: 4 additions & 2 deletions build/devenv/gencfg/gencfg.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"golang.org/x/oauth2"
"gopkg.in/yaml.v2"

chainsel "github.com/smartcontractkit/chain-selectors"
"github.com/smartcontractkit/chainlink-ccip/ccv/chains/evm/deployment/v1_7_0/operations/committee_verifier"
executor_operations "github.com/smartcontractkit/chainlink-ccip/ccv/chains/evm/deployment/v1_7_0/operations/executor"
offrampoperations "github.com/smartcontractkit/chainlink-ccip/ccv/chains/evm/deployment/v1_7_0/operations/offramp"
Expand Down Expand Up @@ -81,11 +82,12 @@ func GenerateConfigs(cldDomain string, verifierPubKeys []string, numExecutors in
rmnRemoteAddresses = make(map[string]string)
rmnRemoteAddressesUint64 = make(map[uint64]string)
offRampAddresses = make(map[uint64]string)
thresholdPerSource = make(map[uint64]uint8)
thresholdPerSource = make(map[string]uint8)
)

for _, ref := range addressRefs {
chainSelectorStr := strconv.FormatUint(ref.ChainSelector, 10)
chainID, _ := chainsel.GetChainIDFromSelector(ref.ChainSelector)
switch ref.Type {
case datastore.ContractType(onrampoperations.ContractType):
onRampAddresses[chainSelectorStr] = ref.Address
Expand All @@ -101,7 +103,7 @@ func GenerateConfigs(cldDomain string, verifierPubKeys []string, numExecutors in
case datastore.ContractType(offrampoperations.ContractType):
offRampAddresses[ref.ChainSelector] = ref.Address
}
thresholdPerSource[ref.ChainSelector] = ocrThreshold(len(verifierPubKeys))
thresholdPerSource[chainID] = ocrThreshold(len(verifierPubKeys))
}

tempDir, err := os.MkdirTemp("", "ccv-configs")
Expand Down
Loading
Loading