diff --git a/cmd/neofs-cli/internal/client/client.go b/cmd/neofs-cli/internal/client/client.go index fb23fec80..706c84bcf 100644 --- a/cmd/neofs-cli/internal/client/client.go +++ b/cmd/neofs-cli/internal/client/client.go @@ -1,7 +1,10 @@ package internal import ( + "bytes" "context" + "errors" + "fmt" "io" "github.com/nspcc-dev/neofs-sdk-go/accounting" @@ -19,12 +22,12 @@ import ( // BalanceOfPrm groups parameters of BalanceOf operation. type BalanceOfPrm struct { commonPrm - client.GetBalancePrm + client.PrmBalanceGet } // BalanceOfRes groups resulting values of BalanceOf operation. type BalanceOfRes struct { - cliRes *client.GetBalanceRes + cliRes *client.ResBalanceGet } // Balance returns current balance. @@ -36,7 +39,7 @@ func (x BalanceOfRes) Balance() *accounting.Decimal { // // Returns any error prevented the operation from completing correctly in error return. func BalanceOf(prm BalanceOfPrm) (res BalanceOfRes, err error) { - res.cliRes, err = prm.cli.GetBalance(context.Background(), prm.GetBalancePrm) + res.cliRes, err = prm.cli.BalanceGet(context.Background(), prm.PrmBalanceGet) return } @@ -44,12 +47,12 @@ func BalanceOf(prm BalanceOfPrm) (res BalanceOfRes, err error) { // ListContainersPrm groups parameters of ListContainers operation. type ListContainersPrm struct { commonPrm - client.ContainerListPrm + client.PrmContainerList } // ListContainersRes groups resulting values of ListContainers operation. type ListContainersRes struct { - cliRes *client.ContainerListRes + cliRes *client.ResContainerList } // IDList returns list of identifiers of user's containers. @@ -61,7 +64,7 @@ func (x ListContainersRes) IDList() []*cid.ID { // // Returns any error prevented the operation from completing correctly in error return. func ListContainers(prm ListContainersPrm) (res ListContainersRes, err error) { - res.cliRes, err = prm.cli.ListContainers(context.Background(), prm.ContainerListPrm) + res.cliRes, err = prm.cli.ContainerList(context.Background(), prm.PrmContainerList) return } @@ -69,12 +72,12 @@ func ListContainers(prm ListContainersPrm) (res ListContainersRes, err error) { // PutContainerPrm groups parameters of PutContainer operation. type PutContainerPrm struct { commonPrm - client.ContainerPutPrm + client.PrmContainerPut } // PutContainerRes groups resulting values of PutContainer operation. type PutContainerRes struct { - cliRes *client.ContainerPutRes + cliRes *client.ResContainerPut } // ID returns identifier of the created container. @@ -91,7 +94,7 @@ func (x PutContainerRes) ID() *cid.ID { // // Returns any error prevented the operation from completing correctly in error return. func PutContainer(prm PutContainerPrm) (res PutContainerRes, err error) { - res.cliRes, err = prm.cli.PutContainer(context.Background(), prm.ContainerPutPrm) + res.cliRes, err = prm.cli.ContainerPut(context.Background(), prm.PrmContainerPut) return } @@ -99,7 +102,7 @@ func PutContainer(prm PutContainerPrm) (res PutContainerRes, err error) { // GetContainerPrm groups parameters of GetContainer operation. type GetContainerPrm struct { commonPrm - cliPrm client.ContainerGetPrm + cliPrm client.PrmContainerGet } // SetContainer sets identifier of the container to be read. @@ -109,7 +112,7 @@ func (x *GetContainerPrm) SetContainer(id cid.ID) { // GetContainerRes groups resulting values of GetContainer operation. type GetContainerRes struct { - cliRes *client.ContainerGetRes + cliRes *client.ResContainerGet } // Container returns structured of the requested container. @@ -121,7 +124,7 @@ func (x GetContainerRes) Container() *container.Container { // // Returns any error prevented the operation from completing correctly in error return. func GetContainer(prm GetContainerPrm) (res GetContainerRes, err error) { - res.cliRes, err = prm.cli.GetContainer(context.Background(), prm.cliPrm) + res.cliRes, err = prm.cli.ContainerGet(context.Background(), prm.cliPrm) return } @@ -129,7 +132,7 @@ func GetContainer(prm GetContainerPrm) (res GetContainerRes, err error) { // DeleteContainerPrm groups parameters of DeleteContainerPrm operation. type DeleteContainerPrm struct { commonPrm - client.ContainerDeletePrm + client.PrmContainerDelete } // DeleteContainerRes groups resulting values of DeleteContainer operation. @@ -144,7 +147,7 @@ type DeleteContainerRes struct{} // // Returns any error prevented the operation from completing correctly in error return. func DeleteContainer(prm DeleteContainerPrm) (res DeleteContainerRes, err error) { - _, err = prm.cli.DeleteContainer(context.Background(), prm.ContainerDeletePrm) + _, err = prm.cli.ContainerDelete(context.Background(), prm.PrmContainerDelete) return } @@ -152,12 +155,12 @@ func DeleteContainer(prm DeleteContainerPrm) (res DeleteContainerRes, err error) // EACLPrm groups parameters of EACL operation. type EACLPrm struct { commonPrm - client.EACLPrm + client.PrmContainerEACL } // EACLRes groups resulting values of EACL operation. type EACLRes struct { - cliRes *client.EACLRes + cliRes *client.ResContainerEACL } // EACL returns requested eACL table. @@ -169,7 +172,7 @@ func (x EACLRes) EACL() *eacl.Table { // // Returns any error prevented the operation from completing correctly in error return. func EACL(prm EACLPrm) (res EACLRes, err error) { - res.cliRes, err = prm.cli.EACL(context.Background(), prm.EACLPrm) + res.cliRes, err = prm.cli.ContainerEACL(context.Background(), prm.PrmContainerEACL) return } @@ -177,7 +180,7 @@ func EACL(prm EACLPrm) (res EACLRes, err error) { // SetEACLPrm groups parameters of SetEACL operation. type SetEACLPrm struct { commonPrm - client.SetEACLPrm + client.PrmContainerSetEACL } // SetEACLRes groups resulting values of SetEACL operation. @@ -192,7 +195,7 @@ type SetEACLRes struct{} // // Returns any error prevented the operation from completing correctly in error return. func SetEACL(prm SetEACLPrm) (res SetEACLRes, err error) { - _, err = prm.cli.SetEACL(context.Background(), prm.SetEACLPrm) + _, err = prm.cli.ContainerSetEACL(context.Background(), prm.PrmContainerSetEACL) return } @@ -200,12 +203,12 @@ func SetEACL(prm SetEACLPrm) (res SetEACLRes, err error) { // NetworkInfoPrm groups parameters of NetworkInfo operation. type NetworkInfoPrm struct { commonPrm - client.NetworkInfoPrm + client.PrmNetworkInfo } // NetworkInfoRes groups resulting values of NetworkInfo operation. type NetworkInfoRes struct { - cliRes *client.NetworkInfoRes + cliRes *client.ResNetworkInfo } // NetworkInfo returns structured information about the NeoFS network. @@ -217,7 +220,7 @@ func (x NetworkInfoRes) NetworkInfo() *netmap.NetworkInfo { // // Returns any error prevented the operation from completing correctly in error return. func NetworkInfo(prm NetworkInfoPrm) (res NetworkInfoRes, err error) { - res.cliRes, err = prm.cli.NetworkInfo(context.Background(), prm.NetworkInfoPrm) + res.cliRes, err = prm.cli.NetworkInfo(context.Background(), prm.PrmNetworkInfo) return } @@ -225,12 +228,12 @@ func NetworkInfo(prm NetworkInfoPrm) (res NetworkInfoRes, err error) { // NodeInfoPrm groups parameters of NodeInfo operation. type NodeInfoPrm struct { commonPrm - client.EndpointInfoPrm + client.PrmEndpointInfo } // NodeInfoRes groups resulting values of NodeInfo operation. type NodeInfoRes struct { - cliRes *client.EndpointInfoRes + cliRes *client.ResEndpointInfo } // NodeInfo returns information about the node from netmap. @@ -247,7 +250,7 @@ func (x NodeInfoRes) LatestVersion() *version.Version { // // Returns any error prevented the operation from completing correctly in error return. func NodeInfo(prm NodeInfoPrm) (res NodeInfoRes, err error) { - res.cliRes, err = prm.cli.EndpointInfo(context.Background(), prm.EndpointInfoPrm) + res.cliRes, err = prm.cli.EndpointInfo(context.Background(), prm.PrmEndpointInfo) return } @@ -255,12 +258,12 @@ func NodeInfo(prm NodeInfoPrm) (res NodeInfoRes, err error) { // CreateSessionPrm groups parameters of CreateSession operation. type CreateSessionPrm struct { commonPrm - client.CreateSessionPrm + client.PrmSessionCreate } // CreateSessionRes groups resulting values of CreateSession operation. type CreateSessionRes struct { - cliRes *client.CreateSessionRes + cliRes *client.ResSessionCreate } // ID returns session identifier. @@ -277,7 +280,7 @@ func (x CreateSessionRes) SessionKey() []byte { // // Returns any error prevented the operation from completing correctly in error return. func CreateSession(prm CreateSessionPrm) (res CreateSessionRes, err error) { - res.cliRes, err = prm.cli.CreateSession(context.Background(), prm.CreateSessionPrm) + res.cliRes, err = prm.cli.SessionCreate(context.Background(), prm.PrmSessionCreate) return } @@ -303,29 +306,94 @@ func (x *PutObjectPrm) SetPayloadReader(rdr io.Reader) { // PutObjectRes groups resulting values of PutObject operation. type PutObjectRes struct { - cliRes *client.ObjectPutRes + id *oidSDK.ID } // ID returns identifier of the created object. func (x PutObjectRes) ID() *oidSDK.ID { - return x.cliRes.ID() + return x.id } // PutObject saves the object in NeoFS network. // // Returns any error prevented the operation from completing correctly in error return. -func PutObject(prm PutObjectPrm) (res PutObjectRes, err error) { - var putPrm client.PutObjectParams +func PutObject(prm PutObjectPrm) (*PutObjectRes, error) { + var putPrm client.PrmObjectPutInit - putPrm.WithObject(prm.hdr) - putPrm.WithPayloadReader(prm.rdr) + wrt, err := prm.cli.ObjectPutInit(context.Background(), putPrm) + if err != nil { + return nil, fmt.Errorf("init object writing: %w", err) + } - res.cliRes, err = prm.cli.PutObject(context.Background(), &putPrm, append(prm.opts, - client.WithSession(prm.sessionToken), - client.WithBearer(prm.bearerToken), - )...) + if prm.sessionToken != nil { + wrt.WithinSession(*prm.sessionToken) + } - return + if prm.bearerToken != nil { + wrt.WithBearerToken(*prm.bearerToken) + } + + if prm.local { + wrt.MarkLocal() + } + + if wrt.WriteHeader(*prm.hdr) { + sz := prm.hdr.PayloadSize() + + if data := prm.hdr.Payload(); len(data) > 0 { + if prm.rdr != nil { + prm.rdr = io.MultiReader(bytes.NewReader(data), prm.rdr) + } else { + prm.rdr = bytes.NewReader(data) + sz = uint64(len(data)) + } + } + + if prm.rdr != nil { + // TODO: (neofs-node#1198) explore better values or configure it + const defaultBufferSizePut = 4096 + + if sz == 0 || sz > defaultBufferSizePut { + sz = defaultBufferSizePut + } + + buf := make([]byte, sz) + + var n int + + for { + n, err = prm.rdr.Read(buf) + if n > 0 { + if !wrt.WritePayloadChunk(buf[:n]) { + break + } + + continue + } + + if errors.Is(err, io.EOF) { + break + } + + return nil, fmt.Errorf("read payload: %w", err) + } + } + } + + res, err := wrt.Close() + if err != nil { // here err already carries both status and client errors + return nil, fmt.Errorf("client failure: %w", err) + } + + var id oidSDK.ID + + if !res.ReadStoredObjectID(&id) { + return nil, errors.New("missing ID of the stored object") + } + + return &PutObjectRes{ + id: &id, + }, nil } // DeleteObjectPrm groups parameters of DeleteObject operation. @@ -336,28 +404,54 @@ type DeleteObjectPrm struct { // DeleteObjectRes groups resulting values of DeleteObject operation. type DeleteObjectRes struct { - cliRes *client.ObjectDeleteRes + addrTombstone *addressSDK.Address } // TombstoneAddress returns address of the created object with tombstone. func (x DeleteObjectRes) TombstoneAddress() *addressSDK.Address { - return x.cliRes.TombstoneAddress() + return x.addrTombstone } // DeleteObject marks object to be removed from NeoFS through tombstone placement. // // Returns any error prevented the operation from completing correctly in error return. -func DeleteObject(prm DeleteObjectPrm) (res DeleteObjectRes, err error) { - var delPrm client.DeleteObjectParams +func DeleteObject(prm DeleteObjectPrm) (*DeleteObjectRes, error) { + var delPrm client.PrmObjectDelete - delPrm.WithAddress(prm.objAddr) + if id := prm.objAddr.ContainerID(); id != nil { + delPrm.FromContainer(*id) + } - res.cliRes, err = prm.cli.DeleteObject(context.Background(), &delPrm, append(prm.opts, - client.WithSession(prm.sessionToken), - client.WithBearer(prm.bearerToken), - )...) + if id := prm.objAddr.ObjectID(); id != nil { + delPrm.ByID(*id) + } - return + if prm.sessionToken != nil { + delPrm.WithinSession(*prm.sessionToken) + } + + if prm.bearerToken != nil { + delPrm.WithBearerToken(*prm.bearerToken) + } + + cliRes, err := prm.cli.ObjectDelete(context.Background(), delPrm) + if err != nil { + return nil, fmt.Errorf("remove object via client: %w", err) + } + + var id oidSDK.ID + + if !cliRes.ReadTombstoneID(&id) { + return nil, errors.New("object removed but tombstone ID is missing") + } + + var addr addressSDK.Address + addr.SetObjectID(&id) + addr.SetContainerID(prm.objAddr.ContainerID()) + + return &DeleteObjectRes{ + addrTombstone: &addr, + }, nil } // GetObjectPrm groups parameters of GetObject operation. @@ -370,33 +464,79 @@ type GetObjectPrm struct { // GetObjectRes groups resulting values of GetObject operation. type GetObjectRes struct { - cliRes *client.ObjectGetRes + hdr *object.Object } // Header returns header of the request object. func (x GetObjectRes) Header() *object.Object { - return x.cliRes.Object() + return x.hdr } +// maximum size of the buffer use for io.Copy*. +// Chosen small due to the expected low volume of NeoFS CLI process resources. +// TODO: (neofs-node#1198) explore better values or configure it +const maxPayloadBufferSize = 1024 + // GetObject reads the object by address. // // Interrupts on any writer error. If successful, payload is written to writer. // // Returns any error prevented the operation from completing correctly in error return. // For raw reading, returns *object.SplitInfoError error if object is virtual. -func GetObject(prm GetObjectPrm) (res GetObjectRes, err error) { - var getPrm client.GetObjectParams +func GetObject(prm GetObjectPrm) (*GetObjectRes, error) { + var getPrm client.PrmObjectGet - getPrm.WithAddress(prm.objAddr) - getPrm.WithPayloadWriter(prm.wrt) - getPrm.WithRawFlag(prm.raw) + if id := prm.objAddr.ContainerID(); id != nil { + getPrm.FromContainer(*id) + } - res.cliRes, err = prm.cli.GetObject(context.Background(), &getPrm, append(prm.opts, - client.WithSession(prm.sessionToken), - client.WithBearer(prm.bearerToken), - )...) + if id := prm.objAddr.ObjectID(); id != nil { + getPrm.ByID(*id) + } - return + if prm.sessionToken != nil { + getPrm.WithinSession(*prm.sessionToken) + } + + if prm.bearerToken != nil { + getPrm.WithBearerToken(*prm.bearerToken) + } + + if prm.raw { + getPrm.MarkRaw() + } + + if prm.local { + getPrm.MarkLocal() + } + + rdr, err := prm.cli.ObjectGetInit(context.Background(), getPrm) + if err != nil { + return nil, fmt.Errorf("init object reading on client: %w", err) + } + + var hdr object.Object + + if !rdr.ReadHeader(&hdr) { + _, err = rdr.Close() + return nil, fmt.Errorf("read object header: %w", err) + } + + sz := hdr.PayloadSize() + if sz > maxPayloadBufferSize { + sz = maxPayloadBufferSize + } + + buf := make([]byte, sz) + + _, err = io.CopyBuffer(prm.wrt, rdr, buf) + if err != nil { + return nil, fmt.Errorf("copy payload: %w", err) + } + + return &GetObjectRes{ + hdr: &hdr, + }, nil } // HeadObjectPrm groups parameters of HeadObject operation. @@ -415,36 +555,51 @@ func (x *HeadObjectPrm) SetMainOnlyFlag(v bool) { // HeadObjectRes groups resulting values of HeadObject operation. type HeadObjectRes struct { - cliRes *client.ObjectHeadRes + hdr *object.Object } // Header returns requested object header. func (x HeadObjectRes) Header() *object.Object { - return x.cliRes.Object() + return x.hdr } // HeadObject reads object header by address. // // Returns any error prevented the operation from completing correctly in error return. // For raw reading, returns *object.SplitInfoError error if object is virtual. -func HeadObject(prm HeadObjectPrm) (res HeadObjectRes, err error) { - var cliPrm client.ObjectHeaderParams +func HeadObject(prm HeadObjectPrm) (*HeadObjectRes, error) { + var cliPrm client.PrmObjectHead - cliPrm.WithAddress(prm.objAddr) - cliPrm.WithRawFlag(prm.raw) - - if prm.mainOnly { - cliPrm.WithMainFields() - } else { - cliPrm.WithAllFields() + if id := prm.objAddr.ContainerID(); id != nil { + cliPrm.FromContainer(*id) } - res.cliRes, err = prm.cli.HeadObject(context.Background(), &cliPrm, append(prm.opts, - client.WithSession(prm.sessionToken), - client.WithBearer(prm.bearerToken), - )...) + if id := prm.objAddr.ObjectID(); id != nil { + cliPrm.ByID(*id) + } - return + if prm.raw { + cliPrm.MarkRaw() + } + + if prm.local { + cliPrm.MarkLocal() + } + + res, err := prm.cli.ObjectHead(context.Background(), cliPrm) + if err != nil { + return nil, fmt.Errorf("read object header via client: %w", err) + } + + var hdr object.Object + + if !res.ReadHeader(&hdr) { + return nil, fmt.Errorf("missing header in response") + } + + return &HeadObjectRes{ + hdr: &hdr, + }, nil } // SearchObjectsPrm groups parameters of SearchObjects operation. @@ -462,29 +617,68 @@ func (x *SearchObjectsPrm) SetFilters(filters object.SearchFilters) { // SearchObjectsRes groups resulting values of SearchObjects operation. type SearchObjectsRes struct { - cliRes *client.ObjectSearchRes + ids []*oidSDK.ID } // IDList returns identifiers of the matched objects. func (x SearchObjectsRes) IDList() []*oidSDK.ID { - return x.cliRes.IDList() + return x.ids } // SearchObjects selects objects from container which match the filters. // // Returns any error prevented the operation from completing correctly in error return. -func SearchObjects(prm SearchObjectsPrm) (res SearchObjectsRes, err error) { - var cliPrm client.SearchObjectParams +func SearchObjects(prm SearchObjectsPrm) (*SearchObjectsRes, error) { + var cliPrm client.PrmObjectSearch - cliPrm.WithSearchFilters(prm.filters) - cliPrm.WithContainerID(prm.cnrID) + if prm.cnrID != nil { + cliPrm.InContainer(*prm.cnrID) + } - res.cliRes, err = prm.cli.SearchObjects(context.Background(), &cliPrm, append(prm.opts, - client.WithSession(prm.sessionToken), - client.WithBearer(prm.bearerToken), - )...) + cliPrm.SetFilters(prm.filters) - return + if prm.sessionToken != nil { + cliPrm.WithinSession(*prm.sessionToken) + } + + if prm.bearerToken != nil { + cliPrm.WithBearerToken(*prm.bearerToken) + } + + if prm.local { + cliPrm.MarkLocal() + } + + rdr, err := prm.cli.ObjectSearchInit(context.Background(), cliPrm) + if err != nil { + return nil, fmt.Errorf("init object search: %w", err) + } + + buf := make([]oidSDK.ID, 10) + var list []*oidSDK.ID + var n int + var ok bool + + for { + n, ok = rdr.Read(buf) + if !ok { + break + } + + for i := 0; i < n; i++ { + v := buf[i] + list = append(list, &v) + } + } + + _, err = rdr.Close() + if err != nil { + return nil, fmt.Errorf("read object list: %w", err) + } + + return &SearchObjectsRes{ + ids: list, + }, nil } // HashPayloadRangesPrm groups parameters of HashPayloadRanges operation. @@ -516,35 +710,64 @@ func (x *HashPayloadRangesPrm) SetSalt(salt []byte) { // HashPayloadRangesRes groups resulting values of HashPayloadRanges operation. type HashPayloadRangesRes struct { - cliRes *client.ObjectRangeHashRes + cliRes *client.ResObjectHash } // HashList returns list of hashes of the payload ranges keeping order. func (x HashPayloadRangesRes) HashList() [][]byte { - return x.cliRes.Hashes() + return x.cliRes.Checksums() } // HashPayloadRanges requests hashes (by default SHA256) of the object payload ranges. // // Returns any error prevented the operation from completing correctly in error return. // Returns an error if number of received hashes differs with the number of requested ranges. -func HashPayloadRanges(prm HashPayloadRangesPrm) (res HashPayloadRangesRes, err error) { - var cliPrm client.RangeChecksumParams +func HashPayloadRanges(prm HashPayloadRangesPrm) (*HashPayloadRangesRes, error) { + var cliPrm client.PrmObjectHash - cliPrm.WithAddress(prm.objAddr) - cliPrm.WithSalt(prm.salt) - cliPrm.WithRangeList(prm.rngs...) - - if prm.tz { - cliPrm.TZ() + if id := prm.objAddr.ContainerID(); id != nil { + cliPrm.FromContainer(*id) } - res.cliRes, err = prm.cli.HashObjectPayloadRanges(context.Background(), &cliPrm, append(prm.opts, - client.WithSession(prm.sessionToken), - client.WithBearer(prm.bearerToken), - )...) + if id := prm.objAddr.ObjectID(); id != nil { + cliPrm.ByID(*id) + } - return + if prm.local { + cliPrm.MarkLocal() + } + + cliPrm.UseSalt(prm.salt) + + rngs := make([]uint64, 2*len(prm.rngs)) + + for i := range prm.rngs { + rngs[2*i] = prm.rngs[i].GetOffset() + rngs[2*i+1] = prm.rngs[i].GetLength() + } + + cliPrm.SetRangeList(rngs...) + + if prm.tz { + cliPrm.TillichZemorAlgo() + } + + if prm.sessionToken != nil { + cliPrm.WithinSession(*prm.sessionToken) + } + + if prm.bearerToken != nil { + cliPrm.WithBearerToken(*prm.bearerToken) + } + + res, err := prm.cli.ObjectHash(context.Background(), cliPrm) + if err != nil { + return nil, fmt.Errorf("read payload hashes via client: %w", err) + } + + return &HashPayloadRangesRes{ + cliRes: res, + }, nil } // PayloadRangePrm groups parameters of PayloadRange operation. @@ -571,18 +794,44 @@ type PayloadRangeRes struct{} // // Returns any error prevented the operation from completing correctly in error return. // For raw reading, returns *object.SplitInfoError error if object is virtual. -func PayloadRange(prm PayloadRangePrm) (res PayloadRangeRes, err error) { - var cliPrm client.RangeDataParams +func PayloadRange(prm PayloadRangePrm) (*PayloadRangeRes, error) { + var cliPrm client.PrmObjectRange - cliPrm.WithRaw(prm.raw) - cliPrm.WithAddress(prm.objAddr) - cliPrm.WithDataWriter(prm.wrt) - cliPrm.WithRange(prm.rng) + if id := prm.objAddr.ContainerID(); id != nil { + cliPrm.FromContainer(*id) + } - _, err = prm.cli.ObjectPayloadRangeData(context.Background(), &cliPrm, append(prm.opts, - client.WithSession(prm.sessionToken), - client.WithBearer(prm.bearerToken), - )...) + if id := prm.objAddr.ObjectID(); id != nil { + cliPrm.ByID(*id) + } - return + if prm.raw { + cliPrm.MarkRaw() + } + + if prm.local { + cliPrm.MarkLocal() + } + + cliPrm.SetOffset(prm.rng.GetOffset()) + cliPrm.SetLength(prm.rng.GetLength()) + + rdr, err := prm.cli.ObjectRangeInit(context.Background(), cliPrm) + if err != nil { + return nil, fmt.Errorf("init payload reading: %w", err) + } + + sz := prm.rng.GetLength() + if sz > maxPayloadBufferSize { + sz = maxPayloadBufferSize + } + + buf := make([]byte, sz) + + _, err = io.CopyBuffer(prm.wrt, rdr, buf) + if err != nil { + return nil, fmt.Errorf("copy payload: %w", err) + } + + return new(PayloadRangeRes), nil } diff --git a/cmd/neofs-cli/internal/client/prm.go b/cmd/neofs-cli/internal/client/prm.go index 2db149857..186a60669 100644 --- a/cmd/neofs-cli/internal/client/prm.go +++ b/cmd/neofs-cli/internal/client/prm.go @@ -79,17 +79,15 @@ type commonObjectPrm struct { sessionTokenPrm bearerTokenPrm - opts []client.CallOption + local bool } // SetTTL sets request TTL value. func (x *commonObjectPrm) SetTTL(ttl uint32) { - x.opts = append(x.opts, client.WithTTL(ttl)) + x.local = ttl < 2 } // SetXHeaders sets request X-Headers. -func (x *commonObjectPrm) SetXHeaders(xhdrs []*session.XHeader) { - for _, xhdr := range xhdrs { - x.opts = append(x.opts, client.WithXHeader(xhdr)) - } +func (x *commonObjectPrm) SetXHeaders(_ []*session.XHeader) { + // FIXME: (neofs-node#1194) not supported by client } diff --git a/cmd/neofs-cli/modules/container.go b/cmd/neofs-cli/modules/container.go index a6a41f5fd..650e7758d 100644 --- a/cmd/neofs-cli/modules/container.go +++ b/cmd/neofs-cli/modules/container.go @@ -187,10 +187,6 @@ It will be stored in sidechain when inner ring will accepts it.`, prepareAPIClientWithKey(cmd, key, &putPrm, &getPrm) putPrm.SetContainer(*cnr) - if tok != nil { - putPrm.SetSessionToken(*tok) - } - res, err := internalclient.PutContainer(putPrm) exitOnErr(cmd, errf("rpc error: %w", err)) @@ -423,10 +419,6 @@ Container ID in EACL table will be substituted with ID from the CLI.`, prepareAPIClient(cmd, &setEACLPrm, &getEACLPrm) setEACLPrm.SetTable(*eaclTable) - if tok != nil { - setEACLPrm.SetSessionToken(*tok) - } - _, err = internalclient.SetEACL(setEACLPrm) exitOnErr(cmd, errf("rpc error: %w", err)) @@ -754,8 +746,8 @@ func prettyPrintContainer(cmd *cobra.Command, cnr *container.Container, jsonEnco id := container.CalculateID(cnr) cmd.Println("container ID:", id) - version := cnr.Version() - cmd.Printf("version: %d.%d\n", version.Major(), version.Minor()) + v := cnr.Version() + cmd.Printf("version: %d.%d\n", v.Major(), v.Minor()) cmd.Println("owner ID:", cnr.OwnerID()) diff --git a/cmd/neofs-node/container.go b/cmd/neofs-node/container.go index e83cadd93..4273b5691 100644 --- a/cmd/neofs-node/container.go +++ b/cmd/neofs-node/container.go @@ -308,11 +308,11 @@ func (r *remoteLoadAnnounceWriter) Put(a containerSDK.UsedSpaceAnnouncement) err } func (r *remoteLoadAnnounceWriter) Close() error { - var cliPrm apiClient.AnnounceSpacePrm + var cliPrm apiClient.PrmAnnounceSpace cliPrm.SetValues(r.buf) - _, err := r.client.AnnounceContainerUsedSpace(r.ctx, cliPrm) + _, err := r.client.ContainerAnnounceUsedSpace(r.ctx, cliPrm) return err } @@ -515,7 +515,7 @@ func (l *loadPlacementBuilder) isNodeFromContainerKey(epoch uint64, cid *cid.ID, return false, nil } -func (c *usedSpaceService) processLoadValue(ctx context.Context, a containerSDK.UsedSpaceAnnouncement, +func (c *usedSpaceService) processLoadValue(_ context.Context, a containerSDK.UsedSpaceAnnouncement, route []loadroute.ServerInfo, w loadcontroller.Writer) error { fromCnr, err := c.loadPlacementBuilder.isNodeFromContainerKey(a.Epoch(), a.ContainerID(), route[0].PublicKey()) if err != nil { diff --git a/cmd/neofs-node/object.go b/cmd/neofs-node/object.go index 196feb8db..5464a0fee 100644 --- a/cmd/neofs-node/object.go +++ b/cmd/neofs-node/object.go @@ -36,6 +36,7 @@ import ( truststorage "github.com/nspcc-dev/neofs-node/pkg/services/reputation/local/storage" "github.com/nspcc-dev/neofs-node/pkg/util/logger" "github.com/nspcc-dev/neofs-sdk-go/client" + apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status" cid "github.com/nspcc-dev/neofs-sdk-go/container/id" eaclSDK "github.com/nspcc-dev/neofs-sdk-go/eacl" addressSDK "github.com/nspcc-dev/neofs-sdk-go/object/address" @@ -449,57 +450,55 @@ func (c *reputationClient) submitResult(err error) { c.cons.trustStorage.Update(prm) } -func (c *reputationClient) PutObject(ctx context.Context, prm *client.PutObjectParams, opts ...client.CallOption) (*client.ObjectPutRes, error) { - res, err := c.MultiAddressClient.PutObject(ctx, prm, opts...) +func (c *reputationClient) ObjectPutInit(ctx context.Context, prm client.PrmObjectPutInit) (*client.ObjectWriter, error) { + res, err := c.MultiAddressClient.ObjectPutInit(ctx, prm) + + // FIXME: (neofs-node#1193) here we submit only initialization errors, writing errors are not processed + c.submitResult(err) + + return res, err +} + +func (c *reputationClient) ObjectDelete(ctx context.Context, prm client.PrmObjectDelete) (*client.ResObjectDelete, error) { + res, err := c.MultiAddressClient.ObjectDelete(ctx, prm) + if err != nil { + c.submitResult(err) + } else { + c.submitResult(apistatus.ErrFromStatus(res.Status())) + } + + return res, err +} + +func (c *reputationClient) GetObjectInit(ctx context.Context, prm client.PrmObjectGet) (*client.ObjectReader, error) { + res, err := c.MultiAddressClient.ObjectGetInit(ctx, prm) + + // FIXME: (neofs-node#1193) here we submit only initialization errors, reading errors are not processed + c.submitResult(err) + + return res, err +} + +func (c *reputationClient) ObjectHead(ctx context.Context, prm client.PrmObjectHead) (*client.ResObjectHead, error) { + res, err := c.MultiAddressClient.ObjectHead(ctx, prm) c.submitResult(err) return res, err } -func (c *reputationClient) DeleteObject(ctx context.Context, prm *client.DeleteObjectParams, opts ...client.CallOption) (*client.ObjectDeleteRes, error) { - res, err := c.MultiAddressClient.DeleteObject(ctx, prm, opts...) +func (c *reputationClient) ObjectHash(ctx context.Context, prm client.PrmObjectHash) (*client.ResObjectHash, error) { + res, err := c.MultiAddressClient.ObjectHash(ctx, prm) c.submitResult(err) return res, err } -func (c *reputationClient) GetObject(ctx context.Context, prm *client.GetObjectParams, opts ...client.CallOption) (*client.ObjectGetRes, error) { - res, err := c.MultiAddressClient.GetObject(ctx, prm, opts...) - - c.submitResult(err) - - return res, err -} - -func (c *reputationClient) HeadObject(ctx context.Context, prm *client.ObjectHeaderParams, opts ...client.CallOption) (*client.ObjectHeadRes, error) { - res, err := c.MultiAddressClient.HeadObject(ctx, prm, opts...) - - c.submitResult(err) - - return res, err -} - -func (c *reputationClient) ObjectPayloadRangeData(ctx context.Context, prm *client.RangeDataParams, opts ...client.CallOption) (*client.ObjectRangeRes, error) { - res, err := c.MultiAddressClient.ObjectPayloadRangeData(ctx, prm, opts...) - - c.submitResult(err) - - return res, err -} - -func (c *reputationClient) HashObjectPayloadRanges(ctx context.Context, prm *client.RangeChecksumParams, opts ...client.CallOption) (*client.ObjectRangeHashRes, error) { - res, err := c.MultiAddressClient.HashObjectPayloadRanges(ctx, prm, opts...) - - c.submitResult(err) - - return res, err -} - -func (c *reputationClient) SearchObjects(ctx context.Context, prm *client.SearchObjectParams, opts ...client.CallOption) (*client.ObjectSearchRes, error) { - res, err := c.MultiAddressClient.SearchObjects(ctx, prm, opts...) +func (c *reputationClient) ObjectSearchInit(ctx context.Context, prm client.PrmObjectSearch) (*client.ObjectListReader, error) { + res, err := c.MultiAddressClient.ObjectSearchInit(ctx, prm) + // FIXME: (neofs-node#1193) here we submit only initialization errors, reading errors are not processed c.submitResult(err) return res, err diff --git a/cmd/neofs-node/reputation/intermediate/remote.go b/cmd/neofs-node/reputation/intermediate/remote.go index 8cc1e3c5b..e19e1e4c2 100644 --- a/cmd/neofs-node/reputation/intermediate/remote.go +++ b/cmd/neofs-node/reputation/intermediate/remote.go @@ -95,7 +95,6 @@ func (rtp *RemoteTrustWriter) Write(t reputation.Trust) error { p.SetContext(rtp.eiCtx) p.SetClient(rtp.client) - p.SetPrivateKey(rtp.key) p.SetEpoch(rtp.eiCtx.Epoch()) p.SetIteration(rtp.eiCtx.I()) p.SetTrust(*apiPeerToPeerTrust) diff --git a/cmd/neofs-node/reputation/internal/client/client.go b/cmd/neofs-node/reputation/internal/client/client.go index e6f40e579..1fcaf5b6e 100644 --- a/cmd/neofs-node/reputation/internal/client/client.go +++ b/cmd/neofs-node/reputation/internal/client/client.go @@ -2,7 +2,6 @@ package internal import ( "context" - "crypto/ecdsa" coreclient "github.com/nspcc-dev/neofs-node/pkg/core/client" "github.com/nspcc-dev/neofs-sdk-go/client" @@ -14,8 +13,6 @@ type commonPrm struct { cli coreclient.Client ctx context.Context - - opts []client.CallOption } // SetClient sets base client for NeoFS API communication. @@ -32,18 +29,11 @@ func (x *commonPrm) SetContext(ctx context.Context) { x.ctx = ctx } -// SetPrivateKey sets private key to sign the request(s). -// -// Required parameter. -func (x *commonPrm) SetPrivateKey(key *ecdsa.PrivateKey) { - x.opts = append(x.opts, client.WithKey(key)) -} - // AnnounceLocalPrm groups parameters of AnnounceLocal operation. type AnnounceLocalPrm struct { commonPrm - cliPrm client.AnnounceLocalTrustPrm + cliPrm client.PrmAnnounceLocalTrust } // SetEpoch sets epoch in which the trust was assessed. @@ -65,7 +55,7 @@ type AnnounceLocalRes struct{} // // Returns any error prevented the operation from completing correctly in error return. func AnnounceLocal(prm AnnounceLocalPrm) (res AnnounceLocalRes, err error) { - var cliRes *client.AnnounceLocalTrustRes + var cliRes *client.ResAnnounceLocalTrust cliRes, err = prm.cli.AnnounceLocalTrust(prm.ctx, prm.cliPrm) if err == nil { @@ -80,7 +70,7 @@ func AnnounceLocal(prm AnnounceLocalPrm) (res AnnounceLocalRes, err error) { type AnnounceIntermediatePrm struct { commonPrm - cliPrm client.AnnounceIntermediateTrustPrm + cliPrm client.PrmAnnounceIntermediateTrust } // SetEpoch sets number of the epoch when the trust calculation's iteration was executed. @@ -108,7 +98,7 @@ type AnnounceIntermediateRes struct{} // // Returns any error prevented the operation from completing correctly in error return. func AnnounceIntermediate(prm AnnounceIntermediatePrm) (res AnnounceIntermediateRes, err error) { - var cliRes *client.AnnounceIntermediateTrustRes + var cliRes *client.ResAnnounceIntermediateTrust cliRes, err = prm.cli.AnnounceIntermediateTrust(prm.ctx, prm.cliPrm) if err == nil { diff --git a/cmd/neofs-node/reputation/local/remote.go b/cmd/neofs-node/reputation/local/remote.go index b8254452c..9cea7fbb2 100644 --- a/cmd/neofs-node/reputation/local/remote.go +++ b/cmd/neofs-node/reputation/local/remote.go @@ -89,7 +89,6 @@ func (rtp *RemoteTrustWriter) Close() error { prm.SetContext(rtp.ctx) prm.SetClient(rtp.client) - prm.SetPrivateKey(rtp.key) prm.SetEpoch(rtp.ctx.Epoch()) prm.SetTrusts(rtp.buf) diff --git a/go.mod b/go.mod index 8b3a9236a..d1659caa1 100644 --- a/go.mod +++ b/go.mod @@ -14,10 +14,10 @@ require ( github.com/multiformats/go-multiaddr v0.4.0 github.com/nspcc-dev/hrw v1.0.9 github.com/nspcc-dev/neo-go v0.98.0 - github.com/nspcc-dev/neofs-api-go/v2 v2.11.2-0.20220127135316-32dd0bb3f9c5 + github.com/nspcc-dev/neofs-api-go/v2 v2.12.0 github.com/nspcc-dev/neofs-contract v0.14.2 - github.com/nspcc-dev/neofs-sdk-go v0.0.0-20220201141054-6a7ba33b59ef - github.com/nspcc-dev/tzhash v1.5.1 + github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.1.0.20220225083115-4fba1af6aa08 + github.com/nspcc-dev/tzhash v1.5.2 github.com/panjf2000/ants/v2 v2.4.0 github.com/paulmach/orb v0.2.2 github.com/prometheus/client_golang v1.11.0 diff --git a/go.sum b/go.sum index 5b253f9a4..60588c956 100644 --- a/go.sum +++ b/go.sum @@ -368,8 +368,8 @@ github.com/nspcc-dev/neo-go v0.73.1-pre.0.20200303142215-f5a1b928ce09/go.mod h1: github.com/nspcc-dev/neo-go v0.98.0 h1:yyW4sgY88/pLf0949qmgfkQXzRKC3CI/WyhqXNnwMd8= github.com/nspcc-dev/neo-go v0.98.0/go.mod h1:E3cc1x6RXSXrJb2nDWXTXjnXk3rIqVN8YdFyWv+FrqM= github.com/nspcc-dev/neofs-api-go/v2 v2.11.0-pre.0.20211201134523-3604d96f3fe1/go.mod h1:oS8dycEh8PPf2Jjp6+8dlwWyEv2Dy77h/XhhcdxYEFs= -github.com/nspcc-dev/neofs-api-go/v2 v2.11.2-0.20220127135316-32dd0bb3f9c5 h1:y9tbmUYhcr052QXsa4/IfUKAi2cx3TGDsEZUAow3P/Y= -github.com/nspcc-dev/neofs-api-go/v2 v2.11.2-0.20220127135316-32dd0bb3f9c5/go.mod h1:oS8dycEh8PPf2Jjp6+8dlwWyEv2Dy77h/XhhcdxYEFs= +github.com/nspcc-dev/neofs-api-go/v2 v2.12.0 h1:xWqXzorDk9WFMTtWP7cwwlyJDL1X6Z4HT1e5zqkq7xY= +github.com/nspcc-dev/neofs-api-go/v2 v2.12.0/go.mod h1:oS8dycEh8PPf2Jjp6+8dlwWyEv2Dy77h/XhhcdxYEFs= github.com/nspcc-dev/neofs-contract v0.14.2 h1:m3Wx5LO9QMKt0w7iVVqrsU4SPs67RfTCS6QSyhqCkCA= github.com/nspcc-dev/neofs-contract v0.14.2/go.mod h1:wSA0lmDqERsb0LsSPxOzkYULrTCaOc9JZG609uNNBzc= github.com/nspcc-dev/neofs-crypto v0.2.0/go.mod h1:F/96fUzPM3wR+UGsPi3faVNmFlA9KAEAUQR7dMxZmNA= @@ -377,13 +377,13 @@ github.com/nspcc-dev/neofs-crypto v0.2.3/go.mod h1:8w16GEJbH6791ktVqHN9YRNH3s9BE github.com/nspcc-dev/neofs-crypto v0.3.0 h1:zlr3pgoxuzrmGCxc5W8dGVfA9Rro8diFvVnBg0L4ifM= github.com/nspcc-dev/neofs-crypto v0.3.0/go.mod h1:8w16GEJbH6791ktVqHN9YRNH3s9BEEKYxGhlFnp0cDw= github.com/nspcc-dev/neofs-sdk-go v0.0.0-20211201182451-a5b61c4f6477/go.mod h1:dfMtQWmBHYpl9Dez23TGtIUKiFvCIxUZq/CkSIhEpz4= -github.com/nspcc-dev/neofs-sdk-go v0.0.0-20220201141054-6a7ba33b59ef h1:0DuR21CIuOIPfVIyThWATulCkemdqHmmEqKdt22EHXk= -github.com/nspcc-dev/neofs-sdk-go v0.0.0-20220201141054-6a7ba33b59ef/go.mod h1:dPvrJlIgoF1hLJlOWgbNmxQwANsQI/8dTe/wfjxwy04= +github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.1.0.20220225083115-4fba1af6aa08 h1:pYPSLxuyG77BPzqVN34CVh7aR8//1h5PRlNrFSnpyEw= +github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.1.0.20220225083115-4fba1af6aa08/go.mod h1:/WV31AQHs6YLTjMgMjMZw8Z3/Q7b6kMjNgJVsRab5AU= github.com/nspcc-dev/rfc6979 v0.1.0/go.mod h1:exhIh1PdpDC5vQmyEsGvc4YDM/lyQp/452QxGq/UEso= github.com/nspcc-dev/rfc6979 v0.2.0 h1:3e1WNxrN60/6N0DW7+UYisLeZJyfqZTNOjeV/toYvOE= github.com/nspcc-dev/rfc6979 v0.2.0/go.mod h1:exhIh1PdpDC5vQmyEsGvc4YDM/lyQp/452QxGq/UEso= -github.com/nspcc-dev/tzhash v1.5.1 h1:eiPfipjS/7/jVJIkQYQgr7O3VL2NBsuROJGwC3g2GUk= -github.com/nspcc-dev/tzhash v1.5.1/go.mod h1:gwAx6mcsbkfY+JVp+PovoP2Gvw6y57W8dj7zDHKOhzI= +github.com/nspcc-dev/tzhash v1.5.2 h1:GuIQPOY2xpl5ZE1pbUbz+QdKXVOTyzbbxSVv0nBfa98= +github.com/nspcc-dev/tzhash v1.5.2/go.mod h1:gwAx6mcsbkfY+JVp+PovoP2Gvw6y57W8dj7zDHKOhzI= github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= diff --git a/pkg/core/client/client.go b/pkg/core/client/client.go index b833fa3cf..9843bfb37 100644 --- a/pkg/core/client/client.go +++ b/pkg/core/client/client.go @@ -12,18 +12,18 @@ import ( // Client is an interface of NeoFS storage // node's client. type Client interface { - AnnounceContainerUsedSpace(context.Context, client.AnnounceSpacePrm) (*client.AnnounceSpaceRes, error) + ContainerAnnounceUsedSpace(context.Context, client.PrmAnnounceSpace) (*client.ResAnnounceSpace, error) - PutObject(context.Context, *client.PutObjectParams, ...client.CallOption) (*client.ObjectPutRes, error) - DeleteObject(context.Context, *client.DeleteObjectParams, ...client.CallOption) (*client.ObjectDeleteRes, error) - GetObject(context.Context, *client.GetObjectParams, ...client.CallOption) (*client.ObjectGetRes, error) - HeadObject(context.Context, *client.ObjectHeaderParams, ...client.CallOption) (*client.ObjectHeadRes, error) - SearchObjects(context.Context, *client.SearchObjectParams, ...client.CallOption) (*client.ObjectSearchRes, error) - ObjectPayloadRangeData(context.Context, *client.RangeDataParams, ...client.CallOption) (*client.ObjectRangeRes, error) - HashObjectPayloadRanges(context.Context, *client.RangeChecksumParams, ...client.CallOption) (*client.ObjectRangeHashRes, error) + ObjectPutInit(context.Context, client.PrmObjectPutInit) (*client.ObjectWriter, error) + ObjectDelete(context.Context, client.PrmObjectDelete) (*client.ResObjectDelete, error) + ObjectGetInit(context.Context, client.PrmObjectGet) (*client.ObjectReader, error) + ObjectHead(context.Context, client.PrmObjectHead) (*client.ResObjectHead, error) + ObjectSearchInit(context.Context, client.PrmObjectSearch) (*client.ObjectListReader, error) + ObjectRangeInit(context.Context, client.PrmObjectRange) (*client.ObjectRangeReader, error) + ObjectHash(context.Context, client.PrmObjectHash) (*client.ResObjectHash, error) - AnnounceLocalTrust(context.Context, client.AnnounceLocalTrustPrm) (*client.AnnounceLocalTrustRes, error) - AnnounceIntermediateTrust(context.Context, client.AnnounceIntermediateTrustPrm) (*client.AnnounceIntermediateTrustRes, error) + AnnounceLocalTrust(context.Context, client.PrmAnnounceLocalTrust) (*client.ResAnnounceLocalTrust, error) + AnnounceIntermediateTrust(context.Context, client.PrmAnnounceIntermediateTrust) (*client.ResAnnounceIntermediateTrust, error) Raw() *rawclient.Client diff --git a/pkg/innerring/internal/client/client.go b/pkg/innerring/internal/client/client.go index 25f15afa6..2d3803245 100644 --- a/pkg/innerring/internal/client/client.go +++ b/pkg/innerring/internal/client/client.go @@ -3,7 +3,9 @@ package neofsapiclient import ( "context" "crypto/ecdsa" + "errors" "fmt" + "io" clientcore "github.com/nspcc-dev/neofs-node/pkg/core/client" "github.com/nspcc-dev/neofs-node/pkg/services/object_manager/storagegroup" @@ -46,12 +48,12 @@ func (x *SearchSGPrm) SetContainerID(id *cid.ID) { // SearchSGRes groups resulting values of SearchSG operation. type SearchSGRes struct { - cliRes *client.ObjectSearchRes + cliRes []*oid.ID } // IDList returns list of IDs of storage groups in container. func (x SearchSGRes) IDList() []*oid.ID { - return x.cliRes.IDList() + return x.cliRes } var sgFilter = storagegroup.SearchQuery() @@ -59,21 +61,49 @@ var sgFilter = storagegroup.SearchQuery() // SearchSG lists objects of storage group type in the container. // // Returns any error prevented the operation from completing correctly in error return. -func (x Client) SearchSG(prm SearchSGPrm) (res SearchSGRes, err error) { - var cliPrm client.SearchObjectParams +func (x Client) SearchSG(prm SearchSGPrm) (*SearchSGRes, error) { + var cliPrm client.PrmObjectSearch - cliPrm.WithContainerID(prm.cnrID) - cliPrm.WithSearchFilters(sgFilter) + cliPrm.InContainer(*prm.cnrID) + cliPrm.SetFilters(sgFilter) - res.cliRes, err = x.c.SearchObjects(prm.ctx, &cliPrm, - client.WithKey(x.key), - ) - if err == nil { - // pull out an error from status - err = apistatus.ErrFromStatus(res.cliRes.Status()) + rdr, err := x.c.ObjectSearchInit(prm.ctx, cliPrm) + if err != nil { + return nil, fmt.Errorf("init object search: %w", err) } - return + rdr.UseKey(*x.key) + + buf := make([]oid.ID, 10) + var list []*oid.ID + var n int + var ok bool + + for { + n, ok = rdr.Read(buf) + if !ok { + break + } + + for i := 0; i < n; i++ { + v := buf[i] + list = append(list, &v) + } + } + + res, err := rdr.Close() + if err == nil { + // pull out an error from status + err = apistatus.ErrFromStatus(res.Status()) + } + + if err != nil { + return nil, fmt.Errorf("read object list: %w", err) + } + + return &SearchSGRes{ + cliRes: list, + }, nil } // GetObjectPrm groups parameters of GetObject operation. @@ -83,31 +113,59 @@ type GetObjectPrm struct { // GetObjectRes groups resulting values of GetObject operation. type GetObjectRes struct { - cliRes *client.ObjectGetRes + obj *object.Object } // Object returns received object. func (x GetObjectRes) Object() *object.Object { - return x.cliRes.Object() + return x.obj } // GetObject reads the object by address. // // Returns any error prevented the operation from completing correctly in error return. -func (x Client) GetObject(prm GetObjectPrm) (res GetObjectRes, err error) { - var cliPrm client.GetObjectParams +func (x Client) GetObject(prm GetObjectPrm) (*GetObjectRes, error) { + var cliPrm client.PrmObjectGet - cliPrm.WithAddress(prm.objAddr) - - res.cliRes, err = x.c.GetObject(prm.ctx, &cliPrm, - client.WithKey(x.key), - ) - if err == nil { - // pull out an error from status - err = apistatus.ErrFromStatus(res.cliRes.Status()) + if id := prm.objAddr.ContainerID(); id != nil { + cliPrm.FromContainer(*id) } - return + if id := prm.objAddr.ObjectID(); id != nil { + cliPrm.ByID(*id) + } + + rdr, err := x.c.ObjectGetInit(prm.ctx, cliPrm) + if err == nil { + return nil, fmt.Errorf("init object search: %w", err) + } + + rdr.UseKey(*x.key) + + var obj object.Object + + if !rdr.ReadHeader(&obj) { + res, err := rdr.Close() + if err == nil { + // pull out an error from status + err = apistatus.ErrFromStatus(res.Status()) + } + + return nil, fmt.Errorf("read object header: %w", err) + } + + buf := make([]byte, obj.PayloadSize()) + + _, err = rdr.Read(buf) + if err != nil && !errors.Is(err, io.EOF) { + return nil, fmt.Errorf("read payload: %w", err) + } + + object.NewRawFrom(&obj).SetPayload(buf) + + return &GetObjectRes{ + obj: &obj, + }, nil } // HeadObjectPrm groups parameters of HeadObject operation. @@ -116,7 +174,7 @@ type HeadObjectPrm struct { raw bool - ttl uint32 + local bool } // SetRawFlag sets flag of raw request. @@ -126,40 +184,61 @@ func (x *HeadObjectPrm) SetRawFlag() { // SetTTL sets request TTL value. func (x *HeadObjectPrm) SetTTL(ttl uint32) { - x.ttl = ttl + x.local = ttl < 2 } // HeadObjectRes groups resulting values of HeadObject operation. type HeadObjectRes struct { - cliRes *client.ObjectHeadRes + hdr *object.Object } // Header returns received object header. func (x HeadObjectRes) Header() *object.Object { - return x.cliRes.Object() + return x.hdr } // HeadObject reads short object header by address. // // Returns any error prevented the operation from completing correctly in error return. // For raw requests, returns *object.SplitInfoError error if requested object is virtual. -func (x Client) HeadObject(prm HeadObjectPrm) (res HeadObjectRes, err error) { - var cliPrm client.ObjectHeaderParams +func (x Client) HeadObject(prm HeadObjectPrm) (*HeadObjectRes, error) { + var cliPrm client.PrmObjectHead - cliPrm.WithAddress(prm.objAddr) - cliPrm.WithRawFlag(prm.raw) - cliPrm.WithMainFields() - - res.cliRes, err = x.c.HeadObject(prm.ctx, &cliPrm, - client.WithKey(x.key), - client.WithTTL(prm.ttl), - ) - if err == nil { - // pull out an error from status - err = apistatus.ErrFromStatus(res.cliRes.Status()) + if prm.raw { + cliPrm.MarkRaw() } - return + if prm.local { + cliPrm.MarkLocal() + } + + if id := prm.objAddr.ContainerID(); id != nil { + cliPrm.FromContainer(*id) + } + + if id := prm.objAddr.ObjectID(); id != nil { + cliPrm.ByID(*id) + } + + cliRes, err := x.c.ObjectHead(prm.ctx, cliPrm) + if err == nil { + // pull out an error from status + err = apistatus.ErrFromStatus(cliRes.Status()) + } + + if err != nil { + return nil, fmt.Errorf("read object header from NeoFS: %w", err) + } + + var hdr object.Object + + if !cliRes.ReadHeader(&hdr) { + return nil, errors.New("missing object header in the response") + } + + return &HeadObjectRes{ + hdr: &hdr, + }, nil } // GetObjectPayload reads object by address from NeoFS via Client and returns its payload. @@ -231,21 +310,25 @@ func (x HashPayloadRangeRes) Hash() []byte { return x.h } -// HashObjectRange requests to calculate Tillich-Zemor hash of the payload range of the object +// HashPayloadRange requests to calculate Tillich-Zemor hash of the payload range of the object // from the remote server's local storage. // // Returns any error prevented the operation from completing correctly in error return. func (x Client) HashPayloadRange(prm HashPayloadRangePrm) (res HashPayloadRangeRes, err error) { - var cliPrm client.RangeChecksumParams + var cliPrm client.PrmObjectHash - cliPrm.WithAddress(prm.objAddr) - cliPrm.WithRangeList(prm.rng) - cliPrm.TZ() + if id := prm.objAddr.ContainerID(); id != nil { + cliPrm.FromContainer(*id) + } - cliRes, err := x.c.HashObjectPayloadRanges(prm.ctx, &cliPrm, - client.WithKey(x.key), - client.WithTTL(1), - ) + if id := prm.objAddr.ObjectID(); id != nil { + cliPrm.ByID(*id) + } + + cliPrm.SetRangeList(prm.rng.GetOffset(), prm.rng.GetLength()) + cliPrm.TillichZemorAlgo() + + cliRes, err := x.c.ObjectHash(prm.ctx, cliPrm) if err == nil { // pull out an error from status err = apistatus.ErrFromStatus(cliRes.Status()) @@ -253,9 +336,9 @@ func (x Client) HashPayloadRange(prm HashPayloadRangePrm) (res HashPayloadRangeR return } - hs := cliRes.Hashes() + hs := cliRes.Checksums() if ln := len(hs); ln != 1 { - err = fmt.Errorf("wrong number of hashes %d", ln) + err = fmt.Errorf("wrong number of checksums %d", ln) } else { res.h = hs[0] } diff --git a/pkg/innerring/processors/neofs/process_bind.go b/pkg/innerring/processors/neofs/process_bind.go index e46dbd40d..20a6034af 100644 --- a/pkg/innerring/processors/neofs/process_bind.go +++ b/pkg/innerring/processors/neofs/process_bind.go @@ -4,12 +4,11 @@ import ( "crypto/elliptic" "fmt" - "github.com/mr-tron/base58" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" - "github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neofs-node/pkg/morph/client/neofsid" "github.com/nspcc-dev/neofs-node/pkg/morph/event/neofs" + "github.com/nspcc-dev/neofs-sdk-go/owner" "go.uber.org/zap" ) @@ -74,7 +73,6 @@ func (np *Processor) checkBindCommon(e *bindCommonContext) error { func (np *Processor) approveBindCommon(e *bindCommonContext) { // calculate wallet address - // TODO: nspcc-dev/neofs-sdk-go#134 implement some utilities in API Go lib to do it scriptHash := e.User() u160, err := util.Uint160DecodeBytesBE(scriptHash) @@ -86,17 +84,8 @@ func (np *Processor) approveBindCommon(e *bindCommonContext) { return } - wallet, err := base58.Decode(address.Uint160ToString(u160)) - if err != nil { - np.log.Error("could not decode wallet address", - zap.String("error", err.Error()), - ) - - return - } - prm := neofsid.CommonBindPrm{} - prm.SetOwnerID(wallet) + prm.SetOwnerID(owner.ScriptHashToIDBytes(u160)) prm.SetKeys(e.Keys()) prm.SetHash(e.bindCommon.TxHash()) diff --git a/pkg/innerring/processors/settlement/basic/context.go b/pkg/innerring/processors/settlement/basic/context.go index 075300009..e73eeddb1 100644 --- a/pkg/innerring/processors/settlement/basic/context.go +++ b/pkg/innerring/processors/settlement/basic/context.go @@ -4,7 +4,6 @@ import ( "math/big" "sync" - "github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neofs-node/pkg/innerring/processors/settlement/common" "github.com/nspcc-dev/neofs-node/pkg/morph/client/container" @@ -60,10 +59,8 @@ type ( ) func NewIncomeSettlementContext(p *IncomeSettlementContextPrms) (*IncomeSettlementContext, error) { - bankingAccount, err := bankOwnerID() - if err != nil { - return nil, err // should never happen - } + bankingAccount := owner.NewID() + bankingAccount.SetScriptHash(util.Uint160{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}) return &IncomeSettlementContext{ log: p.Log, @@ -79,17 +76,3 @@ func NewIncomeSettlementContext(p *IncomeSettlementContextPrms) (*IncomeSettleme distributeTable: NewNodeSizeTable(), }, nil } - -func bankOwnerID() (*owner.ID, error) { - u := util.Uint160{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} - - o := owner.NewID() - // TODO: nspcc-dev/neofs-sdk-go#134 use `SetScriptHash` method. - err := o.Parse(address.Uint160ToString(u)) - if err != nil { - return nil, err - } - - return o, nil -} diff --git a/pkg/innerring/rpc.go b/pkg/innerring/rpc.go index 63e73e6dc..c4332ddb7 100644 --- a/pkg/innerring/rpc.go +++ b/pkg/innerring/rpc.go @@ -13,7 +13,6 @@ import ( "github.com/nspcc-dev/neofs-node/pkg/network/cache" "github.com/nspcc-dev/neofs-node/pkg/services/audit" "github.com/nspcc-dev/neofs-node/pkg/services/object_manager/placement" - "github.com/nspcc-dev/neofs-sdk-go/client" "github.com/nspcc-dev/neofs-sdk-go/netmap" "github.com/nspcc-dev/neofs-sdk-go/object" addressSDK "github.com/nspcc-dev/neofs-sdk-go/object/address" @@ -75,9 +74,6 @@ func (c *ClientCache) getSG(ctx context.Context, addr *addressSDK.Address, nm *n return nil, fmt.Errorf("can't build object placement: %w", err) } - getParams := new(client.GetObjectParams) - getParams.WithAddress(addr) - var info clientcore.NodeInfo for _, node := range placement.FlattenNodes(nodes) { diff --git a/pkg/network/cache/multi.go b/pkg/network/cache/multi.go index d4fb65c40..294434b01 100644 --- a/pkg/network/cache/multi.go +++ b/pkg/network/cache/multi.go @@ -79,79 +79,79 @@ func (x *multiClient) iterateClients(ctx context.Context, f func(clientcore.Clie return firstErr } -func (x *multiClient) PutObject(ctx context.Context, p *client.PutObjectParams, opts ...client.CallOption) (res *client.ObjectPutRes, err error) { +func (x *multiClient) ObjectPutInit(ctx context.Context, p client.PrmObjectPutInit) (res *client.ObjectWriter, err error) { err = x.iterateClients(ctx, func(c clientcore.Client) error { - res, err = c.PutObject(ctx, p, opts...) + res, err = c.ObjectPutInit(ctx, p) return err }) return } -func (x *multiClient) AnnounceContainerUsedSpace(ctx context.Context, prm client.AnnounceSpacePrm) (res *client.AnnounceSpaceRes, err error) { +func (x *multiClient) ContainerAnnounceUsedSpace(ctx context.Context, prm client.PrmAnnounceSpace) (res *client.ResAnnounceSpace, err error) { err = x.iterateClients(ctx, func(c clientcore.Client) error { - res, err = c.AnnounceContainerUsedSpace(ctx, prm) + res, err = c.ContainerAnnounceUsedSpace(ctx, prm) return err }) return } -func (x *multiClient) DeleteObject(ctx context.Context, p *client.DeleteObjectParams, opts ...client.CallOption) (res *client.ObjectDeleteRes, err error) { +func (x *multiClient) ObjectDelete(ctx context.Context, p client.PrmObjectDelete) (res *client.ResObjectDelete, err error) { err = x.iterateClients(ctx, func(c clientcore.Client) error { - res, err = c.DeleteObject(ctx, p, opts...) + res, err = c.ObjectDelete(ctx, p) return err }) return } -func (x *multiClient) GetObject(ctx context.Context, p *client.GetObjectParams, opts ...client.CallOption) (res *client.ObjectGetRes, err error) { +func (x *multiClient) ObjectGetInit(ctx context.Context, p client.PrmObjectGet) (res *client.ObjectReader, err error) { err = x.iterateClients(ctx, func(c clientcore.Client) error { - res, err = c.GetObject(ctx, p, opts...) + res, err = c.ObjectGetInit(ctx, p) return err }) return } -func (x *multiClient) ObjectPayloadRangeData(ctx context.Context, p *client.RangeDataParams, opts ...client.CallOption) (res *client.ObjectRangeRes, err error) { +func (x *multiClient) ObjectRangeInit(ctx context.Context, p client.PrmObjectRange) (res *client.ObjectRangeReader, err error) { err = x.iterateClients(ctx, func(c clientcore.Client) error { - res, err = c.ObjectPayloadRangeData(ctx, p, opts...) + res, err = c.ObjectRangeInit(ctx, p) return err }) return } -func (x *multiClient) HeadObject(ctx context.Context, p *client.ObjectHeaderParams, opts ...client.CallOption) (res *client.ObjectHeadRes, err error) { +func (x *multiClient) ObjectHead(ctx context.Context, p client.PrmObjectHead) (res *client.ResObjectHead, err error) { err = x.iterateClients(ctx, func(c clientcore.Client) error { - res, err = c.HeadObject(ctx, p, opts...) + res, err = c.ObjectHead(ctx, p) return err }) return } -func (x *multiClient) HashObjectPayloadRanges(ctx context.Context, p *client.RangeChecksumParams, opts ...client.CallOption) (res *client.ObjectRangeHashRes, err error) { +func (x *multiClient) ObjectHash(ctx context.Context, p client.PrmObjectHash) (res *client.ResObjectHash, err error) { err = x.iterateClients(ctx, func(c clientcore.Client) error { - res, err = c.HashObjectPayloadRanges(ctx, p, opts...) + res, err = c.ObjectHash(ctx, p) return err }) return } -func (x *multiClient) SearchObjects(ctx context.Context, p *client.SearchObjectParams, opts ...client.CallOption) (res *client.ObjectSearchRes, err error) { +func (x *multiClient) ObjectSearchInit(ctx context.Context, p client.PrmObjectSearch) (res *client.ObjectListReader, err error) { err = x.iterateClients(ctx, func(c clientcore.Client) error { - res, err = c.SearchObjects(ctx, p, opts...) + res, err = c.ObjectSearchInit(ctx, p) return err }) return } -func (x *multiClient) AnnounceLocalTrust(ctx context.Context, prm client.AnnounceLocalTrustPrm) (res *client.AnnounceLocalTrustRes, err error) { +func (x *multiClient) AnnounceLocalTrust(ctx context.Context, prm client.PrmAnnounceLocalTrust) (res *client.ResAnnounceLocalTrust, err error) { err = x.iterateClients(ctx, func(c clientcore.Client) error { res, err = c.AnnounceLocalTrust(ctx, prm) return err @@ -160,7 +160,7 @@ func (x *multiClient) AnnounceLocalTrust(ctx context.Context, prm client.Announc return } -func (x *multiClient) AnnounceIntermediateTrust(ctx context.Context, prm client.AnnounceIntermediateTrustPrm) (res *client.AnnounceIntermediateTrustRes, err error) { +func (x *multiClient) AnnounceIntermediateTrust(ctx context.Context, prm client.PrmAnnounceIntermediateTrust) (res *client.ResAnnounceIntermediateTrust, err error) { err = x.iterateClients(ctx, func(c clientcore.Client) error { res, err = c.AnnounceIntermediateTrust(ctx, prm) return err diff --git a/pkg/services/audit/auditor/pop.go b/pkg/services/audit/auditor/pop.go index 8ada03b5c..fec35d761 100644 --- a/pkg/services/audit/auditor/pop.go +++ b/pkg/services/audit/auditor/pop.go @@ -1,15 +1,15 @@ package auditor import ( - "github.com/nspcc-dev/neofs-sdk-go/client" "github.com/nspcc-dev/neofs-sdk-go/netmap" oidSDK "github.com/nspcc-dev/neofs-sdk-go/object/id" + "github.com/nspcc-dev/tzhash/tz" "go.uber.org/zap" ) const ( hashRangeNumber = 4 - minGamePayloadSize = hashRangeNumber * client.TZSize + minGamePayloadSize = hashRangeNumber * tz.Size ) func (c *Context) executePoP() { diff --git a/pkg/services/container/executor.go b/pkg/services/container/executor.go index 011723b75..276232bbd 100644 --- a/pkg/services/container/executor.go +++ b/pkg/services/container/executor.go @@ -12,7 +12,7 @@ import ( type ContextWithToken struct { context.Context - SessionToken *session.SessionToken + SessionToken *session.Token } type ServiceExecutor interface { @@ -40,7 +40,7 @@ func NewExecutionService(exec ServiceExecutor) Server { func contextWithTokenFromRequest(ctx context.Context, req interface { GetMetaHeader() *session.RequestMetaHeader }) ContextWithToken { - var tok *session.SessionToken + var tok *session.Token for meta := req.GetMetaHeader(); meta != nil; meta = meta.GetOrigin() { tok = meta.GetSessionToken() diff --git a/pkg/services/container/morph/executor_test.go b/pkg/services/container/morph/executor_test.go index 857fd1e9f..28b6eccd7 100644 --- a/pkg/services/container/morph/executor_test.go +++ b/pkg/services/container/morph/executor_test.go @@ -18,27 +18,27 @@ import ( type mock struct{} -func (m mock) Put(c *containerSDK.Container) (*cid.ID, error) { +func (m mock) Put(_ *containerSDK.Container) (*cid.ID, error) { return new(cid.ID), nil } -func (m mock) Delete(witness containerCore.RemovalWitness) error { +func (m mock) Delete(_ containerCore.RemovalWitness) error { return nil } -func (m mock) PutEACL(table *eacl.Table) error { +func (m mock) PutEACL(_ *eacl.Table) error { return nil } -func (m mock) Get(id *cid.ID) (*containerSDK.Container, error) { +func (m mock) Get(_ *cid.ID) (*containerSDK.Container, error) { panic("implement me") } -func (m mock) GetEACL(id *cid.ID) (*eacl.Table, error) { +func (m mock) GetEACL(_ *cid.ID) (*eacl.Table, error) { panic("implement me") } -func (m mock) List(id *owner.ID) ([]*cid.ID, error) { +func (m mock) List(_ *owner.ID) ([]*cid.ID, error) { panic("implement me") } @@ -90,11 +90,11 @@ func TestInvalidToken(t *testing.T) { } } -func generateToken(ctx session.SessionTokenContext) *session.SessionToken { - body := new(session.SessionTokenBody) +func generateToken(ctx session.TokenContext) *session.Token { + body := new(session.TokenBody) body.SetContext(ctx) - tok := new(session.SessionToken) + tok := new(session.Token) tok.SetBody(body) return tok diff --git a/pkg/services/object/acl/acl.go b/pkg/services/object/acl/acl.go index de6ee4ccd..72aed16de 100644 --- a/pkg/services/object/acl/acl.go +++ b/pkg/services/object/acl/acl.go @@ -140,7 +140,7 @@ func New(opts ...Option) Service { } func (b Service) Get(request *object.GetRequest, stream objectSvc.GetObjectStream) error { - cid, err := getContainerIDFromRequest(request) + idCnr, err := getContainerIDFromRequest(request) if err != nil { return err } @@ -154,7 +154,7 @@ func (b Service) Get(request *object.GetRequest, stream objectSvc.GetObjectStrea src: request, } - reqInfo, err := b.findRequestInfo(req, cid, eaclSDK.OperationGet) + reqInfo, err := b.findRequestInfo(req, idCnr, eaclSDK.OperationGet) if err != nil { return err } @@ -188,7 +188,7 @@ func (b Service) Put(ctx context.Context) (objectSvc.PutObjectStream, error) { func (b Service) Head( ctx context.Context, request *object.HeadRequest) (*object.HeadResponse, error) { - cid, err := getContainerIDFromRequest(request) + idCnr, err := getContainerIDFromRequest(request) if err != nil { return nil, err } @@ -202,7 +202,7 @@ func (b Service) Head( src: request, } - reqInfo, err := b.findRequestInfo(req, cid, eaclSDK.OperationHead) + reqInfo, err := b.findRequestInfo(req, idCnr, eaclSDK.OperationHead) if err != nil { return nil, err } @@ -264,7 +264,7 @@ func (b Service) Search(request *object.SearchRequest, stream objectSvc.SearchSt func (b Service) Delete( ctx context.Context, request *object.DeleteRequest) (*object.DeleteResponse, error) { - cid, err := getContainerIDFromRequest(request) + idCnr, err := getContainerIDFromRequest(request) if err != nil { return nil, err } @@ -278,7 +278,7 @@ func (b Service) Delete( src: request, } - reqInfo, err := b.findRequestInfo(req, cid, eaclSDK.OperationDelete) + reqInfo, err := b.findRequestInfo(req, idCnr, eaclSDK.OperationDelete) if err != nil { return nil, err } @@ -296,7 +296,7 @@ func (b Service) Delete( } func (b Service) GetRange(request *object.GetRangeRequest, stream objectSvc.GetObjectRangeStream) error { - cid, err := getContainerIDFromRequest(request) + idCnr, err := getContainerIDFromRequest(request) if err != nil { return err } @@ -310,7 +310,7 @@ func (b Service) GetRange(request *object.GetRangeRequest, stream objectSvc.GetO src: request, } - reqInfo, err := b.findRequestInfo(req, cid, eaclSDK.OperationRange) + reqInfo, err := b.findRequestInfo(req, idCnr, eaclSDK.OperationRange) if err != nil { return err } @@ -334,7 +334,7 @@ func (b Service) GetRange(request *object.GetRangeRequest, stream objectSvc.GetO func (b Service) GetRangeHash( ctx context.Context, request *object.GetRangeHashRequest) (*object.GetRangeHashResponse, error) { - cid, err := getContainerIDFromRequest(request) + idCnr, err := getContainerIDFromRequest(request) if err != nil { return nil, err } @@ -348,7 +348,7 @@ func (b Service) GetRangeHash( src: request, } - reqInfo, err := b.findRequestInfo(req, cid, eaclSDK.OperationRangeHash) + reqInfo, err := b.findRequestInfo(req, idCnr, eaclSDK.OperationRangeHash) if err != nil { return nil, err } @@ -373,7 +373,7 @@ func (p putStreamBasicChecker) Send(request *object.PutRequest) error { part := body.GetObjectPart() if part, ok := part.(*object.PutObjectPartInit); ok { - cid, err := getContainerIDFromRequest(request) + idCnr, err := getContainerIDFromRequest(request) if err != nil { return err } @@ -392,7 +392,7 @@ func (p putStreamBasicChecker) Send(request *object.PutRequest) error { src: request, } - reqInfo, err := p.source.findRequestInfo(req, cid, eaclSDK.OperationPut) + reqInfo, err := p.source.findRequestInfo(req, idCnr, eaclSDK.OperationPut) if err != nil { return err } @@ -507,7 +507,7 @@ func getContainerIDFromRequest(req interface{}) (id *cid.ID, err error) { } } -func useObjectIDFromSession(req *requestInfo, token *session.SessionToken) { +func useObjectIDFromSession(req *requestInfo, token *session.Token) { if token == nil { return } @@ -795,7 +795,7 @@ func originalBearerToken(header *session.RequestMetaHeader) *bearer.BearerToken // originalSessionToken goes down to original request meta header and fetches // session token from there. -func originalSessionToken(header *session.RequestMetaHeader) *session.SessionToken { +func originalSessionToken(header *session.RequestMetaHeader) *session.Token { for header.GetOrigin() != nil { header = header.GetOrigin() } diff --git a/pkg/services/object/acl/acl_test.go b/pkg/services/object/acl/acl_test.go index a0dad6969..5ee3c528f 100644 --- a/pkg/services/object/acl/acl_test.go +++ b/pkg/services/object/acl/acl_test.go @@ -24,7 +24,7 @@ func TestOriginalTokens(t *testing.T) { } } -func testGenerateMetaHeader(depth uint32, b *acl.BearerToken, s *session.SessionToken) *session.RequestMetaHeader { +func testGenerateMetaHeader(depth uint32, b *acl.BearerToken, s *session.Token) *session.RequestMetaHeader { metaHeader := new(session.RequestMetaHeader) metaHeader.SetBearerToken(b) metaHeader.SetSessionToken(s) diff --git a/pkg/services/object/acl/classifier.go b/pkg/services/object/acl/classifier.go index db25f215e..c1acf0bc0 100644 --- a/pkg/services/object/acl/classifier.go +++ b/pkg/services/object/acl/classifier.go @@ -28,7 +28,7 @@ type ( metaWithToken struct { vheader *session.RequestVerificationHeader - token *session.SessionToken + token *session.Token bearer *bearer.BearerToken src interface{} } @@ -188,7 +188,7 @@ func lookupKeyInContainer( return false, nil } -func ownerFromToken(token *session.SessionToken) (*owner.ID, *keys.PublicKey, error) { +func ownerFromToken(token *session.Token) (*owner.ID, *keys.PublicKey, error) { // 1. First check signature of session token. signWrapper := v2signature.StableMarshalerWrapper{SM: token.GetBody()} if err := sigutil.VerifyDataWithSource(signWrapper, func() (key, sig []byte) { diff --git a/pkg/services/object/internal/client/client.go b/pkg/services/object/internal/client/client.go index 2688b8f07..672c46937 100644 --- a/pkg/services/object/internal/client/client.go +++ b/pkg/services/object/internal/client/client.go @@ -3,9 +3,10 @@ package internal import ( "context" "crypto/ecdsa" - "strconv" + "errors" + "fmt" + "io" - session2 "github.com/nspcc-dev/neofs-api-go/v2/session" coreclient "github.com/nspcc-dev/neofs-node/pkg/core/client" "github.com/nspcc-dev/neofs-sdk-go/client" apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status" @@ -22,7 +23,13 @@ type commonPrm struct { ctx context.Context - opts []client.CallOption + key *ecdsa.PrivateKey + + tokenSession *session.Token + + tokenBearer *token.BearerToken + + local bool } // SetClient sets base client for NeoFS API communication. @@ -43,35 +50,33 @@ func (x *commonPrm) SetContext(ctx context.Context) { // // Required parameter. func (x *commonPrm) SetPrivateKey(key *ecdsa.PrivateKey) { - x.opts = append(x.opts, client.WithKey(key)) + x.key = key } // SetSessionToken sets token of the session within which request should be sent. // // By default the request will be sent outside the session. func (x *commonPrm) SetSessionToken(tok *session.Token) { - x.opts = append(x.opts, client.WithSession(tok)) + x.tokenSession = tok } // SetBearerToken sets bearer token to be attached to the request. // // By default token is not attached to the request. func (x *commonPrm) SetBearerToken(tok *token.BearerToken) { - x.opts = append(x.opts, client.WithBearer(tok)) + x.tokenBearer = tok } // SetTTL sets time-to-live call option. func (x *commonPrm) SetTTL(ttl uint32) { - x.opts = append(x.opts, client.WithTTL(ttl)) + x.local = ttl < 2 } // SetXHeaders sets request X-Headers. // // By default X-Headers will not be attached to the request. -func (x *commonPrm) SetXHeaders(xhdrs []*session.XHeader) { - for _, xhdr := range xhdrs { - x.opts = append(x.opts, client.WithXHeader(xhdr)) - } +func (x *commonPrm) SetXHeaders(_ []*session.XHeader) { + // FIXME: (neofs-node#1194) not supported by client } type readPrmCommon struct { @@ -81,43 +86,45 @@ type readPrmCommon struct { // SetNetmapEpoch sets the epoch number to be used to locate the object. // // By default current epoch on the server will be used. -func (x *readPrmCommon) SetNetmapEpoch(epoch uint64) { - xNetmapEpoch := session.NewXHeader() - xNetmapEpoch.SetKey(session2.XHeaderNetmapEpoch) - xNetmapEpoch.SetValue(strconv.FormatUint(epoch, 10)) - - x.opts = append(x.opts, client.WithXHeader(xNetmapEpoch)) +func (x *readPrmCommon) SetNetmapEpoch(_ uint64) { + // FIXME: (neofs-node#1194) not supported by client } // GetObjectPrm groups parameters of GetObject operation. type GetObjectPrm struct { readPrmCommon - cliPrm client.GetObjectParams + cliPrm client.PrmObjectGet } // SetRawFlag sets raw flag of the request. // // By default request will not be raw. func (x *GetObjectPrm) SetRawFlag() { - x.cliPrm.WithRawFlag(true) + x.cliPrm.MarkRaw() } // SetAddress sets object address. // // Required parameter. func (x *GetObjectPrm) SetAddress(addr *addressSDK.Address) { - x.cliPrm.WithAddress(addr) + if id := addr.ContainerID(); id != nil { + x.cliPrm.FromContainer(*id) + } + + if id := addr.ObjectID(); id != nil { + x.cliPrm.ByID(*id) + } } // GetObjectRes groups resulting values of GetObject operation. type GetObjectRes struct { - cliRes *client.ObjectGetRes + obj *object.Object } // Object returns requested object. func (x GetObjectRes) Object() *object.Object { - return x.cliRes.Object() + return x.obj } // GetObject reads the object by address. @@ -128,47 +135,91 @@ func (x GetObjectRes) Object() *object.Object { // Returns: // error of type *object.SplitInfoError if object if raw flag is set and requested object is virtual; // object.ErrAlreadyRemoved error if requested object is marked to be removed. -func GetObject(prm GetObjectPrm) (res GetObjectRes, err error) { - res.cliRes, err = prm.cli.GetObject(prm.ctx, &prm.cliPrm, prm.opts...) +func GetObject(prm GetObjectPrm) (*GetObjectRes, error) { + if prm.tokenSession != nil { + prm.cliPrm.WithinSession(*prm.tokenSession) + } + + if prm.tokenBearer != nil { + prm.cliPrm.WithBearerToken(*prm.tokenBearer) + } + + if prm.local { + prm.cliPrm.MarkLocal() + } + + rdr, err := prm.cli.ObjectGetInit(prm.ctx, prm.cliPrm) if err == nil { - // pull out an error from status - err = apistatus.ErrFromStatus(res.cliRes.Status()) + return nil, fmt.Errorf("init object reading: %w", err) + } + + if prm.key != nil { + rdr.UseKey(*prm.key) + } + + var obj object.Object + + if !rdr.ReadHeader(&obj) { + res, err := rdr.Close() + if err == nil { + // pull out an error from status + err = apistatus.ErrFromStatus(res.Status()) + } + + return nil, fmt.Errorf("read object header: %w", err) + } + + buf := make([]byte, obj.PayloadSize()) + + _, err = rdr.Read(buf) + if err != nil && !errors.Is(err, io.EOF) { + return nil, fmt.Errorf("read payload: %w", err) } // FIXME: #1158 object.ErrAlreadyRemoved never returns - return + object.NewRawFrom(&obj).SetPayload(buf) + + return &GetObjectRes{ + obj: &obj, + }, nil } // HeadObjectPrm groups parameters of HeadObject operation. type HeadObjectPrm struct { readPrmCommon - cliPrm client.ObjectHeaderParams + cliPrm client.PrmObjectHead } // SetRawFlag sets raw flag of the request. // // By default request will not be raw. func (x *HeadObjectPrm) SetRawFlag() { - x.cliPrm.WithRawFlag(true) + x.cliPrm.MarkRaw() } // SetAddress sets object address. // // Required parameter. func (x *HeadObjectPrm) SetAddress(addr *addressSDK.Address) { - x.cliPrm.WithAddress(addr) + if id := addr.ContainerID(); id != nil { + x.cliPrm.FromContainer(*id) + } + + if id := addr.ObjectID(); id != nil { + x.cliPrm.ByID(*id) + } } -// GetObjectRes groups resulting values of GetObject operation. +// HeadObjectRes groups resulting values of GetObject operation. type HeadObjectRes struct { - cliRes *client.ObjectHeadRes + hdr *object.Object } // Header returns requested object header. func (x HeadObjectRes) Header() *object.Object { - return x.cliRes.Object() + return x.hdr } // HeadObject reads object header by address. @@ -179,54 +230,87 @@ func (x HeadObjectRes) Header() *object.Object { // Returns: // error of type *object.SplitInfoError if object if raw flag is set and requested object is virtual; // object.ErrAlreadyRemoved error if requested object is marked to be removed. -func HeadObject(prm HeadObjectPrm) (res HeadObjectRes, err error) { - res.cliRes, err = prm.cli.HeadObject(prm.ctx, &prm.cliPrm, prm.opts...) +func HeadObject(prm HeadObjectPrm) (*HeadObjectRes, error) { + if prm.local { + prm.cliPrm.MarkLocal() + } + + if prm.tokenSession != nil { + prm.cliPrm.WithinSession(*prm.tokenSession) + } + + if prm.tokenBearer != nil { + prm.cliPrm.WithBearerToken(*prm.tokenBearer) + } + + cliRes, err := prm.cli.ObjectHead(prm.ctx, prm.cliPrm) if err == nil { // pull out an error from status - err = apistatus.ErrFromStatus(res.cliRes.Status()) + err = apistatus.ErrFromStatus(cliRes.Status()) + } + + if err != nil { + return nil, fmt.Errorf("read object header from NeoFS: %w", err) } // FIXME: #1158 object.ErrAlreadyRemoved never returns - return + var hdr object.Object + + if !cliRes.ReadHeader(&hdr) { + return nil, errors.New("missing object header in the response") + } + + return &HeadObjectRes{ + hdr: &hdr, + }, nil } // PayloadRangePrm groups parameters of PayloadRange operation. type PayloadRangePrm struct { readPrmCommon - cliPrm client.RangeDataParams + ln uint64 + + cliPrm client.PrmObjectRange } // SetRawFlag sets raw flag of the request. // // By default request will not be raw. func (x *PayloadRangePrm) SetRawFlag() { - x.cliPrm.WithRaw(true) + x.cliPrm.MarkRaw() } // SetAddress sets object address. // // Required parameter. func (x *PayloadRangePrm) SetAddress(addr *addressSDK.Address) { - x.cliPrm.WithAddress(addr) + if id := addr.ContainerID(); id != nil { + x.cliPrm.FromContainer(*id) + } + + if id := addr.ObjectID(); id != nil { + x.cliPrm.ByID(*id) + } } // SetRange range of the object payload to be read. // // Required parameter. func (x *PayloadRangePrm) SetRange(rng *object.Range) { - x.cliPrm.WithRange(rng) + x.cliPrm.SetOffset(rng.GetOffset()) + x.ln = rng.GetLength() } // PayloadRangeRes groups resulting values of GetObject operation. type PayloadRangeRes struct { - cliRes *client.ObjectRangeRes + data []byte } // PayloadRange returns data of the requested payload range. func (x PayloadRangeRes) PayloadRange() []byte { - return x.cliRes.Data() + return x.data } // PayloadRange reads object payload range by address. @@ -237,40 +321,62 @@ func (x PayloadRangeRes) PayloadRange() []byte { // Returns: // error of type *object.SplitInfoError if object if raw flag is set and requested object is virtual; // object.ErrAlreadyRemoved error if requested object is marked to be removed. -func PayloadRange(prm PayloadRangePrm) (res PayloadRangeRes, err error) { - res.cliRes, err = prm.cli.ObjectPayloadRangeData(prm.ctx, &prm.cliPrm, prm.opts...) - if err == nil { - // pull out an error from status - err = apistatus.ErrFromStatus(res.cliRes.Status()) +func PayloadRange(prm PayloadRangePrm) (*PayloadRangeRes, error) { + if prm.local { + prm.cliPrm.MarkLocal() + } + + if prm.tokenSession != nil { + prm.cliPrm.WithinSession(*prm.tokenSession) + } + + if prm.tokenBearer != nil { + prm.cliPrm.WithBearerToken(*prm.tokenBearer) + } + + prm.cliPrm.SetLength(prm.ln) + + rdr, err := prm.cli.ObjectRangeInit(prm.ctx, prm.cliPrm) + if err != nil { + return nil, fmt.Errorf("init payload reading: %w", err) + } + + data := make([]byte, prm.ln) + + _, err = io.ReadFull(rdr, data) + if err != nil { + return nil, fmt.Errorf("read payload: %w", err) } // FIXME: #1158 object.ErrAlreadyRemoved never returns - return + return &PayloadRangeRes{ + data: data, + }, nil } // PutObjectPrm groups parameters of PutObject operation. type PutObjectPrm struct { commonPrm - cliPrm client.PutObjectParams + obj *object.Object } // SetObject sets object to be stored. // // Required parameter. func (x *PutObjectPrm) SetObject(obj *object.Object) { - x.cliPrm.WithObject(obj) + x.obj = obj } // PutObjectRes groups resulting values of PutObject operation. type PutObjectRes struct { - cliRes *client.ObjectPutRes + id *oidSDK.ID } // ID returns identifier of the stored object. func (x PutObjectRes) ID() *oidSDK.ID { - return x.cliRes.ID() + return x.id } // PutObject saves the object in local storage of the remote node. @@ -278,56 +384,137 @@ func (x PutObjectRes) ID() *oidSDK.ID { // Client, context and key must be set. // // Returns any error prevented the operation from completing correctly in error return. -func PutObject(prm PutObjectPrm) (res PutObjectRes, err error) { - res.cliRes, err = prm.cli.PutObject(prm.ctx, &prm.cliPrm, - append(prm.opts, client.WithTTL(1))..., - ) - if err == nil { - // pull out an error from status - err = apistatus.ErrFromStatus(res.cliRes.Status()) +func PutObject(prm PutObjectPrm) (*PutObjectRes, error) { + var prmCli client.PrmObjectPutInit + + w, err := prm.cli.ObjectPutInit(prm.ctx, prmCli) + if err != nil { + return nil, fmt.Errorf("init object writing on client: %w", err) } - return + w.MarkLocal() + + if prm.key != nil { + w.UseKey(*prm.key) + } + + if prm.tokenSession != nil { + w.WithinSession(*prm.tokenSession) + } + + if prm.tokenBearer != nil { + w.WithBearerToken(*prm.tokenBearer) + } + + if w.WriteHeader(*prm.obj) { + w.WritePayloadChunk(prm.obj.Payload()) + } + + res, err := w.Close() + if err == nil { + err = apistatus.ErrFromStatus(res.Status()) + } + + if err != nil { + return nil, fmt.Errorf("write object via client: %w", err) + } + + var id oidSDK.ID + if !res.ReadStoredObjectID(&id) { + return nil, errors.New("missing identifier in the response") + } + + return &PutObjectRes{ + id: &id, + }, nil } // SearchObjectsPrm groups parameters of SearchObjects operation. type SearchObjectsPrm struct { readPrmCommon - cliPrm client.SearchObjectParams + cliPrm client.PrmObjectSearch } // SetContainerID sets identifier of the container to search the objects. // // Required parameter. func (x *SearchObjectsPrm) SetContainerID(id *cid.ID) { - x.cliPrm.WithContainerID(id) + if id != nil { + x.cliPrm.InContainer(*id) + } } // SetFilters sets search filters. func (x *SearchObjectsPrm) SetFilters(fs object.SearchFilters) { - x.cliPrm.WithSearchFilters(fs) + x.cliPrm.SetFilters(fs) } // SearchObjectsRes groups resulting values of SearchObjects operation. type SearchObjectsRes struct { - cliRes *client.ObjectSearchRes + ids []*oidSDK.ID } // IDList returns identifiers of the matched objects. func (x SearchObjectsRes) IDList() []*oidSDK.ID { - return x.cliRes.IDList() + return x.ids } // SearchObjects selects objects from container which match the filters. // // Returns any error prevented the operation from completing correctly in error return. -func SearchObjects(prm SearchObjectsPrm) (res SearchObjectsRes, err error) { - res.cliRes, err = prm.cli.SearchObjects(prm.ctx, &prm.cliPrm, prm.opts...) - if err == nil { - // pull out an error from status - err = apistatus.ErrFromStatus(res.cliRes.Status()) +func SearchObjects(prm SearchObjectsPrm) (*SearchObjectsRes, error) { + if prm.local { + prm.cliPrm.MarkLocal() } - return + if prm.tokenSession != nil { + prm.cliPrm.WithinSession(*prm.tokenSession) + } + + if prm.tokenBearer != nil { + prm.cliPrm.WithBearerToken(*prm.tokenBearer) + } + + rdr, err := prm.cli.ObjectSearchInit(prm.ctx, prm.cliPrm) + if err != nil { + return nil, fmt.Errorf("init object searching in client: %w", err) + } + + if prm.key != nil { + rdr.UseKey(*prm.key) + } + + buf := make([]oidSDK.ID, 10) + var ids []*oidSDK.ID + var n int + var ok bool + + for { + n, ok = rdr.Read(buf) + if n > 0 { + for i := range buf[:n] { + v := buf[i] + ids = append(ids, &v) + } + } + + if !ok { + break + } + } + + res, err := rdr.Close() + if err == nil { + // pull out an error from status + err = apistatus.ErrFromStatus(res.Status()) + } + + if err != nil { + return nil, fmt.Errorf("read object list: %w", err) + } + + return &SearchObjectsRes{ + ids: ids, + }, nil } diff --git a/pkg/services/object_manager/storagegroup/collect.go b/pkg/services/object_manager/storagegroup/collect.go index 987798eeb..c2ad0bdb6 100644 --- a/pkg/services/object_manager/storagegroup/collect.go +++ b/pkg/services/object_manager/storagegroup/collect.go @@ -4,7 +4,6 @@ import ( "github.com/nspcc-dev/neofs-node/pkg/core/object" objutil "github.com/nspcc-dev/neofs-node/pkg/services/object/util" "github.com/nspcc-dev/neofs-sdk-go/checksum" - "github.com/nspcc-dev/neofs-sdk-go/client" cid "github.com/nspcc-dev/neofs-sdk-go/container/id" addressSDK "github.com/nspcc-dev/neofs-sdk-go/object/address" oidSDK "github.com/nspcc-dev/neofs-sdk-go/object/id" @@ -45,7 +44,7 @@ func CollectMembers(r objutil.HeadReceiver, cid *cid.ID, members []*oidSDK.ID) ( } cs := checksum.New() - tzHash := [client.TZSize]byte{} + tzHash := [64]byte{} copy(tzHash[:], sumHash) cs.SetTillichZemor(tzHash) diff --git a/pkg/services/object_manager/transformer/transformer.go b/pkg/services/object_manager/transformer/transformer.go index 315a42f73..00ce03961 100644 --- a/pkg/services/object_manager/transformer/transformer.go +++ b/pkg/services/object_manager/transformer/transformer.go @@ -39,8 +39,6 @@ type payloadChecksumHasher struct { checksumWriter func([]byte) } -const tzChecksumSize = 64 - // NewPayloadSizeLimiter returns ObjectTarget instance that restricts payload length // of the writing object and writes generated objects to targets from initializer. // @@ -148,11 +146,11 @@ func payloadHashersForObject(obj *object.RawObject) []*payloadChecksumHasher { { hasher: tz.New(), checksumWriter: func(cs []byte) { - if ln := len(cs); ln != tzChecksumSize { - panic(fmt.Sprintf("wrong checksum length: expected %d, has %d", ln, tzChecksumSize)) + if ln := len(cs); ln != tz.Size { + panic(fmt.Sprintf("wrong checksum length: expected %d, has %d", tz.Size, ln)) } - csTZ := [tzChecksumSize]byte{} + csTZ := [tz.Size]byte{} copy(csTZ[:], cs) checksum := checksum.New()