From 717385756433feaf438c77482a99235d64065ded Mon Sep 17 00:00:00 2001 From: wenjian3 Date: Mon, 3 Sep 2018 02:14:21 -0400 Subject: [PATCH] [FAB-11294] Prover Service - List Tokens This change-set does the following: - Update prover.proto to support ListUnspentTokens command - Implement ListUnspentTokens for Prover service - Add transactor interface to reduce dependency on TMS Change-Id: Ib8b9d8564933aadd85aacc05267f10ca3a1274b8 Signed-off-by: Wenjian Qiao --- protos/token/prover.pb.go | 365 ++++++++++++++++++++++++------- protos/token/prover.proto | 26 ++- token/server/manager.go | 6 + token/server/mock/tms_manager.go | 80 +++++++ token/server/mock/transactor.go | 94 ++++++++ token/server/prover.go | 19 ++ token/server/prover_test.go | 134 ++++++++++-- token/server/tms.go | 12 + 8 files changed, 637 insertions(+), 99 deletions(-) create mode 100644 token/server/mock/transactor.go diff --git a/protos/token/prover.pb.go b/protos/token/prover.pb.go index 478a133dbb8..1ebeb1a5ca2 100644 --- a/protos/token/prover.pb.go +++ b/protos/token/prover.pb.go @@ -41,7 +41,7 @@ func (m *TokenToIssue) Reset() { *m = TokenToIssue{} } func (m *TokenToIssue) String() string { return proto.CompactTextString(m) } func (*TokenToIssue) ProtoMessage() {} func (*TokenToIssue) Descriptor() ([]byte, []int) { - return fileDescriptor_prover_405073bc77f17ef9, []int{0} + return fileDescriptor_prover_7f0f822712f3b134, []int{0} } func (m *TokenToIssue) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_TokenToIssue.Unmarshal(m, b) @@ -87,7 +87,7 @@ type RecipientTransferShare struct { // Recipient refers to the prospective owner of a transferred token Recipient []byte `protobuf:"bytes,1,opt,name=recipient,proto3" json:"recipient,omitempty"` // Quantity refers to the number of token units to be transferred to the recipient - Quantity uint64 `protobuf:"varint,2,opt,name=quantity" json:"quantity,omitempty"` + Quantity uint64 `protobuf:"varint,2,opt,name=quantity,proto3" json:"quantity,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -97,7 +97,7 @@ func (m *RecipientTransferShare) Reset() { *m = RecipientTransferShare{} func (m *RecipientTransferShare) String() string { return proto.CompactTextString(m) } func (*RecipientTransferShare) ProtoMessage() {} func (*RecipientTransferShare) Descriptor() ([]byte, []int) { - return fileDescriptor_prover_405073bc77f17ef9, []int{1} + return fileDescriptor_prover_7f0f822712f3b134, []int{1} } func (m *RecipientTransferShare) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_RecipientTransferShare.Unmarshal(m, b) @@ -131,6 +131,142 @@ func (m *RecipientTransferShare) GetQuantity() uint64 { return 0 } +// TokenOutput is used to specify a token returned by ListRequest +type TokenOutput struct { + // ID is used to uniquely identify the token + Id []byte `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + // Type is the type of the token + Type string `protobuf:"bytes,2,opt,name=type,proto3" json:"type,omitempty"` + // Quantity represents the number for this type of token + Quantity uint64 `protobuf:"varint,3,opt,name=quantity,proto3" json:"quantity,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *TokenOutput) Reset() { *m = TokenOutput{} } +func (m *TokenOutput) String() string { return proto.CompactTextString(m) } +func (*TokenOutput) ProtoMessage() {} +func (*TokenOutput) Descriptor() ([]byte, []int) { + return fileDescriptor_prover_7f0f822712f3b134, []int{2} +} +func (m *TokenOutput) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_TokenOutput.Unmarshal(m, b) +} +func (m *TokenOutput) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_TokenOutput.Marshal(b, m, deterministic) +} +func (dst *TokenOutput) XXX_Merge(src proto.Message) { + xxx_messageInfo_TokenOutput.Merge(dst, src) +} +func (m *TokenOutput) XXX_Size() int { + return xxx_messageInfo_TokenOutput.Size(m) +} +func (m *TokenOutput) XXX_DiscardUnknown() { + xxx_messageInfo_TokenOutput.DiscardUnknown(m) +} + +var xxx_messageInfo_TokenOutput proto.InternalMessageInfo + +func (m *TokenOutput) GetId() []byte { + if m != nil { + return m.Id + } + return nil +} + +func (m *TokenOutput) GetType() string { + if m != nil { + return m.Type + } + return "" +} + +func (m *TokenOutput) GetQuantity() uint64 { + if m != nil { + return m.Quantity + } + return 0 +} + +// UnspentTokens is used to hold the output of listRequest +type UnspentTokens struct { + Tokens []*TokenOutput `protobuf:"bytes,1,rep,name=tokens,proto3" json:"tokens,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *UnspentTokens) Reset() { *m = UnspentTokens{} } +func (m *UnspentTokens) String() string { return proto.CompactTextString(m) } +func (*UnspentTokens) ProtoMessage() {} +func (*UnspentTokens) Descriptor() ([]byte, []int) { + return fileDescriptor_prover_7f0f822712f3b134, []int{3} +} +func (m *UnspentTokens) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_UnspentTokens.Unmarshal(m, b) +} +func (m *UnspentTokens) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_UnspentTokens.Marshal(b, m, deterministic) +} +func (dst *UnspentTokens) XXX_Merge(src proto.Message) { + xxx_messageInfo_UnspentTokens.Merge(dst, src) +} +func (m *UnspentTokens) XXX_Size() int { + return xxx_messageInfo_UnspentTokens.Size(m) +} +func (m *UnspentTokens) XXX_DiscardUnknown() { + xxx_messageInfo_UnspentTokens.DiscardUnknown(m) +} + +var xxx_messageInfo_UnspentTokens proto.InternalMessageInfo + +func (m *UnspentTokens) GetTokens() []*TokenOutput { + if m != nil { + return m.Tokens + } + return nil +} + +// ListRequest is used to request a list of unspent tokens +type ListRequest struct { + Credential []byte `protobuf:"bytes,1,opt,name=credential,proto3" json:"credential,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ListRequest) Reset() { *m = ListRequest{} } +func (m *ListRequest) String() string { return proto.CompactTextString(m) } +func (*ListRequest) ProtoMessage() {} +func (*ListRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_prover_7f0f822712f3b134, []int{4} +} +func (m *ListRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ListRequest.Unmarshal(m, b) +} +func (m *ListRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ListRequest.Marshal(b, m, deterministic) +} +func (dst *ListRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_ListRequest.Merge(dst, src) +} +func (m *ListRequest) XXX_Size() int { + return xxx_messageInfo_ListRequest.Size(m) +} +func (m *ListRequest) XXX_DiscardUnknown() { + xxx_messageInfo_ListRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_ListRequest proto.InternalMessageInfo + +func (m *ListRequest) GetCredential() []byte { + if m != nil { + return m.Credential + } + return nil +} + // ImportRequest is used to request creation of imports type ImportRequest struct { // Credential contains information about the party who is requesting the operation @@ -147,7 +283,7 @@ func (m *ImportRequest) Reset() { *m = ImportRequest{} } func (m *ImportRequest) String() string { return proto.CompactTextString(m) } func (*ImportRequest) ProtoMessage() {} func (*ImportRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_prover_405073bc77f17ef9, []int{2} + return fileDescriptor_prover_7f0f822712f3b134, []int{5} } func (m *ImportRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ImportRequest.Unmarshal(m, b) @@ -185,7 +321,7 @@ func (m *ImportRequest) GetTokensToIssue() []*TokenToIssue { type TransferRequest struct { Credential []byte `protobuf:"bytes,1,opt,name=credential,proto3" json:"credential,omitempty"` TokenIDs [][]byte `protobuf:"bytes,2,rep,name=tokenIDs,proto3" json:"tokenIDs,omitempty"` - Shares []*RecipientTransferShare `protobuf:"bytes,3,rep,name=shares" json:"shares,omitempty"` + Shares []*RecipientTransferShare `protobuf:"bytes,3,rep,name=shares,proto3" json:"shares,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -195,7 +331,7 @@ func (m *TransferRequest) Reset() { *m = TransferRequest{} } func (m *TransferRequest) String() string { return proto.CompactTextString(m) } func (*TransferRequest) ProtoMessage() {} func (*TransferRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_prover_405073bc77f17ef9, []int{3} + return fileDescriptor_prover_7f0f822712f3b134, []int{6} } func (m *TransferRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_TransferRequest.Unmarshal(m, b) @@ -258,7 +394,7 @@ func (m *Header) Reset() { *m = Header{} } func (m *Header) String() string { return proto.CompactTextString(m) } func (*Header) ProtoMessage() {} func (*Header) Descriptor() ([]byte, []int) { - return fileDescriptor_prover_405073bc77f17ef9, []int{4} + return fileDescriptor_prover_7f0f822712f3b134, []int{7} } func (m *Header) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Header.Unmarshal(m, b) @@ -315,6 +451,7 @@ type Command struct { // Types that are valid to be assigned to Payload: // *Command_ImportRequest // *Command_TransferRequest + // *Command_ListRequest Payload isCommand_Payload `protobuf_oneof:"payload"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` @@ -325,7 +462,7 @@ func (m *Command) Reset() { *m = Command{} } func (m *Command) String() string { return proto.CompactTextString(m) } func (*Command) ProtoMessage() {} func (*Command) Descriptor() ([]byte, []int) { - return fileDescriptor_prover_405073bc77f17ef9, []int{5} + return fileDescriptor_prover_7f0f822712f3b134, []int{8} } func (m *Command) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Command.Unmarshal(m, b) @@ -345,13 +482,6 @@ func (m *Command) XXX_DiscardUnknown() { var xxx_messageInfo_Command proto.InternalMessageInfo -func (m *Command) GetHeader() *Header { - if m != nil { - return m.Header - } - return nil -} - type isCommand_Payload interface { isCommand_Payload() } @@ -360,11 +490,15 @@ type Command_ImportRequest struct { ImportRequest *ImportRequest `protobuf:"bytes,2,opt,name=import_request,json=importRequest,proto3,oneof"` } type Command_TransferRequest struct { - TransferRequest *TransferRequest `protobuf:"bytes,3,opt,name=transfer_request,json=transferRequest,oneof"` + TransferRequest *TransferRequest `protobuf:"bytes,3,opt,name=transfer_request,json=transferRequest,proto3,oneof"` +} +type Command_ListRequest struct { + ListRequest *ListRequest `protobuf:"bytes,4,opt,name=list_request,json=listRequest,proto3,oneof"` } func (*Command_ImportRequest) isCommand_Payload() {} func (*Command_TransferRequest) isCommand_Payload() {} +func (*Command_ListRequest) isCommand_Payload() {} func (m *Command) GetPayload() isCommand_Payload { if m != nil { @@ -373,6 +507,13 @@ func (m *Command) GetPayload() isCommand_Payload { return nil } +func (m *Command) GetHeader() *Header { + if m != nil { + return m.Header + } + return nil +} + func (m *Command) GetImportRequest() *ImportRequest { if x, ok := m.GetPayload().(*Command_ImportRequest); ok { return x.ImportRequest @@ -387,11 +528,19 @@ func (m *Command) GetTransferRequest() *TransferRequest { return nil } +func (m *Command) GetListRequest() *ListRequest { + if x, ok := m.GetPayload().(*Command_ListRequest); ok { + return x.ListRequest + } + return nil +} + // XXX_OneofFuncs is for the internal use of the proto package. func (*Command) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { return _Command_OneofMarshaler, _Command_OneofUnmarshaler, _Command_OneofSizer, []interface{}{ (*Command_ImportRequest)(nil), (*Command_TransferRequest)(nil), + (*Command_ListRequest)(nil), } } @@ -409,6 +558,11 @@ func _Command_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { if err := b.EncodeMessage(x.TransferRequest); err != nil { return err } + case *Command_ListRequest: + b.EncodeVarint(4<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.ListRequest); err != nil { + return err + } case nil: default: return fmt.Errorf("Command.Payload has unexpected type %T", x) @@ -435,6 +589,14 @@ func _Command_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer err := b.DecodeMessage(msg) m.Payload = &Command_TransferRequest{msg} return true, err + case 4: // payload.list_request + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(ListRequest) + err := b.DecodeMessage(msg) + m.Payload = &Command_ListRequest{msg} + return true, err default: return false, nil } @@ -454,6 +616,11 @@ func _Command_OneofSizer(msg proto.Message) (n int) { n += 1 // tag and wire n += proto.SizeVarint(uint64(s)) n += s + case *Command_ListRequest: + s := proto.Size(x.ListRequest) + n += 1 // tag and wire + n += proto.SizeVarint(uint64(s)) + n += s case nil: default: panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) @@ -476,7 +643,7 @@ func (m *SignedCommand) Reset() { *m = SignedCommand{} } func (m *SignedCommand) String() string { return proto.CompactTextString(m) } func (*SignedCommand) ProtoMessage() {} func (*SignedCommand) Descriptor() ([]byte, []int) { - return fileDescriptor_prover_405073bc77f17ef9, []int{6} + return fileDescriptor_prover_7f0f822712f3b134, []int{9} } func (m *SignedCommand) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_SignedCommand.Unmarshal(m, b) @@ -530,7 +697,7 @@ func (m *CommandResponseHeader) Reset() { *m = CommandResponseHeader{} } func (m *CommandResponseHeader) String() string { return proto.CompactTextString(m) } func (*CommandResponseHeader) ProtoMessage() {} func (*CommandResponseHeader) Descriptor() ([]byte, []int) { - return fileDescriptor_prover_405073bc77f17ef9, []int{7} + return fileDescriptor_prover_7f0f822712f3b134, []int{10} } func (m *CommandResponseHeader) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_CommandResponseHeader.Unmarshal(m, b) @@ -571,7 +738,7 @@ func (m *CommandResponseHeader) GetCreator() []byte { return nil } -// Error reports an applicaton error +// Error reports an application error type Error struct { // Message associated with this response. Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` @@ -586,7 +753,7 @@ func (m *Error) Reset() { *m = Error{} } func (m *Error) String() string { return proto.CompactTextString(m) } func (*Error) ProtoMessage() {} func (*Error) Descriptor() ([]byte, []int) { - return fileDescriptor_prover_405073bc77f17ef9, []int{8} + return fileDescriptor_prover_7f0f822712f3b134, []int{11} } func (m *Error) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Error.Unmarshal(m, b) @@ -629,6 +796,7 @@ type CommandResponse struct { // Types that are valid to be assigned to Payload: // *CommandResponse_Err // *CommandResponse_TokenTransaction + // *CommandResponse_UnspentTokens Payload isCommandResponse_Payload `protobuf_oneof:"payload"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` @@ -639,7 +807,7 @@ func (m *CommandResponse) Reset() { *m = CommandResponse{} } func (m *CommandResponse) String() string { return proto.CompactTextString(m) } func (*CommandResponse) ProtoMessage() {} func (*CommandResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_prover_405073bc77f17ef9, []int{9} + return fileDescriptor_prover_7f0f822712f3b134, []int{12} } func (m *CommandResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_CommandResponse.Unmarshal(m, b) @@ -659,13 +827,6 @@ func (m *CommandResponse) XXX_DiscardUnknown() { var xxx_messageInfo_CommandResponse proto.InternalMessageInfo -func (m *CommandResponse) GetHeader() *CommandResponseHeader { - if m != nil { - return m.Header - } - return nil -} - type isCommandResponse_Payload interface { isCommandResponse_Payload() } @@ -673,14 +834,16 @@ type isCommandResponse_Payload interface { type CommandResponse_Err struct { Err *Error `protobuf:"bytes,2,opt,name=err,proto3,oneof"` } - type CommandResponse_TokenTransaction struct { TokenTransaction *TokenTransaction `protobuf:"bytes,3,opt,name=token_transaction,json=tokenTransaction,proto3,oneof"` } +type CommandResponse_UnspentTokens struct { + UnspentTokens *UnspentTokens `protobuf:"bytes,4,opt,name=unspent_tokens,json=unspentTokens,proto3,oneof"` +} -func (*CommandResponse_Err) isCommandResponse_Payload() {} - +func (*CommandResponse_Err) isCommandResponse_Payload() {} func (*CommandResponse_TokenTransaction) isCommandResponse_Payload() {} +func (*CommandResponse_UnspentTokens) isCommandResponse_Payload() {} func (m *CommandResponse) GetPayload() isCommandResponse_Payload { if m != nil { @@ -689,6 +852,13 @@ func (m *CommandResponse) GetPayload() isCommandResponse_Payload { return nil } +func (m *CommandResponse) GetHeader() *CommandResponseHeader { + if m != nil { + return m.Header + } + return nil +} + func (m *CommandResponse) GetErr() *Error { if x, ok := m.GetPayload().(*CommandResponse_Err); ok { return x.Err @@ -703,11 +873,19 @@ func (m *CommandResponse) GetTokenTransaction() *TokenTransaction { return nil } +func (m *CommandResponse) GetUnspentTokens() *UnspentTokens { + if x, ok := m.GetPayload().(*CommandResponse_UnspentTokens); ok { + return x.UnspentTokens + } + return nil +} + // XXX_OneofFuncs is for the internal use of the proto package. func (*CommandResponse) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { return _CommandResponse_OneofMarshaler, _CommandResponse_OneofUnmarshaler, _CommandResponse_OneofSizer, []interface{}{ (*CommandResponse_Err)(nil), (*CommandResponse_TokenTransaction)(nil), + (*CommandResponse_UnspentTokens)(nil), } } @@ -725,6 +903,11 @@ func _CommandResponse_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { if err := b.EncodeMessage(x.TokenTransaction); err != nil { return err } + case *CommandResponse_UnspentTokens: + b.EncodeVarint(4<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.UnspentTokens); err != nil { + return err + } case nil: default: return fmt.Errorf("CommandResponse.Payload has unexpected type %T", x) @@ -751,6 +934,14 @@ func _CommandResponse_OneofUnmarshaler(msg proto.Message, tag, wire int, b *prot err := b.DecodeMessage(msg) m.Payload = &CommandResponse_TokenTransaction{msg} return true, err + case 4: // payload.unspent_tokens + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(UnspentTokens) + err := b.DecodeMessage(msg) + m.Payload = &CommandResponse_UnspentTokens{msg} + return true, err default: return false, nil } @@ -770,6 +961,11 @@ func _CommandResponse_OneofSizer(msg proto.Message) (n int) { n += 1 // tag and wire n += proto.SizeVarint(uint64(s)) n += s + case *CommandResponse_UnspentTokens: + s := proto.Size(x.UnspentTokens) + n += 1 // tag and wire + n += proto.SizeVarint(uint64(s)) + n += s case nil: default: panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) @@ -792,7 +988,7 @@ func (m *SignedCommandResponse) Reset() { *m = SignedCommandResponse{} } func (m *SignedCommandResponse) String() string { return proto.CompactTextString(m) } func (*SignedCommandResponse) ProtoMessage() {} func (*SignedCommandResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_prover_405073bc77f17ef9, []int{10} + return fileDescriptor_prover_7f0f822712f3b134, []int{13} } func (m *SignedCommandResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_SignedCommandResponse.Unmarshal(m, b) @@ -829,6 +1025,9 @@ func (m *SignedCommandResponse) GetSignature() []byte { func init() { proto.RegisterType((*TokenToIssue)(nil), "protos.TokenToIssue") proto.RegisterType((*RecipientTransferShare)(nil), "protos.RecipientTransferShare") + proto.RegisterType((*TokenOutput)(nil), "protos.TokenOutput") + proto.RegisterType((*UnspentTokens)(nil), "protos.UnspentTokens") + proto.RegisterType((*ListRequest)(nil), "protos.ListRequest") proto.RegisterType((*ImportRequest)(nil), "protos.ImportRequest") proto.RegisterType((*TransferRequest)(nil), "protos.TransferRequest") proto.RegisterType((*Header)(nil), "protos.Header") @@ -920,52 +1119,58 @@ var _Prover_serviceDesc = grpc.ServiceDesc{ Metadata: "token/prover.proto", } -func init() { proto.RegisterFile("token/prover.proto", fileDescriptor_prover_405073bc77f17ef9) } - -var fileDescriptor_prover_405073bc77f17ef9 = []byte{ - // 700 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x95, 0x5f, 0x6b, 0xdb, 0x3a, - 0x14, 0xc0, 0xe3, 0xa6, 0x4d, 0x9b, 0x93, 0xa4, 0x69, 0x45, 0x7b, 0x1b, 0xc2, 0x6d, 0x6f, 0xea, - 0x0b, 0x97, 0x70, 0x1f, 0x1c, 0xc8, 0xd8, 0x18, 0x6c, 0x8c, 0xd1, 0x75, 0x2c, 0x79, 0x6b, 0xd5, - 0x3c, 0x8d, 0x41, 0x50, 0xec, 0x53, 0xdb, 0x2c, 0xb6, 0x5c, 0x49, 0x19, 0xe4, 0x03, 0xec, 0x75, - 0xb0, 0x6f, 0xb3, 0xe7, 0x7d, 0xb2, 0x61, 0x59, 0x72, 0xfe, 0x50, 0xb6, 0xc1, 0x9e, 0xe2, 0xf3, - 0x47, 0xe7, 0xdf, 0xef, 0x48, 0x01, 0xa2, 0xf8, 0x47, 0x4c, 0x07, 0x99, 0xe0, 0x9f, 0x50, 0x78, - 0x99, 0xe0, 0x8a, 0x93, 0x9a, 0xfe, 0x91, 0xdd, 0x7f, 0x42, 0xce, 0xc3, 0x39, 0x0e, 0xb4, 0x38, - 0x5b, 0xdc, 0x0f, 0x54, 0x9c, 0xa0, 0x54, 0x2c, 0xc9, 0x0a, 0xc7, 0xee, 0x59, 0x71, 0x58, 0x09, - 0x96, 0x4a, 0xe6, 0xab, 0x98, 0xa7, 0x85, 0xc1, 0xfd, 0x00, 0xcd, 0x49, 0x6e, 0x9a, 0xf0, 0xb1, - 0x94, 0x0b, 0x24, 0x7f, 0x43, 0x5d, 0xa0, 0x1f, 0x67, 0x31, 0xa6, 0xaa, 0xe3, 0xf4, 0x9c, 0x7e, - 0x93, 0xae, 0x14, 0x84, 0xc0, 0xae, 0x5a, 0x66, 0xd8, 0xd9, 0xe9, 0x39, 0xfd, 0x3a, 0xd5, 0xdf, - 0xa4, 0x0b, 0x07, 0x0f, 0x0b, 0x96, 0xaa, 0x58, 0x2d, 0x3b, 0xd5, 0x9e, 0xd3, 0xdf, 0xa5, 0xa5, - 0xec, 0x52, 0xf8, 0x8b, 0xda, 0xc3, 0x93, 0x3c, 0xf7, 0x3d, 0x8a, 0xbb, 0x88, 0x89, 0x5f, 0xe5, - 0x59, 0x8f, 0xb9, 0xb3, 0x15, 0x33, 0x81, 0xd6, 0x38, 0xc9, 0xb8, 0x50, 0x14, 0x1f, 0x16, 0x28, - 0x15, 0xb9, 0x00, 0xf0, 0x05, 0x06, 0x98, 0xaa, 0x98, 0xcd, 0x4d, 0xac, 0x35, 0x0d, 0x79, 0x09, - 0x6d, 0xdd, 0xbd, 0x9c, 0x2a, 0x3e, 0x8d, 0xf3, 0x2e, 0x3b, 0x3b, 0xbd, 0x6a, 0xbf, 0x31, 0x3c, - 0x29, 0x66, 0x20, 0xbd, 0xf5, 0x09, 0xd0, 0x56, 0xe1, 0x6c, 0x44, 0xf7, 0xb3, 0x03, 0x6d, 0x5b, - 0xfa, 0xef, 0x66, 0xec, 0xc2, 0x81, 0x0e, 0x32, 0xbe, 0x96, 0x3a, 0x55, 0x93, 0x96, 0x32, 0x79, - 0x06, 0x35, 0x99, 0x4f, 0x40, 0x76, 0xaa, 0xba, 0x88, 0x0b, 0x5b, 0xc4, 0xe3, 0x83, 0xa2, 0xc6, - 0xdb, 0xfd, 0xea, 0x40, 0x6d, 0x84, 0x2c, 0x40, 0x41, 0x9e, 0x43, 0xbd, 0xe4, 0xab, 0xb3, 0x37, - 0x86, 0x5d, 0xaf, 0xd8, 0x00, 0xcf, 0x6e, 0x80, 0x37, 0xb1, 0x1e, 0x74, 0xe5, 0x4c, 0xce, 0x01, - 0xfc, 0x88, 0xa5, 0x29, 0xce, 0xa7, 0x71, 0x60, 0x28, 0xd6, 0x8d, 0x66, 0x1c, 0x90, 0x13, 0xd8, - 0x4b, 0x79, 0xea, 0xa3, 0xe6, 0xd8, 0xa4, 0x85, 0x40, 0x3a, 0xb0, 0xef, 0x0b, 0x64, 0x8a, 0x8b, - 0xce, 0xae, 0xd6, 0x5b, 0xd1, 0xfd, 0xee, 0xc0, 0xfe, 0x1b, 0x9e, 0x24, 0x2c, 0x0d, 0xc8, 0x7f, - 0x50, 0x8b, 0x74, 0x79, 0xa6, 0xa2, 0x43, 0xdb, 0x57, 0x51, 0x34, 0x35, 0x56, 0xf2, 0x0a, 0x0e, - 0x63, 0x8d, 0x6f, 0x2a, 0x8a, 0x69, 0xea, 0x32, 0x1a, 0xc3, 0x53, 0xeb, 0xbf, 0x01, 0x77, 0x54, - 0xa1, 0xad, 0x78, 0x83, 0xf6, 0x35, 0x1c, 0x29, 0x33, 0xa0, 0x32, 0x42, 0x55, 0x47, 0x38, 0x2b, - 0x71, 0x6e, 0xe2, 0x1a, 0x55, 0x68, 0x5b, 0x6d, 0xaa, 0xae, 0xea, 0xb0, 0x9f, 0xb1, 0xe5, 0x9c, - 0xb3, 0xc0, 0x7d, 0x07, 0xad, 0xbb, 0x38, 0x4c, 0x31, 0xb0, 0x9d, 0xe4, 0xfd, 0x16, 0x9f, 0x06, - 0xad, 0x15, 0xf3, 0xa5, 0x95, 0x71, 0x98, 0x32, 0xb5, 0x10, 0xc5, 0x1d, 0x68, 0xd2, 0x95, 0xc2, - 0xfd, 0xe2, 0xc0, 0xa9, 0x89, 0x41, 0x51, 0x66, 0x3c, 0x95, 0xf8, 0xc7, 0xc0, 0x2e, 0xa1, 0x69, - 0x92, 0x4f, 0x23, 0x26, 0x23, 0x93, 0xb4, 0x61, 0x74, 0x23, 0x26, 0xa3, 0x75, 0x3c, 0xd5, 0x4d, - 0x3c, 0x2f, 0x60, 0xef, 0xad, 0x10, 0x5c, 0xe4, 0x2e, 0x09, 0x4a, 0xc9, 0x42, 0xd4, 0xd9, 0xeb, - 0xd4, 0x8a, 0xb9, 0xc5, 0xcc, 0xc1, 0x84, 0x2e, 0xc7, 0xf2, 0xcd, 0x81, 0xf6, 0x56, 0x37, 0xe4, - 0xe9, 0x16, 0xe3, 0x73, 0x3b, 0xf1, 0x47, 0xdb, 0x2e, 0x91, 0x5f, 0x42, 0x15, 0x85, 0x30, 0x9c, - 0x5b, 0xf6, 0x8c, 0x2e, 0x6d, 0x54, 0xa1, 0xb9, 0x8d, 0xbc, 0x86, 0x63, 0x7d, 0x43, 0xa6, 0x6b, - 0x2f, 0x94, 0xc1, 0x7a, 0x6c, 0xae, 0xe7, 0xca, 0x30, 0xaa, 0xd0, 0x23, 0xb5, 0xa5, 0x5b, 0x27, - 0x7a, 0x0b, 0xa7, 0x1b, 0x44, 0xcb, 0xfa, 0xbb, 0x70, 0x20, 0xcc, 0xb7, 0x41, 0x5b, 0xca, 0x3f, - 0x67, 0x3b, 0xa4, 0x50, 0xbb, 0xd1, 0x0f, 0x2f, 0x19, 0xc1, 0xe1, 0x8d, 0xe0, 0x3e, 0x4a, 0x69, - 0xf7, 0xa5, 0xdc, 0xdc, 0x8d, 0xa4, 0xdd, 0xf3, 0x47, 0xd5, 0xb6, 0x16, 0xb7, 0x72, 0x75, 0x0b, - 0xff, 0x72, 0x11, 0x7a, 0xd1, 0x32, 0x43, 0x31, 0xc7, 0x20, 0x44, 0xe1, 0xdd, 0xb3, 0x99, 0x88, - 0x7d, 0x7b, 0x50, 0xf7, 0xf8, 0xfe, 0xff, 0x30, 0x56, 0xd1, 0x62, 0xe6, 0xf9, 0x3c, 0x19, 0xac, - 0xf9, 0x0e, 0x0a, 0xdf, 0xe2, 0xc9, 0x97, 0x03, 0xed, 0x3b, 0x2b, 0xfe, 0x0f, 0x9e, 0xfc, 0x08, - 0x00, 0x00, 0xff, 0xff, 0xf0, 0x1f, 0x1b, 0x93, 0x2c, 0x06, 0x00, 0x00, +func init() { proto.RegisterFile("token/prover.proto", fileDescriptor_prover_7f0f822712f3b134) } + +var fileDescriptor_prover_7f0f822712f3b134 = []byte{ + // 800 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x55, 0xdf, 0xab, 0xe3, 0x44, + 0x14, 0x6e, 0xda, 0x6e, 0xef, 0xed, 0x69, 0x7b, 0xef, 0xee, 0xb8, 0xd7, 0x0d, 0xc5, 0xbb, 0xde, + 0x8d, 0x20, 0x45, 0x31, 0x85, 0x8a, 0xb2, 0xe0, 0x22, 0xb2, 0xae, 0x98, 0x82, 0xe2, 0xee, 0x6c, + 0x7d, 0x11, 0xa1, 0x4c, 0x93, 0xb9, 0xc9, 0x60, 0x93, 0xc9, 0xce, 0x4c, 0x84, 0xfe, 0x01, 0xbe, + 0x0a, 0xfe, 0xb7, 0x3e, 0xf8, 0x20, 0x99, 0x1f, 0x69, 0x52, 0x2e, 0xba, 0xe2, 0x53, 0x72, 0x7e, + 0xcc, 0x39, 0xdf, 0x9c, 0xef, 0x9b, 0x19, 0x40, 0x8a, 0xff, 0x42, 0x8b, 0x65, 0x29, 0xf8, 0xaf, + 0x54, 0x84, 0xa5, 0xe0, 0x8a, 0xa3, 0x91, 0xfe, 0xc8, 0xf9, 0xfb, 0x29, 0xe7, 0xe9, 0x9e, 0x2e, + 0xb5, 0xb9, 0xab, 0x6e, 0x97, 0x8a, 0xe5, 0x54, 0x2a, 0x92, 0x97, 0x26, 0x71, 0xfe, 0xc8, 0x2c, + 0x56, 0x82, 0x14, 0x92, 0xc4, 0x8a, 0xf1, 0xc2, 0x04, 0x82, 0x9f, 0x61, 0xba, 0xa9, 0x43, 0x1b, + 0xbe, 0x96, 0xb2, 0xa2, 0xe8, 0x3d, 0x18, 0x0b, 0x1a, 0xb3, 0x92, 0xd1, 0x42, 0xf9, 0xde, 0x8d, + 0xb7, 0x98, 0xe2, 0xa3, 0x03, 0x21, 0x18, 0xaa, 0x43, 0x49, 0xfd, 0xfe, 0x8d, 0xb7, 0x18, 0x63, + 0xfd, 0x8f, 0xe6, 0x70, 0xfe, 0xa6, 0x22, 0x85, 0x62, 0xea, 0xe0, 0x0f, 0x6e, 0xbc, 0xc5, 0x10, + 0x37, 0x76, 0x80, 0xe1, 0x5d, 0xec, 0x16, 0x6f, 0xea, 0xde, 0xb7, 0x54, 0xbc, 0xce, 0x88, 0xf8, + 0xb7, 0x3e, 0xed, 0x9a, 0xfd, 0x93, 0x9a, 0xdf, 0xc3, 0x44, 0x23, 0xfe, 0xa1, 0x52, 0x65, 0xa5, + 0xd0, 0x05, 0xf4, 0x59, 0x62, 0x2b, 0xf4, 0x59, 0xf2, 0x9f, 0x21, 0x3e, 0x83, 0xd9, 0x8f, 0x85, + 0x2c, 0x6b, 0x80, 0x75, 0x55, 0x89, 0x3e, 0x86, 0x91, 0x1e, 0x96, 0xf4, 0xbd, 0x9b, 0xc1, 0x62, + 0xb2, 0x7a, 0xc7, 0x4c, 0x4a, 0x86, 0xad, 0xae, 0xd8, 0xa6, 0x04, 0x9f, 0xc0, 0xe4, 0x3b, 0x26, + 0x15, 0xa6, 0x6f, 0x2a, 0x2a, 0x15, 0x7a, 0x0c, 0x10, 0x0b, 0x9a, 0xd0, 0x42, 0x31, 0xb2, 0xb7, + 0xa0, 0x5a, 0x9e, 0x20, 0x87, 0xd9, 0x3a, 0x2f, 0xb9, 0x78, 0xdb, 0x05, 0xe8, 0x19, 0x5c, 0x9a, + 0x4e, 0x5b, 0xc5, 0xb7, 0xac, 0x66, 0xc8, 0xef, 0x6b, 0x54, 0x0f, 0x3b, 0xa8, 0x2c, 0x7b, 0x78, + 0x66, 0x92, 0xad, 0x19, 0xfc, 0xe6, 0xc1, 0xa5, 0x1b, 0xfb, 0xdb, 0x76, 0x9c, 0xc3, 0xb9, 0x2e, + 0xb2, 0x7e, 0x21, 0x75, 0xab, 0x29, 0x6e, 0x6c, 0xf4, 0x39, 0x8c, 0x64, 0xcd, 0x9e, 0xf4, 0x07, + 0x1a, 0xc4, 0x63, 0x07, 0xe2, 0x6e, 0x92, 0xb1, 0xcd, 0x0e, 0xfe, 0xf0, 0x60, 0x14, 0x51, 0x92, + 0x50, 0x81, 0x9e, 0xc2, 0xb8, 0xd1, 0xa6, 0xee, 0x3e, 0x59, 0xcd, 0x43, 0xa3, 0xde, 0xd0, 0xa9, + 0x37, 0xdc, 0xb8, 0x0c, 0x7c, 0x4c, 0x46, 0xd7, 0x00, 0x71, 0x46, 0x8a, 0x82, 0xee, 0xb7, 0x2c, + 0xb1, 0xf4, 0x8e, 0xad, 0x67, 0x9d, 0xa0, 0x87, 0x70, 0xaf, 0xe0, 0x45, 0x4c, 0x35, 0xc1, 0x53, + 0x6c, 0x0c, 0xe4, 0xc3, 0x59, 0x2c, 0x28, 0x51, 0x5c, 0xf8, 0x43, 0xed, 0x77, 0x66, 0xf0, 0x97, + 0x07, 0x67, 0x5f, 0xf3, 0x3c, 0x27, 0x45, 0x82, 0x3e, 0x84, 0x51, 0xa6, 0xe1, 0x59, 0x44, 0x17, + 0x6e, 0x5f, 0x06, 0x34, 0xb6, 0x51, 0xf4, 0x25, 0x5c, 0x30, 0x4d, 0xdf, 0x56, 0x98, 0x69, 0x6a, + 0x18, 0x93, 0xd5, 0x95, 0xcb, 0xef, 0x90, 0x1b, 0xf5, 0xf0, 0x8c, 0x75, 0xd8, 0x7e, 0x01, 0xf7, + 0x95, 0x1d, 0x50, 0x53, 0x61, 0xa0, 0x2b, 0x3c, 0x6a, 0xe8, 0xec, 0xd2, 0x15, 0xf5, 0xf0, 0xa5, + 0x3a, 0x61, 0xf0, 0x29, 0x4c, 0xf7, 0x4c, 0x1e, 0x31, 0x0c, 0x75, 0x85, 0x46, 0xa6, 0x2d, 0x3d, + 0x46, 0x3d, 0x3c, 0xd9, 0x1f, 0xcd, 0xe7, 0x63, 0x38, 0x2b, 0xc9, 0x61, 0xcf, 0x49, 0x12, 0x7c, + 0x0b, 0xb3, 0xd7, 0x2c, 0x2d, 0x68, 0xe2, 0x66, 0x50, 0x4f, 0xca, 0xfc, 0x5a, 0x51, 0x38, 0xb3, + 0x3e, 0xaa, 0x92, 0xa5, 0x05, 0x51, 0x95, 0x30, 0xc7, 0x6a, 0x8a, 0x8f, 0x8e, 0xe0, 0x77, 0x0f, + 0xae, 0x6c, 0x0d, 0x4c, 0x65, 0xc9, 0x0b, 0x49, 0xff, 0x37, 0xd5, 0x4f, 0x60, 0x6a, 0x9b, 0x6f, + 0x33, 0x22, 0x33, 0xdb, 0x74, 0x62, 0x7d, 0x11, 0x91, 0x59, 0x9b, 0xd8, 0x41, 0x97, 0xd8, 0x2f, + 0xe0, 0xde, 0x37, 0x42, 0x70, 0x51, 0xa7, 0xe4, 0x54, 0x4a, 0x92, 0x52, 0xdd, 0x7d, 0x8c, 0x9d, + 0x59, 0x47, 0xec, 0x1c, 0x6c, 0xe9, 0x66, 0x2c, 0x7f, 0x7a, 0x70, 0x79, 0xb2, 0x1b, 0xf4, 0xd9, + 0x89, 0x3a, 0xae, 0xdd, 0xa4, 0xef, 0xdc, 0x76, 0x23, 0x96, 0x27, 0x30, 0xa0, 0x42, 0x58, 0x85, + 0xcc, 0xdc, 0x1a, 0x0d, 0x2d, 0xea, 0xe1, 0x3a, 0x86, 0xbe, 0x82, 0x07, 0xfa, 0x6c, 0x6d, 0x5b, + 0xf7, 0xb2, 0x15, 0xc4, 0x03, 0x7b, 0xb0, 0x8f, 0x81, 0xa8, 0x87, 0xef, 0xab, 0x13, 0x5f, 0xad, + 0xc8, 0xca, 0xdc, 0x5e, 0x5b, 0x7b, 0x69, 0x0d, 0xbb, 0x8a, 0xec, 0xdc, 0x6d, 0xb5, 0x22, 0xab, + 0xb6, 0xa3, 0xad, 0x88, 0x57, 0x70, 0xd5, 0x51, 0x44, 0xb3, 0xff, 0x39, 0x9c, 0x0b, 0xfb, 0x6f, + 0xa5, 0xd1, 0xd8, 0xff, 0xac, 0x8d, 0x15, 0x86, 0xd1, 0x4b, 0xfd, 0x5c, 0xa1, 0x08, 0x2e, 0x5e, + 0x0a, 0x1e, 0x53, 0x29, 0x9d, 0xde, 0x1a, 0x84, 0x9d, 0xa6, 0xf3, 0xeb, 0x3b, 0xdd, 0x0e, 0x4b, + 0xd0, 0x7b, 0xfe, 0x0a, 0x3e, 0xe0, 0x22, 0x0d, 0xb3, 0x43, 0x49, 0xc5, 0x9e, 0x26, 0x29, 0x15, + 0xe1, 0x2d, 0xd9, 0x09, 0x16, 0xbb, 0x85, 0x7a, 0x0e, 0x3f, 0x7d, 0x94, 0x32, 0x95, 0x55, 0xbb, + 0x30, 0xe6, 0xf9, 0xb2, 0x95, 0xbb, 0x34, 0xb9, 0xe6, 0xa1, 0x94, 0x4b, 0x9d, 0xbb, 0x33, 0xaf, + 0xe8, 0xa7, 0x7f, 0x07, 0x00, 0x00, 0xff, 0xff, 0x28, 0xf9, 0x31, 0x56, 0x62, 0x07, 0x00, 0x00, } diff --git a/protos/token/prover.proto b/protos/token/prover.proto index e9d67570b49..1c879d5e72f 100644 --- a/protos/token/prover.proto +++ b/protos/token/prover.proto @@ -35,6 +35,28 @@ message RecipientTransferShare { uint64 quantity = 2; } +// TokenOutput is used to specify a token returned by ListRequest +message TokenOutput { + // ID is used to uniquely identify the token + bytes id = 1; + + // Type is the type of the token + string type = 2; + + // Quantity represents the number for this type of token + uint64 quantity = 3; +} + +// UnspentTokens is used to hold the output of listRequest +message UnspentTokens { + repeated TokenOutput tokens = 1; +} + +// ListRequest is used to request a list of unspent tokens +message ListRequest { + bytes credential = 1; +} + // ImportRequest is used to request creation of imports message ImportRequest { // Credential contains information about the party who is requesting the operation @@ -82,6 +104,7 @@ message Command { oneof payload { ImportRequest import_request = 2; TransferRequest transfer_request = 3; + ListRequest list_request = 4; } } @@ -109,7 +132,7 @@ message CommandResponseHeader { bytes creator = 3; } -// Error reports an applicaton error +// Error reports an application error message Error { // Message associated with this response. string message = 1; @@ -127,6 +150,7 @@ message CommandResponse { oneof payload { Error err = 2; TokenTransaction token_transaction = 3; + UnspentTokens unspent_tokens = 4; } } diff --git a/token/server/manager.go b/token/server/manager.go index f52dd1bd9cb..7eb5edbbc9b 100644 --- a/token/server/manager.go +++ b/token/server/manager.go @@ -21,3 +21,9 @@ type Manager struct { func (t *Manager) GetIssuer(channel string, privateCredential, publicCredential []byte) (Issuer, error) { return &plain.Issuer{}, nil } + +// GetTransactor returns a Transactor bound to the passed channel and whose credential +// is the tuple (privateCredential, publicCredential). +func (t *Manager) GetTransactor(channel string, privateCredential, publicCredential []byte) (Transactor, error) { + panic("not implemented yet") +} diff --git a/token/server/mock/tms_manager.go b/token/server/mock/tms_manager.go index a43a166dab9..d43ce606acf 100644 --- a/token/server/mock/tms_manager.go +++ b/token/server/mock/tms_manager.go @@ -23,6 +23,21 @@ type TMSManager struct { result1 server.Issuer result2 error } + GetTransactorStub func(channel string, privateCredential, publicCredential []byte) (server.Transactor, error) + getTransactorMutex sync.RWMutex + getTransactorArgsForCall []struct { + channel string + privateCredential []byte + publicCredential []byte + } + getTransactorReturns struct { + result1 server.Transactor + result2 error + } + getTransactorReturnsOnCall map[int]struct { + result1 server.Transactor + result2 error + } invocations map[string][][]interface{} invocationsMutex sync.RWMutex } @@ -90,11 +105,76 @@ func (fake *TMSManager) GetIssuerReturnsOnCall(i int, result1 server.Issuer, res }{result1, result2} } +func (fake *TMSManager) GetTransactor(channel string, privateCredential []byte, publicCredential []byte) (server.Transactor, error) { + var privateCredentialCopy []byte + if privateCredential != nil { + privateCredentialCopy = make([]byte, len(privateCredential)) + copy(privateCredentialCopy, privateCredential) + } + var publicCredentialCopy []byte + if publicCredential != nil { + publicCredentialCopy = make([]byte, len(publicCredential)) + copy(publicCredentialCopy, publicCredential) + } + fake.getTransactorMutex.Lock() + ret, specificReturn := fake.getTransactorReturnsOnCall[len(fake.getTransactorArgsForCall)] + fake.getTransactorArgsForCall = append(fake.getTransactorArgsForCall, struct { + channel string + privateCredential []byte + publicCredential []byte + }{channel, privateCredentialCopy, publicCredentialCopy}) + fake.recordInvocation("GetTransactor", []interface{}{channel, privateCredentialCopy, publicCredentialCopy}) + fake.getTransactorMutex.Unlock() + if fake.GetTransactorStub != nil { + return fake.GetTransactorStub(channel, privateCredential, publicCredential) + } + if specificReturn { + return ret.result1, ret.result2 + } + return fake.getTransactorReturns.result1, fake.getTransactorReturns.result2 +} + +func (fake *TMSManager) GetTransactorCallCount() int { + fake.getTransactorMutex.RLock() + defer fake.getTransactorMutex.RUnlock() + return len(fake.getTransactorArgsForCall) +} + +func (fake *TMSManager) GetTransactorArgsForCall(i int) (string, []byte, []byte) { + fake.getTransactorMutex.RLock() + defer fake.getTransactorMutex.RUnlock() + return fake.getTransactorArgsForCall[i].channel, fake.getTransactorArgsForCall[i].privateCredential, fake.getTransactorArgsForCall[i].publicCredential +} + +func (fake *TMSManager) GetTransactorReturns(result1 server.Transactor, result2 error) { + fake.GetTransactorStub = nil + fake.getTransactorReturns = struct { + result1 server.Transactor + result2 error + }{result1, result2} +} + +func (fake *TMSManager) GetTransactorReturnsOnCall(i int, result1 server.Transactor, result2 error) { + fake.GetTransactorStub = nil + if fake.getTransactorReturnsOnCall == nil { + fake.getTransactorReturnsOnCall = make(map[int]struct { + result1 server.Transactor + result2 error + }) + } + fake.getTransactorReturnsOnCall[i] = struct { + result1 server.Transactor + result2 error + }{result1, result2} +} + func (fake *TMSManager) Invocations() map[string][][]interface{} { fake.invocationsMutex.RLock() defer fake.invocationsMutex.RUnlock() fake.getIssuerMutex.RLock() defer fake.getIssuerMutex.RUnlock() + fake.getTransactorMutex.RLock() + defer fake.getTransactorMutex.RUnlock() copiedInvocations := map[string][][]interface{}{} for key, value := range fake.invocations { copiedInvocations[key] = value diff --git a/token/server/mock/transactor.go b/token/server/mock/transactor.go new file mode 100644 index 00000000000..a3e46cf849f --- /dev/null +++ b/token/server/mock/transactor.go @@ -0,0 +1,94 @@ +// Code generated by counterfeiter. DO NOT EDIT. +package mock + +import ( + "sync" + + "github.com/hyperledger/fabric/protos/token" + "github.com/hyperledger/fabric/token/server" +) + +type Transactor struct { + ListUnspentTokensStub func() ([]*token.TokenOutput, error) + listUnspentTokensMutex sync.RWMutex + listUnspentTokensArgsForCall []struct{} + listUnspentTokensReturns struct { + result1 []*token.TokenOutput + result2 error + } + listUnspentTokensReturnsOnCall map[int]struct { + result1 []*token.TokenOutput + result2 error + } + invocations map[string][][]interface{} + invocationsMutex sync.RWMutex +} + +func (fake *Transactor) ListUnspentTokens() ([]*token.TokenOutput, error) { + fake.listUnspentTokensMutex.Lock() + ret, specificReturn := fake.listUnspentTokensReturnsOnCall[len(fake.listUnspentTokensArgsForCall)] + fake.listUnspentTokensArgsForCall = append(fake.listUnspentTokensArgsForCall, struct{}{}) + fake.recordInvocation("ListUnspentTokens", []interface{}{}) + fake.listUnspentTokensMutex.Unlock() + if fake.ListUnspentTokensStub != nil { + return fake.ListUnspentTokensStub() + } + if specificReturn { + return ret.result1, ret.result2 + } + return fake.listUnspentTokensReturns.result1, fake.listUnspentTokensReturns.result2 +} + +func (fake *Transactor) ListUnspentTokensCallCount() int { + fake.listUnspentTokensMutex.RLock() + defer fake.listUnspentTokensMutex.RUnlock() + return len(fake.listUnspentTokensArgsForCall) +} + +func (fake *Transactor) ListUnspentTokensReturns(result1 []*token.TokenOutput, result2 error) { + fake.ListUnspentTokensStub = nil + fake.listUnspentTokensReturns = struct { + result1 []*token.TokenOutput + result2 error + }{result1, result2} +} + +func (fake *Transactor) ListUnspentTokensReturnsOnCall(i int, result1 []*token.TokenOutput, result2 error) { + fake.ListUnspentTokensStub = nil + if fake.listUnspentTokensReturnsOnCall == nil { + fake.listUnspentTokensReturnsOnCall = make(map[int]struct { + result1 []*token.TokenOutput + result2 error + }) + } + fake.listUnspentTokensReturnsOnCall[i] = struct { + result1 []*token.TokenOutput + result2 error + }{result1, result2} +} + +func (fake *Transactor) Invocations() map[string][][]interface{} { + fake.invocationsMutex.RLock() + defer fake.invocationsMutex.RUnlock() + fake.listUnspentTokensMutex.RLock() + defer fake.listUnspentTokensMutex.RUnlock() + copiedInvocations := map[string][][]interface{}{} + for key, value := range fake.invocations { + copiedInvocations[key] = value + } + return copiedInvocations +} + +func (fake *Transactor) recordInvocation(key string, args []interface{}) { + fake.invocationsMutex.Lock() + defer fake.invocationsMutex.Unlock() + if fake.invocations == nil { + fake.invocations = map[string][][]interface{}{} + } + if fake.invocations[key] == nil { + fake.invocations[key] = [][]interface{}{} + } + fake.invocations[key] = append(fake.invocations[key], args) +} + +var _ server.Transactor = new(Transactor) diff --git a/token/server/prover.go b/token/server/prover.go index 2436fcb50c6..79735d1e27f 100644 --- a/token/server/prover.go +++ b/token/server/prover.go @@ -55,6 +55,8 @@ func (s *Prover) ProcessCommand(ctx context.Context, sc *token.SignedCommand) (* switch t := command.GetPayload().(type) { case *token.Command_ImportRequest: payload, err = s.RequestImport(ctx, command.Header, t.ImportRequest) + case *token.Command_ListRequest: + payload, err = s.ListUnspentTokens(ctx, command.Header, t.ListRequest) default: err = errors.Errorf("command type not recognized: %T", t) } @@ -82,6 +84,23 @@ func (s *Prover) RequestImport(ctx context.Context, header *token.Header, reques return &token.CommandResponse_TokenTransaction{TokenTransaction: tokenTransaction}, nil } +func (s *Prover) ListUnspentTokens(ctxt context.Context, header *token.Header, listRequest *token.ListRequest) (*token.CommandResponse_UnspentTokens, error) { + trasactor, err := s.TMSManager.GetTransactor(header.ChannelId, listRequest.Credential, header.Creator) + if err != nil { + return nil, err + } + + tokens, err := trasactor.ListUnspentTokens() + if err != nil { + return nil, err + } + + return &token.CommandResponse_UnspentTokens{ + UnspentTokens: &token.UnspentTokens{ + Tokens: tokens, + }}, nil +} + func (s *Prover) ValidateHeader(header *token.Header) error { if header == nil { return errors.New("command header is required") diff --git a/token/server/prover_test.go b/token/server/prover_test.go index 2d5d2a97fc8..fe00f9a1455 100644 --- a/token/server/prover_test.go +++ b/token/server/prover_test.go @@ -26,17 +26,21 @@ var _ = Describe("Prover", func() { fakePolicyChecker *mock.PolicyChecker fakeMarshaler *mock.Marshaler fakeIssuer *mock.Issuer + fakeTransactor *mock.Transactor fakeTMSManager *mock.TMSManager prover *server.Prover - importRequest *token.ImportRequest - command *token.Command - marshaledCommand []byte - signedCommand *token.SignedCommand - + importRequest *token.ImportRequest + command *token.Command + marshaledCommand []byte + signedCommand *token.SignedCommand tokenTransaction *token.TokenTransaction marshaledResponse *token.SignedCommandResponse + + listRequest *token.ListRequest + unspentTokens *token.UnspentTokens + transactorTokens []*token.TokenOutput ) BeforeEach(func() { @@ -60,8 +64,18 @@ var _ = Describe("Prover", func() { fakeIssuer = &mock.Issuer{} fakeIssuer.RequestImportReturns(tokenTransaction, nil) + transactorTokens = []*token.TokenOutput{ + {Id: []byte("idaz"), Type: "typeaz", Quantity: 135}, + {Id: []byte("idby"), Type: "typeby", Quantity: 79}, + } + unspentTokens = &token.UnspentTokens{Tokens: transactorTokens} + + fakeTransactor = &mock.Transactor{} + fakeTransactor.ListUnspentTokensReturns(transactorTokens, nil) + fakeTMSManager = &mock.TMSManager{} fakeTMSManager.GetIssuerReturns(fakeIssuer, nil) + fakeTMSManager.GetTransactorReturns(fakeTransactor, nil) marshaledResponse = &token.SignedCommandResponse{Response: []byte("signed-command-response")} fakeMarshaler = &mock.Marshaler{} @@ -96,6 +110,10 @@ var _ = Describe("Prover", func() { Command: marshaledCommand, Signature: []byte("command-signature"), } + + listRequest = &token.ListRequest{ + Credential: []byte("credential"), + } }) Describe("ProcessCommand", func() { @@ -109,19 +127,6 @@ var _ = Describe("Prover", func() { Expect(proto.Equal(c, command)).To(BeTrue()) }) - It("returns a signed command response", func() { - resp, err := prover.ProcessCommand(context.Background(), signedCommand) - Expect(err).NotTo(HaveOccurred()) - Expect(resp).To(Equal(marshaledResponse)) - - Expect(fakeMarshaler.MarshalCommandResponseCallCount()).To(Equal(1)) - cmd, payload := fakeMarshaler.MarshalCommandResponseArgsForCall(0) - Expect(cmd).To(Equal(marshaledCommand)) - Expect(payload).To(Equal(&token.CommandResponse_TokenTransaction{ - TokenTransaction: tokenTransaction, - })) - }) - Context("when the access control check fails", func() { BeforeEach(func() { fakePolicyChecker.CheckReturns(errors.New("banana-time")) @@ -268,6 +273,54 @@ var _ = Describe("Prover", func() { }) }) + Describe("Process RequestImport command", func() { + It("returns a signed command response", func() { + resp, err := prover.ProcessCommand(context.Background(), signedCommand) + Expect(err).NotTo(HaveOccurred()) + Expect(resp).To(Equal(marshaledResponse)) + + Expect(fakeMarshaler.MarshalCommandResponseCallCount()).To(Equal(1)) + cmd, payload := fakeMarshaler.MarshalCommandResponseArgsForCall(0) + Expect(cmd).To(Equal(marshaledCommand)) + Expect(payload).To(Equal(&token.CommandResponse_TokenTransaction{ + TokenTransaction: tokenTransaction, + })) + }) + }) + + Describe("Process ListUnspentTokens command", func() { + BeforeEach(func() { + command = &token.Command{ + Header: &token.Header{ + ChannelId: "channel-id", + Creator: []byte("creator"), + Nonce: []byte("nonce"), + }, + Payload: &token.Command_ListRequest{ + ListRequest: listRequest, + }, + } + marshaledCommand = ProtoMarshal(command) + signedCommand = &token.SignedCommand{ + Command: marshaledCommand, + Signature: []byte("command-signature"), + } + }) + + It("returns a signed command response", func() { + resp, err := prover.ProcessCommand(context.Background(), signedCommand) + Expect(err).NotTo(HaveOccurred()) + Expect(resp).To(Equal(marshaledResponse)) + + Expect(fakeMarshaler.MarshalCommandResponseCallCount()).To(Equal(1)) + cmd, payload := fakeMarshaler.MarshalCommandResponseArgsForCall(0) + Expect(cmd).To(Equal(marshaledCommand)) + Expect(payload).To(Equal(&token.CommandResponse_UnspentTokens{ + UnspentTokens: unspentTokens, + })) + }) + }) + Describe("RequestImport", func() { It("gets an issuer", func() { _, err := prover.RequestImport(context.Background(), command.Header, importRequest) @@ -483,4 +536,49 @@ var _ = Describe("Prover", func() { }) }) }) + + Describe("ListUnspentTokens", func() { + It("gets a transactor", func() { + _, err := prover.ListUnspentTokens(context.Background(), command.Header, listRequest) + Expect(err).NotTo(HaveOccurred()) + + Expect(fakeTMSManager.GetTransactorCallCount()).To(Equal(1)) + channel, cred, creator := fakeTMSManager.GetTransactorArgsForCall(0) + Expect(channel).To(Equal("channel-id")) + Expect(cred).To(Equal([]byte("credential"))) + Expect(creator).To(Equal([]byte("creator"))) + }) + + It("uses the transactor to list unspent tokens", func() { + resp, err := prover.ListUnspentTokens(context.Background(), command.Header, listRequest) + Expect(err).NotTo(HaveOccurred()) + Expect(resp).To(Equal(&token.CommandResponse_UnspentTokens{ + UnspentTokens: unspentTokens, + })) + + Expect(fakeTransactor.ListUnspentTokensCallCount()).To(Equal(1)) + }) + + Context("when the TMS manager fails to get a transactor", func() { + BeforeEach(func() { + fakeTMSManager.GetTransactorReturns(nil, errors.New("pineapple")) + }) + + It("returns the error", func() { + _, err := prover.ListUnspentTokens(context.Background(), command.Header, listRequest) + Expect(err).To(MatchError("pineapple")) + }) + }) + + Context("when the transactor fails to list tokens", func() { + BeforeEach(func() { + fakeTransactor.ListUnspentTokensReturns(nil, errors.New("pineapple")) + }) + + It("returns the error", func() { + _, err := prover.ListUnspentTokens(context.Background(), command.Header, listRequest) + Expect(err).To(MatchError("pineapple")) + }) + }) + }) }) diff --git a/token/server/tms.go b/token/server/tms.go index d07ea4f96cf..baf3708c986 100644 --- a/token/server/tms.go +++ b/token/server/tms.go @@ -15,10 +15,22 @@ type Issuer interface { RequestImport(tokensToIssue []*token.TokenToIssue) (*token.TokenTransaction, error) } +//go:generate counterfeiter -o mock/transactor.go -fake-name Transactor . Transactor + +// Transactor allows to operate on issued tokens +type Transactor interface { + // ListUnspentTokens returns a slice of unspent tokens owned by this transactor + ListUnspentTokens() ([]*token.TokenOutput, error) +} + //go:generate counterfeiter -o mock/tms_manager.go -fake-name TMSManager . TMSManager type TMSManager interface { // GetIssuer returns an Issuer bound to the passed channel and whose credential // is the tuple (privateCredential, publicCredential). GetIssuer(channel string, privateCredential, publicCredential []byte) (Issuer, error) + + // GetTransactor returns a Transactor bound to the passed channel and whose credential + // is the tuple (privateCredential, publicCredential). + GetTransactor(channel string, privateCredential, publicCredential []byte) (Transactor, error) }