store: order-preserving varint key encoding (#5771)

This commit is contained in:
Callum Waters
2021-01-05 16:53:26 +01:00
committed by GitHub
parent 0555772d3a
commit 9b9222f461
9 changed files with 195 additions and 127 deletions
+28 -16
View File
@@ -11,6 +11,7 @@ import (
"github.com/gogo/protobuf/proto"
gogotypes "github.com/gogo/protobuf/types"
"github.com/google/orderedcode"
dbm "github.com/tendermint/tm-db"
clist "github.com/tendermint/tendermint/libs/clist"
@@ -21,8 +22,9 @@ import (
)
const (
baseKeyCommitted = byte(0x00)
baseKeyPending = byte(0x01)
// prefixes are unique across all tm db's
prefixCommitted = int64(8)
prefixPending = int64(9)
)
// Pool maintains a pool of valid evidence to be broadcasted and committed
@@ -67,7 +69,7 @@ func NewPool(evidenceDB dbm.DB, stateDB sm.Store, blockStore BlockStore) (*Pool,
// if pending evidence already in db, in event of prior failure, then check for expiration,
// update the size and load it back to the evidenceList
pool.pruningHeight, pool.pruningTime = pool.removeExpiredPendingEvidence()
evList, _, err := pool.listEvidence(baseKeyPending, -1)
evList, _, err := pool.listEvidence(prefixPending, -1)
if err != nil {
return nil, err
}
@@ -84,7 +86,7 @@ func (evpool *Pool) PendingEvidence(maxBytes int64) ([]types.Evidence, int64) {
if evpool.Size() == 0 {
return []types.Evidence{}, 0
}
evidence, size, err := evpool.listEvidence(baseKeyPending, maxBytes)
evidence, size, err := evpool.listEvidence(prefixPending, maxBytes)
if err != nil {
evpool.logger.Error("Unable to retrieve pending evidence", "err", err)
}
@@ -402,7 +404,7 @@ func (evpool *Pool) markEvidenceAsCommitted(evidence types.EvidenceList) {
// listEvidence retrieves lists evidence from oldest to newest within maxBytes.
// If maxBytes is -1, there's no cap on the size of returned evidence.
func (evpool *Pool) listEvidence(prefixKey byte, maxBytes int64) ([]types.Evidence, int64, error) {
func (evpool *Pool) listEvidence(prefixKey int64, maxBytes int64) ([]types.Evidence, int64, error) {
var (
evSize int64
totalSize int64
@@ -410,11 +412,12 @@ func (evpool *Pool) listEvidence(prefixKey byte, maxBytes int64) ([]types.Eviden
evList tmproto.EvidenceList // used for calculating the bytes size
)
iter, err := dbm.IteratePrefix(evpool.evidenceStore, []byte{prefixKey})
iter, err := dbm.IteratePrefix(evpool.evidenceStore, prefixToBytes(prefixKey))
if err != nil {
return nil, totalSize, fmt.Errorf("database error: %v", err)
}
defer iter.Close()
for ; iter.Valid(); iter.Next() {
var evpb tmproto.Evidence
err := evpb.Unmarshal(iter.Value())
@@ -446,7 +449,7 @@ func (evpool *Pool) listEvidence(prefixKey byte, maxBytes int64) ([]types.Eviden
}
func (evpool *Pool) removeExpiredPendingEvidence() (int64, time.Time) {
iter, err := dbm.IteratePrefix(evpool.evidenceStore, []byte{baseKeyPending})
iter, err := dbm.IteratePrefix(evpool.evidenceStore, prefixToBytes(prefixPending))
if err != nil {
evpool.logger.Error("Unable to iterate over pending evidence", "err", err)
return evpool.State().LastBlockHeight, evpool.State().LastBlockTime
@@ -511,19 +514,28 @@ func evMapKey(ev types.Evidence) string {
return string(ev.Hash())
}
// big endian padded hex
func bE(h int64) string {
return fmt.Sprintf("%0.16X", h)
func prefixToBytes(prefix int64) []byte {
key, err := orderedcode.Append(nil, prefix)
if err != nil {
panic(err)
}
return key
}
func keyCommitted(evidence types.Evidence) []byte {
return append([]byte{baseKeyCommitted}, keySuffix(evidence)...)
var height int64 = evidence.Height()
key, err := orderedcode.Append(nil, prefixCommitted, height, string(evidence.Hash()))
if err != nil {
panic(err)
}
return key
}
func keyPending(evidence types.Evidence) []byte {
return append([]byte{baseKeyPending}, keySuffix(evidence)...)
}
func keySuffix(evidence types.Evidence) []byte {
return []byte(fmt.Sprintf("%s/%X", bE(evidence.Height()), evidence.Hash()))
var height int64 = evidence.Height()
key, err := orderedcode.Append(nil, prefixPending, height, string(evidence.Hash()))
if err != nil {
panic(err)
}
return key
}