diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go index c3c68b5896..d25168aacf 100644 --- a/cmd/geth/chaincmd.go +++ b/cmd/geth/chaincmd.go @@ -578,7 +578,7 @@ func parseDumpConfig(ctx *cli.Context, db ethdb.Database) (*state.DumpConfig, co arg := ctx.Args().First() if hashish(arg) { hash := common.HexToHash(arg) - if number := rawdb.ReadHeaderNumber(db, hash); number != rawdb.EmptyNumber { + if number, ok := rawdb.ReadHeaderNumber(db, hash); ok { header = rawdb.ReadHeader(db, hash, number) } else { return nil, common.Hash{}, fmt.Errorf("block %x not found", hash) diff --git a/core/blockchain_reader.go b/core/blockchain_reader.go index 64eb6aa6f9..0d56dee78f 100644 --- a/core/blockchain_reader.go +++ b/core/blockchain_reader.go @@ -88,7 +88,7 @@ func (bc *BlockChain) GetHeaderByNumber(number uint64) *types.Header { // GetBlockNumber retrieves the block number associated with a block hash. func (bc *BlockChain) GetBlockNumber(hash common.Hash) *uint64 { - if num := bc.hc.GetBlockNumber(hash); num != rawdb.EmptyNumber { + if num, ok := bc.hc.GetBlockNumber(hash); ok { return &num } return nil @@ -107,8 +107,8 @@ func (bc *BlockChain) GetBody(hash common.Hash) *types.Body { if cached, ok := bc.bodyCache.Get(hash); ok { return cached } - number := bc.hc.GetBlockNumber(hash) - if number == rawdb.EmptyNumber { + number, ok := bc.hc.GetBlockNumber(hash) + if !ok { return nil } body := rawdb.ReadBody(bc.db, hash, number) @@ -127,8 +127,8 @@ func (bc *BlockChain) GetBodyRLP(hash common.Hash) rlp.RawValue { if cached, ok := bc.bodyRLPCache.Get(hash); ok { return cached } - number := bc.hc.GetBlockNumber(hash) - if number == rawdb.EmptyNumber { + number, ok := bc.hc.GetBlockNumber(hash) + if !ok { return nil } body := rawdb.ReadBodyRLP(bc.db, hash, number) @@ -180,8 +180,8 @@ func (bc *BlockChain) GetBlock(hash common.Hash, number uint64) *types.Block { // GetBlockByHash retrieves a block from the database by hash, caching it if found. func (bc *BlockChain) GetBlockByHash(hash common.Hash) *types.Block { - number := bc.hc.GetBlockNumber(hash) - if number == rawdb.EmptyNumber { + number, ok := bc.hc.GetBlockNumber(hash) + if !ok { return nil } return bc.GetBlock(hash, number) @@ -200,8 +200,8 @@ func (bc *BlockChain) GetBlockByNumber(number uint64) *types.Block { // GetBlocksFromHash returns the block corresponding to hash and up to n-1 ancestors. // [deprecated by eth/62] func (bc *BlockChain) GetBlocksFromHash(hash common.Hash, n int) (blocks []*types.Block) { - number := bc.hc.GetBlockNumber(hash) - if number == rawdb.EmptyNumber { + number, ok := bc.hc.GetBlockNumber(hash) + if !ok { return nil } for i := 0; i < n; i++ { @@ -221,8 +221,8 @@ func (bc *BlockChain) GetReceiptsByHash(hash common.Hash) types.Receipts { if receipts, ok := bc.receiptsCache.Get(hash); ok { return receipts } - number := rawdb.ReadHeaderNumber(bc.db, hash) - if number == rawdb.EmptyNumber { + number, ok := rawdb.ReadHeaderNumber(bc.db, hash) + if !ok { return nil } header := bc.GetHeader(hash, number) @@ -248,8 +248,8 @@ func (bc *BlockChain) GetRawReceipts(hash common.Hash, number uint64) types.Rece // GetReceiptsRLP retrieves the receipts of a block. func (bc *BlockChain) GetReceiptsRLP(hash common.Hash) rlp.RawValue { - number := rawdb.ReadHeaderNumber(bc.db, hash) - if number == rawdb.EmptyNumber { + number, ok := rawdb.ReadHeaderNumber(bc.db, hash) + if !ok { return nil } return rawdb.ReadReceiptsRLP(bc.db, hash, number) diff --git a/core/blockchain_test.go b/core/blockchain_test.go index 15d45ed9b6..ad5da975ca 100644 --- a/core/blockchain_test.go +++ b/core/blockchain_test.go @@ -778,13 +778,13 @@ func testFastVsFullChains(t *testing.T, scheme string) { } // Check that hash-to-number mappings are present in all databases. - if m := rawdb.ReadHeaderNumber(fastDb, hash); m == rawdb.EmptyNumber || m != num { + if m, ok := rawdb.ReadHeaderNumber(fastDb, hash); !ok || m != num { t.Errorf("block #%d [%x]: wrong hash-to-number mapping in fastdb: %v", num, hash, m) } - if m := rawdb.ReadHeaderNumber(ancientDb, hash); m == rawdb.EmptyNumber || m != num { + if m, ok := rawdb.ReadHeaderNumber(ancientDb, hash); !ok || m != num { t.Errorf("block #%d [%x]: wrong hash-to-number mapping in ancientdb: %v", num, hash, m) } - if m := rawdb.ReadHeaderNumber(archiveDb, hash); m == rawdb.EmptyNumber || m != num { + if m, ok := rawdb.ReadHeaderNumber(archiveDb, hash); !ok || m != num { t.Errorf("block #%d [%x]: wrong hash-to-number mapping in archivedb: %v", num, hash, m) } } diff --git a/core/headerchain.go b/core/headerchain.go index be814757ad..a33222e9fd 100644 --- a/core/headerchain.go +++ b/core/headerchain.go @@ -97,15 +97,15 @@ func NewHeaderChain(chainDb ethdb.Database, config *params.ChainConfig, engine c // GetBlockNumber retrieves the block number belonging to the given hash // from the cache or database -func (hc *HeaderChain) GetBlockNumber(hash common.Hash) uint64 { +func (hc *HeaderChain) GetBlockNumber(hash common.Hash) (uint64, bool) { if cached, ok := hc.numberCache.Get(hash); ok { - return cached + return cached, true } - number := rawdb.ReadHeaderNumber(hc.chainDb, hash) - if number != rawdb.EmptyNumber { + number, ok := rawdb.ReadHeaderNumber(hc.chainDb, hash) + if ok { hc.numberCache.Add(hash, number) } - return number + return number, ok } type headerWriteResult struct { @@ -402,8 +402,8 @@ func (hc *HeaderChain) GetHeader(hash common.Hash, number uint64) *types.Header // GetHeaderByHash retrieves a block header from the database by hash, caching it if // found. func (hc *HeaderChain) GetHeaderByHash(hash common.Hash) *types.Header { - number := hc.GetBlockNumber(hash) - if number == rawdb.EmptyNumber { + number, ok := hc.GetBlockNumber(hash) + if !ok { return nil } return hc.GetHeader(hash, number) diff --git a/core/rawdb/accessors_chain.go b/core/rawdb/accessors_chain.go index 7e1970d6ec..6a5d09c542 100644 --- a/core/rawdb/accessors_chain.go +++ b/core/rawdb/accessors_chain.go @@ -142,16 +142,14 @@ func ReadAllCanonicalHashes(db ethdb.Iteratee, from uint64, to uint64, limit int return numbers, hashes } -const EmptyNumber = ^uint64(0) - // ReadHeaderNumber returns the header number assigned to a hash. -func ReadHeaderNumber(db ethdb.KeyValueReader, hash common.Hash) uint64 { +func ReadHeaderNumber(db ethdb.KeyValueReader, hash common.Hash) (uint64, bool) { data, _ := db.Get(headerNumberKey(hash)) if len(data) != 8 { - return EmptyNumber + return 0, false } number := binary.BigEndian.Uint64(data) - return number + return number, true } // WriteHeaderNumber stores the hash->number mapping. @@ -909,8 +907,8 @@ func ReadHeadHeader(db ethdb.Reader) *types.Header { if headHeaderHash == (common.Hash{}) { return nil } - headHeaderNumber := ReadHeaderNumber(db, headHeaderHash) - if headHeaderNumber == EmptyNumber { + headHeaderNumber, ok := ReadHeaderNumber(db, headHeaderHash) + if !ok { return nil } return ReadHeader(db, headHeaderHash, headHeaderNumber) @@ -922,8 +920,8 @@ func ReadHeadBlock(db ethdb.Reader) *types.Block { if headBlockHash == (common.Hash{}) { return nil } - headBlockNumber := ReadHeaderNumber(db, headBlockHash) - if headBlockNumber == EmptyNumber { + headBlockNumber, ok := ReadHeaderNumber(db, headBlockHash) + if !ok { return nil } return ReadBlock(db, headBlockHash, headBlockNumber) diff --git a/core/rawdb/accessors_indexes.go b/core/rawdb/accessors_indexes.go index fa354440bc..8c420e0457 100644 --- a/core/rawdb/accessors_indexes.go +++ b/core/rawdb/accessors_indexes.go @@ -39,7 +39,10 @@ func DecodeTxLookupEntry(data []byte, db ethdb.Reader) *uint64 { } // Database v4-v5 tx lookup format just stores the hash if len(data) == common.HashLength { - number := ReadHeaderNumber(db, common.BytesToHash(data)) + number, ok := ReadHeaderNumber(db, common.BytesToHash(data)) + if !ok { + return nil + } return &number } // Finally try database v3 tx lookup format diff --git a/core/rawdb/chain_freezer.go b/core/rawdb/chain_freezer.go index e6d89a4d29..0c556e56d2 100644 --- a/core/rawdb/chain_freezer.go +++ b/core/rawdb/chain_freezer.go @@ -95,8 +95,8 @@ func (f *chainFreezer) readHeadNumber(db ethdb.KeyValueReader) uint64 { log.Error("Head block is not reachable") return 0 } - number := ReadHeaderNumber(db, hash) - if number == EmptyNumber { + number, ok := ReadHeaderNumber(db, hash) + if !ok { log.Error("Number of head block is missing") return 0 } @@ -110,8 +110,8 @@ func (f *chainFreezer) readFinalizedNumber(db ethdb.KeyValueReader) uint64 { if hash == (common.Hash{}) { return 0 } - number := ReadHeaderNumber(db, hash) - if number == EmptyNumber { + number, ok := ReadHeaderNumber(db, hash) + if !ok { log.Error("Number of finalized block is missing") return 0 } diff --git a/core/rawdb/database.go b/core/rawdb/database.go index 6c6bd401e0..38d2e5f1b4 100644 --- a/core/rawdb/database.go +++ b/core/rawdb/database.go @@ -243,7 +243,12 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, ancient string, namespace st if kvhash, _ := db.Get(headerHashKey(frozen)); len(kvhash) == 0 { // Subsequent header after the freezer limit is missing from the database. // Reject startup if the database has a more recent head. - if head := ReadHeaderNumber(db, ReadHeadHeaderHash(db)); head > frozen-1 { + head, ok := ReadHeaderNumber(db, ReadHeadHeaderHash(db)) + if !ok { + printChainMetadata(db) + return nil, fmt.Errorf("could not read header number, hash %v", ReadHeadHeaderHash(db)) + } + if head > frozen-1 { // Find the smallest block stored in the key-value store // in range of [frozen, head] var number uint64 diff --git a/core/txindexer.go b/core/txindexer.go index 813e5641f1..b2a94a6ead 100644 --- a/core/txindexer.go +++ b/core/txindexer.go @@ -217,8 +217,8 @@ func (indexer *txIndexer) resolveHead() uint64 { if headBlockHash == (common.Hash{}) { return 0 } - headBlockNumber := rawdb.ReadHeaderNumber(indexer.db, headBlockHash) - if headBlockNumber == rawdb.EmptyNumber { + headBlockNumber, ok := rawdb.ReadHeaderNumber(indexer.db, headBlockHash) + if !ok { return 0 } return headBlockNumber diff --git a/eth/filters/filter_system_test.go b/eth/filters/filter_system_test.go index df80e099c1..ea9ea2a37a 100644 --- a/eth/filters/filter_system_test.go +++ b/eth/filters/filter_system_test.go @@ -92,15 +92,15 @@ func (b *testBackend) HeaderByNumber(ctx context.Context, blockNr rpc.BlockNumbe switch blockNr { case rpc.LatestBlockNumber: hash = rawdb.ReadHeadBlockHash(b.db) - number := rawdb.ReadHeaderNumber(b.db, hash) - if number == rawdb.EmptyNumber { + number, ok := rawdb.ReadHeaderNumber(b.db, hash) + if !ok { return nil, nil } num = number case rpc.FinalizedBlockNumber: hash = rawdb.ReadFinalizedBlockHash(b.db) - number := rawdb.ReadHeaderNumber(b.db, hash) - if number == rawdb.EmptyNumber { + number, ok := rawdb.ReadHeaderNumber(b.db, hash) + if !ok { return nil, nil } num = number @@ -114,8 +114,8 @@ func (b *testBackend) HeaderByNumber(ctx context.Context, blockNr rpc.BlockNumbe } func (b *testBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) { - number := rawdb.ReadHeaderNumber(b.db, hash) - if number == rawdb.EmptyNumber { + number, ok := rawdb.ReadHeaderNumber(b.db, hash) + if !ok { return nil, nil } return rawdb.ReadHeader(b.db, hash, number), nil @@ -129,7 +129,7 @@ func (b *testBackend) GetBody(ctx context.Context, hash common.Hash, number rpc. } func (b *testBackend) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) { - if number := rawdb.ReadHeaderNumber(b.db, hash); number != rawdb.EmptyNumber { + if number, ok := rawdb.ReadHeaderNumber(b.db, hash); ok { if header := rawdb.ReadHeader(b.db, hash, number); header != nil { return rawdb.ReadReceipts(b.db, hash, number, header.Time, params.TestChainConfig), nil } diff --git a/log/logger_test.go b/log/logger_test.go index 3ec6d2e19c..efc3450126 100644 --- a/log/logger_test.go +++ b/log/logger_test.go @@ -76,6 +76,18 @@ func BenchmarkTraceLogging(b *testing.B) { } } +func BenchmarkVmodule(b *testing.B) { + out := new(bytes.Buffer) + glog := NewGlogHandler(NewTerminalHandlerWithLevel(out, LevelTrace, false)) + glog.Verbosity(LevelCrit) + logger := NewLogger(glog) + glog.Vmodule("logger_test.go=5") + for i := 0; i < b.N; i++ { + logger.Warn("This should not be seen", "ignored", "true") + logger.Trace("a message", "foo", "bar") + } +} + func BenchmarkTerminalHandler(b *testing.B) { l := NewLogger(NewTerminalHandler(io.Discard, false)) benchmarkLogger(b, l)