mirror of
https://github.com/tendermint/tendermint.git
synced 2026-01-06 13:26:23 +00:00
simplify commit and validators rpc calls (#5393)
This commit is contained in:
committed by
Erik Grinaker
parent
7c17fa115a
commit
3822ab924e
@@ -13,6 +13,7 @@ import (
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
"github.com/tendermint/tendermint/crypto/merkle"
|
||||
tmbytes "github.com/tendermint/tendermint/libs/bytes"
|
||||
tmmath "github.com/tendermint/tendermint/libs/math"
|
||||
service "github.com/tendermint/tendermint/libs/service"
|
||||
light "github.com/tendermint/tendermint/light"
|
||||
rpcclient "github.com/tendermint/tendermint/rpc/client"
|
||||
@@ -375,32 +376,16 @@ func (c *Client) BlockResults(ctx context.Context, height *int64) (*ctypes.Resul
|
||||
}
|
||||
|
||||
func (c *Client) Commit(ctx context.Context, height *int64) (*ctypes.ResultCommit, error) {
|
||||
res, err := c.next.Commit(ctx, height)
|
||||
// Update the light client if we're behind and retrieve the light block at the requested height
|
||||
l, err := c.updateLightClientIfNeededTo(ctx, *height)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Validate res.
|
||||
if err := res.SignedHeader.ValidateBasic(c.lc.ChainID()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if res.Height <= 0 {
|
||||
return nil, errNegOrZeroHeight
|
||||
}
|
||||
|
||||
// Update the light client if we're behind.
|
||||
l, err := c.updateLightClientIfNeededTo(ctx, res.Height)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Verify commit.
|
||||
if rH, tH := res.Hash(), l.Hash(); !bytes.Equal(rH, tH) {
|
||||
return nil, fmt.Errorf("header %X does not match with trusted header %X",
|
||||
rH, tH)
|
||||
}
|
||||
|
||||
return res, nil
|
||||
return &ctypes.ResultCommit{
|
||||
SignedHeader: *l.SignedHeader,
|
||||
CanonicalCommit: true,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Tx calls rpcclient#Tx method and then verifies the proof if such was
|
||||
@@ -432,52 +417,30 @@ func (c *Client) TxSearch(ctx context.Context, query string, prove bool, page, p
|
||||
}
|
||||
|
||||
// Validators fetches and verifies validators.
|
||||
//
|
||||
// WARNING: only full validator sets are verified (when length of validators is
|
||||
// less than +perPage+. +perPage+ default is 30, max is 100).
|
||||
func (c *Client) Validators(ctx context.Context, height *int64, page, perPage *int) (*ctypes.ResultValidators, error) {
|
||||
res, err := c.next.Validators(ctx, height, page, perPage)
|
||||
func (c *Client) Validators(ctx context.Context, height *int64, pagePtr, perPagePtr *int) (*ctypes.ResultValidators,
|
||||
error) {
|
||||
// Update the light client if we're behind and retrieve the light block at the requested height.
|
||||
l, err := c.updateLightClientIfNeededTo(ctx, *height)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Validate res.
|
||||
if res.BlockHeight <= 0 {
|
||||
return nil, errNegOrZeroHeight
|
||||
}
|
||||
|
||||
updateHeight := res.BlockHeight - 1
|
||||
|
||||
// updateHeight can't be zero which happens when we are looking for the validators of the first block
|
||||
if updateHeight == 0 {
|
||||
updateHeight = 1
|
||||
}
|
||||
|
||||
// Update the light client if we're behind.
|
||||
l, err := c.updateLightClientIfNeededTo(ctx, updateHeight)
|
||||
totalCount := len(l.ValidatorSet.Validators)
|
||||
perPage := validatePerPage(perPagePtr)
|
||||
page, err := validatePage(pagePtr, perPage, totalCount)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tH tmbytes.HexBytes
|
||||
switch res.BlockHeight {
|
||||
case 1:
|
||||
// if it's the first block we need to validate with the current validator hash as opposed to the
|
||||
// next validator hash
|
||||
tH = l.ValidatorsHash
|
||||
default:
|
||||
tH = l.NextValidatorsHash
|
||||
}
|
||||
skipCount := validateSkipCount(page, perPage)
|
||||
|
||||
// Verify validators.
|
||||
if res.Count <= res.Total {
|
||||
if rH := types.NewValidatorSet(res.Validators).Hash(); !bytes.Equal(rH, tH) {
|
||||
return nil, fmt.Errorf("validators %X does not match with trusted validators %X",
|
||||
rH, tH)
|
||||
}
|
||||
}
|
||||
v := l.ValidatorSet.Validators[skipCount : skipCount+tmmath.MinInt(perPage, totalCount-skipCount)]
|
||||
|
||||
return res, nil
|
||||
return &ctypes.ResultValidators{
|
||||
BlockHeight: *height,
|
||||
Validators: v,
|
||||
Count: len(v),
|
||||
Total: totalCount}, nil
|
||||
}
|
||||
|
||||
func (c *Client) BroadcastEvidence(ctx context.Context, ev types.Evidence) (*ctypes.ResultBroadcastEvidence, error) {
|
||||
@@ -575,3 +538,54 @@ func parseQueryStorePath(path string) (storeName string, err error) {
|
||||
|
||||
return paths[1], nil
|
||||
}
|
||||
|
||||
// XXX: Copied from rpc/core/env.go
|
||||
const (
|
||||
// see README
|
||||
defaultPerPage = 30
|
||||
maxPerPage = 100
|
||||
)
|
||||
|
||||
func validatePage(pagePtr *int, perPage, totalCount int) (int, error) {
|
||||
if perPage < 1 {
|
||||
panic(fmt.Sprintf("zero or negative perPage: %d", perPage))
|
||||
}
|
||||
|
||||
if pagePtr == nil { // no page parameter
|
||||
return 1, nil
|
||||
}
|
||||
|
||||
pages := ((totalCount - 1) / perPage) + 1
|
||||
if pages == 0 {
|
||||
pages = 1 // one page (even if it's empty)
|
||||
}
|
||||
page := *pagePtr
|
||||
if page <= 0 || page > pages {
|
||||
return 1, fmt.Errorf("page should be within [1, %d] range, given %d", pages, page)
|
||||
}
|
||||
|
||||
return page, nil
|
||||
}
|
||||
|
||||
func validatePerPage(perPagePtr *int) int {
|
||||
if perPagePtr == nil { // no per_page parameter
|
||||
return defaultPerPage
|
||||
}
|
||||
|
||||
perPage := *perPagePtr
|
||||
if perPage < 1 {
|
||||
return defaultPerPage
|
||||
} else if perPage > maxPerPage {
|
||||
return maxPerPage
|
||||
}
|
||||
return perPage
|
||||
}
|
||||
|
||||
func validateSkipCount(page, perPage int) int {
|
||||
skipCount := (page - 1) * perPage
|
||||
if skipCount < 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
return skipCount
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user