mirror of
https://github.com/fluencelabs/tendermint
synced 2025-06-30 13:11:38 +00:00
Refactor "lite" to handle delayed validator set changes.
Also, fix consensus liveness issue.
This commit is contained in:
117
lite/provider.go
117
lite/provider.go
@ -1,103 +1,28 @@
|
||||
package lite
|
||||
|
||||
// Provider is used to get more validators by other means.
|
||||
//
|
||||
// Examples: MemProvider, files.Provider, client.Provider, CacheProvider....
|
||||
import (
|
||||
"github.com/tendermint/tendermint/types"
|
||||
)
|
||||
|
||||
// Provider provides information for the lite client to sync validators.
|
||||
// Examples: MemProvider, files.Provider, client.Provider, CacheProvider.
|
||||
type Provider interface {
|
||||
// StoreCommit saves a FullCommit after we have verified it,
|
||||
// so we can query for it later. Important for updating our
|
||||
// store of trusted commits.
|
||||
StoreCommit(fc FullCommit) error
|
||||
// GetByHeight returns the closest commit with height <= h.
|
||||
GetByHeight(h int64) (FullCommit, error)
|
||||
// GetByHash returns a commit exactly matching this validator hash.
|
||||
GetByHash(hash []byte) (FullCommit, error)
|
||||
// LatestCommit returns the newest commit stored.
|
||||
LatestCommit() (FullCommit, error)
|
||||
|
||||
// LatestFullCommit returns the latest commit with minHeight <= height <=
|
||||
// maxHeight.
|
||||
// If maxHeight is zero, returns the latest where minHeight <= height.
|
||||
LatestFullCommit(chainID string, minHeight, maxHeight int64) (FullCommit, error)
|
||||
|
||||
// Get the valset that corresponds to chainID and height and return.
|
||||
// Height must be >= 1.
|
||||
ValidatorSet(chainID string, height int64) (*types.ValidatorSet, error)
|
||||
}
|
||||
|
||||
// cacheProvider allows you to place one or more caches in front of a source
|
||||
// Provider. It runs through them in order until a match is found.
|
||||
// So you can keep a local cache, and check with the network if
|
||||
// no data is there.
|
||||
type cacheProvider struct {
|
||||
Providers []Provider
|
||||
}
|
||||
// A provider that can also persist new information.
|
||||
// Examples: MemProvider, files.Provider, CacheProvider.
|
||||
type PersistentProvider interface {
|
||||
Provider
|
||||
|
||||
// NewCacheProvider returns a new provider which wraps multiple other providers.
|
||||
func NewCacheProvider(providers ...Provider) Provider {
|
||||
return cacheProvider{
|
||||
Providers: providers,
|
||||
}
|
||||
}
|
||||
|
||||
// StoreCommit tries to add the seed to all providers.
|
||||
//
|
||||
// Aborts on first error it encounters (closest provider)
|
||||
func (c cacheProvider) StoreCommit(fc FullCommit) (err error) {
|
||||
for _, p := range c.Providers {
|
||||
err = p.StoreCommit(fc)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// GetByHeight should return the closest possible match from all providers.
|
||||
//
|
||||
// The Cache is usually organized in order from cheapest call (memory)
|
||||
// to most expensive calls (disk/network). However, since GetByHeight returns
|
||||
// a FullCommit at h' <= h, if the memory has a seed at h-10, but the network would
|
||||
// give us the exact match, a naive "stop at first non-error" would hide
|
||||
// the actual desired results.
|
||||
//
|
||||
// Thus, we query each provider in order until we find an exact match
|
||||
// or we finished querying them all. If at least one returned a non-error,
|
||||
// then this returns the best match (minimum h-h').
|
||||
func (c cacheProvider) GetByHeight(h int64) (fc FullCommit, err error) {
|
||||
for _, p := range c.Providers {
|
||||
var tfc FullCommit
|
||||
tfc, err = p.GetByHeight(h)
|
||||
if err == nil {
|
||||
if tfc.Height() > fc.Height() {
|
||||
fc = tfc
|
||||
}
|
||||
if tfc.Height() == h {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
// even if the last one had an error, if any was a match, this is good
|
||||
if fc.Height() > 0 {
|
||||
err = nil
|
||||
}
|
||||
return fc, err
|
||||
}
|
||||
|
||||
// GetByHash returns the FullCommit for the hash or an error if the commit is not found.
|
||||
func (c cacheProvider) GetByHash(hash []byte) (fc FullCommit, err error) {
|
||||
for _, p := range c.Providers {
|
||||
fc, err = p.GetByHash(hash)
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
return fc, err
|
||||
}
|
||||
|
||||
// LatestCommit returns the latest FullCommit or an error if no commit exists.
|
||||
func (c cacheProvider) LatestCommit() (fc FullCommit, err error) {
|
||||
for _, p := range c.Providers {
|
||||
var tfc FullCommit
|
||||
tfc, err = p.LatestCommit()
|
||||
if err == nil && tfc.Height() > fc.Height() {
|
||||
fc = tfc
|
||||
}
|
||||
}
|
||||
// even if the last one had an error, if any was a match, this is good
|
||||
if fc.Height() > 0 {
|
||||
err = nil
|
||||
}
|
||||
return fc, err
|
||||
// SaveFullCommit saves a FullCommit (without verification).
|
||||
SaveFullCommit(fc FullCommit) error
|
||||
}
|
||||
|
Reference in New Issue
Block a user