- package db
-
- import (
- "errors"
- "fmt"
- "regexp"
- "strconv"
-
- "github.com/tendermint/go-amino"
- dbm "github.com/tendermint/tm-db"
-
- cryptoAmino "github.com/tendermint/tendermint/crypto/encoding/amino"
- "github.com/tendermint/tendermint/lite2/store"
- "github.com/tendermint/tendermint/types"
- )
-
- type dbs struct {
- db dbm.DB
- prefix string
-
- cdc *amino.Codec
- }
-
- // New returns a Store that wraps any DB (with an optional prefix in case you
- // want to use one DB with many light clients).
- func New(db dbm.DB, prefix string) store.Store {
- cdc := amino.NewCodec()
- cryptoAmino.RegisterAmino(cdc)
- return &dbs{db: db, prefix: prefix, cdc: cdc}
- }
-
- func (s *dbs) SaveSignedHeader(sh *types.SignedHeader) error {
- if sh.Height <= 0 {
- panic("negative or zero height")
- }
-
- bz, err := s.cdc.MarshalBinaryLengthPrefixed(sh)
- if err != nil {
- return err
- }
- s.db.Set(s.shKey(sh.Height), bz)
- return nil
- }
-
- func (s *dbs) SaveValidatorSet(valSet *types.ValidatorSet, height int64) error {
- if height <= 0 {
- panic("negative or zero height")
- }
-
- bz, err := s.cdc.MarshalBinaryLengthPrefixed(valSet)
- if err != nil {
- return err
- }
- s.db.Set(s.vsKey(height), bz)
- return nil
- }
-
- func (s *dbs) SignedHeader(height int64) (*types.SignedHeader, error) {
- bz := s.db.Get(s.shKey(height))
- if bz == nil {
- return nil, nil
- }
-
- var signedHeader *types.SignedHeader
- err := s.cdc.UnmarshalBinaryLengthPrefixed(bz, &signedHeader)
- return signedHeader, err
- }
-
- func (s *dbs) ValidatorSet(height int64) (*types.ValidatorSet, error) {
- bz := s.db.Get(s.vsKey(height))
- if bz == nil {
- return nil, nil
- }
-
- var valSet *types.ValidatorSet
- err := s.cdc.UnmarshalBinaryLengthPrefixed(bz, &valSet)
- return valSet, err
- }
-
- func (s *dbs) LastSignedHeaderHeight() (int64, error) {
- itr := s.db.ReverseIterator(
- s.shKey(1),
- append(s.shKey(1<<63-1), byte(0x00)),
- )
- defer itr.Close()
-
- for itr.Valid() {
- key := itr.Key()
- _, height, ok := parseShKey(key)
- if ok {
- return height, nil
- }
- }
-
- return -1, errors.New("no headers found")
- }
-
- func (s *dbs) shKey(height int64) []byte {
- return []byte(fmt.Sprintf("sh/%s/%010d", s.prefix, height))
- }
-
- func (s *dbs) vsKey(height int64) []byte {
- return []byte(fmt.Sprintf("vs/%s/%010d", s.prefix, height))
- }
-
- var keyPattern = regexp.MustCompile(`^(sh|vs)/([^/]*)/([0-9]+)/$`)
-
- func parseKey(key []byte) (part string, prefix string, height int64, ok bool) {
- submatch := keyPattern.FindSubmatch(key)
- if submatch == nil {
- return "", "", 0, false
- }
- part = string(submatch[1])
- prefix = string(submatch[2])
- heightStr := string(submatch[3])
- heightInt, err := strconv.Atoi(heightStr)
- if err != nil {
- return "", "", 0, false
- }
- height = int64(heightInt)
- ok = true // good!
- return
- }
-
- func parseShKey(key []byte) (prefix string, height int64, ok bool) {
- var part string
- part, prefix, height, ok = parseKey(key)
- if part != "sh" {
- return "", 0, false
- }
- return
- }
|