|
|
- package lite
-
- // Provider is used to get more validators by other means.
- //
- // 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)
- }
-
- // 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
- }
-
- // 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
- }
|