From 78577392c394e56906736bb6251825d4e0771c78 Mon Sep 17 00:00:00 2001 From: Cassandra Heart Date: Mon, 22 Dec 2025 03:53:09 -0600 Subject: [PATCH] add tagged sync --- node/consensus/app/app_consensus_engine.go | 17 +- .../global/global_consensus_engine.go | 14 +- node/consensus/sync/app_sync_hooks.go | 8 +- node/consensus/sync/sync_provider.go | 12 +- node/rpc/hypergraph_sync_rpc_server_test.go | 291 ++++++++++++++- protobufs/application.pb.go | 337 +++++++++--------- protobufs/application.proto | 4 + types/hypergraph/hypergraph.go | 5 +- types/mocks/hypergraph.go | 3 +- 9 files changed, 514 insertions(+), 177 deletions(-) diff --git a/node/consensus/app/app_consensus_engine.go b/node/consensus/app/app_consensus_engine.go index 9e4a7ac..493357b 100644 --- a/node/consensus/app/app_consensus_engine.go +++ b/node/consensus/app/app_consensus_engine.go @@ -55,6 +55,7 @@ import ( "source.quilibrium.com/quilibrium/monorepo/types/execution" "source.quilibrium.com/quilibrium/monorepo/types/execution/intrinsics" "source.quilibrium.com/quilibrium/monorepo/types/execution/state" + hgcrdt "source.quilibrium.com/quilibrium/monorepo/hypergraph" "source.quilibrium.com/quilibrium/monorepo/types/hypergraph" tkeys "source.quilibrium.com/quilibrium/monorepo/types/keys" tp2p "source.quilibrium.com/quilibrium/monorepo/types/p2p" @@ -989,7 +990,7 @@ func (e *AppConsensusEngine) handleGlobalProverRoot( ) e.globalProverRootSynced.Store(false) e.globalProverRootVerifiedFrame.Store(0) - e.triggerGlobalHypersync(frame.Header.Prover) + e.triggerGlobalHypersync(frame.Header.Prover, expectedProverRoot) return } @@ -1006,7 +1007,7 @@ func (e *AppConsensusEngine) handleGlobalProverRoot( ) e.globalProverRootSynced.Store(false) e.globalProverRootVerifiedFrame.Store(0) - e.triggerGlobalHypersync(frame.Header.Prover) + e.triggerGlobalHypersync(frame.Header.Prover, expectedProverRoot) return } @@ -1048,7 +1049,7 @@ func (e *AppConsensusEngine) computeLocalGlobalProverRoot( return nil, errors.New("global prover root shard missing") } -func (e *AppConsensusEngine) triggerGlobalHypersync(proposer []byte) { +func (e *AppConsensusEngine) triggerGlobalHypersync(proposer []byte, expectedRoot []byte) { if e.syncProvider == nil || len(proposer) == 0 { e.logger.Debug("no sync provider or proposer for hypersync") return @@ -1073,7 +1074,7 @@ func (e *AppConsensusEngine) triggerGlobalHypersync(proposer []byte) { L2: intrinsics.GLOBAL_INTRINSIC_ADDRESS, } - e.syncProvider.HyperSync(ctx, proposer, shardKey, nil) + e.syncProvider.HyperSync(ctx, proposer, shardKey, nil, expectedRoot) if err := e.proverRegistry.Refresh(); err != nil { e.logger.Warn( "failed to refresh prover registry after hypersync", @@ -1993,6 +1994,14 @@ func (e *AppConsensusEngine) internalProveFrame( stateRoots[3] = make([]byte, 64) } + // Publish the snapshot generation with the shard's vertex add root so clients + // can sync against this specific state. + if len(stateRoots[0]) > 0 { + if hgCRDT, ok := e.hypergraph.(*hgcrdt.HypergraphCRDT); ok { + hgCRDT.PublishSnapshot(stateRoots[0]) + } + } + txMap := map[string][][]byte{} for i, message := range messages { e.logger.Debug( diff --git a/node/consensus/global/global_consensus_engine.go b/node/consensus/global/global_consensus_engine.go index 11c83b0..93fa8a4 100644 --- a/node/consensus/global/global_consensus_engine.go +++ b/node/consensus/global/global_consensus_engine.go @@ -1748,6 +1748,14 @@ func (e *GlobalConsensusEngine) materialize( } } + // Publish the snapshot generation with the new root so clients can sync + // against this specific state. + if len(localProverRoot) > 0 { + if hgCRDT, ok := e.hypergraph.(*hgcrdt.HypergraphCRDT); ok { + hgCRDT.PublishSnapshot(localProverRoot) + } + } + if len(localProverRoot) > 0 && shouldVerifyRoot { if e.verifyProverRoot( frameNumber, @@ -1913,7 +1921,7 @@ func (e *GlobalConsensusEngine) verifyProverRoot( ) e.proverRootSynced.Store(false) e.proverRootVerifiedFrame.Store(0) - e.triggerProverHypersync(proposer) + e.triggerProverHypersync(proposer, expected) return false } @@ -1929,7 +1937,7 @@ func (e *GlobalConsensusEngine) verifyProverRoot( return true } -func (e *GlobalConsensusEngine) triggerProverHypersync(proposer []byte) { +func (e *GlobalConsensusEngine) triggerProverHypersync(proposer []byte, expectedRoot []byte) { if e.syncProvider == nil || len(proposer) == 0 { e.logger.Debug("no sync provider or proposer") return @@ -1951,7 +1959,7 @@ func (e *GlobalConsensusEngine) triggerProverHypersync(proposer []byte) { L1: [3]byte{0x00, 0x00, 0x00}, L2: intrinsics.GLOBAL_INTRINSIC_ADDRESS, } - e.syncProvider.HyperSync(ctx, proposer, shardKey, nil) + e.syncProvider.HyperSync(ctx, proposer, shardKey, nil, expectedRoot) if err := e.proverRegistry.Refresh(); err != nil { e.logger.Warn( "failed to refresh prover registry after hypersync", diff --git a/node/consensus/sync/app_sync_hooks.go b/node/consensus/sync/app_sync_hooks.go index be4df87..6c650e7 100644 --- a/node/consensus/sync/app_sync_hooks.go +++ b/node/consensus/sync/app_sync_hooks.go @@ -109,7 +109,13 @@ func (h *AppSyncHooks) ensureHyperSync( "detected divergence between local hypergraph and frame roots, initiating hypersync", zap.Uint64("frame_number", frame.Header.FrameNumber), ) - p.HyperSync(ctx, frame.Header.Prover, h.shardKey, frame.Header.Address) + // Pass the frame's vertex adds root as expectedRoot to sync against that + // specific snapshot. + var expectedRoot []byte + if len(frame.Header.StateRoots) > 0 { + expectedRoot = frame.Header.StateRoots[0] + } + p.HyperSync(ctx, frame.Header.Prover, h.shardKey, frame.Header.Address, expectedRoot) } } diff --git a/node/consensus/sync/sync_provider.go b/node/consensus/sync/sync_provider.go index 4b502d8..a12fe26 100644 --- a/node/consensus/sync/sync_provider.go +++ b/node/consensus/sync/sync_provider.go @@ -364,6 +364,7 @@ func (p *SyncProvider[StateT, ProposalT]) HyperSync( prover []byte, shardKey tries.ShardKey, filter []byte, + expectedRoot []byte, ) { registry, err := p.signerRegistry.GetKeyRegistryByProver(prover) if err != nil || registry == nil || registry.IdentityKey == nil { @@ -405,6 +406,7 @@ func (p *SyncProvider[StateT, ProposalT]) HyperSync( phaseSyncs := []func( protobufs.HypergraphComparisonService_HyperStreamClient, tries.ShardKey, + []byte, ){ p.hyperSyncVertexAdds, p.hyperSyncVertexRemoves, @@ -436,7 +438,7 @@ func (p *SyncProvider[StateT, ProposalT]) HyperSync( return } - syncPhase(str, shardKey) + syncPhase(str, shardKey, expectedRoot) if cerr := ch.Close(); cerr != nil { p.logger.Error("error while closing connection", zap.Error(cerr)) } @@ -449,11 +451,13 @@ func (p *SyncProvider[StateT, ProposalT]) HyperSync( func (p *SyncProvider[StateT, ProposalT]) hyperSyncVertexAdds( str protobufs.HypergraphComparisonService_HyperStreamClient, shardKey tries.ShardKey, + expectedRoot []byte, ) { err := p.hypergraph.Sync( str, shardKey, protobufs.HypergraphPhaseSet_HYPERGRAPH_PHASE_SET_VERTEX_ADDS, + expectedRoot, ) if err != nil { p.logger.Error("error from sync", zap.Error(err)) @@ -464,11 +468,13 @@ func (p *SyncProvider[StateT, ProposalT]) hyperSyncVertexAdds( func (p *SyncProvider[StateT, ProposalT]) hyperSyncVertexRemoves( str protobufs.HypergraphComparisonService_HyperStreamClient, shardKey tries.ShardKey, + expectedRoot []byte, ) { err := p.hypergraph.Sync( str, shardKey, protobufs.HypergraphPhaseSet_HYPERGRAPH_PHASE_SET_VERTEX_REMOVES, + expectedRoot, ) if err != nil { p.logger.Error("error from sync", zap.Error(err)) @@ -479,11 +485,13 @@ func (p *SyncProvider[StateT, ProposalT]) hyperSyncVertexRemoves( func (p *SyncProvider[StateT, ProposalT]) hyperSyncHyperedgeAdds( str protobufs.HypergraphComparisonService_HyperStreamClient, shardKey tries.ShardKey, + expectedRoot []byte, ) { err := p.hypergraph.Sync( str, shardKey, protobufs.HypergraphPhaseSet_HYPERGRAPH_PHASE_SET_HYPEREDGE_ADDS, + expectedRoot, ) if err != nil { p.logger.Error("error from sync", zap.Error(err)) @@ -494,11 +502,13 @@ func (p *SyncProvider[StateT, ProposalT]) hyperSyncHyperedgeAdds( func (p *SyncProvider[StateT, ProposalT]) hyperSyncHyperedgeRemoves( str protobufs.HypergraphComparisonService_HyperStreamClient, shardKey tries.ShardKey, + expectedRoot []byte, ) { err := p.hypergraph.Sync( str, shardKey, protobufs.HypergraphPhaseSet_HYPERGRAPH_PHASE_SET_HYPEREDGE_REMOVES, + expectedRoot, ) if err != nil { p.logger.Error("error from sync", zap.Error(err)) diff --git a/node/rpc/hypergraph_sync_rpc_server_test.go b/node/rpc/hypergraph_sync_rpc_server_test.go index bf7a4f0..38ccf86 100644 --- a/node/rpc/hypergraph_sync_rpc_server_test.go +++ b/node/rpc/hypergraph_sync_rpc_server_test.go @@ -311,7 +311,7 @@ func TestHypergraphSyncServer(t *testing.T) { log.Fatalf("Client: failed to stream: %v", err) } - err = crdts[1].Sync(str, shardKey, protobufs.HypergraphPhaseSet_HYPERGRAPH_PHASE_SET_VERTEX_ADDS) + err = crdts[1].Sync(str, shardKey, protobufs.HypergraphPhaseSet_HYPERGRAPH_PHASE_SET_VERTEX_ADDS, nil) if err != nil { log.Fatalf("Client: failed to sync 1: %v", err) } @@ -360,7 +360,7 @@ func TestHypergraphSyncServer(t *testing.T) { log.Fatalf("Client: failed to stream: %v", err) } - err = crdts[1].Sync(str, shardKey, protobufs.HypergraphPhaseSet_HYPERGRAPH_PHASE_SET_VERTEX_ADDS) + err = crdts[1].Sync(str, shardKey, protobufs.HypergraphPhaseSet_HYPERGRAPH_PHASE_SET_VERTEX_ADDS, nil) if err != nil { log.Fatalf("Client: failed to sync 2: %v", err) } @@ -614,7 +614,7 @@ func TestHypergraphPartialSync(t *testing.T) { log.Fatalf("Client: failed to stream: %v", err) } - err = crdts[1].Sync(str, shardKey, protobufs.HypergraphPhaseSet_HYPERGRAPH_PHASE_SET_VERTEX_ADDS) + err = crdts[1].Sync(str, shardKey, protobufs.HypergraphPhaseSet_HYPERGRAPH_PHASE_SET_VERTEX_ADDS, nil) if err != nil { log.Fatalf("Client: failed to sync 1: %v", err) } @@ -634,7 +634,7 @@ func TestHypergraphPartialSync(t *testing.T) { log.Fatalf("Client: failed to stream: %v", err) } - err = crdts[1].Sync(str, shardKey, protobufs.HypergraphPhaseSet_HYPERGRAPH_PHASE_SET_VERTEX_ADDS) + err = crdts[1].Sync(str, shardKey, protobufs.HypergraphPhaseSet_HYPERGRAPH_PHASE_SET_VERTEX_ADDS, nil) if err != nil { log.Fatalf("Client: failed to sync 2: %v", err) } @@ -873,6 +873,7 @@ func TestHypergraphSyncWithConcurrentCommits(t *testing.T) { stream, shardKey, protobufs.HypergraphPhaseSet_HYPERGRAPH_PHASE_SET_VERTEX_ADDS, + nil, ) require.NoError(t, stream.CloseSend()) cancelStream() @@ -940,6 +941,7 @@ func TestHypergraphSyncWithConcurrentCommits(t *testing.T) { stream, shardKey, protobufs.HypergraphPhaseSet_HYPERGRAPH_PHASE_SET_VERTEX_ADDS, + nil, ) require.NoError(t, err) require.NoError(t, stream.CloseSend()) @@ -1098,3 +1100,284 @@ func getNextNibble(key []byte, pos int) int32 { return int32(result & tries.BranchMask) } + +// TestHypergraphSyncWithExpectedRoot tests that clients can request sync +// against a specific snapshot generation by providing an expected root. +// The server should use a matching historical snapshot if available. +func TestHypergraphSyncWithExpectedRoot(t *testing.T) { + logger, _ := zap.NewDevelopment() + enc := verenc.NewMPCitHVerifiableEncryptor(1) + inclusionProver := bls48581.NewKZGInclusionProver(logger) + + // Create data trees for vertices + dataTrees := make([]*tries.VectorCommitmentTree, 100) + for i := 0; i < 100; i++ { + dataTrees[i] = buildDataTree(t, inclusionProver) + } + + serverPath := filepath.Join(t.TempDir(), "server") + + serverDB := store.NewPebbleDB(logger, &config.DBConfig{Path: serverPath}, 0) + defer serverDB.Close() + + serverStore := store.NewPebbleHypergraphStore( + &config.DBConfig{Path: serverPath}, + serverDB, + logger, + enc, + inclusionProver, + ) + + serverHG := hgcrdt.NewHypergraph( + logger.With(zap.String("side", "server")), + serverStore, + inclusionProver, + []int{}, + &tests.Nopthenticator{}, + 200, + ) + + // Create initial vertex to establish shard key + domain := randomBytes32(t) + initialVertex := hgcrdt.NewVertex( + domain, + randomBytes32(t), + dataTrees[0].Commit(inclusionProver, false), + dataTrees[0].GetSize(), + ) + shardKey := application.GetShardKey(initialVertex) + + // Phase 1: Add initial vertices to server and commit + phase1Vertices := make([]application.Vertex, 20) + phase1Vertices[0] = initialVertex + for i := 1; i < 20; i++ { + phase1Vertices[i] = hgcrdt.NewVertex( + domain, + randomBytes32(t), + dataTrees[i].Commit(inclusionProver, false), + dataTrees[i].GetSize(), + ) + } + addVertices(t, serverStore, serverHG, dataTrees[:20], phase1Vertices...) + + // Commit to get root1 + commitResult1, err := serverHG.Commit(1) + require.NoError(t, err) + root1 := commitResult1[shardKey][0] + t.Logf("Root after phase 1: %x", root1) + + // Publish root1 as the current snapshot generation + serverHG.PublishSnapshot(root1) + + // Start gRPC server early so we can create a snapshot while root1 is current + const bufSize = 1 << 20 + lis := bufconn.Listen(bufSize) + + grpcServer := grpc.NewServer( + grpc.ChainStreamInterceptor(func( + srv interface{}, + ss grpc.ServerStream, + info *grpc.StreamServerInfo, + handler grpc.StreamHandler, + ) error { + _, priv, _ := ed448.GenerateKey(rand.Reader) + privKey, err := pcrypto.UnmarshalEd448PrivateKey(priv) + require.NoError(t, err) + + pub := privKey.GetPublic() + peerID, err := peer.IDFromPublicKey(pub) + require.NoError(t, err) + + return handler(srv, &serverStream{ + ServerStream: ss, + ctx: internal_grpc.NewContextWithPeerID(ss.Context(), peerID), + }) + }), + ) + protobufs.RegisterHypergraphComparisonServiceServer(grpcServer, serverHG) + defer grpcServer.Stop() + + go func() { + _ = grpcServer.Serve(lis) + }() + + dialClient := func() (*grpc.ClientConn, protobufs.HypergraphComparisonServiceClient) { + dialer := func(context.Context, string) (net.Conn, error) { + return lis.Dial() + } + conn, err := grpc.DialContext( + context.Background(), + "bufnet", + grpc.WithContextDialer(dialer), + grpc.WithTransportCredentials(insecure.NewCredentials()), + ) + require.NoError(t, err) + return conn, protobufs.NewHypergraphComparisonServiceClient(conn) + } + + // Helper to create a fresh client hypergraph + createClient := func(name string) (*store.PebbleDB, *hgcrdt.HypergraphCRDT) { + clientPath := filepath.Join(t.TempDir(), name) + clientDB := store.NewPebbleDB(logger, &config.DBConfig{Path: clientPath}, 0) + clientStore := store.NewPebbleHypergraphStore( + &config.DBConfig{Path: clientPath}, + clientDB, + logger, + enc, + inclusionProver, + ) + clientHG := hgcrdt.NewHypergraph( + logger.With(zap.String("side", name)), + clientStore, + inclusionProver, + []int{}, + &tests.Nopthenticator{}, + 200, + ) + return clientDB, clientHG + } + + // IMPORTANT: Create a snapshot while root1 is current by doing a sync now. + // This snapshot will be preserved when we later publish root2. + t.Log("Creating snapshot for root1 by syncing a client while root1 is current") + { + clientDB, clientHG := createClient("client-snapshot-root1") + conn, client := dialClient() + + stream, err := client.HyperStream(context.Background()) + require.NoError(t, err) + + err = clientHG.Sync( + stream, + shardKey, + protobufs.HypergraphPhaseSet_HYPERGRAPH_PHASE_SET_VERTEX_ADDS, + nil, + ) + require.NoError(t, err) + require.NoError(t, stream.CloseSend()) + + // Verify this client got root1 + clientCommit, err := clientHG.Commit(1) + require.NoError(t, err) + require.Equal(t, root1, clientCommit[shardKey][0], "snapshot client should have root1") + + conn.Close() + clientDB.Close() + } + + // Phase 2: Add more vertices to server and commit + phase2Vertices := make([]application.Vertex, 30) + for i := 0; i < 30; i++ { + phase2Vertices[i] = hgcrdt.NewVertex( + domain, + randomBytes32(t), + dataTrees[20+i].Commit(inclusionProver, false), + dataTrees[20+i].GetSize(), + ) + } + addVertices(t, serverStore, serverHG, dataTrees[20:50], phase2Vertices...) + + // Commit to get root2 + commitResult2, err := serverHG.Commit(2) + require.NoError(t, err) + root2 := commitResult2[shardKey][0] + t.Logf("Root after phase 2: %x", root2) + + // Publish root2 as the new current snapshot generation + // This preserves the root1 generation (with its snapshot) as a historical generation + serverHG.PublishSnapshot(root2) + + // Verify roots are different + require.NotEqual(t, root1, root2, "roots should be different after adding more data") + + // Test 1: Sync with nil expectedRoot (should get latest = root2) + t.Run("sync with nil expectedRoot gets latest", func(t *testing.T) { + clientDB, clientHG := createClient("client1") + defer clientDB.Close() + + conn, client := dialClient() + defer conn.Close() + + stream, err := client.HyperStream(context.Background()) + require.NoError(t, err) + + err = clientHG.Sync( + stream, + shardKey, + protobufs.HypergraphPhaseSet_HYPERGRAPH_PHASE_SET_VERTEX_ADDS, + nil, // nil expectedRoot should use latest snapshot + ) + require.NoError(t, err) + require.NoError(t, stream.CloseSend()) + + // Commit client to get comparable root + clientCommit, err := clientHG.Commit(1) + require.NoError(t, err) + clientRoot := clientCommit[shardKey][0] + + // Client should have synced to the latest (root2) + assert.Equal(t, root2, clientRoot, "client should sync to latest root when expectedRoot is nil") + }) + + // Test 2: Sync with expectedRoot = root1 (should get historical snapshot) + t.Run("sync with expectedRoot gets matching generation", func(t *testing.T) { + clientDB, clientHG := createClient("client2") + defer clientDB.Close() + + conn, client := dialClient() + defer conn.Close() + + stream, err := client.HyperStream(context.Background()) + require.NoError(t, err) + + err = clientHG.Sync( + stream, + shardKey, + protobufs.HypergraphPhaseSet_HYPERGRAPH_PHASE_SET_VERTEX_ADDS, + root1, // Request sync against root1 + ) + require.NoError(t, err) + require.NoError(t, stream.CloseSend()) + + // Commit client to get comparable root + clientCommit, err := clientHG.Commit(1) + require.NoError(t, err) + clientRoot := clientCommit[shardKey][0] + + // Client should have synced to root1 (the historical snapshot) + assert.Equal(t, root1, clientRoot, "client should sync to historical root when expectedRoot matches") + }) + + // Test 3: Sync with unknown expectedRoot (should fallback to latest) + t.Run("sync with unknown expectedRoot falls back to latest", func(t *testing.T) { + clientDB, clientHG := createClient("client3") + defer clientDB.Close() + + conn, client := dialClient() + defer conn.Close() + + stream, err := client.HyperStream(context.Background()) + require.NoError(t, err) + + // Use a fake root that doesn't exist + unknownRoot := make([]byte, 48) + rand.Read(unknownRoot) + + err = clientHG.Sync( + stream, + shardKey, + protobufs.HypergraphPhaseSet_HYPERGRAPH_PHASE_SET_VERTEX_ADDS, + unknownRoot, // Unknown root should fallback to latest + ) + require.NoError(t, err) + require.NoError(t, stream.CloseSend()) + + // Commit client to get comparable root + clientCommit, err := clientHG.Commit(1) + require.NoError(t, err) + clientRoot := clientCommit[shardKey][0] + + // Client should have synced to latest (root2) since unknown root falls back + assert.Equal(t, root2, clientRoot, "client should sync to latest root when expectedRoot is unknown") + }) +} diff --git a/protobufs/application.pb.go b/protobufs/application.pb.go index 7fb21e0..b09dcee 100644 --- a/protobufs/application.pb.go +++ b/protobufs/application.pb.go @@ -212,6 +212,10 @@ type HypergraphComparisonQuery struct { // If set, the comparison response will contain the data of leaves if present // in the results. IncludeLeafData bool `protobuf:"varint,6,opt,name=include_leaf_data,json=includeLeafData,proto3" json:"include_leaf_data,omitempty"` + // The expected commit root the client wants to sync against. When set, the + // server will attempt to find a snapshot with a matching commit root. If no + // matching snapshot exists, the server may return the latest available. + ExpectedRoot []byte `protobuf:"bytes,7,opt,name=expected_root,json=expectedRoot,proto3" json:"expected_root,omitempty"` } func (x *HypergraphComparisonQuery) Reset() { @@ -288,6 +292,13 @@ func (x *HypergraphComparisonQuery) GetIncludeLeafData() bool { return false } +func (x *HypergraphComparisonQuery) GetExpectedRoot() []byte { + if x != nil { + return x.ExpectedRoot + } + return nil +} + // Defines the response containing the commitment for a node and (optionally) // its immediate children. The children are identified by their index (0–63) and // their commitments. @@ -1287,7 +1298,7 @@ var file_application_proto_rawDesc = []byte{ 0x65, 0x61, 0x76, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x6c, 0x65, 0x61, 0x76, 0x65, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x72, 0x6f, 0x6f, 0x74, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0e, 0x72, 0x6f, - 0x6f, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0xb2, 0x02, 0x0a, + 0x6f, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0xd7, 0x02, 0x0a, 0x19, 0x48, 0x79, 0x70, 0x65, 0x72, 0x67, 0x72, 0x61, 0x70, 0x68, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x69, 0x73, 0x6f, 0x6e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x73, @@ -1307,172 +1318,174 @@ var file_application_proto_rawDesc = []byte{ 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x12, 0x2a, 0x0a, 0x11, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x6c, 0x65, 0x61, 0x66, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x4c, 0x65, 0x61, 0x66, 0x44, 0x61, 0x74, - 0x61, 0x22, 0xb4, 0x01, 0x0a, 0x1c, 0x48, 0x79, 0x70, 0x65, 0x72, 0x67, 0x72, 0x61, 0x70, 0x68, - 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x69, 0x73, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x03, 0x28, 0x05, - 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, - 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, - 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x47, 0x0a, 0x08, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, - 0x65, 0x6e, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, - 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x69, - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x62, 0x2e, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, - 0x43, 0x68, 0x69, 0x6c, 0x64, 0x52, 0x08, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x12, - 0x17, 0x0a, 0x07, 0x69, 0x73, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x06, 0x69, 0x73, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x43, 0x0a, 0x0b, 0x42, 0x72, 0x61, 0x6e, - 0x63, 0x68, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x1e, 0x0a, - 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x90, 0x01, - 0x0a, 0x08, 0x4c, 0x65, 0x61, 0x66, 0x44, 0x61, 0x74, 0x61, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x68, 0x61, 0x73, 0x68, 0x5f, 0x74, 0x61, 0x72, 0x67, 0x65, - 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x68, 0x61, 0x73, 0x68, 0x54, 0x61, 0x72, - 0x67, 0x65, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x75, 0x6e, 0x64, 0x65, 0x72, - 0x6c, 0x79, 0x69, 0x6e, 0x67, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x0e, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x6c, 0x79, 0x69, 0x6e, 0x67, 0x44, 0x61, 0x74, 0x61, - 0x22, 0xea, 0x02, 0x0a, 0x14, 0x48, 0x79, 0x70, 0x65, 0x72, 0x67, 0x72, 0x61, 0x70, 0x68, 0x43, - 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x69, 0x73, 0x6f, 0x6e, 0x12, 0x51, 0x0a, 0x05, 0x71, 0x75, 0x65, - 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, - 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x69, - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x62, 0x2e, 0x48, 0x79, 0x70, 0x65, 0x72, 0x67, - 0x72, 0x61, 0x70, 0x68, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x69, 0x73, 0x6f, 0x6e, 0x51, 0x75, - 0x65, 0x72, 0x79, 0x48, 0x00, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x12, 0x5a, 0x0a, 0x08, - 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3c, - 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, - 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x62, 0x2e, - 0x48, 0x79, 0x70, 0x65, 0x72, 0x67, 0x72, 0x61, 0x70, 0x68, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x72, - 0x69, 0x73, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x00, 0x52, 0x08, - 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x47, 0x0a, 0x09, 0x6c, 0x65, 0x61, 0x66, - 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x71, 0x75, - 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x61, 0x70, - 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x62, 0x2e, 0x4c, 0x65, 0x61, - 0x66, 0x44, 0x61, 0x74, 0x61, 0x48, 0x00, 0x52, 0x08, 0x6c, 0x65, 0x61, 0x66, 0x44, 0x61, 0x74, - 0x61, 0x12, 0x4f, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, - 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x2e, 0x70, 0x62, 0x2e, 0x48, 0x79, 0x70, 0x65, 0x72, 0x73, 0x79, 0x6e, 0x63, 0x4d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, 0x00, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0x42, 0x09, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0x4c, 0x0a, - 0x0a, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x28, 0x0a, 0x0f, 0x6d, - 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6f, 0x6d, 0x6d, 0x69, - 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x22, 0x20, 0x0a, 0x04, 0x50, - 0x61, 0x74, 0x68, 0x12, 0x18, 0x0a, 0x07, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x04, 0x52, 0x07, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x79, 0x0a, - 0x11, 0x54, 0x72, 0x61, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x53, 0x75, 0x62, 0x50, 0x72, 0x6f, - 0x6f, 0x66, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x73, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x0e, 0x0a, 0x02, - 0x79, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x02, 0x79, 0x73, 0x12, 0x3a, 0x0a, 0x05, - 0x70, 0x61, 0x74, 0x68, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x71, 0x75, - 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x61, 0x70, - 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x62, 0x2e, 0x50, 0x61, 0x74, - 0x68, 0x52, 0x05, 0x70, 0x61, 0x74, 0x68, 0x73, 0x22, 0xae, 0x01, 0x0a, 0x0e, 0x54, 0x72, 0x61, - 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x4a, 0x0a, 0x0a, 0x6d, - 0x75, 0x6c, 0x74, 0x69, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x2a, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, - 0x65, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x62, - 0x2e, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x52, 0x0a, 0x6d, 0x75, 0x6c, - 0x74, 0x69, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x50, 0x0a, 0x0a, 0x73, 0x75, 0x62, 0x5f, 0x70, - 0x72, 0x6f, 0x6f, 0x66, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x71, 0x75, - 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x61, 0x70, - 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x62, 0x2e, 0x54, 0x72, 0x61, - 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x53, 0x75, 0x62, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, 0x09, - 0x73, 0x75, 0x62, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x73, 0x22, 0x9d, 0x01, 0x0a, 0x19, 0x47, 0x65, - 0x74, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x46, 0x6f, 0x72, 0x50, 0x61, 0x74, 0x68, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x68, 0x61, 0x72, 0x64, - 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x73, 0x68, 0x61, 0x72, - 0x64, 0x4b, 0x65, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x03, - 0x28, 0x0d, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x4f, 0x0a, 0x09, 0x70, 0x68, 0x61, 0x73, - 0x65, 0x5f, 0x73, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x32, 0x2e, 0x71, 0x75, - 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x61, 0x70, - 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x62, 0x2e, 0x48, 0x79, 0x70, - 0x65, 0x72, 0x67, 0x72, 0x61, 0x70, 0x68, 0x50, 0x68, 0x61, 0x73, 0x65, 0x53, 0x65, 0x74, 0x52, - 0x08, 0x70, 0x68, 0x61, 0x73, 0x65, 0x53, 0x65, 0x74, 0x22, 0x8b, 0x01, 0x0a, 0x0c, 0x54, 0x72, - 0x65, 0x65, 0x50, 0x61, 0x74, 0x68, 0x4c, 0x65, 0x61, 0x66, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x68, 0x61, 0x73, 0x68, 0x5f, 0x74, 0x61, 0x72, 0x67, 0x65, - 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x68, 0x61, 0x73, 0x68, 0x54, 0x61, 0x72, - 0x67, 0x65, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, - 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, - 0x65, 0x6e, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x22, 0xc3, 0x01, 0x0a, 0x0e, 0x54, 0x72, 0x65, 0x65, - 0x50, 0x61, 0x74, 0x68, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x72, - 0x65, 0x66, 0x69, 0x78, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x06, 0x70, 0x72, 0x65, 0x66, - 0x69, 0x78, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, + 0x61, 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x72, 0x6f, + 0x6f, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, + 0x65, 0x64, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0xb4, 0x01, 0x0a, 0x1c, 0x48, 0x79, 0x70, 0x65, 0x72, + 0x67, 0x72, 0x61, 0x70, 0x68, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x69, 0x73, 0x6f, 0x6e, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x05, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x1e, 0x0a, 0x0a, 0x63, + 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x47, 0x0a, 0x08, 0x63, + 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, + 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, + 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x62, 0x2e, 0x42, + 0x72, 0x61, 0x6e, 0x63, 0x68, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x52, 0x08, 0x63, 0x68, 0x69, 0x6c, + 0x64, 0x72, 0x65, 0x6e, 0x12, 0x17, 0x0a, 0x07, 0x69, 0x73, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x69, 0x73, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x43, 0x0a, + 0x0b, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x12, 0x14, 0x0a, 0x05, + 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x69, 0x6e, 0x64, + 0x65, 0x78, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, - 0x6e, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x65, 0x61, 0x66, 0x5f, 0x63, - 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x6c, 0x65, 0x61, 0x66, - 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x25, 0x0a, 0x0e, 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x73, 0x74, - 0x5f, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x6c, - 0x6f, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, 0x1f, 0x0a, 0x0b, - 0x66, 0x75, 0x6c, 0x6c, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x06, 0x20, 0x03, 0x28, - 0x0d, 0x52, 0x0a, 0x66, 0x75, 0x6c, 0x6c, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x22, 0xc0, 0x01, - 0x0a, 0x0f, 0x54, 0x72, 0x65, 0x65, 0x50, 0x61, 0x74, 0x68, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, - 0x74, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, - 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x42, 0x0a, 0x04, 0x6c, 0x65, 0x61, 0x66, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, - 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x62, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x50, 0x61, 0x74, 0x68, 0x4c, - 0x65, 0x61, 0x66, 0x48, 0x00, 0x52, 0x04, 0x6c, 0x65, 0x61, 0x66, 0x12, 0x48, 0x0a, 0x06, 0x62, - 0x72, 0x61, 0x6e, 0x63, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x71, 0x75, + 0x6e, 0x74, 0x22, 0x90, 0x01, 0x0a, 0x08, 0x4c, 0x65, 0x61, 0x66, 0x44, 0x61, 0x74, 0x61, 0x12, + 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6b, 0x65, + 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x68, 0x61, 0x73, 0x68, 0x5f, + 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x68, 0x61, + 0x73, 0x68, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x27, 0x0a, 0x0f, + 0x75, 0x6e, 0x64, 0x65, 0x72, 0x6c, 0x79, 0x69, 0x6e, 0x67, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0e, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x6c, 0x79, 0x69, 0x6e, + 0x67, 0x44, 0x61, 0x74, 0x61, 0x22, 0xea, 0x02, 0x0a, 0x14, 0x48, 0x79, 0x70, 0x65, 0x72, 0x67, + 0x72, 0x61, 0x70, 0x68, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x69, 0x73, 0x6f, 0x6e, 0x12, 0x51, + 0x0a, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, + 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, + 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x62, 0x2e, 0x48, + 0x79, 0x70, 0x65, 0x72, 0x67, 0x72, 0x61, 0x70, 0x68, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x69, + 0x73, 0x6f, 0x6e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x48, 0x00, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, + 0x79, 0x12, 0x5a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, + 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x2e, 0x70, 0x62, 0x2e, 0x48, 0x79, 0x70, 0x65, 0x72, 0x67, 0x72, 0x61, 0x70, 0x68, 0x43, + 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x69, 0x73, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x48, 0x00, 0x52, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x47, 0x0a, + 0x09, 0x6c, 0x65, 0x61, 0x66, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x28, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, + 0x64, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, + 0x62, 0x2e, 0x4c, 0x65, 0x61, 0x66, 0x44, 0x61, 0x74, 0x61, 0x48, 0x00, 0x52, 0x08, 0x6c, 0x65, + 0x61, 0x66, 0x44, 0x61, 0x74, 0x61, 0x12, 0x4f, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, + 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x62, 0x2e, 0x48, 0x79, 0x70, 0x65, 0x72, 0x73, + 0x79, 0x6e, 0x63, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, 0x00, 0x52, 0x08, 0x6d, + 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x42, 0x09, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, + 0x61, 0x64, 0x22, 0x4c, 0x0a, 0x0a, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x72, 0x6f, 0x6f, 0x66, + 0x12, 0x28, 0x0a, 0x0f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, + 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x6d, 0x75, 0x6c, 0x74, 0x69, + 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x72, + 0x6f, 0x6f, 0x66, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x70, 0x72, 0x6f, 0x6f, 0x66, + 0x22, 0x20, 0x0a, 0x04, 0x50, 0x61, 0x74, 0x68, 0x12, 0x18, 0x0a, 0x07, 0x69, 0x6e, 0x64, 0x69, + 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x04, 0x52, 0x07, 0x69, 0x6e, 0x64, 0x69, 0x63, + 0x65, 0x73, 0x22, 0x79, 0x0a, 0x11, 0x54, 0x72, 0x61, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x53, + 0x75, 0x62, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x69, + 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, + 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x79, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x02, 0x79, + 0x73, 0x12, 0x3a, 0x0a, 0x05, 0x70, 0x61, 0x74, 0x68, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x24, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, + 0x64, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, + 0x62, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x52, 0x05, 0x70, 0x61, 0x74, 0x68, 0x73, 0x22, 0xae, 0x01, + 0x0a, 0x0e, 0x54, 0x72, 0x61, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x50, 0x72, 0x6f, 0x6f, 0x66, + 0x12, 0x4a, 0x0a, 0x0a, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, + 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x2e, 0x70, 0x62, 0x2e, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x72, 0x6f, 0x6f, 0x66, + 0x52, 0x0a, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x50, 0x0a, 0x0a, + 0x73, 0x75, 0x62, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x31, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, + 0x64, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, + 0x62, 0x2e, 0x54, 0x72, 0x61, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x53, 0x75, 0x62, 0x50, 0x72, + 0x6f, 0x6f, 0x66, 0x52, 0x09, 0x73, 0x75, 0x62, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x73, 0x22, 0x9d, + 0x01, 0x0a, 0x19, 0x47, 0x65, 0x74, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x46, 0x6f, + 0x72, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, + 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x4b, 0x65, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, + 0x68, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x4f, 0x0a, + 0x09, 0x70, 0x68, 0x61, 0x73, 0x65, 0x5f, 0x73, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, + 0x32, 0x32, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, + 0x64, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, + 0x62, 0x2e, 0x48, 0x79, 0x70, 0x65, 0x72, 0x67, 0x72, 0x61, 0x70, 0x68, 0x50, 0x68, 0x61, 0x73, + 0x65, 0x53, 0x65, 0x74, 0x52, 0x08, 0x70, 0x68, 0x61, 0x73, 0x65, 0x53, 0x65, 0x74, 0x22, 0x8b, + 0x01, 0x0a, 0x0c, 0x54, 0x72, 0x65, 0x65, 0x50, 0x61, 0x74, 0x68, 0x4c, 0x65, 0x61, 0x66, 0x12, + 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6b, 0x65, + 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x68, 0x61, 0x73, 0x68, 0x5f, + 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x68, 0x61, + 0x73, 0x68, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, + 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x63, 0x6f, + 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x22, 0xc3, 0x01, 0x0a, + 0x0e, 0x54, 0x72, 0x65, 0x65, 0x50, 0x61, 0x74, 0x68, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, + 0x16, 0x0a, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0d, 0x52, + 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, + 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x63, 0x6f, 0x6d, + 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, + 0x65, 0x61, 0x66, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x09, 0x6c, 0x65, 0x61, 0x66, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x25, 0x0a, 0x0e, 0x6c, 0x6f, + 0x6e, 0x67, 0x65, 0x73, 0x74, 0x5f, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x0d, 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x42, 0x72, 0x61, 0x6e, 0x63, + 0x68, 0x12, 0x1f, 0x0a, 0x0b, 0x66, 0x75, 0x6c, 0x6c, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, + 0x18, 0x06, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x0a, 0x66, 0x75, 0x6c, 0x6c, 0x50, 0x72, 0x65, 0x66, + 0x69, 0x78, 0x22, 0xc0, 0x01, 0x0a, 0x0f, 0x54, 0x72, 0x65, 0x65, 0x50, 0x61, 0x74, 0x68, 0x53, + 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x42, 0x0a, 0x04, + 0x6c, 0x65, 0x61, 0x66, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x71, 0x75, 0x69, + 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x61, 0x70, 0x70, + 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x62, 0x2e, 0x54, 0x72, 0x65, 0x65, + 0x50, 0x61, 0x74, 0x68, 0x4c, 0x65, 0x61, 0x66, 0x48, 0x00, 0x52, 0x04, 0x6c, 0x65, 0x61, 0x66, + 0x12, 0x48, 0x0a, 0x06, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x2e, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, + 0x64, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, + 0x62, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x50, 0x61, 0x74, 0x68, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, + 0x48, 0x00, 0x52, 0x06, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x42, 0x09, 0x0a, 0x07, 0x73, 0x65, + 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x5f, 0x0a, 0x10, 0x54, 0x72, 0x65, 0x65, 0x50, 0x61, 0x74, + 0x68, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x4b, 0x0a, 0x08, 0x73, 0x65, 0x67, + 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x62, 0x2e, 0x54, 0x72, 0x65, - 0x65, 0x50, 0x61, 0x74, 0x68, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x48, 0x00, 0x52, 0x06, 0x62, - 0x72, 0x61, 0x6e, 0x63, 0x68, 0x42, 0x09, 0x0a, 0x07, 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, - 0x22, 0x5f, 0x0a, 0x10, 0x54, 0x72, 0x65, 0x65, 0x50, 0x61, 0x74, 0x68, 0x53, 0x65, 0x67, 0x6d, - 0x65, 0x6e, 0x74, 0x73, 0x12, 0x4b, 0x0a, 0x08, 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, - 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x62, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x50, 0x61, 0x74, 0x68, - 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x08, 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, - 0x73, 0x22, 0x73, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, - 0x46, 0x6f, 0x72, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x55, 0x0a, 0x0d, 0x70, 0x61, 0x74, 0x68, 0x5f, 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, - 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x62, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x50, 0x61, 0x74, 0x68, - 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x0c, 0x70, 0x61, 0x74, 0x68, 0x53, 0x65, - 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2a, 0xb8, 0x01, 0x0a, 0x12, 0x48, 0x79, 0x70, 0x65, 0x72, - 0x67, 0x72, 0x61, 0x70, 0x68, 0x50, 0x68, 0x61, 0x73, 0x65, 0x53, 0x65, 0x74, 0x12, 0x24, 0x0a, - 0x20, 0x48, 0x59, 0x50, 0x45, 0x52, 0x47, 0x52, 0x41, 0x50, 0x48, 0x5f, 0x50, 0x48, 0x41, 0x53, - 0x45, 0x5f, 0x53, 0x45, 0x54, 0x5f, 0x56, 0x45, 0x52, 0x54, 0x45, 0x58, 0x5f, 0x41, 0x44, 0x44, - 0x53, 0x10, 0x00, 0x12, 0x27, 0x0a, 0x23, 0x48, 0x59, 0x50, 0x45, 0x52, 0x47, 0x52, 0x41, 0x50, - 0x48, 0x5f, 0x50, 0x48, 0x41, 0x53, 0x45, 0x5f, 0x53, 0x45, 0x54, 0x5f, 0x56, 0x45, 0x52, 0x54, - 0x45, 0x58, 0x5f, 0x52, 0x45, 0x4d, 0x4f, 0x56, 0x45, 0x53, 0x10, 0x01, 0x12, 0x27, 0x0a, 0x23, - 0x48, 0x59, 0x50, 0x45, 0x52, 0x47, 0x52, 0x41, 0x50, 0x48, 0x5f, 0x50, 0x48, 0x41, 0x53, 0x45, - 0x5f, 0x53, 0x45, 0x54, 0x5f, 0x48, 0x59, 0x50, 0x45, 0x52, 0x45, 0x44, 0x47, 0x45, 0x5f, 0x41, - 0x44, 0x44, 0x53, 0x10, 0x02, 0x12, 0x2a, 0x0a, 0x26, 0x48, 0x59, 0x50, 0x45, 0x52, 0x47, 0x52, - 0x41, 0x50, 0x48, 0x5f, 0x50, 0x48, 0x41, 0x53, 0x45, 0x5f, 0x53, 0x45, 0x54, 0x5f, 0x48, 0x59, - 0x50, 0x45, 0x52, 0x45, 0x44, 0x47, 0x45, 0x5f, 0x52, 0x45, 0x4d, 0x4f, 0x56, 0x45, 0x53, 0x10, - 0x03, 0x32, 0xaa, 0x02, 0x0a, 0x1b, 0x48, 0x79, 0x70, 0x65, 0x72, 0x67, 0x72, 0x61, 0x70, 0x68, - 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x69, 0x73, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x12, 0x7d, 0x0a, 0x0b, 0x48, 0x79, 0x70, 0x65, 0x72, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, - 0x12, 0x34, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, - 0x64, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, - 0x62, 0x2e, 0x48, 0x79, 0x70, 0x65, 0x72, 0x67, 0x72, 0x61, 0x70, 0x68, 0x43, 0x6f, 0x6d, 0x70, - 0x61, 0x72, 0x69, 0x73, 0x6f, 0x6e, 0x1a, 0x34, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, - 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x62, 0x2e, 0x48, 0x79, 0x70, 0x65, 0x72, 0x67, 0x72, 0x61, - 0x70, 0x68, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x69, 0x73, 0x6f, 0x6e, 0x28, 0x01, 0x30, 0x01, - 0x12, 0x8b, 0x01, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, - 0x46, 0x6f, 0x72, 0x50, 0x61, 0x74, 0x68, 0x12, 0x39, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, + 0x65, 0x50, 0x61, 0x74, 0x68, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x08, 0x73, 0x65, + 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x73, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x43, 0x68, 0x69, + 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x46, 0x6f, 0x72, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x55, 0x0a, 0x0d, 0x70, 0x61, 0x74, 0x68, 0x5f, 0x73, 0x65, 0x67, + 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x71, 0x75, + 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x61, 0x70, + 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x62, 0x2e, 0x54, 0x72, 0x65, + 0x65, 0x50, 0x61, 0x74, 0x68, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x0c, 0x70, + 0x61, 0x74, 0x68, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2a, 0xb8, 0x01, 0x0a, 0x12, + 0x48, 0x79, 0x70, 0x65, 0x72, 0x67, 0x72, 0x61, 0x70, 0x68, 0x50, 0x68, 0x61, 0x73, 0x65, 0x53, + 0x65, 0x74, 0x12, 0x24, 0x0a, 0x20, 0x48, 0x59, 0x50, 0x45, 0x52, 0x47, 0x52, 0x41, 0x50, 0x48, + 0x5f, 0x50, 0x48, 0x41, 0x53, 0x45, 0x5f, 0x53, 0x45, 0x54, 0x5f, 0x56, 0x45, 0x52, 0x54, 0x45, + 0x58, 0x5f, 0x41, 0x44, 0x44, 0x53, 0x10, 0x00, 0x12, 0x27, 0x0a, 0x23, 0x48, 0x59, 0x50, 0x45, + 0x52, 0x47, 0x52, 0x41, 0x50, 0x48, 0x5f, 0x50, 0x48, 0x41, 0x53, 0x45, 0x5f, 0x53, 0x45, 0x54, + 0x5f, 0x56, 0x45, 0x52, 0x54, 0x45, 0x58, 0x5f, 0x52, 0x45, 0x4d, 0x4f, 0x56, 0x45, 0x53, 0x10, + 0x01, 0x12, 0x27, 0x0a, 0x23, 0x48, 0x59, 0x50, 0x45, 0x52, 0x47, 0x52, 0x41, 0x50, 0x48, 0x5f, + 0x50, 0x48, 0x41, 0x53, 0x45, 0x5f, 0x53, 0x45, 0x54, 0x5f, 0x48, 0x59, 0x50, 0x45, 0x52, 0x45, + 0x44, 0x47, 0x45, 0x5f, 0x41, 0x44, 0x44, 0x53, 0x10, 0x02, 0x12, 0x2a, 0x0a, 0x26, 0x48, 0x59, + 0x50, 0x45, 0x52, 0x47, 0x52, 0x41, 0x50, 0x48, 0x5f, 0x50, 0x48, 0x41, 0x53, 0x45, 0x5f, 0x53, + 0x45, 0x54, 0x5f, 0x48, 0x59, 0x50, 0x45, 0x52, 0x45, 0x44, 0x47, 0x45, 0x5f, 0x52, 0x45, 0x4d, + 0x4f, 0x56, 0x45, 0x53, 0x10, 0x03, 0x32, 0xaa, 0x02, 0x0a, 0x1b, 0x48, 0x79, 0x70, 0x65, 0x72, + 0x67, 0x72, 0x61, 0x70, 0x68, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x69, 0x73, 0x6f, 0x6e, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x7d, 0x0a, 0x0b, 0x48, 0x79, 0x70, 0x65, 0x72, 0x53, + 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x34, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, + 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x62, 0x2e, 0x48, 0x79, 0x70, 0x65, 0x72, 0x67, 0x72, 0x61, 0x70, + 0x68, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x69, 0x73, 0x6f, 0x6e, 0x1a, 0x34, 0x2e, 0x71, 0x75, + 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x61, 0x70, + 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x62, 0x2e, 0x48, 0x79, 0x70, + 0x65, 0x72, 0x67, 0x72, 0x61, 0x70, 0x68, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x69, 0x73, 0x6f, + 0x6e, 0x28, 0x01, 0x30, 0x01, 0x12, 0x8b, 0x01, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x43, 0x68, 0x69, + 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x46, 0x6f, 0x72, 0x50, 0x61, 0x74, 0x68, 0x12, 0x39, 0x2e, 0x71, + 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x61, + 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x62, 0x2e, 0x47, 0x65, + 0x74, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x46, 0x6f, 0x72, 0x50, 0x61, 0x74, 0x68, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3a, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x62, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x69, 0x6c, - 0x64, 0x72, 0x65, 0x6e, 0x46, 0x6f, 0x72, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x3a, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, - 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x2e, 0x70, 0x62, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x46, - 0x6f, 0x72, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x3a, - 0x5a, 0x38, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, - 0x69, 0x75, 0x6d, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, - 0x75, 0x6d, 0x2f, 0x6d, 0x6f, 0x6e, 0x6f, 0x72, 0x65, 0x70, 0x6f, 0x2f, 0x6e, 0x6f, 0x64, 0x65, - 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, + 0x64, 0x72, 0x65, 0x6e, 0x46, 0x6f, 0x72, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x42, 0x3a, 0x5a, 0x38, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x71, 0x75, + 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x71, 0x75, 0x69, + 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2f, 0x6d, 0x6f, 0x6e, 0x6f, 0x72, 0x65, 0x70, 0x6f, + 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x73, 0x62, + 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/protobufs/application.proto b/protobufs/application.proto index 1d5f488..558e384 100644 --- a/protobufs/application.proto +++ b/protobufs/application.proto @@ -40,6 +40,10 @@ message HypergraphComparisonQuery { // If set, the comparison response will contain the data of leaves if present // in the results. bool include_leaf_data = 6; + // The expected commit root the client wants to sync against. When set, the + // server will attempt to find a snapshot with a matching commit root. If no + // matching snapshot exists, the server may return the latest available. + bytes expected_root = 7; } // Defines the response containing the commitment for a node and (optionally) diff --git a/types/hypergraph/hypergraph.go b/types/hypergraph/hypergraph.go index c922124..8586de0 100644 --- a/types/hypergraph/hypergraph.go +++ b/types/hypergraph/hypergraph.go @@ -295,11 +295,14 @@ type Hypergraph interface { // Embeds the comparison service protobufs.HypergraphComparisonServiceServer - // Sync is the client-side initiator for synchronization. + // Sync is the client-side initiator for synchronization. If expectedRoot is + // provided, the server will attempt to use a snapshot with a matching commit + // root. This allows the client to sync against a specific known state. Sync( stream protobufs.HypergraphComparisonService_HyperStreamClient, shardKey tries.ShardKey, phaseSet protobufs.HypergraphPhaseSet, + expectedRoot []byte, ) error // Transaction and utility operations diff --git a/types/mocks/hypergraph.go b/types/mocks/hypergraph.go index 541d406..7697cda 100644 --- a/types/mocks/hypergraph.go +++ b/types/mocks/hypergraph.go @@ -212,8 +212,9 @@ func (h *MockHypergraph) Sync( stream protobufs.HypergraphComparisonService_HyperStreamClient, shardKey tries.ShardKey, phaseSet protobufs.HypergraphPhaseSet, + expectedRoot []byte, ) error { - args := h.Called(stream, shardKey, phaseSet) + args := h.Called(stream, shardKey, phaseSet, expectedRoot) return args.Error(0) }