erigon-pulse/cmd/state/stateless/witness_db.go
Igor Mandrigin adf52465e3
move ./trie to ./turbo/trie (#1114)
Useful for minimizing merge conflicts when rebasing new geth
2020-09-14 11:33:39 +01:00

96 lines
2.1 KiB
Go

package stateless
import (
"bytes"
"encoding/binary"
"encoding/csv"
"fmt"
"github.com/ledgerwatch/turbo-geth/common"
"github.com/ledgerwatch/turbo-geth/ethdb"
"github.com/ledgerwatch/turbo-geth/turbo/trie"
)
var (
witnessesBucket = "witnesses"
)
type WitnessDBWriter struct {
storage ethdb.Database
statsWriter *csv.Writer
}
func NewWitnessDBWriter(storage ethdb.Database, statsWriter *csv.Writer) (*WitnessDBWriter, error) {
err := statsWriter.Write([]string{
"blockNum", "maxTrieSize", "witnessesSize",
})
if err != nil {
return nil, err
}
return &WitnessDBWriter{storage, statsWriter}, nil
}
func (db *WitnessDBWriter) MustUpsert(blockNumber uint64, maxTrieSize uint32, resolveWitnesses []*trie.Witness) {
key := deriveDbKey(blockNumber, maxTrieSize)
var buf bytes.Buffer
for i, witness := range resolveWitnesses {
if _, err := witness.WriteTo(&buf); err != nil {
panic(fmt.Errorf("error while writing witness to a buffer: %w", err))
}
if i < len(resolveWitnesses)-1 {
buf.WriteByte(byte(trie.OpNewTrie))
}
}
bytes := buf.Bytes()
batch := db.storage.NewBatch()
err := batch.Put(witnessesBucket, common.CopyBytes(key), common.CopyBytes(bytes))
if err != nil {
panic(fmt.Errorf("error while upserting witness: %w", err))
}
_, err = batch.Commit()
if err != nil {
panic(err)
}
err = db.statsWriter.Write([]string{
fmt.Sprintf("%v", blockNumber),
fmt.Sprintf("%v", maxTrieSize),
fmt.Sprintf("%v", len(bytes)),
})
if err != nil {
panic(fmt.Errorf("error while writing stats: %w", err))
}
db.statsWriter.Flush()
}
type WitnessDBReader struct {
getter ethdb.Getter
}
func NewWitnessDBReader(getter ethdb.Getter) *WitnessDBReader {
return &WitnessDBReader{getter}
}
func (db *WitnessDBReader) GetWitnessesForBlock(blockNumber uint64, maxTrieSize uint32) ([]byte, error) {
key := deriveDbKey(blockNumber, maxTrieSize)
return db.getter.Get(witnessesBucket, key)
}
func deriveDbKey(blockNumber uint64, maxTrieSize uint32) []byte {
buffer := make([]byte, 8+4)
binary.LittleEndian.PutUint64(buffer[:], blockNumber)
binary.LittleEndian.PutUint32(buffer[8:], maxTrieSize)
return buffer
}