Skip to content
Closed
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
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,7 @@ indexer/secrets.toml

# Ignore all log directories
**/logs/

# Go workspace file
go.work
go.work.sum
56 changes: 51 additions & 5 deletions build/devenv/canton/impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,13 @@ import (
"time"

"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/google/uuid"
"github.com/noders-team/go-daml/pkg/client"
"github.com/prometheus/client_golang/prometheus"
"github.com/rs/zerolog"
chainsel "github.com/smartcontractkit/chain-selectors"

"github.com/smartcontractkit/chainlink-canton-internal/contracts"
"github.com/smartcontractkit/chainlink-ccv/deployments"
"github.com/smartcontractkit/chainlink-ccv/devenv/cciptestinterfaces"
"github.com/smartcontractkit/chainlink-ccv/protocol"
Expand All @@ -35,6 +39,53 @@ func New(logger zerolog.Logger) *Chain {
}
}

func (c *Chain) Family() string {
return chainsel.FamilyCanton
}

func (c *Chain) ChainFamily() string {
return chainsel.FamilyCanton
}

// DeployContractsForSelector implements cciptestinterfaces.CCIP17Configuration.
func (c *Chain) DeployContractsForSelector(ctx context.Context, env *deployment.Environment, selector uint64, committees *deployments.EnvironmentTopology) (datastore.DataStore, error) {
l := c.logger
l.Info().Msg("Configuring contracts for selector")
l.Info().Any("Selector", selector).Msg("Deploying for chain selector")
cc := env.BlockChains.CantonChains()[selector]
participant1 := cc.Participants[0]
jwToken, err := participant1.JWTProvider.Token(ctx)
if err != nil {
return nil, fmt.Errorf("failed to get JWT for participant 1: %w", err)
}
c1, err := client.NewDamlClient(jwToken, participant1.Endpoints.GRPCLedgerAPIURL).
WithAdminAddress(participant1.Endpoints.AdminAPIURL).
Build(ctx)
if err != nil {
return nil, fmt.Errorf("failed to create client for participant 1: %w", err)
}
defer c1.Close()

runningDs := datastore.NewMemoryDataStore()

// Deploy contracts

// Using the Coin dar file as an example
coinDar, err := contracts.GetDar(contracts.Coin, contracts.CurrentVersion)
if err != nil {
return nil, fmt.Errorf("failed to compile Coin contract: %w", err)
}
err = c1.PackageMng.UploadDarFile(ctx, coinDar, uuid.New().String())
if err != nil {
return nil, fmt.Errorf("failed to upload Dar file: %w", err)
}
l.Info().Msg("Uploaded Coin Dar file")

// TODO Deploy contracts

return runningDs.Seal(), nil
}

