Browse Source

Garbage collect DBProvider (unoptimized); Certifier creation takes a client

pull/2296/head
Jae Kwon 7 years ago
parent
commit
c3296f2e01
3 changed files with 105 additions and 38 deletions
  1. +1
    -1
      cmd/tendermint/commands/lite.go
  2. +91
    -26
      lite/dbprovider.go
  3. +13
    -11
      lite/proxy/certifier.go

+ 1
- 1
cmd/tendermint/commands/lite.go View File

@ -68,7 +68,7 @@ func runProxy(cmd *cobra.Command, args []string) error {
// First, connect a client // First, connect a client
node := rpcclient.NewHTTP(nodeAddr, "/websocket") node := rpcclient.NewHTTP(nodeAddr, "/websocket")
cert, err := proxy.GetCertifier(chainID, home, nodeAddr)
cert, err := proxy.GetCertifier(chainID, home, node)
if err != nil { if err != nil {
return err return err
} }


+ 91
- 26
lite/dbprovider.go View File

@ -12,36 +12,11 @@ import (
dbm "github.com/tendermint/tmlibs/db" dbm "github.com/tendermint/tmlibs/db"
) )
func signedHeaderKey(chainID string, height int64) []byte {
return []byte(fmt.Sprintf("%s/%010d/sh", chainID, height))
}
var signedHeaderKeyPattern = regexp.MustCompile(`([^/]+)/([0-9]*)/sh`)
func parseSignedHeaderKey(key []byte) (chainID string, height int64, ok bool) {
submatch := signedHeaderKeyPattern.FindSubmatch(key)
if submatch == nil {
return "", 0, false
}
chainID = string(submatch[1])
heightStr := string(submatch[2])
heightInt, err := strconv.Atoi(heightStr)
if err != nil {
return "", 0, false
}
height = int64(heightInt)
ok = true // good!
return
}
func validatorSetKey(chainID string, height int64) []byte {
return []byte(fmt.Sprintf("%s/%010d/vs", chainID, height))
}
type DBProvider struct { type DBProvider struct {
chainID string chainID string
db dbm.DB db dbm.DB
cdc *amino.Codec cdc *amino.Codec
limit int
} }
func NewDBProvider(db dbm.DB) *DBProvider { func NewDBProvider(db dbm.DB) *DBProvider {
@ -52,6 +27,11 @@ func NewDBProvider(db dbm.DB) *DBProvider {
return dbp return dbp
} }
func (dbp *DBProvider) SetLimit(limit int) *DBProvider {
dbp.limit = limit
return dbp
}
// Implements PersistentProvider. // Implements PersistentProvider.
func (dbp *DBProvider) SaveFullCommit(fc FullCommit) error { func (dbp *DBProvider) SaveFullCommit(fc FullCommit) error {
@ -85,6 +65,13 @@ func (dbp *DBProvider) SaveFullCommit(fc FullCommit) error {
// And write sync. // And write sync.
batch.WriteSync() batch.WriteSync()
// Garbage collect.
// TODO: optimize later.
if dbp.limit > 0 {
dbp.deleteAfterN(fc.ChainID(), dbp.limit)
}
return nil return nil
} }
@ -166,3 +153,81 @@ func (dbp *DBProvider) fillFullCommit(sh types.SignedHeader) (FullCommit, error)
NextValidators: nextValset, NextValidators: nextValset,
}, nil }, nil
} }
func (dbp *DBProvider) deleteAfterN(chainID string, after int) error {
itr := dbp.db.ReverseIterator(
signedHeaderKey(chainID, 1<<63-1),
signedHeaderKey(chainID, 0),
)
defer itr.Close()
var lastHeight int64 = 1<<63 - 1
var numSeen = 0
for itr.Valid() {
key := itr.Key()
_, height, ok := parseChainKeyPrefix(key)
if !ok {
return fmt.Errorf("unexpected key %v", key)
} else {
if height < lastHeight {
lastHeight = height
numSeen += 1
}
if numSeen > after {
dbp.db.Delete(key)
}
}
}
return nil
}
//----------------------------------------
func signedHeaderKey(chainID string, height int64) []byte {
return []byte(fmt.Sprintf("%s/%010d/sh", chainID, height))
}
var signedHeaderKeyPattern = regexp.MustCompile(`([^/]+)/([0-9]*)/sh`)
func parseSignedHeaderKey(key []byte) (chainID string, height int64, ok bool) {
submatch := signedHeaderKeyPattern.FindSubmatch(key)
if submatch == nil {
return "", 0, false
}
chainID = string(submatch[1])
heightStr := string(submatch[2])
heightInt, err := strconv.Atoi(heightStr)
if err != nil {
return "", 0, false
}
height = int64(heightInt)
ok = true // good!
return
}
func validatorSetKey(chainID string, height int64) []byte {
return []byte(fmt.Sprintf("%s/%010d/vs", chainID, height))
}
func chainKeyPrefix(chainID string, height int64) []byte {
return []byte(fmt.Sprintf("%s/%010d/", chainID, height))
}
var chainKeyPrefixPattern = regexp.MustCompile(`([^/]+)/([0-9]*)/`)
func parseChainKeyPrefix(key []byte) (chainID string, height int64, ok bool) {
submatch := chainKeyPrefixPattern.FindSubmatch(key)
if submatch == nil {
return "", 0, false
}
chainID = string(submatch[1])
heightStr := string(submatch[2])
heightInt, err := strconv.Atoi(heightStr)
if err != nil {
return "", 0, false
}
height = int64(heightInt)
ok = true // good!
return
}

+ 13
- 11
lite/proxy/certifier.go View File

@ -6,22 +6,24 @@ import (
dbm "github.com/tendermint/tmlibs/db" dbm "github.com/tendermint/tmlibs/db"
) )
func GetCertifier(chainID, rootDir, nodeAddr string) (*lite.InquiringCertifier, error) {
func GetCertifier(chainID, rootDir string, client lclient.SignStatusClient) (*lite.InquiringCertifier, error) {
trust := lite.NewMultiProvider( trust := lite.NewMultiProvider(
lite.NewDBProvider(dbm.NewMemDB()),
lite.NewDBProvider(dbm.NewMemDB()).SetLimit(10),
lite.NewDBProvider(dbm.NewDB("trust-base", dbm.LevelDBBackend, rootDir)), lite.NewDBProvider(dbm.NewDB("trust-base", dbm.LevelDBBackend, rootDir)),
) )
source := lclient.NewProvider(chainID, client)
source := lclient.NewHTTPProvider(chainID, nodeAddr)
// XXX: total insecure hack to avoid `init`
fc, err := source.LatestFullCommit(chainID, 1, 1)
// TODO: Make this more secure, e.g. make it interactive in the console?
_, err := trust.LatestFullCommit(chainID, 1, 1<<63-1)
if err != nil { if err != nil {
return nil, err
}
err = trust.SaveFullCommit(fc)
if err != nil {
return nil, err
fc, err := source.LatestFullCommit(chainID, 1, 1)
if err != nil {
return nil, err
}
err = trust.SaveFullCommit(fc)
if err != nil {
return nil, err
}
} }
cert, err := lite.NewInquiringCertifier(chainID, trust, source) cert, err := lite.NewInquiringCertifier(chainID, trust, source)


Loading…
Cancel
Save