repo_description: A permissioned implementation of Ethereum supporting data privacy
repo_topics: blockchain consensus eea enterprise-ethereum enterprise-ethereum-client ethereum go goquorum ledger privacy protocols-team-goquorum quorum
code: package main
  
  import (
  	"flag"
  	"fmt"
  	"io/ioutil"
  	"math/big"
  	"os"
  	"strings"
  	"testing"
  	"time"
  
  	"github.com/ethereum/go-ethereum/cmd/utils"
  	"github.com/ethereum/go-ethereum/common"
  	"github.com/ethereum/go-ethereum/consensus/istanbul"
  	"github.com/ethereum/go-ethereum/eth/downloader"
  	"github.com/ethereum/go-ethereum/p2p/enode"
  	"github.com/ethereum/go-ethereum/p2p/netutil"
  	"github.com/naoina/toml"
  	"github.com/stretchr/testify/assert"
  	"github.com/stretchr/testify/require"
  	"gopkg.in/urfave/cli.v1"
  )
  
  func TestFlagsConfig(t *testing.T) {
  	flags := []interface{}{
  		utils.DataDirFlag,
  		utils.RaftLogDirFlag,
  		utils.AncientFlag,
  		utils.MinFreeDiskSpaceFlag,
  		utils.KeyStoreDirFlag,
  		utils.NoUSBFlag,
  		utils.USBFlag,
  		utils.SmartCardDaemonPathFlag,
  		utils.NetworkIdFlag,
  		utils.MainnetFlag,
  		utils.GoerliFlag,
  		utils.YoloV3Flag,
  		utils.RinkebyFlag,
  		utils.RopstenFlag,
  		utils.DeveloperFlag,
  		utils.DeveloperPeriodFlag,
  		utils.IdentityFlag,
  		utils.DocRootFlag,
  		utils.ExitWhenSyncedFlag,
  		utils.IterativeOutputFlag,
  		utils.ExcludeStorageFlag,
  		utils.IncludeIncompletesFlag,
  		utils.ExcludeCodeFlag,
  		utils.SyncModeFlag,
  		utils.GCModeFlag,
  		utils.SnapshotFlag,
  		utils.TxLookupLimitFlag,
  		utils.LightKDFFlag,
  		utils.DeprecatedAuthorizationListFlag,
  		utils.AuthorizationListFlag,
  		utils.BloomFilterSizeFlag,
  		utils.OverrideBerlinFlag,
  		utils.LightServeFlag,
  		utils.LightIngressFlag,
  		utils.LightEgressFlag,
  		utils.LightMaxPeersFlag,
  		utils.UltraLightServersFlag,
  		utils.UltraLightFractionFlag,
  		utils.UltraLightOnlyAnnounceFlag,
  		utils.LightNoPruneFlag,
  		utils.LightNoSyncServeFlag,
  		utils.EthashCacheDirFlag,
  		utils.EthashCachesInMemoryFlag,
  		utils.EthashCachesOnDiskFlag,
  		utils.EthashCachesLockMmapFlag,
  		utils.EthashDatasetDirFlag,
  		utils.EthashDatasetsInMemoryFlag,
  		utils.EthashDatasetsOnDiskFlag,
  		utils.EthashDatasetsLockMmapFlag,
  		utils.TxPoolLocalsFlag,
  		utils.TxPoolNoLocalsFlag,
  		utils.TxPoolJournalFlag,
  		utils.TxPoolRejournalFlag,
  		utils.TxPoolPriceLimitFlag,
  		utils.TxPoolPriceBumpFlag,
  		utils.TxPoolAccountSlotsFlag,
  		utils.TxPoolGlobalSlotsFlag,
  		utils.TxPoolAccountQueueFlag,
  		utils.TxPoolGlobalQueueFlag,
  		utils.TxPoolLifetimeFlag,
  		utils.CacheFlag,
  		utils.CacheDatabaseFlag,
  		utils.CacheTrieFlag,
  		utils.CacheTrieJournalFlag,
  		utils.CacheTrieRejournalFlag,
  		utils.CacheGCFlag,
  		utils.CacheSnapshotFlag,
  		utils.CacheNoPrefetchFlag,
  		utils.CachePreimagesFlag,
  		utils.MiningEnabledFlag,
  		utils.MinerThreadsFlag,
  		utils.MinerNotifyFlag,
  		utils.MinerGasTargetFlag,
  		utils.MinerGasLimitFlag,
  		utils.MinerGasPriceFlag,
  		utils.MinerEtherbaseFlag,
  		utils.MinerExtraDataFlag,
  		utils.MinerRecommitIntervalFlag,
  		utils.MinerNoVerfiyFlag,
  		utils.UnlockedAccountFlag,
  		utils.PasswordFileFlag,
  		utils.ExternalSignerFlag,
  		utils.VMEnableDebugFlag,
  		utils.InsecureUnlockAllowedFlag,
  		utils.RPCGlobalGasCapFlag,
  		utils.RPCGlobalTxFeeCapFlag,
  		utils.EthStatsURLFlag,
  		utils.FakePoWFlag,
  		utils.NoCompactionFlag,
  		utils.RPCClientToken,
  		utils.RPCClientTLSCert,
  		utils.RPCClientTLSCaCert,
  		utils.RPCClientTLSCipherSuites,
  		utils.RPCClientTLSInsecureSkipVerify,
  		utils.IPCDisabledFlag,
  		utils.IPCPathFlag,
  		utils.HTTPEnabledFlag,
  		utils.HTTPListenAddrFlag,
  		utils.HTTPPortFlag,
  		utils.HTTPCORSDomainFlag,
  		utils.HTTPVirtualHostsFlag,
  		utils.HTTPApiFlag,
  		utils.HTTPPathPrefixFlag,
  		utils.GraphQLEnabledFlag,
  		utils.GraphQLCORSDomainFlag,
  		utils.GraphQLVirtualHostsFlag,
  		utils.WSEnabledFlag,
  		utils.WSListenAddrFlag,
  		utils.WSPortFlag,
  		utils.WSApiFlag,
  		utils.WSAllowedOriginsFlag,
  		utils.WSPathPrefixFlag,
  		utils.ExecFlag,
  		utils.PreloadJSFlag,
  		utils.AllowUnprotectedTxs,
  		utils.MaxPeersFlag,
  		utils.MaxPendingPeersFlag,
  		utils.ListenPortFlag,
  		utils.BootnodesFlag,
  		utils.NodeKeyFileFlag,
  		utils.NodeKeyHexFlag,
  		utils.NATFlag,
  		utils.NoDiscoverFlag,
  		utils.DiscoveryV5Flag,
  		utils.NetrestrictFlag,
  		utils.DNSDiscoveryFlag,
  		utils.JSpathFlag,
  		utils.GpoBlocksFlag,
  		utils.GpoPercentileFlag,
  		utils.GpoMaxGasPriceFlag,
  		utils.MetricsEnabledFlag,
  		utils.MetricsEnabledExpensiveFlag,
  		utils.MetricsHTTPFlag,
  		utils.MetricsPortFlag,
  		utils.MetricsEnableInfluxDBFlag,
  		utils.MetricsInfluxDBEndpointFlag,
  		utils.MetricsInfluxDBDatabaseFlag,
  		utils.MetricsInfluxDBUsernameFlag,
  		utils.MetricsInfluxDBPasswordFlag,
  		utils.MetricsInfluxDBTagsFlag,
  		utils.EWASMInterpreterFlag,
  		utils.EVMInterpreterFlag,
  		utils.EVMCallTimeOutFlag,
  		utils.QuorumImmutabilityThreshold,
  		utils.RaftModeFlag,
  		utils.RaftBlockTimeFlag,
  		utils.RaftJoinExistingFlag,
  		utils.EmitCheckpointsFlag,
  		utils.RaftPortFlag,
  		utils.RaftDNSEnabledFlag,
  		utils.EnableNodePermissionFlag,
  		utils.AllowedFutureBlockTimeFlag,
  		utils.PluginSettingsFlag,
  		utils.PluginLocalVerifyFlag,
  		utils.PluginPublicKeyFlag,
  		utils.PluginSkipVerifyFlag,
  		utils.AccountPluginNewAccountConfigFlag,
  		utils.IstanbulRequestTimeoutFlag,
  		utils.IstanbulBlockPeriodFlag,
  		utils.MultitenancyFlag,
  		utils.RevertReasonFlag,
  		utils.QuorumEnablePrivacyMarker,
  		utils.QuorumPTMUnixSocketFlag,
  		utils.QuorumPTMUrlFlag,
  		utils.QuorumPTMTimeoutFlag,
  		utils.QuorumPTMDialTimeoutFlag,
  		utils.QuorumPTMHttpIdleTimeoutFlag,
  		utils.QuorumPTMHttpWriteBufferSizeFlag,
  		utils.QuorumPTMHttpReadBufferSizeFlag,
  		utils.QuorumPTMTlsModeFlag,
  		utils.QuorumPTMTlsRootCaFlag,
  		utils.QuorumPTMTlsClientCertFlag,
  		utils.QuorumPTMTlsClientKeyFlag,
  		utils.QuorumPTMTlsInsecureSkipVerify,
  	}
  	nodeKeyFile, err := ioutil.TempFile("/tmp", "nodekey")
  	require.NoError(t, err)
  	defer os.Remove(nodeKeyFile.Name())
  
  	_, err = nodeKeyFile.WriteString("0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF\n")
  	require.NoError(t, err)
  
  	err = nodeKeyFile.Close()
  	require.NoError(t, err)
  
  	set := flag.NewFlagSet("dumpconfig", flag.ContinueOnError)
  	for _, f := range flags {
  		switch f := f.(type) {
  		case utils.DirectoryFlag:
  			set.String(f.Name, f.Value.String()+"/custom", f.Usage)
  		case cli.BoolFlag:
  			set.Bool(f.Name, true, f.Usage)
  		case cli.BoolTFlag:
  			set.Bool(f.Name, false, f.Usage)
  		case cli.StringFlag:
  			switch f {
  			case utils.BootnodesFlag:
  				set.String(f.Name, "", f.Usage)
  			case utils.GCModeFlag:
  				set.String(f.Name, "archive", f.Usage)
  			case utils.NodeKeyHexFlag: // either hex or file
  			//	set.String(f.Name, "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF", f.Usage) // either nodeKeyHex or nodeKeyFile
  			case utils.NodeKeyFileFlag:
  				set.String(f.Name, nodeKeyFile.Name(), f.Usage)
  			case utils.NetrestrictFlag:
  				set.String(f.Name, "127.0.0.0/16, [REDACTED_IP]/24,", f.Usage) // TOML problem
  			case utils.AuthorizationListFlag:
  				set.String(f.Name, "1=0x0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF,2=0x0123456789ABCDEF0123456789ABCDE00123456789ABCDEF0123456789ABCDEF", f.Usage)
  			default:
  				set.String(f.Name, f.Value+"_custom", f.Usage)
  			}
  		case cli.Uint64Flag:
  			set.Uint64(f.Name, f.Value+10, f.Usage)
  		case cli.IntFlag:
  			set.Int(f.Name, f.Value+10, f.Usage)
  		case utils.TextMarshalerFlag:
  			set.String(f.Name, "light", f.Usage)
  		case cli.Int64Flag:
  			set.Int64(f.Name, f.Value+10, f.Usage)
  		case cli.DurationFlag:
  			set.Duration(f.Name, f.Value+5*time.Minute, f.Usage)
  		case utils.BigFlag:
  			set.Uint64(f.Name, f.Value.Uint64()+10, f.Usage)
  		case cli.Float64Flag:
  			set.Float64(f.Name, f.Value+0.1, f.Name)
  		case cli.UintFlag:
  			set.Uint(f.Name, f.Value+10, f.Usage)
  		default:
  			t.Logf("unknown %t", f)
  			t.Fail()
  		}
  	}
  	action := utils.MigrateFlags(dumpConfig)
  	app := &cli.App{
  		Name:   "dumpconfig",
  		Usage:  "dump config",
  		Action: action,
  	}
  
  	ctx := cli.NewContext(app, set, nil)
  
  	out, err := ioutil.TempFile("/tmp", "gethCfg")
  	require.NoError(t, err)
  	defer out.Close()
  	defer os.Remove(out.Name())
  
  	bak := os.Stdout
  	defer func() { os.Stdout = bak }()
  	os.Stdout = out
  
  	err = action(ctx)
  	require.NoError(t, err)
  
  	out2, err := removeComment(out.Name())
  	require.NoError(t, err)
  	defer os.Remove(out2.Name())
  
  	t.Log(out2.Name())
  	val, err := ioutil.ReadFile(out2.Name())
  	require.NoError(t, err)
  	t.Log(string(val))
  
  	cfg := &gethConfig{}
  	err = loadConfig(out2.Name(), cfg)
  	require.NoError(t, err)
  
  	// [Eth]
  	eth := cfg.Eth
  	assert.Equal(t, uint64(1), eth.NetworkId) // mainnet true
  	// Quorum - make full sync the default sync mode in quorum (as opposed to upstream geth)
  	assert.Equal(t, downloader.FullSync, eth.SyncMode)
  	// End Quorum
  	assert.Equal(t, []string{"enrtree://[REDACTED_EMAIL]"}, eth.EthDiscoveryURLs)
  	assert.Equal(t, false, eth.NoPruning)
  	assert.Equal(t, false, eth.NoPrefetch)
  	assert.Equal(t, 100, eth.LightPeers)
  	assert.Equal(t, 75, eth.UltraLightFraction)
  	assert.Equal(t, 768, eth.DatabaseCache)
  	assert.Equal(t, "", eth.DatabaseFreezer)
  	assert.Equal(t, 256, eth.TrieCleanCache)
  	assert.Equal(t, "triecache", eth.TrieCleanCacheJournal)
  	assert.Equal(t, time.Duration(3600000000000), eth.TrieCleanCacheRejournal)
  	assert.Equal(t, 256, eth.TrieDirtyCache)
  	assert.Equal(t, time.Duration(3600000000000), eth.TrieTimeout)
  	assert.Equal(t, 0, eth.SnapshotCache)
  	assert.Equal(t, false, eth.EnablePreimageRecording)
  	assert.Equal(t, "", eth.EWASMInterpreter)
  	assert.Equal(t, "", eth.EVMInterpreter)
  	assert.Equal(t, uint64(25000000), eth.RPCGasCap)
  	assert.Equal(t, float64(1), eth.RPCTxFeeCap)
  	// Quorum
  	assert.Equal(t, time.Duration(15000000000), eth.EVMCallTimeOut)
  	// End Quorum
  
  	// [Eth.Miner]
  	miner := cfg.Eth.Miner
  	assert.Equal(t, uint64(700000000), miner.GasFloor)
  	assert.Equal(t, uint64(800000000), miner.GasCeil)
  	assert.Equal(t, big.NewInt(1000000000), miner.GasPrice)
  	assert.Equal(t, time.Duration(3000000000), miner.Recommit)
  	assert.Equal(t, false, miner.Noverify)
  	assert.Equal(t, uint64(0), miner.AllowedFutureBlockTime)
  
  	// [Eth.GPO]
  	gpo := cfg.Eth.GPO
  	assert.Equal(t, 2, gpo.Blocks)
  	assert.Equal(t, 60, gpo.Percentile)
  
  	// [Eth.TxPool]
  	txPool := cfg.Eth.TxPool
  	assert.Equal(t, []common.Address{}, txPool.Locals)
  	assert.Equal(t, false, txPool.NoLocals)
  	assert.Equal(t, "transactions.rlp", txPool.Journal)
  	assert.Equal(t, time.Duration(3600000000000), txPool.Rejournal)
  	assert.Equal(t, uint64(1), txPool.PriceLimit)
  	assert.Equal(t, uint64(10), txPool.PriceBump)
  	assert.Equal(t, uint64(16), txPool.AccountSlots)
  	assert.Equal(t, uint64(4096), txPool.GlobalSlots)
  	assert.Equal(t, uint64(64), txPool.AccountQueue)
  	assert.Equal(t, uint64(1024), txPool.GlobalQueue)
  	assert.Equal(t, time.Duration(10800000000000), txPool.Lifetime)
  
  	// [Node]
  	node := cfg.Node
  	assert.Equal(t, "", node.DataDir)
  	assert.Equal(t, false, node.InsecureUnlockAllowed)
  	assert.Equal(t, false, node.NoUSB)
  	assert.Equal(t, "", node.IPCPath)
  	assert.Equal(t, "127.0.0.1", node.HTTPHost)
  	assert.Equal(t, 8545, node.HTTPPort)
  	assert.Equal(t, []string(nil), node.HTTPCors)
  	assert.Equal(t, []string{"localhost"}, node.HTTPVirtualHosts)
  	assert.Equal(t, []string{"net", "web3", "eth"}, node.HTTPModules)
  	assert.Equal(t, "127.0.0.1", node.WSHost)
  	assert.Equal(t, 8546, node.WSPort)
  	assert.Equal(t, []string(nil), node.WSOrigins)
  	assert.Equal(t, []string{"net", "web3", "eth"}, node.WSModules)
  	assert.Equal(t, []string(nil), node.GraphQLCors)
  	assert.Equal(t, []string{"localhost"}, node.GraphQLVirtualHosts)
  	assert.Equal(t, false, node.EnableNodePermission)
  
  	// [Node.P2P]
  	p2p := cfg.Node.P2P
  	assert.Equal(t, 0, p2p.MaxPeers)
  	assert.Equal(t, true, p2p.NoDiscovery)
  
  	assert.Equal(t, bootNodes(t).Nodes, p2p.BootstrapNodes)
  	//assert.Equal(t, bootNodesV5(t).Nodes, p2p.BootstrapNodesV5)
  	assert.Equal(t, "", p2p.ListenAddr)
  	assert.Equal(t, false, p2p.EnableMsgEvents)
  
  	type NetRestrictType struct {
  		NetRestrict *netutil.Netlist
  	}
  	var netRestrict NetRestrictType
  	err = toml.Unmarshal([]byte(`NetRestrict = ["127.0.0.0/16", "[REDACTED_IP]/24"]`), &netRestrict)
  	require.NoError(t, err)
  	assert.Equal(t, netRestrict.NetRestrict, p2p.NetRestrict)
  
  	// [Node.HTTPTimeouts]
  	httpTimeouts := cfg.Node.HTTPTimeouts
  	assert.Equal(t, time.Duration(30000000000), httpTimeouts.ReadTimeout)
  	assert.Equal(t, time.Duration(30000000000), httpTimeouts.WriteTimeout)
  	assert.Equal(t, time.Duration(120000000000), httpTimeouts.IdleTimeout)
  
  	// QUORUM
  	// [Eth.Istanbul]
  	quorumIstanbul := eth.Istanbul
  	config := quorumIstanbul.GetConfig(nil)
  	assert.Equal(t, uint64(10000), config.RequestTimeout)
  	assert.Equal(t, uint64(5), config.BlockPeriod)
  	assert.Equal(t, uint64(30000), config.Epoch)
  	assert.Equal(t, big.NewInt(0), quorumIstanbul.Ceil2Nby3Block)
  	assert.Equal(t, istanbul.RoundRobin, quorumIstanbul.ProposerPolicy.Id) // conflict with genesis?
  	// END QUORUM
  }
  
  type BootNodesV5Type struct {
  	Nodes []*enode.Node
  }
  
  func bootNodesV5(t *testing.T) BootNodesV5Type {
  	var bootNodesV5 BootNodesV5Type
  	err := toml.Unmarshal([]byte(`Nodes = ["enode://30b7ab30a01c124a6cceca36863ece12c4f5fa68e3ba9b0b51407ccc002eeed3b3102d20a88f1c1d3c3154e2449317b8ef95090e77b312d5cc39354f86d5d606@[REDACTED_IP]:30303", "enode://865a63255b3bb68023b6bffd5095118fcc13e79dcf014fe4e47e065c350c7cc72af2e53eff895f11ba1bbb6a2b33271c1116ee870f266618eadfc2e78aa7349c@[REDACTED_IP]:30303", "enode://6332792c4a00e3e4ee0926ed89e0d27ef985424d97b6a45bf0f23e51f0dcb5e66b875777506458aea7af6f9e4ffb69f43f3778ee73c81ed9d34c51c4b16b0b0f@[REDACTED_IP]:30303", "enode://94c15d1b9e2fe7ce56e458b9a3b672ef11894ddedd0c6f247e0f1d3487f52b66208fb4aeb8179fce6e3a749ea93ed147c37976d67af557508d199d9594c35f09@[REDACTED_IP]:30303"]`), &bootNodesV5)
  	require.NoError(t, err)
  	return bootNodesV5
  }
  
  type BootNodesType struct {
  	Nodes []*enode.Node
  }
  
  func bootNodes(t *testing.T) BootNodesType {
  	var bootNodes BootNodesType
  	err := toml.Unmarshal([]byte(`Nodes = ["enode://30b7ab30a01c124a6cceca36863ece12c4f5fa68e3ba9b0b51407ccc002eeed3b3102d20a88f1c1d3c3154e2449317b8ef95090e77b312d5cc39354f86d5d606@[REDACTED_IP]:30303", "enode://865a63255b3bb68023b6bffd5095118fcc13e79dcf014fe4e47e065c350c7cc72af2e53eff895f11ba1bbb6a2b33271c1116ee870f266618eadfc2e78aa7349c@[REDACTED_IP]:30303", "enode://6332792c4a00e3e4ee0926ed89e0d27ef985424d97b6a45bf0f23e51f0dcb5e66b875777506458aea7af6f9e4ffb69f43f3778ee73c81ed9d34c51c4b16b0b0f@[REDACTED_IP]:30303", "enode://94c15d1b9e2fe7ce56e458b9a3b672ef11894ddedd0c6f247e0f1d3487f52b66208fb4aeb8179fce6e3a749ea93ed147c37976d67af557508d199d9594c35f09@[REDACTED_IP]:30303"]`), &bootNodes)
  	require.NoError(t, err)
  	return bootNodes
  }
  
  func removeComment(name string) (*os.File, error) {
  	file, err := ioutil.ReadFile(name)
  	if err != nil {
  		return nil, fmt.Errorf("read file: %w", err)
  	}
  	out, err := ioutil.TempFile("/tmp", "gethCfg")
  	if err != nil {
  		return nil, fmt.Errorf("create temp file: %w", err)
  	}
  	defer out.Close()
  	text := string(file)
  	lines := strings.Split(text, "\n")
  	first := true
  	for _, line := range lines {
  		if strings.Index(line, "#") != 0 && !(first && line == "") {
  			line = strings.Replace(line, "e+00", ".0", 1)
  			line = strings.Replace(line, "[[", "[", 1)
  			line = strings.Replace(line, "]]", "]", 1)
  			_, err = out.WriteString(line + "\n")
  			if err != nil {
  				return nil, fmt.Errorf("write line: %w", err)
  			}
  			first = false
  		}
  	}
  	return out, nil
  }
  
  func TestLoadAndDumpGethConfig(t *testing.T) {
  	out, err := ioutil.TempFile("/tmp", "gethCfg")
  	require.NoError(t, err)
  	defer out.Close()
  	_, err = out.WriteString(`[Eth]
  NetworkId = 1337
  SyncMode = "full"
  EthDiscoveryURLs = ["enrtree://[REDACTED_EMAIL]"]
  SnapDiscoveryURLs = []
  NoPruning = false
  NoPrefetch = false
  LightPeers = 100
  UltraLightFraction = 75
  DatabaseCache = 768
  DatabaseFreezer = ""
  TrieCleanCache = 256
  TrieCleanCacheJournal = "triecache-test"
  TrieCleanCacheRejournal = 3600000000000
  TrieDirtyCache = 256
  TrieTimeout = 3600000000000
  SnapshotCache = 0
  Preimages = true
  EnablePreimageRecording = false
  EWASMInterpreter = ""
  EVMInterpreter = ""
  RPCGasCap = 25000000
  RPCTxFeeCap = 1e+00
  RaftMode = true
  EnableNodePermission = true
  EVMCallTimeOut = 3600000000000
  
  [Eth.Miner]
  GasFloor = 700000000
  GasCeil = 800000000
  GasPrice = 0
  Recommit = 3000000000
  Noverify = false
  AllowedFutureBlockTime = 0
  
  [Eth.GPO]
  Blocks = 20
  Percentile = 60
  MaxPrice = 500000000000
  
  [Eth.TxPool]
  Locals = []
  NoLocals = false
  Journal = "transactions.rlp"
  Rejournal = 3600000000000
  PriceLimit = 1
  PriceBump = 10
  AccountSlots = 16
  GlobalSlots = 4096
  AccountQueue = 64
  GlobalQueue = 1024
  Lifetime = 10800000000000
  
  [Eth.Istanbul]
  RequestTimeout = 10000
  BlockPeriod = 5
  ProposerPolicy = "id = 0\n"
  Epoch = 30000
  Ceil2Nby3Block = 0
  TestQBFTBlock = 0
  
  [Node]
  UserIdent = "_custom"
  DataDir = "/data"
  RaftLogDir = ""
  InsecureUnlockAllowed = true
  NoUSB = true
  IPCPath = "geth.ipc"
  HTTPHost = "0.0.0.0"
  HTTPPort = 8545
  HTTPCors = ["'*'"]
  HTTPVirtualHosts = ["'*'"]
  HTTPModules = ["admin", "db", "eth", "debug", "miner", "net", "txpool", "personal", "web3", "quorum", "istanbul"]
  WSHost = "0.0.0.0"
  WSPort = 8546
  WSOrigins = ["'*'"]
  WSModules = ["admin", "db", "eth", "debug", "miner", "net", "txpool", "personal", "web3", "quorum", "istanbul"]
  GraphQLCors = ["'*'"]
  GraphQLVirtualHosts = ["'*'"]
  EnableNodePermission = true
  
  [Node.P2P]
  MaxPeers = 50
  NoDiscovery = true
  BootstrapNodes = ["enode://30b7ab30a01c124a6cceca36863ece12c4f5fa68e3ba9b0b51407ccc002eeed3b3102d20a88f1c1d3c3154e2449317b8ef95090e77b312d5cc39354f86d5d606@[REDACTED_IP]:30303", "enode://865a63255b3bb68023b6bffd5095118fcc13e79dcf014fe4e47e065c350c7cc72af2e53eff895f11ba1bbb6a2b33271c1116ee870f266618eadfc2e78aa7349c@[REDACTED_IP]:30303", "enode://6332792c4a00e3e4ee0926ed89e0d27ef985424d97b6a45bf0f23e51f0dcb5e66b875777506458aea7af6f9e4ffb69f43f3778ee73c81ed9d34c51c4b16b0b0f@[REDACTED_IP]:30303", "enode://94c15d1b9e2fe7ce56e458b9a3b672ef11894ddedd0c6f247e0f1d3487f52b66208fb4aeb8179fce6e3a749ea93ed147c37976d67af557508d199d9594c35f09@[REDACTED_IP]:30303"]
  BootstrapNodesV5 = ["enode://30b7ab30a01c124a6cceca36863ece12c4f5fa68e3ba9b0b51407ccc002eeed3b3102d20a88f1c1d3c3154e2449317b8ef95090e77b312d5cc39354f86d5d606@[REDACTED_IP]:30303", "enode://865a63255b3bb68023b6bffd5095118fcc13e79dcf014fe4e47e065c350c7cc72af2e53eff895f11ba1bbb6a2b33271c1116ee870f266618eadfc2e78aa7349c@[REDACTED_IP]:30303", "enode://6332792c4a00e3e4ee0926ed89e0d27ef985424d97b6a45bf0f23e51f0dcb5e66b875777506458aea7af6f9e4ffb69f43f3778ee73c81ed9d34c51c4b16b0b0f@[REDACTED_IP]:30303", "enode://94c15d1b9e2fe7ce56e458b9a3b672ef11894ddedd0c6f247e0f1d3487f52b66208fb4aeb8179fce6e3a749ea93ed147c37976d67af557508d199d9594c35f09@[REDACTED_IP]:30303"]
  StaticNodes = []
  TrustedNodes = []
  NetRestrict = ["127.0.0.0/16", "[REDACTED_IP]/24"]
  ListenAddr = ":30303"
  EnableMsgEvents = false
  
  [Node.HTTPTimeouts]
  ReadTimeout = 30000000000
  WriteTimeout = 30000000000
  IdleTimeout = 120000000000
          
  [Metrics]
  HTTP = "127.0.0.1"
  Port = 6060
  InfluxDBEndpoint = "http://localhost:8086"
  InfluxDBDatabase = "geth"
  InfluxDBUsername = "test"
  InfluxDBPassword = "test"
  InfluxDBTags = "host=localhost"
  `)
  	require.NoError(t, err)
  	err = out.Close()
  	require.NoError(t, err)
  	cfg := &gethConfig{}
  
  	err = loadConfig(out.Name(), cfg)
  	require.NoError(t, err)
  
  	testConfig(t, cfg)
  
  	out, err = ioutil.TempFile("/tmp", "gethCfg")
  	require.NoError(t, err)
  
  	err = tomlSettings.NewEncoder(out).Encode(cfg)
  	require.NoError(t, err)
  
  	cfg = &gethConfig{}
  	err = loadConfig(out.Name(), cfg)
  	require.NoError(t, err)
  
  	testConfig(t, cfg)
  }
  
  func testConfig(t *testing.T, cfg *gethConfig) {
  	// [Eth]
  	eth := cfg.Eth
  	assert.Equal(t, uint64(1337), eth.NetworkId)
  	assert.Equal(t, downloader.FullSync, eth.SyncMode)
  	assert.Equal(t, []string{"enrtree://[REDACTED_EMAIL]"}, eth.EthDiscoveryURLs)
  	assert.Equal(t, false, eth.NoPruning)
  	assert.Equal(t, false, eth.NoPrefetch)
  	assert.Equal(t, 100, eth.LightPeers)
  	assert.Equal(t, 75, eth.UltraLightFraction)
  	assert.Equal(t, 768, eth.DatabaseCache)
  	assert.Equal(t, "", eth.DatabaseFreezer)
  	assert.Equal(t, 256, eth.TrieCleanCache)
  	assert.Equal(t, "triecache-test", eth.TrieCleanCacheJournal)
  	assert.Equal(t, time.Duration(3600000000000), eth.TrieCleanCacheRejournal)
  	assert.Equal(t, 256, eth.TrieDirtyCache)
  	assert.Equal(t, time.Duration(3600000000000), eth.TrieTimeout)
  	assert.Equal(t, 0, eth.SnapshotCache)
  	assert.Equal(t, false, eth.EnablePreimageRecording)
  	assert.Equal(t, "", eth.EWASMInterpreter)
  	assert.Equal(t, "", eth.EVMInterpreter)
  	assert.Equal(t, uint64(25000000), eth.RPCGasCap)
  	assert.Equal(t, float64(1), eth.RPCTxFeeCap)
  	// Quorum
  	assert.Equal(t, time.Duration(3600000000000), eth.EVMCallTimeOut)
  	assert.Equal(t, true, eth.EnableNodePermission)
  	// End Quorum
  
  	// [Eth.Miner]
  	miner := eth.Miner
  	assert.Equal(t, uint64(700000000), miner.GasFloor)
  	assert.Equal(t, uint64(800000000), miner.GasCeil)
  	assert.Equal(t, big.NewInt(0), miner.GasPrice)
  	assert.Equal(t, time.Duration(3000000000), miner.Recommit)
  	assert.Equal(t, false, miner.Noverify)
  	assert.Equal(t, uint64(0), miner.AllowedFutureBlockTime)
  
  	// [Eth.GPO]
  	gpo := eth.GPO
  	assert.Equal(t, 20, gpo.Blocks)
  	assert.Equal(t, 60, gpo.Percentile)
  
  	// [Eth.TxPool]
  	txPool := eth.TxPool
  	assert.Equal(t, []common.Address{}, txPool.Locals)
  	assert.Equal(t, false, txPool.NoLocals)
  	assert.Equal(t, "transactions.rlp", txPool.Journal)
  	assert.Equal(t, time.Duration(3600000000000), txPool.Rejournal)
  	assert.Equal(t, uint64(1), txPool.PriceLimit)
  	assert.Equal(t, uint64(10), txPool.PriceBump)
  	assert.Equal(t, uint64(16), txPool.AccountSlots)
  	assert.Equal(t, uint64(4096), txPool.GlobalSlots)
  	assert.Equal(t, uint64(64), txPool.AccountQueue)
  	assert.Equal(t, uint64(1024), txPool.GlobalQueue)
  	assert.Equal(t, time.Duration(10800000000000), txPool.Lifetime)
  
  	// [Node]
  	node := cfg.Node
  	assert.Equal(t, "/data", node.DataDir)
  	assert.Equal(t, true, node.InsecureUnlockAllowed)
  	assert.Equal(t, true, node.NoUSB)
  	assert.Equal(t, "geth.ipc", node.IPCPath)
  	assert.Equal(t, "0.0.0.0", node.HTTPHost)
  	assert.Equal(t, 8545, node.HTTPPort)
  	assert.Equal(t, []string{"'*'"}, node.HTTPCors)
  	assert.Equal(t, []string{"'*'"}, node.HTTPVirtualHosts)
  	assert.Equal(t, []string{"admin", "db", "eth", "debug", "miner", "net", "txpool", "personal", "web3", "quorum", "istanbul"}, node.HTTPModules)
  	assert.Equal(t, "0.0.0.0", node.WSHost)
  	assert.Equal(t, 8546, node.WSPort)
  	assert.Equal(t, []string{"'*'"}, node.WSOrigins)
  	assert.Equal(t, []string{"admin", "db", "eth", "debug", "miner", "net", "txpool", "personal", "web3", "quorum", "istanbul"}, node.WSModules)
  	assert.Equal(t, []string{"'*'"}, node.GraphQLCors)
  	assert.Equal(t, []string{"'*'"}, node.GraphQLVirtualHosts)
  	assert.Equal(t, true, node.EnableNodePermission)
  
  	// [Node.P2P]
  	p2p := cfg.Node.P2P
  	assert.Equal(t, 50, p2p.MaxPeers)
  	assert.Equal(t, true, p2p.NoDiscovery)
  	assert.Equal(t, bootNodes(t).Nodes, p2p.BootstrapNodes)
  	assert.Equal(t, bootNodesV5(t).Nodes, p2p.BootstrapNodesV5)
  
  	/*assert.Equal(t, []*enode.Node{}, p2p.BootstrapNodes)
  	if p2p.BootstrapNodesV5 != nil {
  		assert.Equal(t, []*enode.Node{}, p2p.BootstrapNodesV5)
  	}*/
  	assert.Equal(t, ":30303", p2p.ListenAddr)
  	assert.Equal(t, false, p2p.EnableMsgEvents)
  
  	// [Node.HTTPTimeouts]
  	httpTimeouts := cfg.Node.HTTPTimeouts
  	assert.Equal(t, time.Duration(30000000000), httpTimeouts.ReadTimeout)
  	assert.Equal(t, time.Duration(30000000000), httpTimeouts.WriteTimeout)
  	assert.Equal(t, time.Duration(120000000000), httpTimeouts.IdleTimeout)
  
  	// QUORUM
  	// [Eth.Quorum.Istanbul]
  	istanbul := cfg.Eth.Istanbul
  	config := istanbul.GetConfig(nil)
  	assert.Equal(t, uint64(10000), config.RequestTimeout)
  	assert.Equal(t, uint64(5), config.BlockPeriod)
  	assert.Equal(t, uint64(30000), config.Epoch)
  	assert.Equal(t, big.NewInt(0), istanbul.Ceil2Nby3Block)
  	// END QUORUM
  }
  