From dde24bc9e535a53c79e12aa69a5d2f94ff935c8b Mon Sep 17 00:00:00 2001 From: Leonard Lyubich Date: Fri, 15 Jan 2021 10:39:03 +0300 Subject: [PATCH] [#311] control: Rewrite methods for binary encoding and signatures Rewrite marshalers and sizers using proto library from API repo. Signed-off-by: Leonard Lyubich --- pkg/services/control/service.go | 296 ++++++++++++++++++++++++------- pkg/services/control/types.go | 299 ++++++++++++++++++++++++++++---- 2 files changed, 500 insertions(+), 95 deletions(-) diff --git a/pkg/services/control/service.go b/pkg/services/control/service.go index 5f0adcd64..237a8987d 100644 --- a/pkg/services/control/service.go +++ b/pkg/services/control/service.go @@ -1,119 +1,291 @@ package control +import ( + "github.com/nspcc-dev/neofs-api-go/util/proto" +) + +// StableMarshal reads binary representation of health check request body +// in protobuf binary format. +// +// If buffer length is less than x.StableSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same binary format. +func (x *HealthCheckRequest_Body) StableMarshal(buf []byte) ([]byte, error) { + return buf, nil +} + +// StableSize returns binary size of health check request body +// in protobuf binary format. +// +// Structures with the same field values have the same binary size. +func (x *HealthCheckRequest_Body) StableSize() int { + return 0 +} + // SetBody sets health check request body. -func (m *HealthCheckRequest) SetBody(v *HealthCheckRequest_Body) { - if m != nil { - m.Body = v +func (x *HealthCheckRequest) SetBody(v *HealthCheckRequest_Body) { + if x != nil { + x.Body = v } } // SetSignature sets signature of the health check request body. -func (m *HealthCheckRequest) SetSignature(body *Signature) { - if m != nil { - m.Signature = body +func (x *HealthCheckRequest) SetSignature(body *Signature) { + if x != nil { + x.Signature = body } } -// ReadSignedData marshals request body to buf. -func (m *HealthCheckRequest) ReadSignedData(buf []byte) ([]byte, error) { - _, err := m.GetBody().MarshalTo(buf) - - return buf, err +// ReadSignedData reads signed data of health check request to buf. +// +// If buffer length is less than x.SignedDataSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same signed data. +func (x *HealthCheckRequest) ReadSignedData(buf []byte) ([]byte, error) { + return x.GetBody().StableMarshal(buf) } -// SignedDataSize returns binary size of the request body. -func (m *HealthCheckRequest) SignedDataSize() int { - return m.GetBody().Size() +// SignedDataSize returns binary size of the signed data +// of health check request. +// +// Structures with the same field values have the same signed data size. +func (x *HealthCheckRequest) SignedDataSize() int { + return x.GetBody().StableSize() } // SetStatus sets health status of storage node. -func (m *HealthCheckResponse_Body) SetStatus(v HealthStatus) { - if m != nil { - m.Status = v +func (x *HealthCheckResponse_Body) SetStatus(v HealthStatus) { + if x != nil { + x.Status = v } } +const ( + _ = iota + healthRespBodyStatusFNum +) + +// StableMarshal reads binary representation of health check response body +// in protobuf binary format. +// +// If buffer length is less than x.StableSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same binary format. +func (x *HealthCheckResponse_Body) StableMarshal(buf []byte) ([]byte, error) { + if x == nil { + return []byte{}, nil + } + + if sz := x.StableSize(); len(buf) < sz { + buf = make([]byte, sz) + } + + _, err := proto.EnumMarshal(healthRespBodyStatusFNum, buf, int32(x.Status)) + if err != nil { + return nil, err + } + + return buf, nil +} + +// StableSize returns binary size of health check response body +// in protobuf binary format. +// +// Structures with the same field values have the same binary size. +func (x *HealthCheckResponse_Body) StableSize() int { + if x == nil { + return 0 + } + + size := 0 + + size += proto.EnumSize(healthRespBodyStatusFNum, int32(x.Status)) + + return size +} + // SetBody sets health check response body. -func (m *HealthCheckResponse) SetBody(v *HealthCheckResponse_Body) { - if m != nil { - m.Body = v +func (x *HealthCheckResponse) SetBody(v *HealthCheckResponse_Body) { + if x != nil { + x.Body = v } } // SetSignature sets signature of the health check response body. -func (m *HealthCheckResponse) SetSignature(v *Signature) { - if m != nil { - m.Signature = v +func (x *HealthCheckResponse) SetSignature(v *Signature) { + if x != nil { + x.Signature = v } } -// ReadSignedData marshals response body to buf. -func (m *HealthCheckResponse) ReadSignedData(buf []byte) ([]byte, error) { - _, err := m.GetBody().MarshalTo(buf) - - return buf, err +// ReadSignedData reads signed data of health check response to buf. +// +// If buffer length is less than x.SignedDataSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same signed data. +func (x *HealthCheckResponse) ReadSignedData(buf []byte) ([]byte, error) { + return x.GetBody().StableMarshal(buf) } -// SignedDataSize returns binary size of the response body. -func (m *HealthCheckResponse) SignedDataSize() int { - return m.GetBody().Size() +// SignedDataSize returns binary size of the signed data +// of health check response. +// +// Structures with the same field values have the same signed data size. +func (x *HealthCheckResponse) SignedDataSize() int { + return x.GetBody().StableSize() +} + +// StableMarshal reads binary representation of netmap snapshot request body +// in protobuf binary format. +// +// If buffer length is less than x.StableSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same binary format. +func (x *NetmapSnapshotRequest_Body) StableMarshal(buf []byte) ([]byte, error) { + return buf, nil +} + +// StableSize returns binary size of netmap snapshot request body +// in protobuf binary format. +// +// Structures with the same field values have the same binary size. +func (x *NetmapSnapshotRequest_Body) StableSize() int { + return 0 } // SetBody sets get netmap snapshot request body. -func (m *NetmapSnapshotRequest) SetBody(v *NetmapSnapshotRequest_Body) { - if m != nil { - m.Body = v +func (x *NetmapSnapshotRequest) SetBody(v *NetmapSnapshotRequest_Body) { + if x != nil { + x.Body = v } } // SetSignature sets signature of the netmap snapshot request body. -func (m *NetmapSnapshotRequest) SetSignature(body *Signature) { - if m != nil { - m.Signature = body +func (x *NetmapSnapshotRequest) SetSignature(body *Signature) { + if x != nil { + x.Signature = body } } -// ReadSignedData marshals request body to buf. -func (m *NetmapSnapshotRequest) ReadSignedData(buf []byte) ([]byte, error) { - _, err := m.GetBody().MarshalTo(buf) - - return buf, err +// ReadSignedData reads signed data of netmap snapshot request to buf. +// +// If buffer length is less than x.SignedDataSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same signed data. +func (x *NetmapSnapshotRequest) ReadSignedData(buf []byte) ([]byte, error) { + return x.GetBody().StableMarshal(buf) } -// SignedDataSize returns binary size of the request body. -func (m *NetmapSnapshotRequest) SignedDataSize() int { - return m.GetBody().Size() +// SignedDataSize returns binary size of the signed data +// of netmap snapshot request. +// +// Structures with the same field values have the same signed data size. +func (x *NetmapSnapshotRequest) SignedDataSize() int { + return x.GetBody().StableSize() } // SetNetmap sets structure of the current network map. -func (m *NetmapSnapshotResponse_Body) SetNetmap(v *Netmap) { - if m != nil { - m.Netmap = v +func (x *NetmapSnapshotResponse_Body) SetNetmap(v *Netmap) { + if x != nil { + x.Netmap = v } } +const ( + _ = iota + snapshotRespBodyNetmapFNum +) + +// StableMarshal reads binary representation of netmap snapshot response body +// in protobuf binary format. +// +// If buffer length is less than x.StableSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same binary format. +func (x *NetmapSnapshotResponse_Body) StableMarshal(buf []byte) ([]byte, error) { + if x == nil { + return []byte{}, nil + } + + if sz := x.StableSize(); len(buf) < sz { + buf = make([]byte, sz) + } + + _, err := proto.NestedStructureMarshal(snapshotRespBodyNetmapFNum, buf, x.Netmap) + if err != nil { + return nil, err + } + + return buf, nil +} + +// StableSize returns binary size of netmap snapshot response body +// in protobuf binary format. +// +// Structures with the same field values have the same binary size. +func (x *NetmapSnapshotResponse_Body) StableSize() int { + if x == nil { + return 0 + } + + size := 0 + + size += proto.NestedStructureSize(snapshotRespBodyNetmapFNum, x.Netmap) + + return size +} + // SetBody sets get netmap snapshot response body. -func (m *NetmapSnapshotResponse) SetBody(v *NetmapSnapshotResponse_Body) { - if m != nil { - m.Body = v +func (x *NetmapSnapshotResponse) SetBody(v *NetmapSnapshotResponse_Body) { + if x != nil { + x.Body = v } } // SetSignature sets signature of the get netmap snapshot response body. -func (m *NetmapSnapshotResponse) SetSignature(v *Signature) { - if m != nil { - m.Signature = v +func (x *NetmapSnapshotResponse) SetSignature(v *Signature) { + if x != nil { + x.Signature = v } } -// ReadSignedData marshals request body to buf. -func (m *NetmapSnapshotResponse) ReadSignedData(buf []byte) ([]byte, error) { - _, err := m.GetBody().MarshalTo(buf) - - return buf, err +// ReadSignedData reads signed data of netmap snapshot response to buf. +// +// If buffer length is less than x.SignedDataSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same signed data. +func (x *NetmapSnapshotResponse) ReadSignedData(buf []byte) ([]byte, error) { + return x.GetBody().StableMarshal(buf) } -// SignedDataSize returns binary size of the request body. -func (m *NetmapSnapshotResponse) SignedDataSize() int { - return m.GetBody().Size() +// SignedDataSize returns binary size of the signed data +// of netmap snapshot response. +// +// Structures with the same field values have the same signed data size. +func (x *NetmapSnapshotResponse) SignedDataSize() int { + return x.GetBody().StableSize() } diff --git a/pkg/services/control/types.go b/pkg/services/control/types.go index 237cdcc67..43a350db9 100644 --- a/pkg/services/control/types.go +++ b/pkg/services/control/types.go @@ -1,78 +1,311 @@ package control +import ( + "github.com/nspcc-dev/neofs-api-go/util/proto" +) + // SetKey sets public key used for signing. -func (m *Signature) SetKey(v []byte) { - if m != nil { - m.Key = v +func (x *Signature) SetKey(v []byte) { + if x != nil { + x.Key = v } } // SetSign sets binary signature. -func (m *Signature) SetSign(v []byte) { - if m != nil { - m.Sign = v +func (x *Signature) SetSign(v []byte) { + if x != nil { + x.Sign = v } } // SetKey sets key of the node attribute. -func (m *NodeInfo_Attribute) SetKey(v string) { - if m != nil { - m.Key = v +func (x *NodeInfo_Attribute) SetKey(v string) { + if x != nil { + x.Key = v } } // SetValue sets value of the node attribute. -func (m *NodeInfo_Attribute) SetValue(v string) { - if m != nil { - m.Value = v +func (x *NodeInfo_Attribute) SetValue(v string) { + if x != nil { + x.Value = v } } // SetParents sets parent keys. -func (m *NodeInfo_Attribute) SetParents(v []string) { - if m != nil { - m.Parents = v +func (x *NodeInfo_Attribute) SetParents(v []string) { + if x != nil { + x.Parents = v } } +const ( + _ = iota + nodeAttrKeyFNum + nodeAttrValueFNum + nodeAttrParentsFNum +) + +// StableMarshal reads binary representation of node attribute +// in protobuf binary format. +// +// If buffer length is less than x.StableSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same binary format. +func (x *NodeInfo_Attribute) StableMarshal(buf []byte) ([]byte, error) { + if x == nil { + return []byte{}, nil + } + + if sz := x.StableSize(); len(buf) < sz { + buf = make([]byte, sz) + } + + var ( + offset, n int + err error + ) + + n, err = proto.StringMarshal(nodeAttrKeyFNum, buf[offset:], x.Key) + if err != nil { + return nil, err + } + + offset += n + + n, err = proto.StringMarshal(nodeAttrValueFNum, buf[offset:], x.Value) + if err != nil { + return nil, err + } + + offset += n + + for i := range x.Parents { + n, err = proto.StringMarshal(nodeAttrParentsFNum, buf[offset:], x.Parents[i]) + if err != nil { + return nil, err + } + + offset += n + } + + return buf, nil +} + +// StableSize returns binary size of node attribute +// in protobuf binary format. +// +// Structures with the same field values have the same binary size. +func (x *NodeInfo_Attribute) StableSize() int { + if x == nil { + return 0 + } + + size := 0 + + size += proto.StringSize(nodeAttrKeyFNum, x.Key) + size += proto.StringSize(nodeAttrValueFNum, x.Value) + + parents := x.GetParents() + for i := range parents { + size += proto.StringSize(nodeAttrParentsFNum, parents[i]) + } + + return size +} + // SetPublicKey sets public key of the NeoFS node in a binary format. -func (m *NodeInfo) SetPublicKey(v []byte) { - if m != nil { - m.PublicKey = v +func (x *NodeInfo) SetPublicKey(v []byte) { + if x != nil { + x.PublicKey = v } } // SetAddress sets ways to connect to a node. -func (m *NodeInfo) SetAddress(v string) { - if m != nil { - m.Address = v +func (x *NodeInfo) SetAddress(v string) { + if x != nil { + x.Address = v } } // SetAttributes sets attributes of the NeoFS Storage Node. -func (m *NodeInfo) SetAttributes(v []*NodeInfo_Attribute) { - if m != nil { - m.Attributes = v +func (x *NodeInfo) SetAttributes(v []*NodeInfo_Attribute) { + if x != nil { + x.Attributes = v } } // SetState sets state of the NeoFS node. -func (m *NodeInfo) SetState(v HealthStatus) { - if m != nil { - m.State = v +func (x *NodeInfo) SetState(v HealthStatus) { + if x != nil { + x.State = v } } +const ( + _ = iota + nodePubKeyFNum + nodeAddrFNum + nodeAttrsFNum + nodeStateFNum +) + +// StableMarshal reads binary representation of node information +// in protobuf binary format. +// +// If buffer length is less than x.StableSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same binary format. +func (x *NodeInfo) StableMarshal(buf []byte) ([]byte, error) { + if x == nil { + return []byte{}, nil + } + + if sz := x.StableSize(); len(buf) < sz { + buf = make([]byte, sz) + } + + var ( + offset, n int + err error + ) + + n, err = proto.BytesMarshal(nodePubKeyFNum, buf[offset:], x.PublicKey) + if err != nil { + return nil, err + } + + offset += n + + n, err = proto.StringMarshal(nodeAddrFNum, buf[offset:], x.Address) + if err != nil { + return nil, err + } + + offset += n + + for i := range x.Attributes { + n, err = proto.NestedStructureMarshal(nodeAttrsFNum, buf[offset:], x.Attributes[i]) + if err != nil { + return nil, err + } + + offset += n + } + + _, err = proto.EnumMarshal(nodeStateFNum, buf[offset:], int32(x.State)) + if err != nil { + return nil, err + } + + return buf, nil +} + +// StableSize returns binary size of node information +// in protobuf binary format. +// +// Structures with the same field values have the same binary size. +func (x *NodeInfo) StableSize() int { + if x == nil { + return 0 + } + + size := 0 + + size += proto.BytesSize(nodePubKeyFNum, x.PublicKey) + size += proto.StringSize(nodeAddrFNum, x.Address) + + for i := range x.Attributes { + size += proto.NestedStructureSize(nodeAttrsFNum, x.Attributes[i]) + } + + size += proto.EnumSize(nodeStateFNum, int32(x.State)) + + return size +} + // SetEpoch sets revision number of the network map. -func (m *Netmap) SetEpoch(v uint64) { - if m != nil { - m.Epoch = v +func (x *Netmap) SetEpoch(v uint64) { + if x != nil { + x.Epoch = v } } // SetNodes sets nodes presented in network. -func (m *Netmap) SetNodes(v []*NodeInfo) { - if m != nil { - m.Nodes = v +func (x *Netmap) SetNodes(v []*NodeInfo) { + if x != nil { + x.Nodes = v } } + +const ( + _ = iota + netmapEpochFNum + netmapNodesFNum +) + +// StableMarshal reads binary representation of netmap in protobuf binary format. +// +// If buffer length is less than x.StableSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same binary format. +func (x *Netmap) StableMarshal(buf []byte) ([]byte, error) { + if x == nil { + return []byte{}, nil + } + + if sz := x.StableSize(); len(buf) < sz { + buf = make([]byte, sz) + } + + var ( + offset, n int + err error + ) + + n, err = proto.UInt64Marshal(netmapEpochFNum, buf[offset:], x.Epoch) + if err != nil { + return nil, err + } + + offset += n + + for i := range x.Nodes { + n, err = proto.NestedStructureMarshal(netmapNodesFNum, buf[offset:], x.Nodes[i]) + if err != nil { + return nil, err + } + + offset += n + } + + return buf, nil +} + +// StableSize returns binary size of netmap in protobuf binary format. +// +// Structures with the same field values have the same binary size. +func (x *Netmap) StableSize() int { + if x == nil { + return 0 + } + + size := 0 + + size += proto.UInt64Size(netmapEpochFNum, x.Epoch) + + for i := range x.Nodes { + size += proto.NestedStructureSize(netmapNodesFNum, x.Nodes[i]) + } + + return size +}