github.com/smartcontractkit/chainlink-testing-framework/libs@v0.0.0-20240227141906-ec710b4eb1a3/docker/test_env/eth2_common.go (about) 1 package test_env 2 3 import ( 4 "context" 5 _ "embed" 6 "errors" 7 "fmt" 8 "testing" 9 "time" 10 11 "github.com/ethereum/go-ethereum/common" 12 "github.com/pelletier/go-toml/v2" 13 "github.com/rs/zerolog" 14 tc "github.com/testcontainers/testcontainers-go" 15 16 "github.com/smartcontractkit/chainlink-testing-framework/libs/blockchain" 17 ) 18 19 var ( 20 ETH2_EXECUTION_PORT = "8551" 21 WALLET_PASSWORD = "password" 22 VALIDATOR_WALLET_PASSWORD_FILE_INSIDE_CONTAINER = fmt.Sprintf("%s/wallet_password.txt", GENERATED_DATA_DIR_INSIDE_CONTAINER) 23 ACCOUNT_PASSWORD_FILE_INSIDE_CONTAINER = fmt.Sprintf("%s/account_password.txt", GENERATED_DATA_DIR_INSIDE_CONTAINER) 24 ACCOUNT_KEYSTORE_FILE_INSIDE_CONTAINER = fmt.Sprintf("%s/account_key", KEYSTORE_DIR_LOCATION_INSIDE_CONTAINER) 25 KEYSTORE_DIR_LOCATION_INSIDE_CONTAINER = fmt.Sprintf("%s/keystore", GENERATED_DATA_DIR_INSIDE_CONTAINER) 26 GENERATED_VALIDATOR_KEYS_DIR_INSIDE_CONTAINER = "/keys" 27 NODE_0_DIR_INSIDE_CONTAINER = fmt.Sprintf("%s/node-0", GENERATED_VALIDATOR_KEYS_DIR_INSIDE_CONTAINER) 28 GENERATED_DATA_DIR_INSIDE_CONTAINER = "/data/custom_config_data" 29 JWT_SECRET_FILE_LOCATION_INSIDE_CONTAINER = fmt.Sprintf("%s/jwtsecret", GENERATED_DATA_DIR_INSIDE_CONTAINER) // #nosec G101 30 VALIDATOR_BIP39_MNEMONIC = "giant issue aisle success illegal bike spike question tent bar rely arctic volcano long crawl hungry vocal artwork sniff fantasy very lucky have athlete" 31 ) 32 33 type EthereumChainConfig struct { 34 SecondsPerSlot int `json:"seconds_per_slot" toml:"seconds_per_slot"` 35 SlotsPerEpoch int `json:"slots_per_epoch" toml:"slots_per_epoch"` 36 GenesisDelay int `json:"genesis_delay" toml:"genesis_delay"` 37 ValidatorCount int `json:"validator_count" toml:"validator_count"` 38 ChainID int `json:"chain_id" toml:"chain_id"` 39 genesisTimestamp int // this is not serialized 40 AddressesToFund []string `json:"addresses_to_fund" toml:"addresses_to_fund"` 41 } 42 43 //go:embed example/default_ethereum_env.toml 44 var defaultEthereumChainConfig []byte 45 46 func (c *EthereumChainConfig) Default() error { 47 wrapper := struct { 48 EthereumNetwork *EthereumNetwork `toml:"PrivateEthereumNetwork"` 49 }{} 50 if err := toml.Unmarshal(defaultEthereumChainConfig, &wrapper); err != nil { 51 return fmt.Errorf("error unmarshaling ethereum network config: %w", err) 52 } 53 54 if wrapper.EthereumNetwork == nil { 55 return errors.New("[EthereumNetwork] was not present in default TOML file") 56 } 57 58 *c = *wrapper.EthereumNetwork.EthereumChainConfig 59 60 if c.genesisTimestamp == 0 { 61 c.GenerateGenesisTimestamp() 62 } 63 64 return nil 65 } 66 67 func GetDefaultChainConfig() EthereumChainConfig { 68 config := EthereumChainConfig{} 69 if err := config.Default(); err != nil { 70 panic(err) 71 } 72 return config 73 } 74 75 func (c *EthereumChainConfig) Validate(logger zerolog.Logger, consensusType ConsensusType) error { 76 if c.ChainID < 1 { 77 return fmt.Errorf("chain id must be >= 0") 78 } 79 80 if consensusType == ConsensusType_PoW { 81 return nil 82 } 83 84 if c.ValidatorCount < 4 { 85 return fmt.Errorf("validator count must be >= 4") 86 } 87 if c.SecondsPerSlot < 3 { 88 return fmt.Errorf("seconds per slot must be >= 3") 89 } 90 if c.SlotsPerEpoch < 2 { 91 return fmt.Errorf("slots per epoch must be >= 1") 92 } 93 if c.GenesisDelay < 10 { 94 return fmt.Errorf("genesis delay must be >= 10") 95 } 96 if c.genesisTimestamp == 0 { 97 return fmt.Errorf("genesis timestamp must be generated by calling GenerateGenesisTimestamp()") 98 } 99 100 addressSet := make(map[string]struct{}) 101 deduplicated := make([]string, 0) 102 103 for _, addr := range c.AddressesToFund { 104 if !common.IsHexAddress(addr) { 105 return fmt.Errorf("address %s is not a valid hex address", addr) 106 } 107 108 if _, exists := addressSet[addr]; exists { 109 logger.Warn().Str("address", addr).Msg("duplicate address in addresses to fund, this should not happen, removing it so that genesis generation doesn't crash") 110 continue 111 } 112 113 addressSet[addr] = struct{}{} 114 deduplicated = append(deduplicated, addr) 115 } 116 117 c.AddressesToFund = deduplicated 118 119 return nil 120 } 121 122 func (c *EthereumChainConfig) ApplyOverrides(from *EthereumChainConfig) error { 123 if from == nil { 124 return nil 125 } 126 if from.ValidatorCount != 0 { 127 c.ValidatorCount = from.ValidatorCount 128 } 129 if from.SecondsPerSlot != 0 { 130 c.SecondsPerSlot = from.SecondsPerSlot 131 } 132 if from.SlotsPerEpoch != 0 { 133 c.SlotsPerEpoch = from.SlotsPerEpoch 134 } 135 if from.GenesisDelay != 0 { 136 c.GenesisDelay = from.GenesisDelay 137 } 138 if from.ChainID != 0 { 139 c.ChainID = from.ChainID 140 } 141 if len(from.AddressesToFund) != 0 { 142 c.AddressesToFund = append([]string{}, from.AddressesToFund...) 143 } 144 return nil 145 } 146 147 func (c *EthereumChainConfig) fillInMissingValuesWithDefault() { 148 defaultConfig := GetDefaultChainConfig() 149 if c.ValidatorCount == 0 { 150 c.ValidatorCount = defaultConfig.ValidatorCount 151 } 152 if c.SecondsPerSlot == 0 { 153 c.SecondsPerSlot = defaultConfig.SecondsPerSlot 154 } 155 if c.SlotsPerEpoch == 0 { 156 c.SlotsPerEpoch = defaultConfig.SlotsPerEpoch 157 } 158 if c.GenesisDelay == 0 { 159 c.GenesisDelay = defaultConfig.GenesisDelay 160 } 161 if c.ChainID == 0 { 162 c.ChainID = defaultConfig.ChainID 163 } 164 if len(c.AddressesToFund) == 0 { 165 c.AddressesToFund = append([]string{}, defaultConfig.AddressesToFund...) 166 } else { 167 c.AddressesToFund = append(append([]string{}, c.AddressesToFund...), defaultConfig.AddressesToFund...) 168 } 169 } 170 171 func (c *EthereumChainConfig) GetValidatorBasedGenesisDelay() int { 172 return c.ValidatorCount * 5 173 } 174 175 func (c *EthereumChainConfig) GenerateGenesisTimestamp() { 176 c.genesisTimestamp = int(time.Now().Unix()) + c.GetValidatorBasedGenesisDelay() 177 } 178 179 func (c *EthereumChainConfig) GetDefaultWaitDuration() time.Duration { 180 return time.Duration((c.GenesisDelay+c.GetValidatorBasedGenesisDelay())*2) * time.Second 181 } 182 183 func (c *EthereumChainConfig) GetDefaultFinalizationWaitDuration() time.Duration { 184 return time.Duration(5 * time.Minute) 185 } 186 187 type ExecutionClient interface { 188 GetContainerName() string 189 StartContainer() (blockchain.EVMNetwork, error) 190 GetContainer() *tc.Container 191 GetContainerType() ContainerType 192 GetInternalExecutionURL() string 193 GetExternalExecutionURL() string 194 GetInternalHttpUrl() string 195 GetInternalWsUrl() string 196 GetExternalHttpUrl() string 197 GetExternalWsUrl() string 198 WaitUntilChainIsReady(ctx context.Context, waitTime time.Duration) error 199 WithTestInstance(t *testing.T) ExecutionClient 200 }