core: improve snapshot journal recovery (#21594)
* core/state/snapshot: introduce snapshot journal version * core: update the disk layer in an atomic way * core: persist the disk layer generator periodically * core/state/snapshot: improve logging * core/state/snapshot: forcibly ensure the legacy snapshot is matched * core/state/snapshot: add debug logs * core, tests: fix tests and special recovery case * core: polish * core: add more blockchain tests for snapshot recovery * core/state: fix comment * core: add recovery flag for snapshot * core: add restart after start-after-crash tests * core/rawdb: fix imports * core: fix tests * core: remove log * core/state/snapshot: fix snapshot * core: avoid callbacks in SetHead * core: fix setHead cornercase where the threshold root has state * core: small docs for the test cases Co-authored-by: Péter Szilágyi <peterke@gmail.com>
This commit is contained in:
@ -17,6 +17,8 @@
|
||||
package rawdb
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
@ -118,3 +120,58 @@ func DeleteSnapshotJournal(db ethdb.KeyValueWriter) {
|
||||
log.Crit("Failed to remove snapshot journal", "err", err)
|
||||
}
|
||||
}
|
||||
|
||||
// ReadSnapshotGenerator retrieves the serialized snapshot generator saved at
|
||||
// the last shutdown.
|
||||
func ReadSnapshotGenerator(db ethdb.KeyValueReader) []byte {
|
||||
data, _ := db.Get(snapshotGeneratorKey)
|
||||
return data
|
||||
}
|
||||
|
||||
// WriteSnapshotGenerator stores the serialized snapshot generator to save at
|
||||
// shutdown.
|
||||
func WriteSnapshotGenerator(db ethdb.KeyValueWriter, generator []byte) {
|
||||
if err := db.Put(snapshotGeneratorKey, generator); err != nil {
|
||||
log.Crit("Failed to store snapshot generator", "err", err)
|
||||
}
|
||||
}
|
||||
|
||||
// DeleteSnapshotGenerator deletes the serialized snapshot generator saved at
|
||||
// the last shutdown
|
||||
func DeleteSnapshotGenerator(db ethdb.KeyValueWriter) {
|
||||
if err := db.Delete(snapshotGeneratorKey); err != nil {
|
||||
log.Crit("Failed to remove snapshot generator", "err", err)
|
||||
}
|
||||
}
|
||||
|
||||
// ReadSnapshotRecoveryNumber retrieves the block number of the last persisted
|
||||
// snapshot layer.
|
||||
func ReadSnapshotRecoveryNumber(db ethdb.KeyValueReader) *uint64 {
|
||||
data, _ := db.Get(snapshotRecoveryKey)
|
||||
if len(data) == 0 {
|
||||
return nil
|
||||
}
|
||||
if len(data) != 8 {
|
||||
return nil
|
||||
}
|
||||
number := binary.BigEndian.Uint64(data)
|
||||
return &number
|
||||
}
|
||||
|
||||
// WriteSnapshotRecoveryNumber stores the block number of the last persisted
|
||||
// snapshot layer.
|
||||
func WriteSnapshotRecoveryNumber(db ethdb.KeyValueWriter, number uint64) {
|
||||
var buf [8]byte
|
||||
binary.BigEndian.PutUint64(buf[:], number)
|
||||
if err := db.Put(snapshotRecoveryKey, buf[:]); err != nil {
|
||||
log.Crit("Failed to store snapshot recovery number", "err", err)
|
||||
}
|
||||
}
|
||||
|
||||
// DeleteSnapshotRecoveryNumber deletes the block number of the last persisted
|
||||
// snapshot layer.
|
||||
func DeleteSnapshotRecoveryNumber(db ethdb.KeyValueWriter) {
|
||||
if err := db.Delete(snapshotRecoveryKey); err != nil {
|
||||
log.Crit("Failed to remove snapshot recovery number", "err", err)
|
||||
}
|
||||
}
|
||||
|
@ -51,6 +51,12 @@ var (
|
||||
// snapshotJournalKey tracks the in-memory diff layers across restarts.
|
||||
snapshotJournalKey = []byte("SnapshotJournal")
|
||||
|
||||
// snapshotGeneratorKey tracks the snapshot generation marker across restarts.
|
||||
snapshotGeneratorKey = []byte("SnapshotGenerator")
|
||||
|
||||
// snapshotRecoveryKey tracks the snapshot recovery marker across restarts.
|
||||
snapshotRecoveryKey = []byte("SnapshotRecovery")
|
||||
|
||||
// txIndexTailKey tracks the oldest block whose transactions have been indexed.
|
||||
txIndexTailKey = []byte("TransactionIndexTail")
|
||||
|
||||
|
Reference in New Issue
Block a user