1
0
Fork 0
forked from forks/go-ethereum

core, triedb/pathdb: bail out error if write state history fails (#31781)

This PR fixes an issue that could lead to data corruption.

Writing the state history may fail due to insufficient disk space or
other potential errors. With this change, the entire state insertion 
will be aborted instead of silently ignoring the error.

Without this fix, state transitions would continue while the associated
state history is lost. After a restart, the resulting gap would be detected, 
making recovery impossible.
This commit is contained in:
rjl493456442 2025-05-08 22:27:01 +08:00 committed by GitHub
parent 6bc57579d1
commit 0f48cbf017
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 21 additions and 10 deletions

View file

@ -258,13 +258,21 @@ func ReadStateHistory(db ethdb.AncientReaderOp, id uint64) ([]byte, []byte, []by
// WriteStateHistory writes the provided state history to database. Compute the
// position of state history in freezer by minus one since the id of first state
// history starts from one(zero for initial state).
func WriteStateHistory(db ethdb.AncientWriter, id uint64, meta []byte, accountIndex []byte, storageIndex []byte, accounts []byte, storages []byte) {
db.ModifyAncients(func(op ethdb.AncientWriteOp) error {
op.AppendRaw(stateHistoryMeta, id-1, meta)
op.AppendRaw(stateHistoryAccountIndex, id-1, accountIndex)
op.AppendRaw(stateHistoryStorageIndex, id-1, storageIndex)
op.AppendRaw(stateHistoryAccountData, id-1, accounts)
op.AppendRaw(stateHistoryStorageData, id-1, storages)
return nil
func WriteStateHistory(db ethdb.AncientWriter, id uint64, meta []byte, accountIndex []byte, storageIndex []byte, accounts []byte, storages []byte) error {
_, err := db.ModifyAncients(func(op ethdb.AncientWriteOp) error {
if err := op.AppendRaw(stateHistoryMeta, id-1, meta); err != nil {
return err
}
if err := op.AppendRaw(stateHistoryAccountIndex, id-1, accountIndex); err != nil {
return err
}
if err := op.AppendRaw(stateHistoryStorageIndex, id-1, storageIndex); err != nil {
return err
}
if err := op.AppendRaw(stateHistoryAccountData, id-1, accounts); err != nil {
return err
}
return op.AppendRaw(stateHistoryStorageData, id-1, storages)
})
return err
}

View file

@ -231,6 +231,8 @@ func (dl *diskLayer) commit(bottom *diffLayer, force bool) (*diskLayer, error) {
oldest uint64
)
if dl.db.freezer != nil {
// Bail out with an error if writing the state history fails.
// This can happen, for example, if the device is full.
err := writeHistory(dl.db.freezer, bottom)
if err != nil {
return nil, err

View file

@ -542,8 +542,9 @@ func writeHistory(writer ethdb.AncientWriter, dl *diffLayer) error {
indexSize := common.StorageSize(len(accountIndex) + len(storageIndex))
// Write history data into five freezer table respectively.
rawdb.WriteStateHistory(writer, dl.stateID(), history.meta.encode(), accountIndex, storageIndex, accountData, storageData)
if err := rawdb.WriteStateHistory(writer, dl.stateID(), history.meta.encode(), accountIndex, storageIndex, accountData, storageData); err != nil {
return err
}
historyDataBytesMeter.Mark(int64(dataSize))
historyIndexBytesMeter.Mark(int64(indexSize))
historyBuildTimeMeter.UpdateSince(start)