github.com/Oyster-zx/tendermint@v0.34.24-fork/light/rpc/client.go (about) 1 package rpc 2 3 import ( 4 "bytes" 5 "context" 6 "errors" 7 "fmt" 8 "regexp" 9 "time" 10 11 "github.com/gogo/protobuf/proto" 12 13 abci "github.com/tendermint/tendermint/abci/types" 14 "github.com/tendermint/tendermint/crypto/merkle" 15 tmbytes "github.com/tendermint/tendermint/libs/bytes" 16 tmmath "github.com/tendermint/tendermint/libs/math" 17 service "github.com/tendermint/tendermint/libs/service" 18 rpcclient "github.com/tendermint/tendermint/rpc/client" 19 ctypes "github.com/tendermint/tendermint/rpc/core/types" 20 rpctypes "github.com/tendermint/tendermint/rpc/jsonrpc/types" 21 "github.com/tendermint/tendermint/types" 22 ) 23 24 var errNegOrZeroHeight = errors.New("negative or zero height") 25 26 // KeyPathFunc builds a merkle path out of the given path and key. 27 type KeyPathFunc func(path string, key []byte) (merkle.KeyPath, error) 28 29 // LightClient is an interface that contains functionality needed by Client from the light client. 30 // 31 //go:generate ../../scripts/mockery_generate.sh LightClient 32 type LightClient interface { 33 ChainID() string 34 Update(ctx context.Context, now time.Time) (*types.LightBlock, error) 35 VerifyLightBlockAtHeight(ctx context.Context, height int64, now time.Time) (*types.LightBlock, error) 36 TrustedLightBlock(height int64) (*types.LightBlock, error) 37 } 38 39 var _ rpcclient.Client = (*Client)(nil) 40 41 // Client is an RPC client, which uses light#Client to verify data (if it can 42 // be proved). Note, merkle.DefaultProofRuntime is used to verify values 43 // returned by ABCI#Query. 44 type Client struct { 45 service.BaseService 46 47 next rpcclient.Client 48 lc LightClient 49 50 // proof runtime used to verify values returned by ABCIQuery 51 prt *merkle.ProofRuntime 52 keyPathFn KeyPathFunc 53 } 54 55 var _ rpcclient.Client = (*Client)(nil) 56 57 // Option allow you to tweak Client. 58 type Option func(*Client) 59 60 // KeyPathFn option can be used to set a function, which parses a given path 61 // and builds the merkle path for the prover. It must be provided if you want 62 // to call ABCIQuery or ABCIQueryWithOptions. 63 func KeyPathFn(fn KeyPathFunc) Option { 64 return func(c *Client) { 65 c.keyPathFn = fn 66 } 67 } 68 69 // DefaultMerkleKeyPathFn creates a function used to generate merkle key paths 70 // from a path string and a key. This is the default used by the cosmos SDK. 71 // This merkle key paths are required when verifying /abci_query calls 72 func DefaultMerkleKeyPathFn() KeyPathFunc { 73 // regexp for extracting store name from /abci_query path 74 storeNameRegexp := regexp.MustCompile(`\/store\/(.+)\/key`) 75 76 return func(path string, key []byte) (merkle.KeyPath, error) { 77 matches := storeNameRegexp.FindStringSubmatch(path) 78 if len(matches) != 2 { 79 return nil, fmt.Errorf("can't find store name in %s using %s", path, storeNameRegexp) 80 } 81 storeName := matches[1] 82 83 kp := merkle.KeyPath{} 84 kp = kp.AppendKey([]byte(storeName), merkle.KeyEncodingURL) 85 kp = kp.AppendKey(key, merkle.KeyEncodingURL) 86 return kp, nil 87 } 88 } 89 90 // NewClient returns a new client. 91 func NewClient(next rpcclient.Client, lc LightClient, opts ...Option) *Client { 92 c := &Client{ 93 next: next, 94 lc: lc, 95 prt: merkle.DefaultProofRuntime(), 96 } 97 c.BaseService = *service.NewBaseService(nil, "Client", c) 98 for _, o := range opts { 99 o(c) 100 } 101 return c 102 } 103 104 func (c *Client) OnStart() error { 105 if !c.next.IsRunning() { 106 return c.next.Start() 107 } 108 return nil 109 } 110 111 func (c *Client) OnStop() { 112 if c.next.IsRunning() { 113 if err := c.next.Stop(); err != nil { 114 c.Logger.Error("Error stopping on next", "err", err) 115 } 116 } 117 } 118 119 func (c *Client) Status(ctx context.Context) (*ctypes.ResultStatus, error) { 120 return c.next.Status(ctx) 121 } 122 123 func (c *Client) ABCIInfo(ctx context.Context) (*ctypes.ResultABCIInfo, error) { 124 return c.next.ABCIInfo(ctx) 125 } 126 127 // ABCIQuery requests proof by default. 128 func (c *Client) ABCIQuery(ctx context.Context, path string, data tmbytes.HexBytes) (*ctypes.ResultABCIQuery, error) { 129 return c.ABCIQueryWithOptions(ctx, path, data, rpcclient.DefaultABCIQueryOptions) 130 } 131 132 // ABCIQueryWithOptions returns an error if opts.Prove is false. 133 func (c *Client) ABCIQueryWithOptions(ctx context.Context, path string, data tmbytes.HexBytes, 134 opts rpcclient.ABCIQueryOptions) (*ctypes.ResultABCIQuery, error) { 135 136 // always request the proof 137 opts.Prove = true 138 139 res, err := c.next.ABCIQueryWithOptions(ctx, path, data, opts) 140 if err != nil { 141 return nil, err 142 } 143 resp := res.Response 144 145 // Validate the response. 146 if resp.IsErr() { 147 return nil, fmt.Errorf("err response code: %v", resp.Code) 148 } 149 if len(resp.Key) == 0 { 150 return nil, errors.New("empty key") 151 } 152 if resp.ProofOps == nil || len(resp.ProofOps.Ops) == 0 { 153 return nil, errors.New("no proof ops") 154 } 155 if resp.Height <= 0 { 156 return nil, errNegOrZeroHeight 157 } 158 159 // Update the light client if we're behind. 160 // NOTE: AppHash for height H is in header H+1. 161 nextHeight := resp.Height + 1 162 l, err := c.updateLightClientIfNeededTo(ctx, &nextHeight) 163 if err != nil { 164 return nil, err 165 } 166 167 // Validate the value proof against the trusted header. 168 if resp.Value != nil { 169 // 1) build a Merkle key path from path and resp.Key 170 if c.keyPathFn == nil { 171 return nil, errors.New("please configure Client with KeyPathFn option") 172 } 173 174 kp, err := c.keyPathFn(path, resp.Key) 175 if err != nil { 176 return nil, fmt.Errorf("can't build merkle key path: %w", err) 177 } 178 179 // 2) verify value 180 err = c.prt.VerifyValue(resp.ProofOps, l.AppHash, kp.String(), resp.Value) 181 if err != nil { 182 return nil, fmt.Errorf("verify value proof: %w", err) 183 } 184 } else { // OR validate the absence proof against the trusted header. 185 err = c.prt.VerifyAbsence(resp.ProofOps, l.AppHash, string(resp.Key)) 186 if err != nil { 187 return nil, fmt.Errorf("verify absence proof: %w", err) 188 } 189 } 190 191 return &ctypes.ResultABCIQuery{Response: resp}, nil 192 } 193 194 func (c *Client) BroadcastTxCommit(ctx context.Context, tx types.Tx) (*ctypes.ResultBroadcastTxCommit, error) { 195 return c.next.BroadcastTxCommit(ctx, tx) 196 } 197 198 func (c *Client) BroadcastTxAsync(ctx context.Context, tx types.Tx) (*ctypes.ResultBroadcastTx, error) { 199 return c.next.BroadcastTxAsync(ctx, tx) 200 } 201 202 func (c *Client) BroadcastTxSync(ctx context.Context, tx types.Tx) (*ctypes.ResultBroadcastTx, error) { 203 return c.next.BroadcastTxSync(ctx, tx) 204 } 205 206 func (c *Client) UnconfirmedTxs(ctx context.Context, limit *int) (*ctypes.ResultUnconfirmedTxs, error) { 207 return c.next.UnconfirmedTxs(ctx, limit) 208 } 209 210 func (c *Client) NumUnconfirmedTxs(ctx context.Context) (*ctypes.ResultUnconfirmedTxs, error) { 211 return c.next.NumUnconfirmedTxs(ctx) 212 } 213 214 func (c *Client) CheckTx(ctx context.Context, tx types.Tx) (*ctypes.ResultCheckTx, error) { 215 return c.next.CheckTx(ctx, tx) 216 } 217 218 func (c *Client) NetInfo(ctx context.Context) (*ctypes.ResultNetInfo, error) { 219 return c.next.NetInfo(ctx) 220 } 221 222 func (c *Client) DumpConsensusState(ctx context.Context) (*ctypes.ResultDumpConsensusState, error) { 223 return c.next.DumpConsensusState(ctx) 224 } 225 226 func (c *Client) ConsensusState(ctx context.Context) (*ctypes.ResultConsensusState, error) { 227 return c.next.ConsensusState(ctx) 228 } 229 230 func (c *Client) ConsensusParams(ctx context.Context, height *int64) (*ctypes.ResultConsensusParams, error) { 231 res, err := c.next.ConsensusParams(ctx, height) 232 if err != nil { 233 return nil, err 234 } 235 236 // Validate res. 237 if err := types.ValidateConsensusParams(res.ConsensusParams); err != nil { 238 return nil, err 239 } 240 if res.BlockHeight <= 0 { 241 return nil, errNegOrZeroHeight 242 } 243 244 // Update the light client if we're behind. 245 l, err := c.updateLightClientIfNeededTo(ctx, &res.BlockHeight) 246 if err != nil { 247 return nil, err 248 } 249 250 // Verify hash. 251 if cH, tH := types.HashConsensusParams(res.ConsensusParams), l.ConsensusHash; !bytes.Equal(cH, tH) { 252 return nil, fmt.Errorf("params hash %X does not match trusted hash %X", 253 cH, tH) 254 } 255 256 return res, nil 257 } 258 259 func (c *Client) Health(ctx context.Context) (*ctypes.ResultHealth, error) { 260 return c.next.Health(ctx) 261 } 262 263 // BlockchainInfo calls rpcclient#BlockchainInfo and then verifies every header 264 // returned. 265 func (c *Client) BlockchainInfo(ctx context.Context, minHeight, maxHeight int64) (*ctypes.ResultBlockchainInfo, error) { 266 res, err := c.next.BlockchainInfo(ctx, minHeight, maxHeight) 267 if err != nil { 268 return nil, err 269 } 270 271 // Validate res. 272 for i, meta := range res.BlockMetas { 273 if meta == nil { 274 return nil, fmt.Errorf("nil block meta %d", i) 275 } 276 if err := meta.ValidateBasic(); err != nil { 277 return nil, fmt.Errorf("invalid block meta %d: %w", i, err) 278 } 279 } 280 281 // Update the light client if we're behind. 282 if len(res.BlockMetas) > 0 { 283 lastHeight := res.BlockMetas[len(res.BlockMetas)-1].Header.Height 284 if _, err := c.updateLightClientIfNeededTo(ctx, &lastHeight); err != nil { 285 return nil, err 286 } 287 } 288 289 // Verify each of the BlockMetas. 290 for _, meta := range res.BlockMetas { 291 h, err := c.lc.TrustedLightBlock(meta.Header.Height) 292 if err != nil { 293 return nil, fmt.Errorf("trusted header %d: %w", meta.Header.Height, err) 294 } 295 if bmH, tH := meta.Header.Hash(), h.Hash(); !bytes.Equal(bmH, tH) { 296 return nil, fmt.Errorf("block meta header %X does not match with trusted header %X", 297 bmH, tH) 298 } 299 } 300 301 return res, nil 302 } 303 304 func (c *Client) Genesis(ctx context.Context) (*ctypes.ResultGenesis, error) { 305 return c.next.Genesis(ctx) 306 } 307 308 func (c *Client) GenesisChunked(ctx context.Context, id uint) (*ctypes.ResultGenesisChunk, error) { 309 return c.next.GenesisChunked(ctx, id) 310 } 311 312 // Block calls rpcclient#Block and then verifies the result. 313 func (c *Client) Block(ctx context.Context, height *int64) (*ctypes.ResultBlock, error) { 314 res, err := c.next.Block(ctx, height) 315 if err != nil { 316 return nil, err 317 } 318 319 // Validate res. 320 if err := res.BlockID.ValidateBasic(); err != nil { 321 return nil, err 322 } 323 if err := res.Block.ValidateBasic(); err != nil { 324 return nil, err 325 } 326 if bmH, bH := res.BlockID.Hash, res.Block.Hash(); !bytes.Equal(bmH, bH) { 327 return nil, fmt.Errorf("blockID %X does not match with block %X", 328 bmH, bH) 329 } 330 331 // Update the light client if we're behind. 332 l, err := c.updateLightClientIfNeededTo(ctx, &res.Block.Height) 333 if err != nil { 334 return nil, err 335 } 336 337 // Verify block. 338 if bH, tH := res.Block.Hash(), l.Hash(); !bytes.Equal(bH, tH) { 339 return nil, fmt.Errorf("block header %X does not match with trusted header %X", 340 bH, tH) 341 } 342 343 return res, nil 344 } 345 346 // BlockByHash calls rpcclient#BlockByHash and then verifies the result. 347 func (c *Client) BlockByHash(ctx context.Context, hash []byte) (*ctypes.ResultBlock, error) { 348 res, err := c.next.BlockByHash(ctx, hash) 349 if err != nil { 350 return nil, err 351 } 352 353 // Validate res. 354 if err := res.BlockID.ValidateBasic(); err != nil { 355 return nil, err 356 } 357 if err := res.Block.ValidateBasic(); err != nil { 358 return nil, err 359 } 360 if bmH, bH := res.BlockID.Hash, res.Block.Hash(); !bytes.Equal(bmH, bH) { 361 return nil, fmt.Errorf("blockID %X does not match with block %X", 362 bmH, bH) 363 } 364 365 // Update the light client if we're behind. 366 l, err := c.updateLightClientIfNeededTo(ctx, &res.Block.Height) 367 if err != nil { 368 return nil, err 369 } 370 371 // Verify block. 372 if bH, tH := res.Block.Hash(), l.Hash(); !bytes.Equal(bH, tH) { 373 return nil, fmt.Errorf("block header %X does not match with trusted header %X", 374 bH, tH) 375 } 376 377 return res, nil 378 } 379 380 // BlockResults returns the block results for the given height. If no height is 381 // provided, the results of the block preceding the latest are returned. 382 func (c *Client) BlockResults(ctx context.Context, height *int64) (*ctypes.ResultBlockResults, error) { 383 var h int64 384 if height == nil { 385 res, err := c.next.Status(ctx) 386 if err != nil { 387 return nil, fmt.Errorf("can't get latest height: %w", err) 388 } 389 // Can't return the latest block results here because we won't be able to 390 // prove them. Return the results for the previous block instead. 391 h = res.SyncInfo.LatestBlockHeight - 1 392 } else { 393 h = *height 394 } 395 396 res, err := c.next.BlockResults(ctx, &h) 397 if err != nil { 398 return nil, err 399 } 400 401 // Validate res. 402 if res.Height <= 0 { 403 return nil, errNegOrZeroHeight 404 } 405 406 // Update the light client if we're behind. 407 nextHeight := h + 1 408 trustedBlock, err := c.updateLightClientIfNeededTo(ctx, &nextHeight) 409 if err != nil { 410 return nil, err 411 } 412 413 // proto-encode BeginBlock events 414 bbeBytes, err := proto.Marshal(&abci.ResponseBeginBlock{ 415 Events: res.BeginBlockEvents, 416 }) 417 if err != nil { 418 return nil, err 419 } 420 421 // Build a Merkle tree of proto-encoded DeliverTx results and get a hash. 422 results := types.NewResults(res.TxsResults) 423 424 // proto-encode EndBlock events. 425 ebeBytes, err := proto.Marshal(&abci.ResponseEndBlock{ 426 Events: res.EndBlockEvents, 427 }) 428 if err != nil { 429 return nil, err 430 } 431 432 // Build a Merkle tree out of the above 3 binary slices. 433 rH := merkle.HashFromByteSlices([][]byte{bbeBytes, results.Hash(), ebeBytes}) 434 435 // Verify block results. 436 if !bytes.Equal(rH, trustedBlock.LastResultsHash) { 437 return nil, fmt.Errorf("last results %X does not match with trusted last results %X", 438 rH, trustedBlock.LastResultsHash) 439 } 440 441 return res, nil 442 } 443 444 func (c *Client) Commit(ctx context.Context, height *int64) (*ctypes.ResultCommit, error) { 445 // Update the light client if we're behind and retrieve the light block at the requested height 446 // or at the latest height if no height is provided. 447 l, err := c.updateLightClientIfNeededTo(ctx, height) 448 if err != nil { 449 return nil, err 450 } 451 452 return &ctypes.ResultCommit{ 453 SignedHeader: *l.SignedHeader, 454 CanonicalCommit: true, 455 }, nil 456 } 457 458 // Tx calls rpcclient#Tx method and then verifies the proof if such was 459 // requested. 460 func (c *Client) Tx(ctx context.Context, hash []byte, prove bool) (*ctypes.ResultTx, error) { 461 res, err := c.next.Tx(ctx, hash, prove) 462 if err != nil || !prove { 463 return res, err 464 } 465 466 // Validate res. 467 if res.Height <= 0 { 468 return nil, errNegOrZeroHeight 469 } 470 471 // Update the light client if we're behind. 472 l, err := c.updateLightClientIfNeededTo(ctx, &res.Height) 473 if err != nil { 474 return nil, err 475 } 476 477 // Validate the proof. 478 return res, res.Proof.Validate(l.DataHash) 479 } 480 481 func (c *Client) TxSearch( 482 ctx context.Context, 483 query string, 484 prove bool, 485 page, perPage *int, 486 orderBy string, 487 ) (*ctypes.ResultTxSearch, error) { 488 return c.next.TxSearch(ctx, query, prove, page, perPage, orderBy) 489 } 490 491 func (c *Client) BlockSearch( 492 ctx context.Context, 493 query string, 494 page, perPage *int, 495 orderBy string, 496 ) (*ctypes.ResultBlockSearch, error) { 497 return c.next.BlockSearch(ctx, query, page, perPage, orderBy) 498 } 499 500 // Validators fetches and verifies validators. 501 func (c *Client) Validators( 502 ctx context.Context, 503 height *int64, 504 pagePtr, perPagePtr *int, 505 ) (*ctypes.ResultValidators, error) { 506 507 // Update the light client if we're behind and retrieve the light block at the 508 // requested height or at the latest height if no height is provided. 509 l, err := c.updateLightClientIfNeededTo(ctx, height) 510 if err != nil { 511 return nil, err 512 } 513 514 totalCount := len(l.ValidatorSet.Validators) 515 perPage := validatePerPage(perPagePtr) 516 page, err := validatePage(pagePtr, perPage, totalCount) 517 if err != nil { 518 return nil, err 519 } 520 521 skipCount := validateSkipCount(page, perPage) 522 v := l.ValidatorSet.Validators[skipCount : skipCount+tmmath.MinInt(perPage, totalCount-skipCount)] 523 524 return &ctypes.ResultValidators{ 525 BlockHeight: l.Height, 526 Validators: v, 527 Count: len(v), 528 Total: totalCount}, nil 529 } 530 531 func (c *Client) BroadcastEvidence(ctx context.Context, ev types.Evidence) (*ctypes.ResultBroadcastEvidence, error) { 532 return c.next.BroadcastEvidence(ctx, ev) 533 } 534 535 func (c *Client) Subscribe(ctx context.Context, subscriber, query string, 536 outCapacity ...int) (out <-chan ctypes.ResultEvent, err error) { 537 return c.next.Subscribe(ctx, subscriber, query, outCapacity...) 538 } 539 540 func (c *Client) Unsubscribe(ctx context.Context, subscriber, query string) error { 541 return c.next.Unsubscribe(ctx, subscriber, query) 542 } 543 544 func (c *Client) UnsubscribeAll(ctx context.Context, subscriber string) error { 545 return c.next.UnsubscribeAll(ctx, subscriber) 546 } 547 548 func (c *Client) updateLightClientIfNeededTo(ctx context.Context, height *int64) (*types.LightBlock, error) { 549 var ( 550 l *types.LightBlock 551 err error 552 ) 553 if height == nil { 554 l, err = c.lc.Update(ctx, time.Now()) 555 } else { 556 l, err = c.lc.VerifyLightBlockAtHeight(ctx, *height, time.Now()) 557 } 558 if err != nil { 559 return nil, fmt.Errorf("failed to update light client to %d: %w", height, err) 560 } 561 return l, nil 562 } 563 564 func (c *Client) RegisterOpDecoder(typ string, dec merkle.OpDecoder) { 565 c.prt.RegisterOpDecoder(typ, dec) 566 } 567 568 // SubscribeWS subscribes for events using the given query and remote address as 569 // a subscriber, but does not verify responses (UNSAFE)! 570 // TODO: verify data 571 func (c *Client) SubscribeWS(ctx *rpctypes.Context, query string) (*ctypes.ResultSubscribe, error) { 572 out, err := c.next.Subscribe(context.Background(), ctx.RemoteAddr(), query) 573 if err != nil { 574 return nil, err 575 } 576 577 go func() { 578 for { 579 select { 580 case resultEvent := <-out: 581 // We should have a switch here that performs a validation 582 // depending on the event's type. 583 ctx.WSConn.TryWriteRPCResponse( 584 rpctypes.NewRPCSuccessResponse( 585 rpctypes.JSONRPCStringID(fmt.Sprintf("%v#event", ctx.JSONReq.ID)), 586 resultEvent, 587 )) 588 case <-c.Quit(): 589 return 590 } 591 } 592 }() 593 594 return &ctypes.ResultSubscribe{}, nil 595 } 596 597 // UnsubscribeWS calls original client's Unsubscribe using remote address as a 598 // subscriber. 599 func (c *Client) UnsubscribeWS(ctx *rpctypes.Context, query string) (*ctypes.ResultUnsubscribe, error) { 600 err := c.next.Unsubscribe(context.Background(), ctx.RemoteAddr(), query) 601 if err != nil { 602 return nil, err 603 } 604 return &ctypes.ResultUnsubscribe{}, nil 605 } 606 607 // UnsubscribeAllWS calls original client's UnsubscribeAll using remote address 608 // as a subscriber. 609 func (c *Client) UnsubscribeAllWS(ctx *rpctypes.Context) (*ctypes.ResultUnsubscribe, error) { 610 err := c.next.UnsubscribeAll(context.Background(), ctx.RemoteAddr()) 611 if err != nil { 612 return nil, err 613 } 614 return &ctypes.ResultUnsubscribe{}, nil 615 } 616 617 // XXX: Copied from rpc/core/env.go 618 const ( 619 // see README 620 defaultPerPage = 30 621 maxPerPage = 100 622 ) 623 624 func validatePage(pagePtr *int, perPage, totalCount int) (int, error) { 625 if perPage < 1 { 626 panic(fmt.Sprintf("zero or negative perPage: %d", perPage)) 627 } 628 629 if pagePtr == nil { // no page parameter 630 return 1, nil 631 } 632 633 pages := ((totalCount - 1) / perPage) + 1 634 if pages == 0 { 635 pages = 1 // one page (even if it's empty) 636 } 637 page := *pagePtr 638 if page <= 0 || page > pages { 639 return 1, fmt.Errorf("page should be within [1, %d] range, given %d", pages, page) 640 } 641 642 return page, nil 643 } 644 645 func validatePerPage(perPagePtr *int) int { 646 if perPagePtr == nil { // no per_page parameter 647 return defaultPerPage 648 } 649 650 perPage := *perPagePtr 651 if perPage < 1 { 652 return defaultPerPage 653 } else if perPage > maxPerPage { 654 return maxPerPage 655 } 656 return perPage 657 } 658 659 func validateSkipCount(page, perPage int) int { 660 skipCount := (page - 1) * perPage 661 if skipCount < 0 { 662 return 0 663 } 664 665 return skipCount 666 }