Files
tendermint/rpc/core/status.go
Erik Grinaker 511ab6717c add state sync reactor (#4705)
Fixes #828. Adds state sync, as outlined in [ADR-053](https://github.com/tendermint/tendermint/blob/master/docs/architecture/adr-053-state-sync-prototype.md). See related PRs in Cosmos SDK (https://github.com/cosmos/cosmos-sdk/pull/5803) and Gaia (https://github.com/cosmos/gaia/pull/327).

This is split out of the previous PR #4645, and branched off of the ABCI interface in #4704. 

* Adds a new P2P reactor which exchanges snapshots with peers, and bootstraps an empty local node from remote snapshots when requested.

* Adds a new configuration section `[statesync]` that enables state sync and configures the light client. Also enables `statesync:info` logging by default.

* Integrates state sync into node startup. Does not support the v2 blockchain reactor, since it needs some reorganization to defer startup.
2020-04-29 10:47:00 +02:00

106 lines
3.0 KiB
Go

package core
import (
"bytes"
"time"
tmbytes "github.com/tendermint/tendermint/libs/bytes"
"github.com/tendermint/tendermint/p2p"
ctypes "github.com/tendermint/tendermint/rpc/core/types"
rpctypes "github.com/tendermint/tendermint/rpc/lib/types"
sm "github.com/tendermint/tendermint/state"
"github.com/tendermint/tendermint/types"
)
// Status returns Tendermint status including node info, pubkey, latest block
// hash, app hash, block height and time.
// More: https://docs.tendermint.com/master/rpc/#/Info/status
func Status(ctx *rpctypes.Context) (*ctypes.ResultStatus, error) {
var (
earliestBlockMeta *types.BlockMeta
earliestBlockHash tmbytes.HexBytes
earliestAppHash tmbytes.HexBytes
earliestBlockTimeNano int64
)
earliestBlockHeight := blockStore.Base()
earliestBlockMeta = blockStore.LoadBlockMeta(earliestBlockHeight)
if earliestBlockMeta != nil {
earliestAppHash = earliestBlockMeta.Header.AppHash
earliestBlockHash = earliestBlockMeta.BlockID.Hash
earliestBlockTimeNano = earliestBlockMeta.Header.Time.UnixNano()
}
var latestHeight int64
if consensusReactor.WaitSync() {
latestHeight = blockStore.Height()
} else {
latestHeight = consensusState.GetLastHeight()
}
var (
latestBlockMeta *types.BlockMeta
latestBlockHash tmbytes.HexBytes
latestAppHash tmbytes.HexBytes
latestBlockTimeNano int64
)
if latestHeight != 0 {
latestBlockMeta = blockStore.LoadBlockMeta(latestHeight)
latestBlockHash = latestBlockMeta.BlockID.Hash
latestAppHash = latestBlockMeta.Header.AppHash
latestBlockTimeNano = latestBlockMeta.Header.Time.UnixNano()
}
var votingPower int64
if val := validatorAtHeight(latestHeight); val != nil {
votingPower = val.VotingPower
}
result := &ctypes.ResultStatus{
NodeInfo: p2pTransport.NodeInfo().(p2p.DefaultNodeInfo),
SyncInfo: ctypes.SyncInfo{
LatestBlockHash: latestBlockHash,
LatestAppHash: latestAppHash,
LatestBlockHeight: latestHeight,
LatestBlockTime: time.Unix(0, latestBlockTimeNano),
EarliestBlockHash: earliestBlockHash,
EarliestAppHash: earliestAppHash,
EarliestBlockHeight: earliestBlockHeight,
EarliestBlockTime: time.Unix(0, earliestBlockTimeNano),
CatchingUp: consensusReactor.WaitSync(),
},
ValidatorInfo: ctypes.ValidatorInfo{
Address: pubKey.Address(),
PubKey: pubKey,
VotingPower: votingPower,
},
}
return result, nil
}
func validatorAtHeight(h int64) *types.Validator {
privValAddress := pubKey.Address()
// If we're still at height h, search in the current validator set.
lastBlockHeight, vals := consensusState.GetValidators()
if lastBlockHeight == h {
for _, val := range vals {
if bytes.Equal(val.Address, privValAddress) {
return val
}
}
}
// If we've moved to the next height, retrieve the validator set from DB.
if lastBlockHeight > h {
vals, err := sm.LoadValidators(stateDB, h)
if err != nil {
return nil // should not happen
}
_, val := vals.GetByAddress(privValAddress)
return val
}
return nil
}