Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix/Child objects ACL #283

Merged
merged 4 commits into from
Feb 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@

### Added
- Numeric operands for object search queries (#265)
- Link object payload message (#263)
- Children sizes index to the link objects (#264)
- `LINK` split chain object type (#283)

### Changed
- Split ID is deprecated, the first child part is used instead and is known to the other parts (#283)

### Removed

Expand Down
30 changes: 30 additions & 0 deletions link/types.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
syntax = "proto3";

package neo.fs.v2.link;

option go_package = "github.com/nspcc-dev/neofs-api-go/v2/link/grpc;link";
option csharp_namespace = "Neo.FileStorage.API.Link";

import "refs/types.proto";

// Link is a payload of helper objects that contain the full list of the split
// chain objects' IDs. It is created only after the whole split chain is known
// and signed. This object is the only object that refers to every "child object"
// ID. It is NOT required for the original object assembling. It MUST have ALL
// the "child objects" IDs. Child objects MUST be ordered according to the
// original payload split, meaning the first payload part holder MUST be placed
// at the first place in the corresponding link object. Sizes MUST NOT be omitted
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if we wanna use it, we should be able to rely on it so there is MUST word. but then, we need to validate it and that is N head requests per link object PUT (N is num of objects in the chain)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

N head requests per link object

the problem is more specific - when assembling a split object, the list of descriptors of child objects can diverge with the stored children (not only the sizes btw, IDs too). The proposed validation is correct, but since we cannot guarantee it at the protocol level (this is a server implementation detail), the assembler - one who operates with split chain - must be prepared for the divergence in any case

protocol-level solution is to additionally store such metadata in the child object headers themselves (mentioned here). Then the link object will remain a pure stand-alone helper

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but since we cannot guarantee it at the protocol level (this is a server implementation detail)

what do you mean? nodes may not accept such link objects

must be prepared for the divergence in any case

there is no solution for #264 then. if you cannot trust the link object, you cannot be sure you are answering with a correct range

protocol-level solution is to additionally store such metadata in the child object headers themselves

should also be validated somehow. a node can get Nth object with some offset in it. what does it do? just believes it is true? searches for the previous ones and calculates their sizes?

@roman-khimov

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what do you mean? nodes may not accept such link objects

nodes may do whatever they want. They may accept linking objects w/o any validation

there is no solution for #264 then

i dont deny current solution, im just highligting that linking object can be unavailable or diverge with the split chain and any network node must be ready for this. In these cases, extra metadata in child objects may be a painkiller in some cases

what does it do?

its own implementation detail, each node can only control what to do itself and what it receives from other nodes


or maybe i misunderstood ur original comment. I dont see any problem with current structure and requirements. If u didnt mean that N head requests per link object PUT is a problem, then everything is ok to me

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nodes may do whatever they want

what does it do?

its own implementation detail, each node can only control what to do itself and what it receives from other nodes

i meant we need to find a balance to implement our "perfect" node that may exist in the world of "worst" nodes. if we may not rely on link object, i think the whole work is useless. but if we want to rely on it, we should validate it somehow

extra metadata in child objects may be a painkiller in some cases

here i want to say that ensuring child object data is ok is the same to ensuring similar info about the link object

If u didnt mean that N head requests per link object PUT is a problem, then everything is ok to me

yes. this and the consequences

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Validation should be implemented. Then I'd be optimistic wrt the link object contents. If it's not correct --- either you get an error (trying to access inexisting object) or reply with a wrong result, but it's not node's fault, garbage in -- garbage out.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Validation should be implemented.

Yes, sure. Just not sure about some link object replication: imagine you have a 1к parts object and receive a link to it for the first time: you need to do 1k head objects before you finish with this object. And you may be an attacker that sends 1k of such 1k-parts objects. 64mb data for a HEAD chaos in the NeoFS network.

// and MUST be a real object payload size in bytes.
message Link {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

really deserves a separate package? to me its overhead. object fits well, or at least in refs

Copy link
Member Author

@carpawell carpawell Jan 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

depends on the final solution about a separate object type. if it is a separate object type, i do not see any difference with tombstone, storagegroup and lock pkgs. but if you ask me, should it be like that, my answer is no, but we have what we have, do not want this object type to be different in any way

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

imo the previously used approach only complicates the structuring and, as a consequence, the knowledge of the protocol concepts. All these entities are inextricably linked with objects - they are about objects, they are in the payload of objects. Сurrent packetization is extremely redundant to me

we have what we have

obviously, but we are not burdened with creating a new package (). Keep the existing ones, and this message can be left in object to comply with the system architecture hierarchy

being a newbie, i'll see acl, container, object and other large sections of the system. And then link - specific detail elevated to the top level of the system with a non-descript name

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to comply with the system architecture hierarchy

so do i. type of the objects are placed where they always have been

the issue was created #284

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 for issue, link is still under the question

// Object ID with its object's payload size.
message MeasuredObject {
// Object ID.
neo.fs.v2.refs.ObjectID id = 1 [json_name = "id"];

// Object size in bytes.
uint32 size = 2 [json_name = "size"];
}

// Full list of the "child" object descriptors.
repeated MeasuredObject children = 1 [json_name = "children"];
}
17 changes: 17 additions & 0 deletions object/types.proto
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import "session/types.proto";
// * TOMBSTONE
// * STORAGE_GROUP
// * LOCK
// * LINK
enum ObjectType {
// Just a normal object
REGULAR = 0;
Expand All @@ -29,6 +30,9 @@ enum ObjectType {

// Object lock
LOCK = 3;

// Object that stores child object IDs for the split objects.
LINK = 4;
}

// Type of match expression
Expand Down Expand Up @@ -185,14 +189,21 @@ message Header {
// `header` field of the parent object. Used to reconstruct parent.
Header parent_header = 4 [json_name = "parentHeader"];

// DEPRECATED. Was used before creating the separate LINK object type. Keep
// child objects list in the LINK object's payload.
// List of identifiers of the objects generated by splitting current one.
repeated neo.fs.v2.refs.ObjectID children = 5 [json_name = "children"];

// DEPRECATED. Was used as an identifier of a split chain. Use the first
// part ID instead.
// 16 byte UUIDv4 used to identify the split object hierarchy parts. Must be
// unique inside container. All objects participating in the split must have
// the same `split_id` value.
bytes split_id = 6 [json_name = "splitID"];

// Identifier of the first part of the origin object. Known to all the split
// parts except the first one. Identifies the split and allows to differ them.
neo.fs.v2.refs.ObjectID first = 7 [json_name = "first"];
}
// Position of the object in the split hierarchy
Split split = 11 [json_name = "split"];
Expand Down Expand Up @@ -223,6 +234,8 @@ message Object {
// assemble the original object. With a linking object one can assemble an object
// right from the object parts.
message SplitInfo {
// DEPRECATED. Was used as an identifier of a split chain. Use the first
// part ID instead.
// 16 byte UUID used to identify the split object hierarchy parts.
bytes split_id = 1;

Expand All @@ -234,4 +247,8 @@ message SplitInfo {
// split header with the original object header and a sorted list of
// object parts.
neo.fs.v2.refs.ObjectID link = 3;

// Identifier of the first part of the origin object. Known to all the split
// parts except the first one. Identifies the split and allows to differ them.
neo.fs.v2.refs.ObjectID first_part = 4;
}
80 changes: 80 additions & 0 deletions proto-docs/link.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# Protocol Documentation
<a name="top"></a>

## Table of Contents

- [link/types.proto](#link/types.proto)

- Messages
- [Link](#neo.fs.v2.link.Link)
- [Link.MeasuredObject](#neo.fs.v2.link.Link.MeasuredObject)


- [Scalar Value Types](#scalar-value-types)



<a name="link/types.proto"></a>
<p align="right"><a href="#top">Top</a></p>

## link/types.proto


<!-- end services -->


<a name="neo.fs.v2.link.Link"></a>

### Message Link
Link is a payload of helper objects that contain the full list of the split
chain objects' IDs. It is created only after the whole split chain is known
and signed. This object is the only object that refers to every "child object"
ID. It is NOT required for the original object assembling. It MUST have ALL
the "child objects" IDs. Child objects MUST be ordered according to the
original payload split, meaning the first payload part holder MUST be placed
at the first place in the corresponding link object. Sizes MUST NOT be omitted
and MUST be a real object payload size in bytes.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| children | [Link.MeasuredObject](#neo.fs.v2.link.Link.MeasuredObject) | repeated | Full list of the "child" object descriptors. |


<a name="neo.fs.v2.link.Link.MeasuredObject"></a>

### Message Link.MeasuredObject
Object ID with its object's payload size.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| id | [neo.fs.v2.refs.ObjectID](#neo.fs.v2.refs.ObjectID) | | Object ID. |
| size | [uint32](#uint32) | | Object size in bytes. |

<!-- end messages -->

<!-- end enums -->



## Scalar Value Types

| .proto Type | Notes | C++ Type | Java Type | Python Type |
| ----------- | ----- | -------- | --------- | ----------- |
| <a name="double" /> double | | double | double | float |
| <a name="float" /> float | | float | float | float |
| <a name="int32" /> int32 | Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint32 instead. | int32 | int | int |
| <a name="int64" /> int64 | Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint64 instead. | int64 | long | int/long |
| <a name="uint32" /> uint32 | Uses variable-length encoding. | uint32 | int | int/long |
| <a name="uint64" /> uint64 | Uses variable-length encoding. | uint64 | long | int/long |
| <a name="sint32" /> sint32 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s. | int32 | int | int |
| <a name="sint64" /> sint64 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s. | int64 | long | int/long |
| <a name="fixed32" /> fixed32 | Always four bytes. More efficient than uint32 if values are often greater than 2^28. | uint32 | int | int |
| <a name="fixed64" /> fixed64 | Always eight bytes. More efficient than uint64 if values are often greater than 2^56. | uint64 | long | int/long |
| <a name="sfixed32" /> sfixed32 | Always four bytes. | int32 | int | int |
| <a name="sfixed64" /> sfixed64 | Always eight bytes. | int64 | long | int/long |
| <a name="bool" /> bool | | bool | boolean | boolean |
| <a name="string" /> string | A string must always contain UTF-8 encoded or 7-bit ASCII text. | string | String | str/unicode |
| <a name="bytes" /> bytes | May contain any arbitrary sequence of bytes. | string | ByteString | str |

10 changes: 7 additions & 3 deletions proto-docs/object.md
Original file line number Diff line number Diff line change
Expand Up @@ -954,8 +954,9 @@ must be within the same container.
| previous | [neo.fs.v2.refs.ObjectID](#neo.fs.v2.refs.ObjectID) | | Identifier of the left split neighbor |
| parent_signature | [neo.fs.v2.refs.Signature](#neo.fs.v2.refs.Signature) | | `signature` field of the parent object. Used to reconstruct parent. |
| parent_header | [Header](#neo.fs.v2.object.Header) | | `header` field of the parent object. Used to reconstruct parent. |
| children | [neo.fs.v2.refs.ObjectID](#neo.fs.v2.refs.ObjectID) | repeated | List of identifiers of the objects generated by splitting current one. |
| split_id | [bytes](#bytes) | | 16 byte UUIDv4 used to identify the split object hierarchy parts. Must be unique inside container. All objects participating in the split must have the same `split_id` value. |
| children | [neo.fs.v2.refs.ObjectID](#neo.fs.v2.refs.ObjectID) | repeated | DEPRECATED. Was used before creating the separate LINK object type. Keep child objects list in the LINK object's payload. List of identifiers of the objects generated by splitting current one. |
| split_id | [bytes](#bytes) | | DEPRECATED. Was used as an identifier of a split chain. Use the first part ID instead. 16 byte UUIDv4 used to identify the split object hierarchy parts. Must be unique inside container. All objects participating in the split must have the same `split_id` value. |
| first | [neo.fs.v2.refs.ObjectID](#neo.fs.v2.refs.ObjectID) | | Identifier of the first part of the origin object. Known to all the split parts except the first one. Identifies the split and allows to differ them. |


<a name="neo.fs.v2.object.Object"></a>
Expand Down Expand Up @@ -1005,9 +1006,10 @@ right from the object parts.

| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| split_id | [bytes](#bytes) | | 16 byte UUID used to identify the split object hierarchy parts. |
| split_id | [bytes](#bytes) | | DEPRECATED. Was used as an identifier of a split chain. Use the first part ID instead. 16 byte UUID used to identify the split object hierarchy parts. |
| last_part | [neo.fs.v2.refs.ObjectID](#neo.fs.v2.refs.ObjectID) | | The identifier of the last object in split hierarchy parts. It contains split header with the original object header. |
| link | [neo.fs.v2.refs.ObjectID](#neo.fs.v2.refs.ObjectID) | | The identifier of a linking object for split hierarchy parts. It contains split header with the original object header and a sorted list of object parts. |
| first_part | [neo.fs.v2.refs.ObjectID](#neo.fs.v2.refs.ObjectID) | | Identifier of the first part of the origin object. Known to all the split parts except the first one. Identifies the split and allows to differ them. |

<!-- end messages -->

Expand Down Expand Up @@ -1043,13 +1045,15 @@ String presentation of object type is the same as definition:
* TOMBSTONE
* STORAGE_GROUP
* LOCK
* LINK

| Name | Number | Description |
| ---- | ------ | ----------- |
| REGULAR | 0 | Just a normal object |
| TOMBSTONE | 1 | Used internally to identify deleted objects |
| STORAGE_GROUP | 2 | StorageGroup information |
| LOCK | 3 | Object lock |
| LINK | 4 | Object that stores child object IDs for the split objects. |


<!-- end enums -->
Expand Down
Loading