Browse Source

simplify commit and validators rpc calls (#5393)

pull/5405/head
Callum Waters 4 years ago
committed by GitHub
parent
commit
f02987e7bc
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 72 additions and 58 deletions
  1. +72
    -58
      light/rpc/client.go

+ 72
- 58
light/rpc/client.go View File

@ -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
}

Loading…
Cancel
Save