Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 26db8cc

Browse files
committedFeb 4, 2025·
feat: expose the data root inclusion proof over gRPC
1 parent a0f3246 commit 26db8cc

File tree

8 files changed

+1230
-165
lines changed

8 files changed

+1230
-165
lines changed
 

‎proto/tendermint/rpc/grpc/types.pb.go

+564-80
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎proto/tendermint/rpc/grpc/types.proto

+21
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import "tendermint/abci/types.proto";
66
import "tendermint/types/types.proto";
77
import "tendermint/p2p/types.proto";
88
import "tendermint/crypto/keys.proto";
9+
import "tendermint/crypto/proof.proto";
910
import "tendermint/types/validator.proto";
1011
import "google/protobuf/timestamp.proto";
1112
import "gogoproto/gogo.proto";
@@ -51,6 +52,15 @@ message SubscribeNewHeightsRequest {}
5152

5253
message StatusRequest {}
5354

55+
message DataRootInclusionProofRequest {
56+
// Height the height of block we want to prove.
57+
int64 height = 1;
58+
// Start the start of the data commitment range containing the block.
59+
uint64 start = 2;
60+
// End the end exclusive of the data commitment range containing the block.
61+
uint64 end = 3;
62+
}
63+
5464
//----------------------------------------
5565
// Response types
5666

@@ -128,6 +138,10 @@ message ValidatorInfo {
128138
int64 voting_power = 3;
129139
}
130140

141+
message DataRootInclusionProofResponse {
142+
tendermint.crypto.Proof proof = 1 [(gogoproto.nullable) = false];
143+
}
144+
131145
//----------------------------------------
132146
// Service Definition
133147

@@ -144,3 +158,10 @@ service BlockAPI {
144158
rpc SubscribeNewHeights(SubscribeNewHeightsRequest) returns (stream NewHeightEvent);
145159
rpc Status(StatusRequest) returns (StatusResponse);
146160
}
161+
162+
service BlobstreamAPI {
163+
// DataRootInclusionProof creates an inclusion proof for the data root of block
164+
// height `height` in the set of blocks defined by `start` and `end`. The range
165+
// is end exclusive.
166+
rpc DataRootInclusionProof(DataRootInclusionProofRequest) returns (DataRootInclusionProofResponse);
167+
}

‎rpc/core/blocks.go

+12-1
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,17 @@ func DataRootInclusionProof(
235235
end uint64,
236236
) (*ctypes.ResultDataRootInclusionProof, error) {
237237
//nolint:gosec
238+
proof, err := GenerateDataRootInclusionProof(height, start, end)
239+
if err != nil {
240+
return nil, err
241+
}
242+
return &ctypes.ResultDataRootInclusionProof{Proof: *proof}, nil
243+
}
244+
245+
func GenerateDataRootInclusionProof(height int64, start, end uint64) (*merkle.Proof, error) {
246+
if globalEnv == nil {
247+
return nil, errors.New("global env is nil. this can only be called inside celestia-core")
248+
}
238249
err := validateDataRootInclusionProofRequest(uint64(height), start, end)
239250
if err != nil {
240251
return nil, err
@@ -247,7 +258,7 @@ func DataRootInclusionProof(
247258
if err != nil {
248259
return nil, err
249260
}
250-
return &ctypes.ResultDataRootInclusionProof{Proof: *proof}, nil
261+
return proof, nil
251262
}
252263

253264
// padBytes Pad bytes to given length

‎rpc/grpc/api.go

+17
Original file line numberDiff line numberDiff line change
@@ -416,3 +416,20 @@ func (blockAPI *BlockAPI) SubscribeNewHeights(_ *SubscribeNewHeightsRequest, str
416416
}
417417
}
418418
}
419+
420+
type BlobstreamAPI struct{}
421+
422+
func NewBlobstreamAPI() *BlobstreamAPI {
423+
return &BlobstreamAPI{}
424+
}
425+
426+
func (blockAPI *BlobstreamAPI) DataRootInclusionProof(_ context.Context, req *DataRootInclusionProofRequest) (*DataRootInclusionProofResponse, error) {
427+
proof, err := core.GenerateDataRootInclusionProof(req.Height, req.Start, req.End)
428+
if err != nil {
429+
return nil, err
430+
}
431+
432+
return &DataRootInclusionProofResponse{
433+
Proof: *proof.ToProto(),
434+
}, nil
435+
}

‎rpc/grpc/client_server.go

