diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go index 3f8717b40b..a257e6bc49 100644 --- a/cmd/geth/chaincmd.go +++ b/cmd/geth/chaincmd.go @@ -195,7 +195,7 @@ func initGenesis(ctx *cli.Context) error { defer stack.Close() for _, name := range []string{"chaindata", "lightchaindata"} { - chaindb, err := stack.OpenDatabaseWithFreezer(name, 0, 0, ctx.String(utils.AncientFlag.Name), "", false) + chaindb, err := stack.OpenDatabaseWithFreezer(name, 0, 0, ctx.String(utils.AncientFlag.Name), "", false, rawdb.ExtraDBConfig{}) if err != nil { utils.Fatalf("Failed to open database: %v", err) } @@ -229,7 +229,7 @@ func dumpGenesis(ctx *cli.Context) error { // dump whatever already exists in the datadir stack, _ := makeConfigNode(ctx) for _, name := range []string{"chaindata", "lightchaindata"} { - db, err := stack.OpenDatabase(name, 0, 0, "", true) + db, err := stack.OpenDatabase(name, 0, 0, "", true, rawdb.ExtraDBConfig{}) if err != nil { if !os.IsNotExist(err) { diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index fbb943ff7e..4e38f75a38 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -414,6 +414,31 @@ var ( Value: 50, Category: flags.PerfCategory, } + + LevelDbCompactionTableSizeFlag = &cli.Uint64Flag{ + Name: "leveldb.compaction.table.size", + Usage: "LevelDB SSTable/file size in mebibytes", + Category: flags.PerfCategory, + } + + LevelDbCompactionTableSizeMultiplierFlag = &cli.Float64Flag{ + Name: "leveldb.compaction.table.size.multiplier", + Usage: "Multiplier on LevelDB SSTable/file size. Size for a level is determined by: `leveldb.compaction.table.size * (leveldb.compaction.table.size.multiplier ^ Level)`", + Category: flags.PerfCategory, + } + + LevelDbCompactionTotalSizeFlag = &cli.Uint64Flag{ + Name: "leveldb.compaction.total.size", + Usage: "Total size in mebibytes of SSTables in a given LevelDB level. Size for a level is determined by: `leveldb.compaction.total.size * (leveldb.compaction.total.size.multiplier ^ Level)`", + Category: flags.PerfCategory, + } + + LevelDbCompactionTotalSizeMultiplierFlag = &cli.Float64Flag{ + Name: "leveldb.compaction.total.size.multiplier", + Usage: "Multiplier on level size on LevelDB levels. Size for a level is determined by: `leveldb.compaction.total.size * (leveldb.compaction.total.size.multiplier ^ Level)`", + Category: flags.PerfCategory, + } + CacheTrieFlag = &cli.IntFlag{ Name: "cache.trie", Usage: "Percentage of cache memory allowance to use for trie caching (default = 15% full mode, 30% archive mode)", @@ -2161,6 +2186,8 @@ func MakeChainDatabase(ctx *cli.Context, stack *node.Node, readonly bool) ethdb. err error chainDb ethdb.Database + + dbOptions = resolveExtraDBConfig(ctx) ) switch { @@ -2174,9 +2201,9 @@ func MakeChainDatabase(ctx *cli.Context, stack *node.Node, readonly bool) ethdb. chainDb = remotedb.New(client) case ctx.String(SyncModeFlag.Name) == "light": - chainDb, err = stack.OpenDatabase("lightchaindata", cache, handles, "", readonly) + chainDb, err = stack.OpenDatabase("lightchaindata", cache, handles, "", readonly, dbOptions) default: - chainDb, err = stack.OpenDatabaseWithFreezer("chaindata", cache, handles, ctx.String(AncientFlag.Name), "", readonly) + chainDb, err = stack.OpenDatabaseWithFreezer("chaindata", cache, handles, ctx.String(AncientFlag.Name), "", readonly, dbOptions) } if err != nil { @@ -2186,6 +2213,15 @@ func MakeChainDatabase(ctx *cli.Context, stack *node.Node, readonly bool) ethdb. return chainDb } +func resolveExtraDBConfig(ctx *cli.Context) rawdb.ExtraDBConfig { + return rawdb.ExtraDBConfig{ + LevelDBCompactionTableSize: ctx.Uint64(LevelDbCompactionTableSizeFlag.Name), + LevelDBCompactionTableSizeMultiplier: ctx.Float64(LevelDbCompactionTableSizeMultiplierFlag.Name), + LevelDBCompactionTotalSize: ctx.Uint64(LevelDbCompactionTotalSizeFlag.Name), + LevelDBCompactionTotalSizeMultiplier: ctx.Float64(LevelDbCompactionTotalSizeMultiplierFlag.Name), + } +} + func IsNetworkPreset(ctx *cli.Context) bool { for _, flag := range NetworkFlags { bFlag, _ := flag.(*cli.BoolFlag) diff --git a/core/rawdb/database.go b/core/rawdb/database.go index 42d1df6205..0801916db3 100644 --- a/core/rawdb/database.go +++ b/core/rawdb/database.go @@ -366,6 +366,14 @@ type OpenOptions struct { Cache int // the capacity(in megabytes) of the data caching Handles int // number of files to be open simultaneously ReadOnly bool + ExtraDBConfig ExtraDBConfig +} + +type ExtraDBConfig struct { + LevelDBCompactionTableSize uint64 // LevelDB SSTable/file size in mebibytes + LevelDBCompactionTableSizeMultiplier float64 // Multiplier on LevelDB SSTable/file size + LevelDBCompactionTotalSize uint64 // Total size in mebibytes of SSTables in a given LevelDB level + LevelDBCompactionTotalSizeMultiplier float64 // Multiplier on level size on LevelDB levels } // openKeyValueDatabase opens a disk-based key-value database, e.g. leveldb or pebble. diff --git a/core/txpool/legacypool/legacypool_test.go b/core/txpool/legacypool/legacypool_test.go index b7b5c14ef0..e9128f5215 100644 --- a/core/txpool/legacypool/legacypool_test.go +++ b/core/txpool/legacypool/legacypool_test.go @@ -1187,18 +1187,13 @@ func testQueueGlobalLimiting(t *testing.T, nolocals bool) { // // This logic should not hold for local transactions, unless the local tracking // mechanism is disabled. - -// nolint : paralleltest func TestQueueTimeLimiting(t *testing.T) { testQueueTimeLimiting(t, false) } - -// nolint : paralleltest func TestQueueTimeLimitingNoLocals(t *testing.T) { testQueueTimeLimiting(t, true) } -// nolint:gocognit,thelper func testQueueTimeLimiting(t *testing.T, nolocals bool) { // Reduce the eviction interval to a testable amount defer func(old time.Duration) { evictionInterval = old }(evictionInterval) @@ -1230,16 +1225,13 @@ func testQueueTimeLimiting(t *testing.T, nolocals bool) { if err := pool.addRemote(pricedTransaction(1, 100000, big.NewInt(1), remote)); err != nil { t.Fatalf("failed to add remote transaction: %v", err) } - pending, queued := pool.Stats() if pending != 0 { t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 0) } - if queued != 2 { t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2) } - if err := validatePoolInternals(pool); err != nil { t.Fatalf("pool internal state corrupted: %v", err) } @@ -1252,11 +1244,9 @@ func testQueueTimeLimiting(t *testing.T, nolocals bool) { if pending != 0 { t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 0) } - if queued != 2 { t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2) } - if err := validatePoolInternals(pool); err != nil { t.Fatalf("pool internal state corrupted: %v", err) } @@ -1268,7 +1258,6 @@ func testQueueTimeLimiting(t *testing.T, nolocals bool) { if pending != 0 { t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 0) } - if nolocals { if queued != 0 { t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0) @@ -1278,7 +1267,6 @@ func testQueueTimeLimiting(t *testing.T, nolocals bool) { t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 1) } } - if err := validatePoolInternals(pool); err != nil { t.Fatalf("pool internal state corrupted: %v", err) } @@ -1293,11 +1281,9 @@ func testQueueTimeLimiting(t *testing.T, nolocals bool) { if pending != 0 { t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 0) } - if queued != 0 { t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0) } - if err := validatePoolInternals(pool); err != nil { t.Fatalf("pool internal state corrupted: %v", err) } @@ -1306,22 +1292,18 @@ func testQueueTimeLimiting(t *testing.T, nolocals bool) { if err := pool.addLocal(pricedTransaction(4, 100000, big.NewInt(1), local)); err != nil { t.Fatalf("failed to add remote transaction: %v", err) } - if err := pool.addRemoteSync(pricedTransaction(4, 100000, big.NewInt(1), remote)); err != nil { t.Fatalf("failed to add remote transaction: %v", err) } - time.Sleep(5 * evictionInterval) // A half lifetime pass // Queue executable transactions, the life cycle should be restarted. if err := pool.addLocal(pricedTransaction(2, 100000, big.NewInt(1), local)); err != nil { t.Fatalf("failed to add remote transaction: %v", err) } - if err := pool.addRemoteSync(pricedTransaction(2, 100000, big.NewInt(1), remote)); err != nil { t.Fatalf("failed to add remote transaction: %v", err) } - time.Sleep(6 * evictionInterval) // All gapped transactions shouldn't be kicked out @@ -1329,23 +1311,19 @@ func testQueueTimeLimiting(t *testing.T, nolocals bool) { if pending != 2 { t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2) } - if queued != 2 { t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2) } - if err := validatePoolInternals(pool); err != nil { t.Fatalf("pool internal state corrupted: %v", err) } // The whole life time pass after last promotion, kick out stale transactions time.Sleep(2 * config.Lifetime) - pending, queued = pool.Stats() if pending != 2 { t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2) } - if nolocals { if queued != 0 { t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0) @@ -1355,7 +1333,6 @@ func testQueueTimeLimiting(t *testing.T, nolocals bool) { t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 1) } } - if err := validatePoolInternals(pool); err != nil { t.Fatalf("pool internal state corrupted: %v", err) } diff --git a/eth/backend.go b/eth/backend.go index 4b62818fc2..f14b7234de 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -117,18 +117,15 @@ type Ethereum struct { func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { // Ensure configuration values are compatible and sane if config.SyncMode == downloader.LightSync { - return nil, errors.New("can't run ethereum.Ethereum in light sync mode, use les.LightEthereum") + return nil, errors.New("can't run eth.Ethereum in light sync mode, use les.LightEthereum") } - if !config.SyncMode.IsValid() { return nil, fmt.Errorf("invalid sync mode %d", config.SyncMode) } - if config.Miner.GasPrice == nil || config.Miner.GasPrice.Cmp(common.Big0) <= 0 { log.Warn("Sanitizing invalid miner gas price", "provided", config.Miner.GasPrice, "updated", ethconfig.Defaults.Miner.GasPrice) config.Miner.GasPrice = new(big.Int).Set(ethconfig.Defaults.Miner.GasPrice) } - if config.NoPruning && config.TrieDirtyCache > 0 { if config.SnapshotCache > 0 { config.TrieCleanCache += config.TrieDirtyCache * 3 / 5 @@ -136,14 +133,13 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { } else { config.TrieCleanCache += config.TrieDirtyCache } - config.TrieDirtyCache = 0 } - log.Info("Allocated trie memory caches", "clean", common.StorageSize(config.TrieCleanCache)*1024*1024, "dirty", common.StorageSize(config.TrieDirtyCache)*1024*1024) + extraDBConfig := resolveExtraDBConfig(config) // Assemble the Ethereum object - chainDb, err := stack.OpenDatabaseWithFreezer("chaindata", config.DatabaseCache, config.DatabaseHandles, config.DatabaseFreezer, "ethereum/db/chaindata/", false) + chainDb, err := stack.OpenDatabaseWithFreezer("chaindata", config.DatabaseCache, config.DatabaseHandles, config.DatabaseFreezer, "ethereum/db/chaindata/", false, extraDBConfig) if err != nil { return nil, err } @@ -171,7 +167,6 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { bloomRequests: make(chan chan *bloombits.Retrieval), bloomIndexer: core.NewBloomIndexer(chainDb, params.BloomBitsBlocks, params.BloomConfirms), p2pServer: stack.Server(), - closeCh: make(chan struct{}), shutdownTracker: shutdowncheck.NewShutdownTracker(chainDb), } @@ -189,6 +184,13 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { // Override the chain config with provided settings. var overrides core.ChainOverrides + if config.OverrideCancun != nil { + overrides.OverrideCancun = config.OverrideCancun + } + if config.OverrideVerkle != nil { + overrides.OverrideVerkle = config.OverrideVerkle + } + chainConfig, _, genesisErr := core.SetupGenesisBlockWithOverride(chainDb, trie.NewDatabase(chainDb), config.Genesis, &overrides) if _, isCompat := genesisErr.(*params.ConfigCompatError); genesisErr != nil && !isCompat { return nil, genesisErr @@ -203,12 +205,10 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { // END: Bor changes bcVersion := rawdb.ReadDatabaseVersion(chainDb) - var dbVer = "" if bcVersion != nil { dbVer = fmt.Sprintf("%d", *bcVersion) } - log.Info("Initialising Ethereum protocol", "network", config.NetworkId, "dbversion", dbVer) if !config.SkipBcVersionCheck { @@ -218,16 +218,12 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { if bcVersion != nil { // only print warning on upgrade, not on init log.Warn("Upgrade blockchain database version", "from", dbVer, "to", core.BlockChainVersion) } - rawdb.WriteDatabaseVersion(chainDb, core.BlockChainVersion) } } - var ( vmConfig = vm.Config{ - EnablePreimageRecording: config.EnablePreimageRecording, - ParallelEnable: config.ParallelEVM.Enable, - ParallelSpeculativeProcesses: config.ParallelEVM.SpeculativeProcesses, + EnablePreimageRecording: config.EnablePreimageRecording, } cacheConfig = &core.CacheConfig{ TrieCleanLimit: config.TrieCleanCache, @@ -237,7 +233,6 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { TrieTimeLimit: config.TrieTimeout, SnapshotLimit: config.SnapshotCache, Preimages: config.Preimages, - TriesInMemory: config.TriesInMemory, } ) @@ -251,16 +246,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { eth.blockchain, err = core.NewBlockChain(chainDb, cacheConfig, config.Genesis, &overrides, eth.engine, vmConfig, eth.shouldPreserve, &config.TxLookupLimit, checker) } - // Override the chain config with provided settings. - if config.OverrideCancun != nil { - overrides.OverrideCancun = config.OverrideCancun - } - if config.OverrideVerkle != nil { - overrides.OverrideVerkle = config.OverrideVerkle - } - eth.APIBackend.gpo = gasprice.NewOracle(eth.APIBackend, gpoParams) - if err != nil { return nil, err } @@ -307,16 +293,14 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { } eth.miner = miner.New(eth, &config.Miner, eth.blockchain.Config(), eth.EventMux(), eth.engine, eth.isLocalBlock) - _ = eth.miner.SetExtra(makeExtraData(config.Miner.ExtraData)) + eth.miner.SetExtra(makeExtraData(config.Miner.ExtraData)) // Setup DNS discovery iterators. dnsclient := dnsdisc.NewClient(dnsdisc.Config{}) - eth.ethDialCandidates, err = dnsclient.NewIterator(eth.config.EthDiscoveryURLs...) if err != nil { return nil, err } - eth.snapDialCandidates, err = dnsclient.NewIterator(eth.config.SnapDiscoveryURLs...) if err != nil { return nil, err @@ -336,6 +320,15 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { return eth, nil } +func resolveExtraDBConfig(config *ethconfig.Config) rawdb.ExtraDBConfig { + return rawdb.ExtraDBConfig{ + LevelDBCompactionTableSize: config.LevelDbCompactionTableSize, + LevelDBCompactionTableSizeMultiplier: config.LevelDbCompactionTableSizeMultiplier, + LevelDBCompactionTotalSize: config.LevelDbCompactionTotalSize, + LevelDBCompactionTotalSizeMultiplier: config.LevelDbCompactionTotalSizeMultiplier, + } +} + func makeExtraData(extra []byte) []byte { if len(extra) == 0 { // create default extradata @@ -565,12 +558,14 @@ func (s *Ethereum) StopMining() { func (s *Ethereum) IsMining() bool { return s.miner.Mining() } func (s *Ethereum) Miner() *miner.Miner { return s.miner } -func (s *Ethereum) AccountManager() *accounts.Manager { return s.accountManager } -func (s *Ethereum) BlockChain() *core.BlockChain { return s.blockchain } -func (s *Ethereum) TxPool() *txpool.TxPool { return s.txPool } -func (s *Ethereum) EventMux() *event.TypeMux { return s.eventMux } -func (s *Ethereum) Engine() consensus.Engine { return s.engine } -func (s *Ethereum) ChainDb() ethdb.Database { return s.chainDb } +func (s *Ethereum) AccountManager() *accounts.Manager { return s.accountManager } +func (s *Ethereum) BlockChain() *core.BlockChain { return s.blockchain } +func (s *Ethereum) TxPool() *txpool.TxPool { return s.txPool } +func (s *Ethereum) EventMux() *event.TypeMux { return s.eventMux } +func (s *Ethereum) Engine() consensus.Engine { return s.engine } +func (s *Ethereum) ChainDb() ethdb.Database { + return s.chainDb +} func (s *Ethereum) IsListening() bool { return true } // Always listening func (s *Ethereum) Downloader() *downloader.Downloader { return s.handler.downloader } func (s *Ethereum) Synced() bool { return s.handler.acceptTxs.Load() } diff --git a/eth/catalyst/api_test.go b/eth/catalyst/api_test.go index f9e5b2744c..4149e38853 100644 --- a/eth/catalyst/api_test.go +++ b/eth/catalyst/api_test.go @@ -200,7 +200,6 @@ func TestEth2PrepareAndGetPayload(t *testing.T) { // We need to properly set the terminal total difficulty genesis.Config.TerminalTotalDifficulty.Sub(genesis.Config.TerminalTotalDifficulty, blocks[9].Difficulty()) n, ethservice := startEthService(t, genesis, blocks[:9]) - defer n.Close() api := NewConsensusAPI(ethservice) @@ -221,13 +220,11 @@ func TestEth2PrepareAndGetPayload(t *testing.T) { FinalizedBlockHash: common.Hash{}, } _, err := api.ForkchoiceUpdatedV1(fcState, &blockParams) - if err != nil { t.Fatalf("error preparing payload, err=%v", err) } // give the payload some time to be built time.Sleep(100 * time.Millisecond) - payloadID := (&miner.BuildPayloadArgs{ Parent: fcState.HeadBlockHash, Timestamp: blockParams.Timestamp, @@ -235,21 +232,17 @@ func TestEth2PrepareAndGetPayload(t *testing.T) { Random: blockParams.Random, }).Id() execData, err := api.GetPayloadV1(payloadID) - if err != nil { t.Fatalf("error getting payload, err=%v", err) } - if len(execData.Transactions) != blocks[9].Transactions().Len() { t.Fatalf("invalid number of transactions %d != 1", len(execData.Transactions)) } // Test invalid payloadID var invPayload engine.PayloadID - copy(invPayload[:], payloadID[:]) invPayload[0] = ^invPayload[0] _, err = api.GetPayloadV1(invPayload) - if err == nil { t.Fatal("expected error retrieving invalid payload") } diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go index eb18e7ad65..ad2faa73cc 100644 --- a/eth/ethconfig/config.go +++ b/eth/ethconfig/config.go @@ -126,6 +126,12 @@ type Config struct { DatabaseCache int DatabaseFreezer string + // Database - LevelDB options + LevelDbCompactionTableSize uint64 + LevelDbCompactionTableSizeMultiplier float64 + LevelDbCompactionTotalSize uint64 + LevelDbCompactionTotalSizeMultiplier float64 + TrieCleanCache int TrieDirtyCache int TrieTimeout time.Duration @@ -201,7 +207,6 @@ type Config struct { // CreateConsensusEngine creates a consensus engine for the given chain configuration. func CreateConsensusEngine(chainConfig *params.ChainConfig, ethConfig *Config, db ethdb.Database, blockchainAPI *ethapi.BlockChainAPI) (consensus.Engine, error) { - var engine consensus.Engine // nolint:nestif if chainConfig.Clique != nil { return beacon.New(clique.New(chainConfig.Clique, db)), nil @@ -230,11 +235,9 @@ func CreateConsensusEngine(chainConfig *params.ChainConfig, ethConfig *Config, d return bor.New(chainConfig, db, blockchainAPI, spanner, heimdallClient, genesisContractsClient, false), nil } - } else if !chainConfig.TerminalTotalDifficultyPassed { - return nil, errors.New("ethash is only supported as a historical component of already merged networks") - } else { - engine = ethash.NewFaker() } - - return beacon.New(engine), nil + if !chainConfig.TerminalTotalDifficultyPassed { + return nil, errors.New("ethash is only supported as a historical component of already merged networks") + } + return beacon.New(ethash.NewFaker()), nil } diff --git a/eth/fetcher/tx_fetcher.go b/eth/fetcher/tx_fetcher.go index b2de199dae..02342a8ac2 100644 --- a/eth/fetcher/tx_fetcher.go +++ b/eth/fetcher/tx_fetcher.go @@ -193,24 +193,25 @@ func NewTxFetcherForTests( hasTx func(common.Hash) bool, addTxs func([]*txpool.Transaction) []error, fetchTxs func(string, []common.Hash) error, clock mclock.Clock, rand *mrand.Rand, txArrivalWait time.Duration) *TxFetcher { return &TxFetcher{ - notify: make(chan *txAnnounce), - cleanup: make(chan *txDelivery), - drop: make(chan *txDrop), - quit: make(chan struct{}), - waitlist: make(map[common.Hash]map[string]struct{}), - waittime: make(map[common.Hash]mclock.AbsTime), - waitslots: make(map[string]map[common.Hash]struct{}), - announces: make(map[string]map[common.Hash]struct{}), - announced: make(map[common.Hash]map[string]struct{}), - fetching: make(map[common.Hash]string), - requests: make(map[string]*txRequest), - alternates: make(map[common.Hash]map[string]struct{}), - underpriced: mapset.NewSet[common.Hash](), - hasTx: hasTx, - addTxs: addTxs, - fetchTxs: fetchTxs, - clock: clock, - rand: rand, + notify: make(chan *txAnnounce), + cleanup: make(chan *txDelivery), + drop: make(chan *txDrop), + quit: make(chan struct{}), + waitlist: make(map[common.Hash]map[string]struct{}), + waittime: make(map[common.Hash]mclock.AbsTime), + waitslots: make(map[string]map[common.Hash]struct{}), + announces: make(map[string]map[common.Hash]struct{}), + announced: make(map[common.Hash]map[string]struct{}), + fetching: make(map[common.Hash]string), + requests: make(map[string]*txRequest), + alternates: make(map[common.Hash]map[string]struct{}), + underpriced: mapset.NewSet[common.Hash](), + hasTx: hasTx, + addTxs: addTxs, + fetchTxs: fetchTxs, + clock: clock, + rand: rand, + txArrivalWait: txArrivalWait, } } diff --git a/eth/tracers/api_test.go b/eth/tracers/api_test.go index 4f37d26fda..1e6668b4d7 100644 --- a/eth/tracers/api_test.go +++ b/eth/tracers/api_test.go @@ -497,6 +497,12 @@ func TestTraceBlock(t *testing.T) { } } +// txTraceResult is the result of a single transaction trace. +type txTraceResultTest struct { + Result interface{} `json:"result,omitempty"` // Trace results produced by the tracer + Error string `json:"error,omitempty"` // Trace failure produced by the tracer +} + func TestIOdump(t *testing.T) { t.Parallel() @@ -558,12 +564,22 @@ func TestIOdump(t *testing.T) { continue } + // Done As txTraceResult struct was changed during Cancun changes + resArr := make([]*txTraceResultTest, 0) + for _, res := range result { + res := &txTraceResultTest{ + Result: res.Result, + Error: res.Error, + } + resArr = append(resArr, res) + } + if err != nil { t.Errorf("test %d, want no error, have %v", i, err) continue } - have, err := json.Marshal(result) + have, err := json.Marshal(resArr) if err != nil { t.Errorf("Error in Marshal: %v", err) } diff --git a/internal/cli/snapshot.go b/internal/cli/snapshot.go index ec82614aa4..3555abccad 100644 --- a/internal/cli/snapshot.go +++ b/internal/cli/snapshot.go @@ -6,6 +6,7 @@ import ( "strings" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/state/pruner" "github.com/ethereum/go-ethereum/internal/cli/flagset" "github.com/ethereum/go-ethereum/internal/cli/server" @@ -161,7 +162,7 @@ func (c *PruneStateCommand) Run(args []string) int { return 1 } - chaindb, err := node.OpenDatabaseWithFreezer(chaindataPath, int(c.cache), dbHandles, c.datadirAncient, "", false) + chaindb, err := node.OpenDatabaseWithFreezer(chaindataPath, int(c.cache), dbHandles, c.datadirAncient, "", false, rawdb.ExtraDBConfig{}) if err != nil { c.UI.Error(err.Error()) diff --git a/internal/ethapi/api_test.go b/internal/ethapi/api_test.go index d9f7864467..436e36e6a6 100644 --- a/internal/ethapi/api_test.go +++ b/internal/ethapi/api_test.go @@ -570,7 +570,7 @@ func (b testBackend) PurgeWhitelistedCheckpoint() { } func (b testBackend) RPCRpcReturnDataLimit() uint64 { - panic("implement me") + return 0 } func (b testBackend) SubscribeChain2HeadEvent(ch chan<- core.Chain2HeadEvent) event.Subscription { diff --git a/les/client.go b/les/client.go index 6f2ad4bf60..cb8e7ba160 100644 --- a/les/client.go +++ b/les/client.go @@ -83,11 +83,12 @@ type LightEthereum struct { // New creates an instance of the light client. func New(stack *node.Node, config *ethconfig.Config) (*LightEthereum, error) { - chainDb, err := stack.OpenDatabase("lightchaindata", config.DatabaseCache, config.DatabaseHandles, "eth/db/chaindata/", false) + extraDBConfig := resolveExtraDBConfig(config) + chainDb, err := stack.OpenDatabase("lightchaindata", config.DatabaseCache, config.DatabaseHandles, "eth/db/chaindata/", false, extraDBConfig) if err != nil { return nil, err } - lesDb, err := stack.OpenDatabase("les.client", 0, 0, "eth/db/lesclient/", false) + lesDb, err := stack.OpenDatabase("les.client", 0, 0, "eth/db/lesclient/", false, extraDBConfig) if err != nil { return nil, err } @@ -203,6 +204,15 @@ func New(stack *node.Node, config *ethconfig.Config) (*LightEthereum, error) { return leth, nil } +func resolveExtraDBConfig(config *ethconfig.Config) rawdb.ExtraDBConfig { + return rawdb.ExtraDBConfig{ + LevelDBCompactionTableSize: config.LevelDbCompactionTableSize, + LevelDBCompactionTableSizeMultiplier: config.LevelDbCompactionTableSizeMultiplier, + LevelDBCompactionTotalSize: config.LevelDbCompactionTotalSize, + LevelDBCompactionTotalSizeMultiplier: config.LevelDbCompactionTotalSizeMultiplier, + } +} + // VfluxRequest sends a batch of requests to the given node through discv5 UDP TalkRequest and returns the responses func (s *LightEthereum) VfluxRequest(n *enode.Node, reqs vflux.Requests) vflux.Replies { if !s.udpEnabled { diff --git a/les/server.go b/les/server.go index d84856c7fb..1e2642fa4c 100644 --- a/les/server.go +++ b/les/server.go @@ -78,7 +78,8 @@ type LesServer struct { } func NewLesServer(node *node.Node, e ethBackend, config *ethconfig.Config) (*LesServer, error) { - lesDb, err := node.OpenDatabase("les.server", 0, 0, "eth/db/lesserver/", false) + dbOptions := resolveExtraDBConfig(config) + lesDb, err := node.OpenDatabase("les.server", 0, 0, "eth/db/lesserver/", false, dbOptions) if err != nil { return nil, err } diff --git a/node/node.go b/node/node.go index 190e1c6b26..f9b910798c 100644 --- a/node/node.go +++ b/node/node.go @@ -780,7 +780,7 @@ func (n *Node) EventMux() *event.TypeMux { // OpenDatabase opens an existing database with the given name (or creates one if no // previous can be found) from within the node's instance directory. If the node is // ephemeral, a memory database is returned. -func (n *Node) OpenDatabase(name string, cache, handles int, namespace string, readonly bool) (ethdb.Database, error) { +func (n *Node) OpenDatabase(name string, cache, handles int, namespace string, readonly bool, extraDBConfig rawdb.ExtraDBConfig) (ethdb.Database, error) { n.lock.Lock() defer n.lock.Unlock() @@ -796,12 +796,13 @@ func (n *Node) OpenDatabase(name string, cache, handles int, namespace string, r db = rawdb.NewMemoryDatabase() } else { db, err = rawdb.Open(rawdb.OpenOptions{ - Type: n.config.DBEngine, - Directory: n.ResolvePath(name), - Namespace: namespace, - Cache: cache, - Handles: handles, - ReadOnly: readonly, + Type: n.config.DBEngine, + Directory: n.ResolvePath(name), + Namespace: namespace, + Cache: cache, + Handles: handles, + ReadOnly: readonly, + ExtraDBConfig: extraDBConfig, }) } @@ -817,7 +818,7 @@ func (n *Node) OpenDatabase(name string, cache, handles int, namespace string, r // also attaching a chain freezer to it that moves ancient chain data from the // database to immutable append-only files. If the node is an ephemeral one, a // memory database is returned. -func (n *Node) OpenDatabaseWithFreezer(name string, cache, handles int, ancient string, namespace string, readonly bool) (ethdb.Database, error) { +func (n *Node) OpenDatabaseWithFreezer(name string, cache int, handles int, ancient string, namespace string, readonly bool, extraDBConfig rawdb.ExtraDBConfig) (ethdb.Database, error) { n.lock.Lock() defer n.lock.Unlock() @@ -840,6 +841,7 @@ func (n *Node) OpenDatabaseWithFreezer(name string, cache, handles int, ancient Cache: cache, Handles: handles, ReadOnly: readonly, + ExtraDBConfig: extraDBConfig, }) } diff --git a/node/node_auth_test.go b/node/node_auth_test.go index ed6462c526..597cd8531f 100644 --- a/node/node_auth_test.go +++ b/node/node_auth_test.go @@ -26,10 +26,9 @@ import ( "testing" "time" - "github.com/golang-jwt/jwt/v4" - "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/rpc" + "github.com/golang-jwt/jwt/v4" ) type helloRPC string @@ -49,7 +48,6 @@ type authTest struct { func (at *authTest) Run(t *testing.T) { ctx := context.Background() - cl, err := rpc.DialOptions(ctx, at.endpoint, rpc.WithHTTPAuth(at.prov)) if at.expectDialFail { if err == nil { @@ -58,13 +56,11 @@ func (at *authTest) Run(t *testing.T) { return } } - if err != nil { t.Fatalf("failed to dial rpc endpoint: %v", err) } var x string - err = cl.CallContext(ctx, &x, "engine_helloWorld") if at.expectCall1Fail { if err == nil { @@ -73,11 +69,9 @@ func (at *authTest) Run(t *testing.T) { return } } - if err != nil { t.Fatalf("failed to call rpc endpoint: %v", err) } - if x != "hello engine" { t.Fatalf("method was silent but did not return expected value: %q", x) } @@ -90,17 +84,14 @@ func (at *authTest) Run(t *testing.T) { return } } - if err != nil { t.Fatalf("failed to call rpc endpoint: %v", err) } - if x != "hello eth" { t.Fatalf("method was silent but did not return expected value: %q", x) } } -// nolint: tparallel, paralleltest func TestAuthEndpoints(t *testing.T) { var secret [32]byte if _, err := crand.Read(secret[:]); err != nil { @@ -211,27 +202,22 @@ func noneAuth(secret [32]byte) rpc.HTTPAuth { token := jwt.NewWithClaims(jwt.SigningMethodNone, jwt.MapClaims{ "iat": &jwt.NumericDate{Time: time.Now()}, }) - s, err := token.SignedString(secret[:]) if err != nil { return fmt.Errorf("failed to create JWT token: %w", err) } - header.Set("Authorization", "Bearer "+s) - return nil } } func changingAuth(provs ...rpc.HTTPAuth) rpc.HTTPAuth { i := 0 - return func(header http.Header) error { i += 1 if i > len(provs) { i = len(provs) } - return provs[i-1](header) } } @@ -241,14 +227,11 @@ func offsetTimeAuth(secret [32]byte, offset time.Duration) rpc.HTTPAuth { token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{ "iat": &jwt.NumericDate{Time: time.Now().Add(offset)}, }) - s, err := token.SignedString(secret[:]) if err != nil { return fmt.Errorf("failed to create JWT token: %w", err) } - header.Set("Authorization", "Bearer "+s) - return nil } } diff --git a/node/node_test.go b/node/node_test.go index dc291f5d91..f53b003684 100644 --- a/node/node_test.go +++ b/node/node_test.go @@ -26,6 +26,7 @@ import ( "strings" "testing" + "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/p2p" @@ -157,7 +158,7 @@ func TestNodeCloseClosesDB(t *testing.T) { stack, _ := New(testNodeConfig()) defer stack.Close() - db, err := stack.OpenDatabase("mydb", 0, 0, "", false) + db, err := stack.OpenDatabase("mydb", 0, 0, "", false, rawdb.ExtraDBConfig{}) if err != nil { t.Fatal("can't open DB:", err) } @@ -184,7 +185,7 @@ func TestNodeOpenDatabaseFromLifecycleStart(t *testing.T) { stack.RegisterLifecycle(&InstrumentedService{ startHook: func() { - db, err = stack.OpenDatabase("mydb", 0, 0, "", false) + db, err = stack.OpenDatabase("mydb", 0, 0, "", false, rawdb.ExtraDBConfig{}) if err != nil { t.Fatal("can't open DB:", err) } @@ -205,7 +206,7 @@ func TestNodeOpenDatabaseFromLifecycleStop(t *testing.T) { stack.RegisterLifecycle(&InstrumentedService{ stopHook: func() { - db, err := stack.OpenDatabase("mydb", 0, 0, "", false) + db, err := stack.OpenDatabase("mydb", 0, 0, "", false, rawdb.ExtraDBConfig{}) if err != nil { t.Fatal("can't open DB:", err) } diff --git a/node/rpcstack_test.go b/node/rpcstack_test.go index e0db8786b9..0eb1079180 100644 --- a/node/rpcstack_test.go +++ b/node/rpcstack_test.go @@ -306,15 +306,11 @@ func rpcRequest(t *testing.T, url, method string, extraHeaders ...string) *http. } func batchRpcRequest(t *testing.T, url string, methods []string, extraHeaders ...string) *http.Response { - t.Helper() - reqs := make([]string, len(methods)) for i, m := range methods { reqs[i] = fmt.Sprintf(`{"jsonrpc":"2.0","id":1,"method":"%s","params":[]}`, m) } - body := fmt.Sprintf(`[%s]`, strings.Join(reqs, ",")) - return baseRpcRequest(t, url, body, extraHeaders...) } @@ -323,12 +319,10 @@ func baseRpcRequest(t *testing.T, url, bodyStr string, extraHeaders ...string) * // Create the request. body := bytes.NewReader([]byte(bodyStr)) - - req, err := http.NewRequestWithContext(context.Background(), http.MethodPost, url, body) + req, err := http.NewRequest(http.MethodPost, url, body) if err != nil { t.Fatal("could not create http request:", err) } - req.Header.Set("content-type", "application/json") req.Header.Set("accept-encoding", "identity") @@ -336,7 +330,6 @@ func baseRpcRequest(t *testing.T, url, bodyStr string, extraHeaders ...string) * if len(extraHeaders)%2 != 0 { panic("odd extraHeaders length") } - for i := 0; i < len(extraHeaders); i += 2 { key, value := extraHeaders[i], extraHeaders[i+1] if strings.EqualFold(key, "host") { @@ -348,14 +341,11 @@ func baseRpcRequest(t *testing.T, url, bodyStr string, extraHeaders ...string) * // Perform the request. t.Logf("checking RPC/HTTP on %s %v", url, extraHeaders) - resp, err := http.DefaultClient.Do(req) if err != nil { t.Fatal(err) } - t.Cleanup(func() { resp.Body.Close() }) - return resp } @@ -367,14 +357,11 @@ func (testClaim) Valid() error { func TestJWT(t *testing.T) { var secret = []byte("secret") - issueToken := func(secret []byte, method jwt.SigningMethod, input map[string]interface{}) string { if method == nil { method = jwt.SigningMethodHS256 } - ss, _ := jwt.NewWithClaims(method, testClaim(input)).SignedString(secret) - return ss } cfg := rpcEndpointConfig{jwtSecret: []byte("secret")} @@ -412,9 +399,7 @@ func TestJWT(t *testing.T) { if err := wsRequest(t, wsUrl, "Authorization", token); err != nil { t.Errorf("test %d-ws, token '%v': expected ok, got %v", i, token, err) } - token = tokenFn() - // nolint:bodyclose if resp := rpcRequest(t, htUrl, testMethod, "Authorization", token); resp.StatusCode != 200 { t.Errorf("test %d-http, token '%v': expected ok, got %v", i, token, resp.StatusCode) } @@ -423,7 +408,7 @@ func TestJWT(t *testing.T) { expFail := []func() string{ // future func() string { - return fmt.Sprintf("Bearer %v", issueToken(secret, nil, testClaim{"iat": time.Now().Unix() + int64(jwtExpiryTimeout.Seconds()) + 1})) + return fmt.Sprintf("Bearer %v", issueToken(secret, nil, testClaim{"iat": time.Now().Unix() + int64(jwtExpiryTimeout.Seconds()) + 2})) }, // stale func() string { @@ -474,9 +459,6 @@ func TestJWT(t *testing.T) { return fmt.Sprintf("Bearer \t%v", issueToken(secret, nil, testClaim{"iat": time.Now().Unix()})) }, } - - var resp *http.Response - for i, tokenFn := range expFail { token := tokenFn() if err := wsRequest(t, wsUrl, "Authorization", token); err == nil { @@ -484,14 +466,11 @@ func TestJWT(t *testing.T) { } token = tokenFn() - resp = rpcRequest(t, htUrl, testMethod, "Authorization", token) - + resp := rpcRequest(t, htUrl, testMethod, "Authorization", token) if resp.StatusCode != http.StatusUnauthorized { t.Errorf("tc %d-http, token '%v': expected not to allow, got %v", i, token, resp.StatusCode) } } - - defer resp.Body.Close() srv.stop() }