+
+## {{.Name}}
+{{.Description}}
+
+{{range .Services}}
+
+
+
+### Service "{{.FullName}}"
+{{.Description}}
+
+```
+{{range .Methods -}}
+ rpc {{.Name}}({{if .RequestStreaming}}stream {{end}}{{.RequestLongType}}) returns ({{if .ResponseStreaming}}stream {{end}}{{.ResponseLongType}});
+{{end}}
+```
+
+{{range .Methods -}}
+#### Method {{.Name}}
+
+{{.Description}}
+
+| Name | Input | Output |
+| ---- | ----- | ------ |
+| {{.Name}} | [{{.RequestLongType}}](#{{.RequestFullType}}) | [{{.ResponseLongType}}](#{{.ResponseFullType}}) |
+{{end}}{{end}}
+
+{{range .Messages}}
+
+
+### Message {{.LongName}}
+{{.Description}}
+
+{{if .HasFields}}
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+{{range .Fields -}}
+ | {{.Name}} | [{{.LongType}}](#{{.FullType}}) | {{.Label}} | {{nobr .Description}}{{if .DefaultValue}} Default: {{.DefaultValue}}{{end}} |
+{{end}}{{end}}
+{{end}}
+
+{{range .Enums}}
+
+
+### {{.LongName}}
+{{.Description}}
+
+| Name | Number | Description |
+| ---- | ------ | ----------- |
+{{range .Values -}}
+ | {{.Name}} | {{.Number}} | {{nobr .Description}} |
+{{end}}
+
+{{end}}
+
+{{end}}
+
+## Scalar Value Types
+
+| .proto Type | Notes | C++ Type | Java Type | Python Type |
+| ----------- | ----- | -------- | --------- | ----------- |
+{{range .Scalars -}}
+ | {{.ProtoType}} | {{.Notes}} | {{.CppType}} | {{.JavaType}} | {{.PythonType}} |
+{{end}}
diff --git a/.forgejo/workflows/dco.yaml b/.forgejo/workflows/dco.yaml
new file mode 100644
index 0000000..74fba6a
--- /dev/null
+++ b/.forgejo/workflows/dco.yaml
@@ -0,0 +1,19 @@
+name: DCO action
+on: [pull_request]
+
+jobs:
+ dco:
+ name: DCO
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v3
+ with:
+ fetch-depth: 0
+ - name: Setup Go
+ uses: actions/setup-go@v3
+ with:
+ go-version: '1.22'
+ - name: Run commit format checker
+ uses: https://git.frostfs.info/TrueCloudLab/dco-go@v3
+ with:
+ from: 'origin/${{ github.event.pull_request.base.ref }}'
diff --git a/.forgejo/workflows/fmt.yaml b/.forgejo/workflows/fmt.yaml
new file mode 100644
index 0000000..ddd50a7
--- /dev/null
+++ b/.forgejo/workflows/fmt.yaml
@@ -0,0 +1,17 @@
+name: Formatters
+on: [pull_request]
+
+jobs:
+ fmt:
+ name: Run fmt
+ runs-on: ubuntu-22.04
+ steps:
+ - uses: actions/checkout@v3
+ - name: Install deps
+ run: |
+ apt update
+ apt install -y clang-format
+ - name: Run fmt
+ run: |
+ make fmt
+ git diff --exit-code --quiet
diff --git a/.forgejo/workflows/pre-commit.yaml b/.forgejo/workflows/pre-commit.yaml
new file mode 100644
index 0000000..5bf97eb
--- /dev/null
+++ b/.forgejo/workflows/pre-commit.yaml
@@ -0,0 +1,18 @@
+name: Pre-commit hooks
+on: [pull_request]
+
+jobs:
+ pre-commit:
+ name: Pre-commit
+ env:
+ # Skip pre-commit hooks which are executed by other actions.
+ SKIP: make-fmt
+ runs-on: ubuntu-22.04
+ steps:
+ - uses: actions/checkout@v3
+ - name: Install deps
+ run: |
+ apt update
+ apt install -y pre-commit
+ - name: Run pre-commit
+ run: pre-commit run --all-files --hook-stage manual --color=always
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..485dee6
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+.idea
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
new file mode 100644
index 0000000..96f3e27
--- /dev/null
+++ b/.pre-commit-config.yaml
@@ -0,0 +1,24 @@
+repos:
+ - repo: https://github.com/pre-commit/pre-commit-hooks
+ rev: v4.6.0
+ hooks:
+ - id: check-added-large-files
+ - id: check-case-conflict
+ - id: check-executables-have-shebangs
+ - id: check-shebang-scripts-are-executable
+ - id: check-merge-conflict
+ - id: check-json
+ - id: check-xml
+ - id: check-yaml
+ - id: trailing-whitespace
+ args: [--markdown-linebreak-ext=md]
+ - id: end-of-file-fixer
+ exclude: ".svg$"
+
+ - repo: local
+ hooks:
+ - id: make-fmt
+ name: Run make fmt
+ entry: make fmt
+ language: system
+ pass_filenames: false
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..70ceb4a
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,498 @@
+# Changelog
+
+## [Unreleased]
+
+### Changed
+- Add `__SYSTEM__` attribute prefix (#12, #14)
+- Add `allow_impersonate` flag to bearer token (#18)
+
+### Removed
+- Reputation system (#22)
+- All `subnet` related fields and types (#25)
+- Storage group (#19)
+
+## [2.14.0] - 2022-09-23 - Anmado (안마도, 鞍馬島)
+
+### Added
+- `NetmapSnapsot` RPC to `netmap.NetmapService` (#228)
+- Well-known object attribute `FilePath` of `object.Header.Attribute` (#238)
+- `MAINTENANCE` value of `netmap.NodeInfo.State` enum (#237)
+- `NODE_UNDER_MAINTENANCE` code to `status.CommonFail` status section (#237)
+- Well-known node attribute `ExternalAddr` of `netmap.NodeInfo.Attribute` (#235)
+
+### Changed
+- Object session can be issued for a group of objects (#202)
+- System network parameters are explicitly declared in `NetworkConfig.Parameter` (#214)
+
+## [2.13.1] - 2022-08-01
+
+### Added
+- `EACL_NOT_FOUND` status code to the `container` section (#230)
+
+## [2.13.0] - 2022-06-21 - Yeonpyeongdo (연평도, 延坪島)
+
+### Added
+- Extended headers usage clarification (#204)
+- `OUT_OF_RANGE` status code to the `object` section (#208)
+- Disabling homomorphic hashing container setting (#217)
+- `LOCK` object behaviour clarification (#221)
+- Storage group members uniqueness constraint (#222)
+- WalletConnect signature scheme (#206)
+- `SIGNATURE_VERIFICATION_FAIL` status code to the `CommonFail` section (#225)
+
+### Deprecated
+- Storage group's expiration epoch field (#205)
+
+### Fixed
+- English language typos (#216)
+
+## [2.12.0] - 2022-02-22 - Heuksando (흑산도, 黑山島)
+
+Network magic, main status codes, object locks and notifications.
+
+### Added
+- `magic_number` field to `RequestMetaHeader` message (#82)
+- `WRONG_MAGIC_NUMBER` status code to `CommonFail` section (#82)
+- Well-known object attributes related to notifications `__NEOFS__TICK_EPOCH`
+ and `__NEOFS__TICK_TOPIC` (#193)
+- `ACCESS_DENIED` status code to `Object` section (#189)
+- `OBJECT_NOT_FOUND`, `CONTAINER_NOT_FOUND` and `OBJECT_ALREADY_REMOVED` status codes (#190)
+- `TOKEN_NOT_FOUND` and `TOKEN_EXPIRED` status codes to `Session` section (#191)
+- `LOCK` value of `object.Type` enum (#194)
+- `Lock` message with payload content of `LOCK` objects (#194)
+- `LOCKED` and `LOCK_NON_REGULAR_OBJECT` status codes to `Object` section (#194)
+- `scheme` field of type `SignatureScheme` to `Signature` message which determines
+ signature scheme (#55)
+- `SignatureRFC6979` message (#203)
+
+### Changed
+- Type of `signature` field in `ContainerService` requests to `SignatureRFC6979` (#203)
+
+## [2.11.0] - 2021-12-02 - Sinjido (신지도, 薪智島)
+
+Subnets and status responses.
+
+### Added
+- `Status` message structure (#150)
+- `status` field of `Status` type to `ResponseMetaHeader` message (#150)
+- `Subnet` message structure (#180)
+- `subnet` field of `Subnet` type to `PlacementPolicy` message (#179)
+
+### Changed
+- Subnet attributes in `NodeInfo` (#181)
+
+## [2.10.0] - 2021-10-14 - Udo (우도, 牛島)
+
+NNS integration, detailed network info and ACL rules for non-native services.
+
+### Added
+- ACL header type for services (#173)
+- Side chain block duration and NeoFS network config fields in `NetworkInfo`
+ message (#172)
+- Well-known container attributes for NNS integration (#177)
+
+## [2.9.1] - 2021-08-26
+
+### Changed
+- String presentation of object type enum.
+
+## [2.9.0] - 2021-08-16 - Anmyeondo (안면도, 安眠島)
+
+Support "common prefix" attribute match operation to simplify filesystem
+directory tree-like structures implementation in NeoFS protocol gateways.
+
+### Added
+- `COMMON_PREFIX` object attribute match type.
+- Storage node's attribute escape symbol description.
+
+## [2.8.0] - 2021-06-25 - Muuido (무의도, 舞衣島)
+
+Storage nodes with a group of network endpoints.
+
+### Changed
+
+- `address` field of `netmap.NodeInfo` message became `repeated`.
+
+## [2.7.0] - 2021-06-03 - Seongmodo (석모도, 席毛島)
+
+Container service sessions.
+
+### Added
+
+#### Session
+
+- `ContainerSessionContext` message.
+- `ContainerSessionContext` value of `context` oneof to `SessionToken.Body` message.
+
+#### Container
+
+##### Get
+
+- `session_token` field of type `session.SessionToken` to `GetResponse.Body` message.
+- `signature` field of type `refs.Signature` to `GetResponse.Body` message.
+
+##### GetExtendedACL
+
+- `session_token` field of type `session.SessionToken` to `GetExtendedACLResponse.Body` message.
+
+## [2.6.0] - 2021-05-07 - Daecheongdo (대청도, 大靑島)
+
+### Added
+
+- Reputation package with reputation service and corresponding type definitions.
+
+## [2.5.0] - 2021-03-19 - Jebudo (제부도, 濟扶島)
+
+This release contains changes and fixes for NEO3 testnet launch.
+
+### Added
+
+- Well-known object attribute `Content-Type`.
+
+### Changed
+
+- Namespace for C# has been changed to `Neo.FileStorage.API`.
+
+## [2.4.0] - 2021-02-26 - Ganghwado (강화도, 江華島)
+
+This release provides new RPC method to fetch network info from storage node.
+By getting current epoch value, application might set up correct expiration
+values in the objects.
+
+### Added
+
+- `netmap.NetworkInfo` request for getting node's network view.
+- Release instructions.
+
+### Changed
+
+- Clarified processing of empty search query in `object.Search` RPC.
+- Specified connection of tombstone expiration value with well-known
+ `__NEOFS__EXPIRATION_EPOCH` object attribute.
+
+## [2.3.0] - 2021-02-11 - Seonyudo (선유도, 仙遊島)
+
+This release brings support for nodes to exchange information about disk space
+used by each Container. This information will be used by Inner Ring nodes to
+calculate basic rewards and payments.
+
+Another significant change is UN/LOCODE support for node's attributes describing
+geographical location. From now on, most of the geographical attributes will be
+calculated automatically from a single `UN-LOCODE` attribute in a deterministic
+manner.
+
+### Added
+
+- Added `container.AnnounceUsedSpace` request for announcing disk space consumed
+ by container's objects on the node
+- Added `Continent` well-known node's attribute
+- Added `SubDivCode` well-known node's attribute
+- Added `Location` well-known node's attribute
+- Added `CounrtyCode` well-known node's attribute
+- Added `STRING_NOT_EQUAL` match type
+- Added `NOT_PRESENT` match type
+- Added JSON names for search request filter fields
+
+### Changed
+
+- `Locode` well-known node's attribute renamed to `UN-LOCODE`. It will be used
+ as a base for calculating most of the node's geographical attributes.
+- `Region` well-known node's attribute renamed to `SubDiv`
+
+### Removed
+
+- Removed `City` well-known node's attribute
+- Removed `Region` well-known node's attribute
+
+## [2.2.1] - 2021-01-15
+
+Define "well-known" X-headers
+
+### Added
+
+- Description of the format of "well-known" X-headers that affect system
+ behavior
+- X-header key to netmap epoch value
+- X-header key to netmap lookup depth value
+
+## [2.2.0] - 2020-12-30 - Yeouido (여의도, 汝矣島)
+
+Storage Groups based Data Audit updates
+
+### Added
+
+- `audit.DataAuditResult` message for recording audit result is added
+
+### Changed
+
+- `object.ShortHeader` now has `payload_hash` and `homomorphic_hash` fields
+
+## [2.1.1] - 2020-12-17
+
+Minor documentation fixes
+
+### Changed
+
+- Clarify JSON encoding for `ObjectID`, `ContainerID` and `OwnerID`
+- Clarify object field usage in some requests' eACL filters
+
+## [2.1.0] - 2020-12-11 - Modo (모도, 茅島)
+
+Object split and deletion improvements, documentation clarifications.
+
+### Added
+
+- `$Object:objectID` added to the list of available ACL and Search filters
+- `split_id` field added in `object.Object.header`
+- `$Object:split.splitID` search filter added
+- json_name notation added to `acl.EACLTable.Version` field
+- Adding `tombstone` field with newly created tombstone address field to
+ `object.DeleteResponse.Body`
+- `tombstone` package added
+- Tombstone payload definition added as `tombstone.Tombstone` message
+- `SplitInfo` message added to `object` package
+- `split_info` field added to `object.GetResponse.Body`
+- `split_info` field added to `object.HeadResponse.Body`
+- `split_info` field added to `object.GetRangeResponse.Body`
+- `raw` flag added in `object.GetRangeRequest.Body`
+
+### Changed
+
+- Clarified special search index descriptions
+- Clarified various types encoding formats descriptions
+
+### Removed
+
+- `$Object:CHILDFREE` filter description removed from well-known list
+- `$Object:LEAF` filter description removed from well-known list
+
+## [2.0.2] - 2020-10-27
+
+More "well-known" application attributes and documentation updates.
+
+### Added
+
+- Added "well-known" attributes list for extended ACL and object search filters
+- Added `Name`, `Timestamp` "well-known" application attributes for container
+- Added `Name`, `FileName`, `Timestamp` "well-known" application attributes for
+ object
+
+### Changed
+
+- `BearerToken.owner_id` field description changed
+- `Subnet` container attribute now has `__NEOFS__` prefix
+- Search and ACL filters now have `key` and `value` fields
+
+## [2.0.1] - 2020-10-19
+
+Documentation updates and JSON field names definition
+
+### Added
+
+- Added "well-known" attributes list for `netmap.NodeInfo`
+- Added "well-known" attributes list for objects
+- Added "well-known" attributes list for containers
+- JSON field names defined for most of data structures
+
+### Changed
+
+- Documentation updated for all packages fixing typos and minor inaccuracies
+- `acl.EACLRecord.Target.key_list` field renamed to `keys` for consistency
+
+### Removed
+
+- Human-written documentation will now be only in [NeoFS
+ Specification](https://github.com/nspcc-dev/neofs-spec)
+
+## [2.0.0] - 2020-09-07 - Jindo (진도, 珍島)
+
+Major API refactoring and simplification.
+
+### Added
+
+- `neo.fs.v2` prefix added to all package names
+- `container.Attributes` field added
+- `refs.ContainerID` added as a separate type
+- `refs.OwnerID` added as a separate type
+- Object Search query language defined in `object.SearchRequest.Body.filter`
+- `netmap` package added
+- `refs.Signature` defined as a separate type
+- `session.SessionToken` now has context information for each service
+- `refs.Version` defined as a separate type
+- `refs.Version` field added to all messages stored in SmartContracts
+- `refs.Checksum` defined as a separate type
+- `netmap.LocalNodeInfo` request added to get actual information from connected
+ peer
+
+### Changed
+
+- Extended ACL Table format changed
+- Protobuf definitions style changed to follow Google Style Guide
+- `System` and `Extended` Object headers are merged into on `object.Header` type
+- `object.UserHeader` renamed to `object.Header.Attribute`
+- `refs.ObjectID` is now a hash of the `object.Header` field, which contains
+ hash of payload
+- `StorageGroup` information moved to Object's payload
+- `netmap.NodeInfo.options` renamed to `netmap.NodeInfo.attributes` and it uses
+ a separate `netmap.NodeInfo.Attribute` type now.
+- `netmap.NodeInfo.Attribute` type now has a list of parents to construct a tree
+- Session Token renamed to `session.SessionToken` from `session.Token`
+- All Requests and Responses now have a common "body-meta-verify" structure
+- Meta and Verification headers now follow Matryoshka-style composition
+- SessionToken and BearerToken are now part of Meta header
+- Object placement policy format is simplified and defined in `netmap` package
+- `object.Head()` request now returns either short header or full header with a
+ signature
+
+### Removed
+
+- gogoproto is not used anymore
+- `decimal` package merged into `accounting` package
+- `query` package merged into `object` package
+- `storagegroup` package merged into `object` package
+- `bootstrap` package merged into `netmap` package
+- `state` package removed
+- `service` package removed. Merged with `session` package
+- `state` package removed. It will be implementation specific part of neofs-node
+- `SpreadMap` functionality removed from `netmap` package
+- Unixtime support removed from creation timestamps, leaving only Epoch number
+- `Link` type removed from Object headers
+- `Redirect` type support removed from Object headers
+- Withdrawal and Account Lock functionality removed from `accounting` service
+- Deposit functionality removed from `accounting` service
+- Settlement functionality removed from `accounting` service
+
+## [1.2.0] - 2020-07-08
+
+### Added
+
+- ```acl.EACLRecord```, ```acl.EACLTable``` messages for the table of extended
+ ACL rules.
+
+## [1.1.0] - 2020-06-18
+
+### Added
+
+- Extended ACL support in container service.
+- Bearer token support in the object service requests.
+- Extended headers for the requests in `service.RequestMetaHeader`
+
+## [1.0.0] - 2020-05-16
+
+Bump major release
+
+## [0.7.5] - 2020-05-15
+
+### Added
+
+- `OwnerKey` bytes field to `service.Token.TokenInfo` message.
+
+
+## [0.7.4] - 2020-05-08
+
+### Added
+
+- `service.TokenLifetime` message.
+
+### Changed
+
+- `service.Token` structure.
+- `session.Session.Create` RPC signature.
+- `session.CreateRequest` structure.
+- `session.CreateResponse` structure.
+
+## [0.7.3] - 2020-04-28
+
+### Changed
+
+- `CreationPoint` disabled stringer method.
+
+## [0.7.2] - 2020-04-28
+
+### Added
+
+- `Raw` boolean field to `service.RequestMetaHeader`.
+- `Token` message field to `service.RequestVerificationHeader`.
+
+### Replaced
+
+- `Token` message from `session` to `service` package.
+- `Signature` message with `Sign` one in `service` package.
+
+### Changed
+
+- `Token` message structure.
+
+### Removed
+
+- `Raw` field from `object.GetRequest` and `object.HeadRequest` messages.
+- `Token` field from `object.PutRequest.PutHeader` and `object.DeleteRequest`
+ messages.
+- `VerificationHeader` message.
+
+## [0.7.1] - 2020-04-20
+
+### Added
+
+- Method to change current node state. (`state.ChangeState`)
+
+## [0.7.0] - 2020-04-16
+
+### Added
+
+- A numerical field CopiesNumber into `object.PutRequest.PutHeader` message.
+
+## [0.6.1] - 2020-04-15
+
+### Added
+
+- State field into Bootstrap request.
+- Request.State enum: Unknown, Online, Offline.
+
+## [0.6.0] - 2020-04-02
+
+### Added
+
+- ACL package with enum of ACL targets.
+
+### Changed
+
+- Use `BasicACL` field in container structure and `container.Put` request.
+
+## [0.5.0] - 2020-04-01
+
+- Initial release
+
+[0.5.0]: https://github.com/nspcc-dev/neofs-api/releases/tag/v0.5.0
+[0.6.0]: https://github.com/nspcc-dev/neofs-api/compare/v0.5.0...v0.6.0
+[0.6.1]: https://github.com/nspcc-dev/neofs-api/compare/v0.6.0...v0.6.1
+[0.7.0]: https://github.com/nspcc-dev/neofs-api/compare/v0.6.1...v0.7.0
+[0.7.1]: https://github.com/nspcc-dev/neofs-api/compare/v0.7.0...v0.7.1
+[0.7.2]: https://github.com/nspcc-dev/neofs-api/compare/v0.7.1...v0.7.2
+[0.7.3]: https://github.com/nspcc-dev/neofs-api/compare/v0.7.2...v0.7.3
+[0.7.4]: https://github.com/nspcc-dev/neofs-api/compare/v0.7.3...v0.7.4
+[0.7.5]: https://github.com/nspcc-dev/neofs-api/compare/v0.7.4...v0.7.5
+[1.0.0]: https://github.com/nspcc-dev/neofs-api/compare/v0.7.5...v1.0.0
+[1.1.0]: https://github.com/nspcc-dev/neofs-api/compare/v1.0.0...v1.1.0
+[1.2.0]: https://github.com/nspcc-dev/neofs-api/compare/v1.1.0...v1.2.0
+[2.0.0]: https://github.com/nspcc-dev/neofs-api/compare/v1.2.0...v2.0.0
+[2.0.1]: https://github.com/nspcc-dev/neofs-api/compare/v2.0.0...v2.0.1
+[2.0.2]: https://github.com/nspcc-dev/neofs-api/compare/v2.0.1...v2.0.2
+[2.1.0]: https://github.com/nspcc-dev/neofs-api/compare/v2.0.2...v2.1.0
+[2.1.1]: https://github.com/nspcc-dev/neofs-api/compare/v2.1.0...v2.1.1
+[2.2.0]: https://github.com/nspcc-dev/neofs-api/compare/v2.1.1...v2.2.0
+[2.2.1]: https://github.com/nspcc-dev/neofs-api/compare/v2.2.0...v2.2.1
+[2.3.0]: https://github.com/nspcc-dev/neofs-api/compare/v2.2.1...v2.3.0
+[2.4.0]: https://github.com/nspcc-dev/neofs-api/compare/v2.3.0...v2.4.0
+[2.5.0]: https://github.com/nspcc-dev/neofs-api/compare/v2.4.0...v2.5.0
+[2.6.0]: https://github.com/nspcc-dev/neofs-api/compare/v2.5.0...v2.6.0
+[2.7.0]: https://github.com/nspcc-dev/neofs-api/compare/v2.6.0...v2.7.0
+[2.8.0]: https://github.com/nspcc-dev/neofs-api/compare/v2.7.0...v2.8.0
+[2.9.0]: https://github.com/nspcc-dev/neofs-api/compare/v2.8.0...v2.9.0
+[2.9.1]: https://github.com/nspcc-dev/neofs-api/compare/v2.9.0...v2.9.1
+[2.10.0]: https://github.com/nspcc-dev/neofs-api/compare/v2.9.1...v2.10.0
+[2.11.0]: https://github.com/nspcc-dev/neofs-api/compare/v2.10.0...v2.11.0
+[2.12.0]: https://github.com/nspcc-dev/neofs-api/compare/v2.11.0...v2.12.0
+[2.13.0]: https://github.com/nspcc-dev/neofs-api/compare/v2.12.0...v2.13.0
+[2.13.1]: https://github.com/nspcc-dev/neofs-api/compare/v2.13.0...v2.13.1
+[2.14.0]: https://github.com/nspcc-dev/neofs-api/compare/v2.13.1...v2.14.0
diff --git a/CODEOWNERS b/CODEOWNERS
new file mode 100644
index 0000000..854e751
--- /dev/null
+++ b/CODEOWNERS
@@ -0,0 +1,3 @@
+.* @alexvanin @realloc @fyrchik @a.bogatyrev @TrueCloudLab/storage-sdk-developers
+.forgejo/.* @potyarkin
+Makefile @potyarkin
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..1ca386f
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,153 @@
+# Contribution guide
+
+First, thank you for contributing! We love and encourage pull requests from
+everyone. Please follow the guidelines:
+
+- Check the open [issues](https://git.frostfs.info/TrueCloudLab/frostfs-api/issues) and
+ [pull requests](https://git.frostfs.info/TrueCloudLab/frostfs-api/pulls) for existing
+ discussions.
+
+- Open an issue first, to discuss a new feature or enhancement.
+
+- Open a pull request, and reference the relevant issue(s).
+
+- Make sure your commits are logically separated and have good comments
+ explaining the details of your change.
+
+- After receiving feedback, amend your commits or add new ones as
+ appropriate.
+
+- **Have fun!**
+
+## Development Workflow
+
+Start by forking the `frostfs-api` repository, make changes in a branch and then
+send a pull request. We encourage pull requests to discuss code changes. Here
+are the steps in details:
+
+### Set up your repository
+
+Fork [FrostFS upstream](https://git.frostfs.info/TrueCloudLab/frostfs-api/fork) source
+repository to your own personal repository. Copy the URL of your fork (you will
+need it for the `git clone` command below).
+
+```sh
+$ git clone https://git.frostfs.info/TrueCloudLab/frostfs-api
+```
+
+### Set up git remote as ``upstream``
+```sh
+$ cd frostfs-api
+$ git remote add upstream https://git.frostfs.info/TrueCloudLab/frostfs-api
+$ git fetch upstream
+$ git merge upstream/master
+...
+```
+
+### Create your feature branch
+Before making code changes, make sure you have created a separate branch for these
+changes. Maybe you will find it convenient to name branch in the
+`/-` format.
+
+```sh
+$ git checkout -b feature/123-something_awesome
+```
+
+### Test your changes
+After your code changes, make sure
+
+- To add test cases for the new code.
+- To run `make lint`
+- To squash your commits into a single commit or a series of logically separated
+ commits run `git rebase -i`. It's okay to force update your pull request.
+
+### Commit changes
+After verification, commit your changes. This is a [great
+post](https://chris.beams.io/posts/git-commit/) on how to write useful commit
+messages. Try following this template:
+
+```
+[#Issue] Summary
+
+Description
+
+
+
+
+```
+
+```sh
+$ git commit -am '[#123] Add some feature'
+```
+
+### Push to the branch
+Push your locally committed changes to the remote origin (your fork)
+```
+$ git push origin feature/123-something_awesome
+```
+
+### Create a Pull Request
+Pull requests can be created via git.frostfs.info. Refer to [this
+document](https://help.github.com/articles/creating-a-pull-request/) for
+detailed steps on how to create a pull request. After a Pull Request gets peer
+reviewed and approved, it will be merged.
+
+## DCO Sign off
+
+All authors to the project retain copyright to their work. However, to ensure
+that they are only submitting work that they have rights to, we are requiring
+everyone to acknowledge this by signing their work.
+
+Any copyright notices in this repository should specify the authors as "the
+contributors".
+
+To sign your work, just add a line like this at the end of your commit message:
+
+```
+Signed-off-by: Samii Sakisaka
+```
+
+This can be done easily with the `--signoff` option to `git commit`.
+
+By doing this, you state that you can certify the following (from [The Developer
+Certificate of Origin](https://developercertificate.org/)):
+
+```
+Developer Certificate of Origin
+Version 1.1
+
+Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
+1 Letterman Drive
+Suite D4700
+San Francisco, CA, 94129
+
+Everyone is permitted to copy and distribute verbatim copies of this
+license document, but changing it is not allowed.
+
+
+Developer's Certificate of Origin 1.1
+
+By making a contribution to this project, I certify that:
+
+(a) The contribution was created in whole or in part by me and I
+ have the right to submit it under the open source license
+ indicated in the file; or
+
+(b) The contribution is based upon previous work that, to the best
+ of my knowledge, is covered under an appropriate open source
+ license and I have the right under that license to submit that
+ work with modifications, whether created in whole or in part
+ by me, under the same open source license (unless I am
+ permitted to submit under a different license), as indicated
+ in the file; or
+
+(c) The contribution was provided directly to me by some other
+ person who certified (a), (b) or (c) and I have not modified
+ it.
+
+(d) I understand and agree that this project and the contribution
+ are public and that a record of the contribution (including all
+ personal information I submit with it, including my sign-off) is
+ maintained indefinitely and may be redistributed consistent with
+ this project or the open source license(s) involved.
+```
diff --git a/CREDITS.md b/CREDITS.md
new file mode 100644
index 0000000..de610a8
--- /dev/null
+++ b/CREDITS.md
@@ -0,0 +1,30 @@
+# Credits
+
+FrostFS continues the development of NeoFS.
+
+Initial NeoFS research and development (2018-2020) was done by
+[NeoSPCC](https://nspcc.ru) team.
+
+In alphabetical order:
+
+- Alexey Vanin
+- Anastasia Prasolova
+- Anatoly Bogatyrev
+- Evgeny Kulikov
+- Evgeny Stratonikov
+- Leonard Liubich
+- Sergei Liubich
+- Stanislav Bogatyrev
+
+# Contributors
+
+In chronological order:
+- Pavel Korotkov
+- Pavel Karpy
+
+# Special Thanks
+
+For product development support:
+
+- Fabian Wahle
+- Neo Global Development
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..261eeb9
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/Makefile b/Makefile
new file mode 100755
index 0000000..6173f5c
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,35 @@
+#!/usr/bin/make -f
+SHELL=bash
+
+include help.mk
+
+.PHONY: doc fmt pre-commit unpre-commit pre-commit-run
+
+# Regenerate documentation for proto files:
+doc:
+ @for f in `find . -type f -name '*.proto' -exec dirname {} \; | sort -u `; do \
+ echo "⇒ Documentation for $$(basename $$f)"; \
+ protoc \
+ --doc_opt=.forgejo/markdown.tmpl,$${f}.md \
+ --proto_path=.:/usr/local/include \
+ --doc_out=proto-docs/ $${f}/*.proto; \
+ done
+
+# Run clang-format
+fmt:
+ @for f in `ls **/*.proto`; do \
+ echo "⇒ Formatting $$f"; \
+ clang-format -i $$f; \
+ done
+
+# Activate pre-commit hooks
+pre-commit:
+ pre-commit install --hook-type pre-commit
+
+# Deactivate pre-commit hooks
+unpre-commit:
+ pre-commit uninstall --hook-type pre-commit
+
+# Run pre-commit hooks
+pre-commit-run:
+ @pre-commit run --all-files --hook-stage manual
diff --git a/README.md b/README.md
index 7463f9e..5447b7b 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,36 @@
-# WIP area: this repo is just a fork!
+
+
+
+
+ FrostFS API language-agnostic protocol definitions
+
-Useful things may be published only in [other branches](../../../branches)
+---
+
+
+## Overview
+
+FrostFS-API repository is the basis for language-specific libraries, e.g.:
+
+- [frostfs-api-go](https://git.frostfs.info/TrueCloudLab/frostfs-api-go)
+
+Those libraries contain compiled protocol buffers definitions, wrapped with
+language-specific code. Use them to integrate applications with FrostFS.
+
+This repository contains:
+
+- protocol buffers packages
+- [auto-generated docs](proto-docs) for protocol buffers
+
+## Contributing
+
+Feel free to contribute to this project after reading the [contributing
+guidelines](CONTRIBUTING.md).
+
+Before you start working on a certain topic, first create a new issue
+describing the feature/topic you are going to implement.
+
+## License
+
+This project is licensed under the Apache 2.0 License -
+see the [LICENSE](LICENSE) file for details
diff --git a/accounting/service.proto b/accounting/service.proto
new file mode 100644
index 0000000..cd49b4d
--- /dev/null
+++ b/accounting/service.proto
@@ -0,0 +1,71 @@
+edition = "2023";
+
+package neo.fs.v2.accounting;
+
+option go_package = "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/accounting/grpc;accounting";
+option csharp_namespace = "Neo.FileStorage.API.Accounting";
+
+import "accounting/types.proto";
+import "refs/types.proto";
+import "session/types.proto";
+
+// Accounting service provides methods for interaction with FrostFS sidechain
+// via other FrostFS nodes to get information about the account balance. Deposit
+// and Withdraw operations can't be implemented here, as they require Mainnet
+// FrostFS smart contract invocation. Transfer operations between internal
+// FrostFS accounts are possible if both use the same token type.
+service AccountingService {
+ // Returns the amount of funds in GAS token for the requested FrostFS account.
+ //
+ // Statuses:
+ // - **OK** (0, SECTION_SUCCESS):
+ // balance has been successfully read;
+ // - Common failures (SECTION_FAILURE_COMMON).
+ rpc Balance(BalanceRequest) returns (BalanceResponse);
+}
+
+// BalanceRequest message
+message BalanceRequest {
+ // To indicate the account for which the balance is requested, its identifier
+ // is used. It can be any existing account in FrostFS sidechain `Balance`
+ // smart contract. If omitted, client implementation MUST set it to the
+ // request's signer `OwnerID`.
+ message Body {
+ // Valid user identifier in `OwnerID` format for which the balance is
+ // requested. Required field.
+ neo.fs.v2.refs.OwnerID owner_id = 1;
+ }
+ // Body of the balance request message.
+ Body body = 1;
+
+ // Carries request meta information. Header data is used only to regulate
+ // message transport and does not affect request execution.
+ neo.fs.v2.session.RequestMetaHeader meta_header = 2;
+
+ // Carries request verification information. This header is used to
+ // authenticate the nodes of the message route and check the correctness of
+ // transmission.
+ neo.fs.v2.session.RequestVerificationHeader verify_header = 3;
+}
+
+// BalanceResponse message
+message BalanceResponse {
+ // The amount of funds in GAS token for the `OwnerID`'s account requested.
+ // Balance is given in the `Decimal` format to avoid precision issues with
+ // rounding.
+ message Body {
+ // Amount of funds in GAS token for the requested account.
+ Decimal balance = 1;
+ }
+ // Body of the balance response message.
+ Body body = 1;
+
+ // Carries response meta information. Header data is used only to regulate
+ // message transport and does not affect request execution.
+ neo.fs.v2.session.ResponseMetaHeader meta_header = 2;
+
+ // Carries response verification information. This header is used to
+ // authenticate the nodes of the message route and check the correctness of
+ // transmission.
+ neo.fs.v2.session.ResponseVerificationHeader verify_header = 3;
+}
diff --git a/accounting/types.proto b/accounting/types.proto
new file mode 100644
index 0000000..7f5e89c
--- /dev/null
+++ b/accounting/types.proto
@@ -0,0 +1,22 @@
+edition = "2023";
+
+package neo.fs.v2.accounting;
+
+option go_package = "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/accounting/grpc;accounting";
+option csharp_namespace = "Neo.FileStorage.API.Accounting";
+
+// Standard floating point data type can't be used in FrostFS due to inexactness
+// of the result when doing lots of small number operations. To solve the lost
+// precision issue, special `Decimal` format is used for monetary computations.
+//
+// Please see [The General Decimal Arithmetic
+// Specification](http://speleotrove.com/decimal/) for detailed problem
+// description.
+message Decimal {
+ // Number in the smallest Token fractions.
+ int64 value = 1 [ json_name = "value" ];
+
+ // Precision value indicating how many smallest fractions can be in one
+ // integer.
+ uint32 precision = 2 [ json_name = "precision" ];
+}
diff --git a/acl/types.proto b/acl/types.proto
new file mode 100644
index 0000000..78f247a
--- /dev/null
+++ b/acl/types.proto
@@ -0,0 +1,249 @@
+edition = "2023";
+
+package neo.fs.v2.acl;
+
+option go_package = "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl/grpc;acl";
+option csharp_namespace = "Neo.FileStorage.API.Acl";
+
+import "refs/types.proto";
+import "ape/types.proto";
+
+// Target role of the access control rule in access control list.
+enum Role {
+ // Unspecified role, default value
+ ROLE_UNSPECIFIED = 0;
+
+ // User target rule is applied if sender is the owner of the container
+ USER = 1;
+
+ // System target rule is applied if sender is a storage node within the
+ // container or an inner ring node
+ SYSTEM = 2;
+
+ // Others target rule is applied if sender is neither a user nor a system
+ // target
+ OTHERS = 3;
+}
+
+// MatchType is an enumeration of match types.
+enum MatchType {
+ // Unspecified match type, default value.
+ MATCH_TYPE_UNSPECIFIED = 0;
+
+ // Return true if strings are equal
+ STRING_EQUAL = 1;
+
+ // Return true if strings are different
+ STRING_NOT_EQUAL = 2;
+}
+
+// Request's operation type to match if the rule is applicable to a particular
+// request.
+enum Operation {
+ // Unspecified operation, default value
+ OPERATION_UNSPECIFIED = 0;
+
+ // Get
+ GET = 1;
+
+ // Head
+ HEAD = 2;
+
+ // Put
+ PUT = 3;
+
+ // Delete
+ DELETE = 4;
+
+ // Search
+ SEARCH = 5;
+
+ // GetRange
+ GETRANGE = 6;
+
+ // GetRangeHash
+ GETRANGEHASH = 7;
+}
+
+// Rule execution result action. Either allows or denies access if the rule's
+// filters match.
+enum Action {
+ // Unspecified action, default value
+ ACTION_UNSPECIFIED = 0;
+
+ // Allow action
+ ALLOW = 1;
+
+ // Deny action
+ DENY = 2;
+}
+
+// Enumeration of possible sources of Headers to apply filters.
+enum HeaderType {
+ // Unspecified header, default value.
+ HEADER_UNSPECIFIED = 0;
+
+ // Filter request headers
+ REQUEST = 1;
+
+ // Filter object headers
+ OBJECT = 2;
+
+ // Filter service headers. These are not processed by FrostFS nodes and
+ // exist for service use only.
+ SERVICE = 3;
+}
+
+// Describes a single eACL rule.
+message EACLRecord {
+ // FrostFS request Verb to match
+ Operation operation = 1 [ json_name = "operation" ];
+
+ // Rule execution result. Either allows or denies access if filters match.
+ Action action = 2 [ json_name = "action" ];
+
+ // Filter to check particular properties of the request or the object.
+ //
+ // By default `key` field refers to the corresponding object's `Attribute`.
+ // Some Object's header fields can also be accessed by adding `$Object:`
+ // prefix to the name. Here is the list of fields available via this prefix:
+ //
+ // * $Object:version \
+ // version
+ // * $Object:objectID \
+ // object_id
+ // * $Object:containerID \
+ // container_id
+ // * $Object:ownerID \
+ // owner_id
+ // * $Object:creationEpoch \
+ // creation_epoch
+ // * $Object:payloadLength \
+ // payload_length
+ // * $Object:payloadHash \
+ // payload_hash
+ // * $Object:objectType \
+ // object_type
+ // * $Object:homomorphicHash \
+ // homomorphic_hash
+ //
+ // Please note, that if request or response does not have object's headers of
+ // full object (Range, RangeHash, Search, Delete), it will not be possible to
+ // filter by object header fields or user attributes. From the well-known list
+ // only `$Object:objectID` and `$Object:containerID` will be available, as
+ // it's possible to take that information from the requested address.
+ message Filter {
+ // Define if Object or Request header will be used
+ HeaderType header_type = 1 [ json_name = "headerType" ];
+
+ // Match operation type
+ MatchType match_type = 2 [ json_name = "matchType" ];
+
+ // Name of the Header to use
+ string key = 3 [ json_name = "key" ];
+
+ // Expected Header Value or pattern to match
+ string value = 4 [ json_name = "value" ];
+ }
+
+ // List of filters to match and see if rule is applicable
+ repeated Filter filters = 3 [ json_name = "filters" ];
+
+ // Target to apply ACL rule. Can be a subject's role class or a list of public
+ // keys to match.
+ message Target {
+ // Target subject's role class
+ Role role = 1 [ json_name = "role" ];
+
+ // List of public keys to identify target subject
+ repeated bytes keys = 2 [ json_name = "keys" ];
+ }
+ // List of target subjects to apply ACL rule to
+ repeated Target targets = 4 [ json_name = "targets" ];
+}
+
+// Extended ACL rules table. A list of ACL rules defined additionally to Basic
+// ACL. Extended ACL rules can be attached to a container and can be updated
+// or may be defined in `BearerToken` structure. Please see the corresponding
+// FrostFS Technical Specification section for detailed description.
+message EACLTable {
+ // eACL format version. Effectively, the version of API library used to create
+ // eACL Table.
+ neo.fs.v2.refs.Version version = 1 [ json_name = "version" ];
+
+ // Identifier of the container that should use given access control rules
+ neo.fs.v2.refs.ContainerID container_id = 2 [ json_name = "containerID" ];
+
+ // List of Extended ACL rules
+ repeated EACLRecord records = 3 [ json_name = "records" ];
+}
+
+// BearerToken allows to attach signed Extended ACL rules to the request in
+// `RequestMetaHeader`. If container's Basic ACL rules allow, the attached rule
+// set will be checked instead of one attached to the container itself. Just
+// like [JWT](https://jwt.io), it has a limited lifetime and scope, hence can be
+// used in the similar use cases, like providing authorisation to externally
+// authenticated party.
+//
+// BearerToken can be issued only by the container's owner and must be signed
+// using the key associated with the container's `OwnerID`.
+message BearerToken {
+ // Bearer Token body structure contains Extended ACL table issued by the
+ // container owner with additional information preventing token abuse.
+ message Body {
+ // Table of Extended ACL rules to use instead of the ones attached to the
+ // container. If it contains `container_id` field, bearer token is only
+ // valid for this specific container. Otherwise, any container of the same
+ // owner is allowed.
+ //
+ // Deprecated: eACL tables are no longer relevant - `APEOverrides` should be
+ // used instead.
+ EACLTable eacl_table = 1 [ json_name = "eaclTable" ];
+
+ // `OwnerID` defines to whom the token was issued. It must match the request
+ // originator's `OwnerID`. If empty, any token bearer will be accepted.
+ neo.fs.v2.refs.OwnerID owner_id = 2 [ json_name = "ownerID" ];
+
+ // Lifetime parameters of the token. Field names taken from
+ // [rfc7519](https://tools.ietf.org/html/rfc7519).
+ message TokenLifetime {
+ // Expiration Epoch
+ uint64 exp = 1 [ json_name = "exp" ];
+
+ // Not valid before Epoch
+ uint64 nbf = 2 [ json_name = "nbf" ];
+
+ // Issued at Epoch
+ uint64 iat = 3 [ json_name = "iat" ];
+ }
+ // Token expiration and valid time period parameters
+ TokenLifetime lifetime = 3 [ json_name = "lifetime" ];
+
+ // AllowImpersonate flag to consider token signer as request owner.
+ // If this field is true extended ACL table in token body isn't processed.
+ bool allow_impersonate = 4 [ json_name = "allowImpersonate" ];
+
+ // APEOverride is the list of APE chains defined for a target.
+ // These chains are meant to serve as overrides to the already defined (or
+ // even undefined) APE chains for the target (see contract `Policy`).
+ //
+ // The server-side processing of the bearer token with set APE overrides
+ // must verify if a client is permitted to override chains for the target,
+ // preventing unauthorized access through the APE mechanism.
+ message APEOverride {
+ // Target for which chains are applied.
+ frostfs.v2.ape.ChainTarget target = 1 [ json_name = "target" ];
+
+ // The list of APE chains.
+ repeated frostfs.v2.ape.Chain chains = 2 [ json_name = "chains" ];
+ }
+
+ // APE override for the target.
+ APEOverride ape_override = 5 [ json_name = "apeOverride" ];
+ }
+ // Bearer Token body
+ Body body = 1 [ json_name = "body" ];
+
+ // Signature of BearerToken body
+ neo.fs.v2.refs.Signature signature = 2 [ json_name = "signature" ];
+}
diff --git a/ape/types.proto b/ape/types.proto
new file mode 100644
index 0000000..2cbc5a9
--- /dev/null
+++ b/ape/types.proto
@@ -0,0 +1,33 @@
+edition = "2023";
+
+package frostfs.v2.ape;
+
+option go_package = "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/ape/grpc;ape";
+
+// TargetType is a type target to which a rule chain is defined.
+enum TargetType {
+ UNDEFINED = 0;
+
+ NAMESPACE = 1;
+
+ CONTAINER = 2;
+
+ USER = 3;
+
+ GROUP = 4;
+}
+
+// ChainTarget is an object to which a rule chain is defined.
+message ChainTarget {
+ TargetType type = 1;
+
+ string name = 2;
+}
+
+// Chain is a chain of rules defined for a specific target.
+message Chain {
+ oneof kind {
+ // Raw representation of a serizalized rule chain.
+ bytes raw = 1;
+ }
+}
diff --git a/apemanager/service.proto b/apemanager/service.proto
new file mode 100644
index 0000000..64c2565
--- /dev/null
+++ b/apemanager/service.proto
@@ -0,0 +1,171 @@
+edition = "2023";
+
+package frostfs.v2.apemanager;
+
+import "ape/types.proto";
+import "session/types.proto";
+
+option go_package = "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/apemanager/grpc;apemanager";
+
+// `APEManagerService` provides API to manage rule chains within sidechain's
+// `Policy` smart contract.
+service APEManagerService {
+ // Add a rule chain for a specific target to `Policy` smart contract.
+ //
+ // Statuses:
+ // - **OK** (0, SECTION_SUCCESS): \
+ // the chain has been successfully added;
+ // - Common failures (SECTION_FAILURE_COMMON);
+ // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \
+ // container (as target) not found;
+ // - **APE_MANAGER_ACCESS_DENIED** (5120, SECTION_APE_MANAGER): \
+ // the operation is denied by the service.
+ rpc AddChain(AddChainRequest) returns (AddChainResponse);
+
+ // Remove a rule chain for a specific target from `Policy` smart contract.
+ // RemoveChain is an idempotent operation: removal of non-existing rule chain
+ // also means success.
+ //
+ // Statuses:
+ // - **OK** (0, SECTION_SUCCESS): \
+ // the chain has been successfully removed;
+ // - Common failures (SECTION_FAILURE_COMMON);
+ // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \
+ // container (as target) not found;
+ // - **APE_MANAGER_ACCESS_DENIED** (5120, SECTION_APE_MANAGER): \
+ // the operation is denied by the service.
+ rpc RemoveChain(RemoveChainRequest) returns (RemoveChainResponse);
+
+ // List chains defined for a specific target from `Policy` smart contract.
+ //
+ // Statuses:
+ // - **OK** (0, SECTION_SUCCESS): \
+ // chains have been successfully listed;
+ // - Common failures (SECTION_FAILURE_COMMON);
+ // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \
+ // container (as target) not found;
+ // - **APE_MANAGER_ACCESS_DENIED** (5120, SECTION_APE_MANAGER): \
+ // the operation is denied by the service.
+ rpc ListChains(ListChainsRequest) returns (ListChainsResponse);
+}
+
+message AddChainRequest {
+ message Body {
+ // A target for which a rule chain is added.
+ frostfs.v2.ape.ChainTarget target = 1;
+
+ // The chain to set for the target.
+ frostfs.v2.ape.Chain chain = 2;
+ }
+
+ // The request's body.
+ Body body = 1;
+
+ // Carries request meta information. Header data is used only to regulate
+ // message transport and does not affect request execution.
+ neo.fs.v2.session.RequestMetaHeader meta_header = 2;
+
+ // Carries request verification information. This header is used to
+ // authenticate the nodes of the message route and check the correctness of
+ // transmission.
+ neo.fs.v2.session.RequestVerificationHeader verify_header = 3;
+}
+
+message AddChainResponse {
+ message Body {
+ // Chain ID assigned for the added rule chain.
+ // If chain ID is left empty in the request, then
+ // it will be generated.
+ bytes chain_id = 1;
+ }
+
+ // The response's body.
+ Body body = 1;
+
+ // Carries response meta information. Header data is used only to regulate
+ // message transport and does not affect request execution.
+ neo.fs.v2.session.ResponseMetaHeader meta_header = 2;
+
+ // Carries response verification information. This header is used to
+ // authenticate the nodes of the message route and check the correctness of
+ // transmission.
+ neo.fs.v2.session.ResponseVerificationHeader verify_header = 3;
+}
+
+message RemoveChainRequest {
+ message Body {
+ // Target for which a rule chain is removed.
+ frostfs.v2.ape.ChainTarget target = 1;
+
+ // Chain ID assigned for the rule chain.
+ bytes chain_id = 2;
+ }
+
+ // The request's body.
+ Body body = 1;
+
+ // Carries request meta information. Header data is used only to regulate
+ // message transport and does not affect request execution.
+ neo.fs.v2.session.RequestMetaHeader meta_header = 2;
+
+ // Carries request verification information. This header is used to
+ // authenticate the nodes of the message route and check the correctness of
+ // transmission.
+ neo.fs.v2.session.RequestVerificationHeader verify_header = 3;
+}
+
+message RemoveChainResponse {
+ // Since RemoveChain is an idempotent operation, then the only indicator that
+ // operation could not be performed is an error returning to a client.
+ message Body {}
+
+ // The response's body.
+ Body body = 1;
+
+ // Carries response meta information. Header data is used only to regulate
+ // message transport and does not affect request execution.
+ neo.fs.v2.session.ResponseMetaHeader meta_header = 2;
+
+ // Carries response verification information. This header is used to
+ // authenticate the nodes of the message route and check the correctness of
+ // transmission.
+ neo.fs.v2.session.ResponseVerificationHeader verify_header = 3;
+}
+
+message ListChainsRequest {
+ message Body {
+ // Target for which rule chains are listed.
+ frostfs.v2.ape.ChainTarget target = 1;
+ }
+
+ // The request's body.
+ Body body = 1;
+
+ // Carries request meta information. Header data is used only to regulate
+ // message transport and does not affect request execution.
+ neo.fs.v2.session.RequestMetaHeader meta_header = 2;
+
+ // Carries request verification information. This header is used to
+ // authenticate the nodes of the message route and check the correctness of
+ // transmission.
+ neo.fs.v2.session.RequestVerificationHeader verify_header = 3;
+}
+
+message ListChainsResponse {
+ message Body {
+ // The list of chains defined for the reqeusted target.
+ repeated frostfs.v2.ape.Chain chains = 1;
+ }
+
+ // The response's body.
+ Body body = 1;
+
+ // Carries response meta information. Header data is used only to regulate
+ // message transport and does not affect request execution.
+ neo.fs.v2.session.ResponseMetaHeader meta_header = 2;
+
+ // Carries response verification information. This header is used to
+ // authenticate the nodes of the message route and check the correctness of
+ // transmission.
+ neo.fs.v2.session.ResponseVerificationHeader verify_header = 3;
+}
diff --git a/container/service.proto b/container/service.proto
new file mode 100644
index 0000000..72b3789
--- /dev/null
+++ b/container/service.proto
@@ -0,0 +1,299 @@
+edition = "2023";
+
+package neo.fs.v2.container;
+
+option go_package = "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container/grpc;container";
+option csharp_namespace = "Neo.FileStorage.API.Container";
+
+import "container/types.proto";
+import "refs/types.proto";
+import "session/types.proto";
+
+// `ContainerService` provides API to interact with `Container` smart contract
+// in FrostFS sidechain via other FrostFS nodes. All of those actions can be
+// done equivalently by directly issuing transactions and RPC calls to sidechain
+// nodes.
+service ContainerService {
+ // `Put` invokes `Container` smart contract's `Put` method and returns
+ // response immediately. After a new block is issued in sidechain, request is
+ // verified by Inner Ring nodes. After one more block in sidechain, the
+ // container is added into smart contract storage.
+ //
+ // Statuses:
+ // - **OK** (0, SECTION_SUCCESS): \
+ // request to save the container has been sent to the sidechain;
+ // - Common failures (SECTION_FAILURE_COMMON);
+ // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \
+ // container create access denied.
+ rpc Put(PutRequest) returns (PutResponse);
+
+ // `Delete` invokes `Container` smart contract's `Delete` method and returns
+ // response immediately. After a new block is issued in sidechain, request is
+ // verified by Inner Ring nodes. After one more block in sidechain, the
+ // container is added into smart contract storage.
+ //
+ // Statuses:
+ // - **OK** (0, SECTION_SUCCESS): \
+ // request to remove the container has been sent to the sidechain;
+ // - Common failures (SECTION_FAILURE_COMMON);
+ // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \
+ // container delete access denied.
+ rpc Delete(DeleteRequest) returns (DeleteResponse);
+
+ // Returns container structure from `Container` smart contract storage.
+ //
+ // Statuses:
+ // - **OK** (0, SECTION_SUCCESS): \
+ // container has been successfully read;
+ // - Common failures (SECTION_FAILURE_COMMON);
+ // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \
+ // requested container not found;
+ // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \
+ // access to container is denied.
+ rpc Get(GetRequest) returns (GetResponse);
+
+ // Returns all owner's containers from `Container` smart contract storage.
+ //
+ // Statuses:
+ // - **OK** (0, SECTION_SUCCESS): \
+ // container list has been successfully read;
+ // - Common failures (SECTION_FAILURE_COMMON);
+ // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \
+ // container list access denied.
+ rpc List(ListRequest) returns (ListResponse);
+
+ // Returns all owner's containers from `Container` smart contract storage
+ // via stream.
+ //
+ // Statuses:
+ // - **OK** (0, SECTION_SUCCESS): \
+ // container list has been successfully read;
+ // - Common failures (SECTION_FAILURE_COMMON);
+ // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \
+ // container list access denied.
+ rpc ListStream(ListStreamRequest) returns (stream ListStreamResponse);
+}
+
+// New FrostFS Container creation request
+message PutRequest {
+ // Container creation request has container structure's signature as a
+ // separate field. It's not stored in sidechain, just verified on container
+ // creation by `Container` smart contract. `ContainerID` is a SHA256 hash of
+ // the stable-marshalled container strucutre, hence there is no need for
+ // additional signature checks.
+ message Body {
+ // Container structure to register in FrostFS
+ container.Container container = 1;
+
+ // Signature of a stable-marshalled container according to RFC-6979.
+ neo.fs.v2.refs.SignatureRFC6979 signature = 2;
+ }
+ // Body of container put request message.
+ Body body = 1;
+
+ // Carries request meta information. Header data is used only to regulate
+ // message transport and does not affect request execution.
+ neo.fs.v2.session.RequestMetaHeader meta_header = 2;
+
+ // Carries request verification information. This header is used to
+ // authenticate the nodes of the message route and check the correctness of
+ // transmission.
+ neo.fs.v2.session.RequestVerificationHeader verify_header = 3;
+}
+
+// New FrostFS Container creation response
+message PutResponse {
+ // Container put response body contains information about the newly registered
+ // container as seen by `Container` smart contract. `ContainerID` can be
+ // calculated beforehand from the container structure and compared to the one
+ // returned here to make sure everything has been done as expected.
+ message Body {
+ // Unique identifier of the newly created container
+ neo.fs.v2.refs.ContainerID container_id = 1;
+ }
+ // Body of container put response message.
+ Body body = 1;
+
+ // Carries response meta information. Header data is used only to regulate
+ // message transport and does not affect request execution.
+ neo.fs.v2.session.ResponseMetaHeader meta_header = 2;
+
+ // Carries response verification information. This header is used to
+ // authenticate the nodes of the message route and check the correctness of
+ // transmission.
+ neo.fs.v2.session.ResponseVerificationHeader verify_header = 3;
+}
+
+// Container removal request
+message DeleteRequest {
+ // Container removal request body has signed `ContainerID` as a proof of
+ // the container owner's intent. The signature will be verified by `Container`
+ // smart contract, so signing algorithm must be supported by NeoVM.
+ message Body {
+ // Identifier of the container to delete from FrostFS
+ neo.fs.v2.refs.ContainerID container_id = 1;
+
+ // `ContainerID` signed with the container owner's key according to
+ // RFC-6979.
+ neo.fs.v2.refs.SignatureRFC6979 signature = 2;
+ }
+ // Body of container delete request message.
+ Body body = 1;
+
+ // Carries request meta information. Header data is used only to regulate
+ // message transport and does not affect request execution.
+ neo.fs.v2.session.RequestMetaHeader meta_header = 2;
+
+ // Carries request verification information. This header is used to
+ // authenticate the nodes of the message route and check the correctness of
+ // transmission.
+ neo.fs.v2.session.RequestVerificationHeader verify_header = 3;
+}
+
+// `DeleteResponse` has an empty body because delete operation is asynchronous
+// and done via consensus in Inner Ring nodes.
+message DeleteResponse {
+ // `DeleteResponse` has an empty body because delete operation is asynchronous
+ // and done via consensus in Inner Ring nodes.
+ message Body {}
+ // Body of container delete response message.
+ Body body = 1;
+
+ // Carries response meta information. Header data is used only to regulate
+ // message transport and does not affect request execution.
+ neo.fs.v2.session.ResponseMetaHeader meta_header = 2;
+
+ // Carries response verification information. This header is used to
+ // authenticate the nodes of the message route and check the correctness of
+ // transmission.
+ neo.fs.v2.session.ResponseVerificationHeader verify_header = 3;
+}
+
+// Get container structure
+message GetRequest {
+ // Get container structure request body.
+ message Body {
+ // Identifier of the container to get
+ neo.fs.v2.refs.ContainerID container_id = 1;
+ }
+ // Body of container get request message.
+ Body body = 1;
+
+ // Carries request meta information. Header data is used only to regulate
+ // message transport and does not affect request execution.
+ neo.fs.v2.session.RequestMetaHeader meta_header = 2;
+
+ // Carries request verification information. This header is used to
+ // authenticate the nodes of the message route and check the correctness of
+ // transmission.
+ neo.fs.v2.session.RequestVerificationHeader verify_header = 3;
+}
+
+// Get container structure
+message GetResponse {
+ // Get container response body does not have container structure signature. It
+ // has been already verified upon container creation.
+ message Body {
+ // Requested container structure
+ Container container = 1;
+
+ // Signature of a stable-marshalled container according to RFC-6979.
+ neo.fs.v2.refs.SignatureRFC6979 signature = 2;
+
+ // Session token if the container has been created within the session
+ neo.fs.v2.session.SessionToken session_token = 3;
+ }
+ // Body of container get response message.
+ Body body = 1;
+
+ // Carries response meta information. Header data is used only to regulate
+ // message transport and does not affect request execution.
+ neo.fs.v2.session.ResponseMetaHeader meta_header = 2;
+
+ // Carries response verification information. This header is used to
+ // authenticate the nodes of the message route and check the correctness of
+ // transmission.
+ neo.fs.v2.session.ResponseVerificationHeader verify_header = 3;
+}
+
+// List containers
+message ListRequest {
+ // List containers request body.
+ message Body {
+ // Identifier of the container owner
+ neo.fs.v2.refs.OwnerID owner_id = 1;
+ }
+ // Body of list containers request message
+ Body body = 1;
+
+ // Carries request meta information. Header data is used only to regulate
+ // message transport and does not affect request execution.
+ neo.fs.v2.session.RequestMetaHeader meta_header = 2;
+
+ // Carries request verification information. This header is used to
+ // authenticate the nodes of the message route and check the correctness of
+ // transmission.
+ neo.fs.v2.session.RequestVerificationHeader verify_header = 3;
+}
+
+// List containers
+message ListResponse {
+ // List containers response body.
+ message Body {
+ // List of `ContainerID`s belonging to the requested `OwnerID`
+ repeated refs.ContainerID container_ids = 1;
+ }
+
+ // Body of list containers response message.
+ Body body = 1;
+
+ // Carries response meta information. Header data is used only to regulate
+ // message transport and does not affect request execution.
+ neo.fs.v2.session.ResponseMetaHeader meta_header = 2;
+
+ // Carries response verification information. This header is used to
+ // authenticate the nodes of the message route and check the correctness of
+ // transmission.
+ neo.fs.v2.session.ResponseVerificationHeader verify_header = 3;
+}
+
+// List containers stream
+message ListStreamRequest {
+ // List containers stream request body.
+ message Body {
+ // Identifier of the container owner.
+ neo.fs.v2.refs.OwnerID owner_id = 1;
+ }
+ // Body of list containers stream request message.
+ Body body = 1;
+
+ // Carries request meta information. Header data is used only to regulate
+ // message transport and does not affect request execution.
+ neo.fs.v2.session.RequestMetaHeader meta_header = 2;
+
+ // Carries request verification information. This header is used to
+ // authenticate the nodes of the message route and check the correctness of
+ // transmission.
+ neo.fs.v2.session.RequestVerificationHeader verify_header = 3;
+}
+
+// List containers stream
+message ListStreamResponse {
+ // List containers stream response body.
+ message Body {
+ // List of `ContainerID`s belonging to the requested `OwnerID`
+ repeated refs.ContainerID container_ids = 1;
+ }
+
+ // Body of list containers stream response message.
+ Body body = 1;
+
+ // Carries response meta information. Header data is used only to regulate
+ // message transport and does not affect request execution.
+ neo.fs.v2.session.ResponseMetaHeader meta_header = 2;
+
+ // Carries response verification information. This header is used to
+ // authenticate the nodes of the message route and check the correctness of
+ // transmission.
+ neo.fs.v2.session.ResponseVerificationHeader verify_header = 3;
+}
diff --git a/container/types.proto b/container/types.proto
new file mode 100644
index 0000000..d114205
--- /dev/null
+++ b/container/types.proto
@@ -0,0 +1,76 @@
+edition = "2023";
+
+package neo.fs.v2.container;
+
+option go_package = "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container/grpc;container";
+option csharp_namespace = "Neo.FileStorage.API.Container";
+
+import "netmap/types.proto";
+import "refs/types.proto";
+
+// Container is a structure that defines object placement behaviour. Objects can
+// be stored only within containers. They define placement rule, attributes and
+// access control information. An ID of a container is a 32 byte long SHA256
+// hash of stable-marshalled container message.
+message Container {
+ // Container format version. Effectively, the version of API library used to
+ // create the container.
+ neo.fs.v2.refs.Version version = 1 [ json_name = "version" ];
+
+ // Identifier of the container owner
+ neo.fs.v2.refs.OwnerID owner_id = 2 [ json_name = "ownerID" ];
+
+ // Nonce is a 16 byte UUIDv4, used to avoid collisions of `ContainerID`s
+ bytes nonce = 3 [ json_name = "nonce" ];
+
+ // `BasicACL` contains access control rules for the owner, system and others
+ // groups, as well as permission bits for `BearerToken` and `Extended ACL`
+ uint32 basic_acl = 4 [ json_name = "basicACL" ];
+
+ // `Attribute` is a user-defined Key-Value metadata pair attached to the
+ // container. Container attributes are immutable. They are set at the moment
+ // of container creation and can never be added or updated.
+ //
+ // Key name must be a container-unique valid UTF-8 string. Value can't be
+ // empty. Containers with duplicated attribute names or attributes with empty
+ // values will be considered invalid.
+ //
+ // There are some "well-known" attributes affecting system behaviour:
+ //
+ // * [ __SYSTEM__NAME ] \
+ // (`__NEOFS__NAME` is deprecated) \
+ // String of a human-friendly container name registered as a domain in
+ // NNS contract.
+ // * [ __SYSTEM__ZONE ] \
+ // (`__NEOFS__ZONE` is deprecated) \
+ // String of a zone for `__SYSTEM__NAME` (`__NEOFS__NAME` is deprecated).
+ // Used as a TLD of a domain name in NNS contract. If no zone is specified,
+ // use default zone: `container`.
+ // * [ __SYSTEM__DISABLE_HOMOMORPHIC_HASHING ] \
+ // (`__NEOFS__DISABLE_HOMOMORPHIC_HASHING` is deprecated) \
+ // Disables homomorphic hashing for the container if the value equals "true"
+ // string. Any other values are interpreted as missing attribute. Container
+ // could be accepted in a FrostFS network only if the global network hashing
+ // configuration value corresponds with that attribute's value. After
+ // container inclusion, network setting is ignored.
+ //
+ // And some well-known attributes used by applications only:
+ //
+ // * Name \
+ // Human-friendly name
+ // * Timestamp \
+ // User-defined local time of container creation in Unix Timestamp format
+ message Attribute {
+ // Attribute name key
+ string key = 1 [ json_name = "key" ];
+
+ // Attribute value
+ string value = 2 [ json_name = "value" ];
+ }
+ // Attributes represent immutable container's meta data
+ repeated Attribute attributes = 5 [ json_name = "attributes" ];
+
+ // Placement policy for the object inside the container
+ neo.fs.v2.netmap.PlacementPolicy placement_policy = 6
+ [ json_name = "placementPolicy" ];
+}
diff --git a/doc/release_instructions.md b/doc/release_instructions.md
new file mode 100644
index 0000000..d4fb9d4
--- /dev/null
+++ b/doc/release_instructions.md
@@ -0,0 +1,62 @@
+# Release instructions
+
+This documents outlines the frostfs-api release process and can be used as a TODO
+list for a new release.
+
+## Pre-release checks
+
+This should run successfully:
+* `make lint`
+
+## Pre-release actions
+
+This must be run:
+* `make doc`
+
+## Writing CHANGELOG
+
+Add an entry to the CHANGELOG.md following the style established there.
+
+Add a codename for releases with the new major version, version and release date in
+the heading. Write a paragraph describing the most significant changes done in
+this release. Then add sections with what has been added, changed and removed,
+describing each change briefly with a reference to issues, where
+available.
+
+## Release commit
+
+Release commit summary should follow the template:
+
+`Release v - (, )`, e.g.:
+
+```
+Release v2.9.0 - Anmyeondo (안면도, 安眠島)
+```
+
+## Tag the release
+
+Use `vX.Y.Z` tag following the semantic versioning standard. For pre-release
+versions use `vX.Y.Z-rc.N` scheme.
+
+## Push changes and release tag to repository
+
+This step should bypass the default PR mechanism to get a correct result (so
+that releasing requires admin privileges for the project), both the `master`
+branch update and tag must be pushed simultaneously like this:
+
+```
+$ git push origin master v2.7.0
+```
+
+## Make a proper release
+
+Edit an automatically-created release on git.frostfs.info
+
+Release title has to follow ` ( )` scheme for major releases and just `` for regular point
+releases.
+
+## Post-release actions
+
+* Close corresponding X.Y.Z milestone
+* Make announcements in Matrix and Discord channels
diff --git a/help.mk b/help.mk
new file mode 100644
index 0000000..a2ac989
--- /dev/null
+++ b/help.mk
@@ -0,0 +1,11 @@
+.PHONY: help
+
+# Show this help prompt
+help:
+ @echo ' Usage:'
+ @echo ''
+ @echo ' make '
+ @echo ''
+ @echo ' Targets:'
+ @echo ''
+ @awk '/^#/{ comment = substr($$0,3) } /^[a-zA-Z][a-zA-Z0-9_-]+:/{ print " ", $$1, comment; comment = "" }' $(MAKEFILE_LIST) | column -t -s ':' | grep -v 'IGNORE' | sort | uniq
diff --git a/lock/types.proto b/lock/types.proto
new file mode 100644
index 0000000..dc55276
--- /dev/null
+++ b/lock/types.proto
@@ -0,0 +1,19 @@
+edition = "2023";
+
+package neo.fs.v2.lock;
+
+option go_package = "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/lock/grpc;lock";
+option csharp_namespace = "Neo.FileStorage.API.Lock";
+
+import "refs/types.proto";
+
+// Lock objects protects a list of objects from being deleted. The lifetime of a
+// lock object is limited similar to regular objects in
+// `__SYSTEM__EXPIRATION_EPOCH` (`__NEOFS__EXPIRATION_EPOCH` is deprecated)
+// attribute. Lock object MUST have expiration epoch. It is impossible to delete
+// a lock object via ObjectService.Delete RPC call.
+message Lock {
+ // List of objects to lock. Must not be empty or carry empty IDs.
+ // All members must be of the `REGULAR` type.
+ repeated neo.fs.v2.refs.ObjectID members = 1 [ json_name = "members" ];
+}
diff --git a/netmap/service.proto b/netmap/service.proto
new file mode 100644
index 0000000..c21fb53
--- /dev/null
+++ b/netmap/service.proto
@@ -0,0 +1,162 @@
+edition = "2023";
+
+package neo.fs.v2.netmap;
+
+option go_package = "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap/grpc;netmap";
+option csharp_namespace = "Neo.FileStorage.API.Netmap";
+
+import "netmap/types.proto";
+import "refs/types.proto";
+import "session/types.proto";
+
+// `NetmapService` provides methods to work with `Network Map` and the
+// information required to build it. The resulting `Network Map` is stored in
+// sidechain `Netmap` smart contract, while related information can be obtained
+// from other FrostFS nodes.
+service NetmapService {
+ // Get NodeInfo structure from the particular node directly.
+ // Node information can be taken from `Netmap` smart contract. In some cases,
+ // though, one may want to get recent information directly or to talk to the
+ // node not yet present in the `Network Map` to find out what API version can
+ // be used for further communication. This can be also used to check if a node
+ // is up and running.
+ //
+ // Statuses:
+ // - **OK** (0, SECTION_SUCCESS):
+ // information about the server has been successfully read;
+ // - Common failures (SECTION_FAILURE_COMMON).
+ rpc LocalNodeInfo(LocalNodeInfoRequest) returns (LocalNodeInfoResponse);
+
+ // Read recent information about the FrostFS network.
+ //
+ // Statuses:
+ // - **OK** (0, SECTION_SUCCESS):
+ // information about the current network state has been successfully read;
+ // - Common failures (SECTION_FAILURE_COMMON).
+ rpc NetworkInfo(NetworkInfoRequest) returns (NetworkInfoResponse);
+
+ // Returns network map snapshot of the current FrostFS epoch.
+ //
+ // Statuses:
+ // - **OK** (0, SECTION_SUCCESS):
+ // information about the current network map has been successfully read;
+ // - Common failures (SECTION_FAILURE_COMMON).
+ rpc NetmapSnapshot(NetmapSnapshotRequest) returns (NetmapSnapshotResponse);
+}
+
+// Get NodeInfo structure directly from a particular node
+message LocalNodeInfoRequest {
+ // LocalNodeInfo request body is empty.
+ message Body {}
+ // Body of the LocalNodeInfo request message
+ Body body = 1;
+
+ // Carries request meta information. Header data is used only to regulate
+ // message transport and does not affect request execution.
+ neo.fs.v2.session.RequestMetaHeader meta_header = 2;
+
+ // Carries request verification information. This header is used to
+ // authenticate the nodes of the message route and check the correctness of
+ // transmission.
+ neo.fs.v2.session.RequestVerificationHeader verify_header = 3;
+}
+
+// Local Node Info, including API Version in use
+message LocalNodeInfoResponse {
+ // Local Node Info, including API Version in use.
+ message Body {
+ // Latest FrostFS API version in use
+ neo.fs.v2.refs.Version version = 1;
+
+ // NodeInfo structure with recent information from node itself
+ NodeInfo node_info = 2;
+ }
+ // Body of the balance response message.
+ Body body = 1;
+
+ // Carries response meta information. Header data is used only to regulate
+ // message transport and does not affect response execution.
+ neo.fs.v2.session.ResponseMetaHeader meta_header = 2;
+
+ // Carries response verification information. This header is used to
+ // authenticate the nodes of the message route and check the correctness of
+ // transmission.
+ neo.fs.v2.session.ResponseVerificationHeader verify_header = 3;
+}
+
+// Get NetworkInfo structure with the network view from a particular node.
+message NetworkInfoRequest {
+ // NetworkInfo request body is empty.
+ message Body {}
+ // Body of the NetworkInfo request message
+ Body body = 1;
+
+ // Carries request meta information. Header data is used only to regulate
+ // message transport and does not affect request execution.
+ neo.fs.v2.session.RequestMetaHeader meta_header = 2;
+
+ // Carries request verification information. This header is used to
+ // authenticate the nodes of the message route and check the correctness of
+ // transmission.
+ neo.fs.v2.session.RequestVerificationHeader verify_header = 3;
+}
+
+// Response with NetworkInfo structure including current epoch and
+// sidechain magic number.
+message NetworkInfoResponse {
+ // Information about the network.
+ message Body {
+ // NetworkInfo structure with recent information.
+ NetworkInfo network_info = 1;
+ }
+ // Body of the NetworkInfo response message.
+ Body body = 1;
+
+ // Carries response meta information. Header data is used only to regulate
+ // message transport and does not affect response execution.
+ neo.fs.v2.session.ResponseMetaHeader meta_header = 2;
+
+ // Carries response verification information. This header is used to
+ // authenticate the nodes of the message route and check the correctness of
+ // transmission.
+ neo.fs.v2.session.ResponseVerificationHeader verify_header = 3;
+}
+
+// Get netmap snapshot request
+message NetmapSnapshotRequest {
+ // Get netmap snapshot request body.
+ message Body {}
+
+ // Body of get netmap snapshot request message.
+ Body body = 1;
+
+ // Carries request meta information. Header data is used only to regulate
+ // message transport and does not affect request execution.
+ neo.fs.v2.session.RequestMetaHeader meta_header = 2;
+
+ // Carries request verification information. This header is used to
+ // authenticate the nodes of the message route and check the correctness of
+ // transmission.
+ neo.fs.v2.session.RequestVerificationHeader verify_header = 3;
+}
+
+// Response with current netmap snapshot
+message NetmapSnapshotResponse {
+ // Get netmap snapshot response body
+ message Body {
+ // Structure of the requested network map.
+ Netmap netmap = 1 [ json_name = "netmap" ];
+ }
+
+ // Body of get netmap snapshot response message.
+ Body body = 1;
+
+ // Carries response meta information. Header data is used only to regulate
+ // message transport and does not affect response execution.
+ neo.fs.v2.session.ResponseMetaHeader meta_header = 2;
+
+ // Carries response verification information. This header is used to
+ // authenticate the nodes of the message route and check the correctness of
+ // transmission.
+ neo.fs.v2.session.ResponseVerificationHeader verify_header = 3;
+}
diff --git a/netmap/types.proto b/netmap/types.proto
new file mode 100644
index 0000000..b76b3c1
--- /dev/null
+++ b/netmap/types.proto
@@ -0,0 +1,357 @@
+edition = "2023";
+
+package neo.fs.v2.netmap;
+
+option go_package = "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap/grpc;netmap";
+option csharp_namespace = "Neo.FileStorage.API.Netmap";
+
+// Operations on filters
+enum Operation {
+ // No Operation defined
+ OPERATION_UNSPECIFIED = 0;
+
+ // Equal
+ EQ = 1;
+
+ // Not Equal
+ NE = 2;
+
+ // Greater then
+ GT = 3;
+
+ // Greater or equal
+ GE = 4;
+
+ // Less then
+ LT = 5;
+
+ // Less or equal
+ LE = 6;
+
+ // Logical OR
+ OR = 7;
+
+ // Logical AND
+ AND = 8;
+
+ // Logical negation
+ NOT = 9;
+
+ // Matches pattern
+ LIKE = 10;
+}
+
+// Selector modifier shows how the node set will be formed. By default selector
+// just groups nodes into a bucket by attribute, selecting nodes only by their
+// hash distance.
+enum Clause {
+ // No modifier defined. Nodes will be selected from the bucket randomly
+ CLAUSE_UNSPECIFIED = 0;
+
+ // SAME will select only nodes having the same value of bucket attribute
+ SAME = 1;
+
+ // DISTINCT will select nodes having different values of bucket attribute
+ DISTINCT = 2;
+}
+
+// This filter will return the subset of nodes from `NetworkMap` or another
+// filter's results that will satisfy filter's conditions.
+message Filter {
+ // Name of the filter or a reference to a named filter. '*' means
+ // application to the whole unfiltered NetworkMap. At top level it's used as a
+ // filter name. At lower levels it's considered to be a reference to another
+ // named filter
+ string name = 1 [ json_name = "name" ];
+
+ // Key to filter
+ string key = 2 [ json_name = "key" ];
+
+ // Filtering operation
+ Operation op = 3 [ json_name = "op" ];
+
+ // Value to match
+ string value = 4 [ json_name = "value" ];
+
+ // List of inner filters. Top level operation will be applied to the whole
+ // list.
+ repeated Filter filters = 5 [ json_name = "filters" ];
+}
+
+// Selector chooses a number of nodes from the bucket taking the nearest nodes
+// to the provided `ContainerID` by hash distance.
+message Selector {
+ // Selector name to reference in object placement section
+ string name = 1 [ json_name = "name" ];
+
+ // How many nodes to select from the bucket
+ uint32 count = 2 [ json_name = "count" ];
+
+ // Selector modifier showing how to form a bucket
+ Clause clause = 3 [ json_name = "clause" ];
+
+ // Bucket attribute to select from
+ string attribute = 4 [ json_name = "attribute" ];
+
+ // Filter reference to select from
+ string filter = 5 [ json_name = "filter" ];
+}
+
+// Number of object replicas in a set of nodes from the defined selector. If no
+// selector set, the root bucket containing all possible nodes will be used by
+// default.
+message Replica {
+ // How many object replicas to put
+ uint32 count = 1 [ json_name = "count" ];
+
+ // Named selector bucket to put replicas
+ string selector = 2 [ json_name = "selector" ];
+
+ // Data shards count
+ uint32 ec_data_count = 3 [ json_name = "ecDataCount" ];
+
+ // Parity shards count
+ uint32 ec_parity_count = 4 [ json_name = "ecParityCount" ];
+}
+
+// Set of rules to select a subset of nodes from `NetworkMap` able to store
+// container's objects. The format is simple enough to transpile from different
+// storage policy definition languages.
+message PlacementPolicy {
+ // Rules to set number of object replicas and place each one into a named
+ // bucket
+ repeated Replica replicas = 1 [ json_name = "replicas" ];
+
+ // Container backup factor controls how deep FrostFS will search for nodes
+ // alternatives to include into container's nodes subset
+ uint32 container_backup_factor = 2 [ json_name = "containerBackupFactor" ];
+
+ // Set of Selectors to form the container's nodes subset
+ repeated Selector selectors = 3 [ json_name = "selectors" ];
+
+ // List of named filters to reference in selectors
+ repeated Filter filters = 4 [ json_name = "filters" ];
+
+ // Unique flag defines non-overlapping application for replicas
+ bool unique = 5 [ json_name = "unique" ];
+}
+
+// FrostFS node description
+message NodeInfo {
+ // Public key of the FrostFS node in a binary format
+ bytes public_key = 1 [ json_name = "publicKey" ];
+
+ // Ways to connect to a node
+ repeated string addresses = 2 [ json_name = "addresses" ];
+
+ // Administrator-defined Attributes of the FrostFS Storage Node.
+ //
+ // `Attribute` is a Key-Value metadata pair. Key name must be a valid UTF-8
+ // string. Value can't be empty.
+ //
+ // Attributes can be constructed into a chain of attributes: any attribute can
+ // have a parent attribute and a child attribute (except the first and the
+ // last one). A string representation of the chain of attributes in FrostFS
+ // Storage Node configuration uses ":" and "/" symbols, e.g.:
+ //
+ // `FrostFS_NODE_ATTRIBUTE_1=key1:val1/key2:val2`
+ //
+ // Therefore the string attribute representation in the Node configuration
+ // must use "\:", "\/" and "\\" escaped symbols if any of them appears in an
+ // attribute's key or value.
+ //
+ // Node's attributes are mostly used during Storage Policy evaluation to
+ // calculate object's placement and find a set of nodes satisfying policy
+ // requirements. There are some "well-known" node attributes common to all the
+ // Storage Nodes in the network and used implicitly with default values if not
+ // explicitly set:
+ //
+ // * Capacity \
+ // Total available disk space in Gigabytes.
+ // * Price \
+ // Price in GAS tokens for storing one GB of data during one Epoch. In node
+ // attributes it's a string presenting floating point number with comma or
+ // point delimiter for decimal part. In the Network Map it will be saved as
+ // 64-bit unsigned integer representing number of minimal token fractions.
+ // * UN-LOCODE \
+ // Node's geographic location in
+ // [UN/LOCODE](https://www.unece.org/cefact/codesfortrade/codes_index.html)
+ // format approximated to the nearest point defined in the standard.
+ // * CountryCode \
+ // Country code in
+ // [ISO 3166-1_alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2)
+ // format. Calculated automatically from `UN-LOCODE` attribute.
+ // * Country \
+ // Country short name in English, as defined in
+ // [ISO-3166](https://www.iso.org/obp/ui/#search). Calculated automatically
+ // from `UN-LOCODE` attribute.
+ // * Location \
+ // Place names are given, whenever possible, in their national language
+ // versions as expressed in the Roman alphabet using the 26 characters of
+ // the character set adopted for international trade data interchange,
+ // written without diacritics . Calculated automatically from `UN-LOCODE`
+ // attribute.
+ // * SubDivCode \
+ // Country's administrative subdivision where node is located. Calculated
+ // automatically from `UN-LOCODE` attribute based on `SubDiv` field.
+ // Presented in [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2)
+ // format.
+ // * SubDiv \
+ // Country's administrative subdivision name, as defined in
+ // [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2). Calculated
+ // automatically from `UN-LOCODE` attribute.
+ // * Continent \
+ // Node's continent name according to the [Seven-Continent
+ // model](https://en.wikipedia.org/wiki/Continent#Number). Calculated
+ // automatically from `UN-LOCODE` attribute.
+ // * ExternalAddr
+ // Node's preferred way for communications with external clients.
+ // Clients SHOULD use these addresses if possible.
+ // Must contain a comma-separated list of multi-addresses.
+ //
+ // For detailed description of each well-known attribute please see the
+ // corresponding section in FrostFS Technical Specification.
+ message Attribute {
+ // Key of the node attribute
+ string key = 1 [ json_name = "key" ];
+
+ // Value of the node attribute
+ string value = 2 [ json_name = "value" ];
+
+ // Parent keys, if any. For example for `City` it could be `Region` and
+ // `Country`.
+ repeated string parents = 3 [ json_name = "parents" ];
+ }
+ // Carries list of the FrostFS node attributes in a key-value form. Key name
+ // must be a node-unique valid UTF-8 string. Value can't be empty. NodeInfo
+ // structures with duplicated attribute names or attributes with empty values
+ // will be considered invalid.
+ repeated Attribute attributes = 3 [ json_name = "attributes" ];
+
+ // Represents the enumeration of various states of the FrostFS node.
+ enum State {
+ // Unknown state
+ UNSPECIFIED = 0;
+
+ // Active state in the network
+ ONLINE = 1;
+
+ // Network unavailable state
+ OFFLINE = 2;
+
+ // Maintenance state
+ MAINTENANCE = 3;
+ }
+
+ // Carries state of the FrostFS node
+ State state = 4 [ json_name = "state" ];
+}
+
+// Network map structure
+message Netmap {
+ // Network map revision number.
+ uint64 epoch = 1 [ json_name = "epoch" ];
+
+ // Nodes presented in network.
+ repeated NodeInfo nodes = 2 [ json_name = "nodes" ];
+}
+
+// FrostFS network configuration
+message NetworkConfig {
+ // Single configuration parameter. Key MUST be network-unique.
+ //
+ // System parameters:
+ // - **AuditFee** \
+ // Fee paid by the storage group owner to the Inner Ring member.
+ // Value: little-endian integer. Default: 0.
+ // - **BasicIncomeRate** \
+ // Cost of storing one gigabyte of data for a period of one epoch. Paid by
+ // container owner to container nodes.
+ // Value: little-endian integer. Default: 0.
+ // - **ContainerAliasFee** \
+ // Fee paid for named container's creation by the container owner.
+ // Value: little-endian integer. Default: 0.
+ // - **ContainerFee** \
+ // Fee paid for container creation by the container owner.
+ // Value: little-endian integer. Default: 0.
+ // - **EpochDuration** \
+ // FrostFS epoch duration measured in Sidechain blocks.
+ // Value: little-endian integer. Default: 0.
+ // - **HomomorphicHashingDisabled** \
+ // Flag of disabling the homomorphic hashing of objects' payload.
+ // Value: true if any byte != 0. Default: false.
+ // - **InnerRingCandidateFee** \
+ // Fee for entrance to the Inner Ring paid by the candidate.
+ // Value: little-endian integer. Default: 0.
+ // - **MaintenanceModeAllowed** \
+ // Flag allowing setting the MAINTENANCE state to storage nodes.
+ // Value: true if any byte != 0. Default: false.
+ // - **MaxObjectSize** \
+ // Maximum size of physically stored FrostFS object measured in bytes.
+ // Value: little-endian integer. Default: 0.
+ //
+ // This value refers to the maximum size of a **physically** stored object
+ // in FrostFS. However, from a user's perspective, the **logical** size of a
+ // stored object can be significantly larger. The relationship between the
+ // physical and logical object sizes is governed by the following formula
+ //
+ // ```math
+ // \mathrm{Stored\ Object\ Size} \le
+ // \frac{
+ // \left(\mathrm{Max\ Object\ Size}\right)^2
+ // }{
+ // \mathrm{Object\ ID\ Size}
+ // }
+ // ```
+ //
+ // This arises from the fact that a tombstone, also being an object, stores
+ // the IDs of inhumed objects and cannot be divided into smaller objects,
+ // thus having an upper limit for its size.
+ //
+ // For example, if:
+ // * Max Object Size Size = 64 MiB;
+ // * Object ID Size = 32 B;
+ //
+ // then:
+ // ```math
+ // \mathrm{Stored\ Object\ Size} \le
+ // \frac{\left(64\ \mathrm{MiB}\right)^2}{32\ \mathrm{B}} =
+ // \frac{2^{52}}{2^5}\ \mathrm{B} =
+ // 2^{47}\ \mathrm{B} =
+ // 128\ \mathrm{TiB}
+ // ```
+ // - **WithdrawFee** \
+ // Fee paid for withdrawal of funds paid by the account owner.
+ // Value: little-endian integer. Default: 0.
+ // - **MaxECDataCount** \
+ // Maximum number of data shards for EC placement policy.
+ // Value: little-endian integer. Default: 0.
+ // - **MaxECParityCount** \
+ // Maximum number of parity shards for EC placement policy.
+ // Value: little-endian integer. Default: 0.
+ message Parameter {
+ // Parameter key. UTF-8 encoded string
+ bytes key = 1 [ json_name = "key" ];
+
+ // Parameter value
+ bytes value = 2 [ json_name = "value" ];
+ }
+ // List of parameter values
+ repeated Parameter parameters = 1 [ json_name = "parameters" ];
+}
+
+// Information about FrostFS network
+message NetworkInfo {
+ // Number of the current epoch in the FrostFS network
+ uint64 current_epoch = 1 [ json_name = "currentEpoch" ];
+
+ // Magic number of the sidechain of the FrostFS network
+ uint64 magic_number = 2 [ json_name = "magicNumber" ];
+
+ // MillisecondsPerBlock network parameter of the sidechain of the FrostFS
+ // network
+ int64 ms_per_block = 3 [ json_name = "msPerBlock" ];
+
+ // FrostFS network configuration
+ NetworkConfig network_config = 4 [ json_name = "networkConfig" ];
+}
diff --git a/object/service.proto b/object/service.proto
new file mode 100644
index 0000000..c5e4fc7
--- /dev/null
+++ b/object/service.proto
@@ -0,0 +1,947 @@
+edition = "2023";
+
+package neo.fs.v2.object;
+
+option go_package = "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object/grpc;object";
+option csharp_namespace = "Neo.FileStorage.API.Object";
+
+import "object/types.proto";
+import "refs/types.proto";
+import "session/types.proto";
+
+// `ObjectService` provides API for manipulating objects. Object operations do
+// not affect the sidechain and are only served by nodes in p2p style.
+service ObjectService {
+ // Receive full object structure, including Headers and payload. Response uses
+ // gRPC stream. First response message carries the object with the requested
+ // address. Chunk messages are parts of the object's payload if it is needed.
+ // All messages, except the first one, carry payload chunks. The requested
+ // object can be restored by concatenation of object message payload and all
+ // chunks keeping the receiving order.
+ //
+ // Extended headers can change `Get` behaviour:
+ // * [ __SYSTEM__NETMAP_EPOCH ] \
+ // (`__NEOFS__NETMAP_EPOCH` is deprecated) \
+ // Will use the requsted version of Network Map for object placement
+ // calculation.
+ // * [ __SYSTEM__NETMAP_LOOKUP_DEPTH ] \
+ // (`__NEOFS__NETMAP_LOOKUP_DEPTH` is deprecated) \
+ // Will try older versions (starting from `__SYSTEM__NETMAP_EPOCH`
+ // (`__NEOFS__NETMAP_EPOCH` is deprecated) if specified or the latest one
+ // otherwise) of Network Map to find an object until the depth limit is
+ // reached.
+ //
+ // Please refer to detailed `XHeader` description.
+ //
+ // Statuses:
+ // - **OK** (0, SECTION_SUCCESS): \
+ // object has been successfully read;
+ // - Common failures (SECTION_FAILURE_COMMON);
+ // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \
+ // read access to the object is denied;
+ // - **OBJECT_NOT_FOUND** (2049, SECTION_OBJECT): \
+ // object not found in container;
+ // - **OBJECT_ALREADY_REMOVED** (2052, SECTION_OBJECT): \
+ // the requested object has been marked as deleted;
+ // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \
+ // object container not found;
+ // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \
+ // access to container is denied;
+ // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \
+ // provided session token has expired.
+ rpc Get(GetRequest) returns (stream GetResponse);
+
+ // Put the object into container. Request uses gRPC stream. First message
+ // SHOULD be of PutHeader type. `ContainerID` and `OwnerID` of an object
+ // SHOULD be set. Session token SHOULD be obtained before `PUT` operation (see
+ // session package). Chunk messages are considered by server as a part of an
+ // object payload. All messages, except first one, SHOULD be payload chunks.
+ // Chunk messages SHOULD be sent in the direct order of fragmentation.
+ //
+ // Extended headers can change `Put` behaviour:
+ // * [ __SYSTEM__NETMAP_EPOCH \
+ // (`__NEOFS__NETMAP_EPOCH` is deprecated) \
+ // Will use the requsted version of Network Map for object placement
+ // calculation.
+ //
+ // Please refer to detailed `XHeader` description.
+ //
+ // Statuses:
+ // - **OK** (0, SECTION_SUCCESS): \
+ // object has been successfully saved in the container;
+ // - Common failures (SECTION_FAILURE_COMMON);
+ // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \
+ // write access to the container is denied;
+ // - **LOCKED** (2050, SECTION_OBJECT): \
+ // placement of an object of type TOMBSTONE that includes at least one
+ // locked object is prohibited;
+ // - **LOCK_NON_REGULAR_OBJECT** (2051, SECTION_OBJECT): \
+ // placement of an object of type LOCK that includes at least one object of
+ // type other than REGULAR is prohibited;
+ // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \
+ // object storage container not found;
+ // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \
+ // access to container is denied;
+ // - **TOKEN_NOT_FOUND** (4096, SECTION_SESSION): \
+ // (for trusted object preparation) session private key does not exist or
+ // has
+ // been deleted;
+ // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \
+ // provided session token has expired.
+ rpc Put(stream PutRequest) returns (PutResponse);
+
+ // Delete the object from a container. There is no immediate removal
+ // guarantee. Object will be marked for removal and deleted eventually.
+ //
+ // Extended headers can change `Delete` behaviour:
+ // * [ __SYSTEM__NETMAP_EPOCH ] \
+ // (`__NEOFS__NETMAP_EPOCH` is deprecated) \
+ // Will use the requested version of Network Map for object placement
+ // calculation.
+ //
+ // Please refer to detailed `XHeader` description.
+ //
+ // Statuses:
+ // - **OK** (0, SECTION_SUCCESS): \
+ // object has been successfully marked to be removed from the container;
+ // - Common failures (SECTION_FAILURE_COMMON);
+ // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \
+ // delete access to the object is denied;
+ // - **OBJECT_NOT_FOUND** (2049, SECTION_OBJECT): \
+ // the object could not be deleted because it has not been \
+ // found within the container;
+ // - **LOCKED** (2050, SECTION_OBJECT): \
+ // deleting a locked object is prohibited;
+ // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \
+ // object container not found;
+ // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \
+ // access to container is denied;
+ // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \
+ // provided session token has expired.
+ rpc Delete(DeleteRequest) returns (DeleteResponse);
+
+ // Returns the object Headers without data payload. By default full header is
+ // returned. If `main_only` request field is set, the short header with only
+ // the very minimal information will be returned instead.
+ //
+ // Max header size is currently not limited by this API, but may be restricted
+ // on the service level. By default, gRPC uses a message size of 4 MiB.
+ //
+ // Extended headers can change `Head` behaviour:
+ // * [ __SYSTEM__NETMAP_EPOCH ] \
+ // (`__NEOFS__NETMAP_EPOCH` is deprecated) \
+ // Will use the requested version of Network Map for object placement
+ // calculation.
+ //
+ // Please refer to detailed `XHeader` description.
+ //
+ // Statuses:
+ // - **OK** (0, SECTION_SUCCESS): \
+ // object header has been successfully read;
+ // - Common failures (SECTION_FAILURE_COMMON);
+ // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \
+ // access to operation HEAD of the object is denied;
+ // - **OBJECT_NOT_FOUND** (2049, SECTION_OBJECT): \
+ // object not found in container;
+ // - **OBJECT_ALREADY_REMOVED** (2052, SECTION_OBJECT): \
+ // the requested object has been marked as deleted;
+ // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \
+ // object container not found;
+ // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \
+ // access to container is denied;
+ // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \
+ // provided session token has expired.
+ rpc Head(HeadRequest) returns (HeadResponse);
+
+ // Search objects in container. Search query allows to match by Object
+ // Header's filed values. Please see the corresponding FrostFS Technical
+ // Specification section for more details.
+ //
+ // Extended headers can change `Search` behaviour:
+ // * [ __SYSTEM__NETMAP_EPOCH ] \
+ // (`__NEOFS__NETMAP_EPOCH` is deprecated) \
+ // Will use the requested version of Network Map for object placement
+ // calculation.
+ //
+ // Please refer to detailed `XHeader` description.
+ //
+ // Statuses:
+ // - **OK** (0, SECTION_SUCCESS): \
+ // objects have been successfully selected;
+ // - Common failures (SECTION_FAILURE_COMMON);
+ // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \
+ // access to operation SEARCH of the object is denied;
+ // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \
+ // search container not found;
+ // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \
+ // access to container is denied;
+ // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \
+ // provided session token has expired.
+ rpc Search(SearchRequest) returns (stream SearchResponse);
+
+ // Get byte range of data payload. Range is set as an (offset, length) tuple.
+ // Like in `Get` method, the response uses gRPC stream. Requested range can be
+ // restored by concatenation of all received payload chunks keeping the
+ // receiving order.
+ //
+ // Extended headers can change `GetRange` behaviour:
+ // * [ __SYSTEM__NETMAP_EPOCH ] \
+ // (`__NEOFS__NETMAP_EPOCH` is deprecated) \
+ // Will use the requested version of Network Map for object placement
+ // calculation.
+ // * [ __SYSTEM__NETMAP_LOOKUP_DEPTH ] \
+ // (`__NEOFS__NETMAP_LOOKUP_DEPTH` is deprecated) \
+ // Will try older versions of Network Map to find an object until the depth
+ // limit is reached.
+ //
+ // Please refer to detailed `XHeader` description.
+ //
+ // Statuses:
+ // - **OK** (0, SECTION_SUCCESS): \
+ // data range of the object payload has been successfully read;
+ // - Common failures (SECTION_FAILURE_COMMON);
+ // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \
+ // access to operation RANGE of the object is denied;
+ // - **OBJECT_NOT_FOUND** (2049, SECTION_OBJECT): \
+ // object not found in container;
+ // - **OBJECT_ALREADY_REMOVED** (2052, SECTION_OBJECT): \
+ // the requested object has been marked as deleted.
+ // - **OUT_OF_RANGE** (2053, SECTION_OBJECT): \
+ // the requested range is out of bounds;
+ // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \
+ // object container not found;
+ // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \
+ // access to container is denied;
+ // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \
+ // provided session token has expired.
+ rpc GetRange(GetRangeRequest) returns (stream GetRangeResponse);
+
+ // Returns homomorphic or regular hash of object's payload range after
+ // applying XOR operation with the provided `salt`. Ranges are set of (offset,
+ // length) tuples. Hashes order in response corresponds to the ranges order in
+ // the request. Note that hash is calculated for XORed data.
+ //
+ // Extended headers can change `GetRangeHash` behaviour:
+ // * [ __SYSTEM__NETMAP_EPOCH ] \
+ // (`__NEOFS__NETMAP_EPOCH` is deprecated) \
+ // Will use the requested version of Network Map for object placement
+ // calculation.
+ // * [ __SYSTEM__NETMAP_LOOKUP_DEPTH ] \
+ // (`__NEOFS__NETMAP_LOOKUP_DEPTH` is deprecated) \
+ // Will try older versions of Network Map to find an object until the depth
+ // limit is reached.
+ //
+ // Please refer to detailed `XHeader` description.
+ //
+ // Statuses:
+ // - **OK** (0, SECTION_SUCCESS): \
+ // data range of the object payload has been successfully hashed;
+ // - Common failures (SECTION_FAILURE_COMMON);
+ // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \
+ // access to operation RANGEHASH of the object is denied;
+ // - **OBJECT_NOT_FOUND** (2049, SECTION_OBJECT): \
+ // object not found in container;
+ // - **OUT_OF_RANGE** (2053, SECTION_OBJECT): \
+ // the requested range is out of bounds;
+ // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \
+ // object container not found;
+ // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \
+ // access to container is denied;
+ // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \
+ // provided session token has expired.
+ rpc GetRangeHash(GetRangeHashRequest) returns (GetRangeHashResponse);
+
+ // Put the prepared object into container.
+ // `ContainerID`, `ObjectID`, `OwnerID`, `PayloadHash` and `PayloadLength` of
+ // an object MUST be set.
+ //
+ // Extended headers can change `Put` behaviour:
+ // * [ __SYSTEM__NETMAP_EPOCH \
+ // (`__NEOFS__NETMAP_EPOCH` is deprecated) \
+ // Will use the requested version of Network Map for object placement
+ // calculation.
+ //
+ // Please refer to detailed `XHeader` description.
+ //
+ // Statuses:
+ // - **OK** (0, SECTION_SUCCESS): \
+ // object has been successfully saved in the container;
+ // - Common failures (SECTION_FAILURE_COMMON);
+ // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \
+ // write access to the container is denied;
+ // - **LOCKED** (2050, SECTION_OBJECT): \
+ // placement of an object of type TOMBSTONE that includes at least one
+ // locked object is prohibited;
+ // - **LOCK_NON_REGULAR_OBJECT** (2051, SECTION_OBJECT): \
+ // placement of an object of type LOCK that includes at least one object of
+ // type other than REGULAR is prohibited;
+ // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \
+ // object storage container not found;
+ // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \
+ // access to container is denied;
+ // - **TOKEN_NOT_FOUND** (4096, SECTION_SESSION): \
+ // (for trusted object preparation) session private key does not exist or
+ // has
+ // been deleted;
+ // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \
+ // provided session token has expired.
+ rpc PutSingle(PutSingleRequest) returns (PutSingleResponse);
+
+ // Patch the object. Request uses gRPC stream. First message must set
+ // the address of the object that is going to get patched. If the object's
+ // attributes are patched, then these attrubutes must be set only within the
+ // first stream message.
+ //
+ // If the patch request is performed by NOT the object's owner but if the
+ // actor has the permission to perform the patch, then `OwnerID` of the object
+ // is changed. In this case the object's owner loses the object's ownership
+ // after the patch request is successfully done.
+ //
+ // As objects are content-addressable the patching causes new object ID
+ // generation for the patched object. This object id is set witihn
+ // `PatchResponse`. But the object id may remain unchanged in such cases:
+ // 1. The chunk of the applying patch contains the same value as the object's
+ // payload within the same range;
+ // 2. The patch that reverts the changes applied by preceding patch;
+ // 3. The application of the same patches for the object a few times.
+ //
+ // Extended headers can change `Patch` behaviour:
+ // * [ __SYSTEM__NETMAP_EPOCH \
+ // (`__NEOFS__NETMAP_EPOCH` is deprecated) \
+ // Will use the requsted version of Network Map for object placement
+ // calculation.
+ //
+ // Please refer to detailed `XHeader` description.
+ //
+ // Statuses:
+ // - **OK** (0, SECTION_SUCCESS): \
+ // object has been successfully patched and saved in the container;
+ // - Common failures (SECTION_FAILURE_COMMON);
+ // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \
+ // write access to the container is denied;
+ // - **OBJECT_NOT_FOUND** (2049, SECTION_OBJECT): \
+ // object not found in container;
+ // - **OBJECT_ALREADY_REMOVED** (2052, SECTION_OBJECT): \
+ // the requested object has been marked as deleted.
+ // - **OUT_OF_RANGE** (2053, SECTION_OBJECT): \
+ // the requested range is out of bounds;
+ // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \
+ // object storage container not found;
+ // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \
+ // access to container is denied;
+ // - **TOKEN_NOT_FOUND** (4096, SECTION_SESSION): \
+ // (for trusted object preparation) session private key does not exist or
+ // has been deleted;
+ // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \
+ // provided session token has expired.
+ rpc Patch(stream PatchRequest) returns (PatchResponse);
+}
+
+// GET object request
+message GetRequest {
+ // GET Object request body
+ message Body {
+ // Address of the requested object
+ neo.fs.v2.refs.Address address = 1;
+
+ // If `raw` flag is set, request will work only with objects that are
+ // physically stored on the peer node
+ bool raw = 2;
+ }
+ // Body of get object request message.
+ Body body = 1;
+
+ // Carries request meta information. Header data is used only to regulate
+ // message transport and does not affect request execution.
+ neo.fs.v2.session.RequestMetaHeader meta_header = 2;
+
+ // Carries request verification information. This header is used to
+ // authenticate the nodes of the message route and check the correctness of
+ // transmission.
+ neo.fs.v2.session.RequestVerificationHeader verify_header = 3;
+}
+
+// GET object response
+message GetResponse {
+ // GET Object Response body
+ message Body {
+ // Initial part of the `Object` structure stream. Technically it's a
+ // set of all `Object` structure's fields except `payload`.
+ message Init {
+ // Object's unique identifier.
+ neo.fs.v2.refs.ObjectID object_id = 1;
+
+ // Signed `ObjectID`
+ neo.fs.v2.refs.Signature signature = 2;
+
+ // Object metadata headers
+ Header header = 3;
+ }
+ // Single message in the response stream.
+ oneof object_part {
+ // Initial part of the object stream
+ Init init = 1;
+
+ // Chunked object payload
+ bytes chunk = 2;
+
+ // Meta information of split hierarchy for object assembly.
+ SplitInfo split_info = 3;
+
+ // Meta information for EC object assembly.
+ ECInfo ec_info = 4;
+ }
+ }
+ // Body of get object response message.
+ Body body = 1;
+
+ // Carries response meta information. Header data is used only to regulate
+ // message transport and does not affect request execution.
+ neo.fs.v2.session.ResponseMetaHeader meta_header = 2;
+
+ // Carries response verification information. This header is used to
+ // authenticate the nodes of the message route and check the correctness of
+ // transmission.
+ neo.fs.v2.session.ResponseVerificationHeader verify_header = 3;
+}
+
+// PUT object request
+message PutRequest {
+ // PUT request body
+ message Body {
+ // Newly created object structure parameters. If some optional parameters
+ // are not set, they will be calculated by a peer node.
+ message Init {
+ // ObjectID if available.
+ neo.fs.v2.refs.ObjectID object_id = 1;
+
+ // Object signature if available
+ neo.fs.v2.refs.Signature signature = 2;
+
+ // Object's Header
+ Header header = 3;
+
+ // Number of copies of the object to store within the RPC call. By
+ // default, object is processed according to the container's placement
+ // policy. Can be one of:
+ // 1. A single number; applied to the whole request and is treated as
+ // a minimal number of nodes that must store an object to complete the
+ // request successfully.
+ // 2. An ordered array; every number is treated as a minimal number of
+ // nodes in a corresponding placement vector that must store an object
+ // to complete the request successfully. The length MUST equal the
+ // placement vectors number, otherwise request is considered malformed.
+ repeated uint32 copies_number = 4;
+ }
+ // Single message in the request stream.
+ oneof object_part {
+ // Initial part of the object stream
+ Init init = 1;
+
+ // Chunked object payload
+ bytes chunk = 2;
+ }
+ }
+ // Body of put object request message.
+ Body body = 1;
+
+ // Carries request meta information. Header data is used only to regulate
+ // message transport and does not affect request execution.
+ neo.fs.v2.session.RequestMetaHeader meta_header = 2;
+
+ // Carries request verification information. This header is used to
+ // authenticate the nodes of the message route and check the correctness of
+ // transmission.
+ neo.fs.v2.session.RequestVerificationHeader verify_header = 3;
+}
+
+// PUT Object response
+message PutResponse {
+ // PUT Object response body
+ message Body {
+ // Identifier of the saved object
+ neo.fs.v2.refs.ObjectID object_id = 1;
+ }
+ // Body of put object response message.
+ Body body = 1;
+
+ // Carries response meta information. Header data is used only to regulate
+ // message transport and does not affect request execution.
+ neo.fs.v2.session.ResponseMetaHeader meta_header = 2;
+
+ // Carries response verification information. This header is used to
+ // authenticate the nodes of the message route and check the correctness of
+ // transmission.
+ neo.fs.v2.session.ResponseVerificationHeader verify_header = 3;
+}
+
+// Object DELETE request
+message DeleteRequest {
+ // Object DELETE request body
+ message Body {
+ // Address of the object to be deleted
+ neo.fs.v2.refs.Address address = 1;
+ }
+ // Body of delete object request message.
+ Body body = 1;
+
+ // Carries request meta information. Header data is used only to regulate
+ // message transport and does not affect request execution.
+ neo.fs.v2.session.RequestMetaHeader meta_header = 2;
+
+ // Carries request verification information. This header is used to
+ // authenticate the nodes of the message route and check the correctness of
+ // transmission.
+ neo.fs.v2.session.RequestVerificationHeader verify_header = 3;
+}
+
+// DeleteResponse body is empty because we cannot guarantee permanent object
+// removal in distributed system.
+message DeleteResponse {
+ // Object DELETE Response has an empty body.
+ message Body {
+ // Address of the tombstone created for the deleted object
+ neo.fs.v2.refs.Address tombstone = 1;
+ }
+
+ // Body of delete object response message.
+ Body body = 1;
+
+ // Carries response meta information. Header data is used only to regulate
+ // message transport and does not affect request execution.
+ neo.fs.v2.session.ResponseMetaHeader meta_header = 2;
+
+ // Carries response verification information. This header is used to
+ // authenticate the nodes of the message route and check the correctness of
+ // transmission.
+ neo.fs.v2.session.ResponseVerificationHeader verify_header = 3;
+}
+
+// Object HEAD request
+message HeadRequest {
+ // Object HEAD request body
+ message Body {
+ // Address of the object with the requested Header
+ neo.fs.v2.refs.Address address = 1;
+
+ // Return only minimal header subset
+ bool main_only = 2;
+
+ // If `raw` flag is set, request will work only with objects that are
+ // physically stored on the peer node
+ bool raw = 3;
+ }
+ // Body of head object request message.
+ Body body = 1;
+
+ // Carries request meta information. Header data is used only to regulate
+ // message transport and does not affect request execution.
+ neo.fs.v2.session.RequestMetaHeader meta_header = 2;
+
+ // Carries request verification information. This header is used to
+ // authenticate the nodes of the message route and check the correctness of
+ // transmission.
+ neo.fs.v2.session.RequestVerificationHeader verify_header = 3;
+}
+
+// Tuple of a full object header and signature of an `ObjectID`. \
+// Signed `ObjectID` is present to verify full header's authenticity through the
+// following steps:
+//
+// 1. Calculate `SHA-256` of the marshalled `Header` structure
+// 2. Check if the resulting hash matches `ObjectID`
+// 3. Check if `ObjectID` signature in `signature` field is correct
+message HeaderWithSignature {
+ // Full object header
+ Header header = 1 [ json_name = "header" ];
+
+ // Signed `ObjectID` to verify full header's authenticity
+ neo.fs.v2.refs.Signature signature = 2 [ json_name = "signature" ];
+}
+
+// Object HEAD response
+message HeadResponse {
+ // Object HEAD response body
+ message Body {
+ // Requested object header, it's part or meta information about split
+ // object.
+ oneof head {
+ // Full object's `Header` with `ObjectID` signature
+ HeaderWithSignature header = 1;
+
+ // Short object header
+ ShortHeader short_header = 2;
+
+ // Meta information of split hierarchy.
+ // Indicates that the object is virtual, manual assembly is required.
+ SplitInfo split_info = 3;
+
+ // Meta information for EC object assembly.
+ ECInfo ec_info = 4;
+ }
+ }
+ // Body of head object response message.
+ Body body = 1;
+
+ // Carries response meta information. Header data is used only to regulate
+ // message transport and does not affect request execution.
+ neo.fs.v2.session.ResponseMetaHeader meta_header = 2;
+
+ // Carries response verification information. This header is used to
+ // authenticate the nodes of the message route and check the correctness of
+ // transmission.
+ neo.fs.v2.session.ResponseVerificationHeader verify_header = 3;
+}
+
+// Object Search request
+message SearchRequest {
+ // Object Search request body
+ message Body {
+ // Container identifier were to search
+ neo.fs.v2.refs.ContainerID container_id = 1;
+
+ // Version of the Query Language used
+ uint32 version = 2;
+ // Filter structure checks if the object header field or the attribute
+ // content matches a value.
+ //
+ // If no filters are set, search request will return all objects of the
+ // container, including Regular object and Tombstone
+ // objects. Most human users expect to get only object they can directly
+ // work with. In that case, `$Object:ROOT` filter should be used.
+ //
+ // By default `key` field refers to the corresponding object's `Attribute`.
+ // Some Object's header fields can also be accessed by adding `$Object:`
+ // prefix to the name. Here is the list of fields available via this prefix:
+ //
+ // * $Object:version \
+ // version
+ // * $Object:objectID \
+ // object_id
+ // * $Object:containerID \
+ // container_id
+ // * $Object:ownerID \
+ // owner_id
+ // * $Object:creationEpoch \
+ // creation_epoch
+ // * $Object:payloadLength \
+ // payload_length
+ // * $Object:payloadHash \
+ // payload_hash
+ // * $Object:objectType \
+ // object_type
+ // * $Object:homomorphicHash \
+ // homomorphic_hash
+ // * $Object:split.parent \
+ // object_id of parent
+ // * $Object:split.splitID \
+ // 16 byte UUIDv4 used to identify the split object hierarchy parts
+ // * $Object:ec.parent \
+ // If the object is stored according to EC policy, then ec_parent
+ // attribute is set to return an id list of all related EC chunks.
+ //
+ // There are some well-known filter aliases to match objects by certain
+ // properties:
+ //
+ // * $Object:ROOT \
+ // Returns only `REGULAR` type objects that are not split or that are the
+ // top level root objects in a split hierarchy. This includes objects not
+ // present physically, like large objects split into smaller objects
+ // without a separate top-level root object. Objects of other types like
+ // Locks and Tombstones will not be shown. This filter may be
+ // useful for listing objects like `ls` command of some virtual file
+ // system. This filter is activated if the `key` exists, disregarding the
+ // value and matcher type.
+ // * $Object:PHY \
+ // Returns only objects physically stored in the system. This filter is
+ // activated if the `key` exists, disregarding the value and matcher type.
+ //
+ // Note: using filters with a key with prefix `$Object:` and match type
+ // `NOT_PRESENT `is not recommended since this is not a cross-version
+ // approach. Behavior when processing this kind of filters is undefined.
+ message Filter {
+ // Match type to use
+ MatchType match_type = 1 [ json_name = "matchType" ];
+
+ // Attribute or Header fields to match
+ string key = 2 [ json_name = "key" ];
+
+ // Value to match
+ string value = 3 [ json_name = "value" ];
+ }
+ // List of search expressions
+ repeated Filter filters = 3;
+ }
+ // Body of search object request message.
+ Body body = 1;
+
+ // Carries request meta information. Header data is used only to regulate
+ // message transport and does not affect request execution.
+ neo.fs.v2.session.RequestMetaHeader meta_header = 2;
+
+ // Carries request verification information. This header is used to
+ // authenticate the nodes of the message route and check the correctness of
+ // transmission.
+ neo.fs.v2.session.RequestVerificationHeader verify_header = 3;
+}
+
+// Search response
+message SearchResponse {
+ // Object Search response body
+ message Body {
+ // List of `ObjectID`s that match the search query
+ repeated neo.fs.v2.refs.ObjectID id_list = 1;
+ }
+ // Body of search object response message.
+ Body body = 1;
+
+ // Carries response meta information. Header data is used only to regulate
+ // message transport and does not affect request execution.
+ neo.fs.v2.session.ResponseMetaHeader meta_header = 2;
+
+ // Carries response verification information. This header is used to
+ // authenticate the nodes of the message route and check the correctness of
+ // transmission.
+ neo.fs.v2.session.ResponseVerificationHeader verify_header = 3;
+}
+
+// Object payload range.Ranges of zero length SHOULD be considered as invalid.
+message Range {
+ // Offset of the range from the object payload start
+ uint64 offset = 1;
+
+ // Length in bytes of the object payload range
+ uint64 length = 2;
+}
+
+// Request part of object's payload
+message GetRangeRequest {
+ // Byte range of object's payload request body
+ message Body {
+ // Address of the object containing the requested payload range
+ neo.fs.v2.refs.Address address = 1;
+
+ // Requested payload range
+ Range range = 2;
+
+ // If `raw` flag is set, request will work only with objects that are
+ // physically stored on the peer node.
+ bool raw = 3;
+ }
+
+ // Body of get range object request message.
+ Body body = 1;
+
+ // Carries request meta information. Header data is used only to regulate
+ // message transport and does not affect request execution.
+ neo.fs.v2.session.RequestMetaHeader meta_header = 2;
+
+ // Carries request verification information. This header is used to
+ // authenticate the nodes of the message route and check the correctness of
+ // transmission.
+ neo.fs.v2.session.RequestVerificationHeader verify_header = 3;
+}
+
+// Get part of object's payload
+message GetRangeResponse {
+ // Get Range response body uses streams to transfer the response. Because
+ // object payload considered a byte sequence, there is no need to have some
+ // initial preamble message. The requested byte range is sent as a series
+ // chunks.
+ message Body {
+ // Requested object range or meta information about split object.
+ oneof range_part {
+ // Chunked object payload's range.
+ bytes chunk = 1;
+
+ // Meta information of split hierarchy.
+ SplitInfo split_info = 2;
+
+ // Meta information for EC object assembly.
+ ECInfo ec_info = 3;
+ }
+ }
+
+ // Body of get range object response message.
+ Body body = 1;
+
+ // Carries response meta information. Header data is used only to regulate
+ // message transport and does not affect request execution.
+ neo.fs.v2.session.ResponseMetaHeader meta_header = 2;
+
+ // Carries response verification information. This header is used to
+ // authenticate the nodes of the message route and check the correctness of
+ // transmission.
+ neo.fs.v2.session.ResponseVerificationHeader verify_header = 3;
+}
+
+// Get hash of object's payload part
+message GetRangeHashRequest {
+ // Get hash of object's payload part request body.
+ message Body {
+ // Address of the object that containing the requested payload range
+ neo.fs.v2.refs.Address address = 1;
+
+ // List of object's payload ranges to calculate homomorphic hash
+ repeated Range ranges = 2;
+
+ // Binary salt to XOR object's payload ranges before hash calculation
+ bytes salt = 3;
+
+ // Checksum algorithm type
+ neo.fs.v2.refs.ChecksumType type = 4;
+ }
+ // Body of get range hash object request message.
+ Body body = 1;
+
+ // Carries request meta information. Header data is used only to regulate
+ // message transport and does not affect request execution.
+ neo.fs.v2.session.RequestMetaHeader meta_header = 2;
+
+ // Carries request verification information. This header is used to
+ // authenticate the nodes of the message route and check the correctness of
+ // transmission.
+ neo.fs.v2.session.RequestVerificationHeader verify_header = 3;
+}
+
+// Get hash of object's payload part
+message GetRangeHashResponse {
+ // Get hash of object's payload part response body.
+ message Body {
+ // Checksum algorithm type
+ neo.fs.v2.refs.ChecksumType type = 1;
+
+ // List of range hashes in a binary format
+ repeated bytes hash_list = 2;
+ }
+ // Body of get range hash object response message.
+ Body body = 1;
+
+ // Carries response meta information. Header data is used only to regulate
+ // message transport and does not affect request execution.
+ neo.fs.v2.session.ResponseMetaHeader meta_header = 2;
+
+ // Carries response verification information. This header is used to
+ // authenticate the nodes of the message route and check the correctness of
+ // transmission.
+ neo.fs.v2.session.ResponseVerificationHeader verify_header = 3;
+}
+
+// Object PUT Single request
+message PutSingleRequest {
+ // PUT Single request body
+ message Body {
+ // Prepared object with payload.
+ Object object = 1;
+ // Number of copies of the object to store within the RPC call. By default,
+ // object is processed according to the container's placement policy.
+ // Every number is treated as a minimal number of
+ // nodes in a corresponding placement vector that must store an object
+ // to complete the request successfully. The length MUST equal the placement
+ // vectors number, otherwise request is considered malformed.
+ repeated uint32 copies_number = 2;
+ }
+ // Body of put single object request message.
+ Body body = 1;
+
+ // Carries request meta information. Header data is used only to regulate
+ // message transport and does not affect request execution.
+ neo.fs.v2.session.RequestMetaHeader meta_header = 2;
+
+ // Carries request verification information. This header is used to
+ // authenticate the nodes of the message route and check the correctness of
+ // transmission.
+ neo.fs.v2.session.RequestVerificationHeader verify_header = 3;
+}
+
+// Object PUT Single response
+message PutSingleResponse {
+ // PUT Single Object response body
+ message Body {}
+ // Body of put single object response message.
+ Body body = 1;
+
+ // Carries response meta information. Header data is used only to regulate
+ // message transport and does not affect request execution.
+ neo.fs.v2.session.ResponseMetaHeader meta_header = 2;
+
+ // Carries response verification information. This header is used to
+ // authenticate the nodes of the message route and check the correctness of
+ // transmission.
+ neo.fs.v2.session.ResponseVerificationHeader verify_header = 3;
+}
+
+// Object PATCH request
+message PatchRequest {
+ // PATCH request body
+ message Body {
+ // The address of the object that is requested to get patched.
+ neo.fs.v2.refs.Address address = 1;
+
+ // New attributes for the object. See `replace_attributes` flag usage to
+ // define how new attributes should be set.
+ repeated neo.fs.v2.object.Header.Attribute new_attributes = 2;
+
+ // If this flag is set, then the object's attributes will be entirely
+ // replaced by `new_attributes` list. The empty `new_attributes` list with
+ // `replace_attributes = true` just resets attributes list for the object.
+ //
+ // Default `false` value for this flag means the attributes will be just
+ // merged. If the incoming `new_attributes` list contains already existing
+ // key, then it just replaces it while merging the lists.
+ bool replace_attributes = 3;
+
+ // New split header for the object. This defines how the object will relate
+ // to other objects in a split operation.
+ neo.fs.v2.object.Header.Split new_split_header = 5;
+
+ // The patch for the object's payload.
+ message Patch {
+ // The range of the source object for which the payload is replaced by the
+ // patch's chunk. If the range's `length = 0`, then the patch's chunk is
+ // just appended to the original payload starting from the `offest`
+ // without any replace.
+ Range source_range = 1;
+
+ // The chunk that is being appended to or that replaces the original
+ // payload on the given range.
+ bytes chunk = 2;
+ }
+
+ // The patch that is applied for the object.
+ Patch patch = 4;
+ }
+
+ // Body for patch request message.
+ Body body = 1;
+
+ // Carries request meta information. Header data is used only to regulate
+ // message transport and does not affect request execution.
+ neo.fs.v2.session.RequestMetaHeader meta_header = 2;
+
+ // Carries request verification information. This header is used to
+ // authenticate the nodes of the message route and check the correctness of
+ // transmission.
+ neo.fs.v2.session.RequestVerificationHeader verify_header = 3;
+}
+
+// Object PATCH response
+message PatchResponse {
+ // PATCH response body
+ message Body {
+ // The object ID of the saved patched object.
+ neo.fs.v2.refs.ObjectID object_id = 1;
+ }
+
+ // Body for patch response message.
+ Body body = 1;
+
+ // Carries response meta information. Header data is used only to regulate
+ // message transport and does not affect request execution.
+ neo.fs.v2.session.ResponseMetaHeader meta_header = 2;
+
+ // Carries response verification information. This header is used to
+ // authenticate the nodes of the message route and check the correctness of
+ // transmission.
+ neo.fs.v2.session.ResponseVerificationHeader verify_header = 3;
+}
diff --git a/object/types.proto b/object/types.proto
new file mode 100644
index 0000000..62a6792
--- /dev/null
+++ b/object/types.proto
@@ -0,0 +1,279 @@
+edition = "2023";
+
+package neo.fs.v2.object;
+
+option go_package = "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object/grpc;object";
+option csharp_namespace = "Neo.FileStorage.API.Object";
+
+import "refs/types.proto";
+import "session/types.proto";
+
+// Type of the object payload content. Only `REGULAR` type objects can be split,
+// hence `TOMBSTONE` and `LOCK` payload is limited by the
+// maximum object size.
+//
+// String presentation of object type is the same as definition:
+// * REGULAR
+// * TOMBSTONE
+// * LOCK
+enum ObjectType {
+ // Just a normal object
+ REGULAR = 0;
+
+ // Used internally to identify deleted objects
+ TOMBSTONE = 1;
+
+ // Unused (previously storageGroup information)
+ // _ = 2;
+
+ // Object lock
+ LOCK = 3;
+}
+
+// Type of match expression
+enum MatchType {
+ // Unknown. Not used
+ MATCH_TYPE_UNSPECIFIED = 0;
+
+ // Full string match
+ STRING_EQUAL = 1;
+
+ // Full string mismatch
+ STRING_NOT_EQUAL = 2;
+
+ // Lack of key
+ NOT_PRESENT = 3;
+
+ // String prefix match
+ COMMON_PREFIX = 4;
+}
+
+// Short header fields
+message ShortHeader {
+ // Object format version. Effectively, the version of API library used to
+ // create particular object.
+ neo.fs.v2.refs.Version version = 1 [ json_name = "version" ];
+
+ // Epoch when the object was created
+ uint64 creation_epoch = 2 [ json_name = "creationEpoch" ];
+
+ // Object's owner
+ neo.fs.v2.refs.OwnerID owner_id = 3 [ json_name = "ownerID" ];
+
+ // Type of the object payload content
+ ObjectType object_type = 4 [ json_name = "objectType" ];
+
+ // Size of payload in bytes.
+ // `0xFFFFFFFFFFFFFFFF` means `payload_length` is unknown
+ uint64 payload_length = 5 [ json_name = "payloadLength" ];
+
+ // Hash of payload bytes
+ neo.fs.v2.refs.Checksum payload_hash = 6 [ json_name = "payloadHash" ];
+
+ // Homomorphic hash of the object payload
+ neo.fs.v2.refs.Checksum homomorphic_hash = 7
+ [ json_name = "homomorphicHash" ];
+}
+
+// Object Header
+message Header {
+ // Object format version. Effectively, the version of API library used to
+ // create particular object
+ neo.fs.v2.refs.Version version = 1 [ json_name = "version" ];
+
+ // Object's container
+ neo.fs.v2.refs.ContainerID container_id = 2 [ json_name = "containerID" ];
+
+ // Object's owner
+ neo.fs.v2.refs.OwnerID owner_id = 3 [ json_name = "ownerID" ];
+
+ // Object creation Epoch
+ uint64 creation_epoch = 4 [ json_name = "creationEpoch" ];
+
+ // Size of payload in bytes.
+ // `0xFFFFFFFFFFFFFFFF` means `payload_length` is unknown.
+ uint64 payload_length = 5 [ json_name = "payloadLength" ];
+
+ // Hash of payload bytes
+ neo.fs.v2.refs.Checksum payload_hash = 6 [ json_name = "payloadHash" ];
+
+ // Type of the object payload content
+ ObjectType object_type = 7 [ json_name = "objectType" ];
+
+ // Homomorphic hash of the object payload
+ neo.fs.v2.refs.Checksum homomorphic_hash = 8
+ [ json_name = "homomorphicHash" ];
+
+ // Session token, if it was used during Object creation. Need it to verify
+ // integrity and authenticity out of Request scope.
+ neo.fs.v2.session.SessionToken session_token = 9
+ [ json_name = "sessionToken" ];
+
+ // `Attribute` is a user-defined Key-Value metadata pair attached to an
+ // object.
+ //
+ // Key name must be an object-unique valid UTF-8 string. Value can't be empty.
+ // Objects with duplicated attribute names or attributes with empty values
+ // will be considered invalid.
+ //
+ // There are some "well-known" attributes starting with `__SYSTEM__`
+ // (`__NEOFS__` is deprecated) prefix that affect system behaviour:
+ //
+ // * [ __SYSTEM__UPLOAD_ID ] \
+ // (`__NEOFS__UPLOAD_ID` is deprecated) \
+ // Marks smaller parts of a split bigger object
+ // * [ __SYSTEM__EXPIRATION_EPOCH ] \
+ // (`__NEOFS__EXPIRATION_EPOCH` is deprecated) \
+ // The epoch after which object with no LOCKs on it becomes unavailable.
+ // Locked object continues to be available until each of the LOCKs expire.
+ // * [ __SYSTEM__TICK_EPOCH ] \
+ // (`__NEOFS__TICK_EPOCH` is deprecated) \
+ // Decimal number that defines what epoch must produce
+ // object notification with UTF-8 object address in a
+ // body (`0` value produces notification right after
+ // object put)
+ // * [ __SYSTEM__TICK_TOPIC ] \
+ // (`__NEOFS__TICK_TOPIC` is deprecated) \
+ // UTF-8 string topic ID that is used for object notification
+ //
+ // And some well-known attributes used by applications only:
+ //
+ // * Name \
+ // Human-friendly name
+ // * FileName \
+ // File name to be associated with the object on saving. FileName must not
+ // contain the delimiting symbol '/'.
+ // * FilePath \
+ // Full path to be associated with the object on saving. Should start with a
+ // '/' and use '/' as a delimiting symbol. Trailing '/' should be
+ // interpreted as a virtual directory marker. If an object has conflicting
+ // FilePath and FileName, FilePath should have higher priority, because it
+ // is used to construct the directory tree. FilePath with trailing '/' and
+ // non-empty FileName attribute should not be used together.
+ // * Timestamp \
+ // User-defined local time of object creation in Unix Timestamp format
+ // * Content-Type \
+ // MIME Content Type of object's payload
+ //
+ // For detailed description of each well-known attribute please see the
+ // corresponding section in FrostFS Technical Specification.
+ message Attribute {
+ // string key to the object attribute
+ string key = 1 [ json_name = "key" ];
+ // string value of the object attribute
+ string value = 2 [ json_name = "value" ];
+ }
+ // User-defined object attributes
+ repeated Attribute attributes = 10 [ json_name = "attributes" ];
+
+ // Bigger objects can be split into a chain of smaller objects. Information
+ // about inter-dependencies between spawned objects and how to re-construct
+ // the original one is in the `Split` headers. Parent and children objects
+ // must be within the same container.
+ message Split {
+ // Identifier of the origin object. Known only to the minor child.
+ neo.fs.v2.refs.ObjectID parent = 1 [ json_name = "parent" ];
+
+ // Identifier of the left split neighbor
+ neo.fs.v2.refs.ObjectID previous = 2 [ json_name = "previous" ];
+
+ // `signature` field of the parent object. Used to reconstruct parent.
+ neo.fs.v2.refs.Signature parent_signature = 3
+ [ json_name = "parentSignature" ];
+
+ // `header` field of the parent object. Used to reconstruct parent.
+ Header parent_header = 4 [ json_name = "parentHeader" ];
+
+ // List of identifiers of the objects generated by splitting current one.
+ repeated neo.fs.v2.refs.ObjectID children = 5 [ json_name = "children" ];
+
+ // 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" ];
+ }
+ // Position of the object in the split hierarchy
+ Split split = 11 [ json_name = "split" ];
+
+ // Erasure code can be applied to any object.
+ // Information about encoded object structure is stored in `EC` header.
+ // All objects belonging to a single EC group have the same `parent` field.
+ message EC {
+ // Identifier of the origin object. Known to all chunks.
+ neo.fs.v2.refs.ObjectID parent = 1 [ json_name = "parent" ];
+ // Index of this chunk.
+ uint32 index = 2 [ json_name = "index" ];
+ // Total number of chunks in this split.
+ uint32 total = 3 [ json_name = "total" ];
+ // Total length of a parent header. Used to trim padding zeroes.
+ uint32 header_length = 4 [ json_name = "headerLength" ];
+ // Chunk of a parent header.
+ bytes header = 5 [ json_name = "header" ];
+ // As the origin object is EC-splitted its identifier is known to all
+ // chunks as parent. But parent itself can be a part of Split (does not
+ // relate to EC-split). In this case parent_split_id should be set.
+ bytes parent_split_id = 6 [ json_name = "parentSplitID" ];
+ // EC-parent's parent ID. parent_split_parent_id is set if EC-parent,
+ // itself, is a part of Split and if an object ID of its parent is
+ // presented. The field allows to determine how EC-chunk is placed in Split
+ // hierarchy.
+ neo.fs.v2.refs.ObjectID parent_split_parent_id = 7
+ [ json_name = "parentSplitParentID" ];
+ // EC parent's attributes.
+ repeated Attribute parent_attributes = 8 [ json_name = "parentAttributes" ];
+ }
+ // Erasure code chunk information.
+ EC ec = 12 [ json_name = "ec" ];
+}
+
+// Object structure. Object is immutable and content-addressed. It means
+// `ObjectID` will change if the header or the payload changes. It's calculated
+// as a hash of header field which contains hash of the object's payload.
+//
+// For non-regular object types payload format depends on object type specified
+// in the header.
+message Object {
+ // Object's unique identifier.
+ neo.fs.v2.refs.ObjectID object_id = 1 [ json_name = "objectID" ];
+
+ // Signed object_id
+ neo.fs.v2.refs.Signature signature = 2 [ json_name = "signature" ];
+
+ // Object metadata headers
+ Header header = 3 [ json_name = "header" ];
+
+ // Payload bytes
+ bytes payload = 4 [ json_name = "payload" ];
+}
+
+// Meta information of split hierarchy for object assembly. With the last part
+// one can traverse linked list of split hierarchy back to the first part and
+// assemble the original object. With a linking object one can assemble an
+// object right from the object parts.
+message SplitInfo {
+ // 16 byte UUID used to identify the split object hierarchy parts.
+ bytes split_id = 1;
+
+ // The identifier of the last object in split hierarchy parts. It contains
+ // split header with the original object header.
+ neo.fs.v2.refs.ObjectID last_part = 2;
+
+ // 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.
+ neo.fs.v2.refs.ObjectID link = 3;
+}
+
+// Meta information for the erasure-encoded object.
+message ECInfo {
+ message Chunk {
+ // Object ID of the chunk.
+ neo.fs.v2.refs.ObjectID id = 1;
+ // Index of the chunk.
+ uint32 index = 2;
+ // Total number of chunks in this split.
+ uint32 total = 3;
+ }
+ // Chunk stored on the node.
+ repeated Chunk chunks = 1;
+}
diff --git a/proto-docs/accounting.md b/proto-docs/accounting.md
new file mode 100644
index 0000000..a8bfd16
--- /dev/null
+++ b/proto-docs/accounting.md
@@ -0,0 +1,172 @@
+# Protocol Documentation
+
+
+## Table of Contents
+
+- [accounting/service.proto](#accounting/service.proto)
+ - Services
+ - [AccountingService](#neo.fs.v2.accounting.AccountingService)
+
+ - Messages
+ - [BalanceRequest](#neo.fs.v2.accounting.BalanceRequest)
+ - [BalanceRequest.Body](#neo.fs.v2.accounting.BalanceRequest.Body)
+ - [BalanceResponse](#neo.fs.v2.accounting.BalanceResponse)
+ - [BalanceResponse.Body](#neo.fs.v2.accounting.BalanceResponse.Body)
+
+
+- [accounting/types.proto](#accounting/types.proto)
+
+ - Messages
+ - [Decimal](#neo.fs.v2.accounting.Decimal)
+
+
+- [Scalar Value Types](#scalar-value-types)
+
+
+
+
+
+
+## accounting/service.proto
+
+
+
+
+
+
+### Service "neo.fs.v2.accounting.AccountingService"
+Accounting service provides methods for interaction with FrostFS sidechain
+via other FrostFS nodes to get information about the account balance. Deposit
+and Withdraw operations can't be implemented here, as they require Mainnet
+FrostFS smart contract invocation. Transfer operations between internal
+FrostFS accounts are possible if both use the same token type.
+
+```
+rpc Balance(BalanceRequest) returns (BalanceResponse);
+
+```
+
+#### Method Balance
+
+Returns the amount of funds in GAS token for the requested FrostFS account.
+
+Statuses:
+- **OK** (0, SECTION_SUCCESS):
+balance has been successfully read;
+- Common failures (SECTION_FAILURE_COMMON).
+
+| Name | Input | Output |
+| ---- | ----- | ------ |
+| Balance | [BalanceRequest](#neo.fs.v2.accounting.BalanceRequest) | [BalanceResponse](#neo.fs.v2.accounting.BalanceResponse) |
+
+
+
+
+
+### Message BalanceRequest
+BalanceRequest message
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| body | [BalanceRequest.Body](#neo.fs.v2.accounting.BalanceRequest.Body) | | Body of the balance request message. |
+| meta_header | [neo.fs.v2.session.RequestMetaHeader](#neo.fs.v2.session.RequestMetaHeader) | | Carries request meta information. Header data is used only to regulate message transport and does not affect request execution. |
+| verify_header | [neo.fs.v2.session.RequestVerificationHeader](#neo.fs.v2.session.RequestVerificationHeader) | | Carries request verification information. This header is used to authenticate the nodes of the message route and check the correctness of transmission. |
+
+
+
+
+### Message BalanceRequest.Body
+To indicate the account for which the balance is requested, its identifier
+is used. It can be any existing account in FrostFS sidechain `Balance`
+smart contract. If omitted, client implementation MUST set it to the
+request's signer `OwnerID`.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| owner_id | [neo.fs.v2.refs.OwnerID](#neo.fs.v2.refs.OwnerID) | | Valid user identifier in `OwnerID` format for which the balance is requested. Required field. |
+
+
+
+
+### Message BalanceResponse
+BalanceResponse message
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| body | [BalanceResponse.Body](#neo.fs.v2.accounting.BalanceResponse.Body) | | Body of the balance response message. |
+| meta_header | [neo.fs.v2.session.ResponseMetaHeader](#neo.fs.v2.session.ResponseMetaHeader) | | Carries response meta information. Header data is used only to regulate message transport and does not affect request execution. |
+| verify_header | [neo.fs.v2.session.ResponseVerificationHeader](#neo.fs.v2.session.ResponseVerificationHeader) | | Carries response verification information. This header is used to authenticate the nodes of the message route and check the correctness of transmission. |
+
+
+
+
+### Message BalanceResponse.Body
+The amount of funds in GAS token for the `OwnerID`'s account requested.
+Balance is given in the `Decimal` format to avoid precision issues with
+rounding.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| balance | [Decimal](#neo.fs.v2.accounting.Decimal) | | Amount of funds in GAS token for the requested account. |
+
+
+
+
+
+
+
+
+
+
+## accounting/types.proto
+
+
+
+
+
+
+
+### Message Decimal
+Standard floating point data type can't be used in FrostFS due to inexactness
+of the result when doing lots of small number operations. To solve the lost
+precision issue, special `Decimal` format is used for monetary computations.
+
+Please see [The General Decimal Arithmetic
+Specification](http://speleotrove.com/decimal/) for detailed problem
+description.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| value | [int64](#int64) | | Number in the smallest Token fractions. |
+| precision | [uint32](#uint32) | | Precision value indicating how many smallest fractions can be in one integer. |
+
+
+
+
+
+
+
+## Scalar Value Types
+
+| .proto Type | Notes | C++ Type | Java Type | Python Type |
+| ----------- | ----- | -------- | --------- | ----------- |
+| double | | double | double | float |
+| float | | float | float | float |
+| 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 |
+| 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 |
+| uint32 | Uses variable-length encoding. | uint32 | int | int/long |
+| uint64 | Uses variable-length encoding. | uint64 | long | int/long |
+| sint32 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s. | int32 | int | int |
+| sint64 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s. | int64 | long | int/long |
+| fixed32 | Always four bytes. More efficient than uint32 if values are often greater than 2^28. | uint32 | int | int |
+| fixed64 | Always eight bytes. More efficient than uint64 if values are often greater than 2^56. | uint64 | long | int/long |
+| sfixed32 | Always four bytes. | int32 | int | int |
+| sfixed64 | Always eight bytes. | int64 | long | int/long |
+| bool | | bool | boolean | boolean |
+| string | A string must always contain UTF-8 encoded or 7-bit ASCII text. | string | String | str/unicode |
+| bytes | May contain any arbitrary sequence of bytes. | string | ByteString | str |
diff --git a/proto-docs/acl.md b/proto-docs/acl.md
new file mode 100644
index 0000000..fdc7ade
--- /dev/null
+++ b/proto-docs/acl.md
@@ -0,0 +1,285 @@
+# Protocol Documentation
+
+
+## Table of Contents
+
+- [acl/types.proto](#acl/types.proto)
+
+ - Messages
+ - [BearerToken](#neo.fs.v2.acl.BearerToken)
+ - [BearerToken.Body](#neo.fs.v2.acl.BearerToken.Body)
+ - [BearerToken.Body.APEOverride](#neo.fs.v2.acl.BearerToken.Body.APEOverride)
+ - [BearerToken.Body.TokenLifetime](#neo.fs.v2.acl.BearerToken.Body.TokenLifetime)
+ - [EACLRecord](#neo.fs.v2.acl.EACLRecord)
+ - [EACLRecord.Filter](#neo.fs.v2.acl.EACLRecord.Filter)
+ - [EACLRecord.Target](#neo.fs.v2.acl.EACLRecord.Target)
+ - [EACLTable](#neo.fs.v2.acl.EACLTable)
+
+
+- [Scalar Value Types](#scalar-value-types)
+
+
+
+
+
+
+## acl/types.proto
+
+
+
+
+
+
+
+### Message BearerToken
+BearerToken allows to attach signed Extended ACL rules to the request in
+`RequestMetaHeader`. If container's Basic ACL rules allow, the attached rule
+set will be checked instead of one attached to the container itself. Just
+like [JWT](https://jwt.io), it has a limited lifetime and scope, hence can be
+used in the similar use cases, like providing authorisation to externally
+authenticated party.
+
+BearerToken can be issued only by the container's owner and must be signed
+using the key associated with the container's `OwnerID`.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| body | [BearerToken.Body](#neo.fs.v2.acl.BearerToken.Body) | | Bearer Token body |
+| signature | [neo.fs.v2.refs.Signature](#neo.fs.v2.refs.Signature) | | Signature of BearerToken body |
+
+
+
+
+### Message BearerToken.Body
+Bearer Token body structure contains Extended ACL table issued by the
+container owner with additional information preventing token abuse.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| eacl_table | [EACLTable](#neo.fs.v2.acl.EACLTable) | | Table of Extended ACL rules to use instead of the ones attached to the container. If it contains `container_id` field, bearer token is only valid for this specific container. Otherwise, any container of the same owner is allowed.
+
+Deprecated: eACL tables are no longer relevant - `APEOverrides` should be used instead. |
+| owner_id | [neo.fs.v2.refs.OwnerID](#neo.fs.v2.refs.OwnerID) | | `OwnerID` defines to whom the token was issued. It must match the request originator's `OwnerID`. If empty, any token bearer will be accepted. |
+| lifetime | [BearerToken.Body.TokenLifetime](#neo.fs.v2.acl.BearerToken.Body.TokenLifetime) | | Token expiration and valid time period parameters |
+| allow_impersonate | [bool](#bool) | | AllowImpersonate flag to consider token signer as request owner. If this field is true extended ACL table in token body isn't processed. |
+| ape_override | [BearerToken.Body.APEOverride](#neo.fs.v2.acl.BearerToken.Body.APEOverride) | | APE override for the target. |
+
+
+
+
+### Message BearerToken.Body.APEOverride
+APEOverride is the list of APE chains defined for a target.
+These chains are meant to serve as overrides to the already defined (or
+even undefined) APE chains for the target (see contract `Policy`).
+
+The server-side processing of the bearer token with set APE overrides
+must verify if a client is permitted to override chains for the target,
+preventing unauthorized access through the APE mechanism.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| target | [frostfs.v2.ape.ChainTarget](#frostfs.v2.ape.ChainTarget) | | Target for which chains are applied. |
+| chains | [frostfs.v2.ape.Chain](#frostfs.v2.ape.Chain) | repeated | The list of APE chains. |
+
+
+
+
+### Message BearerToken.Body.TokenLifetime
+Lifetime parameters of the token. Field names taken from
+[rfc7519](https://tools.ietf.org/html/rfc7519).
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| exp | [uint64](#uint64) | | Expiration Epoch |
+| nbf | [uint64](#uint64) | | Not valid before Epoch |
+| iat | [uint64](#uint64) | | Issued at Epoch |
+
+
+
+
+### Message EACLRecord
+Describes a single eACL rule.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| operation | [Operation](#neo.fs.v2.acl.Operation) | | FrostFS request Verb to match |
+| action | [Action](#neo.fs.v2.acl.Action) | | Rule execution result. Either allows or denies access if filters match. |
+| filters | [EACLRecord.Filter](#neo.fs.v2.acl.EACLRecord.Filter) | repeated | List of filters to match and see if rule is applicable |
+| targets | [EACLRecord.Target](#neo.fs.v2.acl.EACLRecord.Target) | repeated | List of target subjects to apply ACL rule to |
+
+
+
+
+### Message EACLRecord.Filter
+Filter to check particular properties of the request or the object.
+
+By default `key` field refers to the corresponding object's `Attribute`.
+Some Object's header fields can also be accessed by adding `$Object:`
+prefix to the name. Here is the list of fields available via this prefix:
+
+* $Object:version \
+ version
+* $Object:objectID \
+ object_id
+* $Object:containerID \
+ container_id
+* $Object:ownerID \
+ owner_id
+* $Object:creationEpoch \
+ creation_epoch
+* $Object:payloadLength \
+ payload_length
+* $Object:payloadHash \
+ payload_hash
+* $Object:objectType \
+ object_type
+* $Object:homomorphicHash \
+ homomorphic_hash
+
+Please note, that if request or response does not have object's headers of
+full object (Range, RangeHash, Search, Delete), it will not be possible to
+filter by object header fields or user attributes. From the well-known list
+only `$Object:objectID` and `$Object:containerID` will be available, as
+it's possible to take that information from the requested address.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| header_type | [HeaderType](#neo.fs.v2.acl.HeaderType) | | Define if Object or Request header will be used |
+| match_type | [MatchType](#neo.fs.v2.acl.MatchType) | | Match operation type |
+| key | [string](#string) | | Name of the Header to use |
+| value | [string](#string) | | Expected Header Value or pattern to match |
+
+
+
+
+### Message EACLRecord.Target
+Target to apply ACL rule. Can be a subject's role class or a list of public
+keys to match.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| role | [Role](#neo.fs.v2.acl.Role) | | Target subject's role class |
+| keys | [bytes](#bytes) | repeated | List of public keys to identify target subject |
+
+
+
+
+### Message EACLTable
+Extended ACL rules table. A list of ACL rules defined additionally to Basic
+ACL. Extended ACL rules can be attached to a container and can be updated
+or may be defined in `BearerToken` structure. Please see the corresponding
+FrostFS Technical Specification section for detailed description.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| version | [neo.fs.v2.refs.Version](#neo.fs.v2.refs.Version) | | eACL format version. Effectively, the version of API library used to create eACL Table. |
+| container_id | [neo.fs.v2.refs.ContainerID](#neo.fs.v2.refs.ContainerID) | | Identifier of the container that should use given access control rules |
+| records | [EACLRecord](#neo.fs.v2.acl.EACLRecord) | repeated | List of Extended ACL rules |
+
+
+
+
+
+
+### Action
+Rule execution result action. Either allows or denies access if the rule's
+filters match.
+
+| Name | Number | Description |
+| ---- | ------ | ----------- |
+| ACTION_UNSPECIFIED | 0 | Unspecified action, default value |
+| ALLOW | 1 | Allow action |
+| DENY | 2 | Deny action |
+
+
+
+
+
+### HeaderType
+Enumeration of possible sources of Headers to apply filters.
+
+| Name | Number | Description |
+| ---- | ------ | ----------- |
+| HEADER_UNSPECIFIED | 0 | Unspecified header, default value. |
+| REQUEST | 1 | Filter request headers |
+| OBJECT | 2 | Filter object headers |
+| SERVICE | 3 | Filter service headers. These are not processed by FrostFS nodes and exist for service use only. |
+
+
+
+
+
+### MatchType
+MatchType is an enumeration of match types.
+
+| Name | Number | Description |
+| ---- | ------ | ----------- |
+| MATCH_TYPE_UNSPECIFIED | 0 | Unspecified match type, default value. |
+| STRING_EQUAL | 1 | Return true if strings are equal |
+| STRING_NOT_EQUAL | 2 | Return true if strings are different |
+
+
+
+
+
+### Operation
+Request's operation type to match if the rule is applicable to a particular
+request.
+
+| Name | Number | Description |
+| ---- | ------ | ----------- |
+| OPERATION_UNSPECIFIED | 0 | Unspecified operation, default value |
+| GET | 1 | Get |
+| HEAD | 2 | Head |
+| PUT | 3 | Put |
+| DELETE | 4 | Delete |
+| SEARCH | 5 | Search |
+| GETRANGE | 6 | GetRange |
+| GETRANGEHASH | 7 | GetRangeHash |
+
+
+
+
+
+### Role
+Target role of the access control rule in access control list.
+
+| Name | Number | Description |
+| ---- | ------ | ----------- |
+| ROLE_UNSPECIFIED | 0 | Unspecified role, default value |
+| USER | 1 | User target rule is applied if sender is the owner of the container |
+| SYSTEM | 2 | System target rule is applied if sender is a storage node within the container or an inner ring node |
+| OTHERS | 3 | Others target rule is applied if sender is neither a user nor a system target |
+
+
+
+
+
+
+## Scalar Value Types
+
+| .proto Type | Notes | C++ Type | Java Type | Python Type |
+| ----------- | ----- | -------- | --------- | ----------- |
+| double | | double | double | float |
+| float | | float | float | float |
+| 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 |
+| 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 |
+| uint32 | Uses variable-length encoding. | uint32 | int | int/long |
+| uint64 | Uses variable-length encoding. | uint64 | long | int/long |
+| sint32 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s. | int32 | int | int |
+| sint64 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s. | int64 | long | int/long |
+| fixed32 | Always four bytes. More efficient than uint32 if values are often greater than 2^28. | uint32 | int | int |
+| fixed64 | Always eight bytes. More efficient than uint64 if values are often greater than 2^56. | uint64 | long | int/long |
+| sfixed32 | Always four bytes. | int32 | int | int |
+| sfixed64 | Always eight bytes. | int64 | long | int/long |
+| bool | | bool | boolean | boolean |
+| string | A string must always contain UTF-8 encoded or 7-bit ASCII text. | string | String | str/unicode |
+| bytes | May contain any arbitrary sequence of bytes. | string | ByteString | str |
diff --git a/proto-docs/ape.md b/proto-docs/ape.md
new file mode 100644
index 0000000..9795bc5
--- /dev/null
+++ b/proto-docs/ape.md
@@ -0,0 +1,87 @@
+# Protocol Documentation
+
+
+## Table of Contents
+
+- [ape/types.proto](#ape/types.proto)
+
+ - Messages
+ - [Chain](#frostfs.v2.ape.Chain)
+ - [ChainTarget](#frostfs.v2.ape.ChainTarget)
+
+
+- [Scalar Value Types](#scalar-value-types)
+
+
+
+
+
+
+## apemanager/service.proto
+
+
+
+
+
+
+### Service "frostfs.v2.apemanager.APEManagerService"
+`APEManagerService` provides API to manage rule chains within sidechain's
+`Policy` smart contract.
+
+```
+rpc AddChain(AddChainRequest) returns (AddChainResponse);
+rpc RemoveChain(RemoveChainRequest) returns (RemoveChainResponse);
+rpc ListChains(ListChainsRequest) returns (ListChainsResponse);
+
+```
+
+#### Method AddChain
+
+Add a rule chain for a specific target to `Policy` smart contract.
+
+Statuses:
+- **OK** (0, SECTION_SUCCESS): \
+ the chain has been successfully added;
+- Common failures (SECTION_FAILURE_COMMON);
+- **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \
+ container (as target) not found;
+- **APE_MANAGER_ACCESS_DENIED** (5120, SECTION_APE_MANAGER): \
+ the operation is denied by the service.
+
+| Name | Input | Output |
+| ---- | ----- | ------ |
+| AddChain | [AddChainRequest](#frostfs.v2.apemanager.AddChainRequest) | [AddChainResponse](#frostfs.v2.apemanager.AddChainResponse) |
+#### Method RemoveChain
+
+Remove a rule chain for a specific target from `Policy` smart contract.
+RemoveChain is an idempotent operation: removal of non-existing rule chain
+also means success.
+
+Statuses:
+- **OK** (0, SECTION_SUCCESS): \
+ the chain has been successfully removed;
+- Common failures (SECTION_FAILURE_COMMON);
+- **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \
+ container (as target) not found;
+- **APE_MANAGER_ACCESS_DENIED** (5120, SECTION_APE_MANAGER): \
+ the operation is denied by the service.
+
+| Name | Input | Output |
+| ---- | ----- | ------ |
+| RemoveChain | [RemoveChainRequest](#frostfs.v2.apemanager.RemoveChainRequest) | [RemoveChainResponse](#frostfs.v2.apemanager.RemoveChainResponse) |
+#### Method ListChains
+
+List chains defined for a specific target from `Policy` smart contract.
+
+Statuses:
+- **OK** (0, SECTION_SUCCESS): \
+ chains have been successfully listed;
+- Common failures (SECTION_FAILURE_COMMON);
+- **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \
+ container (as target) not found;
+- **APE_MANAGER_ACCESS_DENIED** (5120, SECTION_APE_MANAGER): \
+ the operation is denied by the service.
+
+| Name | Input | Output |
+| ---- | ----- | ------ |
+| ListChains | [ListChainsRequest](#frostfs.v2.apemanager.ListChainsRequest) | [ListChainsResponse](#frostfs.v2.apemanager.ListChainsResponse) |
+
+
+
+
+
+### Message AddChainRequest
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| body | [AddChainRequest.Body](#frostfs.v2.apemanager.AddChainRequest.Body) | | The request's body. |
+| meta_header | [neo.fs.v2.session.RequestMetaHeader](#neo.fs.v2.session.RequestMetaHeader) | | Carries request meta information. Header data is used only to regulate message transport and does not affect request execution. |
+| verify_header | [neo.fs.v2.session.RequestVerificationHeader](#neo.fs.v2.session.RequestVerificationHeader) | | Carries request verification information. This header is used to authenticate the nodes of the message route and check the correctness of transmission. |
+
+
+
+
+### Message AddChainRequest.Body
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| target | [frostfs.v2.ape.ChainTarget](#frostfs.v2.ape.ChainTarget) | | A target for which a rule chain is added. |
+| chain | [frostfs.v2.ape.Chain](#frostfs.v2.ape.Chain) | | The chain to set for the target. |
+
+
+
+
+### Message AddChainResponse
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| body | [AddChainResponse.Body](#frostfs.v2.apemanager.AddChainResponse.Body) | | The response's body. |
+| meta_header | [neo.fs.v2.session.ResponseMetaHeader](#neo.fs.v2.session.ResponseMetaHeader) | | Carries response meta information. Header data is used only to regulate message transport and does not affect request execution. |
+| verify_header | [neo.fs.v2.session.ResponseVerificationHeader](#neo.fs.v2.session.ResponseVerificationHeader) | | Carries response verification information. This header is used to authenticate the nodes of the message route and check the correctness of transmission. |
+
+
+
+
+### Message AddChainResponse.Body
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| chain_id | [bytes](#bytes) | | Chain ID assigned for the added rule chain. If chain ID is left empty in the request, then it will be generated. |
+
+
+
+
+### Message ListChainsRequest
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| body | [ListChainsRequest.Body](#frostfs.v2.apemanager.ListChainsRequest.Body) | | The request's body. |
+| meta_header | [neo.fs.v2.session.RequestMetaHeader](#neo.fs.v2.session.RequestMetaHeader) | | Carries request meta information. Header data is used only to regulate message transport and does not affect request execution. |
+| verify_header | [neo.fs.v2.session.RequestVerificationHeader](#neo.fs.v2.session.RequestVerificationHeader) | | Carries request verification information. This header is used to authenticate the nodes of the message route and check the correctness of transmission. |
+
+
+
+
+### Message ListChainsRequest.Body
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| target | [frostfs.v2.ape.ChainTarget](#frostfs.v2.ape.ChainTarget) | | Target for which rule chains are listed. |
+
+
+
+
+### Message ListChainsResponse
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| body | [ListChainsResponse.Body](#frostfs.v2.apemanager.ListChainsResponse.Body) | | The response's body. |
+| meta_header | [neo.fs.v2.session.ResponseMetaHeader](#neo.fs.v2.session.ResponseMetaHeader) | | Carries response meta information. Header data is used only to regulate message transport and does not affect request execution. |
+| verify_header | [neo.fs.v2.session.ResponseVerificationHeader](#neo.fs.v2.session.ResponseVerificationHeader) | | Carries response verification information. This header is used to authenticate the nodes of the message route and check the correctness of transmission. |
+
+
+
+
+### Message ListChainsResponse.Body
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| chains | [frostfs.v2.ape.Chain](#frostfs.v2.ape.Chain) | repeated | The list of chains defined for the reqeusted target. |
+
+
+
+
+### Message RemoveChainRequest
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| body | [RemoveChainRequest.Body](#frostfs.v2.apemanager.RemoveChainRequest.Body) | | The request's body. |
+| meta_header | [neo.fs.v2.session.RequestMetaHeader](#neo.fs.v2.session.RequestMetaHeader) | | Carries request meta information. Header data is used only to regulate message transport and does not affect request execution. |
+| verify_header | [neo.fs.v2.session.RequestVerificationHeader](#neo.fs.v2.session.RequestVerificationHeader) | | Carries request verification information. This header is used to authenticate the nodes of the message route and check the correctness of transmission. |
+
+
+
+
+### Message RemoveChainRequest.Body
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| target | [frostfs.v2.ape.ChainTarget](#frostfs.v2.ape.ChainTarget) | | Target for which a rule chain is removed. |
+| chain_id | [bytes](#bytes) | | Chain ID assigned for the rule chain. |
+
+
+
+
+### Message RemoveChainResponse
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| body | [RemoveChainResponse.Body](#frostfs.v2.apemanager.RemoveChainResponse.Body) | | The response's body. |
+| meta_header | [neo.fs.v2.session.ResponseMetaHeader](#neo.fs.v2.session.ResponseMetaHeader) | | Carries response meta information. Header data is used only to regulate message transport and does not affect request execution. |
+| verify_header | [neo.fs.v2.session.ResponseVerificationHeader](#neo.fs.v2.session.ResponseVerificationHeader) | | Carries response verification information. This header is used to authenticate the nodes of the message route and check the correctness of transmission. |
+
+
+
+
+### Message RemoveChainResponse.Body
+Since RemoveChain is an idempotent operation, then the only indicator that
+operation could not be performed is an error returning to a client.
+
+
+
+
+
+
+
+
+## Scalar Value Types
+
+| .proto Type | Notes | C++ Type | Java Type | Python Type |
+| ----------- | ----- | -------- | --------- | ----------- |
+| double | | double | double | float |
+| float | | float | float | float |
+| 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 |
+| 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 |
+| uint32 | Uses variable-length encoding. | uint32 | int | int/long |
+| uint64 | Uses variable-length encoding. | uint64 | long | int/long |
+| sint32 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s. | int32 | int | int |
+| sint64 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s. | int64 | long | int/long |
+| fixed32 | Always four bytes. More efficient than uint32 if values are often greater than 2^28. | uint32 | int | int |
+| fixed64 | Always eight bytes. More efficient than uint64 if values are often greater than 2^56. | uint64 | long | int/long |
+| sfixed32 | Always four bytes. | int32 | int | int |
+| sfixed64 | Always eight bytes. | int64 | long | int/long |
+| bool | | bool | boolean | boolean |
+| string | A string must always contain UTF-8 encoded or 7-bit ASCII text. | string | String | str/unicode |
+| bytes | May contain any arbitrary sequence of bytes. | string | ByteString | str |
diff --git a/proto-docs/container.md b/proto-docs/container.md
new file mode 100644
index 0000000..7ee5dab
--- /dev/null
+++ b/proto-docs/container.md
@@ -0,0 +1,503 @@
+# Protocol Documentation
+
+
+## Table of Contents
+
+- [container/service.proto](#container/service.proto)
+ - Services
+ - [ContainerService](#neo.fs.v2.container.ContainerService)
+
+ - Messages
+ - [DeleteRequest](#neo.fs.v2.container.DeleteRequest)
+ - [DeleteRequest.Body](#neo.fs.v2.container.DeleteRequest.Body)
+ - [DeleteResponse](#neo.fs.v2.container.DeleteResponse)
+ - [DeleteResponse.Body](#neo.fs.v2.container.DeleteResponse.Body)
+ - [GetRequest](#neo.fs.v2.container.GetRequest)
+ - [GetRequest.Body](#neo.fs.v2.container.GetRequest.Body)
+ - [GetResponse](#neo.fs.v2.container.GetResponse)
+ - [GetResponse.Body](#neo.fs.v2.container.GetResponse.Body)
+ - [ListRequest](#neo.fs.v2.container.ListRequest)
+ - [ListRequest.Body](#neo.fs.v2.container.ListRequest.Body)
+ - [ListResponse](#neo.fs.v2.container.ListResponse)
+ - [ListResponse.Body](#neo.fs.v2.container.ListResponse.Body)
+ - [ListStreamRequest](#neo.fs.v2.container.ListStreamRequest)
+ - [ListStreamRequest.Body](#neo.fs.v2.container.ListStreamRequest.Body)
+ - [ListStreamResponse](#neo.fs.v2.container.ListStreamResponse)
+ - [ListStreamResponse.Body](#neo.fs.v2.container.ListStreamResponse.Body)
+ - [PutRequest](#neo.fs.v2.container.PutRequest)
+ - [PutRequest.Body](#neo.fs.v2.container.PutRequest.Body)
+ - [PutResponse](#neo.fs.v2.container.PutResponse)
+ - [PutResponse.Body](#neo.fs.v2.container.PutResponse.Body)
+
+
+- [container/types.proto](#container/types.proto)
+
+ - Messages
+ - [Container](#neo.fs.v2.container.Container)
+ - [Container.Attribute](#neo.fs.v2.container.Container.Attribute)
+
+
+- [Scalar Value Types](#scalar-value-types)
+
+
+
+
+
+
+## container/service.proto
+
+
+
+
+
+
+### Service "neo.fs.v2.container.ContainerService"
+`ContainerService` provides API to interact with `Container` smart contract
+in FrostFS sidechain via other FrostFS nodes. All of those actions can be
+done equivalently by directly issuing transactions and RPC calls to sidechain
+nodes.
+
+```
+rpc Put(PutRequest) returns (PutResponse);
+rpc Delete(DeleteRequest) returns (DeleteResponse);
+rpc Get(GetRequest) returns (GetResponse);
+rpc List(ListRequest) returns (ListResponse);
+rpc ListStream(ListStreamRequest) returns (stream ListStreamResponse);
+
+```
+
+#### Method Put
+
+`Put` invokes `Container` smart contract's `Put` method and returns
+response immediately. After a new block is issued in sidechain, request is
+verified by Inner Ring nodes. After one more block in sidechain, the
+container is added into smart contract storage.
+
+Statuses:
+- **OK** (0, SECTION_SUCCESS): \
+ request to save the container has been sent to the sidechain;
+- Common failures (SECTION_FAILURE_COMMON);
+- **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \
+ container create access denied.
+
+| Name | Input | Output |
+| ---- | ----- | ------ |
+| Put | [PutRequest](#neo.fs.v2.container.PutRequest) | [PutResponse](#neo.fs.v2.container.PutResponse) |
+#### Method Delete
+
+`Delete` invokes `Container` smart contract's `Delete` method and returns
+response immediately. After a new block is issued in sidechain, request is
+verified by Inner Ring nodes. After one more block in sidechain, the
+container is added into smart contract storage.
+
+Statuses:
+- **OK** (0, SECTION_SUCCESS): \
+ request to remove the container has been sent to the sidechain;
+- Common failures (SECTION_FAILURE_COMMON);
+- **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \
+ container delete access denied.
+
+| Name | Input | Output |
+| ---- | ----- | ------ |
+| Delete | [DeleteRequest](#neo.fs.v2.container.DeleteRequest) | [DeleteResponse](#neo.fs.v2.container.DeleteResponse) |
+#### Method Get
+
+Returns container structure from `Container` smart contract storage.
+
+Statuses:
+- **OK** (0, SECTION_SUCCESS): \
+ container has been successfully read;
+- Common failures (SECTION_FAILURE_COMMON);
+- **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \
+ requested container not found;
+- **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \
+ access to container is denied.
+
+| Name | Input | Output |
+| ---- | ----- | ------ |
+| Get | [GetRequest](#neo.fs.v2.container.GetRequest) | [GetResponse](#neo.fs.v2.container.GetResponse) |
+#### Method List
+
+Returns all owner's containers from `Container` smart contract storage.
+
+Statuses:
+- **OK** (0, SECTION_SUCCESS): \
+ container list has been successfully read;
+- Common failures (SECTION_FAILURE_COMMON);
+- **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \
+ container list access denied.
+
+| Name | Input | Output |
+| ---- | ----- | ------ |
+| List | [ListRequest](#neo.fs.v2.container.ListRequest) | [ListResponse](#neo.fs.v2.container.ListResponse) |
+#### Method ListStream
+
+Returns all owner's containers from `Container` smart contract storage
+via stream.
+
+Statuses:
+- **OK** (0, SECTION_SUCCESS): \
+ container list has been successfully read;
+- Common failures (SECTION_FAILURE_COMMON);
+- **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \
+ container list access denied.
+
+| Name | Input | Output |
+| ---- | ----- | ------ |
+| ListStream | [ListStreamRequest](#neo.fs.v2.container.ListStreamRequest) | [ListStreamResponse](#neo.fs.v2.container.ListStreamResponse) |
+
+
+
+
+
+### Message DeleteRequest
+Container removal request
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| body | [DeleteRequest.Body](#neo.fs.v2.container.DeleteRequest.Body) | | Body of container delete request message. |
+| meta_header | [neo.fs.v2.session.RequestMetaHeader](#neo.fs.v2.session.RequestMetaHeader) | | Carries request meta information. Header data is used only to regulate message transport and does not affect request execution. |
+| verify_header | [neo.fs.v2.session.RequestVerificationHeader](#neo.fs.v2.session.RequestVerificationHeader) | | Carries request verification information. This header is used to authenticate the nodes of the message route and check the correctness of transmission. |
+
+
+
+
+### Message DeleteRequest.Body
+Container removal request body has signed `ContainerID` as a proof of
+the container owner's intent. The signature will be verified by `Container`
+smart contract, so signing algorithm must be supported by NeoVM.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| container_id | [neo.fs.v2.refs.ContainerID](#neo.fs.v2.refs.ContainerID) | | Identifier of the container to delete from FrostFS |
+| signature | [neo.fs.v2.refs.SignatureRFC6979](#neo.fs.v2.refs.SignatureRFC6979) | | `ContainerID` signed with the container owner's key according to RFC-6979. |
+
+
+
+
+### Message DeleteResponse
+`DeleteResponse` has an empty body because delete operation is asynchronous
+and done via consensus in Inner Ring nodes.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| body | [DeleteResponse.Body](#neo.fs.v2.container.DeleteResponse.Body) | | Body of container delete response message. |
+| meta_header | [neo.fs.v2.session.ResponseMetaHeader](#neo.fs.v2.session.ResponseMetaHeader) | | Carries response meta information. Header data is used only to regulate message transport and does not affect request execution. |
+| verify_header | [neo.fs.v2.session.ResponseVerificationHeader](#neo.fs.v2.session.ResponseVerificationHeader) | | Carries response verification information. This header is used to authenticate the nodes of the message route and check the correctness of transmission. |
+
+
+
+
+### Message DeleteResponse.Body
+`DeleteResponse` has an empty body because delete operation is asynchronous
+and done via consensus in Inner Ring nodes.
+
+
+
+
+
+### Message GetRequest
+Get container structure
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| body | [GetRequest.Body](#neo.fs.v2.container.GetRequest.Body) | | Body of container get request message. |
+| meta_header | [neo.fs.v2.session.RequestMetaHeader](#neo.fs.v2.session.RequestMetaHeader) | | Carries request meta information. Header data is used only to regulate message transport and does not affect request execution. |
+| verify_header | [neo.fs.v2.session.RequestVerificationHeader](#neo.fs.v2.session.RequestVerificationHeader) | | Carries request verification information. This header is used to authenticate the nodes of the message route and check the correctness of transmission. |
+
+
+
+
+### Message GetRequest.Body
+Get container structure request body.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| container_id | [neo.fs.v2.refs.ContainerID](#neo.fs.v2.refs.ContainerID) | | Identifier of the container to get |
+
+
+
+
+### Message GetResponse
+Get container structure
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| body | [GetResponse.Body](#neo.fs.v2.container.GetResponse.Body) | | Body of container get response message. |
+| meta_header | [neo.fs.v2.session.ResponseMetaHeader](#neo.fs.v2.session.ResponseMetaHeader) | | Carries response meta information. Header data is used only to regulate message transport and does not affect request execution. |
+| verify_header | [neo.fs.v2.session.ResponseVerificationHeader](#neo.fs.v2.session.ResponseVerificationHeader) | | Carries response verification information. This header is used to authenticate the nodes of the message route and check the correctness of transmission. |
+
+
+
+
+### Message GetResponse.Body
+Get container response body does not have container structure signature. It
+has been already verified upon container creation.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| container | [Container](#neo.fs.v2.container.Container) | | Requested container structure |
+| signature | [neo.fs.v2.refs.SignatureRFC6979](#neo.fs.v2.refs.SignatureRFC6979) | | Signature of a stable-marshalled container according to RFC-6979. |
+| session_token | [neo.fs.v2.session.SessionToken](#neo.fs.v2.session.SessionToken) | | Session token if the container has been created within the session |
+
+
+
+
+### Message ListRequest
+List containers
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| body | [ListRequest.Body](#neo.fs.v2.container.ListRequest.Body) | | Body of list containers request message |
+| meta_header | [neo.fs.v2.session.RequestMetaHeader](#neo.fs.v2.session.RequestMetaHeader) | | Carries request meta information. Header data is used only to regulate message transport and does not affect request execution. |
+| verify_header | [neo.fs.v2.session.RequestVerificationHeader](#neo.fs.v2.session.RequestVerificationHeader) | | Carries request verification information. This header is used to authenticate the nodes of the message route and check the correctness of transmission. |
+
+
+
+
+### Message ListRequest.Body
+List containers request body.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| owner_id | [neo.fs.v2.refs.OwnerID](#neo.fs.v2.refs.OwnerID) | | Identifier of the container owner |
+
+
+
+
+### Message ListResponse
+List containers
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| body | [ListResponse.Body](#neo.fs.v2.container.ListResponse.Body) | | Body of list containers response message. |
+| meta_header | [neo.fs.v2.session.ResponseMetaHeader](#neo.fs.v2.session.ResponseMetaHeader) | | Carries response meta information. Header data is used only to regulate message transport and does not affect request execution. |
+| verify_header | [neo.fs.v2.session.ResponseVerificationHeader](#neo.fs.v2.session.ResponseVerificationHeader) | | Carries response verification information. This header is used to authenticate the nodes of the message route and check the correctness of transmission. |
+
+
+
+
+### Message ListResponse.Body
+List containers response body.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| container_ids | [neo.fs.v2.refs.ContainerID](#neo.fs.v2.refs.ContainerID) | repeated | List of `ContainerID`s belonging to the requested `OwnerID` |
+
+
+
+
+### Message ListStreamRequest
+List containers stream
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| body | [ListStreamRequest.Body](#neo.fs.v2.container.ListStreamRequest.Body) | | Body of list containers stream request message. |
+| meta_header | [neo.fs.v2.session.RequestMetaHeader](#neo.fs.v2.session.RequestMetaHeader) | | Carries request meta information. Header data is used only to regulate message transport and does not affect request execution. |
+| verify_header | [neo.fs.v2.session.RequestVerificationHeader](#neo.fs.v2.session.RequestVerificationHeader) | | Carries request verification information. This header is used to authenticate the nodes of the message route and check the correctness of transmission. |
+
+
+
+
+### Message ListStreamRequest.Body
+List containers stream request body.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| owner_id | [neo.fs.v2.refs.OwnerID](#neo.fs.v2.refs.OwnerID) | | Identifier of the container owner. |
+
+
+
+
+### Message ListStreamResponse
+List containers stream
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| body | [ListStreamResponse.Body](#neo.fs.v2.container.ListStreamResponse.Body) | | Body of list containers stream response message. |
+| meta_header | [neo.fs.v2.session.ResponseMetaHeader](#neo.fs.v2.session.ResponseMetaHeader) | | Carries response meta information. Header data is used only to regulate message transport and does not affect request execution. |
+| verify_header | [neo.fs.v2.session.ResponseVerificationHeader](#neo.fs.v2.session.ResponseVerificationHeader) | | Carries response verification information. This header is used to authenticate the nodes of the message route and check the correctness of transmission. |
+
+
+
+
+### Message ListStreamResponse.Body
+List containers stream response body.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| container_ids | [neo.fs.v2.refs.ContainerID](#neo.fs.v2.refs.ContainerID) | repeated | List of `ContainerID`s belonging to the requested `OwnerID` |
+
+
+
+
+### Message PutRequest
+New FrostFS Container creation request
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| body | [PutRequest.Body](#neo.fs.v2.container.PutRequest.Body) | | Body of container put request message. |
+| meta_header | [neo.fs.v2.session.RequestMetaHeader](#neo.fs.v2.session.RequestMetaHeader) | | Carries request meta information. Header data is used only to regulate message transport and does not affect request execution. |
+| verify_header | [neo.fs.v2.session.RequestVerificationHeader](#neo.fs.v2.session.RequestVerificationHeader) | | Carries request verification information. This header is used to authenticate the nodes of the message route and check the correctness of transmission. |
+
+
+
+
+### Message PutRequest.Body
+Container creation request has container structure's signature as a
+separate field. It's not stored in sidechain, just verified on container
+creation by `Container` smart contract. `ContainerID` is a SHA256 hash of
+the stable-marshalled container strucutre, hence there is no need for
+additional signature checks.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| container | [Container](#neo.fs.v2.container.Container) | | Container structure to register in FrostFS |
+| signature | [neo.fs.v2.refs.SignatureRFC6979](#neo.fs.v2.refs.SignatureRFC6979) | | Signature of a stable-marshalled container according to RFC-6979. |
+
+
+
+
+### Message PutResponse
+New FrostFS Container creation response
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| body | [PutResponse.Body](#neo.fs.v2.container.PutResponse.Body) | | Body of container put response message. |
+| meta_header | [neo.fs.v2.session.ResponseMetaHeader](#neo.fs.v2.session.ResponseMetaHeader) | | Carries response meta information. Header data is used only to regulate message transport and does not affect request execution. |
+| verify_header | [neo.fs.v2.session.ResponseVerificationHeader](#neo.fs.v2.session.ResponseVerificationHeader) | | Carries response verification information. This header is used to authenticate the nodes of the message route and check the correctness of transmission. |
+
+
+
+
+### Message PutResponse.Body
+Container put response body contains information about the newly registered
+container as seen by `Container` smart contract. `ContainerID` can be
+calculated beforehand from the container structure and compared to the one
+returned here to make sure everything has been done as expected.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| container_id | [neo.fs.v2.refs.ContainerID](#neo.fs.v2.refs.ContainerID) | | Unique identifier of the newly created container |
+
+
+
+
+
+
+
+
+
+
+## container/types.proto
+
+
+
+
+
+
+
+### Message Container
+Container is a structure that defines object placement behaviour. Objects can
+be stored only within containers. They define placement rule, attributes and
+access control information. An ID of a container is a 32 byte long SHA256
+hash of stable-marshalled container message.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| version | [neo.fs.v2.refs.Version](#neo.fs.v2.refs.Version) | | Container format version. Effectively, the version of API library used to create the container. |
+| owner_id | [neo.fs.v2.refs.OwnerID](#neo.fs.v2.refs.OwnerID) | | Identifier of the container owner |
+| nonce | [bytes](#bytes) | | Nonce is a 16 byte UUIDv4, used to avoid collisions of `ContainerID`s |
+| basic_acl | [uint32](#uint32) | | `BasicACL` contains access control rules for the owner, system and others groups, as well as permission bits for `BearerToken` and `Extended ACL` |
+| attributes | [Container.Attribute](#neo.fs.v2.container.Container.Attribute) | repeated | Attributes represent immutable container's meta data |
+| placement_policy | [neo.fs.v2.netmap.PlacementPolicy](#neo.fs.v2.netmap.PlacementPolicy) | | Placement policy for the object inside the container |
+
+
+
+
+### Message Container.Attribute
+`Attribute` is a user-defined Key-Value metadata pair attached to the
+container. Container attributes are immutable. They are set at the moment
+of container creation and can never be added or updated.
+
+Key name must be a container-unique valid UTF-8 string. Value can't be
+empty. Containers with duplicated attribute names or attributes with empty
+values will be considered invalid.
+
+There are some "well-known" attributes affecting system behaviour:
+
+* [ __SYSTEM__NAME ] \
+ (`__NEOFS__NAME` is deprecated) \
+ String of a human-friendly container name registered as a domain in
+ NNS contract.
+* [ __SYSTEM__ZONE ] \
+ (`__NEOFS__ZONE` is deprecated) \
+ String of a zone for `__SYSTEM__NAME` (`__NEOFS__NAME` is deprecated).
+ Used as a TLD of a domain name in NNS contract. If no zone is specified,
+ use default zone: `container`.
+* [ __SYSTEM__DISABLE_HOMOMORPHIC_HASHING ] \
+ (`__NEOFS__DISABLE_HOMOMORPHIC_HASHING` is deprecated) \
+ Disables homomorphic hashing for the container if the value equals "true"
+ string. Any other values are interpreted as missing attribute. Container
+ could be accepted in a FrostFS network only if the global network hashing
+ configuration value corresponds with that attribute's value. After
+ container inclusion, network setting is ignored.
+
+And some well-known attributes used by applications only:
+
+* Name \
+ Human-friendly name
+* Timestamp \
+ User-defined local time of container creation in Unix Timestamp format
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| key | [string](#string) | | Attribute name key |
+| value | [string](#string) | | Attribute value |
+
+
+
+
+
+
+
+## Scalar Value Types
+
+| .proto Type | Notes | C++ Type | Java Type | Python Type |
+| ----------- | ----- | -------- | --------- | ----------- |
+| double | | double | double | float |
+| float | | float | float | float |
+| 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 |
+| 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 |
+| uint32 | Uses variable-length encoding. | uint32 | int | int/long |
+| uint64 | Uses variable-length encoding. | uint64 | long | int/long |
+| sint32 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s. | int32 | int | int |
+| sint64 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s. | int64 | long | int/long |
+| fixed32 | Always four bytes. More efficient than uint32 if values are often greater than 2^28. | uint32 | int | int |
+| fixed64 | Always eight bytes. More efficient than uint64 if values are often greater than 2^56. | uint64 | long | int/long |
+| sfixed32 | Always four bytes. | int32 | int | int |
+| sfixed64 | Always eight bytes. | int64 | long | int/long |
+| bool | | bool | boolean | boolean |
+| string | A string must always contain UTF-8 encoded or 7-bit ASCII text. | string | String | str/unicode |
+| bytes | May contain any arbitrary sequence of bytes. | string | ByteString | str |
diff --git a/proto-docs/lock.md b/proto-docs/lock.md
new file mode 100644
index 0000000..ba23306
--- /dev/null
+++ b/proto-docs/lock.md
@@ -0,0 +1,63 @@
+# Protocol Documentation
+
+
+## Table of Contents
+
+- [lock/types.proto](#lock/types.proto)
+
+ - Messages
+ - [Lock](#neo.fs.v2.lock.Lock)
+
+
+- [Scalar Value Types](#scalar-value-types)
+
+
+
+
+
+
+## netmap/service.proto
+
+
+
+
+
+
+### Service "neo.fs.v2.netmap.NetmapService"
+`NetmapService` provides methods to work with `Network Map` and the
+information required to build it. The resulting `Network Map` is stored in
+sidechain `Netmap` smart contract, while related information can be obtained
+from other FrostFS nodes.
+
+```
+rpc LocalNodeInfo(LocalNodeInfoRequest) returns (LocalNodeInfoResponse);
+rpc NetworkInfo(NetworkInfoRequest) returns (NetworkInfoResponse);
+rpc NetmapSnapshot(NetmapSnapshotRequest) returns (NetmapSnapshotResponse);
+
+```
+
+#### Method LocalNodeInfo
+
+Get NodeInfo structure from the particular node directly.
+Node information can be taken from `Netmap` smart contract. In some cases,
+though, one may want to get recent information directly or to talk to the
+node not yet present in the `Network Map` to find out what API version can
+be used for further communication. This can be also used to check if a node
+is up and running.
+
+Statuses:
+- **OK** (0, SECTION_SUCCESS):
+information about the server has been successfully read;
+- Common failures (SECTION_FAILURE_COMMON).
+
+| Name | Input | Output |
+| ---- | ----- | ------ |
+| LocalNodeInfo | [LocalNodeInfoRequest](#neo.fs.v2.netmap.LocalNodeInfoRequest) | [LocalNodeInfoResponse](#neo.fs.v2.netmap.LocalNodeInfoResponse) |
+#### Method NetworkInfo
+
+Read recent information about the FrostFS network.
+
+Statuses:
+- **OK** (0, SECTION_SUCCESS):
+information about the current network state has been successfully read;
+- Common failures (SECTION_FAILURE_COMMON).
+
+| Name | Input | Output |
+| ---- | ----- | ------ |
+| NetworkInfo | [NetworkInfoRequest](#neo.fs.v2.netmap.NetworkInfoRequest) | [NetworkInfoResponse](#neo.fs.v2.netmap.NetworkInfoResponse) |
+#### Method NetmapSnapshot
+
+Returns network map snapshot of the current FrostFS epoch.
+
+Statuses:
+- **OK** (0, SECTION_SUCCESS):
+information about the current network map has been successfully read;
+- Common failures (SECTION_FAILURE_COMMON).
+
+| Name | Input | Output |
+| ---- | ----- | ------ |
+| NetmapSnapshot | [NetmapSnapshotRequest](#neo.fs.v2.netmap.NetmapSnapshotRequest) | [NetmapSnapshotResponse](#neo.fs.v2.netmap.NetmapSnapshotResponse) |
+
+
+
+
+
+### Message LocalNodeInfoRequest
+Get NodeInfo structure directly from a particular node
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| body | [LocalNodeInfoRequest.Body](#neo.fs.v2.netmap.LocalNodeInfoRequest.Body) | | Body of the LocalNodeInfo request message |
+| meta_header | [neo.fs.v2.session.RequestMetaHeader](#neo.fs.v2.session.RequestMetaHeader) | | Carries request meta information. Header data is used only to regulate message transport and does not affect request execution. |
+| verify_header | [neo.fs.v2.session.RequestVerificationHeader](#neo.fs.v2.session.RequestVerificationHeader) | | Carries request verification information. This header is used to authenticate the nodes of the message route and check the correctness of transmission. |
+
+
+
+
+### Message LocalNodeInfoRequest.Body
+LocalNodeInfo request body is empty.
+
+
+
+
+
+### Message LocalNodeInfoResponse
+Local Node Info, including API Version in use
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| body | [LocalNodeInfoResponse.Body](#neo.fs.v2.netmap.LocalNodeInfoResponse.Body) | | Body of the balance response message. |
+| meta_header | [neo.fs.v2.session.ResponseMetaHeader](#neo.fs.v2.session.ResponseMetaHeader) | | Carries response meta information. Header data is used only to regulate message transport and does not affect response execution. |
+| verify_header | [neo.fs.v2.session.ResponseVerificationHeader](#neo.fs.v2.session.ResponseVerificationHeader) | | Carries response verification information. This header is used to authenticate the nodes of the message route and check the correctness of transmission. |
+
+
+
+
+### Message LocalNodeInfoResponse.Body
+Local Node Info, including API Version in use.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| version | [neo.fs.v2.refs.Version](#neo.fs.v2.refs.Version) | | Latest FrostFS API version in use |
+| node_info | [NodeInfo](#neo.fs.v2.netmap.NodeInfo) | | NodeInfo structure with recent information from node itself |
+
+
+
+
+### Message NetmapSnapshotRequest
+Get netmap snapshot request
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| body | [NetmapSnapshotRequest.Body](#neo.fs.v2.netmap.NetmapSnapshotRequest.Body) | | Body of get netmap snapshot request message. |
+| meta_header | [neo.fs.v2.session.RequestMetaHeader](#neo.fs.v2.session.RequestMetaHeader) | | Carries request meta information. Header data is used only to regulate message transport and does not affect request execution. |
+| verify_header | [neo.fs.v2.session.RequestVerificationHeader](#neo.fs.v2.session.RequestVerificationHeader) | | Carries request verification information. This header is used to authenticate the nodes of the message route and check the correctness of transmission. |
+
+
+
+
+### Message NetmapSnapshotRequest.Body
+Get netmap snapshot request body.
+
+
+
+
+
+### Message NetmapSnapshotResponse
+Response with current netmap snapshot
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| body | [NetmapSnapshotResponse.Body](#neo.fs.v2.netmap.NetmapSnapshotResponse.Body) | | Body of get netmap snapshot response message. |
+| meta_header | [neo.fs.v2.session.ResponseMetaHeader](#neo.fs.v2.session.ResponseMetaHeader) | | Carries response meta information. Header data is used only to regulate message transport and does not affect response execution. |
+| verify_header | [neo.fs.v2.session.ResponseVerificationHeader](#neo.fs.v2.session.ResponseVerificationHeader) | | Carries response verification information. This header is used to authenticate the nodes of the message route and check the correctness of transmission. |
+
+
+
+
+### Message NetmapSnapshotResponse.Body
+Get netmap snapshot response body
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| netmap | [Netmap](#neo.fs.v2.netmap.Netmap) | | Structure of the requested network map. |
+
+
+
+
+### Message NetworkInfoRequest
+Get NetworkInfo structure with the network view from a particular node.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| body | [NetworkInfoRequest.Body](#neo.fs.v2.netmap.NetworkInfoRequest.Body) | | Body of the NetworkInfo request message |
+| meta_header | [neo.fs.v2.session.RequestMetaHeader](#neo.fs.v2.session.RequestMetaHeader) | | Carries request meta information. Header data is used only to regulate message transport and does not affect request execution. |
+| verify_header | [neo.fs.v2.session.RequestVerificationHeader](#neo.fs.v2.session.RequestVerificationHeader) | | Carries request verification information. This header is used to authenticate the nodes of the message route and check the correctness of transmission. |
+
+
+
+
+### Message NetworkInfoRequest.Body
+NetworkInfo request body is empty.
+
+
+
+
+
+### Message NetworkInfoResponse
+Response with NetworkInfo structure including current epoch and
+sidechain magic number.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| body | [NetworkInfoResponse.Body](#neo.fs.v2.netmap.NetworkInfoResponse.Body) | | Body of the NetworkInfo response message. |
+| meta_header | [neo.fs.v2.session.ResponseMetaHeader](#neo.fs.v2.session.ResponseMetaHeader) | | Carries response meta information. Header data is used only to regulate message transport and does not affect response execution. |
+| verify_header | [neo.fs.v2.session.ResponseVerificationHeader](#neo.fs.v2.session.ResponseVerificationHeader) | | Carries response verification information. This header is used to authenticate the nodes of the message route and check the correctness of transmission. |
+
+
+
+
+### Message NetworkInfoResponse.Body
+Information about the network.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| network_info | [NetworkInfo](#neo.fs.v2.netmap.NetworkInfo) | | NetworkInfo structure with recent information. |
+
+
+
+
+
+
+
+
+
+
+## netmap/types.proto
+
+
+
+
+
+
+
+### Message Filter
+This filter will return the subset of nodes from `NetworkMap` or another
+filter's results that will satisfy filter's conditions.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| name | [string](#string) | | Name of the filter or a reference to a named filter. '*' means application to the whole unfiltered NetworkMap. At top level it's used as a filter name. At lower levels it's considered to be a reference to another named filter |
+| key | [string](#string) | | Key to filter |
+| op | [Operation](#neo.fs.v2.netmap.Operation) | | Filtering operation |
+| value | [string](#string) | | Value to match |
+| filters | [Filter](#neo.fs.v2.netmap.Filter) | repeated | List of inner filters. Top level operation will be applied to the whole list. |
+
+
+
+
+### Message Netmap
+Network map structure
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| epoch | [uint64](#uint64) | | Network map revision number. |
+| nodes | [NodeInfo](#neo.fs.v2.netmap.NodeInfo) | repeated | Nodes presented in network. |
+
+
+
+
+### Message NetworkConfig
+FrostFS network configuration
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| parameters | [NetworkConfig.Parameter](#neo.fs.v2.netmap.NetworkConfig.Parameter) | repeated | List of parameter values |
+
+
+
+
+### Message NetworkConfig.Parameter
+Single configuration parameter. Key MUST be network-unique.
+
+System parameters:
+- **AuditFee** \
+ Fee paid by the storage group owner to the Inner Ring member.
+ Value: little-endian integer. Default: 0.
+- **BasicIncomeRate** \
+ Cost of storing one gigabyte of data for a period of one epoch. Paid by
+ container owner to container nodes.
+ Value: little-endian integer. Default: 0.
+- **ContainerAliasFee** \
+ Fee paid for named container's creation by the container owner.
+ Value: little-endian integer. Default: 0.
+- **ContainerFee** \
+ Fee paid for container creation by the container owner.
+ Value: little-endian integer. Default: 0.
+- **EpochDuration** \
+ FrostFS epoch duration measured in Sidechain blocks.
+ Value: little-endian integer. Default: 0.
+- **HomomorphicHashingDisabled** \
+ Flag of disabling the homomorphic hashing of objects' payload.
+ Value: true if any byte != 0. Default: false.
+- **InnerRingCandidateFee** \
+ Fee for entrance to the Inner Ring paid by the candidate.
+ Value: little-endian integer. Default: 0.
+- **MaintenanceModeAllowed** \
+ Flag allowing setting the MAINTENANCE state to storage nodes.
+ Value: true if any byte != 0. Default: false.
+- **MaxObjectSize** \
+ Maximum size of physically stored FrostFS object measured in bytes.
+ Value: little-endian integer. Default: 0.
+
+ This value refers to the maximum size of a **physically** stored object
+ in FrostFS. However, from a user's perspective, the **logical** size of a
+ stored object can be significantly larger. The relationship between the
+ physical and logical object sizes is governed by the following formula
+
+ ```math
+ \mathrm{Stored\ Object\ Size} \le
+ \frac{
+ \left(\mathrm{Max\ Object\ Size}\right)^2
+ }{
+ \mathrm{Object\ ID\ Size}
+ }
+ ```
+
+ This arises from the fact that a tombstone, also being an object, stores
+ the IDs of inhumed objects and cannot be divided into smaller objects,
+ thus having an upper limit for its size.
+
+ For example, if:
+ * Max Object Size Size = 64 MiB;
+ * Object ID Size = 32 B;
+
+ then:
+ ```math
+ \mathrm{Stored\ Object\ Size} \le
+ \frac{\left(64\ \mathrm{MiB}\right)^2}{32\ \mathrm{B}} =
+ \frac{2^{52}}{2^5}\ \mathrm{B} =
+ 2^{47}\ \mathrm{B} =
+ 128\ \mathrm{TiB}
+ ```
+- **WithdrawFee** \
+ Fee paid for withdrawal of funds paid by the account owner.
+ Value: little-endian integer. Default: 0.
+- **MaxECDataCount** \
+ Maximum number of data shards for EC placement policy.
+ Value: little-endian integer. Default: 0.
+- **MaxECParityCount** \
+ Maximum number of parity shards for EC placement policy.
+ Value: little-endian integer. Default: 0.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| key | [bytes](#bytes) | | Parameter key. UTF-8 encoded string |
+| value | [bytes](#bytes) | | Parameter value |
+
+
+
+
+### Message NetworkInfo
+Information about FrostFS network
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| current_epoch | [uint64](#uint64) | | Number of the current epoch in the FrostFS network |
+| magic_number | [uint64](#uint64) | | Magic number of the sidechain of the FrostFS network |
+| ms_per_block | [int64](#int64) | | MillisecondsPerBlock network parameter of the sidechain of the FrostFS network |
+| network_config | [NetworkConfig](#neo.fs.v2.netmap.NetworkConfig) | | FrostFS network configuration |
+
+
+
+
+### Message NodeInfo
+FrostFS node description
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| public_key | [bytes](#bytes) | | Public key of the FrostFS node in a binary format |
+| addresses | [string](#string) | repeated | Ways to connect to a node |
+| attributes | [NodeInfo.Attribute](#neo.fs.v2.netmap.NodeInfo.Attribute) | repeated | Carries list of the FrostFS node attributes in a key-value form. Key name must be a node-unique valid UTF-8 string. Value can't be empty. NodeInfo structures with duplicated attribute names or attributes with empty values will be considered invalid. |
+| state | [NodeInfo.State](#neo.fs.v2.netmap.NodeInfo.State) | | Carries state of the FrostFS node |
+
+
+
+
+### Message NodeInfo.Attribute
+Administrator-defined Attributes of the FrostFS Storage Node.
+
+`Attribute` is a Key-Value metadata pair. Key name must be a valid UTF-8
+string. Value can't be empty.
+
+Attributes can be constructed into a chain of attributes: any attribute can
+have a parent attribute and a child attribute (except the first and the
+last one). A string representation of the chain of attributes in FrostFS
+Storage Node configuration uses ":" and "/" symbols, e.g.:
+
+ `FrostFS_NODE_ATTRIBUTE_1=key1:val1/key2:val2`
+
+Therefore the string attribute representation in the Node configuration
+must use "\:", "\/" and "\\" escaped symbols if any of them appears in an
+attribute's key or value.
+
+Node's attributes are mostly used during Storage Policy evaluation to
+calculate object's placement and find a set of nodes satisfying policy
+requirements. There are some "well-known" node attributes common to all the
+Storage Nodes in the network and used implicitly with default values if not
+explicitly set:
+
+* Capacity \
+ Total available disk space in Gigabytes.
+* Price \
+ Price in GAS tokens for storing one GB of data during one Epoch. In node
+ attributes it's a string presenting floating point number with comma or
+ point delimiter for decimal part. In the Network Map it will be saved as
+ 64-bit unsigned integer representing number of minimal token fractions.
+* UN-LOCODE \
+ Node's geographic location in
+ [UN/LOCODE](https://www.unece.org/cefact/codesfortrade/codes_index.html)
+ format approximated to the nearest point defined in the standard.
+* CountryCode \
+ Country code in
+ [ISO 3166-1_alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2)
+ format. Calculated automatically from `UN-LOCODE` attribute.
+* Country \
+ Country short name in English, as defined in
+ [ISO-3166](https://www.iso.org/obp/ui/#search). Calculated automatically
+ from `UN-LOCODE` attribute.
+* Location \
+ Place names are given, whenever possible, in their national language
+ versions as expressed in the Roman alphabet using the 26 characters of
+ the character set adopted for international trade data interchange,
+ written without diacritics . Calculated automatically from `UN-LOCODE`
+ attribute.
+* SubDivCode \
+ Country's administrative subdivision where node is located. Calculated
+ automatically from `UN-LOCODE` attribute based on `SubDiv` field.
+ Presented in [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2)
+ format.
+* SubDiv \
+ Country's administrative subdivision name, as defined in
+ [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2). Calculated
+ automatically from `UN-LOCODE` attribute.
+* Continent \
+ Node's continent name according to the [Seven-Continent
+ model](https://en.wikipedia.org/wiki/Continent#Number). Calculated
+ automatically from `UN-LOCODE` attribute.
+* ExternalAddr
+ Node's preferred way for communications with external clients.
+ Clients SHOULD use these addresses if possible.
+ Must contain a comma-separated list of multi-addresses.
+
+For detailed description of each well-known attribute please see the
+corresponding section in FrostFS Technical Specification.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| key | [string](#string) | | Key of the node attribute |
+| value | [string](#string) | | Value of the node attribute |
+| parents | [string](#string) | repeated | Parent keys, if any. For example for `City` it could be `Region` and `Country`. |
+
+
+
+
+### Message PlacementPolicy
+Set of rules to select a subset of nodes from `NetworkMap` able to store
+container's objects. The format is simple enough to transpile from different
+storage policy definition languages.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| replicas | [Replica](#neo.fs.v2.netmap.Replica) | repeated | Rules to set number of object replicas and place each one into a named bucket |
+| container_backup_factor | [uint32](#uint32) | | Container backup factor controls how deep FrostFS will search for nodes alternatives to include into container's nodes subset |
+| selectors | [Selector](#neo.fs.v2.netmap.Selector) | repeated | Set of Selectors to form the container's nodes subset |
+| filters | [Filter](#neo.fs.v2.netmap.Filter) | repeated | List of named filters to reference in selectors |
+| unique | [bool](#bool) | | Unique flag defines non-overlapping application for replicas |
+
+
+
+
+### Message Replica
+Number of object replicas in a set of nodes from the defined selector. If no
+selector set, the root bucket containing all possible nodes will be used by
+default.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| count | [uint32](#uint32) | | How many object replicas to put |
+| selector | [string](#string) | | Named selector bucket to put replicas |
+| ec_data_count | [uint32](#uint32) | | Data shards count |
+| ec_parity_count | [uint32](#uint32) | | Parity shards count |
+
+
+
+
+### Message Selector
+Selector chooses a number of nodes from the bucket taking the nearest nodes
+to the provided `ContainerID` by hash distance.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| name | [string](#string) | | Selector name to reference in object placement section |
+| count | [uint32](#uint32) | | How many nodes to select from the bucket |
+| clause | [Clause](#neo.fs.v2.netmap.Clause) | | Selector modifier showing how to form a bucket |
+| attribute | [string](#string) | | Bucket attribute to select from |
+| filter | [string](#string) | | Filter reference to select from |
+
+
+
+
+
+
+### Clause
+Selector modifier shows how the node set will be formed. By default selector
+just groups nodes into a bucket by attribute, selecting nodes only by their
+hash distance.
+
+| Name | Number | Description |
+| ---- | ------ | ----------- |
+| CLAUSE_UNSPECIFIED | 0 | No modifier defined. Nodes will be selected from the bucket randomly |
+| SAME | 1 | SAME will select only nodes having the same value of bucket attribute |
+| DISTINCT | 2 | DISTINCT will select nodes having different values of bucket attribute |
+
+
+
+
+
+### NodeInfo.State
+Represents the enumeration of various states of the FrostFS node.
+
+| Name | Number | Description |
+| ---- | ------ | ----------- |
+| UNSPECIFIED | 0 | Unknown state |
+| ONLINE | 1 | Active state in the network |
+| OFFLINE | 2 | Network unavailable state |
+| MAINTENANCE | 3 | Maintenance state |
+
+
+
+
+
+### Operation
+Operations on filters
+
+| Name | Number | Description |
+| ---- | ------ | ----------- |
+| OPERATION_UNSPECIFIED | 0 | No Operation defined |
+| EQ | 1 | Equal |
+| NE | 2 | Not Equal |
+| GT | 3 | Greater then |
+| GE | 4 | Greater or equal |
+| LT | 5 | Less then |
+| LE | 6 | Less or equal |
+| OR | 7 | Logical OR |
+| AND | 8 | Logical AND |
+| NOT | 9 | Logical negation |
+| LIKE | 10 | Matches pattern |
+
+
+
+
+
+
+## Scalar Value Types
+
+| .proto Type | Notes | C++ Type | Java Type | Python Type |
+| ----------- | ----- | -------- | --------- | ----------- |
+| double | | double | double | float |
+| float | | float | float | float |
+| 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 |
+| 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 |
+| uint32 | Uses variable-length encoding. | uint32 | int | int/long |
+| uint64 | Uses variable-length encoding. | uint64 | long | int/long |
+| sint32 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s. | int32 | int | int |
+| sint64 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s. | int64 | long | int/long |
+| fixed32 | Always four bytes. More efficient than uint32 if values are often greater than 2^28. | uint32 | int | int |
+| fixed64 | Always eight bytes. More efficient than uint64 if values are often greater than 2^56. | uint64 | long | int/long |
+| sfixed32 | Always four bytes. | int32 | int | int |
+| sfixed64 | Always eight bytes. | int64 | long | int/long |
+| bool | | bool | boolean | boolean |
+| string | A string must always contain UTF-8 encoded or 7-bit ASCII text. | string | String | str/unicode |
+| bytes | May contain any arbitrary sequence of bytes. | string | ByteString | str |
diff --git a/proto-docs/object.md b/proto-docs/object.md
new file mode 100644
index 0000000..14b9ae6
--- /dev/null
+++ b/proto-docs/object.md
@@ -0,0 +1,1328 @@
+# Protocol Documentation
+
+
+## Table of Contents
+
+- [object/service.proto](#object/service.proto)
+ - Services
+ - [ObjectService](#neo.fs.v2.object.ObjectService)
+
+ - Messages
+ - [DeleteRequest](#neo.fs.v2.object.DeleteRequest)
+ - [DeleteRequest.Body](#neo.fs.v2.object.DeleteRequest.Body)
+ - [DeleteResponse](#neo.fs.v2.object.DeleteResponse)
+ - [DeleteResponse.Body](#neo.fs.v2.object.DeleteResponse.Body)
+ - [GetRangeHashRequest](#neo.fs.v2.object.GetRangeHashRequest)
+ - [GetRangeHashRequest.Body](#neo.fs.v2.object.GetRangeHashRequest.Body)
+ - [GetRangeHashResponse](#neo.fs.v2.object.GetRangeHashResponse)
+ - [GetRangeHashResponse.Body](#neo.fs.v2.object.GetRangeHashResponse.Body)
+ - [GetRangeRequest](#neo.fs.v2.object.GetRangeRequest)
+ - [GetRangeRequest.Body](#neo.fs.v2.object.GetRangeRequest.Body)
+ - [GetRangeResponse](#neo.fs.v2.object.GetRangeResponse)
+ - [GetRangeResponse.Body](#neo.fs.v2.object.GetRangeResponse.Body)
+ - [GetRequest](#neo.fs.v2.object.GetRequest)
+ - [GetRequest.Body](#neo.fs.v2.object.GetRequest.Body)
+ - [GetResponse](#neo.fs.v2.object.GetResponse)
+ - [GetResponse.Body](#neo.fs.v2.object.GetResponse.Body)
+ - [GetResponse.Body.Init](#neo.fs.v2.object.GetResponse.Body.Init)
+ - [HeadRequest](#neo.fs.v2.object.HeadRequest)
+ - [HeadRequest.Body](#neo.fs.v2.object.HeadRequest.Body)
+ - [HeadResponse](#neo.fs.v2.object.HeadResponse)
+ - [HeadResponse.Body](#neo.fs.v2.object.HeadResponse.Body)
+ - [HeaderWithSignature](#neo.fs.v2.object.HeaderWithSignature)
+ - [PatchRequest](#neo.fs.v2.object.PatchRequest)
+ - [PatchRequest.Body](#neo.fs.v2.object.PatchRequest.Body)
+ - [PatchRequest.Body.Patch](#neo.fs.v2.object.PatchRequest.Body.Patch)
+ - [PatchResponse](#neo.fs.v2.object.PatchResponse)
+ - [PatchResponse.Body](#neo.fs.v2.object.PatchResponse.Body)
+ - [PutRequest](#neo.fs.v2.object.PutRequest)
+ - [PutRequest.Body](#neo.fs.v2.object.PutRequest.Body)
+ - [PutRequest.Body.Init](#neo.fs.v2.object.PutRequest.Body.Init)
+ - [PutResponse](#neo.fs.v2.object.PutResponse)
+ - [PutResponse.Body](#neo.fs.v2.object.PutResponse.Body)
+ - [PutSingleRequest](#neo.fs.v2.object.PutSingleRequest)
+ - [PutSingleRequest.Body](#neo.fs.v2.object.PutSingleRequest.Body)
+ - [PutSingleResponse](#neo.fs.v2.object.PutSingleResponse)
+ - [PutSingleResponse.Body](#neo.fs.v2.object.PutSingleResponse.Body)
+ - [Range](#neo.fs.v2.object.Range)
+ - [SearchRequest](#neo.fs.v2.object.SearchRequest)
+ - [SearchRequest.Body](#neo.fs.v2.object.SearchRequest.Body)
+ - [SearchRequest.Body.Filter](#neo.fs.v2.object.SearchRequest.Body.Filter)
+ - [SearchResponse](#neo.fs.v2.object.SearchResponse)
+ - [SearchResponse.Body](#neo.fs.v2.object.SearchResponse.Body)
+
+
+- [object/types.proto](#object/types.proto)
+
+ - Messages
+ - [ECInfo](#neo.fs.v2.object.ECInfo)
+ - [ECInfo.Chunk](#neo.fs.v2.object.ECInfo.Chunk)
+ - [Header](#neo.fs.v2.object.Header)
+ - [Header.Attribute](#neo.fs.v2.object.Header.Attribute)
+ - [Header.EC](#neo.fs.v2.object.Header.EC)
+ - [Header.Split](#neo.fs.v2.object.Header.Split)
+ - [Object](#neo.fs.v2.object.Object)
+ - [ShortHeader](#neo.fs.v2.object.ShortHeader)
+ - [SplitInfo](#neo.fs.v2.object.SplitInfo)
+
+
+- [Scalar Value Types](#scalar-value-types)
+
+
+
+
+
+
+## object/service.proto
+
+
+
+
+
+
+### Service "neo.fs.v2.object.ObjectService"
+`ObjectService` provides API for manipulating objects. Object operations do
+not affect the sidechain and are only served by nodes in p2p style.
+
+```
+rpc Get(GetRequest) returns (stream GetResponse);
+rpc Put(stream PutRequest) returns (PutResponse);
+rpc Delete(DeleteRequest) returns (DeleteResponse);
+rpc Head(HeadRequest) returns (HeadResponse);
+rpc Search(SearchRequest) returns (stream SearchResponse);
+rpc GetRange(GetRangeRequest) returns (stream GetRangeResponse);
+rpc GetRangeHash(GetRangeHashRequest) returns (GetRangeHashResponse);
+rpc PutSingle(PutSingleRequest) returns (PutSingleResponse);
+rpc Patch(stream PatchRequest) returns (PatchResponse);
+
+```
+
+#### Method Get
+
+Receive full object structure, including Headers and payload. Response uses
+gRPC stream. First response message carries the object with the requested
+address. Chunk messages are parts of the object's payload if it is needed.
+All messages, except the first one, carry payload chunks. The requested
+object can be restored by concatenation of object message payload and all
+chunks keeping the receiving order.
+
+Extended headers can change `Get` behaviour:
+* [ __SYSTEM__NETMAP_EPOCH ] \
+ (`__NEOFS__NETMAP_EPOCH` is deprecated) \
+ Will use the requsted version of Network Map for object placement
+ calculation.
+* [ __SYSTEM__NETMAP_LOOKUP_DEPTH ] \
+ (`__NEOFS__NETMAP_LOOKUP_DEPTH` is deprecated) \
+ Will try older versions (starting from `__SYSTEM__NETMAP_EPOCH`
+ (`__NEOFS__NETMAP_EPOCH` is deprecated) if specified or the latest one
+ otherwise) of Network Map to find an object until the depth limit is
+ reached.
+
+Please refer to detailed `XHeader` description.
+
+Statuses:
+- **OK** (0, SECTION_SUCCESS): \
+ object has been successfully read;
+- Common failures (SECTION_FAILURE_COMMON);
+- **ACCESS_DENIED** (2048, SECTION_OBJECT): \
+ read access to the object is denied;
+- **OBJECT_NOT_FOUND** (2049, SECTION_OBJECT): \
+ object not found in container;
+- **OBJECT_ALREADY_REMOVED** (2052, SECTION_OBJECT): \
+ the requested object has been marked as deleted;
+- **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \
+ object container not found;
+- **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \
+ access to container is denied;
+- **TOKEN_EXPIRED** (4097, SECTION_SESSION): \
+ provided session token has expired.
+
+| Name | Input | Output |
+| ---- | ----- | ------ |
+| Get | [GetRequest](#neo.fs.v2.object.GetRequest) | [GetResponse](#neo.fs.v2.object.GetResponse) |
+#### Method Put
+
+Put the object into container. Request uses gRPC stream. First message
+SHOULD be of PutHeader type. `ContainerID` and `OwnerID` of an object
+SHOULD be set. Session token SHOULD be obtained before `PUT` operation (see
+session package). Chunk messages are considered by server as a part of an
+object payload. All messages, except first one, SHOULD be payload chunks.
+Chunk messages SHOULD be sent in the direct order of fragmentation.
+
+Extended headers can change `Put` behaviour:
+* [ __SYSTEM__NETMAP_EPOCH \
+ (`__NEOFS__NETMAP_EPOCH` is deprecated) \
+ Will use the requsted version of Network Map for object placement
+ calculation.
+
+Please refer to detailed `XHeader` description.
+
+Statuses:
+- **OK** (0, SECTION_SUCCESS): \
+ object has been successfully saved in the container;
+- Common failures (SECTION_FAILURE_COMMON);
+- **ACCESS_DENIED** (2048, SECTION_OBJECT): \
+ write access to the container is denied;
+- **LOCKED** (2050, SECTION_OBJECT): \
+ placement of an object of type TOMBSTONE that includes at least one
+ locked object is prohibited;
+- **LOCK_NON_REGULAR_OBJECT** (2051, SECTION_OBJECT): \
+ placement of an object of type LOCK that includes at least one object of
+ type other than REGULAR is prohibited;
+- **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \
+ object storage container not found;
+- **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \
+ access to container is denied;
+- **TOKEN_NOT_FOUND** (4096, SECTION_SESSION): \
+ (for trusted object preparation) session private key does not exist or
+ has
+been deleted;
+- **TOKEN_EXPIRED** (4097, SECTION_SESSION): \
+ provided session token has expired.
+
+| Name | Input | Output |
+| ---- | ----- | ------ |
+| Put | [PutRequest](#neo.fs.v2.object.PutRequest) | [PutResponse](#neo.fs.v2.object.PutResponse) |
+#### Method Delete
+
+Delete the object from a container. There is no immediate removal
+guarantee. Object will be marked for removal and deleted eventually.
+
+Extended headers can change `Delete` behaviour:
+* [ __SYSTEM__NETMAP_EPOCH ] \
+ (`__NEOFS__NETMAP_EPOCH` is deprecated) \
+ Will use the requested version of Network Map for object placement
+ calculation.
+
+Please refer to detailed `XHeader` description.
+
+Statuses:
+- **OK** (0, SECTION_SUCCESS): \
+ object has been successfully marked to be removed from the container;
+- Common failures (SECTION_FAILURE_COMMON);
+- **ACCESS_DENIED** (2048, SECTION_OBJECT): \
+ delete access to the object is denied;
+- **OBJECT_NOT_FOUND** (2049, SECTION_OBJECT): \
+ the object could not be deleted because it has not been \
+ found within the container;
+- **LOCKED** (2050, SECTION_OBJECT): \
+ deleting a locked object is prohibited;
+- **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \
+ object container not found;
+- **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \
+ access to container is denied;
+- **TOKEN_EXPIRED** (4097, SECTION_SESSION): \
+ provided session token has expired.
+
+| Name | Input | Output |
+| ---- | ----- | ------ |
+| Delete | [DeleteRequest](#neo.fs.v2.object.DeleteRequest) | [DeleteResponse](#neo.fs.v2.object.DeleteResponse) |
+#### Method Head
+
+Returns the object Headers without data payload. By default full header is
+returned. If `main_only` request field is set, the short header with only
+the very minimal information will be returned instead.
+
+Max header size is currently not limited by this API, but may be restricted
+on the service level. By default, gRPC uses a message size of 4 MiB.
+
+Extended headers can change `Head` behaviour:
+* [ __SYSTEM__NETMAP_EPOCH ] \
+ (`__NEOFS__NETMAP_EPOCH` is deprecated) \
+ Will use the requested version of Network Map for object placement
+ calculation.
+
+Please refer to detailed `XHeader` description.
+
+Statuses:
+- **OK** (0, SECTION_SUCCESS): \
+ object header has been successfully read;
+- Common failures (SECTION_FAILURE_COMMON);
+- **ACCESS_DENIED** (2048, SECTION_OBJECT): \
+ access to operation HEAD of the object is denied;
+- **OBJECT_NOT_FOUND** (2049, SECTION_OBJECT): \
+ object not found in container;
+- **OBJECT_ALREADY_REMOVED** (2052, SECTION_OBJECT): \
+ the requested object has been marked as deleted;
+- **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \
+ object container not found;
+- **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \
+ access to container is denied;
+- **TOKEN_EXPIRED** (4097, SECTION_SESSION): \
+ provided session token has expired.
+
+| Name | Input | Output |
+| ---- | ----- | ------ |
+| Head | [HeadRequest](#neo.fs.v2.object.HeadRequest) | [HeadResponse](#neo.fs.v2.object.HeadResponse) |
+#### Method Search
+
+Search objects in container. Search query allows to match by Object
+Header's filed values. Please see the corresponding FrostFS Technical
+Specification section for more details.
+
+Extended headers can change `Search` behaviour:
+* [ __SYSTEM__NETMAP_EPOCH ] \
+ (`__NEOFS__NETMAP_EPOCH` is deprecated) \
+ Will use the requested version of Network Map for object placement
+ calculation.
+
+Please refer to detailed `XHeader` description.
+
+Statuses:
+- **OK** (0, SECTION_SUCCESS): \
+ objects have been successfully selected;
+- Common failures (SECTION_FAILURE_COMMON);
+- **ACCESS_DENIED** (2048, SECTION_OBJECT): \
+ access to operation SEARCH of the object is denied;
+- **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \
+ search container not found;
+- **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \
+ access to container is denied;
+- **TOKEN_EXPIRED** (4097, SECTION_SESSION): \
+ provided session token has expired.
+
+| Name | Input | Output |
+| ---- | ----- | ------ |
+| Search | [SearchRequest](#neo.fs.v2.object.SearchRequest) | [SearchResponse](#neo.fs.v2.object.SearchResponse) |
+#### Method GetRange
+
+Get byte range of data payload. Range is set as an (offset, length) tuple.
+Like in `Get` method, the response uses gRPC stream. Requested range can be
+restored by concatenation of all received payload chunks keeping the
+receiving order.
+
+Extended headers can change `GetRange` behaviour:
+* [ __SYSTEM__NETMAP_EPOCH ] \
+ (`__NEOFS__NETMAP_EPOCH` is deprecated) \
+ Will use the requested version of Network Map for object placement
+ calculation.
+* [ __SYSTEM__NETMAP_LOOKUP_DEPTH ] \
+ (`__NEOFS__NETMAP_LOOKUP_DEPTH` is deprecated) \
+ Will try older versions of Network Map to find an object until the depth
+ limit is reached.
+
+Please refer to detailed `XHeader` description.
+
+Statuses:
+- **OK** (0, SECTION_SUCCESS): \
+ data range of the object payload has been successfully read;
+- Common failures (SECTION_FAILURE_COMMON);
+- **ACCESS_DENIED** (2048, SECTION_OBJECT): \
+ access to operation RANGE of the object is denied;
+- **OBJECT_NOT_FOUND** (2049, SECTION_OBJECT): \
+ object not found in container;
+- **OBJECT_ALREADY_REMOVED** (2052, SECTION_OBJECT): \
+ the requested object has been marked as deleted.
+- **OUT_OF_RANGE** (2053, SECTION_OBJECT): \
+ the requested range is out of bounds;
+- **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \
+ object container not found;
+- **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \
+ access to container is denied;
+- **TOKEN_EXPIRED** (4097, SECTION_SESSION): \
+ provided session token has expired.
+
+| Name | Input | Output |
+| ---- | ----- | ------ |
+| GetRange | [GetRangeRequest](#neo.fs.v2.object.GetRangeRequest) | [GetRangeResponse](#neo.fs.v2.object.GetRangeResponse) |
+#### Method GetRangeHash
+
+Returns homomorphic or regular hash of object's payload range after
+applying XOR operation with the provided `salt`. Ranges are set of (offset,
+length) tuples. Hashes order in response corresponds to the ranges order in
+the request. Note that hash is calculated for XORed data.
+
+Extended headers can change `GetRangeHash` behaviour:
+* [ __SYSTEM__NETMAP_EPOCH ] \
+ (`__NEOFS__NETMAP_EPOCH` is deprecated) \
+ Will use the requested version of Network Map for object placement
+ calculation.
+* [ __SYSTEM__NETMAP_LOOKUP_DEPTH ] \
+ (`__NEOFS__NETMAP_LOOKUP_DEPTH` is deprecated) \
+ Will try older versions of Network Map to find an object until the depth
+ limit is reached.
+
+Please refer to detailed `XHeader` description.
+
+Statuses:
+- **OK** (0, SECTION_SUCCESS): \
+ data range of the object payload has been successfully hashed;
+- Common failures (SECTION_FAILURE_COMMON);
+- **ACCESS_DENIED** (2048, SECTION_OBJECT): \
+ access to operation RANGEHASH of the object is denied;
+- **OBJECT_NOT_FOUND** (2049, SECTION_OBJECT): \
+ object not found in container;
+- **OUT_OF_RANGE** (2053, SECTION_OBJECT): \
+ the requested range is out of bounds;
+- **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \
+ object container not found;
+- **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \
+ access to container is denied;
+- **TOKEN_EXPIRED** (4097, SECTION_SESSION): \
+ provided session token has expired.
+
+| Name | Input | Output |
+| ---- | ----- | ------ |
+| GetRangeHash | [GetRangeHashRequest](#neo.fs.v2.object.GetRangeHashRequest) | [GetRangeHashResponse](#neo.fs.v2.object.GetRangeHashResponse) |
+#### Method PutSingle
+
+Put the prepared object into container.
+`ContainerID`, `ObjectID`, `OwnerID`, `PayloadHash` and `PayloadLength` of
+an object MUST be set.
+
+Extended headers can change `Put` behaviour:
+* [ __SYSTEM__NETMAP_EPOCH \
+ (`__NEOFS__NETMAP_EPOCH` is deprecated) \
+ Will use the requested version of Network Map for object placement
+ calculation.
+
+Please refer to detailed `XHeader` description.
+
+Statuses:
+- **OK** (0, SECTION_SUCCESS): \
+ object has been successfully saved in the container;
+- Common failures (SECTION_FAILURE_COMMON);
+- **ACCESS_DENIED** (2048, SECTION_OBJECT): \
+ write access to the container is denied;
+- **LOCKED** (2050, SECTION_OBJECT): \
+ placement of an object of type TOMBSTONE that includes at least one
+ locked object is prohibited;
+- **LOCK_NON_REGULAR_OBJECT** (2051, SECTION_OBJECT): \
+ placement of an object of type LOCK that includes at least one object of
+ type other than REGULAR is prohibited;
+- **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \
+ object storage container not found;
+- **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \
+ access to container is denied;
+- **TOKEN_NOT_FOUND** (4096, SECTION_SESSION): \
+ (for trusted object preparation) session private key does not exist or
+ has
+been deleted;
+- **TOKEN_EXPIRED** (4097, SECTION_SESSION): \
+ provided session token has expired.
+
+| Name | Input | Output |
+| ---- | ----- | ------ |
+| PutSingle | [PutSingleRequest](#neo.fs.v2.object.PutSingleRequest) | [PutSingleResponse](#neo.fs.v2.object.PutSingleResponse) |
+#### Method Patch
+
+Patch the object. Request uses gRPC stream. First message must set
+the address of the object that is going to get patched. If the object's
+attributes are patched, then these attrubutes must be set only within the
+first stream message.
+
+If the patch request is performed by NOT the object's owner but if the
+actor has the permission to perform the patch, then `OwnerID` of the object
+is changed. In this case the object's owner loses the object's ownership
+after the patch request is successfully done.
+
+As objects are content-addressable the patching causes new object ID
+generation for the patched object. This object id is set witihn
+`PatchResponse`. But the object id may remain unchanged in such cases:
+1. The chunk of the applying patch contains the same value as the object's
+payload within the same range;
+2. The patch that reverts the changes applied by preceding patch;
+3. The application of the same patches for the object a few times.
+
+Extended headers can change `Patch` behaviour:
+* [ __SYSTEM__NETMAP_EPOCH \
+ (`__NEOFS__NETMAP_EPOCH` is deprecated) \
+ Will use the requsted version of Network Map for object placement
+ calculation.
+
+Please refer to detailed `XHeader` description.
+
+Statuses:
+- **OK** (0, SECTION_SUCCESS): \
+ object has been successfully patched and saved in the container;
+- Common failures (SECTION_FAILURE_COMMON);
+- **ACCESS_DENIED** (2048, SECTION_OBJECT): \
+ write access to the container is denied;
+- **OBJECT_NOT_FOUND** (2049, SECTION_OBJECT): \
+ object not found in container;
+- **OBJECT_ALREADY_REMOVED** (2052, SECTION_OBJECT): \
+ the requested object has been marked as deleted.
+- **OUT_OF_RANGE** (2053, SECTION_OBJECT): \
+ the requested range is out of bounds;
+- **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \
+ object storage container not found;
+- **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \
+ access to container is denied;
+- **TOKEN_NOT_FOUND** (4096, SECTION_SESSION): \
+ (for trusted object preparation) session private key does not exist or
+ has been deleted;
+- **TOKEN_EXPIRED** (4097, SECTION_SESSION): \
+ provided session token has expired.
+
+| Name | Input | Output |
+| ---- | ----- | ------ |
+| Patch | [PatchRequest](#neo.fs.v2.object.PatchRequest) | [PatchResponse](#neo.fs.v2.object.PatchResponse) |
+
+
+
+
+
+### Message DeleteRequest
+Object DELETE request
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| body | [DeleteRequest.Body](#neo.fs.v2.object.DeleteRequest.Body) | | Body of delete object request message. |
+| meta_header | [neo.fs.v2.session.RequestMetaHeader](#neo.fs.v2.session.RequestMetaHeader) | | Carries request meta information. Header data is used only to regulate message transport and does not affect request execution. |
+| verify_header | [neo.fs.v2.session.RequestVerificationHeader](#neo.fs.v2.session.RequestVerificationHeader) | | Carries request verification information. This header is used to authenticate the nodes of the message route and check the correctness of transmission. |
+
+
+
+
+### Message DeleteRequest.Body
+Object DELETE request body
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| address | [neo.fs.v2.refs.Address](#neo.fs.v2.refs.Address) | | Address of the object to be deleted |
+
+
+
+
+### Message DeleteResponse
+DeleteResponse body is empty because we cannot guarantee permanent object
+removal in distributed system.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| body | [DeleteResponse.Body](#neo.fs.v2.object.DeleteResponse.Body) | | Body of delete object response message. |
+| meta_header | [neo.fs.v2.session.ResponseMetaHeader](#neo.fs.v2.session.ResponseMetaHeader) | | Carries response meta information. Header data is used only to regulate message transport and does not affect request execution. |
+| verify_header | [neo.fs.v2.session.ResponseVerificationHeader](#neo.fs.v2.session.ResponseVerificationHeader) | | Carries response verification information. This header is used to authenticate the nodes of the message route and check the correctness of transmission. |
+
+
+
+
+### Message DeleteResponse.Body
+Object DELETE Response has an empty body.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| tombstone | [neo.fs.v2.refs.Address](#neo.fs.v2.refs.Address) | | Address of the tombstone created for the deleted object |
+
+
+
+
+### Message GetRangeHashRequest
+Get hash of object's payload part
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| body | [GetRangeHashRequest.Body](#neo.fs.v2.object.GetRangeHashRequest.Body) | | Body of get range hash object request message. |
+| meta_header | [neo.fs.v2.session.RequestMetaHeader](#neo.fs.v2.session.RequestMetaHeader) | | Carries request meta information. Header data is used only to regulate message transport and does not affect request execution. |
+| verify_header | [neo.fs.v2.session.RequestVerificationHeader](#neo.fs.v2.session.RequestVerificationHeader) | | Carries request verification information. This header is used to authenticate the nodes of the message route and check the correctness of transmission. |
+
+
+
+
+### Message GetRangeHashRequest.Body
+Get hash of object's payload part request body.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| address | [neo.fs.v2.refs.Address](#neo.fs.v2.refs.Address) | | Address of the object that containing the requested payload range |
+| ranges | [Range](#neo.fs.v2.object.Range) | repeated | List of object's payload ranges to calculate homomorphic hash |
+| salt | [bytes](#bytes) | | Binary salt to XOR object's payload ranges before hash calculation |
+| type | [neo.fs.v2.refs.ChecksumType](#neo.fs.v2.refs.ChecksumType) | | Checksum algorithm type |
+
+
+
+
+### Message GetRangeHashResponse
+Get hash of object's payload part
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| body | [GetRangeHashResponse.Body](#neo.fs.v2.object.GetRangeHashResponse.Body) | | Body of get range hash object response message. |
+| meta_header | [neo.fs.v2.session.ResponseMetaHeader](#neo.fs.v2.session.ResponseMetaHeader) | | Carries response meta information. Header data is used only to regulate message transport and does not affect request execution. |
+| verify_header | [neo.fs.v2.session.ResponseVerificationHeader](#neo.fs.v2.session.ResponseVerificationHeader) | | Carries response verification information. This header is used to authenticate the nodes of the message route and check the correctness of transmission. |
+
+
+
+
+### Message GetRangeHashResponse.Body
+Get hash of object's payload part response body.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| type | [neo.fs.v2.refs.ChecksumType](#neo.fs.v2.refs.ChecksumType) | | Checksum algorithm type |
+| hash_list | [bytes](#bytes) | repeated | List of range hashes in a binary format |
+
+
+
+
+### Message GetRangeRequest
+Request part of object's payload
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| body | [GetRangeRequest.Body](#neo.fs.v2.object.GetRangeRequest.Body) | | Body of get range object request message. |
+| meta_header | [neo.fs.v2.session.RequestMetaHeader](#neo.fs.v2.session.RequestMetaHeader) | | Carries request meta information. Header data is used only to regulate message transport and does not affect request execution. |
+| verify_header | [neo.fs.v2.session.RequestVerificationHeader](#neo.fs.v2.session.RequestVerificationHeader) | | Carries request verification information. This header is used to authenticate the nodes of the message route and check the correctness of transmission. |
+
+
+
+
+### Message GetRangeRequest.Body
+Byte range of object's payload request body
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| address | [neo.fs.v2.refs.Address](#neo.fs.v2.refs.Address) | | Address of the object containing the requested payload range |
+| range | [Range](#neo.fs.v2.object.Range) | | Requested payload range |
+| raw | [bool](#bool) | | If `raw` flag is set, request will work only with objects that are physically stored on the peer node. |
+
+
+
+
+### Message GetRangeResponse
+Get part of object's payload
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| body | [GetRangeResponse.Body](#neo.fs.v2.object.GetRangeResponse.Body) | | Body of get range object response message. |
+| meta_header | [neo.fs.v2.session.ResponseMetaHeader](#neo.fs.v2.session.ResponseMetaHeader) | | Carries response meta information. Header data is used only to regulate message transport and does not affect request execution. |
+| verify_header | [neo.fs.v2.session.ResponseVerificationHeader](#neo.fs.v2.session.ResponseVerificationHeader) | | Carries response verification information. This header is used to authenticate the nodes of the message route and check the correctness of transmission. |
+
+
+
+
+### Message GetRangeResponse.Body
+Get Range response body uses streams to transfer the response. Because
+object payload considered a byte sequence, there is no need to have some
+initial preamble message. The requested byte range is sent as a series
+chunks.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| chunk | [bytes](#bytes) | | Chunked object payload's range. |
+| split_info | [SplitInfo](#neo.fs.v2.object.SplitInfo) | | Meta information of split hierarchy. |
+| ec_info | [ECInfo](#neo.fs.v2.object.ECInfo) | | Meta information for EC object assembly. |
+
+
+
+
+### Message GetRequest
+GET object request
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| body | [GetRequest.Body](#neo.fs.v2.object.GetRequest.Body) | | Body of get object request message. |
+| meta_header | [neo.fs.v2.session.RequestMetaHeader](#neo.fs.v2.session.RequestMetaHeader) | | Carries request meta information. Header data is used only to regulate message transport and does not affect request execution. |
+| verify_header | [neo.fs.v2.session.RequestVerificationHeader](#neo.fs.v2.session.RequestVerificationHeader) | | Carries request verification information. This header is used to authenticate the nodes of the message route and check the correctness of transmission. |
+
+
+
+
+### Message GetRequest.Body
+GET Object request body
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| address | [neo.fs.v2.refs.Address](#neo.fs.v2.refs.Address) | | Address of the requested object |
+| raw | [bool](#bool) | | If `raw` flag is set, request will work only with objects that are physically stored on the peer node |
+
+
+
+
+### Message GetResponse
+GET object response
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| body | [GetResponse.Body](#neo.fs.v2.object.GetResponse.Body) | | Body of get object response message. |
+| meta_header | [neo.fs.v2.session.ResponseMetaHeader](#neo.fs.v2.session.ResponseMetaHeader) | | Carries response meta information. Header data is used only to regulate message transport and does not affect request execution. |
+| verify_header | [neo.fs.v2.session.ResponseVerificationHeader](#neo.fs.v2.session.ResponseVerificationHeader) | | Carries response verification information. This header is used to authenticate the nodes of the message route and check the correctness of transmission. |
+
+
+
+
+### Message GetResponse.Body
+GET Object Response body
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| init | [GetResponse.Body.Init](#neo.fs.v2.object.GetResponse.Body.Init) | | Initial part of the object stream |
+| chunk | [bytes](#bytes) | | Chunked object payload |
+| split_info | [SplitInfo](#neo.fs.v2.object.SplitInfo) | | Meta information of split hierarchy for object assembly. |
+| ec_info | [ECInfo](#neo.fs.v2.object.ECInfo) | | Meta information for EC object assembly. |
+
+
+
+
+### Message GetResponse.Body.Init
+Initial part of the `Object` structure stream. Technically it's a
+set of all `Object` structure's fields except `payload`.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| object_id | [neo.fs.v2.refs.ObjectID](#neo.fs.v2.refs.ObjectID) | | Object's unique identifier. |
+| signature | [neo.fs.v2.refs.Signature](#neo.fs.v2.refs.Signature) | | Signed `ObjectID` |
+| header | [Header](#neo.fs.v2.object.Header) | | Object metadata headers |
+
+
+
+
+### Message HeadRequest
+Object HEAD request
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| body | [HeadRequest.Body](#neo.fs.v2.object.HeadRequest.Body) | | Body of head object request message. |
+| meta_header | [neo.fs.v2.session.RequestMetaHeader](#neo.fs.v2.session.RequestMetaHeader) | | Carries request meta information. Header data is used only to regulate message transport and does not affect request execution. |
+| verify_header | [neo.fs.v2.session.RequestVerificationHeader](#neo.fs.v2.session.RequestVerificationHeader) | | Carries request verification information. This header is used to authenticate the nodes of the message route and check the correctness of transmission. |
+
+
+
+
+### Message HeadRequest.Body
+Object HEAD request body
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| address | [neo.fs.v2.refs.Address](#neo.fs.v2.refs.Address) | | Address of the object with the requested Header |
+| main_only | [bool](#bool) | | Return only minimal header subset |
+| raw | [bool](#bool) | | If `raw` flag is set, request will work only with objects that are physically stored on the peer node |
+
+
+
+
+### Message HeadResponse
+Object HEAD response
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| body | [HeadResponse.Body](#neo.fs.v2.object.HeadResponse.Body) | | Body of head object response message. |
+| meta_header | [neo.fs.v2.session.ResponseMetaHeader](#neo.fs.v2.session.ResponseMetaHeader) | | Carries response meta information. Header data is used only to regulate message transport and does not affect request execution. |
+| verify_header | [neo.fs.v2.session.ResponseVerificationHeader](#neo.fs.v2.session.ResponseVerificationHeader) | | Carries response verification information. This header is used to authenticate the nodes of the message route and check the correctness of transmission. |
+
+
+
+
+### Message HeadResponse.Body
+Object HEAD response body
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| header | [HeaderWithSignature](#neo.fs.v2.object.HeaderWithSignature) | | Full object's `Header` with `ObjectID` signature |
+| short_header | [ShortHeader](#neo.fs.v2.object.ShortHeader) | | Short object header |
+| split_info | [SplitInfo](#neo.fs.v2.object.SplitInfo) | | Meta information of split hierarchy. Indicates that the object is virtual, manual assembly is required. |
+| ec_info | [ECInfo](#neo.fs.v2.object.ECInfo) | | Meta information for EC object assembly. |
+
+
+
+
+### Message HeaderWithSignature
+Tuple of a full object header and signature of an `ObjectID`. \
+Signed `ObjectID` is present to verify full header's authenticity through the
+following steps:
+
+1. Calculate `SHA-256` of the marshalled `Header` structure
+2. Check if the resulting hash matches `ObjectID`
+3. Check if `ObjectID` signature in `signature` field is correct
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| header | [Header](#neo.fs.v2.object.Header) | | Full object header |
+| signature | [neo.fs.v2.refs.Signature](#neo.fs.v2.refs.Signature) | | Signed `ObjectID` to verify full header's authenticity |
+
+
+
+
+### Message PatchRequest
+Object PATCH request
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| body | [PatchRequest.Body](#neo.fs.v2.object.PatchRequest.Body) | | Body for patch request message. |
+| meta_header | [neo.fs.v2.session.RequestMetaHeader](#neo.fs.v2.session.RequestMetaHeader) | | Carries request meta information. Header data is used only to regulate message transport and does not affect request execution. |
+| verify_header | [neo.fs.v2.session.RequestVerificationHeader](#neo.fs.v2.session.RequestVerificationHeader) | | Carries request verification information. This header is used to authenticate the nodes of the message route and check the correctness of transmission. |
+
+
+
+
+### Message PatchRequest.Body
+PATCH request body
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| address | [neo.fs.v2.refs.Address](#neo.fs.v2.refs.Address) | | The address of the object that is requested to get patched. |
+| new_attributes | [Header.Attribute](#neo.fs.v2.object.Header.Attribute) | repeated | New attributes for the object. See `replace_attributes` flag usage to define how new attributes should be set. |
+| replace_attributes | [bool](#bool) | | If this flag is set, then the object's attributes will be entirely replaced by `new_attributes` list. The empty `new_attributes` list with `replace_attributes = true` just resets attributes list for the object.
+
+Default `false` value for this flag means the attributes will be just merged. If the incoming `new_attributes` list contains already existing key, then it just replaces it while merging the lists. |
+| patch | [PatchRequest.Body.Patch](#neo.fs.v2.object.PatchRequest.Body.Patch) | | The patch that is applied for the object. |
+
+
+
+
+### Message PatchRequest.Body.Patch
+The patch for the object's payload.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| source_range | [Range](#neo.fs.v2.object.Range) | | The range of the source object for which the payload is replaced by the patch's chunk. If the range's `length = 0`, then the patch's chunk is just appended to the original payload starting from the `offest` without any replace. |
+| chunk | [bytes](#bytes) | | The chunk that is being appended to or that replaces the original payload on the given range. |
+
+
+
+
+### Message PatchResponse
+Object PATCH response
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| body | [PatchResponse.Body](#neo.fs.v2.object.PatchResponse.Body) | | Body for patch response message. |
+| meta_header | [neo.fs.v2.session.ResponseMetaHeader](#neo.fs.v2.session.ResponseMetaHeader) | | Carries response meta information. Header data is used only to regulate message transport and does not affect request execution. |
+| verify_header | [neo.fs.v2.session.ResponseVerificationHeader](#neo.fs.v2.session.ResponseVerificationHeader) | | Carries response verification information. This header is used to authenticate the nodes of the message route and check the correctness of transmission. |
+
+
+
+
+### Message PatchResponse.Body
+PATCH response body
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| object_id | [neo.fs.v2.refs.ObjectID](#neo.fs.v2.refs.ObjectID) | | The object ID of the saved patched object. |
+
+
+
+
+### Message PutRequest
+PUT object request
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| body | [PutRequest.Body](#neo.fs.v2.object.PutRequest.Body) | | Body of put object request message. |
+| meta_header | [neo.fs.v2.session.RequestMetaHeader](#neo.fs.v2.session.RequestMetaHeader) | | Carries request meta information. Header data is used only to regulate message transport and does not affect request execution. |
+| verify_header | [neo.fs.v2.session.RequestVerificationHeader](#neo.fs.v2.session.RequestVerificationHeader) | | Carries request verification information. This header is used to authenticate the nodes of the message route and check the correctness of transmission. |
+
+
+
+
+### Message PutRequest.Body
+PUT request body
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| init | [PutRequest.Body.Init](#neo.fs.v2.object.PutRequest.Body.Init) | | Initial part of the object stream |
+| chunk | [bytes](#bytes) | | Chunked object payload |
+
+
+
+
+### Message PutRequest.Body.Init
+Newly created object structure parameters. If some optional parameters
+are not set, they will be calculated by a peer node.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| object_id | [neo.fs.v2.refs.ObjectID](#neo.fs.v2.refs.ObjectID) | | ObjectID if available. |
+| signature | [neo.fs.v2.refs.Signature](#neo.fs.v2.refs.Signature) | | Object signature if available |
+| header | [Header](#neo.fs.v2.object.Header) | | Object's Header |
+| copies_number | [uint32](#uint32) | repeated | Number of copies of the object to store within the RPC call. By default, object is processed according to the container's placement policy. Can be one of: 1. A single number; applied to the whole request and is treated as a minimal number of nodes that must store an object to complete the request successfully. 2. An ordered array; every number is treated as a minimal number of nodes in a corresponding placement vector that must store an object to complete the request successfully. The length MUST equal the placement vectors number, otherwise request is considered malformed. |
+
+
+
+
+### Message PutResponse
+PUT Object response
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| body | [PutResponse.Body](#neo.fs.v2.object.PutResponse.Body) | | Body of put object response message. |
+| meta_header | [neo.fs.v2.session.ResponseMetaHeader](#neo.fs.v2.session.ResponseMetaHeader) | | Carries response meta information. Header data is used only to regulate message transport and does not affect request execution. |
+| verify_header | [neo.fs.v2.session.ResponseVerificationHeader](#neo.fs.v2.session.ResponseVerificationHeader) | | Carries response verification information. This header is used to authenticate the nodes of the message route and check the correctness of transmission. |
+
+
+
+
+### Message PutResponse.Body
+PUT Object response body
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| object_id | [neo.fs.v2.refs.ObjectID](#neo.fs.v2.refs.ObjectID) | | Identifier of the saved object |
+
+
+
+
+### Message PutSingleRequest
+Object PUT Single request
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| body | [PutSingleRequest.Body](#neo.fs.v2.object.PutSingleRequest.Body) | | Body of put single object request message. |
+| meta_header | [neo.fs.v2.session.RequestMetaHeader](#neo.fs.v2.session.RequestMetaHeader) | | Carries request meta information. Header data is used only to regulate message transport and does not affect request execution. |
+| verify_header | [neo.fs.v2.session.RequestVerificationHeader](#neo.fs.v2.session.RequestVerificationHeader) | | Carries request verification information. This header is used to authenticate the nodes of the message route and check the correctness of transmission. |
+
+
+
+
+### Message PutSingleRequest.Body
+PUT Single request body
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| object | [Object](#neo.fs.v2.object.Object) | | Prepared object with payload. |
+| copies_number | [uint32](#uint32) | repeated | Number of copies of the object to store within the RPC call. By default, object is processed according to the container's placement policy. Every number is treated as a minimal number of nodes in a corresponding placement vector that must store an object to complete the request successfully. The length MUST equal the placement vectors number, otherwise request is considered malformed. |
+
+
+
+
+### Message PutSingleResponse
+Object PUT Single response
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| body | [PutSingleResponse.Body](#neo.fs.v2.object.PutSingleResponse.Body) | | Body of put single object response message. |
+| meta_header | [neo.fs.v2.session.ResponseMetaHeader](#neo.fs.v2.session.ResponseMetaHeader) | | Carries response meta information. Header data is used only to regulate message transport and does not affect request execution. |
+| verify_header | [neo.fs.v2.session.ResponseVerificationHeader](#neo.fs.v2.session.ResponseVerificationHeader) | | Carries response verification information. This header is used to authenticate the nodes of the message route and check the correctness of transmission. |
+
+
+
+
+### Message PutSingleResponse.Body
+PUT Single Object response body
+
+
+
+
+
+### Message Range
+Object payload range.Ranges of zero length SHOULD be considered as invalid.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| offset | [uint64](#uint64) | | Offset of the range from the object payload start |
+| length | [uint64](#uint64) | | Length in bytes of the object payload range |
+
+
+
+
+### Message SearchRequest
+Object Search request
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| body | [SearchRequest.Body](#neo.fs.v2.object.SearchRequest.Body) | | Body of search object request message. |
+| meta_header | [neo.fs.v2.session.RequestMetaHeader](#neo.fs.v2.session.RequestMetaHeader) | | Carries request meta information. Header data is used only to regulate message transport and does not affect request execution. |
+| verify_header | [neo.fs.v2.session.RequestVerificationHeader](#neo.fs.v2.session.RequestVerificationHeader) | | Carries request verification information. This header is used to authenticate the nodes of the message route and check the correctness of transmission. |
+
+
+
+
+### Message SearchRequest.Body
+Object Search request body
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| container_id | [neo.fs.v2.refs.ContainerID](#neo.fs.v2.refs.ContainerID) | | Container identifier were to search |
+| version | [uint32](#uint32) | | Version of the Query Language used |
+| filters | [SearchRequest.Body.Filter](#neo.fs.v2.object.SearchRequest.Body.Filter) | repeated | List of search expressions |
+
+
+
+
+### Message SearchRequest.Body.Filter
+Filter structure checks if the object header field or the attribute
+content matches a value.
+
+If no filters are set, search request will return all objects of the
+container, including Regular object and Tombstone
+objects. Most human users expect to get only object they can directly
+work with. In that case, `$Object:ROOT` filter should be used.
+
+By default `key` field refers to the corresponding object's `Attribute`.
+Some Object's header fields can also be accessed by adding `$Object:`
+prefix to the name. Here is the list of fields available via this prefix:
+
+* $Object:version \
+ version
+* $Object:objectID \
+ object_id
+* $Object:containerID \
+ container_id
+* $Object:ownerID \
+ owner_id
+* $Object:creationEpoch \
+ creation_epoch
+* $Object:payloadLength \
+ payload_length
+* $Object:payloadHash \
+ payload_hash
+* $Object:objectType \
+ object_type
+* $Object:homomorphicHash \
+ homomorphic_hash
+* $Object:split.parent \
+ object_id of parent
+* $Object:split.splitID \
+ 16 byte UUIDv4 used to identify the split object hierarchy parts
+* $Object:ec.parent \
+ If the object is stored according to EC policy, then ec_parent
+ attribute is set to return an id list of all related EC chunks.
+
+There are some well-known filter aliases to match objects by certain
+properties:
+
+* $Object:ROOT \
+ Returns only `REGULAR` type objects that are not split or that are the
+ top level root objects in a split hierarchy. This includes objects not
+ present physically, like large objects split into smaller objects
+ without a separate top-level root object. Objects of other types like
+ Locks and Tombstones will not be shown. This filter may be
+ useful for listing objects like `ls` command of some virtual file
+ system. This filter is activated if the `key` exists, disregarding the
+ value and matcher type.
+* $Object:PHY \
+ Returns only objects physically stored in the system. This filter is
+ activated if the `key` exists, disregarding the value and matcher type.
+
+Note: using filters with a key with prefix `$Object:` and match type
+`NOT_PRESENT `is not recommended since this is not a cross-version
+approach. Behavior when processing this kind of filters is undefined.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| match_type | [MatchType](#neo.fs.v2.object.MatchType) | | Match type to use |
+| key | [string](#string) | | Attribute or Header fields to match |
+| value | [string](#string) | | Value to match |
+
+
+
+
+### Message SearchResponse
+Search response
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| body | [SearchResponse.Body](#neo.fs.v2.object.SearchResponse.Body) | | Body of search object response message. |
+| meta_header | [neo.fs.v2.session.ResponseMetaHeader](#neo.fs.v2.session.ResponseMetaHeader) | | Carries response meta information. Header data is used only to regulate message transport and does not affect request execution. |
+| verify_header | [neo.fs.v2.session.ResponseVerificationHeader](#neo.fs.v2.session.ResponseVerificationHeader) | | Carries response verification information. This header is used to authenticate the nodes of the message route and check the correctness of transmission. |
+
+
+
+
+### Message SearchResponse.Body
+Object Search response body
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| id_list | [neo.fs.v2.refs.ObjectID](#neo.fs.v2.refs.ObjectID) | repeated | List of `ObjectID`s that match the search query |
+
+
+
+
+
+
+
+
+
+
+## object/types.proto
+
+
+
+
+
+
+
+### Message ECInfo
+Meta information for the erasure-encoded object.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| chunks | [ECInfo.Chunk](#neo.fs.v2.object.ECInfo.Chunk) | repeated | Chunk stored on the node. |
+
+
+
+
+### Message ECInfo.Chunk
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| id | [neo.fs.v2.refs.ObjectID](#neo.fs.v2.refs.ObjectID) | | Object ID of the chunk. |
+| index | [uint32](#uint32) | | Index of the chunk. |
+| total | [uint32](#uint32) | | Total number of chunks in this split. |
+
+
+
+
+### Message Header
+Object Header
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| version | [neo.fs.v2.refs.Version](#neo.fs.v2.refs.Version) | | Object format version. Effectively, the version of API library used to create particular object |
+| container_id | [neo.fs.v2.refs.ContainerID](#neo.fs.v2.refs.ContainerID) | | Object's container |
+| owner_id | [neo.fs.v2.refs.OwnerID](#neo.fs.v2.refs.OwnerID) | | Object's owner |
+| creation_epoch | [uint64](#uint64) | | Object creation Epoch |
+| payload_length | [uint64](#uint64) | | Size of payload in bytes. `0xFFFFFFFFFFFFFFFF` means `payload_length` is unknown. |
+| payload_hash | [neo.fs.v2.refs.Checksum](#neo.fs.v2.refs.Checksum) | | Hash of payload bytes |
+| object_type | [ObjectType](#neo.fs.v2.object.ObjectType) | | Type of the object payload content |
+| homomorphic_hash | [neo.fs.v2.refs.Checksum](#neo.fs.v2.refs.Checksum) | | Homomorphic hash of the object payload |
+| session_token | [neo.fs.v2.session.SessionToken](#neo.fs.v2.session.SessionToken) | | Session token, if it was used during Object creation. Need it to verify integrity and authenticity out of Request scope. |
+| attributes | [Header.Attribute](#neo.fs.v2.object.Header.Attribute) | repeated | User-defined object attributes |
+| split | [Header.Split](#neo.fs.v2.object.Header.Split) | | Position of the object in the split hierarchy |
+| ec | [Header.EC](#neo.fs.v2.object.Header.EC) | | Erasure code chunk information. |
+
+
+
+
+### Message Header.Attribute
+`Attribute` is a user-defined Key-Value metadata pair attached to an
+object.
+
+Key name must be an object-unique valid UTF-8 string. Value can't be empty.
+Objects with duplicated attribute names or attributes with empty values
+will be considered invalid.
+
+There are some "well-known" attributes starting with `__SYSTEM__`
+(`__NEOFS__` is deprecated) prefix that affect system behaviour:
+
+* [ __SYSTEM__UPLOAD_ID ] \
+ (`__NEOFS__UPLOAD_ID` is deprecated) \
+ Marks smaller parts of a split bigger object
+* [ __SYSTEM__EXPIRATION_EPOCH ] \
+ (`__NEOFS__EXPIRATION_EPOCH` is deprecated) \
+ The epoch after which object with no LOCKs on it becomes unavailable.
+ Locked object continues to be available until each of the LOCKs expire.
+* [ __SYSTEM__TICK_EPOCH ] \
+ (`__NEOFS__TICK_EPOCH` is deprecated) \
+ Decimal number that defines what epoch must produce
+ object notification with UTF-8 object address in a
+ body (`0` value produces notification right after
+ object put)
+* [ __SYSTEM__TICK_TOPIC ] \
+ (`__NEOFS__TICK_TOPIC` is deprecated) \
+ UTF-8 string topic ID that is used for object notification
+
+And some well-known attributes used by applications only:
+
+* Name \
+ Human-friendly name
+* FileName \
+ File name to be associated with the object on saving
+* FilePath \
+ Full path to be associated with the object on saving. Should start with a
+ '/' and use '/' as a delimiting symbol. Trailing '/' should be
+ interpreted as a virtual directory marker. If an object has conflicting
+ FilePath and FileName, FilePath should have higher priority, because it
+ is used to construct the directory tree. FilePath with trailing '/' and
+ non-empty FileName attribute should not be used together.
+* Timestamp \
+ User-defined local time of object creation in Unix Timestamp format
+* Content-Type \
+ MIME Content Type of object's payload
+
+For detailed description of each well-known attribute please see the
+corresponding section in FrostFS Technical Specification.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| key | [string](#string) | | string key to the object attribute |
+| value | [string](#string) | | string value of the object attribute |
+
+
+
+
+### Message Header.EC
+Erasure code can be applied to any object.
+Information about encoded object structure is stored in `EC` header.
+All objects belonging to a single EC group have the same `parent` field.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| parent | [neo.fs.v2.refs.ObjectID](#neo.fs.v2.refs.ObjectID) | | Identifier of the origin object. Known to all chunks. |
+| index | [uint32](#uint32) | | Index of this chunk. |
+| total | [uint32](#uint32) | | Total number of chunks in this split. |
+| header_length | [uint32](#uint32) | | Total length of a parent header. Used to trim padding zeroes. |
+| header | [bytes](#bytes) | | Chunk of a parent header. |
+| parent_split_id | [bytes](#bytes) | | As the origin object is EC-splitted its identifier is known to all chunks as parent. But parent itself can be a part of Split (does not relate to EC-split). In this case parent_split_id should be set. |
+| parent_split_parent_id | [neo.fs.v2.refs.ObjectID](#neo.fs.v2.refs.ObjectID) | | EC-parent's parent ID. parent_split_parent_id is set if EC-parent, itself, is a part of Split and if an object ID of its parent is presented. The field allows to determine how EC-chunk is placed in Split hierarchy. |
+| parent_attributes | [Header.Attribute](#neo.fs.v2.object.Header.Attribute) | repeated | EC parent's attributes. |
+
+
+
+
+### Message Header.Split
+Bigger objects can be split into a chain of smaller objects. Information
+about inter-dependencies between spawned objects and how to re-construct
+the original one is in the `Split` headers. Parent and children objects
+must be within the same container.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| parent | [neo.fs.v2.refs.ObjectID](#neo.fs.v2.refs.ObjectID) | | Identifier of the origin object. Known only to the minor child. |
+| 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. |
+
+
+
+
+### Message Object
+Object structure. Object is immutable and content-addressed. It means
+`ObjectID` will change if the header or the payload changes. It's calculated
+as a hash of header field which contains hash of the object's payload.
+
+For non-regular object types payload format depends on object type specified
+in the header.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| object_id | [neo.fs.v2.refs.ObjectID](#neo.fs.v2.refs.ObjectID) | | Object's unique identifier. |
+| signature | [neo.fs.v2.refs.Signature](#neo.fs.v2.refs.Signature) | | Signed object_id |
+| header | [Header](#neo.fs.v2.object.Header) | | Object metadata headers |
+| payload | [bytes](#bytes) | | Payload bytes |
+
+
+
+
+### Message ShortHeader
+Short header fields
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| version | [neo.fs.v2.refs.Version](#neo.fs.v2.refs.Version) | | Object format version. Effectively, the version of API library used to create particular object. |
+| creation_epoch | [uint64](#uint64) | | Epoch when the object was created |
+| owner_id | [neo.fs.v2.refs.OwnerID](#neo.fs.v2.refs.OwnerID) | | Object's owner |
+| object_type | [ObjectType](#neo.fs.v2.object.ObjectType) | | Type of the object payload content |
+| payload_length | [uint64](#uint64) | | Size of payload in bytes. `0xFFFFFFFFFFFFFFFF` means `payload_length` is unknown |
+| payload_hash | [neo.fs.v2.refs.Checksum](#neo.fs.v2.refs.Checksum) | | Hash of payload bytes |
+| homomorphic_hash | [neo.fs.v2.refs.Checksum](#neo.fs.v2.refs.Checksum) | | Homomorphic hash of the object payload |
+
+
+
+
+### Message SplitInfo
+Meta information of split hierarchy for object assembly. With the last part
+one can traverse linked list of split hierarchy back to the first part and
+assemble the original object. With a linking object one can assemble an
+object right from the object parts.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| split_id | [bytes](#bytes) | | 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. |
+
+
+
+
+
+
+### MatchType
+Type of match expression
+
+| Name | Number | Description |
+| ---- | ------ | ----------- |
+| MATCH_TYPE_UNSPECIFIED | 0 | Unknown. Not used |
+| STRING_EQUAL | 1 | Full string match |
+| STRING_NOT_EQUAL | 2 | Full string mismatch |
+| NOT_PRESENT | 3 | Lack of key |
+| COMMON_PREFIX | 4 | String prefix match |
+
+
+
+
+
+### ObjectType
+Type of the object payload content. Only `REGULAR` type objects can be split,
+hence `TOMBSTONE` and `LOCK` payload is limited by the
+maximum object size.
+
+String presentation of object type is the same as definition:
+* REGULAR
+* TOMBSTONE
+* LOCK
+
+| Name | Number | Description |
+| ---- | ------ | ----------- |
+| REGULAR | 0 | Just a normal object |
+| TOMBSTONE | 1 | Used internally to identify deleted objects |
+| LOCK | 3 | Object lock |
+
+
+
+
+
+
+## Scalar Value Types
+
+| .proto Type | Notes | C++ Type | Java Type | Python Type |
+| ----------- | ----- | -------- | --------- | ----------- |
+| double | | double | double | float |
+| float | | float | float | float |
+| 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 |
+| 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 |
+| uint32 | Uses variable-length encoding. | uint32 | int | int/long |
+| uint64 | Uses variable-length encoding. | uint64 | long | int/long |
+| sint32 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s. | int32 | int | int |
+| sint64 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s. | int64 | long | int/long |
+| fixed32 | Always four bytes. More efficient than uint32 if values are often greater than 2^28. | uint32 | int | int |
+| fixed64 | Always eight bytes. More efficient than uint64 if values are often greater than 2^56. | uint64 | long | int/long |
+| sfixed32 | Always four bytes. | int32 | int | int |
+| sfixed64 | Always eight bytes. | int64 | long | int/long |
+| bool | | bool | boolean | boolean |
+| string | A string must always contain UTF-8 encoded or 7-bit ASCII text. | string | String | str/unicode |
+| bytes | May contain any arbitrary sequence of bytes. | string | ByteString | str |
diff --git a/proto-docs/refs.md b/proto-docs/refs.md
new file mode 100644
index 0000000..3ad3126
--- /dev/null
+++ b/proto-docs/refs.md
@@ -0,0 +1,233 @@
+# Protocol Documentation
+
+
+## Table of Contents
+
+- [refs/types.proto](#refs/types.proto)
+
+ - Messages
+ - [Address](#neo.fs.v2.refs.Address)
+ - [Checksum](#neo.fs.v2.refs.Checksum)
+ - [ContainerID](#neo.fs.v2.refs.ContainerID)
+ - [ObjectID](#neo.fs.v2.refs.ObjectID)
+ - [OwnerID](#neo.fs.v2.refs.OwnerID)
+ - [Signature](#neo.fs.v2.refs.Signature)
+ - [SignatureRFC6979](#neo.fs.v2.refs.SignatureRFC6979)
+ - [Version](#neo.fs.v2.refs.Version)
+
+
+- [Scalar Value Types](#scalar-value-types)
+
+
+
+
+
+
+## refs/types.proto
+
+
+
+
+
+
+
+### Message Address
+Objects in FrostFS are addressed by their ContainerID and ObjectID.
+
+String presentation of `Address` is a concatenation of string encoded
+`ContainerID` and `ObjectID` delimited by '/' character.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| container_id | [ContainerID](#neo.fs.v2.refs.ContainerID) | | Container identifier |
+| object_id | [ObjectID](#neo.fs.v2.refs.ObjectID) | | Object identifier |
+
+
+
+
+### Message Checksum
+Checksum message.
+Depending on checksum algorithm type, the string presentation may vary:
+
+* TZ \
+ Hex encoded string without `0x` prefix
+* SHA256 \
+ Hex encoded string without `0x` prefix
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| type | [ChecksumType](#neo.fs.v2.refs.ChecksumType) | | Checksum algorithm type |
+| sum | [bytes](#bytes) | | Checksum itself |
+
+
+
+
+### Message ContainerID
+FrostFS container identifier. Container structures are immutable and
+content-addressed.
+
+`ContainerID` is a 32 byte long
+[SHA256](https://csrc.nist.gov/publications/detail/fips/180/4/final) hash of
+stable-marshalled container message.
+
+String presentation is a
+[base58](https://tools.ietf.org/html/draft-msporny-base58-02) encoded string.
+
+JSON value will be data encoded as a string using standard base64
+encoding with paddings. Either
+[standard](https://tools.ietf.org/html/rfc4648#section-4) or
+[URL-safe](https://tools.ietf.org/html/rfc4648#section-5) base64 encoding
+with/without paddings are accepted.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| value | [bytes](#bytes) | | Container identifier in a binary format. |
+
+
+
+
+### Message ObjectID
+FrostFS Object unique identifier. Objects are immutable and
+content-addressed. It means `ObjectID` will change if the `header` or the
+`payload` changes.
+
+`ObjectID` is a 32 byte long
+[SHA256](https://csrc.nist.gov/publications/detail/fips/180/4/final) hash of
+the object's `header` field, which, in it's turn, contains the hash of the
+object's payload.
+
+String presentation is a
+[base58](https://tools.ietf.org/html/draft-msporny-base58-02) encoded string.
+
+JSON value will be data encoded as a string using standard base64
+encoding with paddings. Either
+[standard](https://tools.ietf.org/html/rfc4648#section-4) or
+[URL-safe](https://tools.ietf.org/html/rfc4648#section-5) base64 encoding
+with/without paddings are accepted.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| value | [bytes](#bytes) | | Object identifier in a binary format |
+
+
+
+
+### Message OwnerID
+`OwnerID` is a derivative of a user's main public key. The transformation
+algorithm is the same as for Neo3 wallet addresses. Neo3 wallet address can
+be directly used as `OwnerID`.
+
+`OwnerID` is a 25 bytes sequence starting with Neo version prefix byte
+followed by 20 bytes of ScrptHash and 4 bytes of checksum.
+
+String presentation is a [Base58
+Check](https://en.bitcoin.it/wiki/Base58Check_encoding) Encoded string.
+
+JSON value will be data encoded as a string using standard base64
+encoding with paddings. Either
+[standard](https://tools.ietf.org/html/rfc4648#section-4) or
+[URL-safe](https://tools.ietf.org/html/rfc4648#section-5) base64 encoding
+with/without paddings are accepted.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| value | [bytes](#bytes) | | Identifier of the container owner in a binary format |
+
+
+
+
+### Message Signature
+Signature of something in FrostFS.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| key | [bytes](#bytes) | | Public key used for signing |
+| sign | [bytes](#bytes) | | Signature |
+| scheme | [SignatureScheme](#neo.fs.v2.refs.SignatureScheme) | | Scheme contains digital signature scheme identifier |
+
+
+
+
+### Message SignatureRFC6979
+RFC 6979 signature.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| key | [bytes](#bytes) | | Public key used for signing |
+| sign | [bytes](#bytes) | | Deterministic ECDSA with SHA-256 hashing |
+
+
+
+
+### Message Version
+API version used by a node.
+
+String presentation is a Semantic Versioning 2.0.0 compatible version string
+with 'v' prefix. i.e. `vX.Y`, where `X` is the major number, `Y` is the minor
+number.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| major | [uint32](#uint32) | | Major API version |
+| minor | [uint32](#uint32) | | Minor API version |
+
+
+
+
+
+
+### ChecksumType
+Checksum algorithm type.
+
+| Name | Number | Description |
+| ---- | ------ | ----------- |
+| CHECKSUM_TYPE_UNSPECIFIED | 0 | Unknown. Not used |
+| TZ | 1 | Tillich-Zemor homomorphic hash function |
+| SHA256 | 2 | SHA-256 |
+
+
+
+
+
+### SignatureScheme
+Signature scheme describes digital signing scheme used for (key, signature)
+pair.
+
+| Name | Number | Description |
+| ---- | ------ | ----------- |
+| ECDSA_SHA512 | 0 | ECDSA with SHA-512 hashing (FIPS 186-3) |
+| ECDSA_RFC6979_SHA256 | 1 | Deterministic ECDSA with SHA-256 hashing (RFC 6979) |
+| ECDSA_RFC6979_SHA256_WALLET_CONNECT | 2 | Deterministic ECDSA with SHA-256 hashing using WalletConnect API. Here the algorithm is the same, but the message format differs. |
+
+
+
+
+
+
+## Scalar Value Types
+
+| .proto Type | Notes | C++ Type | Java Type | Python Type |
+| ----------- | ----- | -------- | --------- | ----------- |
+| double | | double | double | float |
+| float | | float | float | float |
+| 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 |
+| 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 |
+| uint32 | Uses variable-length encoding. | uint32 | int | int/long |
+| uint64 | Uses variable-length encoding. | uint64 | long | int/long |
+| sint32 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s. | int32 | int | int |
+| sint64 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s. | int64 | long | int/long |
+| fixed32 | Always four bytes. More efficient than uint32 if values are often greater than 2^28. | uint32 | int | int |
+| fixed64 | Always eight bytes. More efficient than uint64 if values are often greater than 2^56. | uint64 | long | int/long |
+| sfixed32 | Always four bytes. | int32 | int | int |
+| sfixed64 | Always eight bytes. | int64 | long | int/long |
+| bool | | bool | boolean | boolean |
+| string | A string must always contain UTF-8 encoded or 7-bit ASCII text. | string | String | str/unicode |
+| bytes | May contain any arbitrary sequence of bytes. | string | ByteString | str |
diff --git a/proto-docs/session.md b/proto-docs/session.md
new file mode 100644
index 0000000..984db48
--- /dev/null
+++ b/proto-docs/session.md
@@ -0,0 +1,366 @@
+# Protocol Documentation
+
+
+## Table of Contents
+
+- [session/service.proto](#session/service.proto)
+ - Services
+ - [SessionService](#neo.fs.v2.session.SessionService)
+
+ - Messages
+ - [CreateRequest](#neo.fs.v2.session.CreateRequest)
+ - [CreateRequest.Body](#neo.fs.v2.session.CreateRequest.Body)
+ - [CreateResponse](#neo.fs.v2.session.CreateResponse)
+ - [CreateResponse.Body](#neo.fs.v2.session.CreateResponse.Body)
+
+
+- [session/types.proto](#session/types.proto)
+
+ - Messages
+ - [ContainerSessionContext](#neo.fs.v2.session.ContainerSessionContext)
+ - [ObjectSessionContext](#neo.fs.v2.session.ObjectSessionContext)
+ - [ObjectSessionContext.Target](#neo.fs.v2.session.ObjectSessionContext.Target)
+ - [RequestMetaHeader](#neo.fs.v2.session.RequestMetaHeader)
+ - [RequestVerificationHeader](#neo.fs.v2.session.RequestVerificationHeader)
+ - [ResponseMetaHeader](#neo.fs.v2.session.ResponseMetaHeader)
+ - [ResponseVerificationHeader](#neo.fs.v2.session.ResponseVerificationHeader)
+ - [SessionToken](#neo.fs.v2.session.SessionToken)
+ - [SessionToken.Body](#neo.fs.v2.session.SessionToken.Body)
+ - [SessionToken.Body.TokenLifetime](#neo.fs.v2.session.SessionToken.Body.TokenLifetime)
+ - [XHeader](#neo.fs.v2.session.XHeader)
+
+
+- [Scalar Value Types](#scalar-value-types)
+
+
+
+
+
+
+## session/service.proto
+
+
+
+
+
+
+### Service "neo.fs.v2.session.SessionService"
+`SessionService` allows to establish a temporary trust relationship between
+two peer nodes and generate a `SessionToken` as the proof of trust to be
+attached in requests for further verification. Please see corresponding
+section of FrostFS Technical Specification for details.
+
+```
+rpc Create(CreateRequest) returns (CreateResponse);
+
+```
+
+#### Method Create
+
+Open a new session between two peers.
+
+Statuses:
+- **OK** (0, SECTION_SUCCESS):
+session has been successfully opened;
+- Common failures (SECTION_FAILURE_COMMON).
+
+| Name | Input | Output |
+| ---- | ----- | ------ |
+| Create | [CreateRequest](#neo.fs.v2.session.CreateRequest) | [CreateResponse](#neo.fs.v2.session.CreateResponse) |
+
+
+
+
+
+### Message CreateRequest
+Information necessary for opening a session.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| body | [CreateRequest.Body](#neo.fs.v2.session.CreateRequest.Body) | | Body of a create session token request message. |
+| meta_header | [RequestMetaHeader](#neo.fs.v2.session.RequestMetaHeader) | | Carries request meta information. Header data is used only to regulate message transport and does not affect request execution. |
+| verify_header | [RequestVerificationHeader](#neo.fs.v2.session.RequestVerificationHeader) | | Carries request verification information. This header is used to authenticate the nodes of the message route and check the correctness of transmission. |
+
+
+
+
+### Message CreateRequest.Body
+Session creation request body
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| owner_id | [neo.fs.v2.refs.OwnerID](#neo.fs.v2.refs.OwnerID) | | Session initiating user's or node's key derived `OwnerID` |
+| expiration | [uint64](#uint64) | | Session expiration `Epoch` |
+
+
+
+
+### Message CreateResponse
+Information about the opened session.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| body | [CreateResponse.Body](#neo.fs.v2.session.CreateResponse.Body) | | Body of create session token response message. |
+| meta_header | [ResponseMetaHeader](#neo.fs.v2.session.ResponseMetaHeader) | | Carries response meta information. Header data is used only to regulate message transport and does not affect request execution. |
+| verify_header | [ResponseVerificationHeader](#neo.fs.v2.session.ResponseVerificationHeader) | | Carries response verification information. This header is used to authenticate the nodes of the message route and check the correctness of transmission. |
+
+
+
+
+### Message CreateResponse.Body
+Session creation response body
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| id | [bytes](#bytes) | | Identifier of a newly created session |
+| session_key | [bytes](#bytes) | | Public key used for session |
+
+
+
+
+
+
+
+
+
+
+## session/types.proto
+
+
+
+
+
+
+
+### Message ContainerSessionContext
+Context information for Session Tokens related to ContainerService requests.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| verb | [ContainerSessionContext.Verb](#neo.fs.v2.session.ContainerSessionContext.Verb) | | Type of request for which the token is issued |
+| wildcard | [bool](#bool) | | Spreads the action to all owner containers. If set, container_id field is ignored. |
+| container_id | [neo.fs.v2.refs.ContainerID](#neo.fs.v2.refs.ContainerID) | | Particular container to which the action applies. Ignored if wildcard flag is set. |
+
+
+
+
+### Message ObjectSessionContext
+Context information for Session Tokens related to ObjectService requests
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| verb | [ObjectSessionContext.Verb](#neo.fs.v2.session.ObjectSessionContext.Verb) | | Type of request for which the token is issued |
+| target | [ObjectSessionContext.Target](#neo.fs.v2.session.ObjectSessionContext.Target) | | Object session target. MUST be correctly formed and set. If `objects` field is not empty, then the session applies only to these elements, otherwise, to all objects from the specified container. |
+
+
+
+
+### Message ObjectSessionContext.Target
+Carries objects involved in the object session.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| container | [neo.fs.v2.refs.ContainerID](#neo.fs.v2.refs.ContainerID) | | Indicates which container the session is spread to. Field MUST be set and correct. |
+| objects | [neo.fs.v2.refs.ObjectID](#neo.fs.v2.refs.ObjectID) | repeated | Indicates which objects the session is spread to. Objects are expected to be stored in the FrostFS container referenced by `container` field. Each element MUST have correct format. |
+
+
+
+
+### Message RequestMetaHeader
+Meta information attached to the request. When forwarded between peers,
+request meta headers are folded in matryoshka style.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| version | [neo.fs.v2.refs.Version](#neo.fs.v2.refs.Version) | | Peer's API version used |
+| epoch | [uint64](#uint64) | | Peer's local epoch number. Set to 0 if unknown. |
+| ttl | [uint32](#uint32) | | Maximum number of intermediate nodes in the request route |
+| x_headers | [XHeader](#neo.fs.v2.session.XHeader) | repeated | Request X-Headers |
+| session_token | [SessionToken](#neo.fs.v2.session.SessionToken) | | Session token within which the request is sent |
+| bearer_token | [neo.fs.v2.acl.BearerToken](#neo.fs.v2.acl.BearerToken) | | `BearerToken` with eACL overrides for the request |
+| origin | [RequestMetaHeader](#neo.fs.v2.session.RequestMetaHeader) | | `RequestMetaHeader` of the origin request |
+| magic_number | [uint64](#uint64) | | FrostFS network magic. Must match the value for the network that the server belongs to. |
+
+
+
+
+### Message RequestVerificationHeader
+Verification info for the request signed by all intermediate nodes.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| body_signature | [neo.fs.v2.refs.Signature](#neo.fs.v2.refs.Signature) | | Request Body signature. Should be generated once by the request initiator. |
+| meta_signature | [neo.fs.v2.refs.Signature](#neo.fs.v2.refs.Signature) | | Request Meta signature is added and signed by each intermediate node |
+| origin_signature | [neo.fs.v2.refs.Signature](#neo.fs.v2.refs.Signature) | | Signature of previous hops |
+| origin | [RequestVerificationHeader](#neo.fs.v2.session.RequestVerificationHeader) | | Chain of previous hops signatures |
+
+
+
+
+### Message ResponseMetaHeader
+Information about the response
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| version | [neo.fs.v2.refs.Version](#neo.fs.v2.refs.Version) | | Peer's API version used |
+| epoch | [uint64](#uint64) | | Peer's local epoch number |
+| ttl | [uint32](#uint32) | | Maximum number of intermediate nodes in the request route |
+| x_headers | [XHeader](#neo.fs.v2.session.XHeader) | repeated | Response X-Headers |
+| origin | [ResponseMetaHeader](#neo.fs.v2.session.ResponseMetaHeader) | | `ResponseMetaHeader` of the origin request |
+| status | [neo.fs.v2.status.Status](#neo.fs.v2.status.Status) | | Status return |
+
+
+
+
+### Message ResponseVerificationHeader
+Verification info for the response signed by all intermediate nodes
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| body_signature | [neo.fs.v2.refs.Signature](#neo.fs.v2.refs.Signature) | | Response Body signature. Should be generated once by an answering node. |
+| meta_signature | [neo.fs.v2.refs.Signature](#neo.fs.v2.refs.Signature) | | Response Meta signature is added and signed by each intermediate node |
+| origin_signature | [neo.fs.v2.refs.Signature](#neo.fs.v2.refs.Signature) | | Signature of previous hops |
+| origin | [ResponseVerificationHeader](#neo.fs.v2.session.ResponseVerificationHeader) | | Chain of previous hops signatures |
+
+
+
+
+### Message SessionToken
+FrostFS Session Token.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| body | [SessionToken.Body](#neo.fs.v2.session.SessionToken.Body) | | Session Token contains the proof of trust between peers to be attached in requests for further verification. Please see corresponding section of FrostFS Technical Specification for details. |
+| signature | [neo.fs.v2.refs.Signature](#neo.fs.v2.refs.Signature) | | Signature of `SessionToken` information |
+
+
+
+
+### Message SessionToken.Body
+Session Token body
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| id | [bytes](#bytes) | | Token identifier is a valid UUIDv4 in binary form |
+| owner_id | [neo.fs.v2.refs.OwnerID](#neo.fs.v2.refs.OwnerID) | | Identifier of the session initiator |
+| lifetime | [SessionToken.Body.TokenLifetime](#neo.fs.v2.session.SessionToken.Body.TokenLifetime) | | Lifetime of the session |
+| session_key | [bytes](#bytes) | | Public key used in session |
+| object | [ObjectSessionContext](#neo.fs.v2.session.ObjectSessionContext) | | ObjectService session context |
+| container | [ContainerSessionContext](#neo.fs.v2.session.ContainerSessionContext) | | ContainerService session context |
+
+
+
+
+### Message SessionToken.Body.TokenLifetime
+Lifetime parameters of the token. Field names taken from rfc7519.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| exp | [uint64](#uint64) | | Expiration Epoch |
+| nbf | [uint64](#uint64) | | Not valid before Epoch |
+| iat | [uint64](#uint64) | | Issued at Epoch |
+
+
+
+
+### Message XHeader
+Extended headers for Request/Response. They may contain any user-defined
+headers to be interpreted on application level.
+
+Key name must be a unique valid UTF-8 string. Value can't be empty. Requests
+or Responses with duplicated header names or headers with empty values will
+be considered invalid.
+
+There are some "well-known" headers starting with `__SYSTEM__` (`__NEOFS__`
+is deprecated) prefix that affect system behaviour:
+
+* [ __SYSTEM__NETMAP_EPOCH ] \
+ (`__NEOFS__NETMAP_EPOCH` is deprecated) \
+ Netmap epoch to use for object placement calculation. The `value` is string
+ encoded `uint64` in decimal presentation. If set to '0' or not set, the
+ current epoch only will be used.
+* [ __SYSTEM__NETMAP_LOOKUP_DEPTH ] \
+ (`__NEOFS__NETMAP_LOOKUP_DEPTH` is deprecated) \
+ If object can't be found using current epoch's netmap, this header limits
+ how many past epochs the node can look up through. The `value` is string
+ encoded `uint64` in decimal presentation. If set to '0' or not set, only
+ the current epoch will be used.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| key | [string](#string) | | Key of the X-Header |
+| value | [string](#string) | | Value of the X-Header |
+
+
+
+
+
+
+### ContainerSessionContext.Verb
+Container request verbs
+
+| Name | Number | Description |
+| ---- | ------ | ----------- |
+| VERB_UNSPECIFIED | 0 | Unknown verb |
+| PUT | 1 | Refers to container.Put RPC call |
+| DELETE | 2 | Refers to container.Delete RPC call |
+| SETEACL | 3 | Refers to container.SetExtendedACL RPC call |
+
+
+
+
+
+### ObjectSessionContext.Verb
+Object request verbs
+
+| Name | Number | Description |
+| ---- | ------ | ----------- |
+| VERB_UNSPECIFIED | 0 | Unknown verb |
+| PUT | 1 | Refers to object.Put RPC call |
+| GET | 2 | Refers to object.Get RPC call |
+| HEAD | 3 | Refers to object.Head RPC call |
+| SEARCH | 4 | Refers to object.Search RPC call |
+| DELETE | 5 | Refers to object.Delete RPC call |
+| RANGE | 6 | Refers to object.GetRange RPC call |
+| RANGEHASH | 7 | Refers to object.GetRangeHash RPC call |
+| PATCH | 8 | Refers to object.Patch RPC call |
+
+
+
+
+
+
+## Scalar Value Types
+
+| .proto Type | Notes | C++ Type | Java Type | Python Type |
+| ----------- | ----- | -------- | --------- | ----------- |
+| double | | double | double | float |
+| float | | float | float | float |
+| 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 |
+| 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 |
+| uint32 | Uses variable-length encoding. | uint32 | int | int/long |
+| uint64 | Uses variable-length encoding. | uint64 | long | int/long |
+| sint32 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s. | int32 | int | int |
+| sint64 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s. | int64 | long | int/long |
+| fixed32 | Always four bytes. More efficient than uint32 if values are often greater than 2^28. | uint32 | int | int |
+| fixed64 | Always eight bytes. More efficient than uint64 if values are often greater than 2^56. | uint64 | long | int/long |
+| sfixed32 | Always four bytes. | int32 | int | int |
+| sfixed64 | Always eight bytes. | int64 | long | int/long |
+| bool | | bool | boolean | boolean |
+| string | A string must always contain UTF-8 encoded or 7-bit ASCII text. | string | String | str/unicode |
+| bytes | May contain any arbitrary sequence of bytes. | string | ByteString | str |
diff --git a/proto-docs/status.md b/proto-docs/status.md
new file mode 100644
index 0000000..b00d000
--- /dev/null
+++ b/proto-docs/status.md
@@ -0,0 +1,198 @@
+# Protocol Documentation
+
+
+## Table of Contents
+
+- [status/types.proto](#status/types.proto)
+
+ - Messages
+ - [Status](#neo.fs.v2.status.Status)
+ - [Status.Detail](#neo.fs.v2.status.Status.Detail)
+
+
+- [Scalar Value Types](#scalar-value-types)
+
+
+
+
+
+
+## status/types.proto
+
+
+
+
+
+
+
+### Message Status
+Declares the general format of the status returns of the FrostFS RPC
+protocol. Status is present in all response messages. Each RPC of FrostFS
+protocol describes the possible outcomes and details of the operation.
+
+Each status is assigned a one-to-one numeric code. Any unique result of an
+operation in FrostFS is unambiguously associated with the code value.
+
+Numerical set of codes is split into 1024-element sections. An enumeration
+is defined for each section. Values can be referred to in the following ways:
+
+* numerical value ranging from 0 to 4,294,967,295 (global code);
+
+* values from enumeration (local code). The formula for the ratio of the
+ local code (`L`) of a defined section (`S`) to the global one (`G`):
+ `G = 1024 * S + L`.
+
+All outcomes are divided into successful and failed, which corresponds
+to the success or failure of the operation. The definition of success
+follows the semantics of RPC and the description of its purpose.
+The server must not attach code that is the opposite of the outcome type.
+
+See the set of return codes in the description for calls.
+
+Each status can carry a developer-facing error message. It should be a human
+readable text in English. The server should not transmit (and the client
+should not expect) useful information in the message. Field `details`
+should make the return more detailed.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| code | [uint32](#uint32) | | The status code |
+| message | [string](#string) | | Developer-facing error message |
+| details | [Status.Detail](#neo.fs.v2.status.Status.Detail) | repeated | Data detailing the outcome of the operation. Must be unique by ID. |
+
+
+
+
+### Message Status.Detail
+Return detail. It contains additional information that can be used to
+analyze the response. Each code defines a set of details that can be
+attached to a status. Client should not handle details that are not
+covered by the code.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| id | [uint32](#uint32) | | Detail ID. The identifier is required to determine the binary format of the detail and how to decode it. |
+| value | [bytes](#bytes) | | Binary status detail. Must follow the format associated with ID. The possibility of missing a value must be explicitly allowed. |
+
+
+
+
+
+
+### APEManager
+Section of status for APE manager related operations.
+
+| Name | Number | Description |
+| ---- | ------ | ----------- |
+| APE_MANAGER_ACCESS_DENIED | 0 | [**5120**] The operation is denied by APE manager. |
+
+
+
+
+
+### CommonFail
+Section of failed statuses independent of the operation.
+
+| Name | Number | Description |
+| ---- | ------ | ----------- |
+| INTERNAL | 0 | [**1024**] Internal server error, default failure. Not detailed. If the server cannot match failed outcome to the code, it should use this code. |
+| WRONG_MAGIC_NUMBER | 1 | [**1025**] Wrong magic of the FrostFS network. Details: - [**0**] Magic number of the served FrostFS network (big-endian 64-bit unsigned integer). |
+| SIGNATURE_VERIFICATION_FAIL | 2 | [**1026**] Signature verification failure. |
+| NODE_UNDER_MAINTENANCE | 3 | [**1027**] Node is under maintenance. |
+| INVALID_ARGUMENT | 4 | [**1028**] Invalid argument error. If the server fails on validation of a request parameter as the client sent it incorrectly, then this code should be used. |
+| RESOURCE_EXHAUSTED | 5 | [**1029**] Resource exhausted failure. This code should be used if the operation cannot be performed due to a lack of resources. |
+
+
+
+
+
+### Container
+Section of statuses for container-related operations.
+
+| Name | Number | Description |
+| ---- | ------ | ----------- |
+| CONTAINER_NOT_FOUND | 0 | [**3072**] Container not found. |
+| EACL_NOT_FOUND | 1 | [**3073**] eACL table not found. |
+| CONTAINER_ACCESS_DENIED | 2 | [**3074**] Container access denied. |
+
+
+
+
+
+### Object
+Section of statuses for object-related operations.
+
+| Name | Number | Description |
+| ---- | ------ | ----------- |
+| ACCESS_DENIED | 0 | [**2048**] Access denied by ACL. Details: - [**0**] Human-readable description (UTF-8 encoded string). |
+| OBJECT_NOT_FOUND | 1 | [**2049**] Object not found. |
+| LOCKED | 2 | [**2050**] Operation rejected by the object lock. |
+| LOCK_NON_REGULAR_OBJECT | 3 | [**2051**] Locking an object with a non-REGULAR type rejected. |
+| OBJECT_ALREADY_REMOVED | 4 | [**2052**] Object has been marked deleted. |
+| OUT_OF_RANGE | 5 | [**2053**] Invalid range has been requested for an object. |
+
+
+
+
+
+### Section
+Section identifiers.
+
+| Name | Number | Description |
+| ---- | ------ | ----------- |
+| SECTION_SUCCESS | 0 | Successful return codes. |
+| SECTION_FAILURE_COMMON | 1 | Failure codes regardless of the operation. |
+| SECTION_OBJECT | 2 | Object service-specific errors. |
+| SECTION_CONTAINER | 3 | Container service-specific errors. |
+| SECTION_SESSION | 4 | Session service-specific errors. |
+| SECTION_APE_MANAGER | 5 | Session service-specific errors. |
+
+
+
+
+
+### Session
+Section of statuses for session-related operations.
+
+| Name | Number | Description |
+| ---- | ------ | ----------- |
+| TOKEN_NOT_FOUND | 0 | [**4096**] Token not found. |
+| TOKEN_EXPIRED | 1 | [**4097**] Token has expired. |
+
+
+
+
+
+### Success
+Section of FrostFS successful return codes.
+
+| Name | Number | Description |
+| ---- | ------ | ----------- |
+| OK | 0 | [**0**] Default success. Not detailed. If the server cannot match successful outcome to the code, it should use this code. |
+
+
+
+
+
+
+## Scalar Value Types
+
+| .proto Type | Notes | C++ Type | Java Type | Python Type |
+| ----------- | ----- | -------- | --------- | ----------- |
+| double | | double | double | float |
+| float | | float | float | float |
+| 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 |
+| 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 |
+| uint32 | Uses variable-length encoding. | uint32 | int | int/long |
+| uint64 | Uses variable-length encoding. | uint64 | long | int/long |
+| sint32 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s. | int32 | int | int |
+| sint64 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s. | int64 | long | int/long |
+| fixed32 | Always four bytes. More efficient than uint32 if values are often greater than 2^28. | uint32 | int | int |
+| fixed64 | Always eight bytes. More efficient than uint64 if values are often greater than 2^56. | uint64 | long | int/long |
+| sfixed32 | Always four bytes. | int32 | int | int |
+| sfixed64 | Always eight bytes. | int64 | long | int/long |
+| bool | | bool | boolean | boolean |
+| string | A string must always contain UTF-8 encoded or 7-bit ASCII text. | string | String | str/unicode |
+| bytes | May contain any arbitrary sequence of bytes. | string | ByteString | str |
diff --git a/proto-docs/tombstone.md b/proto-docs/tombstone.md
new file mode 100644
index 0000000..467ad55
--- /dev/null
+++ b/proto-docs/tombstone.md
@@ -0,0 +1,62 @@
+# Protocol Documentation
+
+
+## Table of Contents
+
+- [tombstone/types.proto](#tombstone/types.proto)
+
+ - Messages
+ - [Tombstone](#neo.fs.v2.tombstone.Tombstone)
+
+
+- [Scalar Value Types](#scalar-value-types)
+
+
+
+
+
+
+## tombstone/types.proto
+
+
+
+
+
+
+
+### Message Tombstone
+Tombstone keeps record of deleted objects for a few epochs until they are
+purged from the FrostFS network.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| expiration_epoch | [uint64](#uint64) | | Last FrostFS epoch number of the tombstone lifetime. It's set by the tombstone creator depending on the current FrostFS network settings. A tombstone object must have the same expiration epoch value in `__SYSTEM__EXPIRATION_EPOCH` (`__NEOFS__EXPIRATION_EPOCH` is deprecated) attribute. Otherwise, the tombstone will be rejected by a storage node. |
+| split_id | [bytes](#bytes) | | 16 byte UUID used to identify the split object hierarchy parts. Must be unique inside a container. All objects participating in the split must have the same `split_id` value. |
+| members | [neo.fs.v2.refs.ObjectID](#neo.fs.v2.refs.ObjectID) | repeated | List of objects to be deleted. |
+
+
+
+
+
+
+
+## Scalar Value Types
+
+| .proto Type | Notes | C++ Type | Java Type | Python Type |
+| ----------- | ----- | -------- | --------- | ----------- |
+| double | | double | double | float |
+| float | | float | float | float |
+| 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 |
+| 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 |
+| uint32 | Uses variable-length encoding. | uint32 | int | int/long |
+| uint64 | Uses variable-length encoding. | uint64 | long | int/long |
+| sint32 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s. | int32 | int | int |
+| sint64 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s. | int64 | long | int/long |
+| fixed32 | Always four bytes. More efficient than uint32 if values are often greater than 2^28. | uint32 | int | int |
+| fixed64 | Always eight bytes. More efficient than uint64 if values are often greater than 2^56. | uint64 | long | int/long |
+| sfixed32 | Always four bytes. | int32 | int | int |
+| sfixed64 | Always eight bytes. | int64 | long | int/long |
+| bool | | bool | boolean | boolean |
+| string | A string must always contain UTF-8 encoded or 7-bit ASCII text. | string | String | str/unicode |
+| bytes | May contain any arbitrary sequence of bytes. | string | ByteString | str |
diff --git a/refs/types.proto b/refs/types.proto
new file mode 100644
index 0000000..2464c34
--- /dev/null
+++ b/refs/types.proto
@@ -0,0 +1,151 @@
+edition = "2023";
+
+package neo.fs.v2.refs;
+
+option go_package = "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/grpc;refs";
+option csharp_namespace = "Neo.FileStorage.API.Refs";
+
+// Objects in FrostFS are addressed by their ContainerID and ObjectID.
+//
+// String presentation of `Address` is a concatenation of string encoded
+// `ContainerID` and `ObjectID` delimited by '/' character.
+message Address {
+ // Container identifier
+ ContainerID container_id = 1 [ json_name = "containerID" ];
+ // Object identifier
+ ObjectID object_id = 2 [ json_name = "objectID" ];
+}
+
+// FrostFS Object unique identifier. Objects are immutable and
+// content-addressed. It means `ObjectID` will change if the `header` or the
+// `payload` changes.
+//
+// `ObjectID` is a 32 byte long
+// [SHA256](https://csrc.nist.gov/publications/detail/fips/180/4/final) hash of
+// the object's `header` field, which, in it's turn, contains the hash of the
+// object's payload.
+//
+// String presentation is a
+// [base58](https://tools.ietf.org/html/draft-msporny-base58-02) encoded string.
+//
+// JSON value will be data encoded as a string using standard base64
+// encoding with paddings. Either
+// [standard](https://tools.ietf.org/html/rfc4648#section-4) or
+// [URL-safe](https://tools.ietf.org/html/rfc4648#section-5) base64 encoding
+// with/without paddings are accepted.
+message ObjectID {
+ // Object identifier in a binary format
+ bytes value = 1 [ json_name = "value" ];
+}
+
+// FrostFS container identifier. Container structures are immutable and
+// content-addressed.
+//
+// `ContainerID` is a 32 byte long
+// [SHA256](https://csrc.nist.gov/publications/detail/fips/180/4/final) hash of
+// stable-marshalled container message.
+//
+// String presentation is a
+// [base58](https://tools.ietf.org/html/draft-msporny-base58-02) encoded string.
+//
+// JSON value will be data encoded as a string using standard base64
+// encoding with paddings. Either
+// [standard](https://tools.ietf.org/html/rfc4648#section-4) or
+// [URL-safe](https://tools.ietf.org/html/rfc4648#section-5) base64 encoding
+// with/without paddings are accepted.
+message ContainerID {
+ // Container identifier in a binary format.
+ bytes value = 1 [ json_name = "value" ];
+}
+
+// `OwnerID` is a derivative of a user's main public key. The transformation
+// algorithm is the same as for Neo3 wallet addresses. Neo3 wallet address can
+// be directly used as `OwnerID`.
+//
+// `OwnerID` is a 25 bytes sequence starting with Neo version prefix byte
+// followed by 20 bytes of ScrptHash and 4 bytes of checksum.
+//
+// String presentation is a [Base58
+// Check](https://en.bitcoin.it/wiki/Base58Check_encoding) Encoded string.
+//
+// JSON value will be data encoded as a string using standard base64
+// encoding with paddings. Either
+// [standard](https://tools.ietf.org/html/rfc4648#section-4) or
+// [URL-safe](https://tools.ietf.org/html/rfc4648#section-5) base64 encoding
+// with/without paddings are accepted.
+message OwnerID {
+ // Identifier of the container owner in a binary format
+ bytes value = 1 [ json_name = "value" ];
+}
+
+// API version used by a node.
+//
+// String presentation is a Semantic Versioning 2.0.0 compatible version string
+// with 'v' prefix. i.e. `vX.Y`, where `X` is the major number, `Y` is the minor
+// number.
+message Version {
+ // Major API version
+ uint32 major = 1 [ json_name = "major" ];
+
+ // Minor API version
+ uint32 minor = 2 [ json_name = "minor" ];
+}
+
+// Signature of something in FrostFS.
+message Signature {
+ // Public key used for signing
+ bytes key = 1 [ json_name = "key" ];
+ // Signature
+ bytes sign = 2 [ json_name = "signature" ];
+ // Scheme contains digital signature scheme identifier
+ SignatureScheme scheme = 3 [ json_name = "scheme" ];
+}
+
+// Signature scheme describes digital signing scheme used for (key, signature)
+// pair.
+enum SignatureScheme {
+ // ECDSA with SHA-512 hashing (FIPS 186-3)
+ ECDSA_SHA512 = 0;
+
+ // Deterministic ECDSA with SHA-256 hashing (RFC 6979)
+ ECDSA_RFC6979_SHA256 = 1;
+
+ // Deterministic ECDSA with SHA-256 hashing using WalletConnect API.
+ // Here the algorithm is the same, but the message format differs.
+ ECDSA_RFC6979_SHA256_WALLET_CONNECT = 2;
+}
+
+// RFC 6979 signature.
+message SignatureRFC6979 {
+ // Public key used for signing
+ bytes key = 1 [ json_name = "key" ];
+ // Deterministic ECDSA with SHA-256 hashing
+ bytes sign = 2 [ json_name = "signature" ];
+}
+
+// Checksum algorithm type.
+enum ChecksumType {
+ // Unknown. Not used
+ CHECKSUM_TYPE_UNSPECIFIED = 0;
+
+ // Tillich-Zemor homomorphic hash function
+ TZ = 1;
+
+ // SHA-256
+ SHA256 = 2;
+}
+
+// Checksum message.
+// Depending on checksum algorithm type, the string presentation may vary:
+//
+// * TZ \
+// Hex encoded string without `0x` prefix
+// * SHA256 \
+// Hex encoded string without `0x` prefix
+message Checksum {
+ // Checksum algorithm type
+ ChecksumType type = 1 [ json_name = "type" ];
+
+ // Checksum itself
+ bytes sum = 2 [ json_name = "sum" ];
+}
diff --git a/session/service.proto b/session/service.proto
new file mode 100644
index 0000000..c9a7948
--- /dev/null
+++ b/session/service.proto
@@ -0,0 +1,69 @@
+edition = "2023";
+
+package neo.fs.v2.session;
+
+option go_package = "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session/grpc;session";
+option csharp_namespace = "Neo.FileStorage.API.Session";
+
+import "refs/types.proto";
+import "session/types.proto";
+
+// `SessionService` allows to establish a temporary trust relationship between
+// two peer nodes and generate a `SessionToken` as the proof of trust to be
+// attached in requests for further verification. Please see corresponding
+// section of FrostFS Technical Specification for details.
+service SessionService {
+ // Open a new session between two peers.
+ //
+ // Statuses:
+ // - **OK** (0, SECTION_SUCCESS):
+ // session has been successfully opened;
+ // - Common failures (SECTION_FAILURE_COMMON).
+ rpc Create(CreateRequest) returns (CreateResponse);
+}
+
+// Information necessary for opening a session.
+message CreateRequest {
+ // Session creation request body
+ message Body {
+ // Session initiating user's or node's key derived `OwnerID`
+ neo.fs.v2.refs.OwnerID owner_id = 1;
+ // Session expiration `Epoch`
+ uint64 expiration = 2;
+ }
+ // Body of a create session token request message.
+ Body body = 1;
+
+ // Carries request meta information. Header data is used only to regulate
+ // message transport and does not affect request execution.
+ neo.fs.v2.session.RequestMetaHeader meta_header = 2;
+
+ // Carries request verification information. This header is used to
+ // authenticate the nodes of the message route and check the correctness of
+ // transmission.
+ neo.fs.v2.session.RequestVerificationHeader verify_header = 3;
+}
+
+// Information about the opened session.
+message CreateResponse {
+ // Session creation response body
+ message Body {
+ // Identifier of a newly created session
+ bytes id = 1;
+
+ // Public key used for session
+ bytes session_key = 2;
+ }
+
+ // Body of create session token response message.
+ Body body = 1;
+
+ // Carries response meta information. Header data is used only to regulate
+ // message transport and does not affect request execution.
+ neo.fs.v2.session.ResponseMetaHeader meta_header = 2;
+
+ // Carries response verification information. This header is used to
+ // authenticate the nodes of the message route and check the correctness of
+ // transmission.
+ neo.fs.v2.session.ResponseVerificationHeader verify_header = 3;
+}
diff --git a/session/types.proto b/session/types.proto
new file mode 100644
index 0000000..1e5b9db
--- /dev/null
+++ b/session/types.proto
@@ -0,0 +1,241 @@
+edition = "2023";
+
+package neo.fs.v2.session;
+
+option go_package = "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session/grpc;session";
+option csharp_namespace = "Neo.FileStorage.API.Session";
+
+import "refs/types.proto";
+import "acl/types.proto";
+import "status/types.proto";
+
+// Context information for Session Tokens related to ObjectService requests
+message ObjectSessionContext {
+ // Object request verbs
+ enum Verb {
+ // Unknown verb
+ VERB_UNSPECIFIED = 0;
+
+ // Refers to object.Put RPC call
+ PUT = 1;
+
+ // Refers to object.Get RPC call
+ GET = 2;
+
+ // Refers to object.Head RPC call
+ HEAD = 3;
+
+ // Refers to object.Search RPC call
+ SEARCH = 4;
+
+ // Refers to object.Delete RPC call
+ DELETE = 5;
+
+ // Refers to object.GetRange RPC call
+ RANGE = 6;
+
+ // Refers to object.GetRangeHash RPC call
+ RANGEHASH = 7;
+
+ // Refers to object.Patch RPC call
+ PATCH = 8;
+ }
+ // Type of request for which the token is issued
+ Verb verb = 1 [ json_name = "verb" ];
+
+ // Carries objects involved in the object session.
+ message Target {
+ // Indicates which container the session is spread to. Field MUST be set
+ // and correct.
+ refs.ContainerID container = 1 [ json_name = "container" ];
+
+ // Indicates which objects the session is spread to. Objects are expected
+ // to be stored in the FrostFS container referenced by `container` field.
+ // Each element MUST have correct format.
+ repeated refs.ObjectID objects = 2 [ json_name = "objects" ];
+ }
+ // Object session target. MUST be correctly formed and set. If `objects`
+ // field is not empty, then the session applies only to these elements,
+ // otherwise, to all objects from the specified container.
+ Target target = 2 [ json_name = "target" ];
+}
+
+// Context information for Session Tokens related to ContainerService requests.
+message ContainerSessionContext {
+ // Container request verbs
+ enum Verb {
+ // Unknown verb
+ VERB_UNSPECIFIED = 0;
+
+ // Refers to container.Put RPC call
+ PUT = 1;
+
+ // Refers to container.Delete RPC call
+ DELETE = 2;
+
+ // Refers to container.SetExtendedACL RPC call
+ SETEACL = 3;
+ }
+ // Type of request for which the token is issued
+ Verb verb = 1 [ json_name = "verb" ];
+
+ // Spreads the action to all owner containers.
+ // If set, container_id field is ignored.
+ bool wildcard = 2 [ json_name = "wildcard" ];
+
+ // Particular container to which the action applies.
+ // Ignored if wildcard flag is set.
+ refs.ContainerID container_id = 3 [ json_name = "containerID" ];
+}
+
+// FrostFS Session Token.
+message SessionToken {
+ // Session Token body
+ message Body {
+ // Token identifier is a valid UUIDv4 in binary form
+ bytes id = 1 [ json_name = "id" ];
+
+ // Identifier of the session initiator
+ neo.fs.v2.refs.OwnerID owner_id = 2 [ json_name = "ownerID" ];
+
+ // Lifetime parameters of the token. Field names taken from rfc7519.
+ message TokenLifetime {
+ // Expiration Epoch
+ uint64 exp = 1 [ json_name = "exp" ];
+
+ // Not valid before Epoch
+ uint64 nbf = 2 [ json_name = "nbf" ];
+
+ // Issued at Epoch
+ uint64 iat = 3 [ json_name = "iat" ];
+ }
+ // Lifetime of the session
+ TokenLifetime lifetime = 3 [ json_name = "lifetime" ];
+
+ // Public key used in session
+ bytes session_key = 4 [ json_name = "sessionKey" ];
+
+ // Session Context information
+ oneof context {
+ // ObjectService session context
+ ObjectSessionContext object = 5 [ json_name = "object" ];
+
+ // ContainerService session context
+ ContainerSessionContext container = 6 [ json_name = "container" ];
+ }
+ }
+ // Session Token contains the proof of trust between peers to be attached in
+ // requests for further verification. Please see corresponding section of
+ // FrostFS Technical Specification for details.
+ Body body = 1 [ json_name = "body" ];
+
+ // Signature of `SessionToken` information
+ neo.fs.v2.refs.Signature signature = 2 [ json_name = "signature" ];
+}
+
+// Extended headers for Request/Response. They may contain any user-defined
+// headers to be interpreted on application level.
+//
+// Key name must be a unique valid UTF-8 string. Value can't be empty. Requests
+// or Responses with duplicated header names or headers with empty values will
+// be considered invalid.
+//
+// There are some "well-known" headers starting with `__SYSTEM__` (`__NEOFS__`
+// is deprecated) prefix that affect system behaviour:
+//
+// * [ __SYSTEM__NETMAP_EPOCH ] \
+// (`__NEOFS__NETMAP_EPOCH` is deprecated) \
+// Netmap epoch to use for object placement calculation. The `value` is string
+// encoded `uint64` in decimal presentation. If set to '0' or not set, the
+// current epoch only will be used.
+// * [ __SYSTEM__NETMAP_LOOKUP_DEPTH ] \
+// (`__NEOFS__NETMAP_LOOKUP_DEPTH` is deprecated) \
+// If object can't be found using current epoch's netmap, this header limits
+// how many past epochs the node can look up through. The `value` is string
+// encoded `uint64` in decimal presentation. If set to '0' or not set, only
+// the current epoch will be used.
+message XHeader {
+ // Key of the X-Header
+ string key = 1 [ json_name = "key" ];
+
+ // Value of the X-Header
+ string value = 2 [ json_name = "value" ];
+}
+
+// Meta information attached to the request. When forwarded between peers,
+// request meta headers are folded in matryoshka style.
+message RequestMetaHeader {
+ // Peer's API version used
+ neo.fs.v2.refs.Version version = 1 [ json_name = "version" ];
+
+ // Peer's local epoch number. Set to 0 if unknown.
+ uint64 epoch = 2 [ json_name = "epoch" ];
+
+ // Maximum number of intermediate nodes in the request route
+ uint32 ttl = 3 [ json_name = "ttl" ];
+
+ // Request X-Headers
+ repeated XHeader x_headers = 4 [ json_name = "xHeaders" ];
+
+ // Session token within which the request is sent
+ SessionToken session_token = 5 [ json_name = "sessionToken" ];
+
+ // `BearerToken` with eACL overrides for the request
+ neo.fs.v2.acl.BearerToken bearer_token = 6 [ json_name = "bearerToken" ];
+
+ // `RequestMetaHeader` of the origin request
+ RequestMetaHeader origin = 7 [ json_name = "origin" ];
+
+ // FrostFS network magic. Must match the value for the network
+ // that the server belongs to.
+ uint64 magic_number = 8 [ json_name = "magicNumber" ];
+}
+
+// Information about the response
+message ResponseMetaHeader {
+ // Peer's API version used
+ neo.fs.v2.refs.Version version = 1 [ json_name = "version" ];
+
+ // Peer's local epoch number
+ uint64 epoch = 2 [ json_name = "epoch" ];
+
+ // Maximum number of intermediate nodes in the request route
+ uint32 ttl = 3 [ json_name = "ttl" ];
+
+ // Response X-Headers
+ repeated XHeader x_headers = 4 [ json_name = "xHeaders" ];
+
+ // `ResponseMetaHeader` of the origin request
+ ResponseMetaHeader origin = 5 [ json_name = "origin" ];
+
+ // Status return
+ neo.fs.v2.status.Status status = 6 [ json_name = "status" ];
+}
+
+// Verification info for the request signed by all intermediate nodes.
+message RequestVerificationHeader {
+ // Request Body signature. Should be generated once by the request initiator.
+ neo.fs.v2.refs.Signature body_signature = 1 [ json_name = "bodySignature" ];
+ // Request Meta signature is added and signed by each intermediate node
+ neo.fs.v2.refs.Signature meta_signature = 2 [ json_name = "metaSignature" ];
+ // Signature of previous hops
+ neo.fs.v2.refs.Signature origin_signature = 3
+ [ json_name = "originSignature" ];
+
+ // Chain of previous hops signatures
+ RequestVerificationHeader origin = 4 [ json_name = "origin" ];
+}
+
+// Verification info for the response signed by all intermediate nodes
+message ResponseVerificationHeader {
+ // Response Body signature. Should be generated once by an answering node.
+ neo.fs.v2.refs.Signature body_signature = 1 [ json_name = "bodySignature" ];
+ // Response Meta signature is added and signed by each intermediate node
+ neo.fs.v2.refs.Signature meta_signature = 2 [ json_name = "metaSignature" ];
+ // Signature of previous hops
+ neo.fs.v2.refs.Signature origin_signature = 3
+ [ json_name = "originSignature" ];
+
+ // Chain of previous hops signatures
+ ResponseVerificationHeader origin = 4 [ json_name = "origin" ];
+}
diff --git a/status/types.proto b/status/types.proto
new file mode 100644
index 0000000..6a98f84
--- /dev/null
+++ b/status/types.proto
@@ -0,0 +1,166 @@
+edition = "2023";
+
+package neo.fs.v2.status;
+
+option go_package = "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/status/grpc;status";
+option csharp_namespace = "Neo.FileStorage.API.Status";
+
+// Declares the general format of the status returns of the FrostFS RPC
+// protocol. Status is present in all response messages. Each RPC of FrostFS
+// protocol describes the possible outcomes and details of the operation.
+//
+// Each status is assigned a one-to-one numeric code. Any unique result of an
+// operation in FrostFS is unambiguously associated with the code value.
+//
+// Numerical set of codes is split into 1024-element sections. An enumeration
+// is defined for each section. Values can be referred to in the following ways:
+//
+// * numerical value ranging from 0 to 4,294,967,295 (global code);
+//
+// * values from enumeration (local code). The formula for the ratio of the
+// local code (`L`) of a defined section (`S`) to the global one (`G`):
+// `G = 1024 * S + L`.
+//
+// All outcomes are divided into successful and failed, which corresponds
+// to the success or failure of the operation. The definition of success
+// follows the semantics of RPC and the description of its purpose.
+// The server must not attach code that is the opposite of the outcome type.
+//
+// See the set of return codes in the description for calls.
+//
+// Each status can carry a developer-facing error message. It should be a human
+// readable text in English. The server should not transmit (and the client
+// should not expect) useful information in the message. Field `details`
+// should make the return more detailed.
+message Status {
+ // The status code
+ uint32 code = 1;
+
+ // Developer-facing error message
+ string message = 2;
+
+ // Return detail. It contains additional information that can be used to
+ // analyze the response. Each code defines a set of details that can be
+ // attached to a status. Client should not handle details that are not
+ // covered by the code.
+ message Detail {
+ // Detail ID. The identifier is required to determine the binary format
+ // of the detail and how to decode it.
+ uint32 id = 1;
+
+ // Binary status detail. Must follow the format associated with ID.
+ // The possibility of missing a value must be explicitly allowed.
+ bytes value = 2;
+ }
+
+ // Data detailing the outcome of the operation. Must be unique by ID.
+ repeated Detail details = 3;
+}
+
+// Section identifiers.
+enum Section {
+ // Successful return codes.
+ SECTION_SUCCESS = 0;
+
+ // Failure codes regardless of the operation.
+ SECTION_FAILURE_COMMON = 1;
+
+ // Object service-specific errors.
+ SECTION_OBJECT = 2;
+
+ // Container service-specific errors.
+ SECTION_CONTAINER = 3;
+
+ // Session service-specific errors.
+ SECTION_SESSION = 4;
+
+ // Session service-specific errors.
+ SECTION_APE_MANAGER = 5;
+}
+
+// Section of FrostFS successful return codes.
+enum Success {
+ // [**0**] Default success. Not detailed.
+ // If the server cannot match successful outcome to the code, it should
+ // use this code.
+ OK = 0;
+}
+
+// Section of failed statuses independent of the operation.
+enum CommonFail {
+ // [**1024**] Internal server error, default failure. Not detailed.
+ // If the server cannot match failed outcome to the code, it should
+ // use this code.
+ INTERNAL = 0;
+
+ // [**1025**] Wrong magic of the FrostFS network.
+ // Details:
+ // - [**0**] Magic number of the served FrostFS network (big-endian 64-bit
+ // unsigned integer).
+ WRONG_MAGIC_NUMBER = 1;
+
+ // [**1026**] Signature verification failure.
+ SIGNATURE_VERIFICATION_FAIL = 2;
+
+ // [**1027**] Node is under maintenance.
+ NODE_UNDER_MAINTENANCE = 3;
+
+ // [**1028**] Invalid argument error. If the server fails on validation of a
+ // request parameter as the client sent it incorrectly, then this code should
+ // be used.
+ INVALID_ARGUMENT = 4;
+
+ // [**1029**] Resource exhausted failure. This code should be used
+ // if the operation cannot be performed due to a lack of resources.
+ RESOURCE_EXHAUSTED = 5;
+}
+
+// Section of statuses for object-related operations.
+enum Object {
+ // [**2048**] Access denied by ACL.
+ // Details:
+ // - [**0**] Human-readable description (UTF-8 encoded string).
+ ACCESS_DENIED = 0;
+
+ // [**2049**] Object not found.
+ OBJECT_NOT_FOUND = 1;
+
+ // [**2050**] Operation rejected by the object lock.
+ LOCKED = 2;
+
+ // [**2051**] Locking an object with a non-REGULAR type rejected.
+ LOCK_NON_REGULAR_OBJECT = 3;
+
+ // [**2052**] Object has been marked deleted.
+ OBJECT_ALREADY_REMOVED = 4;
+
+ // [**2053**] Invalid range has been requested for an object.
+ OUT_OF_RANGE = 5;
+}
+
+// Section of statuses for container-related operations.
+enum Container {
+ // [**3072**] Container not found.
+ CONTAINER_NOT_FOUND = 0;
+
+ // [**3073**] eACL table not found.
+ EACL_NOT_FOUND = 1;
+
+ // [**3074**] Container access denied.
+ CONTAINER_ACCESS_DENIED = 2;
+}
+
+// Section of statuses for session-related operations.
+enum Session {
+ // [**4096**] Token not found.
+ TOKEN_NOT_FOUND = 0;
+
+ // [**4097**] Token has expired.
+ TOKEN_EXPIRED = 1;
+}
+
+// Section of status for APE manager related operations.
+enum APEManager {
+ // [**5120**] The operation is denied by APE manager.
+ APE_MANAGER_ACCESS_DENIED = 0;
+}
diff --git a/tombstone/types.proto b/tombstone/types.proto
new file mode 100644
index 0000000..aac19b0
--- /dev/null
+++ b/tombstone/types.proto
@@ -0,0 +1,27 @@
+edition = "2023";
+
+package neo.fs.v2.tombstone;
+
+option go_package = "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/tombstone/grpc;tombstone";
+option csharp_namespace = "Neo.FileStorage.API.Tombstone";
+
+import "refs/types.proto";
+
+// Tombstone keeps record of deleted objects for a few epochs until they are
+// purged from the FrostFS network.
+message Tombstone {
+ // Last FrostFS epoch number of the tombstone lifetime. It's set by the
+ // tombstone creator depending on the current FrostFS network settings. A
+ // tombstone object must have the same expiration epoch value in
+ // `__SYSTEM__EXPIRATION_EPOCH` (`__NEOFS__EXPIRATION_EPOCH` is deprecated)
+ // attribute. Otherwise, the tombstone will be rejected by a storage node.
+ uint64 expiration_epoch = 1 [ json_name = "expirationEpoch" ];
+
+ // 16 byte UUID used to identify the split object hierarchy parts. Must be
+ // unique inside a container. All objects participating in the split must
+ // have the same `split_id` value.
+ bytes split_id = 2 [ json_name = "splitID" ];
+
+ // List of objects to be deleted.
+ repeated neo.fs.v2.refs.ObjectID members = 3 [ json_name = "members" ];
+}