Files
tendermint/rpc/core/status.go
Erik Grinaker 4298bbcc4e add support for block pruning via ABCI Commit response (#4588)
* Added BlockStore.DeleteBlock()

* Added initial block pruner prototype

* wip

* Added BlockStore.PruneBlocks()

* Added consensus setting for block pruning

* Added BlockStore base

* Error on replay if base does not have blocks

* Handle missing blocks when sending VoteSetMaj23Message

* Error message tweak

* Properly update blockstore state

* Error message fix again

* blockchain: ignore peer missing blocks

* Added FIXME

* Added test for block replay with truncated history

* Handle peer base in blockchain reactor

* Improved replay error handling

* Added tests for Store.PruneBlocks()

* Fix non-RPC handling of truncated block history

* Panic on missing block meta in needProofBlock()

* Updated changelog

* Handle truncated block history in RPC layer

* Added info about earliest block in /status RPC

* Reorder height and base in blockchain reactor messages

* Updated changelog

* Fix tests

* Appease linter

* Minor review fixes

* Non-empty BlockStores should always have base > 0

* Update code to assume base > 0 invariant

* Added blockstore tests for pruning to 0

* Make sure we don't prune below the current base

* Added BlockStore.Size()

* config: added retain_blocks recommendations

* Update v1 blockchain reactor to handle blockstore base

* Added state database pruning

* Propagate errors on missing validator sets

* Comment tweaks

* Improved error message

Co-Authored-By: Anton Kaliaev <anton.kalyaev@gmail.com>

* use ABCI field ResponseCommit.retain_height instead of retain-blocks config option

* remove State.RetainHeight, return value instead

* fix minor issues

* rename pruneHeights() to pruneBlocks()

* noop to fix GitHub borkage

Co-authored-by: Anton Kaliaev <anton.kalyaev@gmail.com>
2020-04-03 08:38:32 +00: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.FastSync() {
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.FastSync(),
},
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
}