-
Notifications
You must be signed in to change notification settings - Fork 44
Add Canton Blockchain #2332
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
base: main
Are you sure you want to change the base?
Add Canton Blockchain #2332
Changes from all commits
efe8d83
a14bfbe
324e68f
b207004
ce082cf
ab9c845
caa132f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| - Add support for Canton blockchain |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,101 @@ | ||
| package blockchain | ||
|
|
||
| import ( | ||
| "context" | ||
| "fmt" | ||
|
|
||
| "github.com/testcontainers/testcontainers-go" | ||
| "github.com/testcontainers/testcontainers-go/network" | ||
|
|
||
| "github.com/smartcontractkit/chainlink-testing-framework/framework/components/blockchain/canton" | ||
| ) | ||
|
|
||
| // newCanton sets up a Canton blockchain network with the specified number of validators. | ||
| // It creates a Docker network and starts the necessary containers for Postgres, Canton, Splice, and an Nginx reverse proxy. | ||
| // | ||
| // The reverse proxy is used to allow access to all validator participants through a single HTTP endpoint. | ||
| // The following routes are configured for each participant and the Super Validator (SV): | ||
| // - http://[PARTICIPANT].json-ledger-api.localhost:[PORT] -> JSON Ledger API | ||
| // - grpc://[PARTICIPANT].grpc-ledger-api.localhost:[PORT] -> gRPC Ledger API | ||
| // - http://[PARTICIPANT].admin-api.localhost:[PORT] -> Admin API | ||
| // - http://[PARTICIPANT].wallet.localhost:[PORT] -> Wallet API | ||
| // - http://[PARTICIPANT].http-health-check.localhost:[PORT] -> HTTP Health Check | ||
| // - grpc://[PARTICIPANT].grpc-health-check.localhost:[PORT] -> gRPC Health Check | ||
| // | ||
| // To access a participant's endpoints, replace [PARTICIPANT] with the participant's identifier, i.e. `sv`, `participant01`, `participant02`, ... | ||
| // | ||
| // Additionally, the global Scan service is accessible via: | ||
| // - http://scan.localhost:[PORT]/api/scan -> Scan API | ||
| // - http://scan.localhost:[PORT]/registry -> Scan Registry | ||
| // | ||
| // The PORT is the same for all routes and is specified in the input parameters. | ||
| // | ||
| // Note: The maximum number of validators supported is 99, participants are numbered starting from `participant01` through `participant99`. | ||
| func newCanton(ctx context.Context, in *Input) (*Output, error) { | ||
| if in.NumberOfCantonValidators >= 100 { | ||
| return nil, fmt.Errorf("number of validators too high: %d, max is 99", in.NumberOfCantonValidators) | ||
| } | ||
|
|
||
| // Create separate Docker network for Canton stack | ||
| dockerNetwork, err := network.New(ctx, network.WithAttachable()) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
|
|
||
| // Set up Postgres container | ||
| postgresReq := canton.PostgresContainerRequest(in.NumberOfCantonValidators, dockerNetwork.Name) | ||
| _, err = testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ | ||
| ContainerRequest: postgresReq, | ||
| Started: true, | ||
| }) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
|
|
||
| // Set up Canton container | ||
| cantonReq := canton.ContainerRequest(dockerNetwork.Name, in.NumberOfCantonValidators, in.Image) | ||
| _, err = testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ | ||
| ContainerRequest: cantonReq, | ||
| Started: true, | ||
| }) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
|
|
||
| // Set up Splice container | ||
| spliceReq := canton.SpliceContainerRequest(dockerNetwork.Name, in.NumberOfCantonValidators, in.Image) | ||
| _, err = testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ | ||
| ContainerRequest: spliceReq, | ||
| Started: true, | ||
| }) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
|
|
||
| // Set up Nginx container | ||
| nginxReq := canton.NginxContainerRequest(dockerNetwork.Name, in.NumberOfCantonValidators, in.Port) | ||
| nginxContainer, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ | ||
| ContainerRequest: nginxReq, | ||
| Started: true, | ||
| }) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
|
|
||
| host, err := nginxContainer.Host(ctx) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
|
|
||
| return &Output{ | ||
| UseCache: false, | ||
| Type: in.Type, | ||
| Family: FamilyCanton, | ||
| ContainerName: nginxReq.Name, | ||
| Nodes: []*Node{ | ||
| { | ||
| ExternalHTTPUrl: fmt.Sprintf("http://%s:%s", host, in.Port), | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hmm... shouldn't we return here all the URLs mentioned in the top-level comment?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There could potentially be tens, if not hundreds of different endpoints depending on the number of participants requested - not really sure how this fits the notion of The client/Chainlink node needs some elaborate config anyway, since Maybe if we switched the routing up and changed it to
But what to do with the gRPC and global endpoints? |
||
| }, | ||
| }, | ||
| }, nil | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
any reason why these containers shouldn't be part of the default CTF network? or of both its own and the default network, if having a canton-specific Docker network is important for some reason?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought about adding it to the default network as well, but I think that would require some more templating to have the Canton containers connect to each other. Right now they all have assigned simple network aliases like
canton,splice, etc. which would lead to conflicts if two instances were to be spun up in parallel.But I can of course add this, if you think it's worth it!