diff --git a/node/app/node.go b/node/app/node.go index ad542b3..f6f2ddb 100644 --- a/node/app/node.go +++ b/node/app/node.go @@ -7,6 +7,7 @@ import ( "source.quilibrium.com/quilibrium/monorepo/node/consensus" "source.quilibrium.com/quilibrium/monorepo/node/execution" "source.quilibrium.com/quilibrium/monorepo/node/execution/ceremony" + "source.quilibrium.com/quilibrium/monorepo/node/keys" "source.quilibrium.com/quilibrium/monorepo/node/p2p" "source.quilibrium.com/quilibrium/monorepo/node/store" ) @@ -14,6 +15,7 @@ import ( type Node struct { logger *zap.Logger clockStore store.ClockStore + keyManager keys.KeyManager pubSub p2p.PubSub execEngines map[string]execution.ExecutionEngine engine consensus.ConsensusEngine @@ -22,6 +24,7 @@ type Node struct { func newNode( logger *zap.Logger, clockStore store.ClockStore, + keyManager keys.KeyManager, pubSub p2p.PubSub, ceremonyExecutionEngine *ceremony.CeremonyExecutionEngine, engine consensus.ConsensusEngine, @@ -38,6 +41,7 @@ func newNode( return &Node{ logger, clockStore, + keyManager, pubSub, execEngines, engine, @@ -71,6 +75,10 @@ func (n *Node) GetClockStore() store.ClockStore { return n.clockStore } +func (n *Node) GetKeyManager() keys.KeyManager { + return n.keyManager +} + func (n *Node) GetPubSub() p2p.PubSub { return n.pubSub } diff --git a/node/app/wire_gen.go b/node/app/wire_gen.go index 9c6d604..4a1e7e3 100644 --- a/node/app/wire_gen.go +++ b/node/app/wire_gen.go @@ -26,16 +26,16 @@ func NewNode(configConfig *config.Config) (*Node, error) { dbConfig := configConfig.DB db := store.NewPebbleDB(dbConfig) pebbleClockStore := store.NewPebbleClockStore(db, zapLogger) + keyConfig := configConfig.Key + fileKeyManager := keys.NewFileKeyManager(keyConfig, zapLogger) p2PConfig := configConfig.P2P blossomSub := p2p.NewBlossomSub(p2PConfig, zapLogger) engineConfig := configConfig.Engine - keyConfig := configConfig.Key - fileKeyManager := keys.NewFileKeyManager(keyConfig, zapLogger) pebbleKeyStore := store.NewPebbleKeyStore(db, zapLogger) ceremonyDataClockConsensusEngine := ceremony.NewCeremonyDataClockConsensusEngine(engineConfig, zapLogger, fileKeyManager, pebbleClockStore, pebbleKeyStore, blossomSub) ceremonyExecutionEngine := ceremony2.NewCeremonyExecutionEngine(zapLogger, ceremonyDataClockConsensusEngine, engineConfig, fileKeyManager, blossomSub, pebbleClockStore, pebbleKeyStore) masterClockConsensusEngine := master.NewMasterClockConsensusEngine(engineConfig, zapLogger, pebbleClockStore, fileKeyManager, blossomSub) - node, err := newNode(zapLogger, pebbleClockStore, blossomSub, ceremonyExecutionEngine, masterClockConsensusEngine) + node, err := newNode(zapLogger, pebbleClockStore, fileKeyManager, blossomSub, ceremonyExecutionEngine, masterClockConsensusEngine) if err != nil { return nil, err } diff --git a/node/main.go b/node/main.go index 0588fad..b3a99d0 100644 --- a/node/main.go +++ b/node/main.go @@ -92,6 +92,7 @@ func main() { nodeConfig.ListenRestMultiaddr, node.GetLogger(), node.GetClockStore(), + node.GetKeyManager(), node.GetPubSub(), node.GetExecutionEngines(), ) diff --git a/node/protobufs/node.pb.go b/node/protobufs/node.pb.go index 8bc0823..9b20dc9 100644 --- a/node/protobufs/node.pb.go +++ b/node/protobufs/node.pb.go @@ -560,6 +560,113 @@ func (x *NetworkInfoResponse) GetNetworkInfo() []*NetworkInfo { return nil } +type GetTokenInfoRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *GetTokenInfoRequest) Reset() { + *x = GetTokenInfoRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_node_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetTokenInfoRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetTokenInfoRequest) ProtoMessage() {} + +func (x *GetTokenInfoRequest) ProtoReflect() protoreflect.Message { + mi := &file_node_proto_msgTypes[10] + 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 GetTokenInfoRequest.ProtoReflect.Descriptor instead. +func (*GetTokenInfoRequest) Descriptor() ([]byte, []int) { + return file_node_proto_rawDescGZIP(), []int{10} +} + +type TokenInfoResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Total active token supply, as a 256 bit integer representing maximum + // divisble units. 1 QUIL = 8000000000 units, 50 QUIL would be represented by + // 0x0000000000000000000000000000000000000000000000000000005D21DBA000 + ConfirmedTokenSupply []byte `protobuf:"bytes,1,opt,name=confirmed_token_supply,json=confirmedTokenSupply,proto3" json:"confirmed_token_supply,omitempty"` + // Total token supply, including unconfirmed frame data, as a 256 bit integer. + UnconfirmedTokenSupply []byte `protobuf:"bytes,2,opt,name=unconfirmed_token_supply,json=unconfirmedTokenSupply,proto3" json:"unconfirmed_token_supply,omitempty"` + // The total number of tokens owned by the prover address associated with the + // node. + OwnedTokens []byte `protobuf:"bytes,3,opt,name=owned_tokens,json=ownedTokens,proto3" json:"owned_tokens,omitempty"` +} + +func (x *TokenInfoResponse) Reset() { + *x = TokenInfoResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_node_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TokenInfoResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TokenInfoResponse) ProtoMessage() {} + +func (x *TokenInfoResponse) ProtoReflect() protoreflect.Message { + mi := &file_node_proto_msgTypes[11] + 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 TokenInfoResponse.ProtoReflect.Descriptor instead. +func (*TokenInfoResponse) Descriptor() ([]byte, []int) { + return file_node_proto_rawDescGZIP(), []int{11} +} + +func (x *TokenInfoResponse) GetConfirmedTokenSupply() []byte { + if x != nil { + return x.ConfirmedTokenSupply + } + return nil +} + +func (x *TokenInfoResponse) GetUnconfirmedTokenSupply() []byte { + if x != nil { + return x.UnconfirmedTokenSupply + } + return nil +} + +func (x *TokenInfoResponse) GetOwnedTokens() []byte { + if x != nil { + return x.OwnedTokens + } + return nil +} + var File_node_proto protoreflect.FileDescriptor var file_node_proto_rawDesc = []byte{ @@ -631,7 +738,19 @@ var file_node_proto_rawDesc = []byte{ 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0b, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x6e, 0x66, 0x6f, - 0x32, 0xaf, 0x03, 0x0a, 0x0b, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x22, 0x15, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x49, 0x6e, 0x66, 0x6f, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xa6, 0x01, 0x0a, 0x11, 0x54, 0x6f, 0x6b, 0x65, + 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, + 0x16, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, + 0x5f, 0x73, 0x75, 0x70, 0x70, 0x6c, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x14, 0x63, + 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x65, 0x64, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x75, 0x70, + 0x70, 0x6c, 0x79, 0x12, 0x38, 0x0a, 0x18, 0x75, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, + 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x73, 0x75, 0x70, 0x70, 0x6c, 0x79, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x16, 0x75, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, + 0x65, 0x64, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x75, 0x70, 0x70, 0x6c, 0x79, 0x12, 0x21, 0x0a, + 0x0c, 0x6f, 0x77, 0x6e, 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x6f, 0x77, 0x6e, 0x65, 0x64, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, + 0x32, 0x99, 0x04, 0x0a, 0x0b, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x5f, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x29, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, @@ -658,11 +777,17 @@ var file_node_proto_rawDesc = []byte{ 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x42, 0x3a, 0x5a, 0x38, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x71, 0x75, 0x69, - 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x71, 0x75, 0x69, 0x6c, - 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2f, 0x6d, 0x6f, 0x6e, 0x6f, 0x72, 0x65, 0x70, 0x6f, 0x2f, - 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x73, 0x62, 0x06, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x73, 0x65, 0x12, 0x68, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x49, 0x6e, + 0x66, 0x6f, 0x12, 0x2c, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, + 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x47, 0x65, 0x74, + 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x2a, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, 0x2e, 0x6e, 0x6f, + 0x64, 0x65, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, + 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x3a, 0x5a, 0x38, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, + 0x6d, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x71, 0x75, 0x69, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x75, 0x6d, + 0x2f, 0x6d, 0x6f, 0x6e, 0x6f, 0x72, 0x65, 0x70, 0x6f, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -677,7 +802,7 @@ func file_node_proto_rawDescGZIP() []byte { return file_node_proto_rawDescData } -var file_node_proto_msgTypes = make([]protoimpl.MessageInfo, 10) +var file_node_proto_msgTypes = make([]protoimpl.MessageInfo, 12) var file_node_proto_goTypes = []interface{}{ (*GetFramesRequest)(nil), // 0: quilibrium.node.node.pb.GetFramesRequest (*GetFrameInfoRequest)(nil), // 1: quilibrium.node.node.pb.GetFrameInfoRequest @@ -689,11 +814,13 @@ var file_node_proto_goTypes = []interface{}{ (*PeerInfoResponse)(nil), // 7: quilibrium.node.node.pb.PeerInfoResponse (*NetworkInfo)(nil), // 8: quilibrium.node.node.pb.NetworkInfo (*NetworkInfoResponse)(nil), // 9: quilibrium.node.node.pb.NetworkInfoResponse - (*ClockFrame)(nil), // 10: quilibrium.node.clock.pb.ClockFrame + (*GetTokenInfoRequest)(nil), // 10: quilibrium.node.node.pb.GetTokenInfoRequest + (*TokenInfoResponse)(nil), // 11: quilibrium.node.node.pb.TokenInfoResponse + (*ClockFrame)(nil), // 12: quilibrium.node.clock.pb.ClockFrame } var file_node_proto_depIdxs = []int32{ - 10, // 0: quilibrium.node.node.pb.FramesResponse.truncated_clock_frames:type_name -> quilibrium.node.clock.pb.ClockFrame - 10, // 1: quilibrium.node.node.pb.FrameInfoResponse.clock_frame:type_name -> quilibrium.node.clock.pb.ClockFrame + 12, // 0: quilibrium.node.node.pb.FramesResponse.truncated_clock_frames:type_name -> quilibrium.node.clock.pb.ClockFrame + 12, // 1: quilibrium.node.node.pb.FrameInfoResponse.clock_frame:type_name -> quilibrium.node.clock.pb.ClockFrame 6, // 2: quilibrium.node.node.pb.PeerInfoResponse.peer_info:type_name -> quilibrium.node.node.pb.PeerInfo 6, // 3: quilibrium.node.node.pb.PeerInfoResponse.uncooperative_peer_info:type_name -> quilibrium.node.node.pb.PeerInfo 8, // 4: quilibrium.node.node.pb.NetworkInfoResponse.network_info:type_name -> quilibrium.node.node.pb.NetworkInfo @@ -701,12 +828,14 @@ var file_node_proto_depIdxs = []int32{ 1, // 6: quilibrium.node.node.pb.NodeService.GetFrameInfo:input_type -> quilibrium.node.node.pb.GetFrameInfoRequest 2, // 7: quilibrium.node.node.pb.NodeService.GetPeerInfo:input_type -> quilibrium.node.node.pb.GetPeerInfoRequest 3, // 8: quilibrium.node.node.pb.NodeService.GetNetworkInfo:input_type -> quilibrium.node.node.pb.GetNetworkInfoRequest - 4, // 9: quilibrium.node.node.pb.NodeService.GetFrames:output_type -> quilibrium.node.node.pb.FramesResponse - 5, // 10: quilibrium.node.node.pb.NodeService.GetFrameInfo:output_type -> quilibrium.node.node.pb.FrameInfoResponse - 7, // 11: quilibrium.node.node.pb.NodeService.GetPeerInfo:output_type -> quilibrium.node.node.pb.PeerInfoResponse - 9, // 12: quilibrium.node.node.pb.NodeService.GetNetworkInfo:output_type -> quilibrium.node.node.pb.NetworkInfoResponse - 9, // [9:13] is the sub-list for method output_type - 5, // [5:9] is the sub-list for method input_type + 10, // 9: quilibrium.node.node.pb.NodeService.GetTokenInfo:input_type -> quilibrium.node.node.pb.GetTokenInfoRequest + 4, // 10: quilibrium.node.node.pb.NodeService.GetFrames:output_type -> quilibrium.node.node.pb.FramesResponse + 5, // 11: quilibrium.node.node.pb.NodeService.GetFrameInfo:output_type -> quilibrium.node.node.pb.FrameInfoResponse + 7, // 12: quilibrium.node.node.pb.NodeService.GetPeerInfo:output_type -> quilibrium.node.node.pb.PeerInfoResponse + 9, // 13: quilibrium.node.node.pb.NodeService.GetNetworkInfo:output_type -> quilibrium.node.node.pb.NetworkInfoResponse + 11, // 14: quilibrium.node.node.pb.NodeService.GetTokenInfo:output_type -> quilibrium.node.node.pb.TokenInfoResponse + 10, // [10:15] is the sub-list for method output_type + 5, // [5:10] 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 @@ -839,6 +968,30 @@ func file_node_proto_init() { return nil } } + file_node_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetTokenInfoRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_node_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TokenInfoResponse); 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{ @@ -846,7 +999,7 @@ func file_node_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_node_proto_rawDesc, NumEnums: 0, - NumMessages: 10, + NumMessages: 12, NumExtensions: 0, NumServices: 1, }, diff --git a/node/protobufs/node.pb.gw.go b/node/protobufs/node.pb.gw.go index 78fe621..417d8dc 100644 --- a/node/protobufs/node.pb.gw.go +++ b/node/protobufs/node.pb.gw.go @@ -167,6 +167,40 @@ func local_request_NodeService_GetNetworkInfo_0(ctx context.Context, marshaler r } +func request_NodeService_GetTokenInfo_0(ctx context.Context, marshaler runtime.Marshaler, client NodeServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GetTokenInfoRequest + var metadata runtime.ServerMetadata + + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.GetTokenInfo(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_NodeService_GetTokenInfo_0(ctx context.Context, marshaler runtime.Marshaler, server NodeServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GetTokenInfoRequest + var metadata runtime.ServerMetadata + + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.GetTokenInfo(ctx, &protoReq) + return msg, metadata, err + +} + // RegisterNodeServiceHandlerServer registers the http handlers for service NodeService to "mux". // UnaryRPC :call NodeServiceServer directly. // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. @@ -273,6 +307,31 @@ func RegisterNodeServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux }) + mux.Handle("POST", pattern_NodeService_GetTokenInfo_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + var err error + var annotatedContext context.Context + annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/quilibrium.node.node.pb.NodeService/GetTokenInfo", runtime.WithHTTPPathPattern("/quilibrium.node.node.pb.NodeService/GetTokenInfo")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_NodeService_GetTokenInfo_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + + forward_NodeService_GetTokenInfo_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -402,6 +461,28 @@ func RegisterNodeServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux }) + mux.Handle("POST", pattern_NodeService_GetTokenInfo_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + var err error + var annotatedContext context.Context + annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/quilibrium.node.node.pb.NodeService/GetTokenInfo", runtime.WithHTTPPathPattern("/quilibrium.node.node.pb.NodeService/GetTokenInfo")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_NodeService_GetTokenInfo_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + + forward_NodeService_GetTokenInfo_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -413,6 +494,8 @@ var ( pattern_NodeService_GetPeerInfo_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"quilibrium.node.node.pb.NodeService", "GetPeerInfo"}, "")) pattern_NodeService_GetNetworkInfo_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"quilibrium.node.node.pb.NodeService", "GetNetworkInfo"}, "")) + + pattern_NodeService_GetTokenInfo_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"quilibrium.node.node.pb.NodeService", "GetTokenInfo"}, "")) ) var ( @@ -423,4 +506,6 @@ var ( forward_NodeService_GetPeerInfo_0 = runtime.ForwardResponseMessage forward_NodeService_GetNetworkInfo_0 = runtime.ForwardResponseMessage + + forward_NodeService_GetTokenInfo_0 = runtime.ForwardResponseMessage ) diff --git a/node/protobufs/node.proto b/node/protobufs/node.proto index ffe7209..6862a9c 100644 --- a/node/protobufs/node.proto +++ b/node/protobufs/node.proto @@ -53,9 +53,24 @@ message NetworkInfoResponse { repeated NetworkInfo network_info = 1; } +message GetTokenInfoRequest {} + +message TokenInfoResponse { + // Total active token supply, as a 256 bit integer representing maximum + // divisble units. 1 QUIL = 8000000000 units, 50 QUIL would be represented by + // 0x0000000000000000000000000000000000000000000000000000005D21DBA000 + bytes confirmed_token_supply = 1; + // Total token supply, including unconfirmed frame data, as a 256 bit integer. + bytes unconfirmed_token_supply = 2; + // The total number of tokens owned by the prover address associated with the + // node. + bytes owned_tokens = 3; +} + service NodeService { rpc GetFrames(GetFramesRequest) returns (FramesResponse); rpc GetFrameInfo(GetFrameInfoRequest) returns (FrameInfoResponse); rpc GetPeerInfo(GetPeerInfoRequest) returns (PeerInfoResponse); rpc GetNetworkInfo(GetNetworkInfoRequest) returns (NetworkInfoResponse); + rpc GetTokenInfo(GetTokenInfoRequest) returns (TokenInfoResponse); } \ No newline at end of file diff --git a/node/protobufs/node_grpc.pb.go b/node/protobufs/node_grpc.pb.go index 758b795..a0b2524 100644 --- a/node/protobufs/node_grpc.pb.go +++ b/node/protobufs/node_grpc.pb.go @@ -23,6 +23,7 @@ const ( NodeService_GetFrameInfo_FullMethodName = "/quilibrium.node.node.pb.NodeService/GetFrameInfo" NodeService_GetPeerInfo_FullMethodName = "/quilibrium.node.node.pb.NodeService/GetPeerInfo" NodeService_GetNetworkInfo_FullMethodName = "/quilibrium.node.node.pb.NodeService/GetNetworkInfo" + NodeService_GetTokenInfo_FullMethodName = "/quilibrium.node.node.pb.NodeService/GetTokenInfo" ) // NodeServiceClient is the client API for NodeService service. @@ -33,6 +34,7 @@ type NodeServiceClient interface { GetFrameInfo(ctx context.Context, in *GetFrameInfoRequest, opts ...grpc.CallOption) (*FrameInfoResponse, error) GetPeerInfo(ctx context.Context, in *GetPeerInfoRequest, opts ...grpc.CallOption) (*PeerInfoResponse, error) GetNetworkInfo(ctx context.Context, in *GetNetworkInfoRequest, opts ...grpc.CallOption) (*NetworkInfoResponse, error) + GetTokenInfo(ctx context.Context, in *GetTokenInfoRequest, opts ...grpc.CallOption) (*TokenInfoResponse, error) } type nodeServiceClient struct { @@ -79,6 +81,15 @@ func (c *nodeServiceClient) GetNetworkInfo(ctx context.Context, in *GetNetworkIn return out, nil } +func (c *nodeServiceClient) GetTokenInfo(ctx context.Context, in *GetTokenInfoRequest, opts ...grpc.CallOption) (*TokenInfoResponse, error) { + out := new(TokenInfoResponse) + err := c.cc.Invoke(ctx, NodeService_GetTokenInfo_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // NodeServiceServer is the server API for NodeService service. // All implementations must embed UnimplementedNodeServiceServer // for forward compatibility @@ -87,6 +98,7 @@ type NodeServiceServer interface { GetFrameInfo(context.Context, *GetFrameInfoRequest) (*FrameInfoResponse, error) GetPeerInfo(context.Context, *GetPeerInfoRequest) (*PeerInfoResponse, error) GetNetworkInfo(context.Context, *GetNetworkInfoRequest) (*NetworkInfoResponse, error) + GetTokenInfo(context.Context, *GetTokenInfoRequest) (*TokenInfoResponse, error) mustEmbedUnimplementedNodeServiceServer() } @@ -106,6 +118,9 @@ func (UnimplementedNodeServiceServer) GetPeerInfo(context.Context, *GetPeerInfoR func (UnimplementedNodeServiceServer) GetNetworkInfo(context.Context, *GetNetworkInfoRequest) (*NetworkInfoResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method GetNetworkInfo not implemented") } +func (UnimplementedNodeServiceServer) GetTokenInfo(context.Context, *GetTokenInfoRequest) (*TokenInfoResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetTokenInfo not implemented") +} func (UnimplementedNodeServiceServer) mustEmbedUnimplementedNodeServiceServer() {} // UnsafeNodeServiceServer may be embedded to opt out of forward compatibility for this service. @@ -191,6 +206,24 @@ func _NodeService_GetNetworkInfo_Handler(srv interface{}, ctx context.Context, d return interceptor(ctx, in, info, handler) } +func _NodeService_GetTokenInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetTokenInfoRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NodeServiceServer).GetTokenInfo(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: NodeService_GetTokenInfo_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NodeServiceServer).GetTokenInfo(ctx, req.(*GetTokenInfoRequest)) + } + return interceptor(ctx, in, info, handler) +} + // NodeService_ServiceDesc is the grpc.ServiceDesc for NodeService service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -214,6 +247,10 @@ var NodeService_ServiceDesc = grpc.ServiceDesc{ MethodName: "GetNetworkInfo", Handler: _NodeService_GetNetworkInfo_Handler, }, + { + MethodName: "GetTokenInfo", + Handler: _NodeService_GetTokenInfo_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "node.proto", diff --git a/node/rpc/rpc_server.go b/node/rpc/rpc_server.go index 41e1e2c..5b643be 100644 --- a/node/rpc/rpc_server.go +++ b/node/rpc/rpc_server.go @@ -3,9 +3,11 @@ package rpc import ( "bytes" "context" + "math/big" "net/http" "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" + "github.com/iden3/go-iden3-crypto/poseidon" "github.com/multiformats/go-multiaddr" mn "github.com/multiformats/go-multiaddr/net" "github.com/pkg/errors" @@ -14,9 +16,12 @@ import ( "google.golang.org/grpc/credentials/insecure" "google.golang.org/grpc/reflection" "source.quilibrium.com/quilibrium/monorepo/node/execution" + "source.quilibrium.com/quilibrium/monorepo/node/execution/ceremony/application" + "source.quilibrium.com/quilibrium/monorepo/node/keys" "source.quilibrium.com/quilibrium/monorepo/node/p2p" "source.quilibrium.com/quilibrium/monorepo/node/protobufs" "source.quilibrium.com/quilibrium/monorepo/node/store" + "source.quilibrium.com/quilibrium/monorepo/node/tries" ) type RPCServer struct { @@ -25,6 +30,7 @@ type RPCServer struct { listenAddrHTTP string logger *zap.Logger clockStore store.ClockStore + keyManager keys.KeyManager pubSub p2p.PubSub executionEngines []execution.ExecutionEngine } @@ -209,11 +215,162 @@ func (r *RPCServer) GetPeerInfo( return resp, nil } +func (r *RPCServer) GetTokenInfo( + ctx context.Context, + req *protobufs.GetTokenInfoRequest, +) (*protobufs.TokenInfoResponse, error) { + provingKey, err := r.keyManager.GetRawKey( + "default-proving-key", + ) + if err != nil { + return nil, errors.Wrap(err, "get token info") + } + + addr, err := poseidon.HashBytes(provingKey.PublicKey) + if err != nil { + panic(err) + } + + addrBytes := addr.Bytes() + addrBytes = append(make([]byte, 32-len(addrBytes)), addrBytes...) + + frame, err := r.clockStore.GetLatestDataClockFrame( + application.CEREMONY_ADDRESS, + nil, + ) + if err != nil { + return nil, errors.Wrap(err, "get token info") + } + + confirmed, err := application.MaterializeApplicationFromFrame(frame) + if err != nil { + return nil, errors.Wrap(err, "get token info") + } + + confirmedTotal := new(big.Int) + unconfirmedTotal := new(big.Int) + ownedTotal := new(big.Int) + if confirmed.RewardTrie.Root == nil || + (confirmed.RewardTrie.Root.External == nil && + confirmed.RewardTrie.Root.Internal == nil) { + return &protobufs.TokenInfoResponse{ + ConfirmedTokenSupply: confirmedTotal.FillBytes(make([]byte, 32)), + UnconfirmedTokenSupply: unconfirmedTotal.FillBytes(make([]byte, 32)), + OwnedTokens: ownedTotal.FillBytes(make([]byte, 32)), + }, nil + } + + limbs := []*tries.RewardInternalNode{} + if confirmed.RewardTrie.Root.Internal != nil { + limbs = append(limbs, confirmed.RewardTrie.Root.Internal) + } else { + confirmedTotal = confirmedTotal.Add( + confirmedTotal, + new(big.Int).SetUint64(confirmed.RewardTrie.Root.External.Total), + ) + if bytes.Equal( + confirmed.RewardTrie.Root.External.Key, + addrBytes, + ) { + ownedTotal = ownedTotal.Add( + ownedTotal, + new(big.Int).SetUint64(confirmed.RewardTrie.Root.External.Total), + ) + } + } + + for len(limbs) != 0 { + nextLimbs := []*tries.RewardInternalNode{} + for _, limb := range limbs { + for _, child := range limb.Child { + child := child + if child.Internal != nil { + nextLimbs = append(nextLimbs, child.Internal) + } else { + confirmedTotal = confirmedTotal.Add( + confirmedTotal, + new(big.Int).SetUint64(child.External.Total), + ) + if bytes.Equal( + child.External.Key, + addrBytes, + ) { + ownedTotal = ownedTotal.Add( + ownedTotal, + new(big.Int).SetUint64(child.External.Total), + ) + } + } + } + } + limbs = nextLimbs + } + + candidateFrame, err := r.clockStore.GetHighestCandidateDataClockFrame( + application.CEREMONY_ADDRESS, + ) + if err != nil { + return nil, errors.Wrap(err, "get token info") + } + + unconfirmed, err := application.MaterializeApplicationFromFrame( + candidateFrame, + ) + if err != nil { + return nil, errors.Wrap(err, "get token info") + } + + limbs = []*tries.RewardInternalNode{} + if unconfirmed.RewardTrie.Root.Internal != nil { + limbs = append(limbs, unconfirmed.RewardTrie.Root.Internal) + } else { + unconfirmedTotal = unconfirmedTotal.Add( + unconfirmedTotal, + new(big.Int).SetUint64(unconfirmed.RewardTrie.Root.External.Total), + ) + } + + for len(limbs) != 0 { + nextLimbs := []*tries.RewardInternalNode{} + for _, limb := range limbs { + for _, child := range limb.Child { + child := child + if child.Internal != nil { + nextLimbs = append(nextLimbs, child.Internal) + } else { + unconfirmedTotal = unconfirmedTotal.Add( + unconfirmedTotal, + new(big.Int).SetUint64(child.External.Total), + ) + } + } + } + limbs = nextLimbs + } + + // 1 QUIL = 0x1DCD65000 units + conversionFactor, ok := new(big.Int).SetString("1DCD65000", 16) + if !ok { + return nil, errors.Wrap(err, "get token info") + } + + confirmedTotal = confirmedTotal.Mul(confirmedTotal, conversionFactor) + unconfirmedTotal = unconfirmedTotal.Mul(unconfirmedTotal, conversionFactor) + ownedTotal = ownedTotal.Mul(ownedTotal, conversionFactor) + + return &protobufs.TokenInfoResponse{ + ConfirmedTokenSupply: confirmedTotal.FillBytes(make([]byte, 32)), + UnconfirmedTokenSupply: unconfirmedTotal.FillBytes(make([]byte, 32)), + OwnedTokens: ownedTotal.FillBytes(make([]byte, 32)), + }, nil +} + func NewRPCServer( listenAddrGRPC string, listenAddrHTTP string, logger *zap.Logger, clockStore store.ClockStore, + keyManager keys.KeyManager, pubSub p2p.PubSub, executionEngines []execution.ExecutionEngine, ) (*RPCServer, error) { @@ -222,6 +379,7 @@ func NewRPCServer( listenAddrHTTP: listenAddrHTTP, logger: logger, clockStore: clockStore, + keyManager: keyManager, pubSub: pubSub, executionEngines: executionEngines, }, nil diff --git a/node/store/clock.go b/node/store/clock.go index a1e0345..6df79cd 100644 --- a/node/store/clock.go +++ b/node/store/clock.go @@ -90,6 +90,9 @@ type ClockStore interface { fromFrameNumber uint64, toFrameNumber uint64, ) error + GetHighestCandidateDataClockFrame( + filter []byte, + ) (*protobufs.ClockFrame, error) } type PebbleClockStore struct { @@ -1648,3 +1651,72 @@ func (p *PebbleClockStore) DeleteCandidateDataClockFrameRange( ) return errors.Wrap(err, "delete candidate data clock frame range") } + +func (p *PebbleClockStore) GetHighestCandidateDataClockFrame( + filter []byte, +) (*protobufs.ClockFrame, error) { + frame, err := p.GetLatestDataClockFrame(filter, nil) + if err != nil { + return nil, errors.Wrap(err, "get highest candidate data clock frame") + } + + from := clockDataCandidateFrameKey( + filter, + frame.FrameNumber, + []byte{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + []byte{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + ) + to := clockDataCandidateFrameKey( + filter, + // We could be deeply out of sync and searching for consensus + frame.FrameNumber+20000, + []byte{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + }, + []byte{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + }, + ) + + iter := p.db.NewIter(&pebble.IterOptions{ + LowerBound: from, + UpperBound: to, + }) + + found := iter.SeekLT(to) + if found { + value := iter.Value() + frame = &protobufs.ClockFrame{} + if err := proto.Unmarshal(value, frame); err != nil { + return nil, errors.Wrap( + errors.Wrap(err, ErrInvalidData.Error()), + "get highest candidate data clock frame", + ) + } + + if err := p.fillAggregateProofs(frame); err != nil { + return nil, errors.Wrap( + errors.Wrap(err, ErrInvalidData.Error()), + "get highest candidate data clock frame", + ) + } + } + + return frame, nil +}