mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 02:42:27 +00:00
Make trie.Database.Commit() write out preimages in deterministic order
Iteration order over db.preimages was not deterministic, sorting the batch contents when the batch is written wasn't enough to work around this if preimages didn't fit into a single batch. So now Commit() will pre-sort preimages to ensure their order is always deterministic, even when split across multiple batches.
This commit is contained in:
parent
8d42b72c43
commit
500eef96c8
1 changed files with 21 additions and 2 deletions
|
|
@ -17,8 +17,10 @@
|
||||||
package trie
|
package trie
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"sort"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
|
@ -615,9 +617,26 @@ func (db *Database) Commit(node common.Hash, report bool) error {
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
batch := db.diskdb.NewBatch()
|
batch := db.diskdb.NewBatch()
|
||||||
|
|
||||||
|
type kvPair struct {
|
||||||
|
key []byte
|
||||||
|
value []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort preimages to ensure they are written out in deterministic order
|
||||||
|
orderedPreimages := make([]kvPair, 0, len(db.preimages))
|
||||||
|
for hash := range db.preimages {
|
||||||
|
orderedPreimages = append(orderedPreimages, kvPair{
|
||||||
|
key: common.CopyBytes(hash[:]),
|
||||||
|
value: db.preimages[hash],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
sort.Slice(orderedPreimages, func(j, k int) bool {
|
||||||
|
return bytes.Compare(orderedPreimages[j].key, orderedPreimages[k].key) < 0
|
||||||
|
})
|
||||||
|
|
||||||
// Move all of the accumulated preimages into a write batch
|
// Move all of the accumulated preimages into a write batch
|
||||||
for hash, preimage := range db.preimages {
|
for _, preimage := range orderedPreimages {
|
||||||
if err := batch.Put(db.secureKey(hash[:]), preimage); err != nil {
|
if err := batch.Put(db.secureKey(preimage.key), preimage.value); err != nil {
|
||||||
log.Error("Failed to commit preimage from trie database", "err", err)
|
log.Error("Failed to commit preimage from trie database", "err", err)
|
||||||
db.lock.RUnlock()
|
db.lock.RUnlock()
|
||||||
return err
|
return err
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue