From 52f8cb5932c00803828ed1a9e7a83458a79d510b Mon Sep 17 00:00:00 2001 From: Jonathan Oppenheimer Date: Fri, 26 Sep 2025 12:37:54 -0400 Subject: [PATCH 1/5] Initial setup for randomized parameters --- tests/fixture/tmpnet/genesis.go | 164 ++++++++++++++++++ .../fixture/tmpnet/genesis_randomized_test.go | 151 ++++++++++++++++ tests/fixture/tmpnet/network.go | 72 ++++++++ 3 files changed, 387 insertions(+) create mode 100644 tests/fixture/tmpnet/genesis_randomized_test.go diff --git a/tests/fixture/tmpnet/genesis.go b/tests/fixture/tmpnet/genesis.go index 5a99c505d008..29ede6eb62de 100644 --- a/tests/fixture/tmpnet/genesis.go +++ b/tests/fixture/tmpnet/genesis.go @@ -7,6 +7,9 @@ import ( "encoding/json" "errors" "math/big" + "math/rand" + "os" + "strconv" "time" "github.com/ava-labs/libevm/core" @@ -20,6 +23,7 @@ import ( "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" "github.com/ava-labs/avalanchego/utils/formatting/address" "github.com/ava-labs/avalanchego/utils/units" + "github.com/ava-labs/avalanchego/vms/components/gas" "github.com/ava-labs/avalanchego/vms/platformvm/reward" ) @@ -191,3 +195,163 @@ func stakersForNodes(networkID uint32, nodes []*Node) ([]genesis.UnparsedStaker, return initialStakers, nil } + +// NewRandomizedTestGenesis creates a test genesis with randomized parameters +// using the ANTITHESIS_RANDOM_SEED environment variable for consistent randomization +// across all containers in antithesis tests. +func NewRandomizedTestGenesis( + networkID uint32, + nodes []*Node, + keysToFund []*secp256k1.PrivateKey, +) (*genesis.UnparsedConfig, error) { + // Get the base genesis config first + config, err := NewTestGenesis(networkID, nodes, keysToFund) + if err != nil { + return nil, stacktrace.Wrap(err) + } + + // Check for antithesis random seed + antithesisSeed := os.Getenv("ANTITHESIS_RANDOM_SEED") + if antithesisSeed == "" { + // No randomization requested, return the original config + return config, nil + } + + // Parse the seed and create a deterministic random source + seed, err := strconv.ParseInt(antithesisSeed, 10, 64) + if err != nil { + return nil, stacktrace.Errorf("failed to parse ANTITHESIS_RANDOM_SEED: %w", err) + } + + // Create a deterministic random source + rng := rand.New(rand.NewSource(seed)) // #nosec G404 + + // Randomize the genesis parameters + if err := randomizeGenesisParams(rng, config); err != nil { + return nil, stacktrace.Errorf("failed to randomize genesis params: %w", err) + } + + return config, nil +} + +// randomizeGenesisParams randomizes various genesis parameters +func randomizeGenesisParams(rng *rand.Rand, config *genesis.UnparsedConfig) error { + // Parse C-Chain genesis to modify it + var cChainGenesis core.Genesis + if err := json.Unmarshal([]byte(config.CChainGenesis), &cChainGenesis); err != nil { + return stacktrace.Errorf("failed to unmarshal C-Chain genesis: %w", err) + } + + // Randomize gas limit (between 50M and 200M) + cChainGenesis.GasLimit = uint64(50_000_000 + rng.Intn(150_000_000)) + + // Randomize initial stake duration (between 12 hours and 48 hours) + minStakeDuration := 12 * 60 * 60 // 12 hours in seconds + maxStakeDuration := 48 * 60 * 60 // 48 hours in seconds + stakeDurationRange := maxStakeDuration - minStakeDuration + config.InitialStakeDuration = uint64(minStakeDuration + rng.Intn(stakeDurationRange)) + + // Randomize initial stake duration offset (between 30 minutes and 3 hours) + minOffset := 30 * 60 // 30 minutes in seconds + maxOffset := 3 * 60 * 60 // 3 hours in seconds + offsetRange := maxOffset - minOffset + config.InitialStakeDurationOffset = uint64(minOffset + rng.Intn(offsetRange)) + + // Serialize the modified C-Chain genesis back + cChainGenesisBytes, err := json.Marshal(&cChainGenesis) + if err != nil { + return stacktrace.Errorf("failed to marshal C-Chain genesis: %w", err) + } + config.CChainGenesis = string(cChainGenesisBytes) + + return nil +} + +// RandomizedParams creates randomized network parameters for testing +// using the ANTITHESIS_RANDOM_SEED environment variable. +func RandomizedParams(rng *rand.Rand, baseParams genesis.Params) genesis.Params { + // Create a copy of the base params + params := baseParams + + // Randomize P-Chain minimum gas price + // Range: 1 to 1000 nAVAX (1 to 1000 * 10^9 wei equivalent) + minPrice := 1 + rng.Intn(1000) + params.TxFeeConfig.DynamicFeeConfig.MinPrice = gas.Price(minPrice) + + // Randomize validator fee minimum price + // Range: 1 to 1000 nAVAX + validatorMinPrice := 1 + rng.Intn(1000) + params.TxFeeConfig.ValidatorFeeConfig.MinPrice = gas.Price(uint64(validatorMinPrice) * units.NanoAvax) + + // Randomize transaction fees + // Base transaction fee: 0.1 to 10 milliAVAX + baseFeeMultiplier := 1 + rng.Intn(100) // 1 to 100 + params.TxFeeConfig.TxFee = uint64(baseFeeMultiplier) * (units.MilliAvax / 10) + + // Create asset transaction fee: 0.5 to 50 milliAVAX + createAssetFeeMultiplier := 5 + rng.Intn(500) // 5 to 500 (0.5 to 50 milliAVAX) + params.TxFeeConfig.CreateAssetTxFee = uint64(createAssetFeeMultiplier) * (units.MilliAvax / 10) + + // Randomize gas capacity and throughput parameters + // Max capacity: 500K to 2M + params.TxFeeConfig.DynamicFeeConfig.MaxCapacity = gas.Gas(500_000 + rng.Intn(1_500_000)) + + // Max per second: 50K to 200K + maxPerSecond := 50_000 + rng.Intn(150_000) + params.TxFeeConfig.DynamicFeeConfig.MaxPerSecond = gas.Gas(maxPerSecond) + + // Target per second: 25% to 75% of max per second + targetRatio := 25 + rng.Intn(51) // 25 to 75 + params.TxFeeConfig.DynamicFeeConfig.TargetPerSecond = gas.Gas(maxPerSecond * targetRatio / 100) + + // Randomize validator fee capacity and target + validatorCapacity := 10_000 + rng.Intn(40_000) // 10K to 50K + params.TxFeeConfig.ValidatorFeeConfig.Capacity = gas.Gas(validatorCapacity) + + // Target: 25% to 75% of capacity + validatorTargetRatio := 25 + rng.Intn(51) // 25 to 75 + params.TxFeeConfig.ValidatorFeeConfig.Target = gas.Gas(validatorCapacity * validatorTargetRatio / 100) + + // Randomize staking parameters + // Min validator stake: 1 to 5 KiloAVAX + minValidatorStakeMultiplier := 1 + rng.Intn(5) + params.StakingConfig.MinValidatorStake = uint64(minValidatorStakeMultiplier) * units.KiloAvax + + // Max validator stake: 2 to 10 MegaAVAX + maxValidatorStakeMultiplier := 2 + rng.Intn(9) + params.StakingConfig.MaxValidatorStake = uint64(maxValidatorStakeMultiplier) * units.MegaAvax + + // Min delegator stake: 5 to 100 AVAX + minDelegatorStakeMultiplier := 5 + rng.Intn(96) + params.StakingConfig.MinDelegatorStake = uint64(minDelegatorStakeMultiplier) * units.Avax + + // Min delegation fee: 1% to 10% + minDelegationFeePercent := 1 + rng.Intn(10) + params.StakingConfig.MinDelegationFee = uint32(minDelegationFeePercent * 10000) // Convert to basis points + + return params +} + +// GetRandomizedParams returns randomized network parameters if ANTITHESIS_RANDOM_SEED is set, +// otherwise returns the original parameters for the given network. +func GetRandomizedParams(networkID uint32) genesis.Params { + baseParams := genesis.Params{ + TxFeeConfig: genesis.GetTxFeeConfig(networkID), + StakingConfig: genesis.GetStakingConfig(networkID), + } + + // Check for antithesis random seed + antithesisSeed := os.Getenv("ANTITHESIS_RANDOM_SEED") + if antithesisSeed == "" { + return baseParams + } + + // Parse the seed and create a deterministic random source + seed, err := strconv.ParseInt(antithesisSeed, 10, 64) + if err != nil { + return baseParams + } + + rng := rand.New(rand.NewSource(seed)) // #nosec G404 + return RandomizedParams(rng, baseParams) +} diff --git a/tests/fixture/tmpnet/genesis_randomized_test.go b/tests/fixture/tmpnet/genesis_randomized_test.go new file mode 100644 index 000000000000..d329d5a1ed3f --- /dev/null +++ b/tests/fixture/tmpnet/genesis_randomized_test.go @@ -0,0 +1,151 @@ +// Copyright (C) 2019-2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package tmpnet + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/ava-labs/avalanchego/genesis" +) + +func TestNewRandomizedTestGenesis(t *testing.T) { + require := require.New(t) + + // Test without ANTITHESIS_RANDOM_SEED - should behave like normal genesis + nodes := NewNodesOrPanic(5) + keys, err := NewPrivateKeys(3) + require.NoError(err) + + networkID := uint32(98765) // Use a valid test network ID + + // Normal genesis without randomization + originalGenesis, err := NewTestGenesis(networkID, nodes, keys) + require.NoError(err) + + // Randomized genesis without env var should be the same + randomizedGenesis, err := NewRandomizedTestGenesis(networkID, nodes, keys) + require.NoError(err) + + // Should behave the same when no seed is set + require.Equal(originalGenesis.NetworkID, randomizedGenesis.NetworkID) + require.Equal(len(originalGenesis.Allocations), len(randomizedGenesis.Allocations)) + + // Test with ANTITHESIS_RANDOM_SEED set + t.Setenv("ANTITHESIS_RANDOM_SEED", "12345") + + randomizedGenesis2, err := NewRandomizedTestGenesis(networkID, nodes, keys) + require.NoError(err) + + // Should still have same basic structure + require.Equal(originalGenesis.NetworkID, randomizedGenesis2.NetworkID) + require.Equal(len(originalGenesis.Allocations), len(randomizedGenesis2.Allocations)) + + // But may have different timing parameters + require.NotEqual(randomizedGenesis.InitialStakeDuration, randomizedGenesis2.InitialStakeDuration) + require.NotEqual(randomizedGenesis.InitialStakeDurationOffset, randomizedGenesis2.InitialStakeDurationOffset) +} + +func TestRandomizedParams(t *testing.T) { + require := require.New(t) + + networkID := uint32(98765) // Use a valid test network ID + + // Test with local params as base + baseParams := genesis.LocalParams + + t.Run("without_env_var", func(t *testing.T) { + // Ensure no env var is set for this subtest + t.Setenv("ANTITHESIS_RANDOM_SEED", "") + + params := GetRandomizedParams(networkID) + + // Should return original config when no env var + require.Equal(baseParams.TxFeeConfig.TxFee, params.TxFee) + require.Equal(baseParams.StakingConfig.MinValidatorStake, params.MinValidatorStake) + }) + + t.Run("with_env_var", func(t *testing.T) { + // Test with environment variable + t.Setenv("ANTITHESIS_RANDOM_SEED", "54321") + + randomizedParams := GetRandomizedParams(networkID) + + // Should have randomized values + require.NotEqual(baseParams.TxFeeConfig.DynamicFeeConfig.MinPrice, randomizedParams.DynamicFeeConfig.MinPrice) + require.NotEqual(baseParams.StakingConfig.MinValidatorStake, randomizedParams.MinValidatorStake) + + // Test determinism - same seed should produce same results + randomizedParams2 := GetRandomizedParams(networkID) + + require.Equal(randomizedParams.DynamicFeeConfig.MinPrice, randomizedParams2.DynamicFeeConfig.MinPrice) + require.Equal(randomizedParams.MinValidatorStake, randomizedParams2.MinValidatorStake) + }) +} + +func TestRandomizedParamsValidation(t *testing.T) { + require := require.New(t) + + networkID := uint32(98765) + + // Test with valid seeds + testCases := []struct { + seed string + name string + }{ + {"123456789", "positive integer"}, + {"0", "zero"}, + {"999999999999", "large number"}, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + t.Setenv("ANTITHESIS_RANDOM_SEED", tc.seed) + + // Should not panic or error + params := GetRandomizedParams(networkID) + + // Should have valid randomized values + require.Greater(params.DynamicFeeConfig.MinPrice, genesis.LocalParams.DynamicFeeConfig.MinPrice) + require.Greater(params.MinValidatorStake, uint64(0)) + }) + } +} + +func TestRandomizedGenesisWithDifferentSeeds(t *testing.T) { + require := require.New(t) + + networkID := uint32(98765) + nodes := NewNodesOrPanic(3) + keys, err := NewPrivateKeys(2) + require.NoError(err) + + // Test with different seeds produce different results + seeds := []string{"111", "222", "333"} + var allParams []genesis.Params + + for _, seed := range seeds { + t.Setenv("ANTITHESIS_RANDOM_SEED", seed) + + // Test randomized params + params := GetRandomizedParams(networkID) + allParams = append(allParams, params) + + // Test randomized genesis creation works + genesis, err := NewRandomizedTestGenesis(networkID, nodes, keys) + require.NoError(err) + require.NotNil(genesis) + require.Equal(networkID, genesis.NetworkID) + } + + // Verify different seeds produce different values (at least one pair should be different) + pricesAllSame := allParams[0].DynamicFeeConfig.MinPrice == allParams[1].DynamicFeeConfig.MinPrice && + allParams[1].DynamicFeeConfig.MinPrice == allParams[2].DynamicFeeConfig.MinPrice + require.False(pricesAllSame, "All P-chain min gas prices should not be the same") + + stakesAllSame := allParams[0].MinValidatorStake == allParams[1].MinValidatorStake && + allParams[1].MinValidatorStake == allParams[2].MinValidatorStake + require.False(stakesAllSame, "All min validator stakes should not be the same") +} diff --git a/tests/fixture/tmpnet/network.go b/tests/fixture/tmpnet/network.go index 9623a01c14a0..e425411cd300 100644 --- a/tests/fixture/tmpnet/network.go +++ b/tests/fixture/tmpnet/network.go @@ -294,6 +294,13 @@ func (n *Network) EnsureDefaultConfig(ctx context.Context, log logging.Logger) e return stacktrace.Wrap(errMissingRuntimeConfig) } + // Apply randomized network parameters if ANTITHESIS_RANDOM_SEED is set + if antithesisSeed := os.Getenv("ANTITHESIS_RANDOM_SEED"); antithesisSeed != "" { + if err := n.applyRandomizedFlags(log, antithesisSeed); err != nil { + return stacktrace.Wrap(err) + } + } + return nil } @@ -362,6 +369,11 @@ func (n *Network) DefaultGenesis() (*genesis.UnparsedConfig, error) { } keysToFund = append(keysToFund, n.PreFundedKeys...) + // Check if we should use randomized genesis for antithesis testing + if os.Getenv("ANTITHESIS_RANDOM_SEED") != "" { + return NewRandomizedTestGenesis(defaultNetworkID, n.Nodes, keysToFund) + } + return NewTestGenesis(defaultNetworkID, n.Nodes, keysToFund) } @@ -1132,3 +1144,63 @@ func MetricsLinkForNetwork(networkUUID string, startTime string, endTime string) endTime, ) } + +// applyRandomizedFlags applies randomized network parameters using the provided seed +func (n *Network) applyRandomizedFlags(log logging.Logger, antithesisSeed string) error { + // Validate the seed format (the actual randomization is done in GetRandomized* functions) + if _, err := strconv.ParseInt(antithesisSeed, 10, 64); err != nil { + log.Warn("failed to parse ANTITHESIS_RANDOM_SEED, skipping randomization", zap.Error(err)) + return nil + } + + // Get randomized configuration - single call instead of two separate functions + randomizedParams := GetRandomizedParams(n.GetNetworkID()) + + // Apply randomized config using structured mappings + configMappings := []struct { + flagKey string + value uint64 + }{ + // Dynamic fee parameters + {config.DynamicFeesMinGasPriceKey, uint64(randomizedParams.DynamicFeeConfig.MinPrice)}, + {config.DynamicFeesMaxGasCapacityKey, uint64(randomizedParams.DynamicFeeConfig.MaxCapacity)}, + {config.DynamicFeesMaxGasPerSecondKey, uint64(randomizedParams.DynamicFeeConfig.MaxPerSecond)}, + {config.DynamicFeesTargetGasPerSecondKey, uint64(randomizedParams.DynamicFeeConfig.TargetPerSecond)}, + {config.DynamicFeesExcessConversionConstantKey, uint64(randomizedParams.DynamicFeeConfig.ExcessConversionConstant)}, + + // Validator fee parameters + {config.ValidatorFeesCapacityKey, uint64(randomizedParams.ValidatorFeeConfig.Capacity)}, + {config.ValidatorFeesTargetKey, uint64(randomizedParams.ValidatorFeeConfig.Target)}, + {config.ValidatorFeesMinPriceKey, uint64(randomizedParams.ValidatorFeeConfig.MinPrice)}, + {config.ValidatorFeesExcessConversionConstantKey, uint64(randomizedParams.ValidatorFeeConfig.ExcessConversionConstant)}, + + // Static fee parameters + {config.TxFeeKey, randomizedParams.TxFee}, + {config.CreateAssetTxFeeKey, randomizedParams.CreateAssetTxFee}, + + // Staking parameters + {config.MinValidatorStakeKey, randomizedParams.MinValidatorStake}, + {config.MaxValidatorStakeKey, randomizedParams.MaxValidatorStake}, + {config.MinDelegatorStakeKey, randomizedParams.MinDelegatorStake}, + {config.MinDelegatorFeeKey, uint64(randomizedParams.MinDelegationFee)}, + } + + // Apply all mappings + for _, mapping := range configMappings { + n.DefaultFlags[mapping.flagKey] = strconv.FormatUint(mapping.value, 10) + } + + log.Info("applied randomized network parameters", + zap.String("seed", antithesisSeed), + zap.Uint64("minGasPrice", uint64(randomizedParams.DynamicFeeConfig.MinPrice)), + zap.Uint64("validatorMinPrice", uint64(randomizedParams.ValidatorFeeConfig.MinPrice)), + zap.Uint64("txFee", randomizedParams.TxFee), + zap.Uint64("createAssetTxFee", randomizedParams.CreateAssetTxFee), + zap.Uint64("minValidatorStake", randomizedParams.MinValidatorStake), + zap.Uint64("maxValidatorStake", randomizedParams.MaxValidatorStake), + zap.Uint64("minDelegatorStake", randomizedParams.MinDelegatorStake), + zap.Uint32("minDelegationFee", randomizedParams.MinDelegationFee), + ) + + return nil +} From 2f991e6ec065b83c547002c093f185eaa34ae17d Mon Sep 17 00:00:00 2001 From: Jonathan Oppenheimer Date: Fri, 26 Sep 2025 13:24:54 -0400 Subject: [PATCH 2/5] lint --- tests/fixture/tmpnet/genesis_randomized_test.go | 10 +++++----- tests/fixture/tmpnet/network.go | 16 +++++----------- 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/tests/fixture/tmpnet/genesis_randomized_test.go b/tests/fixture/tmpnet/genesis_randomized_test.go index d329d5a1ed3f..307a1771f374 100644 --- a/tests/fixture/tmpnet/genesis_randomized_test.go +++ b/tests/fixture/tmpnet/genesis_randomized_test.go @@ -19,7 +19,7 @@ func TestNewRandomizedTestGenesis(t *testing.T) { keys, err := NewPrivateKeys(3) require.NoError(err) - networkID := uint32(98765) // Use a valid test network ID + networkID := uint32(98765) // Normal genesis without randomization originalGenesis, err := NewTestGenesis(networkID, nodes, keys) @@ -31,7 +31,7 @@ func TestNewRandomizedTestGenesis(t *testing.T) { // Should behave the same when no seed is set require.Equal(originalGenesis.NetworkID, randomizedGenesis.NetworkID) - require.Equal(len(originalGenesis.Allocations), len(randomizedGenesis.Allocations)) + require.Len(randomizedGenesis.Allocations, len(originalGenesis.Allocations)) // Test with ANTITHESIS_RANDOM_SEED set t.Setenv("ANTITHESIS_RANDOM_SEED", "12345") @@ -41,7 +41,7 @@ func TestNewRandomizedTestGenesis(t *testing.T) { // Should still have same basic structure require.Equal(originalGenesis.NetworkID, randomizedGenesis2.NetworkID) - require.Equal(len(originalGenesis.Allocations), len(randomizedGenesis2.Allocations)) + require.Len(randomizedGenesis2.Allocations, len(originalGenesis.Allocations)) // But may have different timing parameters require.NotEqual(randomizedGenesis.InitialStakeDuration, randomizedGenesis2.InitialStakeDuration) @@ -109,7 +109,7 @@ func TestRandomizedParamsValidation(t *testing.T) { // Should have valid randomized values require.Greater(params.DynamicFeeConfig.MinPrice, genesis.LocalParams.DynamicFeeConfig.MinPrice) - require.Greater(params.MinValidatorStake, uint64(0)) + require.Positive(params.MinValidatorStake) }) } } @@ -124,7 +124,7 @@ func TestRandomizedGenesisWithDifferentSeeds(t *testing.T) { // Test with different seeds produce different results seeds := []string{"111", "222", "333"} - var allParams []genesis.Params + allParams := make([]genesis.Params, 0, len(seeds)) for _, seed := range seeds { t.Setenv("ANTITHESIS_RANDOM_SEED", seed) diff --git a/tests/fixture/tmpnet/network.go b/tests/fixture/tmpnet/network.go index e425411cd300..31d7fbca6785 100644 --- a/tests/fixture/tmpnet/network.go +++ b/tests/fixture/tmpnet/network.go @@ -296,9 +296,7 @@ func (n *Network) EnsureDefaultConfig(ctx context.Context, log logging.Logger) e // Apply randomized network parameters if ANTITHESIS_RANDOM_SEED is set if antithesisSeed := os.Getenv("ANTITHESIS_RANDOM_SEED"); antithesisSeed != "" { - if err := n.applyRandomizedFlags(log, antithesisSeed); err != nil { - return stacktrace.Wrap(err) - } + n.applyRandomizedFlags(log, antithesisSeed) } return nil @@ -1146,17 +1144,15 @@ func MetricsLinkForNetwork(networkUUID string, startTime string, endTime string) } // applyRandomizedFlags applies randomized network parameters using the provided seed -func (n *Network) applyRandomizedFlags(log logging.Logger, antithesisSeed string) error { - // Validate the seed format (the actual randomization is done in GetRandomized* functions) +func (n *Network) applyRandomizedFlags(log logging.Logger, antithesisSeed string) { + // Validate the seed format (the actual randomization is done in GetRandomizedParams) if _, err := strconv.ParseInt(antithesisSeed, 10, 64); err != nil { log.Warn("failed to parse ANTITHESIS_RANDOM_SEED, skipping randomization", zap.Error(err)) - return nil + return } - // Get randomized configuration - single call instead of two separate functions + // TODO(jonathanoppenheimer): is there a better way to apply these values? randomizedParams := GetRandomizedParams(n.GetNetworkID()) - - // Apply randomized config using structured mappings configMappings := []struct { flagKey string value uint64 @@ -1201,6 +1197,4 @@ func (n *Network) applyRandomizedFlags(log logging.Logger, antithesisSeed string zap.Uint64("minDelegatorStake", randomizedParams.MinDelegatorStake), zap.Uint32("minDelegationFee", randomizedParams.MinDelegationFee), ) - - return nil } From d264d49f342d54e0db9a690b66de344e9758887a Mon Sep 17 00:00:00 2001 From: Jonathan Oppenheimer Date: Fri, 26 Sep 2025 13:39:41 -0400 Subject: [PATCH 3/5] genralize network id --- tests/fixture/tmpnet/genesis_randomized_test.go | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/tests/fixture/tmpnet/genesis_randomized_test.go b/tests/fixture/tmpnet/genesis_randomized_test.go index 307a1771f374..5e36c76e5b93 100644 --- a/tests/fixture/tmpnet/genesis_randomized_test.go +++ b/tests/fixture/tmpnet/genesis_randomized_test.go @@ -11,6 +11,8 @@ import ( "github.com/ava-labs/avalanchego/genesis" ) +const networkID = uint32(147147) + func TestNewRandomizedTestGenesis(t *testing.T) { require := require.New(t) @@ -19,8 +21,6 @@ func TestNewRandomizedTestGenesis(t *testing.T) { keys, err := NewPrivateKeys(3) require.NoError(err) - networkID := uint32(98765) - // Normal genesis without randomization originalGenesis, err := NewTestGenesis(networkID, nodes, keys) require.NoError(err) @@ -51,8 +51,6 @@ func TestNewRandomizedTestGenesis(t *testing.T) { func TestRandomizedParams(t *testing.T) { require := require.New(t) - networkID := uint32(98765) // Use a valid test network ID - // Test with local params as base baseParams := genesis.LocalParams @@ -88,8 +86,6 @@ func TestRandomizedParams(t *testing.T) { func TestRandomizedParamsValidation(t *testing.T) { require := require.New(t) - networkID := uint32(98765) - // Test with valid seeds testCases := []struct { seed string @@ -117,7 +113,6 @@ func TestRandomizedParamsValidation(t *testing.T) { func TestRandomizedGenesisWithDifferentSeeds(t *testing.T) { require := require.New(t) - networkID := uint32(98765) nodes := NewNodesOrPanic(3) keys, err := NewPrivateKeys(2) require.NoError(err) From f2c0050877bb46b32ad878893cca2d90ac85b611 Mon Sep 17 00:00:00 2001 From: Jonathan Oppenheimer Date: Fri, 26 Sep 2025 13:58:25 -0400 Subject: [PATCH 4/5] enable randomization in CI --- .github/workflows/ci.yml | 6 ++++++ .github/workflows/publish_antithesis_images.yml | 4 ++++ .github/workflows/trigger-antithesis-avalanchego.yml | 6 ++++++ .github/workflows/trigger-antithesis-xsvm.yml | 6 ++++++ 4 files changed, 22 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dbfe906bd039..d546657f589d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -216,6 +216,9 @@ jobs: - name: Check image build for avalanchego test setup shell: bash run: ./scripts/run_task.sh test-build-antithesis-images-avalanchego + env: + # Use GitHub run ID as a consistent random seed for CI testing + ANTITHESIS_RANDOM_SEED: ${{ github.run_id }} test_build_antithesis_xsvm_images: name: Build Antithesis xsvm images runs-on: ubuntu-latest @@ -225,6 +228,9 @@ jobs: - name: Check image build for xsvm test setup shell: bash run: ./scripts/run_task.sh test-build-antithesis-images-xsvm + env: + # Use GitHub run ID as a consistent random seed for CI testing + ANTITHESIS_RANDOM_SEED: ${{ github.run_id }} e2e_bootstrap_monitor: name: Run bootstrap monitor e2e tests runs-on: ubuntu-latest diff --git a/.github/workflows/publish_antithesis_images.yml b/.github/workflows/publish_antithesis_images.yml index 9506126b698a..48704b5b8d7b 100644 --- a/.github/workflows/publish_antithesis_images.yml +++ b/.github/workflows/publish_antithesis_images.yml @@ -36,9 +36,13 @@ jobs: env: IMAGE_PREFIX: ${{ env.REGISTRY }}/${{ env.REPOSITORY }} IMAGE_TAG: ${{ github.event.inputs.image_tag || 'latest' }} + # Use GitHub run ID for deterministic randomization across Antithesis containers + ANTITHESIS_RANDOM_SEED: ${{ github.run_id }} - name: Build and push images for xsvm test setup run: ./scripts/run_task.sh build-antithesis-images-xsvm env: IMAGE_PREFIX: ${{ env.REGISTRY }}/${{ env.REPOSITORY }} IMAGE_TAG: ${{ github.event.inputs.image_tag || 'latest' }} + # Use GitHub run ID for deterministic randomization across Antithesis containers + ANTITHESIS_RANDOM_SEED: ${{ github.run_id }} diff --git a/.github/workflows/trigger-antithesis-avalanchego.yml b/.github/workflows/trigger-antithesis-avalanchego.yml index d0dd75793f8b..c506c0fffd80 100644 --- a/.github/workflows/trigger-antithesis-avalanchego.yml +++ b/.github/workflows/trigger-antithesis-avalanchego.yml @@ -19,6 +19,11 @@ on: default: latest required: true type: string + random_seed: + description: 'Random seed for genesis randomization (leave empty for default config)' + default: '' + required: false + type: string jobs: antithesis_avalanchego: @@ -39,3 +44,4 @@ jobs: additional_parameters: |- custom.duration=${{ github.event.inputs.duration || '7.5' }} custom.workload=avalanchego + ${{ github.event.inputs.random_seed && format('custom.antithesis_random_seed={0}', github.event.inputs.random_seed) || '' }} diff --git a/.github/workflows/trigger-antithesis-xsvm.yml b/.github/workflows/trigger-antithesis-xsvm.yml index e5efddeb4b2f..1abe9edb3a19 100644 --- a/.github/workflows/trigger-antithesis-xsvm.yml +++ b/.github/workflows/trigger-antithesis-xsvm.yml @@ -19,6 +19,11 @@ on: default: latest required: true type: string + random_seed: + description: 'Random seed for genesis randomization (leave empty for default config)' + default: '' + required: false + type: string jobs: antithesis_xsvm: @@ -39,3 +44,4 @@ jobs: additional_parameters: |- custom.duration=${{ github.event.inputs.duration || '7.5' }} custom.workload=xsvm + ${{ github.event.inputs.random_seed && format('custom.antithesis_random_seed={0}', github.event.inputs.random_seed) || '' }} From 8f02675b4c1b71bd41df6234c4e50aafe9ad6667 Mon Sep 17 00:00:00 2001 From: Jonathan Oppenheimer Date: Fri, 26 Sep 2025 14:02:55 -0400 Subject: [PATCH 5/5] Update tests/fixture/tmpnet/genesis.go Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Jonathan Oppenheimer <147infiniti@gmail.com> --- tests/fixture/tmpnet/genesis.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fixture/tmpnet/genesis.go b/tests/fixture/tmpnet/genesis.go index 29ede6eb62de..fcf85f4657d7 100644 --- a/tests/fixture/tmpnet/genesis.go +++ b/tests/fixture/tmpnet/genesis.go @@ -276,7 +276,7 @@ func RandomizedParams(rng *rand.Rand, baseParams genesis.Params) genesis.Params // Randomize P-Chain minimum gas price // Range: 1 to 1000 nAVAX (1 to 1000 * 10^9 wei equivalent) minPrice := 1 + rng.Intn(1000) - params.TxFeeConfig.DynamicFeeConfig.MinPrice = gas.Price(minPrice) + params.TxFeeConfig.DynamicFeeConfig.MinPrice = gas.Price(uint64(minPrice) * units.NanoAvax) // Randomize validator fee minimum price // Range: 1 to 1000 nAVAX