diff --git a/proto/pb/validatorstate/validator_state.pb.go b/proto/pb/validatorstate/validator_state.pb.go index 591087a08342..055ed82b715b 100644 --- a/proto/pb/validatorstate/validator_state.pb.go +++ b/proto/pb/validatorstate/validator_state.pb.go @@ -264,20 +264,72 @@ func (x *GetValidatorSetRequest) GetSubnetId() []byte { return nil } +type GetCurrentValidatorSetRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + SubnetId []byte `protobuf:"bytes,1,opt,name=subnet_id,json=subnetId,proto3" json:"subnet_id,omitempty"` +} + +func (x *GetCurrentValidatorSetRequest) Reset() { + *x = GetCurrentValidatorSetRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_validatorstate_validator_state_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetCurrentValidatorSetRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetCurrentValidatorSetRequest) ProtoMessage() {} + +func (x *GetCurrentValidatorSetRequest) ProtoReflect() protoreflect.Message { + mi := &file_validatorstate_validator_state_proto_msgTypes[5] + 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 GetCurrentValidatorSetRequest.ProtoReflect.Descriptor instead. +func (*GetCurrentValidatorSetRequest) Descriptor() ([]byte, []int) { + return file_validatorstate_validator_state_proto_rawDescGZIP(), []int{5} +} + +func (x *GetCurrentValidatorSetRequest) GetSubnetId() []byte { + if x != nil { + return x.SubnetId + } + return nil +} + type Validator struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - NodeId []byte `protobuf:"bytes,1,opt,name=node_id,json=nodeId,proto3" json:"node_id,omitempty"` - Weight uint64 `protobuf:"varint,2,opt,name=weight,proto3" json:"weight,omitempty"` - PublicKey []byte `protobuf:"bytes,3,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"` + NodeId []byte `protobuf:"bytes,1,opt,name=node_id,json=nodeId,proto3" json:"node_id,omitempty"` + Weight uint64 `protobuf:"varint,2,opt,name=weight,proto3" json:"weight,omitempty"` + PublicKey []byte `protobuf:"bytes,3,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"` // Uncompressed public key, can be empty + StartTime uint64 `protobuf:"varint,4,opt,name=start_time,json=startTime,proto3" json:"start_time,omitempty"` // can be empty + MinNonce uint64 `protobuf:"varint,5,opt,name=min_nonce,json=minNonce,proto3" json:"min_nonce,omitempty"` // can be empty + IsActive bool `protobuf:"varint,6,opt,name=is_active,json=isActive,proto3" json:"is_active,omitempty"` // can be empty + ValidationId []byte `protobuf:"bytes,7,opt,name=validation_id,json=validationId,proto3" json:"validation_id,omitempty"` // can be empty + IsSov bool `protobuf:"varint,8,opt,name=is_sov,json=isSov,proto3" json:"is_sov,omitempty"` // can be empty } func (x *Validator) Reset() { *x = Validator{} if protoimpl.UnsafeEnabled { - mi := &file_validatorstate_validator_state_proto_msgTypes[5] + mi := &file_validatorstate_validator_state_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -290,7 +342,7 @@ func (x *Validator) String() string { func (*Validator) ProtoMessage() {} func (x *Validator) ProtoReflect() protoreflect.Message { - mi := &file_validatorstate_validator_state_proto_msgTypes[5] + mi := &file_validatorstate_validator_state_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -303,7 +355,7 @@ func (x *Validator) ProtoReflect() protoreflect.Message { // Deprecated: Use Validator.ProtoReflect.Descriptor instead. func (*Validator) Descriptor() ([]byte, []int) { - return file_validatorstate_validator_state_proto_rawDescGZIP(), []int{5} + return file_validatorstate_validator_state_proto_rawDescGZIP(), []int{6} } func (x *Validator) GetNodeId() []byte { @@ -327,6 +379,41 @@ func (x *Validator) GetPublicKey() []byte { return nil } +func (x *Validator) GetStartTime() uint64 { + if x != nil { + return x.StartTime + } + return 0 +} + +func (x *Validator) GetMinNonce() uint64 { + if x != nil { + return x.MinNonce + } + return 0 +} + +func (x *Validator) GetIsActive() bool { + if x != nil { + return x.IsActive + } + return false +} + +func (x *Validator) GetValidationId() []byte { + if x != nil { + return x.ValidationId + } + return nil +} + +func (x *Validator) GetIsSov() bool { + if x != nil { + return x.IsSov + } + return false +} + type GetValidatorSetResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -338,7 +425,7 @@ type GetValidatorSetResponse struct { func (x *GetValidatorSetResponse) Reset() { *x = GetValidatorSetResponse{} if protoimpl.UnsafeEnabled { - mi := &file_validatorstate_validator_state_proto_msgTypes[6] + mi := &file_validatorstate_validator_state_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -351,7 +438,7 @@ func (x *GetValidatorSetResponse) String() string { func (*GetValidatorSetResponse) ProtoMessage() {} func (x *GetValidatorSetResponse) ProtoReflect() protoreflect.Message { - mi := &file_validatorstate_validator_state_proto_msgTypes[6] + mi := &file_validatorstate_validator_state_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -364,7 +451,7 @@ func (x *GetValidatorSetResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetValidatorSetResponse.ProtoReflect.Descriptor instead. func (*GetValidatorSetResponse) Descriptor() ([]byte, []int) { - return file_validatorstate_validator_state_proto_rawDescGZIP(), []int{6} + return file_validatorstate_validator_state_proto_rawDescGZIP(), []int{7} } func (x *GetValidatorSetResponse) GetValidators() []*Validator { @@ -374,6 +461,61 @@ func (x *GetValidatorSetResponse) GetValidators() []*Validator { return nil } +type GetCurrentValidatorSetResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Validators []*Validator `protobuf:"bytes,1,rep,name=validators,proto3" json:"validators,omitempty"` + CurrentHeight uint64 `protobuf:"varint,2,opt,name=current_height,json=currentHeight,proto3" json:"current_height,omitempty"` +} + +func (x *GetCurrentValidatorSetResponse) Reset() { + *x = GetCurrentValidatorSetResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_validatorstate_validator_state_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetCurrentValidatorSetResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetCurrentValidatorSetResponse) ProtoMessage() {} + +func (x *GetCurrentValidatorSetResponse) ProtoReflect() protoreflect.Message { + mi := &file_validatorstate_validator_state_proto_msgTypes[8] + 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 GetCurrentValidatorSetResponse.ProtoReflect.Descriptor instead. +func (*GetCurrentValidatorSetResponse) Descriptor() ([]byte, []int) { + return file_validatorstate_validator_state_proto_rawDescGZIP(), []int{8} +} + +func (x *GetCurrentValidatorSetResponse) GetValidators() []*Validator { + if x != nil { + return x.Validators + } + return nil +} + +func (x *GetCurrentValidatorSetResponse) GetCurrentHeight() uint64 { + if x != nil { + return x.CurrentHeight + } + return 0 +} + var File_validatorstate_validator_state_proto protoreflect.FileDescriptor var file_validatorstate_validator_state_proto_rawDesc = []byte{ @@ -400,45 +542,75 @@ var file_validatorstate_validator_state_proto_rawDesc = []byte{ 0x69, 0x67, 0x68, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x73, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x49, 0x64, 0x22, - 0x5b, 0x0a, 0x09, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x17, 0x0a, 0x07, - 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x6e, - 0x6f, 0x64, 0x65, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x1d, 0x0a, - 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x22, 0x54, 0x0a, 0x17, - 0x47, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x65, 0x74, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x0a, 0x76, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x6f, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x76, 0x61, - 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x56, 0x61, 0x6c, - 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x0a, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, - 0x72, 0x73, 0x32, 0xf8, 0x02, 0x0a, 0x0e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, - 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x54, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x4d, 0x69, 0x6e, 0x69, - 0x6d, 0x75, 0x6d, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, - 0x79, 0x1a, 0x28, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x74, 0x61, - 0x74, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x48, 0x65, 0x69, - 0x67, 0x68, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x10, 0x47, - 0x65, 0x74, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, - 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x28, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x6f, 0x72, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x75, 0x72, 0x72, - 0x65, 0x6e, 0x74, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x56, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x49, 0x44, - 0x12, 0x22, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x74, 0x61, 0x74, - 0x65, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x49, 0x44, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, - 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x49, - 0x44, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x62, 0x0a, 0x0f, 0x47, 0x65, 0x74, - 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x65, 0x74, 0x12, 0x26, 0x2e, 0x76, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x47, 0x65, - 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x65, 0x74, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, - 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, - 0x6f, 0x72, 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x39, 0x5a, - 0x37, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x76, 0x61, 0x2d, - 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x61, 0x76, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x68, 0x65, 0x67, 0x6f, - 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x62, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x6f, 0x72, 0x73, 0x74, 0x61, 0x74, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x3c, 0x0a, 0x1d, 0x47, 0x65, 0x74, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x56, 0x61, 0x6c, + 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x08, 0x73, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x49, 0x64, 0x22, 0xf0, 0x01, + 0x0a, 0x09, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x17, 0x0a, 0x07, 0x6e, + 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x6e, 0x6f, + 0x64, 0x65, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x1d, 0x0a, 0x0a, + 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x73, + 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x69, + 0x6e, 0x5f, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x6d, + 0x69, 0x6e, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x69, 0x73, 0x5f, 0x61, 0x63, + 0x74, 0x69, 0x76, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x69, 0x73, 0x41, 0x63, + 0x74, 0x69, 0x76, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x76, 0x61, 0x6c, + 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x15, 0x0a, 0x06, 0x69, 0x73, 0x5f, + 0x73, 0x6f, 0x76, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x69, 0x73, 0x53, 0x6f, 0x76, + 0x22, 0x54, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, + 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x0a, 0x76, + 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x19, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x74, 0x61, 0x74, 0x65, + 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x0a, 0x76, 0x61, 0x6c, 0x69, + 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x22, 0x82, 0x01, 0x0a, 0x1e, 0x47, 0x65, 0x74, 0x43, 0x75, + 0x72, 0x72, 0x65, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x65, + 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x0a, 0x76, 0x61, 0x6c, + 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, + 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x56, + 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x0a, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, + 0x74, 0x6f, 0x72, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, + 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x63, 0x75, + 0x72, 0x72, 0x65, 0x6e, 0x74, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x32, 0xf1, 0x03, 0x0a, 0x0e, + 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x54, + 0x0a, 0x10, 0x47, 0x65, 0x74, 0x4d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x48, 0x65, 0x69, 0x67, + 0x68, 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x28, 0x2e, 0x76, 0x61, 0x6c, + 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x4d, + 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x43, 0x75, 0x72, 0x72, 0x65, + 0x6e, 0x74, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, + 0x1a, 0x28, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x74, 0x61, 0x74, + 0x65, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x48, 0x65, 0x69, 0x67, + 0x68, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x0b, 0x47, 0x65, + 0x74, 0x53, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x49, 0x44, 0x12, 0x22, 0x2e, 0x76, 0x61, 0x6c, 0x69, + 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x75, + 0x62, 0x6e, 0x65, 0x74, 0x49, 0x44, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, + 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x47, + 0x65, 0x74, 0x53, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x49, 0x44, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x62, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, + 0x6f, 0x72, 0x53, 0x65, 0x74, 0x12, 0x26, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, + 0x72, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, + 0x74, 0x6f, 0x72, 0x53, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, + 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x47, + 0x65, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x65, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x77, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x43, 0x75, 0x72, + 0x72, 0x65, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x65, 0x74, + 0x12, 0x2d, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x74, 0x61, 0x74, + 0x65, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x69, + 0x64, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x2e, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x74, 0x61, 0x74, 0x65, + 0x2e, 0x47, 0x65, 0x74, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, + 0x61, 0x74, 0x6f, 0x72, 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, + 0x39, 0x5a, 0x37, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x76, + 0x61, 0x2d, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x61, 0x76, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x68, 0x65, + 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x62, 0x2f, 0x76, 0x61, 0x6c, 0x69, + 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x74, 0x61, 0x74, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, } var ( @@ -453,32 +625,37 @@ func file_validatorstate_validator_state_proto_rawDescGZIP() []byte { return file_validatorstate_validator_state_proto_rawDescData } -var file_validatorstate_validator_state_proto_msgTypes = make([]protoimpl.MessageInfo, 7) +var file_validatorstate_validator_state_proto_msgTypes = make([]protoimpl.MessageInfo, 9) var file_validatorstate_validator_state_proto_goTypes = []interface{}{ - (*GetMinimumHeightResponse)(nil), // 0: validatorstate.GetMinimumHeightResponse - (*GetCurrentHeightResponse)(nil), // 1: validatorstate.GetCurrentHeightResponse - (*GetSubnetIDRequest)(nil), // 2: validatorstate.GetSubnetIDRequest - (*GetSubnetIDResponse)(nil), // 3: validatorstate.GetSubnetIDResponse - (*GetValidatorSetRequest)(nil), // 4: validatorstate.GetValidatorSetRequest - (*Validator)(nil), // 5: validatorstate.Validator - (*GetValidatorSetResponse)(nil), // 6: validatorstate.GetValidatorSetResponse - (*emptypb.Empty)(nil), // 7: google.protobuf.Empty + (*GetMinimumHeightResponse)(nil), // 0: validatorstate.GetMinimumHeightResponse + (*GetCurrentHeightResponse)(nil), // 1: validatorstate.GetCurrentHeightResponse + (*GetSubnetIDRequest)(nil), // 2: validatorstate.GetSubnetIDRequest + (*GetSubnetIDResponse)(nil), // 3: validatorstate.GetSubnetIDResponse + (*GetValidatorSetRequest)(nil), // 4: validatorstate.GetValidatorSetRequest + (*GetCurrentValidatorSetRequest)(nil), // 5: validatorstate.GetCurrentValidatorSetRequest + (*Validator)(nil), // 6: validatorstate.Validator + (*GetValidatorSetResponse)(nil), // 7: validatorstate.GetValidatorSetResponse + (*GetCurrentValidatorSetResponse)(nil), // 8: validatorstate.GetCurrentValidatorSetResponse + (*emptypb.Empty)(nil), // 9: google.protobuf.Empty } var file_validatorstate_validator_state_proto_depIdxs = []int32{ - 5, // 0: validatorstate.GetValidatorSetResponse.validators:type_name -> validatorstate.Validator - 7, // 1: validatorstate.ValidatorState.GetMinimumHeight:input_type -> google.protobuf.Empty - 7, // 2: validatorstate.ValidatorState.GetCurrentHeight:input_type -> google.protobuf.Empty - 2, // 3: validatorstate.ValidatorState.GetSubnetID:input_type -> validatorstate.GetSubnetIDRequest - 4, // 4: validatorstate.ValidatorState.GetValidatorSet:input_type -> validatorstate.GetValidatorSetRequest - 0, // 5: validatorstate.ValidatorState.GetMinimumHeight:output_type -> validatorstate.GetMinimumHeightResponse - 1, // 6: validatorstate.ValidatorState.GetCurrentHeight:output_type -> validatorstate.GetCurrentHeightResponse - 3, // 7: validatorstate.ValidatorState.GetSubnetID:output_type -> validatorstate.GetSubnetIDResponse - 6, // 8: validatorstate.ValidatorState.GetValidatorSet:output_type -> validatorstate.GetValidatorSetResponse - 5, // [5:9] is the sub-list for method output_type - 1, // [1:5] is the sub-list for method input_type - 1, // [1:1] is the sub-list for extension type_name - 1, // [1:1] is the sub-list for extension extendee - 0, // [0:1] is the sub-list for field type_name + 6, // 0: validatorstate.GetValidatorSetResponse.validators:type_name -> validatorstate.Validator + 6, // 1: validatorstate.GetCurrentValidatorSetResponse.validators:type_name -> validatorstate.Validator + 9, // 2: validatorstate.ValidatorState.GetMinimumHeight:input_type -> google.protobuf.Empty + 9, // 3: validatorstate.ValidatorState.GetCurrentHeight:input_type -> google.protobuf.Empty + 2, // 4: validatorstate.ValidatorState.GetSubnetID:input_type -> validatorstate.GetSubnetIDRequest + 4, // 5: validatorstate.ValidatorState.GetValidatorSet:input_type -> validatorstate.GetValidatorSetRequest + 5, // 6: validatorstate.ValidatorState.GetCurrentValidatorSet:input_type -> validatorstate.GetCurrentValidatorSetRequest + 0, // 7: validatorstate.ValidatorState.GetMinimumHeight:output_type -> validatorstate.GetMinimumHeightResponse + 1, // 8: validatorstate.ValidatorState.GetCurrentHeight:output_type -> validatorstate.GetCurrentHeightResponse + 3, // 9: validatorstate.ValidatorState.GetSubnetID:output_type -> validatorstate.GetSubnetIDResponse + 7, // 10: validatorstate.ValidatorState.GetValidatorSet:output_type -> validatorstate.GetValidatorSetResponse + 8, // 11: validatorstate.ValidatorState.GetCurrentValidatorSet:output_type -> validatorstate.GetCurrentValidatorSetResponse + 7, // [7:12] is the sub-list for method output_type + 2, // [2:7] is the sub-list for method input_type + 2, // [2:2] is the sub-list for extension type_name + 2, // [2:2] is the sub-list for extension extendee + 0, // [0:2] is the sub-list for field type_name } func init() { file_validatorstate_validator_state_proto_init() } @@ -548,7 +725,7 @@ func file_validatorstate_validator_state_proto_init() { } } file_validatorstate_validator_state_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Validator); i { + switch v := v.(*GetCurrentValidatorSetRequest); i { case 0: return &v.state case 1: @@ -560,6 +737,18 @@ func file_validatorstate_validator_state_proto_init() { } } file_validatorstate_validator_state_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Validator); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_validatorstate_validator_state_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GetValidatorSetResponse); i { case 0: return &v.state @@ -571,6 +760,18 @@ func file_validatorstate_validator_state_proto_init() { return nil } } + file_validatorstate_validator_state_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetCurrentValidatorSetResponse); 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{ @@ -578,7 +779,7 @@ func file_validatorstate_validator_state_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_validatorstate_validator_state_proto_rawDesc, NumEnums: 0, - NumMessages: 7, + NumMessages: 9, NumExtensions: 0, NumServices: 1, }, diff --git a/proto/pb/validatorstate/validator_state_grpc.pb.go b/proto/pb/validatorstate/validator_state_grpc.pb.go index 8dc2137aad90..4e5792eb6e3d 100644 --- a/proto/pb/validatorstate/validator_state_grpc.pb.go +++ b/proto/pb/validatorstate/validator_state_grpc.pb.go @@ -20,10 +20,11 @@ import ( const _ = grpc.SupportPackageIsVersion7 const ( - ValidatorState_GetMinimumHeight_FullMethodName = "/validatorstate.ValidatorState/GetMinimumHeight" - ValidatorState_GetCurrentHeight_FullMethodName = "/validatorstate.ValidatorState/GetCurrentHeight" - ValidatorState_GetSubnetID_FullMethodName = "/validatorstate.ValidatorState/GetSubnetID" - ValidatorState_GetValidatorSet_FullMethodName = "/validatorstate.ValidatorState/GetValidatorSet" + ValidatorState_GetMinimumHeight_FullMethodName = "/validatorstate.ValidatorState/GetMinimumHeight" + ValidatorState_GetCurrentHeight_FullMethodName = "/validatorstate.ValidatorState/GetCurrentHeight" + ValidatorState_GetSubnetID_FullMethodName = "/validatorstate.ValidatorState/GetSubnetID" + ValidatorState_GetValidatorSet_FullMethodName = "/validatorstate.ValidatorState/GetValidatorSet" + ValidatorState_GetCurrentValidatorSet_FullMethodName = "/validatorstate.ValidatorState/GetCurrentValidatorSet" ) // ValidatorStateClient is the client API for ValidatorState service. @@ -40,6 +41,9 @@ type ValidatorStateClient interface { // GetValidatorSet returns the weights of the nodeIDs for the provided // subnet at the requested P-chain height. GetValidatorSet(ctx context.Context, in *GetValidatorSetRequest, opts ...grpc.CallOption) (*GetValidatorSetResponse, error) + // GetCurrentValidatorSet returns the validator set for the provided subnet at + // the current P-chain height. + GetCurrentValidatorSet(ctx context.Context, in *GetCurrentValidatorSetRequest, opts ...grpc.CallOption) (*GetCurrentValidatorSetResponse, error) } type validatorStateClient struct { @@ -86,6 +90,15 @@ func (c *validatorStateClient) GetValidatorSet(ctx context.Context, in *GetValid return out, nil } +func (c *validatorStateClient) GetCurrentValidatorSet(ctx context.Context, in *GetCurrentValidatorSetRequest, opts ...grpc.CallOption) (*GetCurrentValidatorSetResponse, error) { + out := new(GetCurrentValidatorSetResponse) + err := c.cc.Invoke(ctx, ValidatorState_GetCurrentValidatorSet_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // ValidatorStateServer is the server API for ValidatorState service. // All implementations must embed UnimplementedValidatorStateServer // for forward compatibility @@ -100,6 +113,9 @@ type ValidatorStateServer interface { // GetValidatorSet returns the weights of the nodeIDs for the provided // subnet at the requested P-chain height. GetValidatorSet(context.Context, *GetValidatorSetRequest) (*GetValidatorSetResponse, error) + // GetCurrentValidatorSet returns the validator set for the provided subnet at + // the current P-chain height. + GetCurrentValidatorSet(context.Context, *GetCurrentValidatorSetRequest) (*GetCurrentValidatorSetResponse, error) mustEmbedUnimplementedValidatorStateServer() } @@ -119,6 +135,9 @@ func (UnimplementedValidatorStateServer) GetSubnetID(context.Context, *GetSubnet func (UnimplementedValidatorStateServer) GetValidatorSet(context.Context, *GetValidatorSetRequest) (*GetValidatorSetResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method GetValidatorSet not implemented") } +func (UnimplementedValidatorStateServer) GetCurrentValidatorSet(context.Context, *GetCurrentValidatorSetRequest) (*GetCurrentValidatorSetResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetCurrentValidatorSet not implemented") +} func (UnimplementedValidatorStateServer) mustEmbedUnimplementedValidatorStateServer() {} // UnsafeValidatorStateServer may be embedded to opt out of forward compatibility for this service. @@ -204,6 +223,24 @@ func _ValidatorState_GetValidatorSet_Handler(srv interface{}, ctx context.Contex return interceptor(ctx, in, info, handler) } +func _ValidatorState_GetCurrentValidatorSet_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetCurrentValidatorSetRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ValidatorStateServer).GetCurrentValidatorSet(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ValidatorState_GetCurrentValidatorSet_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ValidatorStateServer).GetCurrentValidatorSet(ctx, req.(*GetCurrentValidatorSetRequest)) + } + return interceptor(ctx, in, info, handler) +} + // ValidatorState_ServiceDesc is the grpc.ServiceDesc for ValidatorState service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -227,6 +264,10 @@ var ValidatorState_ServiceDesc = grpc.ServiceDesc{ MethodName: "GetValidatorSet", Handler: _ValidatorState_GetValidatorSet_Handler, }, + { + MethodName: "GetCurrentValidatorSet", + Handler: _ValidatorState_GetCurrentValidatorSet_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "validatorstate/validator_state.proto", diff --git a/proto/validatorstate/validator_state.proto b/proto/validatorstate/validator_state.proto index 6d2900f08a01..10170f2e5870 100644 --- a/proto/validatorstate/validator_state.proto +++ b/proto/validatorstate/validator_state.proto @@ -17,6 +17,9 @@ service ValidatorState { // GetValidatorSet returns the weights of the nodeIDs for the provided // subnet at the requested P-chain height. rpc GetValidatorSet(GetValidatorSetRequest) returns (GetValidatorSetResponse); + // GetCurrentValidatorSet returns the validator set for the provided subnet at + // the current P-chain height. + rpc GetCurrentValidatorSet(GetCurrentValidatorSetRequest) returns (GetCurrentValidatorSetResponse); } message GetMinimumHeightResponse { @@ -40,12 +43,26 @@ message GetValidatorSetRequest { bytes subnet_id = 2; } +message GetCurrentValidatorSetRequest { + bytes subnet_id = 1; +} + message Validator { bytes node_id = 1; uint64 weight = 2; - bytes public_key = 3; + bytes public_key = 3; // Uncompressed public key, can be empty + uint64 start_time = 4; // can be empty + uint64 min_nonce = 5; // can be empty + bool is_active = 6; // can be empty + bytes validation_id = 7; // can be empty + bool is_sov = 8; // can be empty } message GetValidatorSetResponse { repeated Validator validators = 1; } + +message GetCurrentValidatorSetResponse { + repeated Validator validators = 1; + uint64 current_height = 2; +} diff --git a/snow/validators/gvalidators/validator_state_client.go b/snow/validators/gvalidators/validator_state_client.go index 60c7a17cd9c8..0fb10fad4d3a 100644 --- a/snow/validators/gvalidators/validator_state_client.go +++ b/snow/validators/gvalidators/validator_state_client.go @@ -94,3 +94,51 @@ func (c *Client) GetValidatorSet( } return vdrs, nil } + +func (c *Client) GetCurrentValidatorSet( + ctx context.Context, + subnetID ids.ID, +) (map[ids.ID]*validators.GetCurrentValidatorOutput, uint64, error) { + resp, err := c.client.GetCurrentValidatorSet(ctx, &pb.GetCurrentValidatorSetRequest{ + SubnetId: subnetID[:], + }) + if err != nil { + return nil, 0, err + } + + vdrs := make(map[ids.ID]*validators.GetCurrentValidatorOutput, len(resp.Validators)) + for _, validator := range resp.Validators { + nodeID, err := ids.ToNodeID(validator.NodeId) + if err != nil { + return nil, 0, err + } + var publicKey *bls.PublicKey + if len(validator.PublicKey) > 0 { + // PublicKeyFromValidUncompressedBytes is used rather than + // PublicKeyFromCompressedBytes because it is significantly faster + // due to the avoidance of decompression and key re-verification. We + // can safely assume that the BLS Public Keys are verified before + // being added to the P-Chain and served by the gRPC server. + publicKey = bls.PublicKeyFromValidUncompressedBytes(validator.PublicKey) + if publicKey == nil { + return nil, 0, errFailedPublicKeyDeserialize + } + } + validationID, err := ids.ToID(validator.ValidationId) + if err != nil { + return nil, 0, err + } + + vdrs[validationID] = &validators.GetCurrentValidatorOutput{ + ValidationID: validationID, + NodeID: nodeID, + PublicKey: publicKey, + Weight: validator.Weight, + StartTime: validator.StartTime, + MinNonce: validator.MinNonce, + IsActive: validator.IsActive, + IsSoV: validator.IsSov, + } + } + return vdrs, resp.GetCurrentHeight(), nil +} diff --git a/snow/validators/gvalidators/validator_state_server.go b/snow/validators/gvalidators/validator_state_server.go index 5eec541af589..d58c61099319 100644 --- a/snow/validators/gvalidators/validator_state_server.go +++ b/snow/validators/gvalidators/validator_state_server.go @@ -80,3 +80,42 @@ func (s *Server) GetValidatorSet(ctx context.Context, req *pb.GetValidatorSetReq } return resp, nil } + +func (s *Server) GetCurrentValidatorSet(ctx context.Context, req *pb.GetCurrentValidatorSetRequest) (*pb.GetCurrentValidatorSetResponse, error) { + subnetID, err := ids.ToID(req.SubnetId) + if err != nil { + return nil, err + } + + vdrs, currentHeight, err := s.state.GetCurrentValidatorSet(ctx, subnetID) + if err != nil { + return nil, err + } + + resp := &pb.GetCurrentValidatorSetResponse{ + Validators: make([]*pb.Validator, len(vdrs)), + CurrentHeight: currentHeight, + } + + i := 0 + for _, vdr := range vdrs { + vdrPB := &pb.Validator{ + NodeId: vdr.NodeID.Bytes(), + StartTime: vdr.StartTime, + IsActive: vdr.IsActive, + ValidationId: vdr.ValidationID[:], + Weight: vdr.Weight, + MinNonce: vdr.MinNonce, + IsSov: vdr.IsSoV, + } + if vdr.PublicKey != nil { + // Passing in the uncompressed bytes is a performance optimization + // to avoid the cost of calling PublicKeyFromCompressedBytes on the + // client side. + vdrPB.PublicKey = bls.PublicKeyToUncompressedBytes(vdr.PublicKey) + } + resp.Validators[i] = vdrPB + i++ + } + return resp, nil +} diff --git a/snow/validators/state.go b/snow/validators/state.go index 3f92df35231b..cbf8b4d6b8e0 100644 --- a/snow/validators/state.go +++ b/snow/validators/state.go @@ -32,6 +32,14 @@ type State interface { height uint64, subnetID ids.ID, ) (map[ids.NodeID]*GetValidatorOutput, error) + + // GetCurrentValidatorSet returns the current validators of the provided subnet + // and the current P-Chain height. + // Map is keyed by ValidationID. + GetCurrentValidatorSet( + ctx context.Context, + subnetID ids.ID, + ) (map[ids.ID]*GetCurrentValidatorOutput, uint64, error) } type lockedState struct { @@ -78,6 +86,16 @@ func (s *lockedState) GetValidatorSet( return s.s.GetValidatorSet(ctx, height, subnetID) } +func (s *lockedState) GetCurrentValidatorSet( + ctx context.Context, + subnetID ids.ID, +) (map[ids.ID]*GetCurrentValidatorOutput, uint64, error) { + s.lock.Lock() + defer s.lock.Unlock() + + return s.s.GetCurrentValidatorSet(ctx, subnetID) +} + type noValidators struct { State } @@ -91,3 +109,8 @@ func NewNoValidatorsState(state State) State { func (*noValidators) GetValidatorSet(context.Context, uint64, ids.ID) (map[ids.NodeID]*GetValidatorOutput, error) { return nil, nil } + +func (n *noValidators) GetCurrentValidatorSet(ctx context.Context, _ ids.ID) (map[ids.ID]*GetCurrentValidatorOutput, uint64, error) { + height, err := n.GetCurrentHeight(ctx) + return nil, height, err +} diff --git a/snow/validators/traced_state.go b/snow/validators/traced_state.go index 1116ab9d7e79..e5ab60f46455 100644 --- a/snow/validators/traced_state.go +++ b/snow/validators/traced_state.go @@ -17,22 +17,24 @@ import ( var _ State = (*tracedState)(nil) type tracedState struct { - s State - getMinimumHeightTag string - getCurrentHeightTag string - getSubnetIDTag string - getValidatorSetTag string - tracer trace.Tracer + s State + getMinimumHeightTag string + getCurrentHeightTag string + getSubnetIDTag string + getValidatorSetTag string + getCurrentValidatorSetTag string + tracer trace.Tracer } func Trace(s State, name string, tracer trace.Tracer) State { return &tracedState{ - s: s, - getMinimumHeightTag: name + ".GetMinimumHeight", - getCurrentHeightTag: name + ".GetCurrentHeight", - getSubnetIDTag: name + ".GetSubnetID", - getValidatorSetTag: name + ".GetValidatorSet", - tracer: tracer, + s: s, + getMinimumHeightTag: name + ".GetMinimumHeight", + getCurrentHeightTag: name + ".GetCurrentHeight", + getSubnetIDTag: name + ".GetSubnetID", + getValidatorSetTag: name + ".GetValidatorSet", + getCurrentValidatorSetTag: name + ".GetCurrentValidatorSet", + tracer: tracer, } } @@ -72,3 +74,15 @@ func (s *tracedState) GetValidatorSet( return s.s.GetValidatorSet(ctx, height, subnetID) } + +func (s *tracedState) GetCurrentValidatorSet( + ctx context.Context, + subnetID ids.ID, +) (map[ids.ID]*GetCurrentValidatorOutput, uint64, error) { + ctx, span := s.tracer.Start(ctx, s.getCurrentValidatorSetTag, oteltrace.WithAttributes( + attribute.Stringer("subnetID", subnetID), + )) + defer span.End() + + return s.s.GetCurrentValidatorSet(ctx, subnetID) +} diff --git a/snow/validators/validator.go b/snow/validators/validator.go index 499b5189e424..4e11c0cc0085 100644 --- a/snow/validators/validator.go +++ b/snow/validators/validator.go @@ -29,3 +29,14 @@ type GetValidatorOutput struct { PublicKey *bls.PublicKey Weight uint64 } + +type GetCurrentValidatorOutput struct { + ValidationID ids.ID + NodeID ids.NodeID + PublicKey *bls.PublicKey + Weight uint64 + StartTime uint64 + MinNonce uint64 + IsActive bool + IsSoV bool +} diff --git a/snow/validators/validatorsmock/state.go b/snow/validators/validatorsmock/state.go index 7bf898d0d4e8..feb6cdbb57ae 100644 --- a/snow/validators/validatorsmock/state.go +++ b/snow/validators/validatorsmock/state.go @@ -56,6 +56,22 @@ func (mr *StateMockRecorder) GetCurrentHeight(arg0 any) *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCurrentHeight", reflect.TypeOf((*State)(nil).GetCurrentHeight), arg0) } +// GetCurrentValidatorSet mocks base method. +func (m *State) GetCurrentValidatorSet(arg0 context.Context, arg1 ids.ID) (map[ids.ID]*validators.GetCurrentValidatorOutput, uint64, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetCurrentValidatorSet", arg0, arg1) + ret0, _ := ret[0].(map[ids.ID]*validators.GetCurrentValidatorOutput) + ret1, _ := ret[1].(uint64) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// GetCurrentValidatorSet indicates an expected call of GetCurrentValidatorSet. +func (mr *StateMockRecorder) GetCurrentValidatorSet(arg0, arg1 any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCurrentValidatorSet", reflect.TypeOf((*State)(nil).GetCurrentValidatorSet), arg0, arg1) +} + // GetMinimumHeight mocks base method. func (m *State) GetMinimumHeight(arg0 context.Context) (uint64, error) { m.ctrl.T.Helper() diff --git a/snow/validators/validatorstest/state.go b/snow/validators/validatorstest/state.go index aa85160af791..f2dfb02521ef 100644 --- a/snow/validators/validatorstest/state.go +++ b/snow/validators/validatorstest/state.go @@ -15,10 +15,11 @@ import ( ) var ( - errMinimumHeight = errors.New("unexpectedly called GetMinimumHeight") - errCurrentHeight = errors.New("unexpectedly called GetCurrentHeight") - errSubnetID = errors.New("unexpectedly called GetSubnetID") - errGetValidatorSet = errors.New("unexpectedly called GetValidatorSet") + errMinimumHeight = errors.New("unexpectedly called GetMinimumHeight") + errCurrentHeight = errors.New("unexpectedly called GetCurrentHeight") + errSubnetID = errors.New("unexpectedly called GetSubnetID") + errGetValidatorSet = errors.New("unexpectedly called GetValidatorSet") + errGetCurrentValidatorSet = errors.New("unexpectedly called GetCurrentValidatorSet") ) var _ validators.State = (*State)(nil) @@ -30,11 +31,13 @@ type State struct { CantGetCurrentHeight, CantGetSubnetID, CantGetValidatorSet bool + CantGetCurrentValidatorSet bool - GetMinimumHeightF func(ctx context.Context) (uint64, error) - GetCurrentHeightF func(ctx context.Context) (uint64, error) - GetSubnetIDF func(ctx context.Context, chainID ids.ID) (ids.ID, error) - GetValidatorSetF func(ctx context.Context, height uint64, subnetID ids.ID) (map[ids.NodeID]*validators.GetValidatorOutput, error) + GetMinimumHeightF func(ctx context.Context) (uint64, error) + GetCurrentHeightF func(ctx context.Context) (uint64, error) + GetSubnetIDF func(ctx context.Context, chainID ids.ID) (ids.ID, error) + GetValidatorSetF func(ctx context.Context, height uint64, subnetID ids.ID) (map[ids.NodeID]*validators.GetValidatorOutput, error) + GetCurrentValidatorSetF func(ctx context.Context, subnetID ids.ID) (map[ids.ID]*validators.GetCurrentValidatorOutput, uint64, error) } func (vm *State) GetMinimumHeight(ctx context.Context) (uint64, error) { @@ -80,3 +83,16 @@ func (vm *State) GetValidatorSet( } return nil, errGetValidatorSet } + +func (vm *State) GetCurrentValidatorSet( + ctx context.Context, + subnetID ids.ID, +) (map[ids.ID]*validators.GetCurrentValidatorOutput, uint64, error) { + if vm.GetCurrentValidatorSetF != nil { + return vm.GetCurrentValidatorSetF(ctx, subnetID) + } + if vm.CantGetCurrentValidatorSet && vm.T != nil { + require.FailNow(vm.T, errGetCurrentValidatorSet.Error()) + } + return nil, 0, errGetCurrentValidatorSet +} diff --git a/vms/platformvm/state/mock_state.go b/vms/platformvm/state/mock_state.go index 3deadddbe14e..b7fa1de35f8e 100644 --- a/vms/platformvm/state/mock_state.go +++ b/vms/platformvm/state/mock_state.go @@ -424,6 +424,22 @@ func (mr *MockStateMockRecorder) GetCurrentValidator(subnetID, nodeID any) *gomo return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCurrentValidator", reflect.TypeOf((*MockState)(nil).GetCurrentValidator), subnetID, nodeID) } +// GetCurrentValidatorSet mocks base method. +func (m *MockState) GetCurrentValidatorSet(ctx context.Context, subnetID ids.ID) (map[ids.ID]*validators.GetCurrentValidatorOutput, uint64, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetCurrentValidatorSet", ctx, subnetID) + ret0, _ := ret[0].(map[ids.ID]*validators.GetCurrentValidatorOutput) + ret1, _ := ret[1].(uint64) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// GetCurrentValidatorSet indicates an expected call of GetCurrentValidatorSet. +func (mr *MockStateMockRecorder) GetCurrentValidatorSet(ctx, subnetID any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCurrentValidatorSet", reflect.TypeOf((*MockState)(nil).GetCurrentValidatorSet), ctx, subnetID) +} + // GetDelegateeReward mocks base method. func (m *MockState) GetDelegateeReward(subnetID ids.ID, nodeID ids.NodeID) (uint64, error) { m.ctrl.T.Helper() diff --git a/vms/platformvm/state/state.go b/vms/platformvm/state/state.go index d2dfd34e47a8..17e4f85114b3 100644 --- a/vms/platformvm/state/state.go +++ b/vms/platformvm/state/state.go @@ -214,6 +214,8 @@ type State interface { SetHeight(height uint64) + GetCurrentValidatorSet(ctx context.Context, subnetID ids.ID) (map[ids.ID]*validators.GetCurrentValidatorOutput, uint64, error) + // Discard uncommitted changes to the database. Abort() @@ -831,6 +833,64 @@ func (s *state) DeleteExpiry(entry ExpiryEntry) { s.expiryDiff.DeleteExpiry(entry) } +func (s *state) GetCurrentValidatorSet(ctx context.Context, subnetID ids.ID) (map[ids.ID]*validators.GetCurrentValidatorOutput, uint64, error) { + result := make(map[ids.ID]*validators.GetCurrentValidatorOutput) + // First add the current validators (non-SoV) + for _, staker := range s.currentStakers.validators[subnetID] { + if err := ctx.Err(); err != nil { + return nil, 0, err + } + validator := staker.validator + result[validator.TxID] = &validators.GetCurrentValidatorOutput{ + ValidationID: validator.TxID, + NodeID: validator.NodeID, + PublicKey: validator.PublicKey, + Weight: validator.Weight, + StartTime: uint64(validator.StartTime.Unix()), + MinNonce: 0, + IsActive: true, + IsSoV: false, + } + } + + // Then iterate over subnetIDNodeID DB and add the SoV validators (if any) + // TODO: consider optimizing this to avoid hitting the subnetIDNodeIDDB and read from actives lookup + // if all validators are active (inactive weight is 0) + validationIDIter := s.subnetIDNodeIDDB.NewIteratorWithPrefix( + subnetID[:], + ) + defer validationIDIter.Release() + + for validationIDIter.Next() { + if err := ctx.Err(); err != nil { + return nil, 0, err + } + + validationID, err := ids.ToID(validationIDIter.Value()) + if err != nil { + return nil, 0, fmt.Errorf("failed to parse validation ID: %w", err) + } + + vdr, err := s.GetSubnetOnlyValidator(validationID) + if err != nil { + return nil, 0, fmt.Errorf("failed to get validator: %w", err) + } + + result[validationID] = &validators.GetCurrentValidatorOutput{ + ValidationID: validationID, + NodeID: vdr.NodeID, + PublicKey: bls.PublicKeyFromValidUncompressedBytes(vdr.PublicKey), + Weight: vdr.Weight, + StartTime: vdr.StartTime, + IsActive: vdr.isActive(), + MinNonce: vdr.MinNonce, + IsSoV: true, + } + } + + return result, s.currentHeight, nil +} + func (s *state) GetActiveSubnetOnlyValidatorsIterator() (iterator.Iterator[SubnetOnlyValidator], error) { return s.sovDiff.getActiveSubnetOnlyValidatorsIterator( s.activeSOVs.newIterator(), diff --git a/vms/platformvm/state/state_test.go b/vms/platformvm/state/state_test.go index 2905e54e2089..7ffe6541a536 100644 --- a/vms/platformvm/state/state_test.go +++ b/vms/platformvm/state/state_test.go @@ -2088,3 +2088,267 @@ func TestSubnetOnlyValidatorAfterLegacyRemoval(t *testing.T) { state.SetHeight(2) require.NoError(state.Commit()) } + +func TestGetCurrentValidators(t *testing.T) { + subnetID1 := ids.GenerateTestID() + subnetID2 := ids.GenerateTestID() + subnetIDs := []ids.ID{subnetID1, subnetID2} + + sk, err := bls.NewSecretKey() + require.NoError(t, err) + pk := bls.PublicFromSecretKey(sk) + pkBytes := bls.PublicKeyToUncompressedBytes(pk) + + otherSK, err := bls.NewSecretKey() + require.NoError(t, err) + otherPK := bls.PublicFromSecretKey(otherSK) + otherPKBytes := bls.PublicKeyToUncompressedBytes(otherPK) + now := time.Now() + + tests := []struct { + name string + initial []*Staker + sovs []SubnetOnlyValidator + }{ + { + name: "empty noop", + }, + { + name: "initial stakers in same subnet", + initial: []*Staker{ + { + TxID: ids.GenerateTestID(), + SubnetID: subnetID1, + NodeID: ids.GenerateTestNodeID(), + PublicKey: pk, + Weight: 1, + StartTime: now, + }, + { + TxID: ids.GenerateTestID(), + SubnetID: subnetID1, + NodeID: ids.GenerateTestNodeID(), + PublicKey: otherPK, + Weight: 1, + StartTime: now, + }, + }, + }, + { + name: "initial stakers in different subnets", + initial: []*Staker{ + { + TxID: ids.GenerateTestID(), + SubnetID: subnetID1, + NodeID: ids.GenerateTestNodeID(), + PublicKey: pk, + Weight: 1, + StartTime: now, + }, + { + TxID: ids.GenerateTestID(), + SubnetID: subnetID2, + NodeID: ids.GenerateTestNodeID(), + PublicKey: otherPK, + Weight: 1, + StartTime: now, + }, + }, + }, + { + name: "sovs only in same subnet", + sovs: []SubnetOnlyValidator{ + { + ValidationID: ids.GenerateTestID(), + SubnetID: subnetID1, + NodeID: ids.GenerateTestNodeID(), + StartTime: uint64(now.Unix()), + PublicKey: pkBytes, + Weight: 1, + }, + { + ValidationID: ids.GenerateTestID(), + SubnetID: subnetID1, + NodeID: ids.GenerateTestNodeID(), + PublicKey: otherPKBytes, + StartTime: uint64(now.Unix()), + Weight: 1, + }, + }, + }, + { + name: "sovs only in different subnets", + sovs: []SubnetOnlyValidator{ + { + ValidationID: ids.GenerateTestID(), + SubnetID: subnetID1, + NodeID: ids.GenerateTestNodeID(), + StartTime: uint64(now.Unix()), + PublicKey: pkBytes, + Weight: 1, + }, + { + ValidationID: ids.GenerateTestID(), + SubnetID: subnetID2, + NodeID: ids.GenerateTestNodeID(), + PublicKey: otherPKBytes, + StartTime: uint64(now.Unix()), + Weight: 1, + }, + }, + }, + { + name: "initial stakers and sovs mixed", + initial: []*Staker{ + { + TxID: ids.GenerateTestID(), + SubnetID: subnetID1, + NodeID: ids.GenerateTestNodeID(), + PublicKey: pk, + Weight: uint64(now.Unix()), + StartTime: now, + }, + { + TxID: ids.GenerateTestID(), + SubnetID: subnetID2, + NodeID: ids.GenerateTestNodeID(), + PublicKey: pk, + Weight: 1, + StartTime: now, + }, + { + TxID: ids.GenerateTestID(), + SubnetID: subnetID1, + NodeID: ids.GenerateTestNodeID(), + PublicKey: otherPK, + Weight: 0, + StartTime: now, + }, + }, + sovs: []SubnetOnlyValidator{ + { + ValidationID: ids.GenerateTestID(), + SubnetID: subnetID1, + NodeID: ids.GenerateTestNodeID(), + StartTime: uint64(now.Unix()), + PublicKey: pkBytes, + Weight: 1, + EndAccumulatedFee: 1, + MinNonce: 2, + }, + { + ValidationID: ids.GenerateTestID(), + SubnetID: subnetID2, + NodeID: ids.GenerateTestNodeID(), + PublicKey: otherPKBytes, + StartTime: uint64(now.Unix()), + Weight: 0, + EndAccumulatedFee: 0, + }, + { + ValidationID: ids.GenerateTestID(), + SubnetID: subnetID1, + NodeID: ids.GenerateTestNodeID(), + PublicKey: pkBytes, + StartTime: uint64(now.Unix()), + Weight: 1, + EndAccumulatedFee: 0, + }, + { + ValidationID: ids.GenerateTestID(), + SubnetID: subnetID1, + NodeID: ids.GenerateTestNodeID(), + PublicKey: otherPKBytes, + StartTime: uint64(now.Unix()), + Weight: 0, + EndAccumulatedFee: 1, + }, + }, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + require := require.New(t) + + db := memdb.New() + state := newTestState(t, db) + + for _, staker := range test.initial { + primaryStaker := &Staker{ + TxID: ids.GenerateTestID(), + SubnetID: constants.PrimaryNetworkID, + NodeID: staker.NodeID, + PublicKey: staker.PublicKey, + Weight: 5, + // start primary network staker 1 second before the subnet staker + StartTime: staker.StartTime.Add(-1 * time.Second), + } + require.NoError(state.PutCurrentValidator(primaryStaker)) + require.NoError(state.PutCurrentValidator(staker)) + } + + for _, sov := range test.sovs { + // The codec creates zero length slices rather than leaving them + // as nil, so we need to populate the slices for later reflect + // based equality checks. + sov.RemainingBalanceOwner = []byte{} + sov.DeactivationOwner = []byte{} + + require.NoError(state.PutSubnetOnlyValidator(sov)) + } + + state.SetHeight(0) + require.NoError(state.Commit()) + + stakersBySubnetID := make(map[ids.ID][]*Staker) + for _, staker := range test.initial { + stakers := stakersBySubnetID[staker.SubnetID] + stakersBySubnetID[staker.SubnetID] = append(stakers, staker) + } + + sovBySubnetID := make(map[ids.ID][]SubnetOnlyValidator) + for _, sov := range test.sovs { + if sov.Weight == 0 { + continue + } + sovs := sovBySubnetID[sov.SubnetID] + sovBySubnetID[sov.SubnetID] = append(sovs, sov) + } + + for _, subnetID := range subnetIDs { + currentValidators, height, err := state.GetCurrentValidatorSet(context.Background(), subnetID) + require.NoError(err) + require.Equal(uint64(0), height) + totalLen := len(stakersBySubnetID[subnetID]) + len(sovBySubnetID[subnetID]) + require.Len(currentValidators, totalLen) + + for _, expectedStaker := range stakersBySubnetID[subnetID] { + currentValidator, ok := currentValidators[expectedStaker.TxID] + require.True(ok) + require.Equal(expectedStaker.TxID, currentValidator.ValidationID) + require.Equal(expectedStaker.NodeID, currentValidator.NodeID) + require.Equal(expectedStaker.PublicKey, currentValidator.PublicKey) + require.Equal(expectedStaker.Weight, currentValidator.Weight) + require.Equal(uint64(expectedStaker.StartTime.Unix()), currentValidator.StartTime) + require.Equal(uint64(0), currentValidator.MinNonce) + require.True(currentValidator.IsActive) + require.False(currentValidator.IsSoV) + } + + for _, expectedSOV := range sovBySubnetID[subnetID] { + currentValidator, ok := currentValidators[expectedSOV.ValidationID] + require.True(ok) + require.Equal(expectedSOV.ValidationID, currentValidator.ValidationID) + require.Equal(expectedSOV.NodeID, currentValidator.NodeID) + require.Equal(expectedSOV.PublicKey, currentValidator.PublicKey.Serialize()) + require.Equal(expectedSOV.Weight, currentValidator.Weight) + require.Equal(expectedSOV.StartTime, currentValidator.StartTime) + require.Equal(expectedSOV.MinNonce, currentValidator.MinNonce) + require.Equal(expectedSOV.isActive(), currentValidator.IsActive) + require.True(currentValidator.IsSoV) + } + } + }) + } +} diff --git a/vms/platformvm/validators/manager.go b/vms/platformvm/validators/manager.go index 5d0c6c803c65..cb1cb51c8280 100644 --- a/vms/platformvm/validators/manager.go +++ b/vms/platformvm/validators/manager.go @@ -100,6 +100,8 @@ type State interface { endHeight uint64, subnetID ids.ID, ) error + + GetCurrentValidatorSet(ctx context.Context, subnetID ids.ID) (map[ids.ID]*validators.GetCurrentValidatorOutput, uint64, error) } func NewManager( @@ -409,3 +411,7 @@ func (m *manager) GetSubnetID(_ context.Context, chainID ids.ID) (ids.ID, error) func (m *manager) OnAcceptedBlockID(blkID ids.ID) { m.recentlyAccepted.Add(blkID) } + +func (m *manager) GetCurrentValidatorSet(ctx context.Context, subnetID ids.ID) (map[ids.ID]*validators.GetCurrentValidatorOutput, uint64, error) { + return m.state.GetCurrentValidatorSet(ctx, subnetID) +} diff --git a/vms/platformvm/validators/validatorstest/manager.go b/vms/platformvm/validators/validatorstest/manager.go index 068073f4af6b..46f74ff47187 100644 --- a/vms/platformvm/validators/validatorstest/manager.go +++ b/vms/platformvm/validators/validatorstest/manager.go @@ -33,3 +33,7 @@ func (manager) GetValidatorSet(context.Context, uint64, ids.ID) (map[ids.NodeID] } func (manager) OnAcceptedBlockID(ids.ID) {} + +func (manager) GetCurrentValidatorSet(context.Context, ids.ID) (map[ids.ID]*snowvalidators.GetCurrentValidatorOutput, uint64, error) { + return nil, 0, nil +}