Skip to content

Commit 2af08f1

Browse files
authored
Canton - support Docker-internal networking (NONEVM-3773) (#816)
This: - Adds an (optional) `InternalEndpoints *ParticipantEndpoints` to a Canton `Participant` - It will automatically be populated when using the CTFProvider - When using the RPC provider, it is optional and will only be populated when specified in the input - Make the RPC provider's `JSONLedgerAPIURL` & `ValidatorAPIURL` URLs optional since they might not be available in all settings - Bump CTF to: https://github.com/smartcontractkit/chainlink-testing-framework/releases/tag/framework%2Fv0.15.0
1 parent 4c73644 commit 2af08f1

9 files changed

Lines changed: 189 additions & 84 deletions

File tree

.changeset/neat-cameras-clap.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"chainlink-deployments-framework": minor
3+
---
4+
5+
Add InternalEndpoints to Canton Chain
6+
Bump CTF to v0.15.0

chain/canton/canton_chain.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ type Participant struct {
3636
Name string
3737
// The endpoints to interact with the participant's APIs
3838
Endpoints ParticipantEndpoints
39+
// Optional (Docker) internal endpoints to interact with the participant's APIs
40+
InternalEndpoints *ParticipantEndpoints
3941
// The set of service clients to interact with the participant's Ledger API.
4042
// All clients are ready-to-use and are already configured with the correct authentication.
4143
LedgerServices LedgerServiceClients

chain/canton/provider/ctf_provider.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ func (p *CTFChainProvider) Initialize(ctx context.Context) (chain.BlockChain, er
9999
}
100100

101101
// Test HTTP health endpoint
102-
for i, participant := range output.NetworkSpecificData.CantonEndpoints.Participants {
102+
for i, participant := range output.NetworkSpecificData.CantonData.ExternalEndpoints.Participants {
103103
req, err := http.NewRequestWithContext(ctx, http.MethodGet, participant.HTTPHealthCheckURL+"/health", nil)
104104
require.NoError(p.t, err)
105105
resp, err := http.DefaultClient.Do(req)
@@ -110,10 +110,10 @@ func (p *CTFChainProvider) Initialize(ctx context.Context) (chain.BlockChain, er
110110

111111
p.chain = &canton.Chain{
112112
ChainMetadata: canton.ChainMetadata{Selector: p.selector},
113-
Participants: make([]canton.Participant, len(output.NetworkSpecificData.CantonEndpoints.Participants)),
113+
Participants: make([]canton.Participant, len(output.NetworkSpecificData.CantonData.ExternalEndpoints.Participants)),
114114
}
115115

116-
for i, participantEndpoints := range output.NetworkSpecificData.CantonEndpoints.Participants {
116+
for i, participantEndpoints := range output.NetworkSpecificData.CantonData.ExternalEndpoints.Participants {
117117
// Create an InsecureStaticProvider that always returns the same JWT token for the participant
118118
authProvider := authentication.NewInsecureStaticProvider(participantEndpoints.JWT)
119119
tokenSource := authProvider.TokenSource()
@@ -159,6 +159,12 @@ func (p *CTFChainProvider) Initialize(ctx context.Context) (chain.BlockChain, er
159159
AdminAPIURL: participantEndpoints.AdminAPIURL,
160160
ValidatorAPIURL: participantEndpoints.ValidatorAPIURL,
161161
},
162+
InternalEndpoints: &canton.ParticipantEndpoints{
163+
JSONLedgerAPIURL: output.NetworkSpecificData.CantonData.InternalEndpoints.Participants[i].JSONLedgerAPIURL,
164+
GRPCLedgerAPIURL: output.NetworkSpecificData.CantonData.InternalEndpoints.Participants[i].GRPCLedgerAPIURL,
165+
AdminAPIURL: output.NetworkSpecificData.CantonData.InternalEndpoints.Participants[i].AdminAPIURL,
166+
ValidatorAPIURL: output.NetworkSpecificData.CantonData.InternalEndpoints.Participants[i].ValidatorAPIURL,
167+
},
162168
LedgerServices: ledgerServices,
163169
AdminServices: &adminServices,
164170
TokenSource: tokenSource,

chain/canton/provider/ctf_provider_test.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,12 @@ func Test_CTFChainProvider_Initialize(t *testing.T) {
116116
// Test that admin service client can be called
117117
_, err = participant.AdminServices.Package.ListDars(t.Context(), &participantv30.ListDarsRequest{})
118118
require.NoError(t, err)
119+
// Test that the internal endpoints have been populated
120+
require.NotNil(t, participant.InternalEndpoints)
121+
assert.NotEmpty(t, participant.InternalEndpoints.JSONLedgerAPIURL)
122+
assert.NotEmpty(t, participant.InternalEndpoints.GRPCLedgerAPIURL)
123+
assert.NotEmpty(t, participant.InternalEndpoints.AdminAPIURL)
124+
assert.NotEmpty(t, participant.InternalEndpoints.ValidatorAPIURL)
119125
}
120126

121127
// Check that subsequent calls to Initialize don't re-initialize the chain

chain/canton/provider/rpc_provider.go

Lines changed: 38 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,27 @@ type RPCChainProviderConfig struct {
2222
// ParticipantConfig is the configuration of a single participant.
2323
// It contains the configuration details to connect and authenticate against a participant's APIs.
2424
type ParticipantConfig struct {
25-
// (HTTP) The URL to access the participant's JSON Ledger API
25+
// The endpoints used to connect to this participant's APIs.
26+
Endpoints
27+
// The (Docker) internal endpoints used to connect to the participant's APIs.
28+
// If Specified, the resulting chain will have its InternalEndpoints field populated with these values.
29+
// This is useful when having to connect Canton from within another Docker container.
30+
// Optional
31+
InternalEndpoints *Endpoints
32+
// The UserID of the user that should be used for accessing the participant's API endpoints.
33+
// Required
34+
UserID string
35+
// The PartyID of the party that should be used for accessing the participant's API endpoints.
36+
// Required
37+
PartyID string
38+
// An authentication.Provider implementation that provides the credentials for authenticating with the participant's API endpoints.
2639
// Required
40+
AuthProvider authentication.Provider
41+
}
42+
43+
type Endpoints struct {
44+
// (HTTP) The URL to access the participant's JSON Ledger API
45+
// Optional
2746
// https://docs.digitalasset.com/build/3.5/reference/json-api/json-api.html
2847
JSONLedgerAPIURL string
2948
// (gRPC) The URL to access the participant's gRPC Ledger API
@@ -35,34 +54,19 @@ type ParticipantConfig struct {
3554
// https://docs.digitalasset.com/operate/3.5/howtos/configure/apis/admin_api.html
3655
AdminAPIURL string
3756
// (HTTP) The URL to access the participant's Validator API
38-
// Required
57+
// Optional
3958
// https://docs.sync.global/app_dev/validator_api/index.html
4059
ValidatorAPIURL string
41-
// The UserID of the user that should be used for accessing the participant's API endpoints.
42-
// Required
43-
UserID string
44-
// The PartyID of the party that should be used for accessing the participant's API endpoints.
45-
// Required
46-
PartyID string
47-
// An authentication.Provider implementation that provides the credentials for authenticating with the participant's API endpoints.
48-
// Required
49-
AuthProvider authentication.Provider
5060
}
5161

5262
func (c RPCChainProviderConfig) validate() error {
5363
if len(c.Participants) == 0 {
5464
return errors.New("no participants specified")
5565
}
5666
for i, participant := range c.Participants {
57-
if participant.JSONLedgerAPIURL == "" {
58-
return fmt.Errorf("participant %d has no JSON Ledger API URL set", i+1)
59-
}
6067
if participant.GRPCLedgerAPIURL == "" {
6168
return fmt.Errorf("participant %d has no gRPC Ledger API URL set", i+1)
6269
}
63-
if participant.ValidatorAPIURL == "" {
64-
return fmt.Errorf("participant %d has no Validator API URL set", i+1)
65-
}
6670
if participant.UserID == "" {
6771
return fmt.Errorf("participant %d has no User ID set", i+1)
6872
}
@@ -140,6 +144,17 @@ func (p *RPCChainProvider) Initialize(_ context.Context) (chain.BlockChain, erro
140144
adminServices = &services
141145
}
142146

147+
// Populate internal endpoints (if set)
148+
var internalEndpoints *canton.ParticipantEndpoints
149+
if participant.InternalEndpoints != nil {
150+
internalEndpoints = &canton.ParticipantEndpoints{
151+
JSONLedgerAPIURL: participant.InternalEndpoints.JSONLedgerAPIURL,
152+
GRPCLedgerAPIURL: participant.InternalEndpoints.GRPCLedgerAPIURL,
153+
AdminAPIURL: participant.InternalEndpoints.AdminAPIURL,
154+
ValidatorAPIURL: participant.InternalEndpoints.ValidatorAPIURL,
155+
}
156+
}
157+
143158
p.chain.Participants[i] = canton.Participant{
144159
Name: fmt.Sprintf("Participant %v", i+1),
145160
Endpoints: canton.ParticipantEndpoints{
@@ -148,11 +163,12 @@ func (p *RPCChainProvider) Initialize(_ context.Context) (chain.BlockChain, erro
148163
AdminAPIURL: participant.AdminAPIURL,
149164
ValidatorAPIURL: participant.ValidatorAPIURL,
150165
},
151-
LedgerServices: ledgerServices,
152-
AdminServices: adminServices,
153-
TokenSource: tokenSource,
154-
UserID: participant.UserID,
155-
PartyID: participant.PartyID,
166+
InternalEndpoints: internalEndpoints,
167+
LedgerServices: ledgerServices,
168+
AdminServices: adminServices,
169+
TokenSource: tokenSource,
170+
UserID: participant.UserID,
171+
PartyID: participant.PartyID,
156172
}
157173
}
158174

0 commit comments

Comments
 (0)