Add logs to lite/*; Fix rpc status to return consensus height, not blockstore height

This commit is contained in:
Jae Kwon 2018-06-26 16:52:38 -07:00
parent 7f4498f8b1
commit 37ef5485b4
15 changed files with 174 additions and 68 deletions

1
.gitignore vendored
View File

@ -27,3 +27,4 @@ scripts/cutWALUntil/cutWALUntil
libs/pubsub/query/fuzz_test/output libs/pubsub/query/fuzz_test/output
shunit2 shunit2
.tendermint-lite

View File

@ -6,10 +6,9 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
cmn "github.com/tendermint/tmlibs/common"
"github.com/tendermint/tendermint/lite/proxy" "github.com/tendermint/tendermint/lite/proxy"
rpcclient "github.com/tendermint/tendermint/rpc/client" rpcclient "github.com/tendermint/tendermint/rpc/client"
cmn "github.com/tendermint/tmlibs/common"
) )
// LiteCmd represents the base command when called without any subcommands // LiteCmd represents the base command when called without any subcommands
@ -66,17 +65,21 @@ func runProxy(cmd *cobra.Command, args []string) error {
} }
// First, connect a client // First, connect a client
logger.Info("Connecting to source HTTP client...")
node := rpcclient.NewHTTP(nodeAddr, "/websocket") node := rpcclient.NewHTTP(nodeAddr, "/websocket")
cert, err := proxy.GetCertifier(chainID, home, node) logger.Info("Constructing certifier...")
cert, err := proxy.NewCertifier(chainID, home, node, logger)
if err != nil { if err != nil {
return err return cmn.ErrorWrap(err, "constructing certifier")
} }
cert.SetLogger(logger)
sc := proxy.SecureClient(node, cert) sc := proxy.SecureClient(node, cert)
logger.Info("Starting proxy...")
err = proxy.StartProxy(sc, listenAddr, logger) err = proxy.StartProxy(sc, listenAddr, logger)
if err != nil { if err != nil {
return err return cmn.ErrorWrap(err, "starting proxy")
} }
cmn.TrapSignal(func() { cmn.TrapSignal(func() {

View File

@ -196,6 +196,15 @@ func (cs *ConsensusState) GetState() sm.State {
return cs.state.Copy() return cs.state.Copy()
} }
// GetLastHeight returns the last height committed.
// If there were no blocks, returns 0.
func (cs *ConsensusState) GetLastHeight() int64 {
cs.mtx.Lock()
defer cs.mtx.Unlock()
return cs.RoundState.Height - 1
}
// GetRoundState returns a shallow copy of the internal consensus state. // GetRoundState returns a shallow copy of the internal consensus state.
func (cs *ConsensusState) GetRoundState() *cstypes.RoundState { func (cs *ConsensusState) GetRoundState() *cstypes.RoundState {
cs.mtx.Lock() cs.mtx.Lock()

View File

@ -8,12 +8,12 @@ package client
import ( import (
"fmt" "fmt"
"github.com/tendermint/tendermint/lite"
lerr "github.com/tendermint/tendermint/lite/errors"
rpcclient "github.com/tendermint/tendermint/rpc/client" rpcclient "github.com/tendermint/tendermint/rpc/client"
ctypes "github.com/tendermint/tendermint/rpc/core/types" ctypes "github.com/tendermint/tendermint/rpc/core/types"
"github.com/tendermint/tendermint/types" "github.com/tendermint/tendermint/types"
log "github.com/tendermint/tmlibs/log"
"github.com/tendermint/tendermint/lite"
lerr "github.com/tendermint/tendermint/lite/errors"
) )
// SignStatusClient combines a SignClient and StatusClient. // SignStatusClient combines a SignClient and StatusClient.
@ -23,22 +23,30 @@ type SignStatusClient interface {
} }
type provider struct { type provider struct {
logger log.Logger
chainID string chainID string
client SignStatusClient client SignStatusClient
} }
// NewProvider implements Provider (but not PersistentProvider). // NewProvider implements Provider (but not PersistentProvider).
func NewProvider(chainID string, client SignStatusClient) lite.Provider { func NewProvider(chainID string, client SignStatusClient) lite.Provider {
return &provider{chainID: chainID, client: client} return &provider{
logger: log.NewNopLogger(),
chainID: chainID,
client: client,
}
} }
// NewHTTPProvider can connect to a tendermint json-rpc endpoint // NewHTTPProvider can connect to a tendermint json-rpc endpoint
// at the given url, and uses that as a read-only provider. // at the given url, and uses that as a read-only provider.
func NewHTTPProvider(chainID, remote string) lite.Provider { func NewHTTPProvider(chainID, remote string) lite.Provider {
return &provider{ return NewProvider(chainID, rpcclient.NewHTTP(remote, "/websocket"))
chainID: chainID,
client: rpcclient.NewHTTP(remote, "/websocket"),
} }
// Implements Provider.
func (p *provider) SetLogger(logger log.Logger) {
logger = logger.With("module", "lite/client")
p.logger = logger
} }
// StatusClient returns the internal client as a StatusClient // StatusClient returns the internal client as a StatusClient

View File

@ -10,23 +10,34 @@ import (
lerr "github.com/tendermint/tendermint/lite/errors" lerr "github.com/tendermint/tendermint/lite/errors"
"github.com/tendermint/tendermint/types" "github.com/tendermint/tendermint/types"
dbm "github.com/tendermint/tmlibs/db" dbm "github.com/tendermint/tmlibs/db"
log "github.com/tendermint/tmlibs/log"
) )
type DBProvider struct { type DBProvider struct {
chainID string logger log.Logger
label string
db dbm.DB db dbm.DB
cdc *amino.Codec cdc *amino.Codec
limit int limit int
} }
func NewDBProvider(db dbm.DB) *DBProvider { func NewDBProvider(label string, db dbm.DB) *DBProvider {
//db = dbm.NewDebugDB("db provider "+cmn.RandStr(4), db) //db = dbm.NewDebugDB("db provider "+cmn.RandStr(4), db)
cdc := amino.NewCodec() cdc := amino.NewCodec()
crypto.RegisterAmino(cdc) crypto.RegisterAmino(cdc)
dbp := &DBProvider{db: db, cdc: cdc} dbp := &DBProvider{
logger: log.NewNopLogger(),
label: label,
db: db,
cdc: cdc,
}
return dbp return dbp
} }
func (dbp *DBProvider) SetLogger(logger log.Logger) {
dbp.logger = logger.With("label", dbp.label)
}
func (dbp *DBProvider) SetLimit(limit int) *DBProvider { func (dbp *DBProvider) SetLimit(limit int) *DBProvider {
dbp.limit = limit dbp.limit = limit
return dbp return dbp
@ -35,6 +46,7 @@ func (dbp *DBProvider) SetLimit(limit int) *DBProvider {
// Implements PersistentProvider. // Implements PersistentProvider.
func (dbp *DBProvider) SaveFullCommit(fc FullCommit) error { func (dbp *DBProvider) SaveFullCommit(fc FullCommit) error {
dbp.logger.Info("DBProvider.SaveFullCommit()...", "fc", fc)
batch := dbp.db.NewBatch() batch := dbp.db.NewBatch()
// Save the fc.validators. // Save the fc.validators.
@ -79,6 +91,9 @@ func (dbp *DBProvider) SaveFullCommit(fc FullCommit) error {
func (dbp *DBProvider) LatestFullCommit(chainID string, minHeight, maxHeight int64) ( func (dbp *DBProvider) LatestFullCommit(chainID string, minHeight, maxHeight int64) (
FullCommit, error) { FullCommit, error) {
dbp.logger.Info("DBProvider.LatestFullCommit()...",
"chainID", chainID, "minHeight", minHeight, "maxHeight", maxHeight)
if minHeight <= 0 { if minHeight <= 0 {
minHeight = 1 minHeight = 1
} }
@ -107,7 +122,15 @@ func (dbp *DBProvider) LatestFullCommit(chainID string, minHeight, maxHeight int
if err != nil { if err != nil {
return FullCommit{}, err return FullCommit{}, err
} else { } else {
return dbp.fillFullCommit(sh) lfc, err := dbp.fillFullCommit(sh)
if err == nil {
dbp.logger.Info("DBProvider.LatestFullCommit() found latest.", "height", lfc.Height())
return lfc, nil
} else {
dbp.logger.Info("DBProvider.LatestFullCommit() got error", "lfc", lfc)
dbp.logger.Info(fmt.Sprintf("%+v", err))
return lfc, err
}
} }
} }
} }
@ -155,6 +178,9 @@ func (dbp *DBProvider) fillFullCommit(sh types.SignedHeader) (FullCommit, error)
} }
func (dbp *DBProvider) deleteAfterN(chainID string, after int) error { func (dbp *DBProvider) deleteAfterN(chainID string, after int) error {
dbp.logger.Info("DBProvider.deleteAfterN()...", "chainID", chainID, "after", after)
itr := dbp.db.ReverseIterator( itr := dbp.db.ReverseIterator(
signedHeaderKey(chainID, 1<<63-1), signedHeaderKey(chainID, 1<<63-1),
signedHeaderKey(chainID, 0), signedHeaderKey(chainID, 0),
@ -163,6 +189,7 @@ func (dbp *DBProvider) deleteAfterN(chainID string, after int) error {
var lastHeight int64 = 1<<63 - 1 var lastHeight int64 = 1<<63 - 1
var numSeen = 0 var numSeen = 0
var numDeleted = 0
for itr.Valid() { for itr.Valid() {
key := itr.Key() key := itr.Key()
@ -176,9 +203,13 @@ func (dbp *DBProvider) deleteAfterN(chainID string, after int) error {
} }
if numSeen > after { if numSeen > after {
dbp.db.Delete(key) dbp.db.Delete(key)
numDeleted += 1
} }
} }
itr.Next()
} }
dbp.logger.Info(fmt.Sprintf("DBProvider.deleteAfterN() deleted %v items\n", numDeleted))
return nil return nil
} }

View File

@ -92,8 +92,9 @@ type PersistentProvider interface {
* MultiProvider - combine multiple providers. * MultiProvider - combine multiple providers.
The suggested use for local light clients is client.NewHTTPProvider(...) for The suggested use for local light clients is client.NewHTTPProvider(...) for
getting new data (Source), and NewMultiProvider(NewDBProvider(dbm.NewMemDB()), getting new data (Source), and NewMultiProvider(NewDBProvider("label",
NewDBProvider(db.NewFileDB(...))) to store confirmed full commits (Trusted) dbm.NewMemDB()), NewDBProvider("label", db.NewFileDB(...))) to store confirmed
full commits (Trusted)
# How We Track Validators # How We Track Validators

View File

@ -3,9 +3,9 @@ package lite
import ( import (
"bytes" "bytes"
"github.com/tendermint/tendermint/types"
lerr "github.com/tendermint/tendermint/lite/errors" lerr "github.com/tendermint/tendermint/lite/errors"
"github.com/tendermint/tendermint/types"
log "github.com/tendermint/tmlibs/log"
) )
var _ Certifier = (*InquiringCertifier)(nil) var _ Certifier = (*InquiringCertifier)(nil)
@ -15,6 +15,7 @@ var _ Certifier = (*InquiringCertifier)(nil)
// validator set changes. It stores properly validated data on the // validator set changes. It stores properly validated data on the
// "trusted" local system. // "trusted" local system.
type InquiringCertifier struct { type InquiringCertifier struct {
logger log.Logger
chainID string chainID string
// These are only properly validated data, from local system. // These are only properly validated data, from local system.
trusted PersistentProvider trusted PersistentProvider
@ -28,14 +29,20 @@ type InquiringCertifier struct {
// //
// The trusted provider should a CacheProvider, MemProvider or // The trusted provider should a CacheProvider, MemProvider or
// files.Provider. The source provider should be a client.HTTPProvider. // files.Provider. The source provider should be a client.HTTPProvider.
func NewInquiringCertifier(chainID string, trusted PersistentProvider, source Provider) ( func NewInquiringCertifier(chainID string, trusted PersistentProvider, source Provider) *InquiringCertifier {
*InquiringCertifier, error) {
return &InquiringCertifier{ return &InquiringCertifier{
logger: log.NewNopLogger(),
chainID: chainID, chainID: chainID,
trusted: trusted, trusted: trusted,
source: source, source: source,
}, nil }
}
func (ic *InquiringCertifier) SetLogger(logger log.Logger) {
logger = logger.With("module", "lite")
ic.logger = logger
ic.trusted.SetLogger(logger)
ic.source.SetLogger(logger)
} }
// Implements Certifier. // Implements Certifier.

View File

@ -8,12 +8,13 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
dbm "github.com/tendermint/tmlibs/db" dbm "github.com/tendermint/tmlibs/db"
log "github.com/tendermint/tmlibs/log"
) )
func TestInquirerValidPath(t *testing.T) { func TestInquirerValidPath(t *testing.T) {
assert, require := assert.New(t), require.New(t) assert, require := assert.New(t), require.New(t)
trust := NewDBProvider(dbm.NewMemDB()) trust := NewDBProvider("trust", dbm.NewMemDB())
source := NewDBProvider(dbm.NewMemDB()) source := NewDBProvider("source", dbm.NewMemDB())
// Set up the validators to generate test blocks. // Set up the validators to generate test blocks.
var vote int64 = 10 var vote int64 = 10
@ -43,8 +44,8 @@ func TestInquirerValidPath(t *testing.T) {
// Initialize a certifier with the initial state. // Initialize a certifier with the initial state.
err := trust.SaveFullCommit(fcz[0]) err := trust.SaveFullCommit(fcz[0])
require.Nil(err) require.Nil(err)
cert, err := NewInquiringCertifier(chainID, trust, source) cert := NewInquiringCertifier(chainID, trust, source)
require.Nil(err) cert.SetLogger(log.TestingLogger())
// This should fail validation: // This should fail validation:
sh := fcz[count-1].SignedHeader sh := fcz[count-1].SignedHeader
@ -70,8 +71,8 @@ func TestInquirerValidPath(t *testing.T) {
func TestInquirerVerifyHistorical(t *testing.T) { func TestInquirerVerifyHistorical(t *testing.T) {
assert, require := assert.New(t), require.New(t) assert, require := assert.New(t), require.New(t)
trust := NewDBProvider(dbm.NewMemDB()) trust := NewDBProvider("trust", dbm.NewMemDB())
source := NewDBProvider(dbm.NewMemDB()) source := NewDBProvider("source", dbm.NewMemDB())
// Set up the validators to generate test blocks. // Set up the validators to generate test blocks.
var vote int64 = 10 var vote int64 = 10
@ -101,8 +102,8 @@ func TestInquirerVerifyHistorical(t *testing.T) {
// Initialize a certifier with the initial state. // Initialize a certifier with the initial state.
err := trust.SaveFullCommit(fcz[0]) err := trust.SaveFullCommit(fcz[0])
require.Nil(err) require.Nil(err)
cert, err := NewInquiringCertifier(chainID, trust, source) cert := NewInquiringCertifier(chainID, trust, source)
require.Nil(err) cert.SetLogger(log.TestingLogger())
// Store a few full commits as trust. // Store a few full commits as trust.
for _, i := range []int{2, 5} { for _, i := range []int{2, 5} {

View File

@ -3,24 +3,35 @@ package lite
import ( import (
lerr "github.com/tendermint/tendermint/lite/errors" lerr "github.com/tendermint/tendermint/lite/errors"
"github.com/tendermint/tendermint/types" "github.com/tendermint/tendermint/types"
log "github.com/tendermint/tmlibs/log"
) )
// multiProvider allows you to place one or more caches in front of a source // multiProvider 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. // Provider. It runs through them in order until a match is found.
type multiProvider struct { type multiProvider struct {
Providers []PersistentProvider logger log.Logger
providers []PersistentProvider
} }
// NewMultiProvider returns a new provider which wraps multiple other providers. // NewMultiProvider returns a new provider which wraps multiple other providers.
func NewMultiProvider(providers ...PersistentProvider) multiProvider { func NewMultiProvider(providers ...PersistentProvider) *multiProvider {
return multiProvider{ return &multiProvider{
Providers: providers, logger: log.NewNopLogger(),
providers: providers,
}
}
// SetLogger sets logger on self and all subproviders.
func (mc *multiProvider) SetLogger(logger log.Logger) {
mc.logger = logger
for _, p := range mc.providers {
p.SetLogger(logger)
} }
} }
// SaveFullCommit saves on all providers, and aborts on the first error. // SaveFullCommit saves on all providers, and aborts on the first error.
func (mc multiProvider) SaveFullCommit(fc FullCommit) (err error) { func (mc *multiProvider) SaveFullCommit(fc FullCommit) (err error) {
for _, p := range mc.Providers { for _, p := range mc.providers {
err = p.SaveFullCommit(fc) err = p.SaveFullCommit(fc)
if err != nil { if err != nil {
return return
@ -32,8 +43,8 @@ func (mc multiProvider) SaveFullCommit(fc FullCommit) (err error) {
// LatestFullCommit loads the latest from all providers and provides // LatestFullCommit loads the latest from all providers and provides
// the latest FullCommit that satisfies the conditions. // the latest FullCommit that satisfies the conditions.
// Returns the first error encountered. // Returns the first error encountered.
func (mc multiProvider) LatestFullCommit(chainID string, minHeight, maxHeight int64) (fc FullCommit, err error) { func (mc *multiProvider) LatestFullCommit(chainID string, minHeight, maxHeight int64) (fc FullCommit, err error) {
for _, p := range mc.Providers { for _, p := range mc.providers {
var fc_ FullCommit var fc_ FullCommit
fc_, err = p.LatestFullCommit(chainID, minHeight, maxHeight) fc_, err = p.LatestFullCommit(chainID, minHeight, maxHeight)
if lerr.IsErrCommitNotFound(err) { if lerr.IsErrCommitNotFound(err) {
@ -60,8 +71,8 @@ func (mc multiProvider) LatestFullCommit(chainID string, minHeight, maxHeight in
// ValidatorSet returns validator set at height as provided by the first // ValidatorSet returns validator set at height as provided by the first
// provider which has it, or an error otherwise. // provider which has it, or an error otherwise.
func (mc multiProvider) ValidatorSet(chainID string, height int64) (valset *types.ValidatorSet, err error) { func (mc *multiProvider) ValidatorSet(chainID string, height int64) (valset *types.ValidatorSet, err error) {
for _, p := range mc.Providers { for _, p := range mc.providers {
valset, err = p.ValidatorSet(chainID, height) valset, err = p.ValidatorSet(chainID, height)
if err == nil { if err == nil {
// TODO Log unexpected types of errors. // TODO Log unexpected types of errors.

View File

@ -2,6 +2,7 @@ package lite
import ( import (
"github.com/tendermint/tendermint/types" "github.com/tendermint/tendermint/types"
log "github.com/tendermint/tmlibs/log"
) )
// Provider provides information for the lite client to sync validators. // Provider provides information for the lite client to sync validators.
@ -16,6 +17,9 @@ type Provider interface {
// Get the valset that corresponds to chainID and height and return. // Get the valset that corresponds to chainID and height and return.
// Height must be >= 1. // Height must be >= 1.
ValidatorSet(chainID string, height int64) (*types.ValidatorSet, error) ValidatorSet(chainID string, height int64) (*types.ValidatorSet, error)
// Set a logger.
SetLogger(logger log.Logger)
} }
// A provider that can also persist new information. // A provider that can also persist new information.

View File

@ -10,6 +10,7 @@ import (
lerr "github.com/tendermint/tendermint/lite/errors" lerr "github.com/tendermint/tendermint/lite/errors"
"github.com/tendermint/tendermint/types" "github.com/tendermint/tendermint/types"
dbm "github.com/tendermint/tmlibs/db" dbm "github.com/tendermint/tmlibs/db"
log "github.com/tendermint/tmlibs/log"
) )
// missingProvider doesn't store anything, always a miss. // missingProvider doesn't store anything, always a miss.
@ -28,16 +29,17 @@ func (missingProvider) LatestFullCommit(chainID string, minHeight, maxHeight int
func (missingProvider) ValidatorSet(chainID string, height int64) (*types.ValidatorSet, error) { func (missingProvider) ValidatorSet(chainID string, height int64) (*types.ValidatorSet, error) {
return nil, errors.New("missing validator set") return nil, errors.New("missing validator set")
} }
func (missingProvider) SetLogger(_ log.Logger) {}
func TestMemProvider(t *testing.T) { func TestMemProvider(t *testing.T) {
p := NewDBProvider(dbm.NewMemDB()) p := NewDBProvider("mem", dbm.NewMemDB())
checkProvider(t, p, "test-mem", "empty") checkProvider(t, p, "test-mem", "empty")
} }
func TestMultiProvider(t *testing.T) { func TestMultiProvider(t *testing.T) {
p := NewMultiProvider( p := NewMultiProvider(
NewMissingProvider(), NewMissingProvider(),
NewDBProvider(dbm.NewMemDB()), NewDBProvider("mem", dbm.NewMemDB()),
NewMissingProvider(), NewMissingProvider(),
) )
checkProvider(t, p, "test-cache", "kjfhekfhkewhgit") checkProvider(t, p, "test-cache", "kjfhekfhkewhgit")
@ -105,8 +107,8 @@ func TestMultiLatestFullCommit(t *testing.T) {
// We will write data to the second level of the cache (p2), and see what // We will write data to the second level of the cache (p2), and see what
// gets cached/stored in. // gets cached/stored in.
p := NewDBProvider(dbm.NewMemDB()) p := NewDBProvider("mem1", dbm.NewMemDB())
p2 := NewDBProvider(dbm.NewMemDB()) p2 := NewDBProvider("mem2", dbm.NewMemDB())
cp := NewMultiProvider(p, p2) cp := NewMultiProvider(p, p2)
chainID := "cache-best-height" chainID := "cache-best-height"

View File

@ -3,33 +3,39 @@ package proxy
import ( import (
"github.com/tendermint/tendermint/lite" "github.com/tendermint/tendermint/lite"
lclient "github.com/tendermint/tendermint/lite/client" lclient "github.com/tendermint/tendermint/lite/client"
cmn "github.com/tendermint/tmlibs/common"
dbm "github.com/tendermint/tmlibs/db" dbm "github.com/tendermint/tmlibs/db"
log "github.com/tendermint/tmlibs/log"
) )
func GetCertifier(chainID, rootDir string, client lclient.SignStatusClient) (*lite.InquiringCertifier, error) { func NewCertifier(chainID, rootDir string, client lclient.SignStatusClient, logger log.Logger) (*lite.InquiringCertifier, error) {
logger = logger.With("module", "lite/proxy")
logger.Info("lite/proxy/NewCertifier()...", "chainID", chainID, "rootDir", rootDir, "client", client)
memProvider := lite.NewDBProvider("trusted.mem", dbm.NewMemDB()).SetLimit(10)
lvlProvider := lite.NewDBProvider("trusted.lvl", dbm.NewDB("trust-base", dbm.LevelDBBackend, rootDir))
trust := lite.NewMultiProvider( trust := lite.NewMultiProvider(
lite.NewDBProvider(dbm.NewMemDB()).SetLimit(10), memProvider,
lite.NewDBProvider(dbm.NewDB("trust-base", dbm.LevelDBBackend, rootDir)), lvlProvider,
) )
source := lclient.NewProvider(chainID, client) source := lclient.NewProvider(chainID, client)
cert := lite.NewInquiringCertifier(chainID, trust, source)
cert.SetLogger(logger) // Sets logger recursively.
// TODO: Make this more secure, e.g. make it interactive in the console? // TODO: Make this more secure, e.g. make it interactive in the console?
_, err := trust.LatestFullCommit(chainID, 1, 1<<63-1) _, err := trust.LatestFullCommit(chainID, 1, 1<<63-1)
if err != nil { if err != nil {
logger.Info("lite/proxy/NewCertifier found no trusted full commit, initializing from source from height 1...")
fc, err := source.LatestFullCommit(chainID, 1, 1) fc, err := source.LatestFullCommit(chainID, 1, 1)
if err != nil { if err != nil {
return nil, err return nil, cmn.ErrorWrap(err, "fetching source full commit @ height 1")
} }
err = trust.SaveFullCommit(fc) err = trust.SaveFullCommit(fc)
if err != nil { if err != nil {
return nil, err return nil, cmn.ErrorWrap(err, "saving full commit to trusted")
} }
} }
cert, err := lite.NewInquiringCertifier(chainID, trust, source)
if err != nil {
return nil, err
}
return cert, nil return cert, nil
} }

View File

@ -89,33 +89,49 @@ func (w Wrapper) BlockchainInfo(minHeight, maxHeight int64) (*ctypes.ResultBlock
// Block returns an entire block and verifies all signatures // Block returns an entire block and verifies all signatures
func (w Wrapper) Block(height *int64) (*ctypes.ResultBlock, error) { func (w Wrapper) Block(height *int64) (*ctypes.ResultBlock, error) {
r, err := w.Client.Block(height) resBlock, err := w.Client.Block(height)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// get a checkpoint to verify from // get a checkpoint to verify from
res, err := w.Commit(height) resCommit, err := w.Commit(height)
if err != nil { if err != nil {
return nil, err return nil, err
} }
sh := res.SignedHeader sh := resCommit.SignedHeader
// now verify // now verify
err = ValidateBlockMeta(r.BlockMeta, sh) err = ValidateBlockMeta(resBlock.BlockMeta, sh)
if err != nil { if err != nil {
return nil, err return nil, err
} }
err = ValidateBlock(r.Block, sh) err = ValidateBlock(resBlock.Block, sh)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return r, nil return resBlock, nil
} }
// Commit downloads the Commit and certifies it with the lite. // Commit downloads the Commit and certifies it with the lite.
// //
// This is the foundation for all other verification in this module // This is the foundation for all other verification in this module
func (w Wrapper) Commit(height *int64) (*ctypes.ResultCommit, error) { func (w Wrapper) Commit(height *int64) (*ctypes.ResultCommit, error) {
if height == nil {
resStatus, err := w.Client.Status()
if err != nil {
return nil, err
}
// NOTE: If resStatus.CatchingUp, there is a race
// condition where the validator set for the next height
// isn't available until some time after the blockstore
// has height h on the remote node. This isn't an issue
// once the node has caught up, and a syncing node likely
// won't have this issue esp with the implementation we
// have here, but we may have to address this at some
// point.
height = new(int64)
*height = resStatus.SyncInfo.LatestBlockHeight
}
rpcclient.WaitForHeight(w.Client, *height, nil) rpcclient.WaitForHeight(w.Client, *height, nil)
res, err := w.Client.Commit(height) res, err := w.Client.Commit(height)
// if we got it, then certify it // if we got it, then certify it

View File

@ -3,8 +3,8 @@ package core
import ( import (
"time" "time"
crypto "github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/consensus" "github.com/tendermint/tendermint/consensus"
crypto "github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/p2p" "github.com/tendermint/tendermint/p2p"
"github.com/tendermint/tendermint/proxy" "github.com/tendermint/tendermint/proxy"
sm "github.com/tendermint/tendermint/state" sm "github.com/tendermint/tendermint/state"
@ -28,6 +28,7 @@ var subscribeTimeout = 5 * time.Second
type Consensus interface { type Consensus interface {
GetState() sm.State GetState() sm.State
GetValidators() (int64, []*types.Validator) GetValidators() (int64, []*types.Validator)
GetLastHeight() int64
GetRoundStateJSON() ([]byte, error) GetRoundStateJSON() ([]byte, error)
GetRoundStateSimpleJSON() ([]byte, error) GetRoundStateSimpleJSON() ([]byte, error)
} }

View File

@ -64,7 +64,12 @@ import (
//} //}
// ``` // ```
func Status() (*ctypes.ResultStatus, error) { func Status() (*ctypes.ResultStatus, error) {
latestHeight := blockStore.Height() var latestHeight int64 = -1
if consensusReactor.FastSync() {
latestHeight = blockStore.Height()
} else {
latestHeight = consensusState.GetLastHeight()
}
var ( var (
latestBlockMeta *types.BlockMeta latestBlockMeta *types.BlockMeta
latestBlockHash cmn.HexBytes latestBlockHash cmn.HexBytes