+23-4
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,15 @@ type Config struct {
2323
func StartGRPCServer(ln net.Listener) error {
2424
grpcServer := grpc.NewServer()
2525
RegisterBroadcastAPIServer(grpcServer, &broadcastAPI{})
26-
api := NewBlockAPI()
27-
RegisterBlockAPIServer(grpcServer, api)
26+
blockAPI := NewBlockAPI()
27+
RegisterBlockAPIServer(grpcServer, blockAPI)
28+
blobstreamAPI := NewBlobstreamAPI()
29+
RegisterBlobstreamAPIServer(grpcServer, blobstreamAPI)
2830
errCh := make(chan error, 2)
2931
ctx, cancel := context.WithCancel(context.Background())
3032
defer cancel()
3133
go func() {
32-
errCh <- api.StartNewBlockEventListener(ctx)
34+
errCh <- blockAPI.StartNewBlockEventListener(ctx)
3335
}()
3436
go func() {
3537
errCh <- grpcServer.Serve(ln)
@@ -40,7 +42,7 @@ func StartGRPCServer(ln net.Listener) error {
4042
if err != nil {
4143
core.GetEnvironment().Logger.Error("error stopping block api", "err", err)
4244
}
43-
}(api, ctx)
45+
}(blockAPI, ctx)
4446
// blocks until one errors or returns nil
4547
return <-errCh
4648
}
@@ -75,3 +77,20 @@ func StartBlockAPIGRPCClient(protoAddr string, opts ...grpc.DialOption) (BlockAP
7577
func dialerFunc(ctx context.Context, addr string) (net.Conn, error) {
7678
return cmtnet.Connect(addr)
7779
}
80+
81+
// StartBlobstreamAPIGRPCClient dials the gRPC server using protoAddr and returns a new
82+
// BlobstreamAPIClient.
83+
func StartBlobstreamAPIGRPCClient(protoAddr string, opts ...grpc.DialOption) (BlobstreamAPIClient, error) {
84+
if len(opts) == 0 {
85+
opts = append(opts, grpc.WithTransportCredentials(insecure.NewCredentials()))
86+
}
87+
opts = append(opts, grpc.WithContextDialer(dialerFunc))
88+
conn, err := grpc.Dial( //nolint:staticcheck
89+
protoAddr,
90+
opts...,
91+
)
92+
if err != nil {
93+
return nil, err
94+
}
95+
return NewBlobstreamAPIClient(conn), nil
96+
}

‎rpc/grpc/grpc_test.go

+20
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,26 @@ func TestBlockQuery_Streaming(t *testing.T) {
392392
assert.NotEqual(t, part2.BlockPart.Proof, crypto.Proof{})
393393
}
394394

395+
func TestBlobstreamAPI(t *testing.T) {
396+
client, err := rpctest.GetBlobstreamAPIClient()
397+
require.NoError(t, err)
398+
waitForHeight(t, 10)
399+
400+
resp, err := client.DataRootInclusionProof(
401+
context.Background(),
402+
&core_grpc.DataRootInclusionProofRequest{
403+
Height: 6,
404+
Start: 1,
405+
End: 10,
406+
},
407+
)
408+
assert.NoError(t, err)
409+
assert.NotNil(t, resp)
410+
assert.Equal(t, int64(9), resp.Proof.Total)
411+
assert.Equal(t, int64(5), resp.Proof.Index)
412+
assert.Equal(t, 4, len(resp.Proof.Aunts))
413+
}
414+
395415
func waitForHeight(t *testing.T, height int64) {
396416
rpcAddr := rpctest.GetConfig().RPC.ListenAddress
397417
c, err := rpchttp.New(rpcAddr, "/websocket")

‎rpc/grpc/types.pb.go

+564-80
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎rpc/test/helpers.go

+9
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,15 @@ func GetBlockAPIClient() (core_grpc.BlockAPIClient, error) {
126126
return client, nil
127127
}
128128

129+
func GetBlobstreamAPIClient() (core_grpc.BlobstreamAPIClient, error) {
130+
grpcAddr := globalConfig.RPC.GRPCListenAddress
131+
client, err := core_grpc.StartBlobstreamAPIGRPCClient(grpcAddr)
132+
if err != nil {
133+
return nil, err
134+
}
135+
return client, nil
136+
}
137+
129138
// StartTendermint starts a test CometBFT server in a go routine and returns when it is initialized
130139
func StartTendermint(app abci.Application, opts ...func(*Options)) *nm.Node {
131140
nodeOpts := defaultOptions

0 commit comments

Comments
 (0)
Please sign in to comment.