diff --git a/testutil/compose/compose/main.go b/testutil/compose/compose/main.go index a1e1a48d6..9d325e9ae 100644 --- a/testutil/compose/compose/main.go +++ b/testutil/compose/compose/main.go @@ -149,12 +149,14 @@ func newNewCmd() *cobra.Command { buildLocal := cmd.Flags().Bool("build-local", conf.BuildLocal, "Enables building a local charon binary from source. Note this requires the CHARON_REPO env var.") beaconNode := cmd.Flags().String("beacon-node", conf.BeaconNode, "Beacon node URL endpoint or 'mock' for simnet.") splitKeys := cmd.Flags().String("split-keys-dir", conf.SplitKeysDir, "Directory containing keys to split for keygen==create, or empty not to split.") + featureSet := cmd.Flags().String("feature-set", conf.FeatureSet, "Minimum feature set to enable: alpha, beta, stable") cmd.RunE = func(cmd *cobra.Command, _ []string) error { conf.KeyGen = compose.KeyGen(*keygen) conf.BuildLocal = *buildLocal conf.BeaconNode = *beaconNode conf.SplitKeysDir = *splitKeys + conf.FeatureSet = *featureSet ctx := log.WithTopic(cmd.Context(), "new") if err := compose.New(ctx, *dir, conf); err != nil { diff --git a/testutil/compose/config.go b/testutil/compose/config.go index 457698000..22224c3c2 100644 --- a/testutil/compose/config.go +++ b/testutil/compose/config.go @@ -25,6 +25,7 @@ const ( defaultNumVals = 1 defaultNumNodes = 4 defaultThreshold = 3 + defaultFeatureSet = "alpha" charonImage = "ghcr.io/obolnetwork/charon" localBinary = "/compose/charon" @@ -95,6 +96,9 @@ type Config struct { // VCs define the types of validator clients to use. VCs []vcType `json:"validator_clients"` + + // FeatureSet defines the minimum feature set to enable. + FeatureSet string `json:"feature_set"` } // entrypoint returns the path to the charon binary based on the BuildLocal field. @@ -116,8 +120,8 @@ func NewDefaultConfig() Config { ImageTag: defaultImageTag, VCs: []vcType{vcTeku, vcLighthouse, vcMock}, KeyGen: defaultKeyGen, - SplitKeysDir: "", BeaconNode: defaultBeaconNode, Step: stepDefined, + FeatureSet: defaultFeatureSet, } } diff --git a/testutil/compose/define.go b/testutil/compose/define.go index 56ef38c33..ed7d9bfbe 100644 --- a/testutil/compose/define.go +++ b/testutil/compose/define.go @@ -106,7 +106,7 @@ func Define(ctx context.Context, dir string) error { } } - if !noPull && conf.ImageTag == "latest" { + if !noPull && !conf.BuildLocal && conf.ImageTag == "latest" { if err := pullLatest(ctx); err != nil { return err } diff --git a/testutil/compose/lock.go b/testutil/compose/lock.go index 69b8ab2f7..d23673f45 100644 --- a/testutil/compose/lock.go +++ b/testutil/compose/lock.go @@ -71,7 +71,7 @@ func Lock(ctx context.Context, dir string) error { var nodes []node for i := 0; i < conf.NumNodes; i++ { - n := node{EnvVars: newNodeEnvs(i, true, conf.BeaconNode)} + n := node{EnvVars: newNodeEnvs(i, true, conf.BeaconNode, conf.FeatureSet)} nodes = append(nodes, n) } @@ -99,7 +99,7 @@ func Lock(ctx context.Context, dir string) error { } // newNodeEnvs returns the default node environment variable to run a charon docker container. -func newNodeEnvs(index int, validatorMock bool, beaconNode string) []kv { +func newNodeEnvs(index int, validatorMock bool, beaconNode string, featureSet string) []kv { beaconMock := false if beaconNode == "mock" { beaconMock = true @@ -122,6 +122,7 @@ func newNodeEnvs(index int, validatorMock bool, beaconNode string) []kv { {"simnet_validator_mock", fmt.Sprintf(`"%v"`, validatorMock)}, {"simnet_beacon_mock", fmt.Sprintf(`"%v"`, beaconMock)}, {"log_level", "debug"}, + {"feature_set", featureSet}, } } diff --git a/testutil/compose/run.go b/testutil/compose/run.go index d79076083..3fd074160 100644 --- a/testutil/compose/run.go +++ b/testutil/compose/run.go @@ -17,7 +17,9 @@ package compose import ( "context" + "fmt" "io/fs" + "strings" "github.com/obolnetwork/charon/app/errors" "github.com/obolnetwork/charon/app/log" @@ -42,11 +44,11 @@ func Run(ctx context.Context, dir string) error { vcs []vc ) for i := 0; i < conf.NumNodes; i++ { - n := node{EnvVars: newNodeEnvs(i, true, conf.BeaconNode)} + n := node{EnvVars: newNodeEnvs(i, true, conf.BeaconNode, conf.FeatureSet)} nodes = append(nodes, n) typ := conf.VCs[i%len(conf.VCs)] - vcs = append(vcs, vcByType[typ]) + vcs = append(vcs, getVC(typ, i)) } data := tmplData{ @@ -66,19 +68,27 @@ func Run(ctx context.Context, dir string) error { return writeDockerCompose(dir, data) } -var vcByType = map[vcType]vc{ - vcLighthouse: { - Label: string(vcLighthouse), - Build: "lighthouse", - }, - vcTeku: { - Label: string(vcTeku), - Image: "consensys/teku:latest", - Command: `| +// getVC returns the validator client template data for the provided type and index. +func getVC(typ vcType, nodeIdx int) vc { + vcByType := map[vcType]vc{ + vcLighthouse: { + Label: string(vcLighthouse), + Build: "lighthouse", + }, + vcTeku: { + Label: string(vcTeku), + Image: "consensys/teku:latest", + Command: `| validator-client --network=auto - --beacon-node-api-endpoint="http://node1:16002" - --validator-keys="/compose/node1:/compose/node1" + --beacon-node-api-endpoint="http://node{{nodeIdx}}:16002" + --validator-keys="/compose/node{{nodeIdx}}:/compose/node{{nodeIdx}}" --validators-proposer-default-fee-recipient="0x0000000000000000000000000000000000000000"`, - }, + }, + } + + resp := vcByType[typ] + resp.Command = strings.ReplaceAll(resp.Command, "{{nodeIdx}}", fmt.Sprint(nodeIdx)) + + return resp } diff --git a/testutil/compose/testdata/TestNewDefaultConfig.golden b/testutil/compose/testdata/TestNewDefaultConfig.golden index 5f42af49c..ca513469d 100644 --- a/testutil/compose/testdata/TestNewDefaultConfig.golden +++ b/testutil/compose/testdata/TestNewDefaultConfig.golden @@ -13,5 +13,6 @@ "teku", "lighthouse", "mock" - ] + ], + "feature_set": "alpha" } \ No newline at end of file diff --git a/testutil/compose/testdata/TestRunCompose.golden b/testutil/compose/testdata/TestRunCompose.golden index aa55c5852..fdbd7a30f 100644 --- a/testutil/compose/testdata/TestRunCompose.golden +++ b/testutil/compose/testdata/TestRunCompose.golden @@ -27,6 +27,7 @@ services: CHARON_SIMNET_VALIDATOR_MOCK: "true" CHARON_SIMNET_BEACON_MOCK: "true" CHARON_LOG_LEVEL: debug + CHARON_FEATURE_SET: alpha node1: <<: *node-base @@ -46,6 +47,7 @@ services: CHARON_SIMNET_VALIDATOR_MOCK: "true" CHARON_SIMNET_BEACON_MOCK: "true" CHARON_LOG_LEVEL: debug + CHARON_FEATURE_SET: alpha node2: <<: *node-base @@ -65,6 +67,7 @@ services: CHARON_SIMNET_VALIDATOR_MOCK: "true" CHARON_SIMNET_BEACON_MOCK: "true" CHARON_LOG_LEVEL: debug + CHARON_FEATURE_SET: alpha node3: <<: *node-base @@ -84,6 +87,7 @@ services: CHARON_SIMNET_VALIDATOR_MOCK: "true" CHARON_SIMNET_BEACON_MOCK: "true" CHARON_LOG_LEVEL: debug + CHARON_FEATURE_SET: alpha bootnode: <<: *node-base @@ -102,8 +106,8 @@ services: command: | validator-client --network=auto - --beacon-node-api-endpoint="http://node1:16002" - --validator-keys="/compose/node1:/compose/node1" + --beacon-node-api-endpoint="http://node0:16002" + --validator-keys="/compose/node0:/compose/node0" --validators-proposer-default-fee-recipient="0x0000000000000000000000000000000000000000" networks: [compose] depends_on: [node0] @@ -126,8 +130,8 @@ services: command: | validator-client --network=auto - --beacon-node-api-endpoint="http://node1:16002" - --validator-keys="/compose/node1:/compose/node1" + --beacon-node-api-endpoint="http://node3:16002" + --validator-keys="/compose/node3:/compose/node3" --validators-proposer-default-fee-recipient="0x0000000000000000000000000000000000000000" networks: [compose] depends_on: [node3]