mirror of
https://github.com/tendermint/tendermint.git
synced 2026-02-08 04:50:16 +00:00
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.
106 lines
3.0 KiB
Go
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
|
|
}
|