Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

all: extend ancient store API with freezer identifier routing #24481

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
14 changes: 7 additions & 7 deletions cmd/devp2p/internal/ethtest/snap.go
Expand Up @@ -372,8 +372,8 @@ func (s *Suite) TestSnapTrieNodes(t *utesting.T) {
{
root: s.chain.RootAt(999),
paths: []snap.TrieNodePathSet{
snap.TrieNodePathSet{}, // zero-length pathset should 'abort' and kick us off
snap.TrieNodePathSet{[]byte{0}},
{}, // zero-length pathset should 'abort' and kick us off
{[]byte{0}},
},
nBytes: 5000,
expHashes: []common.Hash{},
Expand All @@ -382,8 +382,8 @@ func (s *Suite) TestSnapTrieNodes(t *utesting.T) {
{
root: s.chain.RootAt(999),
paths: []snap.TrieNodePathSet{
snap.TrieNodePathSet{[]byte{0}},
snap.TrieNodePathSet{[]byte{1}, []byte{0}},
{[]byte{0}},
{[]byte{1}, []byte{0}},
},
nBytes: 5000,
//0x6b3724a41b8c38b46d4d02fba2bb2074c47a507eb16a9a4b978f91d32e406faf
Expand All @@ -392,7 +392,7 @@ func (s *Suite) TestSnapTrieNodes(t *utesting.T) {
{ // nonsensically long path
root: s.chain.RootAt(999),
paths: []snap.TrieNodePathSet{
snap.TrieNodePathSet{[]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1, 2, 3, 4, 5, 6, 7, 8,
{[]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1, 2, 3, 4, 5, 6, 7, 8,
0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1, 2, 3, 4, 5, 6, 7, 8}},
},
nBytes: 5000,
Expand All @@ -401,8 +401,8 @@ func (s *Suite) TestSnapTrieNodes(t *utesting.T) {
{
root: s.chain.RootAt(0),
paths: []snap.TrieNodePathSet{
snap.TrieNodePathSet{[]byte{0}},
snap.TrieNodePathSet{[]byte{1}, []byte{0}},
{[]byte{0}},
{[]byte{1}, []byte{0}},
},
nBytes: 5000,
expHashes: []common.Hash{},
Expand Down
2 changes: 1 addition & 1 deletion cmd/geth/dbcmd.go
Expand Up @@ -708,7 +708,7 @@ func showMetaData(ctx *cli.Context) error {
stack, _ := makeConfigNode(ctx)
defer stack.Close()
db := utils.MakeChainDatabase(ctx, stack, true)
ancients, err := db.Ancients()
ancients, err := db.Ancients(rawdb.ChainFreezer)
if err != nil {
fmt.Fprintf(os.Stderr, "Error accessing ancients: %v", err)
}
Expand Down
18 changes: 9 additions & 9 deletions core/blockchain.go
Expand Up @@ -272,7 +272,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par
rawdb.InitDatabaseFromFreezer(bc.db)
// If ancient database is not empty, reconstruct all missing
// indices in the background.
frozen, _ := bc.db.Ancients()
frozen, _ := bc.db.Ancients(rawdb.ChainFreezer)
if frozen > 0 {
txIndexBlock = frozen
}
Expand Down Expand Up @@ -311,7 +311,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par
}

// Ensure that a previous crash in SetHead doesn't leave extra ancients
if frozen, err := bc.db.Ancients(); err == nil && frozen > 0 {
if frozen, err := bc.db.Ancients(rawdb.ChainFreezer); err == nil && frozen > 0 {
var (
needRewind bool
low uint64
Expand Down Expand Up @@ -504,7 +504,7 @@ func (bc *BlockChain) setHeadBeyondRoot(head uint64, root common.Hash, repair bo
// Retrieve the last pivot block to short circuit rollbacks beyond it and the
// current freezer limit to start nuking id underflown
pivot := rawdb.ReadLastPivotNumber(bc.db)
frozen, _ := bc.db.Ancients()
frozen, _ := bc.db.Ancients(rawdb.ChainFreezer)

updateFn := func(db ethdb.KeyValueWriter, header *types.Header) (uint64, bool) {
// Rewind the blockchain, ensuring we don't end up with a stateless head
Expand Down Expand Up @@ -601,11 +601,11 @@ func (bc *BlockChain) setHeadBeyondRoot(head uint64, root common.Hash, repair bo
// Rewind the header chain, deleting all block bodies until then
delFn := func(db ethdb.KeyValueWriter, hash common.Hash, num uint64) {
// Ignore the error here since light client won't hit this path
frozen, _ := bc.db.Ancients()
frozen, _ := bc.db.Ancients(rawdb.ChainFreezer)
if num+1 <= frozen {
// Truncate all relative data(header, total difficulty, body, receipt
// and canonical hash) from ancient store.
if err := bc.db.TruncateHead(num); err != nil {
if err := bc.db.TruncateHead(rawdb.ChainFreezer, num); err != nil {
log.Crit("Failed to truncate ancient data", "number", num, "err", err)
}
// Remove the hash <-> number mapping from the active store.
Expand Down Expand Up @@ -952,7 +952,7 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [

// Ensure genesis is in ancients.
if first.NumberU64() == 1 {
if frozen, _ := bc.db.Ancients(); frozen == 0 {
if frozen, _ := bc.db.Ancients(rawdb.ChainFreezer); frozen == 0 {
b := bc.genesisBlock
td := bc.genesisBlock.Difficulty()
writeSize, err := rawdb.WriteAncientBlocks(bc.db, []*types.Block{b}, []types.Receipts{nil}, td)
Expand Down Expand Up @@ -1004,7 +1004,7 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
size += int64(batch.ValueSize())
if err = batch.Write(); err != nil {
fastBlock := bc.CurrentFastBlock().NumberU64()
if err := bc.db.TruncateHead(fastBlock + 1); err != nil {
if err := bc.db.TruncateHead(rawdb.ChainFreezer, fastBlock+1); err != nil {
log.Error("Can't truncate ancient store after failed insert", "err", err)
}
return 0, err
Expand All @@ -1014,15 +1014,15 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
}

// Sync the ancient store explicitly to ensure all data has been flushed to disk.
if err := bc.db.Sync(); err != nil {
if err := bc.db.Sync(rawdb.ChainFreezer); err != nil {
return 0, err
}
// Update the current fast block because all block data is now present in DB.
previousFastBlock := bc.CurrentFastBlock().NumberU64()
if !updateHead(blockChain[len(blockChain)-1]) {
// We end up here if the header chain has reorg'ed, and the blocks/receipts
// don't match the canonical chain.
if err := bc.db.TruncateHead(previousFastBlock + 1); err != nil {
if err := bc.db.TruncateHead(rawdb.ChainFreezer, previousFastBlock+1); err != nil {
log.Error("Can't truncate ancient store after failed insert", "err", err)
}
return 0, errSideChainReceipts
Expand Down
4 changes: 2 additions & 2 deletions core/blockchain_repair_test.go
Expand Up @@ -1819,7 +1819,7 @@ func testRepair(t *testing.T, tt *rewindTest, snapshots bool) {
// Force run a freeze cycle
type freezer interface {
Freeze(threshold uint64) error
Ancients() (uint64, error)
Ancients(string) (uint64, error)
}
db.(freezer).Freeze(tt.freezeThreshold)

Expand Down Expand Up @@ -1858,7 +1858,7 @@ func testRepair(t *testing.T, tt *rewindTest, snapshots bool) {
if head := newChain.CurrentBlock(); head.NumberU64() != tt.expHeadBlock {
t.Errorf("Head block mismatch: have %d, want %d", head.NumberU64(), tt.expHeadBlock)
}
if frozen, err := db.(freezer).Ancients(); err != nil {
if frozen, err := db.(freezer).Ancients(rawdb.ChainFreezer); err != nil {
t.Errorf("Failed to retrieve ancient count: %v\n", err)
} else if int(frozen) != tt.expFrozen {
t.Errorf("Frozen block count mismatch: have %d, want %d", frozen, tt.expFrozen)
Expand Down
4 changes: 2 additions & 2 deletions core/blockchain_sethead_test.go
Expand Up @@ -2024,7 +2024,7 @@ func testSetHead(t *testing.T, tt *rewindTest, snapshots bool) {
// Force run a freeze cycle
type freezer interface {
Freeze(threshold uint64) error
Ancients() (uint64, error)
Ancients(string) (uint64, error)
}
db.(freezer).Freeze(tt.freezeThreshold)

Expand All @@ -2050,7 +2050,7 @@ func testSetHead(t *testing.T, tt *rewindTest, snapshots bool) {
if head := chain.CurrentBlock(); head.NumberU64() != tt.expHeadBlock {
t.Errorf("Head block mismatch: have %d, want %d", head.NumberU64(), tt.expHeadBlock)
}
if frozen, err := db.(freezer).Ancients(); err != nil {
if frozen, err := db.(freezer).Ancients(rawdb.ChainFreezer); err != nil {
t.Errorf("Failed to retrieve ancient count: %v\n", err)
} else if int(frozen) != tt.expFrozen {
t.Errorf("Frozen block count mismatch: have %d, want %d", frozen, tt.expFrozen)
Expand Down
6 changes: 3 additions & 3 deletions core/blockchain_test.go
Expand Up @@ -969,7 +969,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
ancient.SetHead(remove - 1)
assert(t, "ancient", ancient, 0, 0, 0)

if frozen, err := ancientDb.Ancients(); err != nil || frozen != 1 {
if frozen, err := ancientDb.Ancients(rawdb.ChainFreezer); err != nil || frozen != 1 {
t.Fatalf("failed to truncate ancient store, want %v, have %v", 1, frozen)
}
// Import the chain as a light node and ensure all pointers are updated
Expand Down Expand Up @@ -1856,7 +1856,7 @@ func TestInsertReceiptChainRollback(t *testing.T) {
if ancientChain.CurrentFastBlock().NumberU64() != 0 {
t.Fatalf("failed to rollback ancient data, want %d, have %d", 0, ancientChain.CurrentFastBlock().NumberU64())
}
if frozen, err := ancientChain.db.Ancients(); err != nil || frozen != 1 {
if frozen, err := ancientChain.db.Ancients(rawdb.ChainFreezer); err != nil || frozen != 1 {
t.Fatalf("failed to truncate ancient data, frozen index is %d", frozen)
}

Expand All @@ -1868,7 +1868,7 @@ func TestInsertReceiptChainRollback(t *testing.T) {
if ancientChain.CurrentFastBlock().NumberU64() != canonblocks[len(canonblocks)-1].NumberU64() {
t.Fatalf("failed to insert ancient recept chain after rollback")
}
if frozen, _ := ancientChain.db.Ancients(); frozen != uint64(len(canonblocks))+1 {
if frozen, _ := ancientChain.db.Ancients(rawdb.ChainFreezer); frozen != uint64(len(canonblocks))+1 {
t.Fatalf("wrong ancients count %d", frozen)
}
}
Expand Down
36 changes: 23 additions & 13 deletions core/rawdb/accessors_chain.go
Expand Up @@ -36,7 +36,7 @@ import (
// ReadCanonicalHash retrieves the hash assigned to a canonical block number.
func ReadCanonicalHash(db ethdb.Reader, number uint64) common.Hash {
var data []byte
db.ReadAncients(func(reader ethdb.AncientReader) error {
db.ReadAncients(ChainFreezer, func(reader ethdb.AncientReadOp) error {
data, _ = reader.Ancient(freezerHashTable, number)
if len(data) == 0 {
// Get it by hash from leveldb
Expand Down Expand Up @@ -298,7 +298,7 @@ func ReadHeaderRange(db ethdb.Reader, number uint64, count uint64) []rlp.RawValu
// It's ok to request block 0, 1 item
count = number + 1
}
limit, _ := db.Ancients()
limit, _ := db.Ancients(ChainFreezer)
// First read live blocks
if i >= limit {
// If we need to read live blocks, we need to figure out the hash first
Expand All @@ -319,7 +319,7 @@ func ReadHeaderRange(db ethdb.Reader, number uint64, count uint64) []rlp.RawValu
}
// read remaining from ancients
max := count * 700
data, err := db.AncientRange(freezerHeaderTable, i+1-count, count, max)
data, err := db.AncientRange(ChainFreezer, freezerHeaderTable, i+1-count, count, max)
if err == nil && uint64(len(data)) == count {
// the data is on the order [h, h+1, .., n] -- reordering needed
for i := range data {
Expand All @@ -332,7 +332,7 @@ func ReadHeaderRange(db ethdb.Reader, number uint64, count uint64) []rlp.RawValu
// ReadHeaderRLP retrieves a block header in its raw RLP database encoding.
func ReadHeaderRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue {
var data []byte
db.ReadAncients(func(reader ethdb.AncientReader) error {
db.ReadAncients(ChainFreezer, func(reader ethdb.AncientReadOp) error {
// First try to look up the data in ancient database. Extra hash
// comparison is necessary since ancient database only maintains
// the canonical data.
Expand Down Expand Up @@ -409,10 +409,20 @@ func deleteHeaderWithoutNumber(db ethdb.KeyValueWriter, hash common.Hash, number
}
}

// isCanonOp is an internal utility method, to check whether the given number/hash
// is part of the ancient (canon) set.
func isCanonOp(reader ethdb.AncientReadOp, number uint64, hash common.Hash) bool {
h, err := reader.Ancient(freezerHashTable, number)
if err != nil {
return false
}
return bytes.Equal(h, hash[:])
}

// isCanon is an internal utility method, to check whether the given number/hash
// is part of the ancient (canon) set.
func isCanon(reader ethdb.AncientReader, number uint64, hash common.Hash) bool {
h, err := reader.Ancient(freezerHashTable, number)
h, err := reader.Ancient(ChainFreezer, freezerHashTable, number)
if err != nil {
return false
}
Expand All @@ -425,9 +435,9 @@ func ReadBodyRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue
// comparison is necessary since ancient database only maintains
// the canonical data.
var data []byte
db.ReadAncients(func(reader ethdb.AncientReader) error {
db.ReadAncients(ChainFreezer, func(reader ethdb.AncientReadOp) error {
// Check if the data is in ancients
if isCanon(reader, number, hash) {
if isCanonOp(reader, number, hash) {
data, _ = reader.Ancient(freezerBodiesTable, number)
return nil
}
Expand All @@ -442,7 +452,7 @@ func ReadBodyRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue
// block at number, in RLP encoding.
func ReadCanonicalBodyRLP(db ethdb.Reader, number uint64) rlp.RawValue {
var data []byte
db.ReadAncients(func(reader ethdb.AncientReader) error {
db.ReadAncients(ChainFreezer, func(reader ethdb.AncientReadOp) error {
data, _ = reader.Ancient(freezerBodiesTable, number)
if len(data) > 0 {
return nil
Expand Down Expand Up @@ -508,9 +518,9 @@ func DeleteBody(db ethdb.KeyValueWriter, hash common.Hash, number uint64) {
// ReadTdRLP retrieves a block's total difficulty corresponding to the hash in RLP encoding.
func ReadTdRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue {
var data []byte
db.ReadAncients(func(reader ethdb.AncientReader) error {
db.ReadAncients(ChainFreezer, func(reader ethdb.AncientReadOp) error {
// Check if the data is in ancients
if isCanon(reader, number, hash) {
if isCanonOp(reader, number, hash) {
data, _ = reader.Ancient(freezerDifficultyTable, number)
return nil
}
Expand Down Expand Up @@ -568,9 +578,9 @@ func HasReceipts(db ethdb.Reader, hash common.Hash, number uint64) bool {
// ReadReceiptsRLP retrieves all the transaction receipts belonging to a block in RLP encoding.
func ReadReceiptsRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue {
var data []byte
db.ReadAncients(func(reader ethdb.AncientReader) error {
db.ReadAncients(ChainFreezer, func(reader ethdb.AncientReadOp) error {
// Check if the data is in ancients
if isCanon(reader, number, hash) {
if isCanonOp(reader, number, hash) {
data, _ = reader.Ancient(freezerReceiptTable, number)
return nil
}
Expand Down Expand Up @@ -782,7 +792,7 @@ func WriteAncientBlocks(db ethdb.AncientWriter, blocks []*types.Block, receipts
tdSum = new(big.Int).Set(td)
stReceipts []*types.ReceiptForStorage
)
return db.ModifyAncients(func(op ethdb.AncientWriteOp) error {
return db.ModifyAncients(ChainFreezer, func(op ethdb.AncientWriteOp) error {
for i, block := range blocks {
// Convert receipts to storage format and sum up total difficulty.
stReceipts = stReceipts[:0]
Expand Down
4 changes: 2 additions & 2 deletions core/rawdb/chain_iterator.go
Expand Up @@ -34,7 +34,7 @@ import (
// injects into the database the block hash->number mappings.
func InitDatabaseFromFreezer(db ethdb.Database) {
// If we can't access the freezer or it's empty, abort
frozen, err := db.Ancients()
frozen, err := db.Ancients(ChainFreezer)
if err != nil || frozen == 0 {
return
}
Expand All @@ -50,7 +50,7 @@ func InitDatabaseFromFreezer(db ethdb.Database) {
if i+count > frozen {
count = frozen - i
}
data, err := db.AncientRange(freezerHashTable, i, count, 32*count)
data, err := db.AncientRange(ChainFreezer, freezerHashTable, i, count, 32*count)
if err != nil {
log.Crit("Failed to init database from freezer", "err", err)
}
Expand Down