From 1712bde1bcbe555cd85c2cc8847b40d90723a57d Mon Sep 17 00:00:00 2001 From: Larry Ruane Date: Thu, 22 Oct 2020 14:57:39 -0600 Subject: [PATCH] add gRPC GetAddressUtxos --- docs/rtd/index.html | 140 ++++++++++ frontend/service.go | 94 ++++++- walletrpc/service.pb.go | 567 +++++++++++++++++++++++++++++++++------- walletrpc/service.proto | 19 ++ 4 files changed, 714 insertions(+), 106 deletions(-) diff --git a/docs/rtd/index.html b/docs/rtd/index.html index e3f9761..71b1eda 100644 --- a/docs/rtd/index.html +++ b/docs/rtd/index.html @@ -280,6 +280,18 @@ MExclude +
  • + MGetAddressUtxosArg +
  • + +
  • + MGetAddressUtxosReply +
  • + +
  • + MGetAddressUtxosReplyList +
  • +
  • MLightdInfo
  • @@ -1032,6 +1044,120 @@ into a specified block on the next ApplyStaged().

    +

    GetAddressUtxosArg

    +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    FieldTypeLabelDescription
    addressstring

    startHeightuint64

    maxEntriesuint32

    zero means unlimited

    + + + + + +

    GetAddressUtxosReply

    +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    FieldTypeLabelDescription
    txidbytes

    indexint32

    scriptbytes

    valueZatint64

    heightuint64

    + + + + + +

    GetAddressUtxosReplyList

    +

    + + + + + + + + + + + + + + + + +
    FieldTypeLabelDescription
    addressUtxosGetAddressUtxosReplyrepeated

    + + + + +

    LightdInfo

    LightdInfo returns various information about this lightwalletd instance

    and the state of the blockchain.

    @@ -1435,6 +1561,20 @@ values also (even though they can be obtained using GetBlock). The block can be specified by either height or hash.

    + + GetAddressUtxos + GetAddressUtxosArg + GetAddressUtxosReplyList +

    + + + + GetAddressUtxosStream + GetAddressUtxosArg + GetAddressUtxosReply stream +

    + + GetLightdInfo Empty diff --git a/frontend/service.go b/frontend/service.go index b625d4a..7ac2e83 100644 --- a/frontend/service.go +++ b/frontend/service.go @@ -43,6 +43,15 @@ func NewDarksideStreamer(cache *common.BlockCache) (walletrpc.DarksideStreamerSe return &DarksideStreamer{cache}, nil } +// Test to make sure Address is a single t address +func checkTaddress(taddr string) error { + match, err := regexp.Match("\\At[a-zA-Z0-9]{34}\\z", []byte(taddr)) + if err != nil || !match { + return errors.New("Invalid address") + } + return nil +} + // GetLatestBlock returns the height of the best chain, according to zcashd. func (s *lwdStreamer) GetLatestBlock(ctx context.Context, placeholder *walletrpc.ChainSpec) (*walletrpc.BlockID, error) { latestBlock := s.cache.GetLatestHeight() @@ -58,11 +67,8 @@ func (s *lwdStreamer) GetLatestBlock(ctx context.Context, placeholder *walletrpc // GetTaddressTxids is a streaming RPC that returns transaction IDs that have // the given transparent address (taddr) as either an input or output. func (s *lwdStreamer) GetTaddressTxids(addressBlockFilter *walletrpc.TransparentAddressBlockFilter, resp walletrpc.CompactTxStreamer_GetTaddressTxidsServer) error { - // Test to make sure Address is a single t address - match, err := regexp.Match("\\At[a-zA-Z0-9]{34}\\z", []byte(addressBlockFilter.Address)) - if err != nil || !match { - common.Log.Error("Invalid address:", addressBlockFilter.Address) - return errors.New("Invalid address") + if err := checkTaddress(addressBlockFilter.Address); err != nil { + return err } if addressBlockFilter.Range == nil { @@ -95,7 +101,7 @@ func (s *lwdStreamer) GetTaddressTxids(addressBlockFilter *walletrpc.Transparent } var txids []string - err = json.Unmarshal(result, &txids) + err := json.Unmarshal(result, &txids) if err != nil { common.Log.Errorf("GetTaddressTxids error: %s", err.Error()) return err @@ -408,7 +414,6 @@ func (s *lwdStreamer) GetMempoolTx(exclude *walletrpc.Exclude, resp walletrpc.Co if time.Now().Sub(lastMempool).Seconds() >= 2 { lastMempool = time.Now() // Refresh our copy of the mempool. - newmempoolMap := make(map[string]*walletrpc.CompactTx) params := make([]json.RawMessage, 0) result, rpcErr := common.RawRequest("getrawmempool", params) if rpcErr != nil { @@ -418,6 +423,7 @@ func (s *lwdStreamer) GetMempoolTx(exclude *walletrpc.Exclude, resp walletrpc.Co if err != nil { return err } + newmempoolMap := make(map[string]*walletrpc.CompactTx) if mempoolMap == nil { mempoolMap = &newmempoolMap } @@ -523,6 +529,80 @@ func MempoolFilter(items, exclude []string) []string { return tosend } +func getAddressUtxos(arg *walletrpc.GetAddressUtxosArg, f func(*walletrpc.GetAddressUtxosReply) error) error { + if err := checkTaddress(arg.Address); err != nil { + return err + } + params := make([]json.RawMessage, 1) + params[0], _ = json.Marshal(arg.Address) + result, rpcErr := common.RawRequest("getaddressutxos", params) + if rpcErr != nil { + return rpcErr + } + var utxosReply []struct { + Txid string + OutputIndex int64 + Script string + Satoshis uint64 + Height int + } + err := json.Unmarshal(result, &utxosReply) + if err != nil { + return err + } + n := 0 + for _, utxo := range utxosReply { + if uint64(utxo.Height) < arg.StartHeight { + continue + } + n++ + if arg.MaxEntries > 0 && uint32(n) > arg.MaxEntries { + break + } + txidBytes, err := hex.DecodeString(utxo.Txid) + if err != nil { + return err + } + scriptBytes, err := hex.DecodeString(utxo.Script) + if err != nil { + return err + } + err = f(&walletrpc.GetAddressUtxosReply{ + Txid: parser.Reverse(txidBytes), + Index: int32(utxo.OutputIndex), + Script: scriptBytes, + ValueZat: int64(utxo.Satoshis), + Height: uint64(utxo.Height), + }) + if err != nil { + return err + } + } + return nil +} + +func (s *lwdStreamer) GetAddressUtxos(ctx context.Context, arg *walletrpc.GetAddressUtxosArg) (*walletrpc.GetAddressUtxosReplyList, error) { + addressUtxos := make([]*walletrpc.GetAddressUtxosReply, 0) + err := getAddressUtxos(arg, func(utxo *walletrpc.GetAddressUtxosReply) error { + addressUtxos = append(addressUtxos, utxo) + return nil + }) + if err != nil { + return &walletrpc.GetAddressUtxosReplyList{}, err + } + return &walletrpc.GetAddressUtxosReplyList{AddressUtxos: addressUtxos}, nil +} + +func (s *lwdStreamer) GetAddressUtxosStream(arg *walletrpc.GetAddressUtxosArg, resp walletrpc.CompactTxStreamer_GetAddressUtxosStreamServer) error { + err := getAddressUtxos(arg, func(utxo *walletrpc.GetAddressUtxosReply) error { + return resp.Send(utxo) + }) + if err != nil { + return err + } + return nil +} + // This rpc is used only for testing. var concurrent int64 diff --git a/walletrpc/service.pb.go b/walletrpc/service.pb.go index 66a7ddf..a8a1e7c 100644 --- a/walletrpc/service.pb.go +++ b/walletrpc/service.pb.go @@ -968,6 +968,195 @@ func (x *TreeState) GetTree() string { return "" } +type GetAddressUtxosArg struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + StartHeight uint64 `protobuf:"varint,2,opt,name=startHeight,proto3" json:"startHeight,omitempty"` + MaxEntries uint32 `protobuf:"varint,3,opt,name=maxEntries,proto3" json:"maxEntries,omitempty"` // zero means unlimited +} + +func (x *GetAddressUtxosArg) Reset() { + *x = GetAddressUtxosArg{} + if protoimpl.UnsafeEnabled { + mi := &file_service_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetAddressUtxosArg) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetAddressUtxosArg) ProtoMessage() {} + +func (x *GetAddressUtxosArg) ProtoReflect() protoreflect.Message { + mi := &file_service_proto_msgTypes[16] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetAddressUtxosArg.ProtoReflect.Descriptor instead. +func (*GetAddressUtxosArg) Descriptor() ([]byte, []int) { + return file_service_proto_rawDescGZIP(), []int{16} +} + +func (x *GetAddressUtxosArg) GetAddress() string { + if x != nil { + return x.Address + } + return "" +} + +func (x *GetAddressUtxosArg) GetStartHeight() uint64 { + if x != nil { + return x.StartHeight + } + return 0 +} + +func (x *GetAddressUtxosArg) GetMaxEntries() uint32 { + if x != nil { + return x.MaxEntries + } + return 0 +} + +type GetAddressUtxosReply struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Txid []byte `protobuf:"bytes,1,opt,name=txid,proto3" json:"txid,omitempty"` + Index int32 `protobuf:"varint,2,opt,name=index,proto3" json:"index,omitempty"` + Script []byte `protobuf:"bytes,3,opt,name=script,proto3" json:"script,omitempty"` + ValueZat int64 `protobuf:"varint,4,opt,name=valueZat,proto3" json:"valueZat,omitempty"` + Height uint64 `protobuf:"varint,5,opt,name=height,proto3" json:"height,omitempty"` +} + +func (x *GetAddressUtxosReply) Reset() { + *x = GetAddressUtxosReply{} + if protoimpl.UnsafeEnabled { + mi := &file_service_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetAddressUtxosReply) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetAddressUtxosReply) ProtoMessage() {} + +func (x *GetAddressUtxosReply) ProtoReflect() protoreflect.Message { + mi := &file_service_proto_msgTypes[17] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetAddressUtxosReply.ProtoReflect.Descriptor instead. +func (*GetAddressUtxosReply) Descriptor() ([]byte, []int) { + return file_service_proto_rawDescGZIP(), []int{17} +} + +func (x *GetAddressUtxosReply) GetTxid() []byte { + if x != nil { + return x.Txid + } + return nil +} + +func (x *GetAddressUtxosReply) GetIndex() int32 { + if x != nil { + return x.Index + } + return 0 +} + +func (x *GetAddressUtxosReply) GetScript() []byte { + if x != nil { + return x.Script + } + return nil +} + +func (x *GetAddressUtxosReply) GetValueZat() int64 { + if x != nil { + return x.ValueZat + } + return 0 +} + +func (x *GetAddressUtxosReply) GetHeight() uint64 { + if x != nil { + return x.Height + } + return 0 +} + +type GetAddressUtxosReplyList struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AddressUtxos []*GetAddressUtxosReply `protobuf:"bytes,1,rep,name=addressUtxos,proto3" json:"addressUtxos,omitempty"` +} + +func (x *GetAddressUtxosReplyList) Reset() { + *x = GetAddressUtxosReplyList{} + if protoimpl.UnsafeEnabled { + mi := &file_service_proto_msgTypes[18] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetAddressUtxosReplyList) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetAddressUtxosReplyList) ProtoMessage() {} + +func (x *GetAddressUtxosReplyList) ProtoReflect() protoreflect.Message { + mi := &file_service_proto_msgTypes[18] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetAddressUtxosReplyList.ProtoReflect.Descriptor instead. +func (*GetAddressUtxosReplyList) Descriptor() ([]byte, []int) { + return file_service_proto_rawDescGZIP(), []int{18} +} + +func (x *GetAddressUtxosReplyList) GetAddressUtxos() []*GetAddressUtxosReply { + if x != nil { + return x.AddressUtxos + } + return nil +} + var File_service_proto protoreflect.FileDescriptor var file_service_proto_rawDesc = []byte{ @@ -1057,78 +1246,115 @@ var file_service_proto_rawDesc = []byte{ 0x68, 0x61, 0x73, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x72, 0x65, 0x65, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x74, 0x72, 0x65, 0x65, 0x32, 0xd5, 0x08, 0x0a, 0x11, 0x43, 0x6f, 0x6d, - 0x70, 0x61, 0x63, 0x74, 0x54, 0x78, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x65, 0x72, 0x12, 0x54, - 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x4c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, - 0x12, 0x20, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, - 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x53, 0x70, - 0x65, 0x63, 0x1a, 0x1e, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, - 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, - 0x49, 0x44, 0x22, 0x00, 0x12, 0x51, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, - 0x12, 0x1e, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, - 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x49, 0x44, - 0x1a, 0x23, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, - 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, - 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x22, 0x00, 0x12, 0x5b, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x42, 0x6c, - 0x6f, 0x63, 0x6b, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x21, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, - 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, - 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x1a, 0x23, 0x2e, 0x63, 0x61, + 0x28, 0x09, 0x52, 0x04, 0x74, 0x72, 0x65, 0x65, 0x22, 0x70, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x41, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x41, 0x72, 0x67, 0x12, 0x18, + 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x73, 0x74, 0x61, 0x72, + 0x74, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x73, + 0x74, 0x61, 0x72, 0x74, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x6d, 0x61, + 0x78, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, + 0x6d, 0x61, 0x78, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x22, 0x8c, 0x01, 0x0a, 0x14, 0x47, + 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x52, 0x65, + 0x70, 0x6c, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x78, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x04, 0x74, 0x78, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x16, 0x0a, + 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5a, 0x61, + 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5a, 0x61, + 0x74, 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x04, 0x52, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x6b, 0x0a, 0x18, 0x47, 0x65, 0x74, + 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x52, 0x65, 0x70, 0x6c, + 0x79, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x4f, 0x0a, 0x0c, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, + 0x55, 0x74, 0x78, 0x6f, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, - 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, - 0x22, 0x00, 0x30, 0x01, 0x12, 0x5a, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, - 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, - 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x54, - 0x78, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x1a, 0x25, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, - 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, - 0x52, 0x61, 0x77, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x00, - 0x12, 0x5f, 0x0a, 0x0f, 0x53, 0x65, 0x6e, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, - 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x61, 0x77, 0x54, - 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x23, 0x2e, 0x63, 0x61, 0x73, - 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, - 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x00, 0x12, 0x73, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x54, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x54, 0x78, 0x69, 0x64, 0x73, 0x12, 0x34, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, - 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x72, - 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x1a, 0x25, 0x2e, 0x63, 0x61, - 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, - 0x72, 0x70, 0x63, 0x2e, 0x52, 0x61, 0x77, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x22, 0x00, 0x30, 0x01, 0x12, 0x5a, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x54, 0x61, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x22, 0x2e, 0x63, - 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, - 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, - 0x1a, 0x1e, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, - 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, - 0x22, 0x00, 0x12, 0x5e, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x54, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x1e, + 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x55, 0x74, + 0x78, 0x6f, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x52, 0x0c, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, + 0x73, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x32, 0xbb, 0x0a, 0x0a, 0x11, 0x43, 0x6f, 0x6d, 0x70, 0x61, + 0x63, 0x74, 0x54, 0x78, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x65, 0x72, 0x12, 0x54, 0x0a, 0x0e, + 0x47, 0x65, 0x74, 0x4c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x20, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, - 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x1a, 0x1e, + 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x53, 0x70, 0x65, 0x63, + 0x1a, 0x1e, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, + 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x49, 0x44, + 0x22, 0x00, 0x12, 0x51, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x1e, + 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, + 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x49, 0x44, 0x1a, 0x23, + 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, + 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x42, 0x6c, + 0x6f, 0x63, 0x6b, 0x22, 0x00, 0x12, 0x5b, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, + 0x6b, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x21, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, + 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x42, + 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x1a, 0x23, 0x2e, 0x63, 0x61, 0x73, 0x68, + 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, + 0x63, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x22, 0x00, + 0x30, 0x01, 0x12, 0x5a, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, + 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x78, 0x46, + 0x69, 0x6c, 0x74, 0x65, 0x72, 0x1a, 0x25, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, + 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x61, + 0x77, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x00, 0x12, 0x5f, + 0x0a, 0x0f, 0x53, 0x65, 0x6e, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x25, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, + 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x61, 0x77, 0x54, 0x72, 0x61, + 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x23, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, + 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, + 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, + 0x73, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x54, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x54, 0x78, + 0x69, 0x64, 0x73, 0x12, 0x34, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, + 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x72, 0x61, 0x6e, + 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x42, 0x6c, + 0x6f, 0x63, 0x6b, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x1a, 0x25, 0x2e, 0x63, 0x61, 0x73, 0x68, + 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, + 0x63, 0x2e, 0x52, 0x61, 0x77, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x22, 0x00, 0x30, 0x01, 0x12, 0x5a, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x54, 0x61, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x22, 0x2e, 0x63, 0x61, 0x73, + 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, + 0x70, 0x63, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x22, 0x00, - 0x28, 0x01, 0x12, 0x54, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x70, 0x6f, 0x6f, 0x6c, - 0x54, 0x78, 0x12, 0x1e, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, - 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x45, 0x78, 0x63, 0x6c, 0x75, - 0x64, 0x65, 0x1a, 0x20, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, - 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x61, - 0x63, 0x74, 0x54, 0x78, 0x22, 0x00, 0x30, 0x01, 0x12, 0x52, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x54, - 0x72, 0x65, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1e, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, - 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, - 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x49, 0x44, 0x1a, 0x20, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, - 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, - 0x2e, 0x54, 0x72, 0x65, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x22, 0x00, 0x12, 0x52, 0x0a, 0x0d, - 0x47, 0x65, 0x74, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1c, 0x2e, + 0x12, 0x5e, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x54, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x42, + 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x1e, 0x2e, 0x63, + 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, + 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x1a, 0x1e, 0x2e, 0x63, + 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, + 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x22, 0x00, 0x28, 0x01, + 0x12, 0x54, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x70, 0x6f, 0x6f, 0x6c, 0x54, 0x78, + 0x12, 0x1e, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, + 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x45, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, + 0x1a, 0x20, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, + 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, + 0x54, 0x78, 0x22, 0x00, 0x30, 0x01, 0x12, 0x52, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x54, 0x72, 0x65, + 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1e, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, + 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x42, + 0x6c, 0x6f, 0x63, 0x6b, 0x49, 0x44, 0x1a, 0x20, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, + 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x54, + 0x72, 0x65, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x22, 0x00, 0x12, 0x6f, 0x0a, 0x0f, 0x47, 0x65, + 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x12, 0x29, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, - 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x21, 0x2e, 0x63, 0x61, - 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, - 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x00, - 0x12, 0x4e, 0x0a, 0x04, 0x50, 0x69, 0x6e, 0x67, 0x12, 0x1f, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, + 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, + 0x55, 0x74, 0x78, 0x6f, 0x73, 0x41, 0x72, 0x67, 0x1a, 0x2f, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, - 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x23, 0x2e, 0x63, 0x61, 0x73, 0x68, - 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, - 0x63, 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, - 0x42, 0x10, 0x5a, 0x0b, 0x2e, 0x3b, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70, 0x63, 0xba, - 0x02, 0x00, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x2e, 0x47, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x55, 0x74, 0x78, 0x6f, 0x73, + 0x52, 0x65, 0x70, 0x6c, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x22, 0x00, 0x12, 0x73, 0x0a, 0x15, 0x47, + 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x53, 0x74, + 0x72, 0x65, 0x61, 0x6d, 0x12, 0x29, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, + 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, + 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x41, 0x72, 0x67, 0x1a, + 0x2b, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, + 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x30, 0x01, + 0x12, 0x52, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x64, 0x49, 0x6e, 0x66, + 0x6f, 0x12, 0x1c, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, + 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, + 0x21, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, + 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x64, 0x49, 0x6e, + 0x66, 0x6f, 0x22, 0x00, 0x12, 0x4e, 0x0a, 0x04, 0x50, 0x69, 0x6e, 0x67, 0x12, 0x1f, 0x2e, 0x63, + 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, + 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x23, 0x2e, + 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, + 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x00, 0x42, 0x10, 0x5a, 0x0b, 0x2e, 0x3b, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, + 0x72, 0x70, 0x63, 0xba, 0x02, 0x00, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1143,7 +1369,7 @@ func file_service_proto_rawDescGZIP() []byte { return file_service_proto_rawDescData } -var file_service_proto_msgTypes = make([]protoimpl.MessageInfo, 16) +var file_service_proto_msgTypes = make([]protoimpl.MessageInfo, 19) var file_service_proto_goTypes = []interface{}{ (*BlockID)(nil), // 0: cash.z.wallet.sdk.rpc.BlockID (*BlockRange)(nil), // 1: cash.z.wallet.sdk.rpc.BlockRange @@ -1161,43 +1387,51 @@ var file_service_proto_goTypes = []interface{}{ (*Balance)(nil), // 13: cash.z.wallet.sdk.rpc.Balance (*Exclude)(nil), // 14: cash.z.wallet.sdk.rpc.Exclude (*TreeState)(nil), // 15: cash.z.wallet.sdk.rpc.TreeState - (*CompactBlock)(nil), // 16: cash.z.wallet.sdk.rpc.CompactBlock - (*CompactTx)(nil), // 17: cash.z.wallet.sdk.rpc.CompactTx + (*GetAddressUtxosArg)(nil), // 16: cash.z.wallet.sdk.rpc.GetAddressUtxosArg + (*GetAddressUtxosReply)(nil), // 17: cash.z.wallet.sdk.rpc.GetAddressUtxosReply + (*GetAddressUtxosReplyList)(nil), // 18: cash.z.wallet.sdk.rpc.GetAddressUtxosReplyList + (*CompactBlock)(nil), // 19: cash.z.wallet.sdk.rpc.CompactBlock + (*CompactTx)(nil), // 20: cash.z.wallet.sdk.rpc.CompactTx } var file_service_proto_depIdxs = []int32{ 0, // 0: cash.z.wallet.sdk.rpc.BlockRange.start:type_name -> cash.z.wallet.sdk.rpc.BlockID 0, // 1: cash.z.wallet.sdk.rpc.BlockRange.end:type_name -> cash.z.wallet.sdk.rpc.BlockID 0, // 2: cash.z.wallet.sdk.rpc.TxFilter.block:type_name -> cash.z.wallet.sdk.rpc.BlockID 1, // 3: cash.z.wallet.sdk.rpc.TransparentAddressBlockFilter.range:type_name -> cash.z.wallet.sdk.rpc.BlockRange - 5, // 4: cash.z.wallet.sdk.rpc.CompactTxStreamer.GetLatestBlock:input_type -> cash.z.wallet.sdk.rpc.ChainSpec - 0, // 5: cash.z.wallet.sdk.rpc.CompactTxStreamer.GetBlock:input_type -> cash.z.wallet.sdk.rpc.BlockID - 1, // 6: cash.z.wallet.sdk.rpc.CompactTxStreamer.GetBlockRange:input_type -> cash.z.wallet.sdk.rpc.BlockRange - 2, // 7: cash.z.wallet.sdk.rpc.CompactTxStreamer.GetTransaction:input_type -> cash.z.wallet.sdk.rpc.TxFilter - 3, // 8: cash.z.wallet.sdk.rpc.CompactTxStreamer.SendTransaction:input_type -> cash.z.wallet.sdk.rpc.RawTransaction - 8, // 9: cash.z.wallet.sdk.rpc.CompactTxStreamer.GetTaddressTxids:input_type -> cash.z.wallet.sdk.rpc.TransparentAddressBlockFilter - 12, // 10: cash.z.wallet.sdk.rpc.CompactTxStreamer.GetTaddressBalance:input_type -> cash.z.wallet.sdk.rpc.AddressList - 11, // 11: cash.z.wallet.sdk.rpc.CompactTxStreamer.GetTaddressBalanceStream:input_type -> cash.z.wallet.sdk.rpc.Address - 14, // 12: cash.z.wallet.sdk.rpc.CompactTxStreamer.GetMempoolTx:input_type -> cash.z.wallet.sdk.rpc.Exclude - 0, // 13: cash.z.wallet.sdk.rpc.CompactTxStreamer.GetTreeState:input_type -> cash.z.wallet.sdk.rpc.BlockID - 6, // 14: cash.z.wallet.sdk.rpc.CompactTxStreamer.GetLightdInfo:input_type -> cash.z.wallet.sdk.rpc.Empty - 9, // 15: cash.z.wallet.sdk.rpc.CompactTxStreamer.Ping:input_type -> cash.z.wallet.sdk.rpc.Duration - 0, // 16: cash.z.wallet.sdk.rpc.CompactTxStreamer.GetLatestBlock:output_type -> cash.z.wallet.sdk.rpc.BlockID - 16, // 17: cash.z.wallet.sdk.rpc.CompactTxStreamer.GetBlock:output_type -> cash.z.wallet.sdk.rpc.CompactBlock - 16, // 18: cash.z.wallet.sdk.rpc.CompactTxStreamer.GetBlockRange:output_type -> cash.z.wallet.sdk.rpc.CompactBlock - 3, // 19: cash.z.wallet.sdk.rpc.CompactTxStreamer.GetTransaction:output_type -> cash.z.wallet.sdk.rpc.RawTransaction - 4, // 20: cash.z.wallet.sdk.rpc.CompactTxStreamer.SendTransaction:output_type -> cash.z.wallet.sdk.rpc.SendResponse - 3, // 21: cash.z.wallet.sdk.rpc.CompactTxStreamer.GetTaddressTxids:output_type -> cash.z.wallet.sdk.rpc.RawTransaction - 13, // 22: cash.z.wallet.sdk.rpc.CompactTxStreamer.GetTaddressBalance:output_type -> cash.z.wallet.sdk.rpc.Balance - 13, // 23: cash.z.wallet.sdk.rpc.CompactTxStreamer.GetTaddressBalanceStream:output_type -> cash.z.wallet.sdk.rpc.Balance - 17, // 24: cash.z.wallet.sdk.rpc.CompactTxStreamer.GetMempoolTx:output_type -> cash.z.wallet.sdk.rpc.CompactTx - 15, // 25: cash.z.wallet.sdk.rpc.CompactTxStreamer.GetTreeState:output_type -> cash.z.wallet.sdk.rpc.TreeState - 7, // 26: cash.z.wallet.sdk.rpc.CompactTxStreamer.GetLightdInfo:output_type -> cash.z.wallet.sdk.rpc.LightdInfo - 10, // 27: cash.z.wallet.sdk.rpc.CompactTxStreamer.Ping:output_type -> cash.z.wallet.sdk.rpc.PingResponse - 16, // [16:28] is the sub-list for method output_type - 4, // [4:16] is the sub-list for method input_type - 4, // [4:4] is the sub-list for extension type_name - 4, // [4:4] is the sub-list for extension extendee - 0, // [0:4] is the sub-list for field type_name + 17, // 4: cash.z.wallet.sdk.rpc.GetAddressUtxosReplyList.addressUtxos:type_name -> cash.z.wallet.sdk.rpc.GetAddressUtxosReply + 5, // 5: cash.z.wallet.sdk.rpc.CompactTxStreamer.GetLatestBlock:input_type -> cash.z.wallet.sdk.rpc.ChainSpec + 0, // 6: cash.z.wallet.sdk.rpc.CompactTxStreamer.GetBlock:input_type -> cash.z.wallet.sdk.rpc.BlockID + 1, // 7: cash.z.wallet.sdk.rpc.CompactTxStreamer.GetBlockRange:input_type -> cash.z.wallet.sdk.rpc.BlockRange + 2, // 8: cash.z.wallet.sdk.rpc.CompactTxStreamer.GetTransaction:input_type -> cash.z.wallet.sdk.rpc.TxFilter + 3, // 9: cash.z.wallet.sdk.rpc.CompactTxStreamer.SendTransaction:input_type -> cash.z.wallet.sdk.rpc.RawTransaction + 8, // 10: cash.z.wallet.sdk.rpc.CompactTxStreamer.GetTaddressTxids:input_type -> cash.z.wallet.sdk.rpc.TransparentAddressBlockFilter + 12, // 11: cash.z.wallet.sdk.rpc.CompactTxStreamer.GetTaddressBalance:input_type -> cash.z.wallet.sdk.rpc.AddressList + 11, // 12: cash.z.wallet.sdk.rpc.CompactTxStreamer.GetTaddressBalanceStream:input_type -> cash.z.wallet.sdk.rpc.Address + 14, // 13: cash.z.wallet.sdk.rpc.CompactTxStreamer.GetMempoolTx:input_type -> cash.z.wallet.sdk.rpc.Exclude + 0, // 14: cash.z.wallet.sdk.rpc.CompactTxStreamer.GetTreeState:input_type -> cash.z.wallet.sdk.rpc.BlockID + 16, // 15: cash.z.wallet.sdk.rpc.CompactTxStreamer.GetAddressUtxos:input_type -> cash.z.wallet.sdk.rpc.GetAddressUtxosArg + 16, // 16: cash.z.wallet.sdk.rpc.CompactTxStreamer.GetAddressUtxosStream:input_type -> cash.z.wallet.sdk.rpc.GetAddressUtxosArg + 6, // 17: cash.z.wallet.sdk.rpc.CompactTxStreamer.GetLightdInfo:input_type -> cash.z.wallet.sdk.rpc.Empty + 9, // 18: cash.z.wallet.sdk.rpc.CompactTxStreamer.Ping:input_type -> cash.z.wallet.sdk.rpc.Duration + 0, // 19: cash.z.wallet.sdk.rpc.CompactTxStreamer.GetLatestBlock:output_type -> cash.z.wallet.sdk.rpc.BlockID + 19, // 20: cash.z.wallet.sdk.rpc.CompactTxStreamer.GetBlock:output_type -> cash.z.wallet.sdk.rpc.CompactBlock + 19, // 21: cash.z.wallet.sdk.rpc.CompactTxStreamer.GetBlockRange:output_type -> cash.z.wallet.sdk.rpc.CompactBlock + 3, // 22: cash.z.wallet.sdk.rpc.CompactTxStreamer.GetTransaction:output_type -> cash.z.wallet.sdk.rpc.RawTransaction + 4, // 23: cash.z.wallet.sdk.rpc.CompactTxStreamer.SendTransaction:output_type -> cash.z.wallet.sdk.rpc.SendResponse + 3, // 24: cash.z.wallet.sdk.rpc.CompactTxStreamer.GetTaddressTxids:output_type -> cash.z.wallet.sdk.rpc.RawTransaction + 13, // 25: cash.z.wallet.sdk.rpc.CompactTxStreamer.GetTaddressBalance:output_type -> cash.z.wallet.sdk.rpc.Balance + 13, // 26: cash.z.wallet.sdk.rpc.CompactTxStreamer.GetTaddressBalanceStream:output_type -> cash.z.wallet.sdk.rpc.Balance + 20, // 27: cash.z.wallet.sdk.rpc.CompactTxStreamer.GetMempoolTx:output_type -> cash.z.wallet.sdk.rpc.CompactTx + 15, // 28: cash.z.wallet.sdk.rpc.CompactTxStreamer.GetTreeState:output_type -> cash.z.wallet.sdk.rpc.TreeState + 18, // 29: cash.z.wallet.sdk.rpc.CompactTxStreamer.GetAddressUtxos:output_type -> cash.z.wallet.sdk.rpc.GetAddressUtxosReplyList + 17, // 30: cash.z.wallet.sdk.rpc.CompactTxStreamer.GetAddressUtxosStream:output_type -> cash.z.wallet.sdk.rpc.GetAddressUtxosReply + 7, // 31: cash.z.wallet.sdk.rpc.CompactTxStreamer.GetLightdInfo:output_type -> cash.z.wallet.sdk.rpc.LightdInfo + 10, // 32: cash.z.wallet.sdk.rpc.CompactTxStreamer.Ping:output_type -> cash.z.wallet.sdk.rpc.PingResponse + 19, // [19:33] is the sub-list for method output_type + 5, // [5:19] is the sub-list for method input_type + 5, // [5:5] is the sub-list for extension type_name + 5, // [5:5] is the sub-list for extension extendee + 0, // [0:5] is the sub-list for field type_name } func init() { file_service_proto_init() } @@ -1399,6 +1633,42 @@ func file_service_proto_init() { return nil } } + file_service_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetAddressUtxosArg); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_service_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetAddressUtxosReply); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_service_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetAddressUtxosReplyList); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } type x struct{} out := protoimpl.TypeBuilder{ @@ -1406,7 +1676,7 @@ func file_service_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_service_proto_rawDesc, NumEnums: 0, - NumMessages: 16, + NumMessages: 19, NumExtensions: 0, NumServices: 1, }, @@ -1461,6 +1731,8 @@ type CompactTxStreamerClient interface { // values also (even though they can be obtained using GetBlock). // The block can be specified by either height or hash. GetTreeState(ctx context.Context, in *BlockID, opts ...grpc.CallOption) (*TreeState, error) + GetAddressUtxos(ctx context.Context, in *GetAddressUtxosArg, opts ...grpc.CallOption) (*GetAddressUtxosReplyList, error) + GetAddressUtxosStream(ctx context.Context, in *GetAddressUtxosArg, opts ...grpc.CallOption) (CompactTxStreamer_GetAddressUtxosStreamClient, error) // Return information about this lightwalletd instance and the blockchain GetLightdInfo(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*LightdInfo, error) // Testing-only @@ -1659,6 +1931,47 @@ func (c *compactTxStreamerClient) GetTreeState(ctx context.Context, in *BlockID, return out, nil } +func (c *compactTxStreamerClient) GetAddressUtxos(ctx context.Context, in *GetAddressUtxosArg, opts ...grpc.CallOption) (*GetAddressUtxosReplyList, error) { + out := new(GetAddressUtxosReplyList) + err := c.cc.Invoke(ctx, "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetAddressUtxos", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *compactTxStreamerClient) GetAddressUtxosStream(ctx context.Context, in *GetAddressUtxosArg, opts ...grpc.CallOption) (CompactTxStreamer_GetAddressUtxosStreamClient, error) { + stream, err := c.cc.NewStream(ctx, &_CompactTxStreamer_serviceDesc.Streams[4], "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetAddressUtxosStream", opts...) + if err != nil { + return nil, err + } + x := &compactTxStreamerGetAddressUtxosStreamClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type CompactTxStreamer_GetAddressUtxosStreamClient interface { + Recv() (*GetAddressUtxosReply, error) + grpc.ClientStream +} + +type compactTxStreamerGetAddressUtxosStreamClient struct { + grpc.ClientStream +} + +func (x *compactTxStreamerGetAddressUtxosStreamClient) Recv() (*GetAddressUtxosReply, error) { + m := new(GetAddressUtxosReply) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + func (c *compactTxStreamerClient) GetLightdInfo(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*LightdInfo, error) { out := new(LightdInfo) err := c.cc.Invoke(ctx, "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetLightdInfo", in, out, opts...) @@ -1708,6 +2021,8 @@ type CompactTxStreamerServer interface { // values also (even though they can be obtained using GetBlock). // The block can be specified by either height or hash. GetTreeState(context.Context, *BlockID) (*TreeState, error) + GetAddressUtxos(context.Context, *GetAddressUtxosArg) (*GetAddressUtxosReplyList, error) + GetAddressUtxosStream(*GetAddressUtxosArg, CompactTxStreamer_GetAddressUtxosStreamServer) error // Return information about this lightwalletd instance and the blockchain GetLightdInfo(context.Context, *Empty) (*LightdInfo, error) // Testing-only @@ -1748,6 +2063,12 @@ func (*UnimplementedCompactTxStreamerServer) GetMempoolTx(*Exclude, CompactTxStr func (*UnimplementedCompactTxStreamerServer) GetTreeState(context.Context, *BlockID) (*TreeState, error) { return nil, status.Errorf(codes.Unimplemented, "method GetTreeState not implemented") } +func (*UnimplementedCompactTxStreamerServer) GetAddressUtxos(context.Context, *GetAddressUtxosArg) (*GetAddressUtxosReplyList, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetAddressUtxos not implemented") +} +func (*UnimplementedCompactTxStreamerServer) GetAddressUtxosStream(*GetAddressUtxosArg, CompactTxStreamer_GetAddressUtxosStreamServer) error { + return status.Errorf(codes.Unimplemented, "method GetAddressUtxosStream not implemented") +} func (*UnimplementedCompactTxStreamerServer) GetLightdInfo(context.Context, *Empty) (*LightdInfo, error) { return nil, status.Errorf(codes.Unimplemented, "method GetLightdInfo not implemented") } @@ -1956,6 +2277,45 @@ func _CompactTxStreamer_GetTreeState_Handler(srv interface{}, ctx context.Contex return interceptor(ctx, in, info, handler) } +func _CompactTxStreamer_GetAddressUtxos_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetAddressUtxosArg) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(CompactTxStreamerServer).GetAddressUtxos(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetAddressUtxos", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(CompactTxStreamerServer).GetAddressUtxos(ctx, req.(*GetAddressUtxosArg)) + } + return interceptor(ctx, in, info, handler) +} + +func _CompactTxStreamer_GetAddressUtxosStream_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(GetAddressUtxosArg) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(CompactTxStreamerServer).GetAddressUtxosStream(m, &compactTxStreamerGetAddressUtxosStreamServer{stream}) +} + +type CompactTxStreamer_GetAddressUtxosStreamServer interface { + Send(*GetAddressUtxosReply) error + grpc.ServerStream +} + +type compactTxStreamerGetAddressUtxosStreamServer struct { + grpc.ServerStream +} + +func (x *compactTxStreamerGetAddressUtxosStreamServer) Send(m *GetAddressUtxosReply) error { + return x.ServerStream.SendMsg(m) +} + func _CompactTxStreamer_GetLightdInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(Empty) if err := dec(in); err != nil { @@ -2020,6 +2380,10 @@ var _CompactTxStreamer_serviceDesc = grpc.ServiceDesc{ MethodName: "GetTreeState", Handler: _CompactTxStreamer_GetTreeState_Handler, }, + { + MethodName: "GetAddressUtxos", + Handler: _CompactTxStreamer_GetAddressUtxos_Handler, + }, { MethodName: "GetLightdInfo", Handler: _CompactTxStreamer_GetLightdInfo_Handler, @@ -2050,6 +2414,11 @@ var _CompactTxStreamer_serviceDesc = grpc.ServiceDesc{ Handler: _CompactTxStreamer_GetMempoolTx_Handler, ServerStreams: true, }, + { + StreamName: "GetAddressUtxosStream", + Handler: _CompactTxStreamer_GetAddressUtxosStream_Handler, + ServerStreams: true, + }, }, Metadata: "service.proto", } diff --git a/walletrpc/service.proto b/walletrpc/service.proto index 3ad0ba9..101f0c5 100644 --- a/walletrpc/service.proto +++ b/walletrpc/service.proto @@ -113,6 +113,22 @@ message TreeState { string tree = 5; // sapling commitment tree state } +message GetAddressUtxosArg { + string address = 1; + uint64 startHeight = 2; + uint32 maxEntries = 3; // zero means unlimited +} +message GetAddressUtxosReply { + bytes txid = 1; + int32 index = 2; + bytes script = 3; + int64 valueZat = 4; + uint64 height = 5; +} +message GetAddressUtxosReplyList { + repeated GetAddressUtxosReply addressUtxos = 1; +} + service CompactTxStreamer { // Return the height of the tip of the best chain rpc GetLatestBlock(ChainSpec) returns (BlockID) {} @@ -148,6 +164,9 @@ service CompactTxStreamer { // The block can be specified by either height or hash. rpc GetTreeState(BlockID) returns (TreeState) {} + rpc GetAddressUtxos(GetAddressUtxosArg) returns (GetAddressUtxosReplyList) {} + rpc GetAddressUtxosStream(GetAddressUtxosArg) returns (stream GetAddressUtxosReply) {} + // Return information about this lightwalletd instance and the blockchain rpc GetLightdInfo(Empty) returns (LightdInfo) {} // Testing-only