diff --git a/api/grpc/node/node.pb.go b/api/grpc/node/node.pb.go index ebfd8c58e..4ce01f3a0 100644 --- a/api/grpc/node/node.pb.go +++ b/api/grpc/node/node.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.28.1 -// protoc v4.23.4 +// protoc v5.26.1 // source: node/node.proto package node @@ -853,6 +853,125 @@ func (x *BatchHeader) GetReferenceBlockNumber() uint32 { return 0 } +// Node info request +type NodeInfoRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *NodeInfoRequest) Reset() { + *x = NodeInfoRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_node_node_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NodeInfoRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NodeInfoRequest) ProtoMessage() {} + +func (x *NodeInfoRequest) ProtoReflect() protoreflect.Message { + mi := &file_node_node_proto_msgTypes[13] + 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 NodeInfoRequest.ProtoReflect.Descriptor instead. +func (*NodeInfoRequest) Descriptor() ([]byte, []int) { + return file_node_node_proto_rawDescGZIP(), []int{13} +} + +// Node info reply +type NodeInfoReply struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Semver string `protobuf:"bytes,1,opt,name=semver,proto3" json:"semver,omitempty"` + Arch string `protobuf:"bytes,2,opt,name=arch,proto3" json:"arch,omitempty"` + Os string `protobuf:"bytes,3,opt,name=os,proto3" json:"os,omitempty"` + NumCpu uint32 `protobuf:"varint,4,opt,name=num_cpu,json=numCpu,proto3" json:"num_cpu,omitempty"` + MemBytes uint64 `protobuf:"varint,5,opt,name=mem_bytes,json=memBytes,proto3" json:"mem_bytes,omitempty"` +} + +func (x *NodeInfoReply) Reset() { + *x = NodeInfoReply{} + if protoimpl.UnsafeEnabled { + mi := &file_node_node_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NodeInfoReply) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NodeInfoReply) ProtoMessage() {} + +func (x *NodeInfoReply) ProtoReflect() protoreflect.Message { + mi := &file_node_node_proto_msgTypes[14] + 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 NodeInfoReply.ProtoReflect.Descriptor instead. +func (*NodeInfoReply) Descriptor() ([]byte, []int) { + return file_node_node_proto_rawDescGZIP(), []int{14} +} + +func (x *NodeInfoReply) GetSemver() string { + if x != nil { + return x.Semver + } + return "" +} + +func (x *NodeInfoReply) GetArch() string { + if x != nil { + return x.Arch + } + return "" +} + +func (x *NodeInfoReply) GetOs() string { + if x != nil { + return x.Os + } + return "" +} + +func (x *NodeInfoReply) GetNumCpu() uint32 { + if x != nil { + return x.NumCpu + } + return 0 +} + +func (x *NodeInfoReply) GetMemBytes() uint64 { + if x != nil { + return x.MemBytes + } + return 0 +} + var File_node_node_proto protoreflect.FileDescriptor var file_node_node_proto_rawDesc = []byte{ @@ -951,25 +1070,42 @@ var file_node_node_proto_rawDesc = []byte{ 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x14, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x75, 0x6d, 0x62, 0x65, - 0x72, 0x32, 0x4e, 0x0a, 0x09, 0x44, 0x69, 0x73, 0x70, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x12, 0x41, - 0x0a, 0x0b, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x43, 0x68, 0x75, 0x6e, 0x6b, 0x73, 0x12, 0x18, 0x2e, - 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x43, 0x68, 0x75, 0x6e, 0x6b, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x53, - 0x74, 0x6f, 0x72, 0x65, 0x43, 0x68, 0x75, 0x6e, 0x6b, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, - 0x00, 0x32, 0xa0, 0x01, 0x0a, 0x09, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x61, 0x6c, 0x12, - 0x4a, 0x0a, 0x0e, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, 0x43, 0x68, 0x75, 0x6e, 0x6b, - 0x73, 0x12, 0x1b, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, - 0x65, 0x43, 0x68, 0x75, 0x6e, 0x6b, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, - 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, 0x43, 0x68, - 0x75, 0x6e, 0x6b, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x47, 0x0a, 0x0d, 0x47, - 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x62, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x1a, 0x2e, 0x6e, - 0x6f, 0x64, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x62, 0x48, 0x65, 0x61, 0x64, 0x65, - 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, - 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x62, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x65, 0x70, - 0x6c, 0x79, 0x22, 0x00, 0x42, 0x2c, 0x5a, 0x2a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, - 0x6f, 0x6d, 0x2f, 0x4c, 0x61, 0x79, 0x72, 0x2d, 0x4c, 0x61, 0x62, 0x73, 0x2f, 0x65, 0x69, 0x67, - 0x65, 0x6e, 0x64, 0x61, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x6e, 0x6f, - 0x64, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x72, 0x22, 0x11, 0x0a, 0x0f, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x22, 0x81, 0x01, 0x0a, 0x0d, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, + 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x65, 0x6d, 0x76, 0x65, 0x72, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x65, 0x6d, 0x76, 0x65, 0x72, 0x12, 0x12, + 0x0a, 0x04, 0x61, 0x72, 0x63, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x61, 0x72, + 0x63, 0x68, 0x12, 0x0e, 0x0a, 0x02, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, + 0x6f, 0x73, 0x12, 0x17, 0x0a, 0x07, 0x6e, 0x75, 0x6d, 0x5f, 0x63, 0x70, 0x75, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x0d, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x43, 0x70, 0x75, 0x12, 0x1b, 0x0a, 0x09, 0x6d, + 0x65, 0x6d, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, + 0x6d, 0x65, 0x6d, 0x42, 0x79, 0x74, 0x65, 0x73, 0x32, 0x88, 0x01, 0x0a, 0x09, 0x44, 0x69, 0x73, + 0x70, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x12, 0x41, 0x0a, 0x0b, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x43, + 0x68, 0x75, 0x6e, 0x6b, 0x73, 0x12, 0x18, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x53, 0x74, 0x6f, + 0x72, 0x65, 0x43, 0x68, 0x75, 0x6e, 0x6b, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x16, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x43, 0x68, 0x75, 0x6e, + 0x6b, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x38, 0x0a, 0x08, 0x4e, 0x6f, 0x64, + 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x15, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x4e, 0x6f, 0x64, + 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x6e, + 0x6f, 0x64, 0x65, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x70, 0x6c, + 0x79, 0x22, 0x00, 0x32, 0xda, 0x01, 0x0a, 0x09, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x61, + 0x6c, 0x12, 0x4a, 0x0a, 0x0e, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, 0x43, 0x68, 0x75, + 0x6e, 0x6b, 0x73, 0x12, 0x1b, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x52, 0x65, 0x74, 0x72, 0x69, + 0x65, 0x76, 0x65, 0x43, 0x68, 0x75, 0x6e, 0x6b, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x19, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, + 0x43, 0x68, 0x75, 0x6e, 0x6b, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x47, 0x0a, + 0x0d, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x62, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x1a, + 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x62, 0x48, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x6e, 0x6f, 0x64, + 0x65, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x62, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, + 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x38, 0x0a, 0x08, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, + 0x66, 0x6f, 0x12, 0x15, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, + 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x6e, 0x6f, 0x64, 0x65, + 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, + 0x42, 0x2c, 0x5a, 0x2a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x4c, + 0x61, 0x79, 0x72, 0x2d, 0x4c, 0x61, 0x62, 0x73, 0x2f, 0x65, 0x69, 0x67, 0x65, 0x6e, 0x64, 0x61, + 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -984,7 +1120,7 @@ func file_node_node_proto_rawDescGZIP() []byte { return file_node_node_proto_rawDescData } -var file_node_node_proto_msgTypes = make([]protoimpl.MessageInfo, 13) +var file_node_node_proto_msgTypes = make([]protoimpl.MessageInfo, 15) var file_node_node_proto_goTypes = []interface{}{ (*StoreChunksRequest)(nil), // 0: node.StoreChunksRequest (*StoreChunksReply)(nil), // 1: node.StoreChunksReply @@ -999,7 +1135,9 @@ var file_node_node_proto_goTypes = []interface{}{ (*BlobHeader)(nil), // 10: node.BlobHeader (*BlobQuorumInfo)(nil), // 11: node.BlobQuorumInfo (*BatchHeader)(nil), // 12: node.BatchHeader - (*common.G1Commitment)(nil), // 13: common.G1Commitment + (*NodeInfoRequest)(nil), // 13: node.NodeInfoRequest + (*NodeInfoReply)(nil), // 14: node.NodeInfoReply + (*common.G1Commitment)(nil), // 15: common.G1Commitment } var file_node_node_proto_depIdxs = []int32{ 12, // 0: node.StoreChunksRequest.batch_header:type_name -> node.BatchHeader @@ -1008,18 +1146,22 @@ var file_node_node_proto_depIdxs = []int32{ 6, // 3: node.GetBlobHeaderReply.proof:type_name -> node.MerkleProof 10, // 4: node.Blob.header:type_name -> node.BlobHeader 8, // 5: node.Blob.bundles:type_name -> node.Bundle - 13, // 6: node.BlobHeader.commitment:type_name -> common.G1Commitment + 15, // 6: node.BlobHeader.commitment:type_name -> common.G1Commitment 9, // 7: node.BlobHeader.length_commitment:type_name -> node.G2Commitment 9, // 8: node.BlobHeader.length_proof:type_name -> node.G2Commitment 11, // 9: node.BlobHeader.quorum_headers:type_name -> node.BlobQuorumInfo 0, // 10: node.Dispersal.StoreChunks:input_type -> node.StoreChunksRequest - 2, // 11: node.Retrieval.RetrieveChunks:input_type -> node.RetrieveChunksRequest - 4, // 12: node.Retrieval.GetBlobHeader:input_type -> node.GetBlobHeaderRequest - 1, // 13: node.Dispersal.StoreChunks:output_type -> node.StoreChunksReply - 3, // 14: node.Retrieval.RetrieveChunks:output_type -> node.RetrieveChunksReply - 5, // 15: node.Retrieval.GetBlobHeader:output_type -> node.GetBlobHeaderReply - 13, // [13:16] is the sub-list for method output_type - 10, // [10:13] is the sub-list for method input_type + 13, // 11: node.Dispersal.NodeInfo:input_type -> node.NodeInfoRequest + 2, // 12: node.Retrieval.RetrieveChunks:input_type -> node.RetrieveChunksRequest + 4, // 13: node.Retrieval.GetBlobHeader:input_type -> node.GetBlobHeaderRequest + 13, // 14: node.Retrieval.NodeInfo:input_type -> node.NodeInfoRequest + 1, // 15: node.Dispersal.StoreChunks:output_type -> node.StoreChunksReply + 14, // 16: node.Dispersal.NodeInfo:output_type -> node.NodeInfoReply + 3, // 17: node.Retrieval.RetrieveChunks:output_type -> node.RetrieveChunksReply + 5, // 18: node.Retrieval.GetBlobHeader:output_type -> node.GetBlobHeaderReply + 14, // 19: node.Retrieval.NodeInfo:output_type -> node.NodeInfoReply + 15, // [15:20] is the sub-list for method output_type + 10, // [10:15] is the sub-list for method input_type 10, // [10:10] is the sub-list for extension type_name 10, // [10:10] is the sub-list for extension extendee 0, // [0:10] is the sub-list for field type_name @@ -1187,6 +1329,30 @@ func file_node_node_proto_init() { return nil } } + file_node_node_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NodeInfoRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_node_node_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NodeInfoReply); 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{ @@ -1194,7 +1360,7 @@ func file_node_node_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_node_node_proto_rawDesc, NumEnums: 0, - NumMessages: 13, + NumMessages: 15, NumExtensions: 0, NumServices: 2, }, diff --git a/api/grpc/node/node_grpc.pb.go b/api/grpc/node/node_grpc.pb.go index 0dcf6f0eb..20ef64b70 100644 --- a/api/grpc/node/node_grpc.pb.go +++ b/api/grpc/node/node_grpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.3.0 -// - protoc v4.23.4 +// - protoc v5.26.1 // source: node/node.proto package node @@ -20,6 +20,7 @@ const _ = grpc.SupportPackageIsVersion7 const ( Dispersal_StoreChunks_FullMethodName = "/node.Dispersal/StoreChunks" + Dispersal_NodeInfo_FullMethodName = "/node.Dispersal/NodeInfo" ) // DispersalClient is the client API for Dispersal service. @@ -33,6 +34,8 @@ type DispersalClient interface { // for the protocol-defined length of custody. It will return a signature at the // end to attest to the data in this request it has processed. StoreChunks(ctx context.Context, in *StoreChunksRequest, opts ...grpc.CallOption) (*StoreChunksReply, error) + // Retrieve node info metadata + NodeInfo(ctx context.Context, in *NodeInfoRequest, opts ...grpc.CallOption) (*NodeInfoReply, error) } type dispersalClient struct { @@ -52,6 +55,15 @@ func (c *dispersalClient) StoreChunks(ctx context.Context, in *StoreChunksReques return out, nil } +func (c *dispersalClient) NodeInfo(ctx context.Context, in *NodeInfoRequest, opts ...grpc.CallOption) (*NodeInfoReply, error) { + out := new(NodeInfoReply) + err := c.cc.Invoke(ctx, Dispersal_NodeInfo_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // DispersalServer is the server API for Dispersal service. // All implementations must embed UnimplementedDispersalServer // for forward compatibility @@ -63,6 +75,8 @@ type DispersalServer interface { // for the protocol-defined length of custody. It will return a signature at the // end to attest to the data in this request it has processed. StoreChunks(context.Context, *StoreChunksRequest) (*StoreChunksReply, error) + // Retrieve node info metadata + NodeInfo(context.Context, *NodeInfoRequest) (*NodeInfoReply, error) mustEmbedUnimplementedDispersalServer() } @@ -73,6 +87,9 @@ type UnimplementedDispersalServer struct { func (UnimplementedDispersalServer) StoreChunks(context.Context, *StoreChunksRequest) (*StoreChunksReply, error) { return nil, status.Errorf(codes.Unimplemented, "method StoreChunks not implemented") } +func (UnimplementedDispersalServer) NodeInfo(context.Context, *NodeInfoRequest) (*NodeInfoReply, error) { + return nil, status.Errorf(codes.Unimplemented, "method NodeInfo not implemented") +} func (UnimplementedDispersalServer) mustEmbedUnimplementedDispersalServer() {} // UnsafeDispersalServer may be embedded to opt out of forward compatibility for this service. @@ -104,6 +121,24 @@ func _Dispersal_StoreChunks_Handler(srv interface{}, ctx context.Context, dec fu return interceptor(ctx, in, info, handler) } +func _Dispersal_NodeInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(NodeInfoRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DispersalServer).NodeInfo(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Dispersal_NodeInfo_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DispersalServer).NodeInfo(ctx, req.(*NodeInfoRequest)) + } + return interceptor(ctx, in, info, handler) +} + // Dispersal_ServiceDesc is the grpc.ServiceDesc for Dispersal service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -115,6 +150,10 @@ var Dispersal_ServiceDesc = grpc.ServiceDesc{ MethodName: "StoreChunks", Handler: _Dispersal_StoreChunks_Handler, }, + { + MethodName: "NodeInfo", + Handler: _Dispersal_NodeInfo_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "node/node.proto", @@ -123,6 +162,7 @@ var Dispersal_ServiceDesc = grpc.ServiceDesc{ const ( Retrieval_RetrieveChunks_FullMethodName = "/node.Retrieval/RetrieveChunks" Retrieval_GetBlobHeader_FullMethodName = "/node.Retrieval/GetBlobHeader" + Retrieval_NodeInfo_FullMethodName = "/node.Retrieval/NodeInfo" ) // RetrievalClient is the client API for Retrieval service. @@ -131,8 +171,10 @@ const ( type RetrievalClient interface { // RetrieveChunks retrieves the chunks for a blob custodied at the Node. RetrieveChunks(ctx context.Context, in *RetrieveChunksRequest, opts ...grpc.CallOption) (*RetrieveChunksReply, error) - // Similar to RetrieveChunks, this just returns the header of the blob. + // GetBlobHeader is similar to RetrieveChunks, this just returns the header of the blob. GetBlobHeader(ctx context.Context, in *GetBlobHeaderRequest, opts ...grpc.CallOption) (*GetBlobHeaderReply, error) + // Retrieve node info metadata + NodeInfo(ctx context.Context, in *NodeInfoRequest, opts ...grpc.CallOption) (*NodeInfoReply, error) } type retrievalClient struct { @@ -161,14 +203,25 @@ func (c *retrievalClient) GetBlobHeader(ctx context.Context, in *GetBlobHeaderRe return out, nil } +func (c *retrievalClient) NodeInfo(ctx context.Context, in *NodeInfoRequest, opts ...grpc.CallOption) (*NodeInfoReply, error) { + out := new(NodeInfoReply) + err := c.cc.Invoke(ctx, Retrieval_NodeInfo_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // RetrievalServer is the server API for Retrieval service. // All implementations must embed UnimplementedRetrievalServer // for forward compatibility type RetrievalServer interface { // RetrieveChunks retrieves the chunks for a blob custodied at the Node. RetrieveChunks(context.Context, *RetrieveChunksRequest) (*RetrieveChunksReply, error) - // Similar to RetrieveChunks, this just returns the header of the blob. + // GetBlobHeader is similar to RetrieveChunks, this just returns the header of the blob. GetBlobHeader(context.Context, *GetBlobHeaderRequest) (*GetBlobHeaderReply, error) + // Retrieve node info metadata + NodeInfo(context.Context, *NodeInfoRequest) (*NodeInfoReply, error) mustEmbedUnimplementedRetrievalServer() } @@ -182,6 +235,9 @@ func (UnimplementedRetrievalServer) RetrieveChunks(context.Context, *RetrieveChu func (UnimplementedRetrievalServer) GetBlobHeader(context.Context, *GetBlobHeaderRequest) (*GetBlobHeaderReply, error) { return nil, status.Errorf(codes.Unimplemented, "method GetBlobHeader not implemented") } +func (UnimplementedRetrievalServer) NodeInfo(context.Context, *NodeInfoRequest) (*NodeInfoReply, error) { + return nil, status.Errorf(codes.Unimplemented, "method NodeInfo not implemented") +} func (UnimplementedRetrievalServer) mustEmbedUnimplementedRetrievalServer() {} // UnsafeRetrievalServer may be embedded to opt out of forward compatibility for this service. @@ -231,6 +287,24 @@ func _Retrieval_GetBlobHeader_Handler(srv interface{}, ctx context.Context, dec return interceptor(ctx, in, info, handler) } +func _Retrieval_NodeInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(NodeInfoRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(RetrievalServer).NodeInfo(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Retrieval_NodeInfo_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(RetrievalServer).NodeInfo(ctx, req.(*NodeInfoRequest)) + } + return interceptor(ctx, in, info, handler) +} + // Retrieval_ServiceDesc is the grpc.ServiceDesc for Retrieval service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -246,6 +320,10 @@ var Retrieval_ServiceDesc = grpc.ServiceDesc{ MethodName: "GetBlobHeader", Handler: _Retrieval_GetBlobHeader_Handler, }, + { + MethodName: "NodeInfo", + Handler: _Retrieval_NodeInfo_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "node/node.proto", diff --git a/api/proto/node/node.proto b/api/proto/node/node.proto index 32bc20af6..65128bb0f 100644 --- a/api/proto/node/node.proto +++ b/api/proto/node/node.proto @@ -14,6 +14,8 @@ service Dispersal { // for the protocol-defined length of custody. It will return a signature at the // end to attest to the data in this request it has processed. rpc StoreChunks(StoreChunksRequest) returns (StoreChunksReply) {} + // Retrieve node info metadata + rpc NodeInfo(NodeInfoRequest) returns (NodeInfoReply) {} } service Retrieval { @@ -21,6 +23,8 @@ service Retrieval { rpc RetrieveChunks(RetrieveChunksRequest) returns (RetrieveChunksReply) {} // GetBlobHeader is similar to RetrieveChunks, this just returns the header of the blob. rpc GetBlobHeader(GetBlobHeaderRequest) returns (GetBlobHeaderReply) {} + // Retrieve node info metadata + rpc NodeInfo(NodeInfoRequest) returns (NodeInfoReply) {} } // Requests and replies @@ -162,3 +166,16 @@ message BatchHeader { // The Ethereum block number at which the batch is dispersed. uint32 reference_block_number = 3; } + +// Node info request +message NodeInfoRequest { +} + +// Node info reply +message NodeInfoReply { + string semver = 1; + string arch = 2; + string os = 3; + uint32 num_cpu = 4; + uint64 mem_bytes = 5; +} diff --git a/core/data.go b/core/data.go index e71f54482..ca1ad1397 100644 --- a/core/data.go +++ b/core/data.go @@ -1,11 +1,13 @@ package core import ( + "encoding/binary" "errors" "fmt" "github.com/Layr-Labs/eigenda/common" "github.com/Layr-Labs/eigenda/encoding" + "github.com/consensys/gnark-crypto/ecc/bn254" ) type AccountID = string @@ -33,6 +35,8 @@ const ( // which means the max ID can not be larger than 254 (from 0 to 254, there are 255 // different IDs). MaxQuorumID = 254 + + GnarkBundleEncodingFormat = 1 ) func (s *SecurityParam) String() string { @@ -165,6 +169,83 @@ func (b Bundle) Size() uint64 { return size } +// Serialize returns the serialized bytes of the bundle. +// +// The bytes are packed in this format: +// <8 bytes header>chunk 2 bytes>... +// +// The header format: +// - First byte: describes the encoding format. Currently, only GnarkBundleEncodingFormat (1) +// is supported. +// - Remaining 7 bytes: describes the information about chunks. +// +// The chunk format will depend on the encoding format. With the GnarkBundleEncodingFormat, +// each chunk is formated as <32 bytes proof><32 bytes coeff>...<32 bytes coefff>, where the +// proof and coeffs are all encoded with Gnark. +func (b Bundle) Serialize() ([]byte, error) { + if len(b) == 0 { + return []byte{}, nil + } + if len(b[0].Coeffs) == 0 { + return nil, errors.New("invalid bundle: the coeffs length is zero") + } + size := 0 + for _, f := range b { + if len(f.Coeffs) != len(b[0].Coeffs) { + return nil, errors.New("invalid bundle: all chunks should have the same length") + } + size += bn254.SizeOfG1AffineCompressed + encoding.BYTES_PER_SYMBOL*len(f.Coeffs) + } + result := make([]byte, size+8) + buf := result + metadata := uint64(GnarkBundleEncodingFormat) | (uint64(len(b[0].Coeffs)) << 8) + binary.LittleEndian.PutUint64(buf, metadata) + buf = buf[8:] + for _, f := range b { + chunk, err := f.SerializeGnark() + if err != nil { + return nil, err + } + copy(buf, chunk) + buf = buf[len(chunk):] + } + return result, nil +} + +func (b Bundle) Deserialize(data []byte) (Bundle, error) { + if len(data) < 8 { + return nil, errors.New("bundle data must have at least 8 bytes") + } + // Parse metadata + meta := binary.LittleEndian.Uint64(data) + if (meta & 0xFF) != GnarkBundleEncodingFormat { + return nil, errors.New("invalid bundle data encoding format") + } + chunkLen := meta >> 8 + if chunkLen == 0 { + return nil, errors.New("chunk length must be greater than zero") + } + chunkSize := bn254.SizeOfG1AffineCompressed + encoding.BYTES_PER_SYMBOL*int(chunkLen) + if (len(data)-8)%chunkSize != 0 { + return nil, errors.New("bundle data is invalid") + } + // Decode + bundle := make([]*encoding.Frame, 0, (len(data)-8)/chunkSize) + buf := data[8:] + for len(buf) > 0 { + if len(buf) < chunkSize { + return nil, errors.New("bundle data is invalid") + } + f, err := new(encoding.Frame).DeserializeGnark(buf[:chunkSize]) + if err != nil { + return nil, err + } + bundle = append(bundle, f) + buf = buf[chunkSize:] + } + return bundle, nil +} + // Serialize encodes a batch of chunks into a byte array func (cb Bundles) Serialize() (map[uint32][][]byte, error) { data := make(map[uint32][][]byte, len(cb)) diff --git a/core/data_test.go b/core/data_test.go new file mode 100644 index 000000000..184866b6e --- /dev/null +++ b/core/data_test.go @@ -0,0 +1,97 @@ +package core_test + +import ( + "math/rand" + "testing" + + "github.com/Layr-Labs/eigenda/core" + "github.com/Layr-Labs/eigenda/encoding" + "github.com/consensys/gnark-crypto/ecc/bn254/fp" + "github.com/consensys/gnark-crypto/ecc/bn254/fr" + "github.com/stretchr/testify/assert" +) + +func createBundle(t *testing.T, numFrames, numCoeffs, seed int) core.Bundle { + var XCoord, YCoord fp.Element + _, err := XCoord.SetString("21661178944771197726808973281966770251114553549453983978976194544185382599016") + assert.NoError(t, err) + _, err = YCoord.SetString("9207254729396071334325696286939045899948985698134704137261649190717970615186") + assert.NoError(t, err) + r := rand.New(rand.NewSource(int64(seed))) + frames := make([]*encoding.Frame, numFrames) + for n := 0; n < numFrames; n++ { + frames[n] = new(encoding.Frame) + frames[n].Proof = encoding.Proof{ + X: XCoord, + Y: YCoord, + } + for i := 0; i < numCoeffs; i++ { + frames[n].Coeffs = append(frames[n].Coeffs, fr.NewElement(r.Uint64())) + } + } + return frames +} + +func TestInvalidBundleSer(t *testing.T) { + b1 := createBundle(t, 1, 0, 0) + _, err := b1.Serialize() + assert.EqualError(t, err, "invalid bundle: the coeffs length is zero") + + b2 := createBundle(t, 1, 1, 0) + b3 := createBundle(t, 1, 2, 0) + b3 = append(b3, b2...) + _, err = b3.Serialize() + assert.EqualError(t, err, "invalid bundle: all chunks should have the same length") +} + +func TestInvalidBundleDeser(t *testing.T) { + tooSmallBytes := []byte{byte(0b01000000)} + _, err := new(core.Bundle).Deserialize(tooSmallBytes) + assert.EqualError(t, err, "bundle data must have at least 8 bytes") + + invalidFormat := make([]byte, 0, 8) + for i := 0; i < 7; i++ { + invalidFormat = append(invalidFormat, byte(0)) + } + invalidFormat = append(invalidFormat, byte(0b01000000)) + _, err = new(core.Bundle).Deserialize(invalidFormat) + assert.EqualError(t, err, "invalid bundle data encoding format") + + invliadChunkLen := make([]byte, 0, 8) + invliadChunkLen = append(invliadChunkLen, byte(1)) + for i := 0; i < 7; i++ { + invliadChunkLen = append(invliadChunkLen, byte(0)) + } + _, err = new(core.Bundle).Deserialize(invliadChunkLen) + assert.EqualError(t, err, "chunk length must be greater than zero") + + data := make([]byte, 0, 9) + data = append(data, byte(1)) + for i := 0; i < 6; i++ { + data = append(data, byte(0)) + } + data = append(data, byte(0b00100000)) + data = append(data, byte(5)) + data = append(data, byte(0b01000000)) + _, err = new(core.Bundle).Deserialize(data) + assert.EqualError(t, err, "bundle data is invalid") +} + +func TestBundleEncoding(t *testing.T) { + numTrials := 16 + for i := 0; i < numTrials; i++ { + bundle := createBundle(t, 64, 64, i) + bytes, err := bundle.Serialize() + assert.Nil(t, err) + decoded, err := new(core.Bundle).Deserialize(bytes) + assert.Nil(t, err) + assert.Equal(t, len(bundle), len(decoded)) + for i := 0; i < len(bundle); i++ { + assert.True(t, bundle[i].Proof.Equal(&decoded[i].Proof)) + assert.Equal(t, len(bundle[i].Coeffs), len(decoded[i].Coeffs)) + for j := 0; j < len(bundle[i].Coeffs); j++ { + assert.True(t, bundle[i].Coeffs[j].Equal(&decoded[i].Coeffs[j])) + } + } + } +} diff --git a/encoding/kzg/prover/parametrized_prover.go b/encoding/kzg/prover/parametrized_prover.go index ceabb8dfd..d5c367781 100644 --- a/encoding/kzg/prover/parametrized_prover.go +++ b/encoding/kzg/prover/parametrized_prover.go @@ -3,16 +3,13 @@ package prover import ( "fmt" "log" - "math" "time" "github.com/Layr-Labs/eigenda/encoding" + "github.com/hashicorp/go-multierror" - "github.com/Layr-Labs/eigenda/encoding/fft" "github.com/Layr-Labs/eigenda/encoding/kzg" "github.com/Layr-Labs/eigenda/encoding/rs" - "github.com/Layr-Labs/eigenda/encoding/utils/toeplitz" - "github.com/consensys/gnark-crypto/ecc" "github.com/consensys/gnark-crypto/ecc/bn254" "github.com/consensys/gnark-crypto/ecc/bn254/fr" ) @@ -21,18 +18,36 @@ type ParametrizedProver struct { *rs.Encoder *kzg.KzgConfig - Srs *kzg.SRS - G2Trailing []bn254.G2Affine + Ks *kzg.KZGSettings - Fs *fft.FFTSettings - Ks *kzg.KZGSettings - SFs *fft.FFTSettings // fft used for submatrix product helper - FFTPointsT [][]bn254.G1Affine // transpose of FFTPoints + Computer ProofComputer } -type WorkerResult struct { - points []bn254.G1Affine - err error +type RsEncodeResult struct { + Frames []rs.Frame + Indices []uint32 + Duration time.Duration + Err error +} +type LengthCommitmentResult struct { + LengthCommitment bn254.G2Affine + Duration time.Duration + Err error +} +type LengthProofResult struct { + LengthProof bn254.G2Affine + Duration time.Duration + Err error +} +type CommitmentResult struct { + Commitment bn254.G1Affine + Duration time.Duration + Err error +} +type ProofsResult struct { + Proofs []bn254.G1Affine + Duration time.Duration + Err error } // just a wrapper to take bytes not Fr Element @@ -46,228 +61,117 @@ func (g *ParametrizedProver) EncodeBytes(inputBytes []byte) (*bn254.G1Affine, *b func (g *ParametrizedProver) Encode(inputFr []fr.Element) (*bn254.G1Affine, *bn254.G2Affine, *bn254.G2Affine, []encoding.Frame, []uint32, error) { - startTime := time.Now() - poly, frames, indices, err := g.Encoder.Encode(inputFr) - if err != nil { - return nil, nil, nil, nil, nil, err - } - - if len(poly.Coeffs) > int(g.KzgConfig.SRSNumberToLoad) { - return nil, nil, nil, nil, nil, fmt.Errorf("poly Coeff length %v is greater than Loaded SRS points %v", len(poly.Coeffs), int(g.KzgConfig.SRSNumberToLoad)) - } - - // compute commit for the full poly - commit, err := g.Commit(poly.Coeffs) - if err != nil { - return nil, nil, nil, nil, nil, err + if len(inputFr) > int(g.KzgConfig.SRSNumberToLoad) { + return nil, nil, nil, nil, nil, fmt.Errorf("poly Coeff length %v is greater than Loaded SRS points %v", len(inputFr), int(g.KzgConfig.SRSNumberToLoad)) } - config := ecc.MultiExpConfig{} + encodeStart := time.Now() - var lengthCommitment bn254.G2Affine - _, err = lengthCommitment.MultiExp(g.Srs.G2[:len(poly.Coeffs)], poly.Coeffs, config) - if err != nil { - return nil, nil, nil, nil, nil, err - } - - intermediate := time.Now() - - chunkLength := uint64(len(inputFr)) - - if g.Verbose { - log.Printf(" Commiting takes %v\n", time.Since(intermediate)) - intermediate = time.Now() - - log.Printf("shift %v\n", g.SRSOrder-chunkLength) - log.Printf("order %v\n", len(g.Srs.G2)) - log.Println("low degree verification info") - } - - shiftedSecret := g.G2Trailing[g.KzgConfig.SRSNumberToLoad-chunkLength:] - - //The proof of low degree is commitment of the polynomial shifted to the largest srs degree - var lengthProof bn254.G2Affine - _, err = lengthProof.MultiExp(shiftedSecret, poly.Coeffs, config) - if err != nil { - return nil, nil, nil, nil, nil, err - } + rsChan := make(chan RsEncodeResult, 1) + lengthCommitmentChan := make(chan LengthCommitmentResult, 1) + lengthProofChan := make(chan LengthProofResult, 1) + commitmentChan := make(chan CommitmentResult, 1) + proofChan := make(chan ProofsResult, 1) - if g.Verbose { - log.Printf(" Generating Length Proof takes %v\n", time.Since(intermediate)) - intermediate = time.Now() - } - - // compute proofs - paddedCoeffs := make([]fr.Element, g.NumEvaluations()) - copy(paddedCoeffs, poly.Coeffs) - - proofs, err := g.ProveAllCosetThreads(paddedCoeffs, g.NumChunks, g.ChunkLength, g.NumWorker) - if err != nil { - return nil, nil, nil, nil, nil, fmt.Errorf("could not generate proofs: %v", err) - } - - if g.Verbose { - log.Printf(" Proving takes %v\n", time.Since(intermediate)) - } - - kzgFrames := make([]encoding.Frame, len(frames)) - for i, index := range indices { - kzgFrames[i] = encoding.Frame{ - Proof: proofs[index], - Coeffs: frames[i].Coeffs, + // inputFr is untouched + // compute chunks + go func() { + start := time.Now() + frames, indices, err := g.Encoder.Encode(inputFr) + rsChan <- RsEncodeResult{ + Frames: frames, + Indices: indices, + Err: err, + Duration: time.Since(start), } - } - - if g.Verbose { - log.Printf("Total encoding took %v\n", time.Since(startTime)) - } - return &commit, &lengthCommitment, &lengthProof, kzgFrames, indices, nil -} + }() -func (g *ParametrizedProver) Commit(polyFr []fr.Element) (bn254.G1Affine, error) { - commit, err := g.Ks.CommitToPoly(polyFr) - return *commit, err -} - -func (p *ParametrizedProver) ProveAllCosetThreads(polyFr []fr.Element, numChunks, chunkLen, numWorker uint64) ([]bn254.G1Affine, error) { - begin := time.Now() - // Robert: Standardizing this to use the same math used in precomputeSRS - dimE := numChunks - l := chunkLen - - sumVec := make([]bn254.G1Affine, dimE*2) - - jobChan := make(chan uint64, numWorker) - results := make(chan WorkerResult, numWorker) - - // create storage for intermediate fft outputs - coeffStore := make([][]fr.Element, dimE*2) - for i := range coeffStore { - coeffStore[i] = make([]fr.Element, l) - } - - for w := uint64(0); w < numWorker; w++ { - go p.proofWorker(polyFr, jobChan, l, dimE, coeffStore, results) - } - - for j := uint64(0); j < l; j++ { - jobChan <- j - } - close(jobChan) - - // return last error - var err error - for w := uint64(0); w < numWorker; w++ { - wr := <-results - if wr.err != nil { - err = wr.err + // compute commit for the full poly + go func() { + start := time.Now() + commit, err := g.Computer.ComputeCommitment(inputFr) + commitmentChan <- CommitmentResult{ + Commitment: *commit, + Err: err, + Duration: time.Since(start), } - } - - if err != nil { - return nil, fmt.Errorf("proof worker error: %v", err) - } - - t0 := time.Now() - - // compute proof by multi scaler multiplication - msmErrors := make(chan error, dimE*2) - for i := uint64(0); i < dimE*2; i++ { - - go func(k uint64) { - _, err := sumVec[k].MultiExp(p.FFTPointsT[k], coeffStore[k], ecc.MultiExpConfig{}) - // handle error - msmErrors <- err - }(i) - } - - for i := uint64(0); i < dimE*2; i++ { - err := <-msmErrors - if err != nil { - fmt.Println("Error. MSM while adding points", err) - return nil, err + }() + + go func() { + start := time.Now() + lengthCommitment, err := g.Computer.ComputeLengthCommitment(inputFr) + lengthCommitmentChan <- LengthCommitmentResult{ + LengthCommitment: *lengthCommitment, + Err: err, + Duration: time.Since(start), } - } - - t1 := time.Now() - - // only 1 ifft is needed - sumVecInv, err := p.Fs.FFTG1(sumVec, true) - if err != nil { - return nil, fmt.Errorf("fft error: %v", err) - } - - t2 := time.Now() - - // outputs is out of order - buttefly - proofs, err := p.Fs.FFTG1(sumVecInv[:dimE], false) - if err != nil { - return nil, err - } - - t3 := time.Now() - - fmt.Printf("mult-th %v, msm %v,fft1 %v, fft2 %v,\n", t0.Sub(begin), t1.Sub(t0), t2.Sub(t1), t3.Sub(t2)) - - return proofs, nil -} - -func (p *ParametrizedProver) proofWorker( - polyFr []fr.Element, - jobChan <-chan uint64, - l uint64, - dimE uint64, - coeffStore [][]fr.Element, - results chan<- WorkerResult, -) { - - for j := range jobChan { - coeffs, err := p.GetSlicesCoeff(polyFr, dimE, j, l) - if err != nil { - results <- WorkerResult{ - points: nil, - err: err, - } - } else { - for i := 0; i < len(coeffs); i++ { - coeffStore[i][j] = coeffs[i] - } + }() + + go func() { + start := time.Now() + lengthProof, err := g.Computer.ComputeLengthProof(inputFr) + lengthProofChan <- LengthProofResult{ + LengthProof: *lengthProof, + Err: err, + Duration: time.Since(start), + } + }() + + go func() { + start := time.Now() + // compute proofs + paddedCoeffs := make([]fr.Element, g.NumEvaluations()) + // polyCoeffs has less points than paddedCoeffs in general due to erasure redundancy + copy(paddedCoeffs, inputFr) + + numBlob := 1 + flatpaddedCoeffs := make([]fr.Element, 0, numBlob*len(paddedCoeffs)) + for i := 0; i < numBlob; i++ { + flatpaddedCoeffs = append(flatpaddedCoeffs, paddedCoeffs...) } - } - - results <- WorkerResult{ - err: nil, - } -} - -// output is in the form see primeField toeplitz -// -// phi ^ (coset size ) = 1 -// -// implicitly pad slices to power of 2 -func (p *ParametrizedProver) GetSlicesCoeff(polyFr []fr.Element, dimE, j, l uint64) ([]fr.Element, error) { - // there is a constant term - m := uint64(len(polyFr)) - 1 - dim := (m - j) / l - - toeV := make([]fr.Element, 2*dimE-1) - for i := uint64(0); i < dim; i++ { - toeV[i].Set(&polyFr[m-(j+i*l)]) + proofs, err := g.Computer.ComputeMultiFrameProof(flatpaddedCoeffs, g.NumChunks, g.ChunkLength, g.NumWorker) + proofChan <- ProofsResult{ + Proofs: proofs, + Err: err, + Duration: time.Since(start), + } + }() + + lengthProofResult := <-lengthProofChan + lengthCommitmentResult := <-lengthCommitmentChan + commitmentResult := <-commitmentChan + rsResult := <-rsChan + proofsResult := <-proofChan + + if lengthProofResult.Err != nil || lengthCommitmentResult.Err != nil || + commitmentResult.Err != nil || rsResult.Err != nil || + proofsResult.Err != nil { + return nil, nil, nil, nil, nil, multierror.Append(lengthProofResult.Err, lengthCommitmentResult.Err, commitmentResult.Err, rsResult.Err, proofsResult.Err) + } + totalProcessingTime := time.Since(encodeStart) + + log.Printf("\n\t\tRS encode %-v\n\t\tCommiting %-v\n\t\tLengthCommit %-v\n\t\tlengthProof %-v\n\t\tmultiProof %-v\n\t\tMetaInfo. order %-v shift %v\n", + rsResult.Duration, + commitmentResult.Duration, + lengthCommitmentResult.Duration, + lengthProofResult.Duration, + proofsResult.Duration, + g.SRSOrder, + g.SRSOrder-uint64(len(inputFr)), + ) + + // assemble frames + kzgFrames := make([]encoding.Frame, len(rsResult.Frames)) + for i, index := range rsResult.Indices { + kzgFrames[i] = encoding.Frame{ + Proof: proofsResult.Proofs[index], + Coeffs: rsResult.Frames[i].Coeffs, + } } - // use precompute table - tm, err := toeplitz.NewToeplitz(toeV, p.SFs) - if err != nil { - return nil, err + if g.Verbose { + log.Printf("Total encoding took %v\n", totalProcessingTime) } - return tm.GetFFTCoeff() -} - -/* -returns the power of 2 which is immediately bigger than the input -*/ -func CeilIntPowerOf2Num(d uint64) uint64 { - nextPower := math.Ceil(math.Log2(float64(d))) - return uint64(math.Pow(2.0, nextPower)) + return &commitmentResult.Commitment, &lengthCommitmentResult.LengthCommitment, &lengthProofResult.LengthProof, kzgFrames, rsResult.Indices, nil } diff --git a/encoding/kzg/prover/proof_computer.go b/encoding/kzg/prover/proof_computer.go new file mode 100644 index 000000000..658ec7b34 --- /dev/null +++ b/encoding/kzg/prover/proof_computer.go @@ -0,0 +1,209 @@ +package prover + +import ( + "fmt" + "math" + "time" + + "github.com/Layr-Labs/eigenda/encoding/fft" + "github.com/Layr-Labs/eigenda/encoding/kzg" + "github.com/Layr-Labs/eigenda/encoding/utils/toeplitz" + "github.com/consensys/gnark-crypto/ecc" + "github.com/consensys/gnark-crypto/ecc/bn254" + "github.com/consensys/gnark-crypto/ecc/bn254/fr" +) + +type CpuProofComputer struct { + *kzg.KzgConfig + Fs *fft.FFTSettings + FFTPointsT [][]bn254.G1Affine // transpose of FFTPoints + SFs *fft.FFTSettings + Srs *kzg.SRS + G2Trailing []bn254.G2Affine +} + +type WorkerResult struct { + points []bn254.G1Affine + err error +} + +func (p *CpuProofComputer) ComputeLengthProof(coeffs []fr.Element) (*bn254.G2Affine, error) { + inputLength := uint64(len(coeffs)) + shiftedSecret := p.G2Trailing[p.KzgConfig.SRSNumberToLoad-inputLength:] + config := ecc.MultiExpConfig{} + //The proof of low degree is commitment of the polynomial shifted to the largest srs degree + var lengthProof bn254.G2Affine + _, err := lengthProof.MultiExp(shiftedSecret, coeffs, config) + if err != nil { + return nil, err + } + return &lengthProof, nil +} + +func (p *CpuProofComputer) ComputeCommitment(coeffs []fr.Element) (*bn254.G1Affine, error) { + // compute commit for the full poly + config := ecc.MultiExpConfig{} + var commitment bn254.G1Affine + _, err := commitment.MultiExp(p.Srs.G1[:len(coeffs)], coeffs, config) + if err != nil { + return nil, err + } + return &commitment, nil +} + +func (p *CpuProofComputer) ComputeLengthCommitment(coeffs []fr.Element) (*bn254.G2Affine, error) { + config := ecc.MultiExpConfig{} + + var lengthCommitment bn254.G2Affine + _, err := lengthCommitment.MultiExp(p.Srs.G2[:len(coeffs)], coeffs, config) + if err != nil { + return nil, err + } + return &lengthCommitment, nil +} + +func (p *CpuProofComputer) ComputeMultiFrameProof(polyFr []fr.Element, numChunks, chunkLen, numWorker uint64) ([]bn254.G1Affine, error) { + begin := time.Now() + // Robert: Standardizing this to use the same math used in precomputeSRS + dimE := numChunks + l := chunkLen + + sumVec := make([]bn254.G1Affine, dimE*2) + + jobChan := make(chan uint64, numWorker) + results := make(chan WorkerResult, numWorker) + + // create storage for intermediate fft outputs + coeffStore := make([][]fr.Element, dimE*2) + for i := range coeffStore { + coeffStore[i] = make([]fr.Element, l) + } + + for w := uint64(0); w < numWorker; w++ { + go p.proofWorker(polyFr, jobChan, l, dimE, coeffStore, results) + } + + for j := uint64(0); j < l; j++ { + jobChan <- j + } + close(jobChan) + + // return last error + var err error + for w := uint64(0); w < numWorker; w++ { + wr := <-results + if wr.err != nil { + err = wr.err + } + } + + if err != nil { + return nil, fmt.Errorf("proof worker error: %v", err) + } + + t0 := time.Now() + + // compute proof by multi scaler multiplication + msmErrors := make(chan error, dimE*2) + for i := uint64(0); i < dimE*2; i++ { + + go func(k uint64) { + _, err := sumVec[k].MultiExp(p.FFTPointsT[k], coeffStore[k], ecc.MultiExpConfig{}) + // handle error + msmErrors <- err + }(i) + } + + for i := uint64(0); i < dimE*2; i++ { + err := <-msmErrors + if err != nil { + fmt.Println("Error. MSM while adding points", err) + return nil, err + } + } + + t1 := time.Now() + + // only 1 ifft is needed + sumVecInv, err := p.Fs.FFTG1(sumVec, true) + if err != nil { + return nil, fmt.Errorf("fft error: %v", err) + } + + t2 := time.Now() + + // outputs is out of order - buttefly + proofs, err := p.Fs.FFTG1(sumVecInv[:dimE], false) + if err != nil { + return nil, err + } + + t3 := time.Now() + + fmt.Printf("mult-th %v, msm %v,fft1 %v, fft2 %v,\n", t0.Sub(begin), t1.Sub(t0), t2.Sub(t1), t3.Sub(t2)) + + return proofs, nil +} + +func (p *CpuProofComputer) proofWorker( + polyFr []fr.Element, + jobChan <-chan uint64, + l uint64, + dimE uint64, + coeffStore [][]fr.Element, + results chan<- WorkerResult, +) { + + for j := range jobChan { + coeffs, err := p.GetSlicesCoeff(polyFr, dimE, j, l) + if err != nil { + results <- WorkerResult{ + points: nil, + err: err, + } + } else { + for i := 0; i < len(coeffs); i++ { + coeffStore[i][j] = coeffs[i] + } + } + } + + results <- WorkerResult{ + err: nil, + } +} + +// output is in the form see primeField toeplitz +// +// phi ^ (coset size ) = 1 +// +// implicitly pad slices to power of 2 +func (p *CpuProofComputer) GetSlicesCoeff(polyFr []fr.Element, dimE, j, l uint64) ([]fr.Element, error) { + // there is a constant term + m := uint64(len(polyFr)) - 1 + dim := (m - j) / l + + // maximal number of unique values from a toeplitz matrix + tDim := 2*dimE - 1 + + toeV := make([]fr.Element, tDim) + for i := uint64(0); i < dim; i++ { + + toeV[i].Set(&polyFr[m-(j+i*l)]) + } + + // use precompute table + tm, err := toeplitz.NewToeplitz(toeV, p.SFs) + if err != nil { + return nil, err + } + return tm.GetFFTCoeff() +} + +/* +returns the power of 2 which is immediately bigger than the input +*/ +func CeilIntPowerOf2Num(d uint64) uint64 { + nextPower := math.Ceil(math.Log2(float64(d))) + return uint64(math.Pow(2.0, nextPower)) +} diff --git a/encoding/kzg/prover/proof_device.go b/encoding/kzg/prover/proof_device.go new file mode 100644 index 000000000..680b9ab09 --- /dev/null +++ b/encoding/kzg/prover/proof_device.go @@ -0,0 +1,14 @@ +package prover + +import ( + "github.com/consensys/gnark-crypto/ecc/bn254" + "github.com/consensys/gnark-crypto/ecc/bn254/fr" +) + +type ProofComputer interface { + // blobFr are coefficients + ComputeCommitment(blobFr []fr.Element) (*bn254.G1Affine, error) + ComputeMultiFrameProof(blobFr []fr.Element, numChunks, chunkLen, numWorker uint64) ([]bn254.G1Affine, error) + ComputeLengthCommitment(blobFr []fr.Element) (*bn254.G2Affine, error) + ComputeLengthProof(blobFr []fr.Element) (*bn254.G2Affine, error) +} diff --git a/encoding/kzg/prover/prover.go b/encoding/kzg/prover/prover.go index f3fec7ef1..d5a2768c3 100644 --- a/encoding/kzg/prover/prover.go +++ b/encoding/kzg/prover/prover.go @@ -236,15 +236,20 @@ func (g *Prover) newProver(params encoding.EncodingParams) (*ParametrizedProver, t := uint8(math.Log2(float64(2 * encoder.NumChunks))) sfs := fft.NewFFTSettings(t) - return &ParametrizedProver{ - Encoder: encoder, - KzgConfig: g.KzgConfig, - Srs: g.Srs, - G2Trailing: g.G2Trailing, + computer := &CpuProofComputer{ Fs: fs, - Ks: ks, - SFs: sfs, FFTPointsT: fftPointsT, + SFs: sfs, + Srs: g.Srs, + G2Trailing: g.G2Trailing, + KzgConfig: g.KzgConfig, + } + + return &ParametrizedProver{ + Encoder: encoder, + KzgConfig: g.KzgConfig, + Ks: ks, + Computer: computer, }, nil } diff --git a/encoding/rs/encode.go b/encoding/rs/encode.go index 401b6f963..241f0b27d 100644 --- a/encoding/rs/encode.go +++ b/encoding/rs/encode.go @@ -18,10 +18,10 @@ type GlobalPoly struct { } // just a wrapper to take bytes not Fr Element -func (g *Encoder) EncodeBytes(inputBytes []byte) (*GlobalPoly, []Frame, []uint32, error) { +func (g *Encoder) EncodeBytes(inputBytes []byte) ([]Frame, []uint32, error) { inputFr, err := ToFrArray(inputBytes) if err != nil { - return nil, nil, nil, fmt.Errorf("cannot convert bytes to field elements, %w", err) + return nil, nil, fmt.Errorf("cannot convert bytes to field elements, %w", err) } return g.Encode(inputFr) } @@ -33,7 +33,7 @@ func (g *Encoder) EncodeBytes(inputBytes []byte) (*GlobalPoly, []Frame, []uint32 // frame, the multireveal interpolating coefficients are identical to the part of input bytes // in the form of field element. The extra returned integer list corresponds to which leading // coset root of unity, the frame is proving against, which can be deduced from a frame's index -func (g *Encoder) Encode(inputFr []fr.Element) (*GlobalPoly, []Frame, []uint32, error) { +func (g *Encoder) Encode(inputFr []fr.Element) ([]Frame, []uint32, error) { start := time.Now() intermediate := time.Now() @@ -42,12 +42,7 @@ func (g *Encoder) Encode(inputFr []fr.Element) (*GlobalPoly, []Frame, []uint32, // extend data based on Sys, Par ratio. The returned fullCoeffsPoly is padded with 0 to ease proof polyEvals, _, err := g.ExtendPolyEval(polyCoeffs) if err != nil { - return nil, nil, nil, err - } - - poly := &GlobalPoly{ - Values: polyEvals, - Coeffs: polyCoeffs, + return nil, nil, err } if g.verbose { @@ -57,13 +52,13 @@ func (g *Encoder) Encode(inputFr []fr.Element) (*GlobalPoly, []Frame, []uint32, // create frames to group relevant info frames, indices, err := g.MakeFrames(polyEvals) if err != nil { - return nil, nil, nil, err + return nil, nil, err } log.Printf(" SUMMARY: RSEncode %v byte among %v numChunks with chunkLength %v takes %v\n", len(inputFr)*encoding.BYTES_PER_SYMBOL, g.NumChunks, g.ChunkLength, time.Since(start)) - return poly, frames, indices, nil + return frames, indices, nil } // MakeFrames function takes extended evaluation data and bundles relevant information into Frame. diff --git a/encoding/rs/encode_test.go b/encoding/rs/encode_test.go index 832e369b5..fd43fec67 100644 --- a/encoding/rs/encode_test.go +++ b/encoding/rs/encode_test.go @@ -22,7 +22,7 @@ func TestEncodeDecode_InvertsWhenSamplingAllFrames(t *testing.T) { inputFr, err := rs.ToFrArray(GETTYSBURG_ADDRESS_BYTES) assert.Nil(t, err) - _, frames, _, err := enc.Encode(inputFr) + frames, _, err := enc.Encode(inputFr) assert.Nil(t, err) // sample some frames @@ -45,7 +45,7 @@ func TestEncodeDecode_InvertsWhenSamplingMissingFrame(t *testing.T) { inputFr, err := rs.ToFrArray(GETTYSBURG_ADDRESS_BYTES) assert.Nil(t, err) - _, frames, _, err := enc.Encode(inputFr) + frames, _, err := enc.Encode(inputFr) assert.Nil(t, err) // sample some frames @@ -70,7 +70,7 @@ func TestEncodeDecode_ErrorsWhenNotEnoughSampledFrames(t *testing.T) { inputFr, err := rs.ToFrArray(GETTYSBURG_ADDRESS_BYTES) assert.Nil(t, err) - _, frames, _, err := enc.Encode(inputFr) + frames, _, err := enc.Encode(inputFr) assert.Nil(t, err) // sample some frames diff --git a/encoding/rs/encoder_fuzz_test.go b/encoding/rs/encoder_fuzz_test.go index 0c70d5464..b9eb1a7bc 100644 --- a/encoding/rs/encoder_fuzz_test.go +++ b/encoding/rs/encoder_fuzz_test.go @@ -20,7 +20,7 @@ func FuzzOnlySystematic(f *testing.F) { } //encode the data - _, frames, _, err := enc.EncodeBytes(input) + frames, _, err := enc.EncodeBytes(input) if err != nil { t.Errorf("Error Encoding:\n Data:\n %q \n Err: %q", input, err) } diff --git a/encoding/rs/frame_test.go b/encoding/rs/frame_test.go index dc230664e..717b64ff7 100644 --- a/encoding/rs/frame_test.go +++ b/encoding/rs/frame_test.go @@ -17,7 +17,7 @@ func TestEncodeDecodeFrame_AreInverses(t *testing.T) { enc, _ := rs.NewEncoder(params, true) require.NotNil(t, enc) - _, frames, _, err := enc.EncodeBytes(GETTYSBURG_ADDRESS_BYTES) + frames, _, err := enc.EncodeBytes(GETTYSBURG_ADDRESS_BYTES) require.Nil(t, err) require.NotNil(t, frames, err) diff --git a/encoding/serialization_test.go b/encoding/serialization_test.go index ffc3d9895..94fe7ecaa 100644 --- a/encoding/serialization_test.go +++ b/encoding/serialization_test.go @@ -1,6 +1,7 @@ package encoding_test import ( + "math/rand" "testing" "github.com/Layr-Labs/eigenda/encoding" @@ -45,3 +46,74 @@ func TestSerDeserGnark(t *testing.T) { assert.True(t, f.Coeffs[i].Equal(&c.Coeffs[i])) } } + +func createFrames(b *testing.B, numFrames int) []encoding.Frame { + var XCoord, YCoord fp.Element + _, err := XCoord.SetString("21661178944771197726808973281966770251114553549453983978976194544185382599016") + assert.NoError(b, err) + _, err = YCoord.SetString("9207254729396071334325696286939045899948985698134704137261649190717970615186") + assert.NoError(b, err) + r := rand.New(rand.NewSource(2024)) + numCoeffs := 64 + frames := make([]encoding.Frame, numFrames) + for n := 0; n < numFrames; n++ { + frames[n].Proof = encoding.Proof{ + X: XCoord, + Y: YCoord, + } + for i := 0; i < numCoeffs; i++ { + frames[n].Coeffs = append(frames[n].Coeffs, fr.NewElement(r.Uint64())) + } + } + return frames +} + +func BenchmarkFrameGobSerialization(b *testing.B) { + numSamples := 64 + frames := createFrames(b, numSamples) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + _, _ = frames[i%numSamples].Serialize() + } +} + +func BenchmarkFrameGnarkSerialization(b *testing.B) { + numSamples := 64 + frames := createFrames(b, numSamples) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + _, _ = frames[i%numSamples].SerializeGnark() + } +} + +func BenchmarkFrameGobDeserialization(b *testing.B) { + numSamples := 64 + frames := createFrames(b, numSamples) + bytes := make([][]byte, numSamples) + for n := 0; n < numSamples; n++ { + gob, _ := frames[n].Serialize() + bytes[n] = gob + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + _, _ = new(encoding.Frame).Deserialize(bytes[i%numSamples]) + } +} + +func BenchmarkFrameGnarkDeserialization(b *testing.B) { + numSamples := 64 + frames := createFrames(b, numSamples) + bytes := make([][]byte, numSamples) + for n := 0; n < numSamples; n++ { + gnark, _ := frames[n].SerializeGnark() + bytes[n] = gnark + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + _, _ = new(encoding.Frame).DeserializeGnark(bytes[i%numSamples]) + } +} diff --git a/encoding/test/main.go b/encoding/test/main.go index c2b163935..fb8314c4d 100644 --- a/encoding/test/main.go +++ b/encoding/test/main.go @@ -18,14 +18,15 @@ import ( ) func main() { - // TestKzgRs() + TestKzgRs() //err := kzg.WriteGeneratorPoints(30000) //if err != nil { // log.Println("WriteGeneratorPoints failed:", err) //} - readpoints() + //readpoints() } +/* func readpoints() { kzgConfig := &kzg.KzgConfig{ G1Path: "../../inabox/resources/kzg/g1.point", @@ -47,9 +48,10 @@ func readpoints() { fmt.Println("start with gen") } } +*/ func TestKzgRs() { - numSymbols := 3 + numSymbols := 1024 // encode parameters numNode := uint64(4) // 200 numSys := uint64(2) // 180 @@ -61,18 +63,19 @@ func TestKzgRs() { //fmt.Printf(" Data size(byte): %v\n", len(inputBytes)) kzgConfig := &kzg.KzgConfig{ - G1Path: "g1.point", - G2Path: "g2.point", + G1Path: "../../inabox/resources/kzg/g1.point", + G2Path: "../../inabox/resources/kzg/g2.point", CacheDir: "SRSTables", SRSOrder: 3000, SRSNumberToLoad: 3000, NumWorker: uint64(runtime.GOMAXPROCS(0)), + Verbose: true, } // create encoding object p, _ := prover.NewProver(kzgConfig, true) - params := encoding.EncodingParams{NumChunks: 200, ChunkLength: 180} + params := encoding.EncodingParams{NumChunks: numNode, ChunkLength: uint64(numSymbols) / numSys} enc, _ := p.GetKzgEncoder(params) //inputFr := kzg.ToFrArray(inputBytes) diff --git a/go.mod b/go.mod index ed50d2642..2bad729c8 100644 --- a/go.mod +++ b/go.mod @@ -195,7 +195,7 @@ require ( github.com/prometheus/procfs v0.12.0 // indirect github.com/rogpeppe/go-internal v1.10.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect + github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible github.com/stretchr/objx v0.5.2 // indirect github.com/swaggo/files v1.0.1 github.com/swaggo/gin-swagger v1.6.0 diff --git a/inabox/README.md b/inabox/README.md index 947dd389f..746a11c45 100644 --- a/inabox/README.md +++ b/inabox/README.md @@ -139,7 +139,9 @@ Disperse a blob: # This command uses `grpcurl`, a tool to send gRPC request in cli # To install `grpcurl`, run `brew install grpcurl` or `go install github.com/fullstorydev/grpcurl/cmd/grpcurl@latest` -$ grpcurl -plaintext -d '{"data": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "security_params": [{"quorum_id": 0, "adversary_threshold": 50, "quorum_threshold": 100}]}' localhost:32003 disperser.Disperser/DisperseBlob +# From top level eigenda directory +$ grpcurl -plaintext -d '{"data": "'$(tools/kzgpad/bin/kzgpad -e hello)'"}' \ + localhost:32003 disperser.Disperser/DisperseBlob ``` Look for logs such as the following to indicate that the disperser has successfully confirmed the batch: diff --git a/inabox/deploy/config.go b/inabox/deploy/config.go index 5b1614f40..c73f4794d 100644 --- a/inabox/deploy/config.go +++ b/inabox/deploy/config.go @@ -221,7 +221,7 @@ func (env *Config) generateBatcherVars(ind int, key, graphUrl, logPath string) B BATCHER_ENCODING_REQUEST_QUEUE_SIZE: "500", BATCHER_NUM_CONFIRMATIONS: "0", BATCHER_MAX_BLOBS_TO_FETCH_FROM_STORE: "100", - BATCHER_FINALIZATION_BLOCK_DELAY: "5", + BATCHER_FINALIZATION_BLOCK_DELAY: "0", BATCHER_KMS_KEY_DISABLE: "true", } diff --git a/node/Makefile b/node/Makefile index 6b2715211..7a7455f9a 100644 --- a/node/Makefile +++ b/node/Makefile @@ -19,9 +19,18 @@ build: clean go mod tidy go build -o ./bin/node ./cmd +proto: + cd .. && make protoc + clean: rm -rf ./bin +lint: + golangci-lint run + +test: + go test -short ./... + docker: docker-node docker-plugin docker-node: diff --git a/node/config.go b/node/config.go index e1f09ec1a..8a2d95143 100644 --- a/node/config.go +++ b/node/config.go @@ -31,9 +31,9 @@ var ( // this is used for eigen metrics QuorumNames = map[core.QuorumID]string{ 0: "eth_quorum", - 1: "permissioned_quorum", + 1: "eignen_quorum", } - SemVer = "v0.0.0" + SemVer = "0.0.0" GitCommit = "" GitDate = "" ) @@ -72,6 +72,7 @@ type Config struct { ClientIPHeader string UseSecureGrpc bool ReachabilityPollIntervalSec uint64 + DisableNodeInfoResources bool EthClientConfig geth.EthClientConfig LoggerConfig common.LoggerConfig @@ -201,5 +202,6 @@ func NewConfig(ctx *cli.Context) (*Config, error) { NumBatchDeserializationWorkers: ctx.GlobalInt(flags.NumBatchDeserializationWorkersFlag.Name), ClientIPHeader: ctx.GlobalString(flags.ClientIPHeaderFlag.Name), UseSecureGrpc: ctx.GlobalBoolT(flags.ChurnerUseSecureGRPC.Name), + DisableNodeInfoResources: ctx.GlobalBool(flags.DisableNodeInfoResourcesFlag.Name), }, nil } diff --git a/node/flags/flags.go b/node/flags/flags.go index d6a5d8abf..7e81119c4 100644 --- a/node/flags/flags.go +++ b/node/flags/flags.go @@ -259,6 +259,13 @@ var ( Value: "", EnvVar: common.PrefixEnvVar(EnvVarPrefix, "CLIENT_IP_HEADER"), } + + DisableNodeInfoResourcesFlag = cli.BoolFlag{ + Name: common.PrefixFlag(FlagPrefix, "disable-node-info-resources"), + Usage: "Disable system resource information (OS, architecture, CPU, memory) on the NodeInfo API", + Required: false, + EnvVar: common.PrefixEnvVar(EnvVarPrefix, "DISABLE_NODE_INFO_RESOURCES"), + } ) var requiredFlags = []cli.Flag{ @@ -299,6 +306,7 @@ var optionalFlags = []cli.Flag{ EcdsaKeyFileFlag, EcdsaKeyPasswordFlag, DataApiUrlFlag, + DisableNodeInfoResourcesFlag, } func init() { diff --git a/node/grpc/server.go b/node/grpc/server.go index 45f77c150..b6dbae008 100644 --- a/node/grpc/server.go +++ b/node/grpc/server.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "runtime" "sync" "time" @@ -17,6 +18,9 @@ import ( "github.com/Layr-Labs/eigenda/encoding" "github.com/Layr-Labs/eigenda/node" "github.com/Layr-Labs/eigensdk-go/logging" + "github.com/shirou/gopsutil/mem" + + _ "go.uber.org/automaxprocs" "google.golang.org/grpc" "google.golang.org/grpc/reflection" @@ -130,6 +134,20 @@ func (s *Server) serveRetrieval() error { } +func (s *Server) NodeInfo(ctx context.Context, in *pb.NodeInfoRequest) (*pb.NodeInfoReply, error) { + if s.config.DisableNodeInfoResources { + return &pb.NodeInfoReply{Semver: node.SemVer}, nil + } + + memBytes := uint64(0) + v, err := mem.VirtualMemory() + if err == nil { + memBytes = v.Total + } + + return &pb.NodeInfoReply{Semver: node.SemVer, Os: runtime.GOOS, Arch: runtime.GOARCH, NumCpu: uint32(runtime.GOMAXPROCS(0)), MemBytes: memBytes}, nil +} + func (s *Server) handleStoreChunksRequest(ctx context.Context, in *pb.StoreChunksRequest) (*pb.StoreChunksReply, error) { start := time.Now() diff --git a/node/grpc/server_test.go b/node/grpc/server_test.go index 5bc8b5e27..84623ec94 100644 --- a/node/grpc/server_test.go +++ b/node/grpc/server_test.go @@ -278,6 +278,13 @@ func storeChunks(t *testing.T, server *grpc.Server) ([32]byte, [32]byte, []*core return batchHeaderHash, batchRoot, blobHeaders, blobHeadersProto } +func TestNodeInfoRequest(t *testing.T) { + server := newTestServer(t, true) + resp, err := server.NodeInfo(context.Background(), &pb.NodeInfoRequest{}) + assert.True(t, resp.Semver == "0.0.0") + assert.True(t, err == nil) +} + func TestStoreChunksRequestValidation(t *testing.T) { server := newTestServer(t, true)