2020-08-05 21:52:40 +00:00
# Protocol Documentation
< a name = "top" > < / a >
## Table of Contents
2020-09-03 09:19:02 +00:00
- [netmap/service.proto ](#netmap/service.proto )
- Services
- [NetmapService ](#neo.fs.v2.netmap.NetmapService )
- Messages
- [LocalNodeInfoRequest ](#neo.fs.v2.netmap.LocalNodeInfoRequest )
- [LocalNodeInfoRequest.Body ](#neo.fs.v2.netmap.LocalNodeInfoRequest.Body )
- [LocalNodeInfoResponse ](#neo.fs.v2.netmap.LocalNodeInfoResponse )
- [LocalNodeInfoResponse.Body ](#neo.fs.v2.netmap.LocalNodeInfoResponse.Body )
2021-02-26 07:53:47 +00:00
- [NetworkInfoRequest ](#neo.fs.v2.netmap.NetworkInfoRequest )
- [NetworkInfoRequest.Body ](#neo.fs.v2.netmap.NetworkInfoRequest.Body )
- [NetworkInfoResponse ](#neo.fs.v2.netmap.NetworkInfoResponse )
- [NetworkInfoResponse.Body ](#neo.fs.v2.netmap.NetworkInfoResponse.Body )
2020-09-03 09:19:02 +00:00
2020-08-05 21:52:40 +00:00
- [netmap/types.proto ](#netmap/types.proto )
- Messages
2020-08-23 11:42:01 +00:00
- [Filter ](#neo.fs.v2.netmap.Filter )
2021-10-14 15:27:45 +00:00
- [NetworkConfig ](#neo.fs.v2.netmap.NetworkConfig )
- [NetworkConfig.Parameter ](#neo.fs.v2.netmap.NetworkConfig.Parameter )
2021-02-26 07:53:47 +00:00
- [NetworkInfo ](#neo.fs.v2.netmap.NetworkInfo )
2020-08-13 16:18:53 +00:00
- [NodeInfo ](#neo.fs.v2.netmap.NodeInfo )
- [NodeInfo.Attribute ](#neo.fs.v2.netmap.NodeInfo.Attribute )
- [PlacementPolicy ](#neo.fs.v2.netmap.PlacementPolicy )
2020-08-23 11:42:01 +00:00
- [Replica ](#neo.fs.v2.netmap.Replica )
- [Selector ](#neo.fs.v2.netmap.Selector )
2020-08-05 21:52:40 +00:00
- [Scalar Value Types ](#scalar-value-types )
2020-09-03 09:19:02 +00:00
< a name = "netmap/service.proto" > < / a >
< p align = "right" > < a href = "#top" > Top< / a > < / p >
## netmap/service.proto
< a name = "neo.fs.v2.netmap.NetmapService" > < / a >
### Service "neo.fs.v2.netmap.NetmapService"
2020-10-16 11:40:12 +00:00
`NetmapService` provides methods to work with `Network Map` and information
required to build it. The resulting `Network Map` is stored in sidechain
`Netmap` smart contract, while related information can be obtained from other
NeoFS nodes.
2020-09-03 09:19:02 +00:00
```
rpc LocalNodeInfo(LocalNodeInfoRequest) returns (LocalNodeInfoResponse);
2021-02-26 07:53:47 +00:00
rpc NetworkInfo(NetworkInfoRequest) returns (NetworkInfoResponse);
2020-09-03 09:19:02 +00:00
```
#### Method LocalNodeInfo
2020-10-16 11:40:12 +00:00
Get NodeInfo structure from the particular node directly. Node information
can be taken from `Netmap` smart contract, but in some cases the one may
want to get recent information directly, or to talk to the node not yet
present in `Network Map` to find out what API version can be used for
further communication. Can also be used to check if node is up and running.
2020-09-03 09:19:02 +00:00
| Name | Input | Output |
| ---- | ----- | ------ |
| LocalNodeInfo | [LocalNodeInfoRequest ](#neo.fs.v2.netmap.LocalNodeInfoRequest ) | [LocalNodeInfoResponse ](#neo.fs.v2.netmap.LocalNodeInfoResponse ) |
2021-02-26 07:53:47 +00:00
#### Method NetworkInfo
Read recent information about the NeoFS network.
| Name | Input | Output |
| ---- | ----- | ------ |
| NetworkInfo | [NetworkInfoRequest ](#neo.fs.v2.netmap.NetworkInfoRequest ) | [NetworkInfoResponse ](#neo.fs.v2.netmap.NetworkInfoResponse ) |
2020-09-03 09:19:02 +00:00
<!-- end services -->
< a name = "neo.fs.v2.netmap.LocalNodeInfoRequest" > < / a >
### Message LocalNodeInfoRequest
2020-10-16 11:40:12 +00:00
Get NodeInfo structure from the particular node directly
2020-09-03 09:19:02 +00:00
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
2020-10-16 11:40:12 +00:00
| body | [LocalNodeInfoRequest.Body ](#neo.fs.v2.netmap.LocalNodeInfoRequest.Body ) | | Body of the LocalNodeInfo request message |
2020-09-03 09:19:02 +00:00
| 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. |
< a name = "neo.fs.v2.netmap.LocalNodeInfoRequest.Body" > < / a >
### Message LocalNodeInfoRequest.Body
2020-10-16 11:40:12 +00:00
LocalNodeInfo request body is empty.
2020-09-03 09:19:02 +00:00
< a name = "neo.fs.v2.netmap.LocalNodeInfoResponse" > < / a >
### Message LocalNodeInfoResponse
2020-10-16 11:40:12 +00:00
Local Node Info, including API Version in use
2020-09-03 09:19:02 +00:00
| 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. |
< a name = "neo.fs.v2.netmap.LocalNodeInfoResponse.Body" > < / a >
### Message LocalNodeInfoResponse.Body
2020-10-16 11:40:12 +00:00
Local Node Info, including API Version in use.
2020-09-03 09:19:02 +00:00
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
2020-10-16 11:40:12 +00:00
| version | [neo.fs.v2.refs.Version ](#neo.fs.v2.refs.Version ) | | Latest NeoFS API version in use |
| node_info | [NodeInfo ](#neo.fs.v2.netmap.NodeInfo ) | | NodeInfo structure with recent information from node itself |
2020-09-03 09:19:02 +00:00
2021-02-26 07:53:47 +00:00
< a name = "neo.fs.v2.netmap.NetworkInfoRequest" > < / a >
### Message NetworkInfoRequest
Get NetworkInfo structure with the network view from 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. |
< a name = "neo.fs.v2.netmap.NetworkInfoRequest.Body" > < / a >
### Message NetworkInfoRequest.Body
NetworkInfo request body is empty.
< a name = "neo.fs.v2.netmap.NetworkInfoResponse" > < / a >
### 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. |
< a name = "neo.fs.v2.netmap.NetworkInfoResponse.Body" > < / a >
### Message NetworkInfoResponse.Body
Information about the network.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| network_info | [NetworkInfo ](#neo.fs.v2.netmap.NetworkInfo ) | | NetworkInfo structure with recent information. |
2020-09-03 09:19:02 +00:00
<!-- end messages -->
<!-- end enums -->
2020-08-05 21:52:40 +00:00
< a name = "netmap/types.proto" > < / a >
< p align = "right" > < a href = "#top" > Top< / a > < / p >
## netmap/types.proto
<!-- end services -->
2020-08-23 11:42:01 +00:00
< a name = "neo.fs.v2.netmap.Filter" > < / a >
### Message Filter
2020-10-16 11:40:12 +00:00
Filter will return the subset of nodes from `NetworkMap` or another filter's
results, that will satisfy filter's conditions.
2020-08-23 11:42:01 +00:00
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
2020-10-16 11:40:12 +00:00
| name | [string ](#string ) | | Name of the filter or a reference to the 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 |
2020-08-23 11:42:01 +00:00
| 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. |
2021-10-14 15:27:45 +00:00
< a name = "neo.fs.v2.netmap.NetworkConfig" > < / a >
### Message NetworkConfig
NeoFS network configuration
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| parameters | [NetworkConfig.Parameter ](#neo.fs.v2.netmap.NetworkConfig.Parameter ) | repeated | List of parameter values. |
< a name = "neo.fs.v2.netmap.NetworkConfig.Parameter" > < / a >
### Message NetworkConfig.Parameter
Single configuration parameter.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| key | [bytes ](#bytes ) | | Parameter key. UTF-8 encoded string. |
| value | [bytes ](#bytes ) | | Parameter value. |
2021-02-26 07:53:47 +00:00
< a name = "neo.fs.v2.netmap.NetworkInfo" > < / a >
### Message NetworkInfo
Information about NeoFS network
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| current_epoch | [uint64 ](#uint64 ) | | Number of the current epoch in the NeoFS network. |
| magic_number | [uint64 ](#uint64 ) | | Magic number of the sidechain of the NeoFS network. |
2021-10-14 15:27:45 +00:00
| ms_per_block | [int64 ](#int64 ) | | MillisecondsPerBlock network parameter of the sidechain of the NeoFS network. |
| network_config | [NetworkConfig ](#neo.fs.v2.netmap.NetworkConfig ) | | NeoFS network configuration. |
2021-02-26 07:53:47 +00:00
2020-08-13 16:18:53 +00:00
< a name = "neo.fs.v2.netmap.NodeInfo" > < / a >
2020-08-05 21:58:09 +00:00
### Message NodeInfo
2020-08-13 16:18:53 +00:00
NeoFS node description
2020-08-05 21:58:09 +00:00
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
2020-08-13 16:18:53 +00:00
| public_key | [bytes ](#bytes ) | | Public key of the NeoFS node in a binary format. |
2021-06-23 11:53:21 +00:00
| addresses | [string ](#string ) | repeated | Ways to connect to a node |
2020-12-11 07:20:21 +00:00
| attributes | [NodeInfo.Attribute ](#neo.fs.v2.netmap.NodeInfo.Attribute ) | repeated | Carries list of the NeoFS 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. |
2020-08-13 16:18:53 +00:00
| state | [NodeInfo.State ](#neo.fs.v2.netmap.NodeInfo.State ) | | Carries state of the NeoFS node. |
2020-08-05 21:58:09 +00:00
2020-08-13 16:18:53 +00:00
< a name = "neo.fs.v2.netmap.NodeInfo.Attribute" > < / a >
2020-08-05 21:58:09 +00:00
### Message NodeInfo.Attribute
2020-10-16 11:40:12 +00:00
Administrator-defined Attributes of the NeoFS Storage Node.
2020-12-11 07:20:21 +00:00
`Attribute` is a Key-Value metadata pair. Key name must be a valid UTF-8
string. Value can't be empty.
2021-08-16 09:02:46 +00:00
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 NeoFS Storage
Node configuration uses ":" and "/" symbols, e.g.:
`NEOFS_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.
2020-10-16 11:40:12 +00:00
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.
* Subnet \
String ID of Node's storage subnet. There can be only one subnet served
by the Storage Node.
2021-02-11 13:13:07 +00:00
* UN-LOCODE \
2020-10-16 11:40:12 +00:00
Node's geographic location in
[UN/LOCODE ](https://www.unece.org/cefact/codesfortrade/codes_index.html )
2021-02-11 13:13:07 +00:00
format approximated to the nearest point defined in the standard.
* CountryCode \
2020-10-16 11:40:12 +00:00
Country code in
[ISO 3166-1_alpha-2 ](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 )
2021-02-11 13:13:07 +00:00
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.
2020-10-16 11:40:12 +00:00
For detailed description of each well-known attribute please see the
corresponding section in NeoFS Technical specification.
2020-08-05 21:58:09 +00:00
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
2020-08-13 16:18:53 +00:00
| key | [string ](#string ) | | Key of the node attribute. |
| value | [string ](#string ) | | Value of the node attribute. |
2020-10-16 11:40:12 +00:00
| parents | [string ](#string ) | repeated | Parent keys, if any. For example for `City` it could be `Region` and `Country` . |
2020-08-05 21:58:09 +00:00
2020-08-13 16:18:53 +00:00
< a name = "neo.fs.v2.netmap.PlacementPolicy" > < / a >
2020-08-05 21:52:40 +00:00
2020-08-13 16:18:53 +00:00
### Message PlacementPolicy
2020-10-16 11:40:12 +00:00
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.
2020-08-05 21:52:40 +00:00
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
2020-10-16 11:40:12 +00:00
| 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 NeoFS will search for nodes alternatives to include into container's nodes subset |
2020-08-23 11:42:01 +00:00
| 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 |
2020-08-05 21:52:40 +00:00
2020-08-23 11:42:01 +00:00
< a name = "neo.fs.v2.netmap.Replica" > < / a >
2020-08-05 21:52:40 +00:00
2020-08-23 11:42:01 +00:00
### Message Replica
2020-10-16 11:40:12 +00:00
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.
2020-08-05 21:52:40 +00:00
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
2020-08-23 11:42:01 +00:00
| count | [uint32 ](#uint32 ) | | How many object replicas to put |
2020-10-16 11:40:12 +00:00
| selector | [string ](#string ) | | Named selector bucket to put replicas |
2020-08-05 21:52:40 +00:00
2020-08-23 11:42:01 +00:00
< a name = "neo.fs.v2.netmap.Selector" > < / a >
2020-08-05 21:52:40 +00:00
2020-08-23 11:42:01 +00:00
### Message Selector
2020-10-16 11:40:12 +00:00
Selector chooses a number of nodes from the bucket taking the nearest nodes
to the provided `ContainerID` by hash distance.
2020-08-05 21:52:40 +00:00
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
2020-08-23 11:42:01 +00:00
| name | [string ](#string ) | | Selector name to reference in object placement section |
2020-10-16 11:40:12 +00:00
| count | [uint32 ](#uint32 ) | | How many nodes to select from the bucket |
2020-09-07 11:32:37 +00:00
| clause | [Clause ](#neo.fs.v2.netmap.Clause ) | | Selector modifier showing how to form a bucket |
2020-08-23 11:42:01 +00:00
| attribute | [string ](#string ) | | Attribute bucket to select from |
| filter | [string ](#string ) | | Filter reference to select from |
2020-08-05 21:52:40 +00:00
<!-- end messages -->
2020-09-07 11:32:37 +00:00
< a name = "neo.fs.v2.netmap.Clause" > < / a >
### Clause
2020-10-16 11:40:12 +00:00
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.
2020-09-07 11:32:37 +00:00
| Name | Number | Description |
| ---- | ------ | ----------- |
2020-10-16 11:40:12 +00:00
| CLAUSE_UNSPECIFIED | 0 | No modifier defined. Will select nodes from bucket randomly. |
2020-09-07 11:32:37 +00:00
| 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 |
2020-08-13 16:18:53 +00:00
< a name = "neo.fs.v2.netmap.NodeInfo.State" > < / a >
2020-08-05 21:58:09 +00:00
### NodeInfo.State
Represents the enumeration of various states of the NeoFS node.
| Name | Number | Description |
| ---- | ------ | ----------- |
2020-08-13 16:18:53 +00:00
| UNSPECIFIED | 0 | Unknown state. |
2020-08-07 07:53:45 +00:00
| ONLINE | 1 | Active state in the network. |
| OFFLINE | 2 | Network unavailable state. |
2020-08-05 21:58:09 +00:00
2020-08-23 11:42:01 +00:00
< a name = "neo.fs.v2.netmap.Operation" > < / a >
2020-08-05 21:52:40 +00:00
2020-08-23 11:42:01 +00:00
### Operation
Operations on filters
2020-08-05 21:52:40 +00:00
| Name | Number | Description |
| ---- | ------ | ----------- |
2020-08-13 16:18:53 +00:00
| 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 |
2020-08-05 21:52:40 +00:00
<!-- end enums -->
## Scalar Value Types
| .proto Type | Notes | C++ Type | Java Type | Python Type |
| ----------- | ----- | -------- | --------- | ----------- |
| < a name = "double" / > double | | double | double | float |
| < a name = "float" / > float | | float | float | float |
| < a name = "int32" / > int32 | Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint32 instead. | int32 | int | int |
| < a name = "int64" / > int64 | Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint64 instead. | int64 | long | int/long |
| < a name = "uint32" / > uint32 | Uses variable-length encoding. | uint32 | int | int/long |
| < a name = "uint64" / > uint64 | Uses variable-length encoding. | uint64 | long | int/long |
| < a name = "sint32" / > sint32 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s. | int32 | int | int |
| < a name = "sint64" / > sint64 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s. | int64 | long | int/long |
| < a name = "fixed32" / > fixed32 | Always four bytes. More efficient than uint32 if values are often greater than 2^28. | uint32 | int | int |
| < a name = "fixed64" / > fixed64 | Always eight bytes. More efficient than uint64 if values are often greater than 2^56. | uint64 | long | int/long |
| < a name = "sfixed32" / > sfixed32 | Always four bytes. | int32 | int | int |
| < a name = "sfixed64" / > sfixed64 | Always eight bytes. | int64 | long | int/long |
| < a name = "bool" / > bool | | bool | boolean | boolean |
| < a name = "string" / > string | A string must always contain UTF-8 encoded or 7-bit ASCII text. | string | String | str/unicode |
| < a name = "bytes" / > bytes | May contain any arbitrary sequence of bytes. | string | ByteString | str |