github.com/status-im/status-go@v1.1.0/appdatabase/node_config_test.go (about) 1 package appdatabase 2 3 import ( 4 "crypto/rand" 5 "database/sql" 6 "fmt" 7 "math" 8 "math/big" 9 "sort" 10 "testing" 11 "time" 12 13 "github.com/stretchr/testify/require" 14 15 "github.com/ethereum/go-ethereum/p2p/discv5" 16 17 "github.com/status-im/status-go/eth-node/crypto" 18 "github.com/status-im/status-go/nodecfg" 19 "github.com/status-im/status-go/params" 20 "github.com/status-im/status-go/t/helpers" 21 ) 22 23 func setupTestDB(t *testing.T) (*sql.DB, func()) { 24 db, cleanup, err := helpers.SetupTestSQLDB(DbInitializer{}, "settings-tests-") 25 require.NoError(t, err) 26 return db, func() { require.NoError(t, cleanup()) } 27 } 28 29 func TestGetNodeConfig(t *testing.T) { 30 db, stop := setupTestDB(t) 31 defer stop() 32 33 nodeConfig := randomNodeConfig() 34 require.NoError(t, nodecfg.SaveNodeConfig(db, nodeConfig)) 35 36 dbNodeConfig, err := nodecfg.GetNodeConfigFromDB(db) 37 require.NoError(t, err) 38 require.Equal(t, nodeConfig, dbNodeConfig) 39 } 40 41 func TestSaveNodeConfig(t *testing.T) { 42 db, stop := setupTestDB(t) 43 defer stop() 44 45 newNodeConfig := randomNodeConfig() 46 47 require.NoError(t, nodecfg.SaveNodeConfig(db, newNodeConfig)) 48 49 dbNodeConfig, err := nodecfg.GetNodeConfigFromDB(db) 50 require.NoError(t, err) 51 require.Equal(t, *newNodeConfig, *dbNodeConfig) 52 } 53 54 func TestMigrateNodeConfig(t *testing.T) { 55 // Migration will be run in setupTestDB. If there's an error, that function will fail 56 db, stop := setupTestDB(t) 57 defer stop() 58 59 // node_config column should be empty 60 var result string 61 err := db.QueryRow("SELECT COALESCE(NULL, 'empty')").Scan(&result) 62 require.NoError(t, err) 63 require.Equal(t, "empty", result) 64 } 65 66 func randomString() string { 67 b := make([]byte, 10) 68 _, _ = rand.Read(b) 69 return fmt.Sprintf("%x", b)[:10] 70 } 71 72 func randomBool() bool { 73 return randomInt(2) == 1 74 } 75 76 func randomInt(max int64) int { 77 r, _ := rand.Int(rand.Reader, big.NewInt(max)) 78 return int(r.Int64()) 79 } 80 81 func randomFloat(max int64) float64 { 82 r, _ := rand.Int(rand.Reader, big.NewInt(max)) 83 return float64(r.Int64()) / (1 << 63) 84 } 85 86 func randomStringSlice() []string { 87 m := randomInt(7) 88 var result []string 89 for i := 0; i < m; i++ { 90 result = append(result, randomString()) 91 } 92 sort.Strings(result) 93 return result 94 } 95 96 func randomTopicSlice() []discv5.Topic { 97 randomValues := randomStringSlice() 98 var result []discv5.Topic 99 for _, v := range randomValues { 100 result = append(result, discv5.Topic(v)) 101 } 102 return result 103 } 104 105 func randomTopicLimits() map[discv5.Topic]params.Limits { 106 result := make(map[discv5.Topic]params.Limits) 107 m := randomInt(7) + 1 108 for i := 0; i < m; i++ { 109 result[discv5.Topic(fmt.Sprint(i))] = params.Limits{Min: randomInt(2), Max: randomInt(10)} 110 } 111 return result 112 } 113 114 func randomCustomNodes() map[string]string { 115 result := make(map[string]string) 116 m := randomInt(7) 117 for i := 0; i < m; i++ { 118 result[randomString()] = randomString() 119 } 120 return result 121 } 122 123 func randomNodeConfig() *params.NodeConfig { 124 privK, _ := crypto.GenerateKey() 125 126 return ¶ms.NodeConfig{ 127 NetworkID: uint64(int64(randomInt(math.MaxInt64))), 128 DataDir: randomString(), 129 KeyStoreDir: randomString(), 130 NodeKey: randomString(), 131 NoDiscovery: randomBool(), 132 ListenAddr: randomString(), 133 AdvertiseAddr: randomString(), 134 Name: randomString(), 135 Version: randomString(), 136 APIModules: randomString(), 137 TLSEnabled: randomBool(), 138 MaxPeers: randomInt(math.MaxInt64), 139 MaxPendingPeers: randomInt(math.MaxInt64), 140 EnableStatusService: randomBool(), 141 BridgeConfig: params.BridgeConfig{Enabled: randomBool()}, 142 WalletConfig: params.WalletConfig{Enabled: randomBool()}, 143 LocalNotificationsConfig: params.LocalNotificationsConfig{Enabled: randomBool()}, 144 BrowsersConfig: params.BrowsersConfig{Enabled: randomBool()}, 145 PermissionsConfig: params.PermissionsConfig{Enabled: randomBool()}, 146 MailserversConfig: params.MailserversConfig{Enabled: randomBool()}, 147 Web3ProviderConfig: params.Web3ProviderConfig{Enabled: randomBool()}, 148 ConnectorConfig: params.ConnectorConfig{Enabled: randomBool()}, 149 SwarmConfig: params.SwarmConfig{Enabled: randomBool()}, 150 MailServerRegistryAddress: randomString(), 151 HTTPEnabled: randomBool(), 152 HTTPHost: randomString(), 153 HTTPPort: randomInt(math.MaxInt64), 154 HTTPVirtualHosts: randomStringSlice(), 155 HTTPCors: randomStringSlice(), 156 WSEnabled: false, // NOTE: leaving ws field idle since we are moving away from the storing the whole config 157 WSHost: "", 158 WSPort: 0, 159 IPCEnabled: randomBool(), 160 IPCFile: randomString(), 161 LogEnabled: randomBool(), 162 LogMobileSystem: randomBool(), 163 LogDir: randomString(), 164 LogFile: randomString(), 165 LogLevel: randomString(), 166 LogMaxBackups: randomInt(math.MaxInt64), 167 LogMaxSize: randomInt(math.MaxInt64), 168 LogCompressRotated: randomBool(), 169 LogToStderr: randomBool(), 170 UpstreamConfig: params.UpstreamRPCConfig{Enabled: randomBool(), URL: randomString()}, 171 ClusterConfig: params.ClusterConfig{ 172 Enabled: randomBool(), 173 Fleet: randomString(), 174 StaticNodes: randomStringSlice(), 175 BootNodes: randomStringSlice(), 176 }, 177 LightEthConfig: params.LightEthConfig{ 178 Enabled: randomBool(), 179 DatabaseCache: randomInt(math.MaxInt64), 180 TrustedNodes: randomStringSlice(), 181 MinTrustedFraction: randomInt(math.MaxInt64), 182 }, 183 RegisterTopics: randomTopicSlice(), 184 RequireTopics: randomTopicLimits(), 185 PushNotificationServerConfig: params.PushNotificationServerConfig{ 186 Enabled: randomBool(), 187 GorushURL: randomString(), 188 Identity: privK, 189 }, 190 ShhextConfig: params.ShhextConfig{ 191 PFSEnabled: randomBool(), 192 InstallationID: randomString(), 193 MailServerConfirmations: randomBool(), 194 EnableConnectionManager: randomBool(), 195 EnableLastUsedMonitor: randomBool(), 196 ConnectionTarget: randomInt(math.MaxInt64), 197 RequestsDelay: time.Duration(randomInt(math.MaxInt64)), 198 MaxServerFailures: randomInt(math.MaxInt64), 199 MaxMessageDeliveryAttempts: randomInt(math.MaxInt64), 200 WhisperCacheDir: randomString(), 201 DisableGenericDiscoveryTopic: randomBool(), 202 SendV1Messages: randomBool(), 203 DataSyncEnabled: randomBool(), 204 VerifyTransactionURL: randomString(), 205 VerifyENSURL: randomString(), 206 VerifyENSContractAddress: randomString(), 207 VerifyTransactionChainID: int64(randomInt(math.MaxInt64)), 208 AnonMetricsSendID: randomString(), 209 AnonMetricsServerEnabled: randomBool(), 210 AnonMetricsServerPostgresURI: randomString(), 211 BandwidthStatsEnabled: randomBool(), 212 }, 213 WakuV2Config: params.WakuV2Config{ 214 Enabled: randomBool(), 215 Host: randomString(), 216 Port: randomInt(math.MaxInt64), 217 LightClient: randomBool(), 218 FullNode: randomBool(), 219 DiscoveryLimit: randomInt(math.MaxInt64), 220 DataDir: randomString(), 221 MaxMessageSize: uint32(randomInt(math.MaxInt64)), 222 EnableConfirmations: randomBool(), 223 CustomNodes: randomCustomNodes(), 224 EnableDiscV5: randomBool(), 225 UDPPort: randomInt(math.MaxInt64), 226 AutoUpdate: randomBool(), 227 }, 228 WakuConfig: params.WakuConfig{ 229 Enabled: randomBool(), 230 LightClient: randomBool(), 231 FullNode: randomBool(), 232 EnableMailServer: randomBool(), 233 DataDir: randomString(), 234 MinimumPoW: randomFloat(math.MaxInt64), 235 MailServerPassword: randomString(), 236 MailServerRateLimit: randomInt(math.MaxInt64), 237 MailServerDataRetention: randomInt(math.MaxInt64), 238 TTL: randomInt(math.MaxInt64), 239 MaxMessageSize: uint32(randomInt(math.MaxInt64)), 240 DatabaseConfig: params.DatabaseConfig{ 241 PGConfig: params.PGConfig{ 242 Enabled: randomBool(), 243 URI: randomString(), 244 }, 245 }, 246 EnableRateLimiter: randomBool(), 247 PacketRateLimitIP: int64(randomInt(math.MaxInt64)), 248 PacketRateLimitPeerID: int64(randomInt(math.MaxInt64)), 249 BytesRateLimitIP: int64(randomInt(math.MaxInt64)), 250 BytesRateLimitPeerID: int64(randomInt(math.MaxInt64)), 251 RateLimitTolerance: int64(randomInt(math.MaxInt64)), 252 BloomFilterMode: randomBool(), 253 SoftBlacklistedPeerIDs: randomStringSlice(), 254 EnableConfirmations: randomBool(), 255 }, 256 } 257 } 258 259 func TestConfigValidate(t *testing.T) { 260 // GIVEN 261 db, stop := setupTestDB(t) 262 defer stop() 263 264 tmpdir := t.TempDir() 265 nodeConfig, err := params.NewNodeConfig(tmpdir, 1777) 266 267 require.NoError(t, err) 268 require.NoError(t, nodeConfig.Validate()) 269 require.NoError(t, nodecfg.SaveNodeConfig(db, nodeConfig)) 270 271 // WHEN 272 dbNodeConfig, err := nodecfg.GetNodeConfigFromDB(db) 273 require.NoError(t, err) 274 275 // THEN 276 require.NoError(t, dbNodeConfig.Validate()) 277 } 278 279 func TestRepairLoadedTorrentConfig(t *testing.T) { 280 // GIVEN 281 db, stop := setupTestDB(t) 282 defer stop() 283 284 tmpdir := t.TempDir() 285 nodeConfig, err := params.NewNodeConfig(tmpdir, 1777) 286 require.NoError(t, err) 287 288 require.NoError(t, nodeConfig.Validate()) 289 290 // Write config to db 291 require.NoError(t, nodecfg.SaveNodeConfig(db, nodeConfig)) 292 293 // WHEN: Corrupt the torrent config data as described in the ticket 294 // (https://github.com/status-im/status-desktop/issues/14643) 295 // Write invalid torrent config to database 296 nodeConfig.TorrentConfig.DataDir = "" 297 nodeConfig.TorrentConfig.TorrentDir = "" 298 nodeConfig.TorrentConfig.Enabled = true 299 require.Error(t, nodeConfig.Validate()) 300 301 _, err = db.Exec(`INSERT OR REPLACE INTO torrent_config ( 302 enabled, port, data_dir, torrent_dir, synthetic_id 303 ) VALUES (?, ?, ?, ?, 'id')`, 304 nodeConfig.TorrentConfig.Enabled, 305 nodeConfig.TorrentConfig.Port, 306 nodeConfig.TorrentConfig.DataDir, 307 nodeConfig.TorrentConfig.TorrentDir, 308 ) 309 require.NoError(t, err) 310 311 dbNodeConfig, err := nodecfg.GetNodeConfigFromDB(db) 312 require.NoError(t, err) 313 314 // THEN The invalid torrent config should be repaired 315 require.Error(t, dbNodeConfig.Validate()) 316 require.NoError(t, dbNodeConfig.UpdateWithDefaults()) 317 require.NoError(t, dbNodeConfig.Validate()) 318 }