cosmos-sdk/state/bonsai.go

101 lines
2.1 KiB
Go

package state
import (
"errors"
"math/rand"
"github.com/tendermint/tmlibs/merkle"
)
// store nonce as it's own type so no one can even try to fake it
type nonce int64
// Bonsai is a deformed tree forced to fit in a small pot
type Bonsai struct {
id nonce
merkle.Tree
}
var _ SimpleDB = &Bonsai{}
// NewBonsai wraps a merkle tree and tags it to track children
func NewBonsai(tree merkle.Tree) *Bonsai {
return &Bonsai{
id: nonce(rand.Int63()),
Tree: tree,
}
}
// Get matches the signature of KVStore
func (b *Bonsai) Get(key []byte) []byte {
_, value, _ := b.Tree.Get(key)
return value
}
// Set matches the signature of KVStore
func (b *Bonsai) Set(key, value []byte) {
b.Tree.Set(key, value)
}
func (b *Bonsai) Remove(key []byte) (value []byte) {
value, _ = b.Tree.Remove(key)
return
}
func (b *Bonsai) List(start, end []byte, limit int) []Model {
res := []Model{}
stopAtCount := func(key []byte, value []byte) (stop bool) {
m := Model{key, value}
res = append(res, m)
// return false
return limit > 0 && len(res) >= limit
}
b.Tree.IterateRange(start, end, true, stopAtCount)
return res
}
func (b *Bonsai) First(start, end []byte) Model {
var m Model
stopAtFirst := func(key []byte, value []byte) (stop bool) {
m = Model{key, value}
return true
}
b.Tree.IterateRange(start, end, true, stopAtFirst)
return m
}
func (b *Bonsai) Last(start, end []byte) Model {
var m Model
stopAtFirst := func(key []byte, value []byte) (stop bool) {
m = Model{key, value}
return true
}
b.Tree.IterateRange(start, end, false, stopAtFirst)
return m
}
func (b *Bonsai) Checkpoint() SimpleDB {
return &Bonsai{
id: b.id,
Tree: b.Tree.Copy(),
}
}
// Commit will take all changes from the checkpoint and write
// them to the parent.
// Returns an error if this is not a child of this one
func (b *Bonsai) Commit(sub SimpleDB) error {
bb, ok := sub.(*Bonsai)
if !ok || (b.id != bb.id) {
return errors.New("Not a sub-transaction")
}
b.Tree = bb.Tree
return nil
}
// Discard will remove reference to this
func (b *Bonsai) Discard() {
b.id = 0
b.Tree = nil
}