Skip to content

Commit

Permalink
feat: support gRPC endpoints in core (#1513)
Browse files Browse the repository at this point in the history
This is an implementation of a streaming API for blocks in core. 

Helps close celestiaorg/celestia-app#3421 but
not sure it entirely closes it.

It can easily be used:

```go
package main

import (
	"context"
	"fmt"
	coregrpc "github.com/tendermint/tendermint/rpc/grpc"
)

func main() {
	client := coregrpc.StartBlockAPIGRPCClient("tcp://localhost:9090")

	blockStreamer, err := client.BlockByHeight(context.Background(), &coregrpc.BlockByHeightRequest{Height: 2})
	if err != nil {
		panic(err)
	}
	blockMeta, err := client.BlockMetaByHeight(context.Background(), &coregrpc.BlockMetaByHeightRequest{Height: 2})
	if err != nil {
		panic(err)
	}
	parts := make([]*core.Part, 0)
	for i := 0; i < int(blockMeta.BlockMeta.BlockID.PartSetHeader.Total); i++ {
		resp, err := blockStreamer.Recv()
		if err != nil {
			panic(err)
		}
		parts = append(parts, resp.BlockPart)
		if resp.IsLast && i < int(blockMeta.BlockMeta.BlockID.PartSetHeader.Total)-1 {
			panic("couldn't get all parts")
		} else if resp.IsLast {
			break
		}
	}

	h := types.NewPartSetFromHeader(types.PartSetHeader{
		Total: blockMeta.BlockMeta.BlockID.PartSetHeader.Total,
		Hash:  blockMeta.BlockMeta.BlockID.PartSetHeader.Hash,
	})

	for _, part := range parts {
		ok, err := h.AddPart(&types.Part{
			Index: part.Index,
			Bytes: part.Bytes,
			Proof: merkle.Proof{
				Total:    part.Proof.Total,
				Index:    part.Proof.Index,
				LeafHash: part.Proof.LeafHash,
				Aunts:    part.Proof.Aunts,
			},
		})
		if err != nil {
			panic(err)
		}
		if !ok {
			panic("not okey")
		}
	}
	pbb := new(core.Block)
	bz, err := io.ReadAll(h.GetReader())
	if err != nil {
		panic(err)
	}
	err = proto.Unmarshal(bz, pbb)
	if err != nil {
		panic(err)
	}
	block, err := types.BlockFromProto(pbb)
	if err != nil {
		panic(err)
	}
	fmt.Println(block)

	// get a commit
	commit, err := client.Commit(context.Background(), &coregrpc.CommitRequest{Height: 10})
	if err != nil {
		panic(err)
	}
	fmt.Println(commit)

	// listen for new heights
	streamer, err := client.SubscribeNewHeights(context.Background(), &coregrpc.SubscribeNewHeightsRequest{})
	if err != nil {
		panic(err)
	}
	for {
		resp, err := streamer.Recv()
		if err != nil {
			panic(err)
		}
		fmt.Println(resp)
	}
}
```

Ps: I didn't add the tests because I didn't find a direct way of mocking
the environment without polluting the rest of the repo (exporting some
methods, adding new helpers, etc). And I think since the implementation
is simple, just querying the block/state stores for results, it's fine
to leave it untested.

---------

Co-authored-by: Rootul P <[email protected]>
  • Loading branch information
rach-id and rootulp authored Jan 14, 2025
1 parent 1d9821a commit 18a7372
Show file tree
Hide file tree
Showing 11 changed files with 9,214 additions and 777 deletions.
2 changes: 2 additions & 0 deletions buf.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ lint:
- BASIC
- FILE_LOWER_SNAKE_CASE
- UNARY_RPC
except:
- RPC_NO_SERVER_STREAMING
ignore:
- gogoproto
breaking:
Expand Down
2 changes: 2 additions & 0 deletions proto/buf.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@ lint:
- BASIC
- FILE_LOWER_SNAKE_CASE
- UNARY_RPC
except:
- RPC_NO_SERVER_STREAMING
Loading

0 comments on commit 18a7372

Please sign in to comment.