mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-02-26 15:47:21 +00:00
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:
parent
6bc57579d1
commit
0f48cbf017
3 changed files with 21 additions and 10 deletions
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Reference in a new issue