// ConfigureNodes implements cciptestinterfaces.CCIP17Configuration.
func (c *Chain) ConfigureNodes(ctx context.Context, blockchain *blockchain.Input) (string, error) {
return "", nil // TODO: implement
Expand All @@ -45,11 +96,6 @@ func (c *Chain) ConnectContractsWithSelectors(ctx context.Context, e *deployment
return nil // TODO: implement
}

// DeployContractsForSelector implements cciptestinterfaces.CCIP17Configuration.
func (c *Chain) DeployContractsForSelector(ctx context.Context, env *deployment.Environment, selector uint64, committees *deployments.EnvironmentTopology) (datastore.DataStore, error) {
return datastore.NewMemoryDataStore().Seal(), nil // TODO: implement
}

// DeployLocalNetwork implements cciptestinterfaces.CCIP17Configuration.
func (c *Chain) DeployLocalNetwork(ctx context.Context, bcs *blockchain.Input) (*blockchain.Output, error) {
c.logger.
Expand Down
3 changes: 3 additions & 0 deletions build/devenv/cciptestinterfaces/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ type ExecutionStateChangedEvent struct {

// Chain provides methods to interact with a single chain that has CCIP deployed.
type Chain interface {
// Family returns the family of the chain.
Family() string
Comment on lines +125 to +126
Copy link
Collaborator

Choose a reason for hiding this comment

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

Are both Family() and ChainFamily() needed?

// GetEOAReceiverAddress gets an EOA receiver address for this chain.
GetEOAReceiverAddress() (protocol.UnknownAddress, error)
// GetSenderAddress gets the sender address for this chain.
Expand Down Expand Up @@ -161,6 +163,7 @@ type OnChainCommittees struct {
// OnChainConfigurable defines methods that allows devenv to
// deploy, configure Chainlink product and connect on-chain part with other chains.
type OnChainConfigurable interface {
ChainFamily() string // TODO
// DeployContractsForSelector deploys contracts for chain X using topology for CommitteeVerifier configuration.
// Returns all the contract addresses and metadata as datastore.DataStore.
DeployContractsForSelector(ctx context.Context, env *deployment.Environment, selector uint64, topology *deployments.EnvironmentTopology) (datastore.DataStore, error)
Expand Down
128 changes: 82 additions & 46 deletions build/devenv/cldf.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,18 @@ import (

"github.com/smartcontractkit/chainlink-ccv/protocol/common/logging"
"github.com/smartcontractkit/chainlink-common/pkg/logger"
"github.com/smartcontractkit/chainlink-deployments-framework/chain/evm/provider/rpcclient"
"github.com/smartcontractkit/chainlink-deployments-framework/datastore"
"github.com/smartcontractkit/chainlink-deployments-framework/deployment"
"github.com/smartcontractkit/chainlink-deployments-framework/operations"
"github.com/smartcontractkit/chainlink-testing-framework/framework/components/blockchain"

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

cldf_chain "github.com/smartcontractkit/chainlink-deployments-framework/chain"
cldf_canton "github.com/smartcontractkit/chainlink-deployments-framework/chain/canton"
cldf_canton_provider "github.com/smartcontractkit/chainlink-deployments-framework/chain/canton/provider"
cldf_evm_provider "github.com/smartcontractkit/chainlink-deployments-framework/chain/evm/provider"
"github.com/smartcontractkit/chainlink-deployments-framework/chain/evm/provider/rpcclient"
"github.com/smartcontractkit/chainlink-deployments-framework/datastore"
"github.com/smartcontractkit/chainlink-deployments-framework/deployment"
"github.com/smartcontractkit/chainlink-deployments-framework/operations"
)

var Plog = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}).Level(zerolog.DebugLevel).With().Fields(map[string]any{"component": "ccv"}).Logger()
Expand All @@ -47,53 +50,86 @@ func NewCLDFOperationsEnvironment(bc []*blockchain.Input, dataStore datastore.Da
selectors := make([]uint64, 0)
defaultTxTimeout := 30 * time.Second
for _, b := range bc {
if b.Type == blockchain.TypeCanton {
// Canton CLDF is not supported yet
continue
}

chainID := b.Out.ChainID
rpcWSURL := b.Out.Nodes[0].ExternalWSUrl
rpcHTTPURL := b.Out.Nodes[0].ExternalHTTPUrl

d, err := chainsel.GetChainDetailsByChainIDAndFamily(chainID, chainsel.FamilyEVM)
family, err := blockchain.TypeToFamily(b.Type)
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think you can just switch on b.Family - if thats incorrect then its just wrong config.

Copy link
Member Author

Choose a reason for hiding this comment

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

technically they're two different consts - they match 1:1 right now but ideally CTF would just re-use the chainselector constants

if err != nil {
return nil, nil, err
}
selectors = append(selectors, d.ChainSelector)

var confirmer cldf_evm_provider.ConfirmFunctor
switch b.Type {
case blockchain.TypeAnvil:
confirmer = cldf_evm_provider.ConfirmFuncGeth(defaultTxTimeout, cldf_evm_provider.WithTickInterval(5*time.Millisecond))
case blockchain.TypeGeth:
confirmer = cldf_evm_provider.ConfirmFuncGeth(defaultTxTimeout)
default:
panic(fmt.Sprintf("blockchain type %s is not supported", b.Type))
return nil, nil, fmt.Errorf("unable to determine blockchain type: %w", err)
}

p, err := cldf_evm_provider.NewRPCChainProvider(
d.ChainSelector,
cldf_evm_provider.RPCChainProviderConfig{
DeployerTransactorGen: cldf_evm_provider.TransactorFromRaw(
getNetworkPrivateKey(),
),
RPCs: []rpcclient.RPC{
{
Name: "default",
WSURL: rpcWSURL,
HTTPURL: rpcHTTPURL,
PreferredURLScheme: rpcclient.URLSchemePreferenceHTTP,
switch family {
case blockchain.FamilyEVM:
chainID := b.Out.ChainID
rpcWSURL := b.Out.Nodes[0].ExternalWSUrl
rpcHTTPURL := b.Out.Nodes[0].ExternalHTTPUrl

d, err := chainsel.GetChainDetailsByChainIDAndFamily(chainID, chainsel.FamilyEVM)
if err != nil {
return nil, nil, err
}
selectors = append(selectors, d.ChainSelector)

var confirmer cldf_evm_provider.ConfirmFunctor
switch b.Type {
case blockchain.TypeAnvil:
confirmer = cldf_evm_provider.ConfirmFuncGeth(defaultTxTimeout, cldf_evm_provider.WithTickInterval(5*time.Millisecond))
case blockchain.TypeGeth:
confirmer = cldf_evm_provider.ConfirmFuncGeth(defaultTxTimeout)
default:
panic(fmt.Sprintf("EVM blockchain type %s is not supported", b.Type))
}

p, err := cldf_evm_provider.NewRPCChainProvider(
d.ChainSelector,
cldf_evm_provider.RPCChainProviderConfig{
DeployerTransactorGen: cldf_evm_provider.TransactorFromRaw(
getNetworkPrivateKey(),
),
RPCs: []rpcclient.RPC{
{
Name: "default",
WSURL: rpcWSURL,
HTTPURL: rpcHTTPURL,
PreferredURLScheme: rpcclient.URLSchemePreferenceHTTP,
},
},
UsersTransactorGen: GenerateUserTransactors(getUserPrivateKeys()),
ConfirmFunctor: confirmer,
},
UsersTransactorGen: GenerateUserTransactors(getUserPrivateKeys()),
ConfirmFunctor: confirmer,
},
).Initialize(context.Background())
if err != nil {
return nil, nil, err
).Initialize(context.Background())
if err != nil {
return nil, nil, err
}
providers = append(providers, p)
case blockchain.FamilyCanton:
d, err := chainsel.GetChainDetailsByChainIDAndFamily(b.Out.ChainID, chainsel.FamilyCanton)
if err != nil {
return nil, nil, err
}
selectors = append(selectors, d.ChainSelector)

var (
endpoints []cldf_canton.ParticipantEndpoints
jwtProviders []cldf_canton.JWTProvider
)
for _, p := range b.Out.NetworkSpecificData.CantonEndpoints.Participants {
endpoints = append(endpoints, cldf_canton.ParticipantEndpoints{
JSONLedgerAPIURL: p.JSONLedgerAPIURL,
GRPCLedgerAPIURL: p.GRPCLedgerAPIURL,
AdminAPIURL: p.AdminAPIURL,
ValidatorAPIURL: p.ValidatorAPIURL,
})
jwtProviders = append(jwtProviders, cldf_canton.NewStaticJWTProvider(p.JWT))
}

p, err := cldf_canton_provider.NewRPCChainProvider(d.ChainSelector, cldf_canton_provider.RPCChainProviderConfig{
Endpoints: endpoints,
JWTProviders: jwtProviders,
}).Initialize(context.TODO())
if err != nil {
return nil, nil, err
}
providers = append(providers, p)
default:
return nil, nil, fmt.Errorf("unsupported blockchain family: %s", family)
}
providers = append(providers, p)
}

blockchains := cldf_chain.NewBlockChainsFromSlice(providers)
Expand Down
6 changes: 6 additions & 0 deletions build/devenv/env.toml
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,12 @@ execution_interval = 15_000_000_000
port = "8565"
type = "anvil"

[[blockchains]]
type = "canton"
chain_id = "LocalNet"
number_of_canton_validators = 5
port = "8088"
Comment on lines +158 to +162
Copy link
Collaborator

Choose a reason for hiding this comment

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

This may increase CI time for the smoke test significantly and is currently not needed - we can create a new config for Canton/EVM until we figure out how to best set up the test matrices for the full E2E tests.


[fake]
image = "ccv-fakes:dev"
port = 9111
Expand Down
4 changes: 2 additions & 2 deletions build/devenv/environment.go
Original file line number Diff line number Diff line change
Expand Up @@ -550,7 +550,7 @@ func NewEnvironment() (in *Cfg, err error) {
// START: Deploy Pricer service //
///////////////////////////////
if _, err := services.NewPricer(in.Pricer); err != nil {
return nil, fmt.Errorf("failed to setup pricer service")
return nil, fmt.Errorf("failed to setup pricer service: %w", err)
}

if in.Pricer != nil {
Expand Down Expand Up @@ -675,7 +675,7 @@ func NewEnvironment() (in *Cfg, err error) {
}

var networkInfo chainsel.ChainDetails
networkInfo, err = chainsel.GetChainDetailsByChainIDAndFamily(in.Blockchains[i].ChainID, chainsel.FamilyEVM)
networkInfo, err = chainsel.GetChainDetailsByChainIDAndFamily(in.Blockchains[i].ChainID, impl.ChainFamily())
if err != nil {
return nil, err
}
Expand Down
8 changes: 8 additions & 0 deletions build/devenv/evm/impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,10 @@ func NewCCIP17EVM(ctx context.Context, logger zerolog.Logger, e *deployment.Envi
}, nil
}

func (m *CCIP17EVM) Family() string {
return chainsel.FamilyEVM
}

func (m *CCIP17EVM) getOrCreateOnRampPoller() (*eventPoller[cciptestinterfaces.MessageSentEvent], error) {
m.pollersMu.Lock()
defer m.pollersMu.Unlock()
Expand Down Expand Up @@ -1085,6 +1089,10 @@ func (m *CCIP17EVMConfig) ConfigureNodes(ctx context.Context, bc *blockchain.Inp
), nil
}

func (m *CCIP17EVMConfig) ChainFamily() string {
return chainsel.FamilyEVM
}

func (m *CCIP17EVMConfig) DeployContractsForSelector(ctx context.Context, env *deployment.Environment, selector uint64, topology *deployments.EnvironmentTopology) (datastore.DataStore, error) {
l := m.logger
l.Info().Msg("Configuring contracts for selector")
Expand Down
Loading
Loading