From 1cf33e5ffd17f0d11e167e3fdc8ca585cefac4b1 Mon Sep 17 00:00:00 2001
From: Evgeniy Kulikov <kim@nspcc.ru>
Date: Mon, 18 Nov 2019 16:34:06 +0300
Subject: [PATCH] initial

---
 .gitattributes                  |    1 +
 .gitignore                      |    3 +
 LICENSE.md                      |  675 +++++
 Makefile                        |   12 +
 README.md                       |   99 +
 accounting/fixtures/cheque.sh   |    8 +
 accounting/fixtures/cheque_data |  Bin 0 -> 650 bytes
 accounting/service.go           |   49 +
 accounting/service.pb.go        |  701 +++++
 accounting/service.proto        |   23 +
 accounting/types.go             |  353 +++
 accounting/types.pb.go          | 3905 +++++++++++++++++++++++++++
 accounting/types.proto          |  106 +
 accounting/types_test.go        |   84 +
 accounting/withdraw.go          |   53 +
 accounting/withdraw.pb.go       | 2641 ++++++++++++++++++
 accounting/withdraw.proto       |   61 +
 bootstrap/service.go            |   11 +
 bootstrap/service.pb.go         |  483 ++++
 bootstrap/service.proto         |   20 +
 bootstrap/types.go              |  100 +
 bootstrap/types.pb.go           |  697 +++++
 bootstrap/types.proto           |   22 +
 chain/address.go                |  185 ++
 chain/address_test.go           |  292 ++
 container/service.go            |   68 +
 container/service.pb.go         | 2131 +++++++++++++++
 container/service.proto         |   68 +
 container/types.go              |   94 +
 container/types.pb.go           |  464 ++++
 container/types.proto           |   16 +
 container/types_test.go         |   57 +
 decimal/decimal.go              |  110 +
 decimal/decimal.pb.go           |  345 +++
 decimal/decimal.proto           |   14 +
 decimal/decimal_test.go         |  445 +++
 go.mod                          |   22 +
 go.sum                          |  165 ++
 hash/hash.go                    |   98 +
 hash/hash_test.go               |  166 ++
 hash/hashesslice.go             |   20 +
 hash/salt.go                    |   17 +
 internal/error.go               |    7 +
 internal/proto.go               |   16 +
 object/doc.go                   |  143 +
 object/extensions.go            |   84 +
 object/service.go               |  215 ++
 object/service.pb.go            | 4491 +++++++++++++++++++++++++++++++
 object/service.proto            |  119 +
 object/sg.go                    |   66 +
 object/sg_test.go               |   87 +
 object/types.go                 |  219 ++
 object/types.pb.go              | 3814 ++++++++++++++++++++++++++
 object/types.proto              |  107 +
 object/utils.go                 |  107 +
 object/verification.go          |  132 +
 object/verification_test.go     |  105 +
 proto.go                        |    7 +
 query/types.go                  |   43 +
 query/types.pb.go               |  634 +++++
 query/types.proto               |   25 +
 refs/address.go                 |   68 +
 refs/cid.go                     |   96 +
 refs/owner.go                   |   65 +
 refs/sgid.go                    |   14 +
 refs/types.go                   |  106 +
 refs/types.pb.go                |  368 +++
 refs/types.proto                |   15 +
 refs/types_test.go              |  112 +
 refs/uuid.go                    |   76 +
 service/epoch.go                |    7 +
 service/role.go                 |   24 +
 service/role_test.go            |   22 +
 service/sign.go                 |   47 +
 service/ttl.go                  |   45 +
 service/ttl_test.go             |   72 +
 session/service.go              |   57 +
 session/service.pb.go           |  922 +++++++
 session/service.proto           |   27 +
 session/store.go                |   81 +
 session/store_test.go           |   84 +
 session/types.go                |  159 ++
 session/types.pb.go             |  845 ++++++
 session/types.proto             |   22 +
 state/service.go                |   48 +
 state/service.pb.go             | 1111 ++++++++
 state/service.proto             |   37 +
 87 files changed, 29835 insertions(+)
 create mode 100644 .gitattributes
 create mode 100644 .gitignore
 create mode 100644 LICENSE.md
 create mode 100644 Makefile
 create mode 100644 README.md
 create mode 100755 accounting/fixtures/cheque.sh
 create mode 100644 accounting/fixtures/cheque_data
 create mode 100644 accounting/service.go
 create mode 100644 accounting/service.pb.go
 create mode 100644 accounting/service.proto
 create mode 100644 accounting/types.go
 create mode 100644 accounting/types.pb.go
 create mode 100644 accounting/types.proto
 create mode 100644 accounting/types_test.go
 create mode 100644 accounting/withdraw.go
 create mode 100644 accounting/withdraw.pb.go
 create mode 100644 accounting/withdraw.proto
 create mode 100644 bootstrap/service.go
 create mode 100644 bootstrap/service.pb.go
 create mode 100644 bootstrap/service.proto
 create mode 100644 bootstrap/types.go
 create mode 100644 bootstrap/types.pb.go
 create mode 100644 bootstrap/types.proto
 create mode 100644 chain/address.go
 create mode 100644 chain/address_test.go
 create mode 100644 container/service.go
 create mode 100644 container/service.pb.go
 create mode 100644 container/service.proto
 create mode 100644 container/types.go
 create mode 100644 container/types.pb.go
 create mode 100644 container/types.proto
 create mode 100644 container/types_test.go
 create mode 100644 decimal/decimal.go
 create mode 100644 decimal/decimal.pb.go
 create mode 100644 decimal/decimal.proto
 create mode 100644 decimal/decimal_test.go
 create mode 100644 go.mod
 create mode 100644 go.sum
 create mode 100644 hash/hash.go
 create mode 100644 hash/hash_test.go
 create mode 100644 hash/hashesslice.go
 create mode 100644 hash/salt.go
 create mode 100644 internal/error.go
 create mode 100644 internal/proto.go
 create mode 100644 object/doc.go
 create mode 100644 object/extensions.go
 create mode 100644 object/service.go
 create mode 100644 object/service.pb.go
 create mode 100644 object/service.proto
 create mode 100644 object/sg.go
 create mode 100644 object/sg_test.go
 create mode 100644 object/types.go
 create mode 100644 object/types.pb.go
 create mode 100644 object/types.proto
 create mode 100644 object/utils.go
 create mode 100644 object/verification.go
 create mode 100644 object/verification_test.go
 create mode 100644 proto.go
 create mode 100644 query/types.go
 create mode 100644 query/types.pb.go
 create mode 100644 query/types.proto
 create mode 100644 refs/address.go
 create mode 100644 refs/cid.go
 create mode 100644 refs/owner.go
 create mode 100644 refs/sgid.go
 create mode 100644 refs/types.go
 create mode 100644 refs/types.pb.go
 create mode 100644 refs/types.proto
 create mode 100644 refs/types_test.go
 create mode 100644 refs/uuid.go
 create mode 100644 service/epoch.go
 create mode 100644 service/role.go
 create mode 100644 service/role_test.go
 create mode 100644 service/sign.go
 create mode 100644 service/ttl.go
 create mode 100644 service/ttl_test.go
 create mode 100644 session/service.go
 create mode 100644 session/service.pb.go
 create mode 100644 session/service.proto
 create mode 100644 session/store.go
 create mode 100644 session/store_test.go
 create mode 100644 session/types.go
 create mode 100644 session/types.pb.go
 create mode 100644 session/types.proto
 create mode 100644 state/service.go
 create mode 100644 state/service.pb.go
 create mode 100644 state/service.proto

diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 00000000..b002a5dd
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1 @@
+/**/*.pb.go -diff binary
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..22e0c656
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+bin
+temp
+/vendor/
diff --git a/LICENSE.md b/LICENSE.md
new file mode 100644
index 00000000..5c13ba2e
--- /dev/null
+++ b/LICENSE.md
@@ -0,0 +1,675 @@
+### GNU GENERAL PUBLIC LICENSE
+
+Version 3, 29 June 2007
+
+Copyright (C) 2007 Free Software Foundation, Inc.
+<https://fsf.org/>
+
+Everyone is permitted to copy and distribute verbatim copies of this
+license document, but changing it is not allowed.
+
+### Preamble
+
+The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom
+to share and change all versions of a program--to make sure it remains
+free software for all its users. We, the Free Software Foundation, use
+the GNU General Public License for most of our software; it applies
+also to any other work released this way by its authors. You can apply
+it to your programs, too.
+
+When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you
+have certain responsibilities if you distribute copies of the
+software, or if you modify it: responsibilities to respect the freedom
+of others.
+
+For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the
+manufacturer can do so. This is fundamentally incompatible with the
+aim of protecting users' freedom to change the software. The
+systematic pattern of such abuse occurs in the area of products for
+individuals to use, which is precisely where it is most unacceptable.
+Therefore, we have designed this version of the GPL to prohibit the
+practice for those products. If such problems arise substantially in
+other domains, we stand ready to extend this provision to those
+domains in future versions of the GPL, as needed to protect the
+freedom of users.
+
+Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish
+to avoid the special danger that patents applied to a free program
+could make it effectively proprietary. To prevent this, the GPL
+assures that patents cannot be used to render the program non-free.
+
+The precise terms and conditions for copying, distribution and
+modification follow.
+
+### TERMS AND CONDITIONS
+
+#### 0. Definitions.
+
+"This License" refers to version 3 of the GNU General Public License.
+
+"Copyright" also means copyright-like laws that apply to other kinds
+of works, such as semiconductor masks.
+
+"The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of
+an exact copy. The resulting work is called a "modified version" of
+the earlier work or a work "based on" the earlier work.
+
+A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user
+through a computer network, with no transfer of a copy, is not
+conveying.
+
+An interactive user interface displays "Appropriate Legal Notices" to
+the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+#### 1. Source Code.
+
+The "source code" for a work means the preferred form of the work for
+making modifications to it. "Object code" means any non-source form of
+a work.
+
+A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+The Corresponding Source need not include anything that users can
+regenerate automatically from other parts of the Corresponding Source.
+
+The Corresponding Source for a work in source code form is that same
+work.
+
+#### 2. Basic Permissions.
+
+All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+You may make, run and propagate covered works that you do not convey,
+without conditions so long as your license otherwise remains in force.
+You may convey covered works to others for the sole purpose of having
+them make modifications exclusively for you, or provide you with
+facilities for running those works, provided that you comply with the
+terms of this License in conveying all material for which you do not
+control copyright. Those thus making or running the covered works for
+you must do so exclusively on your behalf, under your direction and
+control, on terms that prohibit them from making any copies of your
+copyrighted material outside their relationship with you.
+
+Conveying under any other circumstances is permitted solely under the
+conditions stated below. Sublicensing is not allowed; section 10 makes
+it unnecessary.
+
+#### 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such
+circumvention is effected by exercising rights under this License with
+respect to the covered work, and you disclaim any intention to limit
+operation or modification of the work as a means of enforcing, against
+the work's users, your or third parties' legal rights to forbid
+circumvention of technological measures.
+
+#### 4. Conveying Verbatim Copies.
+
+You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+#### 5. Conveying Modified Source Versions.
+
+You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these
+conditions:
+
+-   a) The work must carry prominent notices stating that you modified
+it, and giving a relevant date.
+-   b) The work must carry prominent notices stating that it is
+released under this License and any conditions added under
+section 7. This requirement modifies the requirement in section 4
+to "keep intact all notices".
+-   c) You must license the entire work, as a whole, under this
+License to anyone who comes into possession of a copy. This
+License will therefore apply, along with any applicable section 7
+additional terms, to the whole of the work, and all its parts,
+regardless of how they are packaged. This License gives no
+permission to license the work in any other way, but it does not
+invalidate such permission if you have separately received it.
+-   d) If the work has interactive user interfaces, each must display
+Appropriate Legal Notices; however, if the Program has interactive
+interfaces that do not display Appropriate Legal Notices, your
+work need not make them do so.
+
+A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+#### 6. Conveying Non-Source Forms.
+
+You may convey a covered work in object code form under the terms of
+sections 4 and 5, provided that you also convey the machine-readable
+Corresponding Source under the terms of this License, in one of these
+ways:
+
+-   a) Convey the object code in, or embodied in, a physical product
+(including a physical distribution medium), accompanied by the
+Corresponding Source fixed on a durable physical medium
+customarily used for software interchange.
+-   b) Convey the object code in, or embodied in, a physical product
+(including a physical distribution medium), accompanied by a
+written offer, valid for at least three years and valid for as
+long as you offer spare parts or customer support for that product
+model, to give anyone who possesses the object code either (1) a
+copy of the Corresponding Source for all the software in the
+product that is covered by this License, on a durable physical
+medium customarily used for software interchange, for a price no
+more than your reasonable cost of physically performing this
+conveying of source, or (2) access to copy the Corresponding
+Source from a network server at no charge.
+-   c) Convey individual copies of the object code with a copy of the
+written offer to provide the Corresponding Source. This
+alternative is allowed only occasionally and noncommercially, and
+only if you received the object code with such an offer, in accord
+with subsection 6b.
+-   d) Convey the object code by offering access from a designated
+place (gratis or for a charge), and offer equivalent access to the
+Corresponding Source in the same way through the same place at no
+further charge. You need not require recipients to copy the
+Corresponding Source along with the object code. If the place to
+copy the object code is a network server, the Corresponding Source
+may be on a different server (operated by you or a third party)
+that supports equivalent copying facilities, provided you maintain
+clear directions next to the object code saying where to find the
+Corresponding Source. Regardless of what server hosts the
+Corresponding Source, you remain obligated to ensure that it is
+available for as long as needed to satisfy these requirements.
+-   e) Convey the object code using peer-to-peer transmission,
+provided you inform other peers where the object code and
+Corresponding Source of the work are being offered to the general
+public at no charge under subsection 6d.
+
+A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal,
+family, or household purposes, or (2) anything designed or sold for
+incorporation into a dwelling. In determining whether a product is a
+consumer product, doubtful cases shall be resolved in favor of
+coverage. For a particular product received by a particular user,
+"normally used" refers to a typical or common use of that class of
+product, regardless of the status of the particular user or of the way
+in which the particular user actually uses, or expects or is expected
+to use, the product. A product is a consumer product regardless of
+whether the product has substantial commercial, industrial or
+non-consumer uses, unless such uses represent the only significant
+mode of use of the product.
+
+"Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to
+install and execute modified versions of a covered work in that User
+Product from a modified version of its Corresponding Source. The
+information must suffice to ensure that the continued functioning of
+the modified object code is in no case prevented or interfered with
+solely because modification has been made.
+
+If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or
+updates for a work that has been modified or installed by the
+recipient, or for the User Product in which it has been modified or
+installed. Access to a network may be denied when the modification
+itself materially and adversely affects the operation of the network
+or violates the rules and protocols for communication across the
+network.
+
+Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+#### 7. Additional Terms.
+
+"Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders
+of that material) supplement the terms of this License with terms:
+
+-   a) Disclaiming warranty or limiting liability differently from the
+terms of sections 15 and 16 of this License; or
+-   b) Requiring preservation of specified reasonable legal notices or
+author attributions in that material or in the Appropriate Legal
+Notices displayed by works containing it; or
+-   c) Prohibiting misrepresentation of the origin of that material,
+or requiring that modified versions of such material be marked in
+reasonable ways as different from the original version; or
+-   d) Limiting the use for publicity purposes of names of licensors
+or authors of the material; or
+-   e) Declining to grant rights under trademark law for use of some
+trade names, trademarks, or service marks; or
+-   f) Requiring indemnification of licensors and authors of that
+material by anyone who conveys the material (or modified versions
+of it) with contractual assumptions of liability to the recipient,
+for any liability that these contractual assumptions directly
+impose on those licensors and authors.
+
+All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions; the
+above requirements apply either way.
+
+#### 8. Termination.
+
+You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+However, if you cease all violation of this License, then your license
+from a particular copyright holder is reinstated (a) provisionally,
+unless and until the copyright holder explicitly and finally
+terminates your license, and (b) permanently, if the copyright holder
+fails to notify you of the violation by some reasonable means prior to
+60 days after the cessation.
+
+Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+#### 9. Acceptance Not Required for Having Copies.
+
+You are not required to accept this License in order to receive or run
+a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+#### 10. Automatic Licensing of Downstream Recipients.
+
+Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+#### 11. Patents.
+
+A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+A contributor's "essential patent claims" are all patent claims owned
+or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+A patent license is "discriminatory" if it does not include within the
+scope of its coverage, prohibits the exercise of, or is conditioned on
+the non-exercise of one or more of the rights that are specifically
+granted under this License. You may not convey a covered work if you
+are a party to an arrangement with a third party that is in the
+business of distributing software, under which you make payment to the
+third party based on the extent of your activity of conveying the
+work, and under which the third party grants, to any of the parties
+who would receive the covered work from you, a discriminatory patent
+license (a) in connection with copies of the covered work conveyed by
+you (or copies made from those copies), or (b) primarily for and in
+connection with specific products or compilations that contain the
+covered work, unless you entered into that arrangement, or that patent
+license was granted, prior to 28 March 2007.
+
+Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+#### 12. No Surrender of Others' Freedom.
+
+If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under
+this License and any other pertinent obligations, then as a
+consequence you may not convey it at all. For example, if you agree to
+terms that obligate you to collect a royalty for further conveying
+from those to whom you convey the Program, the only way you could
+satisfy both those terms and this License would be to refrain entirely
+from conveying the Program.
+
+#### 13. Use with the GNU Affero General Public License.
+
+Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+#### 14. Revised Versions of this License.
+
+The Free Software Foundation may publish revised and/or new versions
+of the GNU General Public License from time to time. Such new versions
+will be similar in spirit to the present version, but may differ in
+detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies that a certain numbered version of the GNU General Public
+License "or any later version" applies to it, you have the option of
+following the terms and conditions either of that numbered version or
+of any later version published by the Free Software Foundation. If the
+Program does not specify a version number of the GNU General Public
+License, you may choose any version ever published by the Free
+Software Foundation.
+
+If the Program specifies that a proxy can decide which future versions
+of the GNU General Public License can be used, that proxy's public
+statement of acceptance of a version permanently authorizes you to
+choose that version for the Program.
+
+Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+#### 15. Disclaimer of Warranty.
+
+THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT
+WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND
+PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE
+DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
+CORRECTION.
+
+#### 16. Limitation of Liability.
+
+IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR
+CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES
+ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT
+NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR
+LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM
+TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER
+PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+#### 17. Interpretation of Sections 15 and 16.
+
+If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+END OF TERMS AND CONDITIONS
+
+### How to Apply These Terms to Your New Programs
+
+If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these
+terms.
+
+To do so, attach the following notices to the program. It is safest to
+attach them to the start of each source file to most effectively state
+the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+<one line to give the program's name and a brief idea of what it does.>
+Copyright (C) <year>  <name of author>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper
+mail.
+
+If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+<program>  Copyright (C) <year>  <name of author>
+This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+        This is free software, and you are welcome to redistribute it
+        under certain conditions; type `show c' for details.
+
+The hypothetical commands \`show w' and \`show c' should show the
+appropriate parts of the General Public License. Of course, your
+program's commands might be different; for a GUI interface, you would
+use an "about box".
+
+You should also get your employer (if you work as a programmer) or
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. For more information on this, and how to apply and follow
+the GNU GPL, see <https://www.gnu.org/licenses/>.
+
+The GNU General Public License does not permit incorporating your
+program into proprietary programs. If your program is a subroutine
+library, you may consider it more useful to permit linking proprietary
+applications with the library. If this is what you want to do, use the
+GNU Lesser General Public License instead of this License. But first,
+please read <https://www.gnu.org/licenses/why-not-lgpl.html>.
\ No newline at end of file
diff --git a/Makefile b/Makefile
new file mode 100644
index 00000000..c17477a8
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,12 @@
+protoc:
+	@go mod tidy -v
+	@go mod vendor
+	# Install specific version for gogo-proto
+	@go list -f '{{.Path}}/...@{{.Version}}' -m github.com/gogo/protobuf | xargs go get -v
+	# Install specific version for protobuf lib
+	@go list -f '{{.Path}}/...@{{.Version}}' -m  github.com/golang/protobuf | xargs go get -v
+	# Protoc generate
+	@find . -type f -name '*.proto' -not -path './vendor/*' \
+		-exec protoc \
+		--proto_path=.:./vendor \
+		--gofast_out=plugins=grpc,paths=source_relative:. '{}' \;
diff --git a/README.md b/README.md
new file mode 100644
index 00000000..9247a10f
--- /dev/null
+++ b/README.md
@@ -0,0 +1,99 @@
+# NeoFS-proto 
+
+NeoFS-proto repository contains implementation of core NeoFS structures that
+can be used for integration with NeoFS. 
+
+## Description
+
+Repository contains 13 packages that implement NeoFS core structures. These
+packages mostly contain protobuf files with service and structure definitions 
+or NeoFS core types with complemented functions. 
+
+### Accounting
+
+Accounting package defines services and structures for accounting operations: 
+balance request and `cheque` operations for withdraw. `Cheque` is a structure
+with inner ring signatures, which approve that user can withdraw requested
+amount of assets. NeoFS smart contract takes binary formatted `cheque` as a 
+parameter in withdraw call. 
+
+### Bootstrap
+
+Bootstrap package defines bootstrap service which is used by storage nodes to
+connect to the storage network. 
+
+### Chain
+
+Chain package contains util functions for operations with NEO Blockchain types:
+wallet addresses, script-hashes. 
+
+### Container
+
+Container package defines service and structures for operations with containers.
+Objects in NeoFS are stored in containers. Container defines storage 
+policy for the objects. 
+
+### Decimal
+
+Decimal defines custom decimal implementation which is used in accounting
+operations.
+
+### Hash
+
+Hash package defines homomorphic hash type.
+
+### Internal
+
+Internal package defines constant error type and proto interface for custom
+protobuf structures. 
+
+### Object
+
+Object package defines service and structures for object operations. Object is 
+a core storage structure in NeoFS. Package contains detailed information
+about object internal structure.
+
+### Query
+
+Query package defines structure for object search requests. 
+
+### Refs
+
+Refs package defines core identity types: Object ID, Container ID, etc.
+
+### Service
+
+Service package defines util structure and functions for all NeoFS services
+operations: TTL and request signature management, node roles, epoch retriever. 
+
+### Session
+
+Session package defines service and structures for session obtain. Object
+operations require an established session with pair of session keys signed by 
+owner of the object. 
+
+### State
+
+State package defines service and structures for metrics gathering. 
+
+## How to use
+
+NeoFS-proto packages contain godoc documentation. Examples of using most of 
+these packages can be found in NeoFS-CLI repository. CLI implements and 
+demonstrates all basic interactions with NeoFS: container, object, storage 
+group, and accounting operations. 
+
+Protobuf files are recompiled with the command:
+
+```
+$ make protoc
+```
+
+## Contributing
+
+At this moment, we do not accept contributions. 
+
+## License
+
+This project is licensed under the GPLv3 License - 
+see the [LICENSE.md](LICENSE.md) file for details
diff --git a/accounting/fixtures/cheque.sh b/accounting/fixtures/cheque.sh
new file mode 100755
index 00000000..93368138
--- /dev/null
+++ b/accounting/fixtures/cheque.sh
@@ -0,0 +1,8 @@
+#!/bin/bash
+
+CHEQUE=d6520dabb6cb9b981792608c73670eff14775e9a65bbc189271723ba2703c53263e8d6e522dc32203339dcd8eee9c6b7439a0000000053724e000000000000001e61000603012d47e76210aec73be39ab3d186e0a40fe8d86bfa3d4fabfda57ba13b88f96abe1de4c7ecd46cb32081c0ff199e0b32708d2ce709dd146ce096484073a9b15a259ca799f8d848eb5bea16f6d0842a0181ccd47384af2cdb0fd0af0819e8a08802f7528ce97c9a93558efe7d4f62577aabdf771c931f54a71be6ad21e7d9cc1777686ad19b5dc4b80d7b8decf90054c5aad66c0e6fe63d8473b751cd77c1bd0557516e0f3e7d0ccb485809023b0c08a89f33ae38b2f99ce3f1ebc7905dddf0ed0f023e00f03a16e8707ce045eb42ee80d392451541ee510dc18e1c8befbac54d7426087d37d32d836537d317deafbbd193002a36f80fbdfbf3a730cf011bc6c75c7e6d5724f3adee7015fcb3068d321e2ae555e79107be0c46070efdae2f724dbc9f0340750b92789821683283bcb98e32b7e032b94f267b6964613fc31a7ce5813fddeea47a1db525634237e924178b5c8ea745549ae60aa3570ce6cf52e370e6ab87652bdf8a179176f1acaf48896bef9ab300818a53f410d86241d506a550f4915403fef27f744e829131d0ec980829fafa51db1714c2761d9f78762c008c323e9d6612e4f9efdc609f191fd9ca5431dd9dc037130150107ab8769780d728e9ffdf314019b57c8d2b940b9ec078afa951ed8b06c1bf352edd2037e29b8f24cca3ec700368a6f5829fb2a34fa03d0308ae6b05f433f2904d9a852fed1f5d2eb598ca79475b74ef6394e712d275cd798062c6d8e41fad822ac5a4fcb167f0a2e196f61f9f65a0adef9650f49150e7eb7bb08dd1739fa6e86b341f1b2cf5657fcd200637e8
+DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
+
+echo $CHEQUE | xxd -p -r > $DIR/cheque_data
+
+exit 0
diff --git a/accounting/fixtures/cheque_data b/accounting/fixtures/cheque_data
new file mode 100644
index 0000000000000000000000000000000000000000..cd7b286642c3d1fc8d0080985c4d070013761b63
GIT binary patch
literal 650
zcmV;50(Je?QVpxN%bS=Nl3<K;XAb`qcV3!hyTOSk7bChS1I039=+@;T+%h0DIo#Op
z>BhH1ng9R*08?^K000000000UVE_gL0WC-8Vi2y!JL8(O(T3op59ruy`aMsp{iS=M
zJBayez8&Pp?9^<tAc4UD8J-I=aE&bI3EdQI;Fd^0bE&afC7h?3_}ED6Tk00}(1a=h
zfy~r%gs&{y574g&8R(#h0{2pk>3o`#RgV6BPhwYktKWAVlOI&48|JMc=h@5`cW7$S
zn_a}X4SS93`2bYKs@7}{Z{|IObGK2=cfq{{S5a;cK79<!NLUF1I}8Y@pEIsFviY3j
z@$1KsUET2Q4+1^_@H!UgaD3oJ>q72;(~?CMLGDov!Hyh@@4CfJbS4OWH`6VHWjE6o
z-mkmSlK?6<_z%7N^QSP+0UO50Tz+j=B=fEAa25Qs28}WvD&<w@kq5pEMh6c4t}k*;
zyq^O=bqkVsm?3B~gS@$pGPmF|xlbm0X=GtP!y0_$fj`~uq<S5-C1XN2=_D76T#lzj
zRGQ`rqgM>(&r;)X=BtNgE8mJ2k#_N{uSkh&@0zm!fr?Y~5ZGct)dr<d^pR8p{_=lx
zPJ)p!(CnB9Df;?R+ZPnVb{(I1b}RslGCrMV66E>s++d#>AKA)OG2NZOHxmI+5PG<F
zmw?wO>Hps`KpC}sjVqK3p1^posZs5V2Eo5IF5MtE;+u~o%%kjZ18Ao8f}gUZPoO;m
z2(D`d^fU61O`3%-?H^q(wV29zM_Y97W0dC-(sj*wfMUkj<R7hqD#fJyv1jn2;g<Fv
kpJkw}@0L*Xkx=LBd$5hsbDyT@YcwAlEcIo7%^(Ih=!|DS#Q*>R

literal 0
HcmV?d00001

diff --git a/accounting/service.go b/accounting/service.go
new file mode 100644
index 00000000..df74e588
--- /dev/null
+++ b/accounting/service.go
@@ -0,0 +1,49 @@
+package accounting
+
+import (
+	"github.com/nspcc-dev/neofs-proto/decimal"
+	"github.com/nspcc-dev/neofs-proto/internal"
+	"github.com/nspcc-dev/neofs-proto/refs"
+)
+
+type (
+	// OwnerID type alias.
+	OwnerID = refs.OwnerID
+
+	// Decimal type alias.
+	Decimal = decimal.Decimal
+
+	// Filter is used to filter accounts by criteria.
+	Filter func(acc *Account) bool
+)
+
+const (
+	// ErrEmptyAddress is raised when passed Address is empty.
+	ErrEmptyAddress = internal.Error("empty address")
+
+	// ErrEmptyLockTarget is raised when passed LockTarget is empty.
+	ErrEmptyLockTarget = internal.Error("empty lock target")
+
+	// ErrEmptyContainerID is raised when passed CID is empty.
+	ErrEmptyContainerID = internal.Error("empty container ID")
+
+	// ErrEmptyParentAddress is raised when passed ParentAddress is empty.
+	ErrEmptyParentAddress = internal.Error("empty parent address")
+)
+
+// SetTTL sets ttl to BalanceRequest to satisfy TTLRequest interface.
+func (m BalanceRequest) SetTTL(v uint32) { m.TTL = v }
+
+// SumFunds goes through all accounts and sums up active funds.
+func SumFunds(accounts []*Account) (res *decimal.Decimal) {
+	res = decimal.Zero.Copy()
+
+	for i := range accounts {
+		if accounts[i] == nil {
+			continue
+		}
+
+		res = res.Add(accounts[i].ActiveFunds)
+	}
+	return
+}
diff --git a/accounting/service.pb.go b/accounting/service.pb.go
new file mode 100644
index 00000000..8708db37
--- /dev/null
+++ b/accounting/service.pb.go
@@ -0,0 +1,701 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: accounting/service.proto
+
+package accounting
+
+import (
+	context "context"
+	fmt "fmt"
+	_ "github.com/gogo/protobuf/gogoproto"
+	proto "github.com/golang/protobuf/proto"
+	decimal "github.com/nspcc-dev/neofs-proto/decimal"
+	grpc "google.golang.org/grpc"
+	codes "google.golang.org/grpc/codes"
+	status "google.golang.org/grpc/status"
+	io "io"
+	math "math"
+	math_bits "math/bits"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
+
+type BalanceRequest struct {
+	OwnerID              OwnerID  `protobuf:"bytes,1,opt,name=OwnerID,proto3,customtype=OwnerID" json:"OwnerID"`
+	TTL                  uint32   `protobuf:"varint,2,opt,name=TTL,proto3" json:"TTL,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *BalanceRequest) Reset()         { *m = BalanceRequest{} }
+func (m *BalanceRequest) String() string { return proto.CompactTextString(m) }
+func (*BalanceRequest) ProtoMessage()    {}
+func (*BalanceRequest) Descriptor() ([]byte, []int) {
+	return fileDescriptor_7f9514b8f1d4c7fe, []int{0}
+}
+func (m *BalanceRequest) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *BalanceRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *BalanceRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_BalanceRequest.Merge(m, src)
+}
+func (m *BalanceRequest) XXX_Size() int {
+	return m.Size()
+}
+func (m *BalanceRequest) XXX_DiscardUnknown() {
+	xxx_messageInfo_BalanceRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_BalanceRequest proto.InternalMessageInfo
+
+func (m *BalanceRequest) GetTTL() uint32 {
+	if m != nil {
+		return m.TTL
+	}
+	return 0
+}
+
+type BalanceResponse struct {
+	Balance              *decimal.Decimal `protobuf:"bytes,1,opt,name=Balance,proto3" json:"Balance,omitempty"`
+	LockAccounts         []*Account       `protobuf:"bytes,2,rep,name=LockAccounts,proto3" json:"LockAccounts,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}         `json:"-"`
+	XXX_unrecognized     []byte           `json:"-"`
+	XXX_sizecache        int32            `json:"-"`
+}
+
+func (m *BalanceResponse) Reset()         { *m = BalanceResponse{} }
+func (m *BalanceResponse) String() string { return proto.CompactTextString(m) }
+func (*BalanceResponse) ProtoMessage()    {}
+func (*BalanceResponse) Descriptor() ([]byte, []int) {
+	return fileDescriptor_7f9514b8f1d4c7fe, []int{1}
+}
+func (m *BalanceResponse) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *BalanceResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *BalanceResponse) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_BalanceResponse.Merge(m, src)
+}
+func (m *BalanceResponse) XXX_Size() int {
+	return m.Size()
+}
+func (m *BalanceResponse) XXX_DiscardUnknown() {
+	xxx_messageInfo_BalanceResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_BalanceResponse proto.InternalMessageInfo
+
+func (m *BalanceResponse) GetBalance() *decimal.Decimal {
+	if m != nil {
+		return m.Balance
+	}
+	return nil
+}
+
+func (m *BalanceResponse) GetLockAccounts() []*Account {
+	if m != nil {
+		return m.LockAccounts
+	}
+	return nil
+}
+
+func init() {
+	proto.RegisterType((*BalanceRequest)(nil), "accounting.BalanceRequest")
+	proto.RegisterType((*BalanceResponse)(nil), "accounting.BalanceResponse")
+}
+
+func init() { proto.RegisterFile("accounting/service.proto", fileDescriptor_7f9514b8f1d4c7fe) }
+
+var fileDescriptor_7f9514b8f1d4c7fe = []byte{
+	// 311 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x48, 0x4c, 0x4e, 0xce,
+	0x2f, 0xcd, 0x2b, 0xc9, 0xcc, 0x4b, 0xd7, 0x2f, 0x4e, 0x2d, 0x2a, 0xcb, 0x4c, 0x4e, 0xd5, 0x2b,
+	0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x42, 0xc8, 0x48, 0x89, 0xa6, 0xa4, 0x26, 0x67, 0xe6, 0x26,
+	0xe6, 0xe8, 0x43, 0x69, 0x88, 0x12, 0x29, 0x31, 0x24, 0xcd, 0x25, 0x95, 0x05, 0xa9, 0xc5, 0x50,
+	0x71, 0xdd, 0xf4, 0xcc, 0x92, 0x8c, 0xd2, 0x24, 0xbd, 0xe4, 0xfc, 0x5c, 0xfd, 0xf4, 0xfc, 0xf4,
+	0x7c, 0x7d, 0xb0, 0x70, 0x52, 0x69, 0x1a, 0x98, 0x07, 0xe6, 0x80, 0x59, 0x10, 0xe5, 0x4a, 0xbe,
+	0x5c, 0x7c, 0x4e, 0x89, 0x39, 0x89, 0x79, 0xc9, 0xa9, 0x41, 0xa9, 0x85, 0xa5, 0xa9, 0xc5, 0x25,
+	0x42, 0x9a, 0x5c, 0xec, 0xfe, 0xe5, 0x79, 0xa9, 0x45, 0x9e, 0x2e, 0x12, 0x8c, 0x0a, 0x8c, 0x1a,
+	0x3c, 0x4e, 0xfc, 0x27, 0xee, 0xc9, 0x33, 0xdc, 0xba, 0x27, 0x0f, 0x13, 0x0e, 0x82, 0x31, 0x84,
+	0x04, 0xb8, 0x98, 0x43, 0x42, 0x7c, 0x24, 0x98, 0x14, 0x18, 0x35, 0x78, 0x83, 0x40, 0x4c, 0xa5,
+	0x32, 0x2e, 0x7e, 0xb8, 0x71, 0xc5, 0x05, 0xf9, 0x79, 0xc5, 0xa9, 0x42, 0x5a, 0x5c, 0xec, 0x50,
+	0x21, 0xb0, 0x79, 0xdc, 0x46, 0x02, 0x7a, 0x30, 0x9f, 0xb8, 0x40, 0xe8, 0x20, 0x98, 0x02, 0x21,
+	0x73, 0x2e, 0x1e, 0x9f, 0xfc, 0xe4, 0x6c, 0x47, 0x88, 0xd7, 0x8a, 0x25, 0x98, 0x14, 0x98, 0x35,
+	0xb8, 0x8d, 0x84, 0xf5, 0x10, 0x7e, 0xd5, 0x83, 0xca, 0x05, 0xa1, 0x28, 0x34, 0x0a, 0xe0, 0xe2,
+	0x72, 0x84, 0xab, 0x11, 0x72, 0x82, 0x5b, 0x29, 0x24, 0x85, 0xac, 0x17, 0xd5, 0xa7, 0x52, 0xd2,
+	0x58, 0xe5, 0x20, 0xce, 0x76, 0x72, 0x3c, 0xf1, 0x48, 0x8e, 0xf1, 0xc2, 0x23, 0x39, 0xc6, 0x1b,
+	0x8f, 0xe4, 0x18, 0x1f, 0x3c, 0x92, 0x63, 0x9c, 0xf1, 0x58, 0x8e, 0x21, 0x4a, 0x1b, 0x29, 0x74,
+	0xf3, 0x8a, 0x0b, 0x92, 0x93, 0x75, 0x53, 0x52, 0xcb, 0xf4, 0xf3, 0x52, 0xf3, 0xd3, 0x8a, 0x75,
+	0x21, 0x61, 0x8b, 0x30, 0x32, 0x89, 0x0d, 0x2c, 0x62, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0x0c,
+	0x45, 0x3c, 0x0a, 0xe8, 0x01, 0x00, 0x00,
+}
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ context.Context
+var _ grpc.ClientConn
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the grpc package it is being compiled against.
+const _ = grpc.SupportPackageIsVersion4
+
+// AccountingClient is the client API for Accounting service.
+//
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
+type AccountingClient interface {
+	Balance(ctx context.Context, in *BalanceRequest, opts ...grpc.CallOption) (*BalanceResponse, error)
+}
+
+type accountingClient struct {
+	cc *grpc.ClientConn
+}
+
+func NewAccountingClient(cc *grpc.ClientConn) AccountingClient {
+	return &accountingClient{cc}
+}
+
+func (c *accountingClient) Balance(ctx context.Context, in *BalanceRequest, opts ...grpc.CallOption) (*BalanceResponse, error) {
+	out := new(BalanceResponse)
+	err := c.cc.Invoke(ctx, "/accounting.Accounting/Balance", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+// AccountingServer is the server API for Accounting service.
+type AccountingServer interface {
+	Balance(context.Context, *BalanceRequest) (*BalanceResponse, error)
+}
+
+// UnimplementedAccountingServer can be embedded to have forward compatible implementations.
+type UnimplementedAccountingServer struct {
+}
+
+func (*UnimplementedAccountingServer) Balance(ctx context.Context, req *BalanceRequest) (*BalanceResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method Balance not implemented")
+}
+
+func RegisterAccountingServer(s *grpc.Server, srv AccountingServer) {
+	s.RegisterService(&_Accounting_serviceDesc, srv)
+}
+
+func _Accounting_Balance_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(BalanceRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(AccountingServer).Balance(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/accounting.Accounting/Balance",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(AccountingServer).Balance(ctx, req.(*BalanceRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+var _Accounting_serviceDesc = grpc.ServiceDesc{
+	ServiceName: "accounting.Accounting",
+	HandlerType: (*AccountingServer)(nil),
+	Methods: []grpc.MethodDesc{
+		{
+			MethodName: "Balance",
+			Handler:    _Accounting_Balance_Handler,
+		},
+	},
+	Streams:  []grpc.StreamDesc{},
+	Metadata: "accounting/service.proto",
+}
+
+func (m *BalanceRequest) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *BalanceRequest) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *BalanceRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if m.TTL != 0 {
+		i = encodeVarintService(dAtA, i, uint64(m.TTL))
+		i--
+		dAtA[i] = 0x10
+	}
+	{
+		size := m.OwnerID.Size()
+		i -= size
+		if _, err := m.OwnerID.MarshalTo(dAtA[i:]); err != nil {
+			return 0, err
+		}
+		i = encodeVarintService(dAtA, i, uint64(size))
+	}
+	i--
+	dAtA[i] = 0xa
+	return len(dAtA) - i, nil
+}
+
+func (m *BalanceResponse) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *BalanceResponse) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *BalanceResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if len(m.LockAccounts) > 0 {
+		for iNdEx := len(m.LockAccounts) - 1; iNdEx >= 0; iNdEx-- {
+			{
+				size, err := m.LockAccounts[iNdEx].MarshalToSizedBuffer(dAtA[:i])
+				if err != nil {
+					return 0, err
+				}
+				i -= size
+				i = encodeVarintService(dAtA, i, uint64(size))
+			}
+			i--
+			dAtA[i] = 0x12
+		}
+	}
+	if m.Balance != nil {
+		{
+			size, err := m.Balance.MarshalToSizedBuffer(dAtA[:i])
+			if err != nil {
+				return 0, err
+			}
+			i -= size
+			i = encodeVarintService(dAtA, i, uint64(size))
+		}
+		i--
+		dAtA[i] = 0xa
+	}
+	return len(dAtA) - i, nil
+}
+
+func encodeVarintService(dAtA []byte, offset int, v uint64) int {
+	offset -= sovService(v)
+	base := offset
+	for v >= 1<<7 {
+		dAtA[offset] = uint8(v&0x7f | 0x80)
+		v >>= 7
+		offset++
+	}
+	dAtA[offset] = uint8(v)
+	return base
+}
+func (m *BalanceRequest) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = m.OwnerID.Size()
+	n += 1 + l + sovService(uint64(l))
+	if m.TTL != 0 {
+		n += 1 + sovService(uint64(m.TTL))
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *BalanceResponse) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.Balance != nil {
+		l = m.Balance.Size()
+		n += 1 + l + sovService(uint64(l))
+	}
+	if len(m.LockAccounts) > 0 {
+		for _, e := range m.LockAccounts {
+			l = e.Size()
+			n += 1 + l + sovService(uint64(l))
+		}
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func sovService(x uint64) (n int) {
+	return (math_bits.Len64(x|1) + 6) / 7
+}
+func sozService(x uint64) (n int) {
+	return sovService(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+func (m *BalanceRequest) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowService
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: BalanceRequest: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: BalanceRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field OwnerID", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthService
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthService
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.OwnerID.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 2:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field TTL", wireType)
+			}
+			m.TTL = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.TTL |= uint32(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		default:
+			iNdEx = preIndex
+			skippy, err := skipService(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *BalanceResponse) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowService
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: BalanceResponse: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: BalanceResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Balance", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthService
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthService
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if m.Balance == nil {
+				m.Balance = &decimal.Decimal{}
+			}
+			if err := m.Balance.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field LockAccounts", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthService
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthService
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.LockAccounts = append(m.LockAccounts, &Account{})
+			if err := m.LockAccounts[len(m.LockAccounts)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipService(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func skipService(dAtA []byte) (n int, err error) {
+	l := len(dAtA)
+	iNdEx := 0
+	depth := 0
+	for iNdEx < l {
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return 0, ErrIntOverflowService
+			}
+			if iNdEx >= l {
+				return 0, io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= (uint64(b) & 0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		wireType := int(wire & 0x7)
+		switch wireType {
+		case 0:
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return 0, ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return 0, io.ErrUnexpectedEOF
+				}
+				iNdEx++
+				if dAtA[iNdEx-1] < 0x80 {
+					break
+				}
+			}
+		case 1:
+			iNdEx += 8
+		case 2:
+			var length int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return 0, ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return 0, io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				length |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if length < 0 {
+				return 0, ErrInvalidLengthService
+			}
+			iNdEx += length
+		case 3:
+			depth++
+		case 4:
+			if depth == 0 {
+				return 0, ErrUnexpectedEndOfGroupService
+			}
+			depth--
+		case 5:
+			iNdEx += 4
+		default:
+			return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+		}
+		if iNdEx < 0 {
+			return 0, ErrInvalidLengthService
+		}
+		if depth == 0 {
+			return iNdEx, nil
+		}
+	}
+	return 0, io.ErrUnexpectedEOF
+}
+
+var (
+	ErrInvalidLengthService        = fmt.Errorf("proto: negative length found during unmarshaling")
+	ErrIntOverflowService          = fmt.Errorf("proto: integer overflow")
+	ErrUnexpectedEndOfGroupService = fmt.Errorf("proto: unexpected end of group")
+)
diff --git a/accounting/service.proto b/accounting/service.proto
new file mode 100644
index 00000000..b75bf9c9
--- /dev/null
+++ b/accounting/service.proto
@@ -0,0 +1,23 @@
+syntax = "proto3";
+package accounting;
+option go_package = "github.com/nspcc-dev/neofs-proto/accounting";
+
+import "decimal/decimal.proto";
+import "accounting/types.proto";
+import "github.com/gogo/protobuf/gogoproto/gogo.proto";
+
+option (gogoproto.stable_marshaler_all) = true;
+
+service Accounting {
+    rpc Balance(BalanceRequest) returns (BalanceResponse);
+}
+
+message BalanceRequest {
+    bytes OwnerID = 1 [(gogoproto.customtype) = "OwnerID", (gogoproto.nullable) = false];
+    uint32 TTL    = 2;
+}
+
+message BalanceResponse {
+    decimal.Decimal Balance       = 1;
+    repeated Account LockAccounts = 2;
+}
diff --git a/accounting/types.go b/accounting/types.go
new file mode 100644
index 00000000..9c76fc75
--- /dev/null
+++ b/accounting/types.go
@@ -0,0 +1,353 @@
+package accounting
+
+import (
+	"crypto/ecdsa"
+	"crypto/rand"
+	"encoding/binary"
+	"reflect"
+
+	"github.com/mr-tron/base58"
+	crypto "github.com/nspcc-dev/neofs-crypto"
+	"github.com/nspcc-dev/neofs-proto/chain"
+	"github.com/nspcc-dev/neofs-proto/decimal"
+	"github.com/nspcc-dev/neofs-proto/internal"
+	"github.com/nspcc-dev/neofs-proto/refs"
+	"github.com/pkg/errors"
+)
+
+type (
+	// Cheque structure that describes a user request for withdrawal of funds.
+	Cheque struct {
+		ID         ChequeID
+		Owner      refs.OwnerID
+		Amount     *decimal.Decimal
+		Height     uint64
+		Signatures []ChequeSignature
+	}
+
+	// BalanceReceiver interface that is used to retrieve user balance by address.
+	BalanceReceiver interface {
+		Balance(accountAddress string) (*Account, error)
+	}
+
+	// ChequeID is identifier of user request for withdrawal of funds.
+	ChequeID string
+
+	// CID type alias.
+	CID = refs.CID
+
+	// SGID type alias.
+	SGID = refs.SGID
+
+	// ChequeSignature contains public key and hash, and is used to verify signatures.
+	ChequeSignature struct {
+		Key  *ecdsa.PublicKey
+		Hash []byte
+	}
+)
+
+const (
+	// ErrWrongSignature is raised when wrong signature is passed.
+	ErrWrongSignature = internal.Error("wrong signature")
+
+	// ErrWrongPublicKey is raised when wrong public key is passed.
+	ErrWrongPublicKey = internal.Error("wrong public key")
+
+	// ErrWrongChequeData is raised when passed bytes cannot not be parsed as valid Cheque.
+	ErrWrongChequeData = internal.Error("wrong cheque data")
+
+	// ErrInvalidLength is raised when passed bytes cannot not be parsed as valid ChequeID.
+	ErrInvalidLength = internal.Error("invalid length")
+
+	u16size = 2
+	u64size = 8
+
+	signaturesOffset = chain.AddressLength + refs.OwnerIDSize + u64size + u64size
+)
+
+// NewChequeID generates valid random ChequeID using crypto/rand.Reader.
+func NewChequeID() (ChequeID, error) {
+	d := make([]byte, chain.AddressLength)
+	if _, err := rand.Read(d); err != nil {
+		return "", err
+	}
+
+	id := base58.Encode(d)
+
+	return ChequeID(id), nil
+}
+
+// String returns string representation of ChequeID.
+func (b ChequeID) String() string { return string(b) }
+
+// Empty returns true, if ChequeID is empty.
+func (b ChequeID) Empty() bool { return len(b) == 0 }
+
+// Valid validates ChequeID.
+func (b ChequeID) Valid() bool {
+	d, err := base58.Decode(string(b))
+	return err == nil && len(d) == chain.AddressLength
+}
+
+// Bytes returns bytes representation of ChequeID.
+func (b ChequeID) Bytes() []byte {
+	d, err := base58.Decode(string(b))
+	if err != nil {
+		return make([]byte, chain.AddressLength)
+	}
+	return d
+}
+
+// Equal checks that current ChequeID is equal to passed ChequeID.
+func (b ChequeID) Equal(b2 ChequeID) bool {
+	return b.Valid() && b2.Valid() && string(b) == string(b2)
+}
+
+// Unmarshal tries to parse []byte into valid ChequeID.
+func (b *ChequeID) Unmarshal(data []byte) error {
+	*b = ChequeID(base58.Encode(data))
+	if !b.Valid() {
+		return ErrInvalidLength
+	}
+	return nil
+}
+
+// Size returns size (chain.AddressLength).
+func (b ChequeID) Size() int {
+	return chain.AddressLength
+}
+
+// MarshalTo tries to marshal ChequeID into passed bytes and returns
+// count of copied bytes or error, if bytes len is not enough to contain ChequeID.
+func (b ChequeID) MarshalTo(data []byte) (int, error) {
+	if len(data) < chain.AddressLength {
+		return 0, ErrInvalidLength
+	}
+	return copy(data, b.Bytes()), nil
+}
+
+// Equals checks that m and tx are valid and equal Tx values.
+func (m Tx) Equals(tx Tx) bool {
+	return m.From == tx.From &&
+		m.To == tx.To &&
+		m.Type == tx.Type &&
+		m.Amount == tx.Amount
+}
+
+// Verify validates current Cheque and Signatures that are generated for current Cheque.
+func (b Cheque) Verify() error {
+	data := b.marshalBody()
+	for i, sign := range b.Signatures {
+		if err := crypto.VerifyRFC6979(sign.Key, data, sign.Hash); err != nil {
+			return errors.Wrapf(ErrWrongSignature, "item #%d: %s", i, err.Error())
+		}
+	}
+
+	return nil
+}
+
+// Sign is used to sign current Cheque and stores result inside b.Signatures.
+func (b *Cheque) Sign(key *ecdsa.PrivateKey) error {
+	hash, err := crypto.SignRFC6979(key, b.marshalBody())
+	if err != nil {
+		return err
+	}
+
+	b.Signatures = append(b.Signatures, ChequeSignature{
+		Key:  &key.PublicKey,
+		Hash: hash,
+	})
+
+	return nil
+}
+
+func (b *Cheque) marshalBody() []byte {
+	buf := make([]byte, signaturesOffset)
+
+	var offset int
+
+	offset += copy(buf, b.ID.Bytes())
+	offset += copy(buf[offset:], b.Owner.Bytes())
+
+	binary.BigEndian.PutUint64(buf[offset:], uint64(b.Amount.Value))
+	offset += u64size
+
+	binary.BigEndian.PutUint64(buf[offset:], b.Height)
+
+	return buf
+}
+
+func (b *Cheque) unmarshalBody(buf []byte) error {
+	var offset int
+
+	if len(buf) < signaturesOffset {
+		return ErrWrongChequeData
+	}
+
+	{ // unmarshal UUID
+		if err := b.ID.Unmarshal(buf[offset : offset+chain.AddressLength]); err != nil {
+			return err
+		}
+		offset += chain.AddressLength
+	}
+
+	{ // unmarshal OwnerID
+		if err := b.Owner.Unmarshal(buf[offset : offset+refs.OwnerIDSize]); err != nil {
+			return err
+		}
+		offset += refs.OwnerIDSize
+	}
+
+	{ // unmarshal amount
+		amount := int64(binary.BigEndian.Uint64(buf[offset:]))
+		b.Amount = decimal.New(amount)
+		offset += u64size
+	}
+
+	{ // unmarshal height
+		b.Height = binary.BigEndian.Uint64(buf[offset:])
+		offset += u64size
+	}
+
+	return nil
+}
+
+// MarshalBinary is used to marshal Cheque into bytes.
+func (b Cheque) MarshalBinary() ([]byte, error) {
+	var (
+		count  = len(b.Signatures)
+		buf    = make([]byte, b.Size())
+		offset = copy(buf, b.marshalBody())
+	)
+
+	binary.BigEndian.PutUint16(buf[offset:], uint16(count))
+	offset += u16size
+
+	for _, sign := range b.Signatures {
+		key := crypto.MarshalPublicKey(sign.Key)
+		offset += copy(buf[offset:], key)
+		offset += copy(buf[offset:], sign.Hash)
+	}
+
+	return buf, nil
+}
+
+// Size returns size of Cheque (count of bytes needs to store it).
+func (b Cheque) Size() int {
+	return signaturesOffset + u16size +
+		len(b.Signatures)*(crypto.PublicKeyCompressedSize+crypto.RFC6979SignatureSize)
+}
+
+// UnmarshalBinary tries to parse []byte into valid Cheque.
+func (b *Cheque) UnmarshalBinary(buf []byte) error {
+	if err := b.unmarshalBody(buf); err != nil {
+		return err
+	}
+
+	body := buf[:signaturesOffset]
+
+	count := int64(binary.BigEndian.Uint16(buf[signaturesOffset:]))
+	offset := signaturesOffset + u16size
+
+	if ln := count * int64(crypto.PublicKeyCompressedSize+crypto.RFC6979SignatureSize); ln > int64(len(buf[offset:])) {
+		return ErrWrongChequeData
+	}
+
+	for i := int64(0); i < count; i++ {
+		sign := ChequeSignature{
+			Key:  crypto.UnmarshalPublicKey(buf[offset : offset+crypto.PublicKeyCompressedSize]),
+			Hash: make([]byte, crypto.RFC6979SignatureSize),
+		}
+
+		offset += crypto.PublicKeyCompressedSize
+		if sign.Key == nil {
+			return errors.Wrapf(ErrWrongPublicKey, "item #%d", i)
+		}
+
+		offset += copy(sign.Hash, buf[offset:offset+crypto.RFC6979SignatureSize])
+		if err := crypto.VerifyRFC6979(sign.Key, body, sign.Hash); err != nil {
+			return errors.Wrapf(ErrWrongSignature, "item #%d: %s (offset=%d, len=%d)", i, err.Error(), offset, len(sign.Hash))
+		}
+
+		b.Signatures = append(b.Signatures, sign)
+	}
+
+	return nil
+}
+
+// ErrNotEnoughFunds generates error using address and amounts.
+func ErrNotEnoughFunds(addr string, needed, residue *decimal.Decimal) error {
+	return errors.Errorf("not enough funds (requested=%s, residue=%s, addr=%s", needed, residue, addr)
+}
+
+func (m *Account) hasLockAcc(addr string) bool {
+	for i := range m.LockAccounts {
+		if m.LockAccounts[i].Address == addr {
+			return true
+		}
+	}
+	return false
+}
+
+// ValidateLock checks that account can be locked.
+func (m *Account) ValidateLock() error {
+	switch {
+	case m.Address == "":
+		return ErrEmptyAddress
+	case m.ParentAddress == "":
+		return ErrEmptyParentAddress
+	case m.LockTarget == nil:
+		return ErrEmptyLockTarget
+	}
+
+	switch v := m.LockTarget.Target.(type) {
+	case *LockTarget_WithdrawTarget:
+		if v.WithdrawTarget.Cheque != m.Address {
+			return errors.Errorf("wrong cheque ID: expected %s, has %s", m.Address, v.WithdrawTarget.Cheque)
+		}
+	case *LockTarget_ContainerCreateTarget:
+		switch {
+		case v.ContainerCreateTarget.CID.Empty():
+			return ErrEmptyContainerID
+		}
+	}
+	return nil
+}
+
+// CanLock checks possibility to lock funds.
+func (m *Account) CanLock(lockAcc *Account) error {
+	switch {
+	case m.ActiveFunds.LT(lockAcc.ActiveFunds):
+		return ErrNotEnoughFunds(lockAcc.ParentAddress, lockAcc.ActiveFunds, m.ActiveFunds)
+	case m.hasLockAcc(lockAcc.Address):
+		return errors.Errorf("could not lock account(%s) funds: duplicating lock(%s)", m.Address, lockAcc.Address)
+	default:
+		return nil
+	}
+}
+
+// LockForWithdraw checks that account contains locked funds by passed ChequeID.
+func (m *Account) LockForWithdraw(chequeID string) bool {
+	switch v := m.LockTarget.Target.(type) {
+	case *LockTarget_WithdrawTarget:
+		return v.WithdrawTarget.Cheque == chequeID
+	}
+	return false
+}
+
+// LockForContainerCreate checks that account contains locked funds for container creation.
+func (m *Account) LockForContainerCreate(cid refs.CID) bool {
+	switch v := m.LockTarget.Target.(type) {
+	case *LockTarget_ContainerCreateTarget:
+		return v.ContainerCreateTarget.CID.Equal(cid)
+	}
+	return false
+}
+
+// Equal checks that current Settlement is equal to passed Settlement.
+func (m *Settlement) Equal(s *Settlement) bool {
+	if s == nil || m.Epoch != s.Epoch || len(m.Transactions) != len(s.Transactions) {
+		return false
+	}
+	return len(m.Transactions) == 0 || reflect.DeepEqual(m.Transactions, s.Transactions)
+}
diff --git a/accounting/types.pb.go b/accounting/types.pb.go
new file mode 100644
index 00000000..cb4b0c8a
--- /dev/null
+++ b/accounting/types.pb.go
@@ -0,0 +1,3905 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: accounting/types.proto
+
+package accounting
+
+import (
+	fmt "fmt"
+	_ "github.com/gogo/protobuf/gogoproto"
+	proto "github.com/golang/protobuf/proto"
+	decimal "github.com/nspcc-dev/neofs-proto/decimal"
+	io "io"
+	math "math"
+	math_bits "math/bits"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
+
+type Lifetime_Unit int32
+
+const (
+	Lifetime_Unlimited  Lifetime_Unit = 0
+	Lifetime_NeoFSEpoch Lifetime_Unit = 1
+	Lifetime_NeoBlock   Lifetime_Unit = 2
+)
+
+var Lifetime_Unit_name = map[int32]string{
+	0: "Unlimited",
+	1: "NeoFSEpoch",
+	2: "NeoBlock",
+}
+
+var Lifetime_Unit_value = map[string]int32{
+	"Unlimited":  0,
+	"NeoFSEpoch": 1,
+	"NeoBlock":   2,
+}
+
+func (x Lifetime_Unit) String() string {
+	return proto.EnumName(Lifetime_Unit_name, int32(x))
+}
+
+func (Lifetime_Unit) EnumDescriptor() ([]byte, []int) {
+	return fileDescriptor_437c556d7375b726, []int{6, 0}
+}
+
+type Tx_Type int32
+
+const (
+	Tx_Unknown  Tx_Type = 0
+	Tx_Withdraw Tx_Type = 1
+	Tx_PayIO    Tx_Type = 2
+	Tx_Inner    Tx_Type = 3
+)
+
+var Tx_Type_name = map[int32]string{
+	0: "Unknown",
+	1: "Withdraw",
+	2: "PayIO",
+	3: "Inner",
+}
+
+var Tx_Type_value = map[string]int32{
+	"Unknown":  0,
+	"Withdraw": 1,
+	"PayIO":    2,
+	"Inner":    3,
+}
+
+func (x Tx_Type) String() string {
+	return proto.EnumName(Tx_Type_name, int32(x))
+}
+
+func (Tx_Type) EnumDescriptor() ([]byte, []int) {
+	return fileDescriptor_437c556d7375b726, []int{7, 0}
+}
+
+// Snapshot accounting messages
+type Account struct {
+	OwnerID              OwnerID          `protobuf:"bytes,1,opt,name=OwnerID,proto3,customtype=OwnerID" json:"OwnerID"`
+	Address              string           `protobuf:"bytes,2,opt,name=Address,proto3" json:"Address,omitempty"`
+	ParentAddress        string           `protobuf:"bytes,3,opt,name=ParentAddress,proto3" json:"ParentAddress,omitempty"`
+	ActiveFunds          *decimal.Decimal `protobuf:"bytes,4,opt,name=ActiveFunds,proto3" json:"ActiveFunds,omitempty"`
+	Lifetime             Lifetime         `protobuf:"bytes,5,opt,name=Lifetime,proto3" json:"Lifetime"`
+	LockTarget           *LockTarget      `protobuf:"bytes,6,opt,name=LockTarget,proto3" json:"LockTarget,omitempty"`
+	LockAccounts         []*Account       `protobuf:"bytes,7,rep,name=LockAccounts,proto3" json:"LockAccounts,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}         `json:"-"`
+	XXX_unrecognized     []byte           `json:"-"`
+	XXX_sizecache        int32            `json:"-"`
+}
+
+func (m *Account) Reset()         { *m = Account{} }
+func (m *Account) String() string { return proto.CompactTextString(m) }
+func (*Account) ProtoMessage()    {}
+func (*Account) Descriptor() ([]byte, []int) {
+	return fileDescriptor_437c556d7375b726, []int{0}
+}
+func (m *Account) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *Account) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *Account) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Account.Merge(m, src)
+}
+func (m *Account) XXX_Size() int {
+	return m.Size()
+}
+func (m *Account) XXX_DiscardUnknown() {
+	xxx_messageInfo_Account.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Account proto.InternalMessageInfo
+
+func (m *Account) GetAddress() string {
+	if m != nil {
+		return m.Address
+	}
+	return ""
+}
+
+func (m *Account) GetParentAddress() string {
+	if m != nil {
+		return m.ParentAddress
+	}
+	return ""
+}
+
+func (m *Account) GetActiveFunds() *decimal.Decimal {
+	if m != nil {
+		return m.ActiveFunds
+	}
+	return nil
+}
+
+func (m *Account) GetLifetime() Lifetime {
+	if m != nil {
+		return m.Lifetime
+	}
+	return Lifetime{}
+}
+
+func (m *Account) GetLockTarget() *LockTarget {
+	if m != nil {
+		return m.LockTarget
+	}
+	return nil
+}
+
+func (m *Account) GetLockAccounts() []*Account {
+	if m != nil {
+		return m.LockAccounts
+	}
+	return nil
+}
+
+type LockTarget struct {
+	// Types that are valid to be assigned to Target:
+	//	*LockTarget_WithdrawTarget
+	//	*LockTarget_ContainerCreateTarget
+	Target               isLockTarget_Target `protobuf_oneof:"Target"`
+	XXX_NoUnkeyedLiteral struct{}            `json:"-"`
+	XXX_unrecognized     []byte              `json:"-"`
+	XXX_sizecache        int32               `json:"-"`
+}
+
+func (m *LockTarget) Reset()         { *m = LockTarget{} }
+func (m *LockTarget) String() string { return proto.CompactTextString(m) }
+func (*LockTarget) ProtoMessage()    {}
+func (*LockTarget) Descriptor() ([]byte, []int) {
+	return fileDescriptor_437c556d7375b726, []int{1}
+}
+func (m *LockTarget) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *LockTarget) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *LockTarget) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_LockTarget.Merge(m, src)
+}
+func (m *LockTarget) XXX_Size() int {
+	return m.Size()
+}
+func (m *LockTarget) XXX_DiscardUnknown() {
+	xxx_messageInfo_LockTarget.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_LockTarget proto.InternalMessageInfo
+
+type isLockTarget_Target interface {
+	isLockTarget_Target()
+	MarshalTo([]byte) (int, error)
+	Size() int
+}
+
+type LockTarget_WithdrawTarget struct {
+	WithdrawTarget *WithdrawTarget `protobuf:"bytes,1,opt,name=WithdrawTarget,proto3,oneof" json:"WithdrawTarget,omitempty"`
+}
+type LockTarget_ContainerCreateTarget struct {
+	ContainerCreateTarget *ContainerCreateTarget `protobuf:"bytes,2,opt,name=ContainerCreateTarget,proto3,oneof" json:"ContainerCreateTarget,omitempty"`
+}
+
+func (*LockTarget_WithdrawTarget) isLockTarget_Target()        {}
+func (*LockTarget_ContainerCreateTarget) isLockTarget_Target() {}
+
+func (m *LockTarget) GetTarget() isLockTarget_Target {
+	if m != nil {
+		return m.Target
+	}
+	return nil
+}
+
+func (m *LockTarget) GetWithdrawTarget() *WithdrawTarget {
+	if x, ok := m.GetTarget().(*LockTarget_WithdrawTarget); ok {
+		return x.WithdrawTarget
+	}
+	return nil
+}
+
+func (m *LockTarget) GetContainerCreateTarget() *ContainerCreateTarget {
+	if x, ok := m.GetTarget().(*LockTarget_ContainerCreateTarget); ok {
+		return x.ContainerCreateTarget
+	}
+	return nil
+}
+
+// XXX_OneofWrappers is for the internal use of the proto package.
+func (*LockTarget) XXX_OneofWrappers() []interface{} {
+	return []interface{}{
+		(*LockTarget_WithdrawTarget)(nil),
+		(*LockTarget_ContainerCreateTarget)(nil),
+	}
+}
+
+// Snapshot balance messages
+type Balances struct {
+	Accounts             []Account `protobuf:"bytes,1,rep,name=Accounts,proto3" json:"Accounts"`
+	XXX_NoUnkeyedLiteral struct{}  `json:"-"`
+	XXX_unrecognized     []byte    `json:"-"`
+	XXX_sizecache        int32     `json:"-"`
+}
+
+func (m *Balances) Reset()         { *m = Balances{} }
+func (m *Balances) String() string { return proto.CompactTextString(m) }
+func (*Balances) ProtoMessage()    {}
+func (*Balances) Descriptor() ([]byte, []int) {
+	return fileDescriptor_437c556d7375b726, []int{2}
+}
+func (m *Balances) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *Balances) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *Balances) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Balances.Merge(m, src)
+}
+func (m *Balances) XXX_Size() int {
+	return m.Size()
+}
+func (m *Balances) XXX_DiscardUnknown() {
+	xxx_messageInfo_Balances.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Balances proto.InternalMessageInfo
+
+func (m *Balances) GetAccounts() []Account {
+	if m != nil {
+		return m.Accounts
+	}
+	return nil
+}
+
+// PayIn / PayOut messages
+type PayIO struct {
+	BlockID              uint64   `protobuf:"varint,1,opt,name=BlockID,proto3" json:"BlockID,omitempty"`
+	Transactions         []Tx     `protobuf:"bytes,2,rep,name=Transactions,proto3" json:"Transactions"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *PayIO) Reset()         { *m = PayIO{} }
+func (m *PayIO) String() string { return proto.CompactTextString(m) }
+func (*PayIO) ProtoMessage()    {}
+func (*PayIO) Descriptor() ([]byte, []int) {
+	return fileDescriptor_437c556d7375b726, []int{3}
+}
+func (m *PayIO) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *PayIO) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *PayIO) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_PayIO.Merge(m, src)
+}
+func (m *PayIO) XXX_Size() int {
+	return m.Size()
+}
+func (m *PayIO) XXX_DiscardUnknown() {
+	xxx_messageInfo_PayIO.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_PayIO proto.InternalMessageInfo
+
+func (m *PayIO) GetBlockID() uint64 {
+	if m != nil {
+		return m.BlockID
+	}
+	return 0
+}
+
+func (m *PayIO) GetTransactions() []Tx {
+	if m != nil {
+		return m.Transactions
+	}
+	return nil
+}
+
+// Clearing messages
+type Clearing struct {
+	Transactions         []Tx     `protobuf:"bytes,1,rep,name=Transactions,proto3" json:"Transactions"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *Clearing) Reset()         { *m = Clearing{} }
+func (m *Clearing) String() string { return proto.CompactTextString(m) }
+func (*Clearing) ProtoMessage()    {}
+func (*Clearing) Descriptor() ([]byte, []int) {
+	return fileDescriptor_437c556d7375b726, []int{4}
+}
+func (m *Clearing) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *Clearing) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *Clearing) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Clearing.Merge(m, src)
+}
+func (m *Clearing) XXX_Size() int {
+	return m.Size()
+}
+func (m *Clearing) XXX_DiscardUnknown() {
+	xxx_messageInfo_Clearing.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Clearing proto.InternalMessageInfo
+
+func (m *Clearing) GetTransactions() []Tx {
+	if m != nil {
+		return m.Transactions
+	}
+	return nil
+}
+
+// Clearing messages
+type Withdraw struct {
+	ID                   string   `protobuf:"bytes,1,opt,name=ID,proto3" json:"ID,omitempty"`
+	Epoch                uint64   `protobuf:"varint,2,opt,name=Epoch,proto3" json:"Epoch,omitempty"`
+	Transaction          *Tx      `protobuf:"bytes,3,opt,name=Transaction,proto3" json:"Transaction,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *Withdraw) Reset()         { *m = Withdraw{} }
+func (m *Withdraw) String() string { return proto.CompactTextString(m) }
+func (*Withdraw) ProtoMessage()    {}
+func (*Withdraw) Descriptor() ([]byte, []int) {
+	return fileDescriptor_437c556d7375b726, []int{5}
+}
+func (m *Withdraw) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *Withdraw) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *Withdraw) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Withdraw.Merge(m, src)
+}
+func (m *Withdraw) XXX_Size() int {
+	return m.Size()
+}
+func (m *Withdraw) XXX_DiscardUnknown() {
+	xxx_messageInfo_Withdraw.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Withdraw proto.InternalMessageInfo
+
+func (m *Withdraw) GetID() string {
+	if m != nil {
+		return m.ID
+	}
+	return ""
+}
+
+func (m *Withdraw) GetEpoch() uint64 {
+	if m != nil {
+		return m.Epoch
+	}
+	return 0
+}
+
+func (m *Withdraw) GetTransaction() *Tx {
+	if m != nil {
+		return m.Transaction
+	}
+	return nil
+}
+
+// Lifetime of locks
+type Lifetime struct {
+	Unit                 Lifetime_Unit `protobuf:"varint,1,opt,name=unit,proto3,enum=accounting.Lifetime_Unit" json:"unit,omitempty"`
+	Value                int64         `protobuf:"varint,2,opt,name=Value,proto3" json:"Value,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}      `json:"-"`
+	XXX_unrecognized     []byte        `json:"-"`
+	XXX_sizecache        int32         `json:"-"`
+}
+
+func (m *Lifetime) Reset()         { *m = Lifetime{} }
+func (m *Lifetime) String() string { return proto.CompactTextString(m) }
+func (*Lifetime) ProtoMessage()    {}
+func (*Lifetime) Descriptor() ([]byte, []int) {
+	return fileDescriptor_437c556d7375b726, []int{6}
+}
+func (m *Lifetime) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *Lifetime) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *Lifetime) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Lifetime.Merge(m, src)
+}
+func (m *Lifetime) XXX_Size() int {
+	return m.Size()
+}
+func (m *Lifetime) XXX_DiscardUnknown() {
+	xxx_messageInfo_Lifetime.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Lifetime proto.InternalMessageInfo
+
+func (m *Lifetime) GetUnit() Lifetime_Unit {
+	if m != nil {
+		return m.Unit
+	}
+	return Lifetime_Unlimited
+}
+
+func (m *Lifetime) GetValue() int64 {
+	if m != nil {
+		return m.Value
+	}
+	return 0
+}
+
+// Transaction messages
+type Tx struct {
+	Type                 Tx_Type          `protobuf:"varint,1,opt,name=type,proto3,enum=accounting.Tx_Type" json:"type,omitempty"`
+	From                 string           `protobuf:"bytes,2,opt,name=From,proto3" json:"From,omitempty"`
+	To                   string           `protobuf:"bytes,3,opt,name=To,proto3" json:"To,omitempty"`
+	Amount               *decimal.Decimal `protobuf:"bytes,4,opt,name=Amount,proto3" json:"Amount,omitempty"`
+	PublicKeys           []byte           `protobuf:"bytes,5,opt,name=PublicKeys,proto3" json:"PublicKeys,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}         `json:"-"`
+	XXX_unrecognized     []byte           `json:"-"`
+	XXX_sizecache        int32            `json:"-"`
+}
+
+func (m *Tx) Reset()         { *m = Tx{} }
+func (m *Tx) String() string { return proto.CompactTextString(m) }
+func (*Tx) ProtoMessage()    {}
+func (*Tx) Descriptor() ([]byte, []int) {
+	return fileDescriptor_437c556d7375b726, []int{7}
+}
+func (m *Tx) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *Tx) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *Tx) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Tx.Merge(m, src)
+}
+func (m *Tx) XXX_Size() int {
+	return m.Size()
+}
+func (m *Tx) XXX_DiscardUnknown() {
+	xxx_messageInfo_Tx.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Tx proto.InternalMessageInfo
+
+func (m *Tx) GetType() Tx_Type {
+	if m != nil {
+		return m.Type
+	}
+	return Tx_Unknown
+}
+
+func (m *Tx) GetFrom() string {
+	if m != nil {
+		return m.From
+	}
+	return ""
+}
+
+func (m *Tx) GetTo() string {
+	if m != nil {
+		return m.To
+	}
+	return ""
+}
+
+func (m *Tx) GetAmount() *decimal.Decimal {
+	if m != nil {
+		return m.Amount
+	}
+	return nil
+}
+
+func (m *Tx) GetPublicKeys() []byte {
+	if m != nil {
+		return m.PublicKeys
+	}
+	return nil
+}
+
+type Settlement struct {
+	Epoch                uint64           `protobuf:"varint,1,opt,name=Epoch,proto3" json:"Epoch,omitempty"`
+	Transactions         []*Settlement_Tx `protobuf:"bytes,2,rep,name=Transactions,proto3" json:"Transactions,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}         `json:"-"`
+	XXX_unrecognized     []byte           `json:"-"`
+	XXX_sizecache        int32            `json:"-"`
+}
+
+func (m *Settlement) Reset()         { *m = Settlement{} }
+func (m *Settlement) String() string { return proto.CompactTextString(m) }
+func (*Settlement) ProtoMessage()    {}
+func (*Settlement) Descriptor() ([]byte, []int) {
+	return fileDescriptor_437c556d7375b726, []int{8}
+}
+func (m *Settlement) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *Settlement) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *Settlement) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Settlement.Merge(m, src)
+}
+func (m *Settlement) XXX_Size() int {
+	return m.Size()
+}
+func (m *Settlement) XXX_DiscardUnknown() {
+	xxx_messageInfo_Settlement.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Settlement proto.InternalMessageInfo
+
+func (m *Settlement) GetEpoch() uint64 {
+	if m != nil {
+		return m.Epoch
+	}
+	return 0
+}
+
+func (m *Settlement) GetTransactions() []*Settlement_Tx {
+	if m != nil {
+		return m.Transactions
+	}
+	return nil
+}
+
+type Settlement_Receiver struct {
+	To                   string           `protobuf:"bytes,1,opt,name=To,proto3" json:"To,omitempty"`
+	Amount               *decimal.Decimal `protobuf:"bytes,2,opt,name=Amount,proto3" json:"Amount,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}         `json:"-"`
+	XXX_unrecognized     []byte           `json:"-"`
+	XXX_sizecache        int32            `json:"-"`
+}
+
+func (m *Settlement_Receiver) Reset()         { *m = Settlement_Receiver{} }
+func (m *Settlement_Receiver) String() string { return proto.CompactTextString(m) }
+func (*Settlement_Receiver) ProtoMessage()    {}
+func (*Settlement_Receiver) Descriptor() ([]byte, []int) {
+	return fileDescriptor_437c556d7375b726, []int{8, 0}
+}
+func (m *Settlement_Receiver) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *Settlement_Receiver) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *Settlement_Receiver) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Settlement_Receiver.Merge(m, src)
+}
+func (m *Settlement_Receiver) XXX_Size() int {
+	return m.Size()
+}
+func (m *Settlement_Receiver) XXX_DiscardUnknown() {
+	xxx_messageInfo_Settlement_Receiver.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Settlement_Receiver proto.InternalMessageInfo
+
+func (m *Settlement_Receiver) GetTo() string {
+	if m != nil {
+		return m.To
+	}
+	return ""
+}
+
+func (m *Settlement_Receiver) GetAmount() *decimal.Decimal {
+	if m != nil {
+		return m.Amount
+	}
+	return nil
+}
+
+type Settlement_Container struct {
+	CID                  CID      `protobuf:"bytes,1,opt,name=CID,proto3,customtype=CID" json:"CID"`
+	SGIDs                []SGID   `protobuf:"bytes,2,rep,name=SGIDs,proto3,customtype=SGID" json:"SGIDs"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *Settlement_Container) Reset()         { *m = Settlement_Container{} }
+func (m *Settlement_Container) String() string { return proto.CompactTextString(m) }
+func (*Settlement_Container) ProtoMessage()    {}
+func (*Settlement_Container) Descriptor() ([]byte, []int) {
+	return fileDescriptor_437c556d7375b726, []int{8, 1}
+}
+func (m *Settlement_Container) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *Settlement_Container) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *Settlement_Container) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Settlement_Container.Merge(m, src)
+}
+func (m *Settlement_Container) XXX_Size() int {
+	return m.Size()
+}
+func (m *Settlement_Container) XXX_DiscardUnknown() {
+	xxx_messageInfo_Settlement_Container.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Settlement_Container proto.InternalMessageInfo
+
+type Settlement_Tx struct {
+	From                 string                `protobuf:"bytes,1,opt,name=From,proto3" json:"From,omitempty"`
+	Container            Settlement_Container  `protobuf:"bytes,2,opt,name=Container,proto3" json:"Container"`
+	Receivers            []Settlement_Receiver `protobuf:"bytes,3,rep,name=Receivers,proto3" json:"Receivers"`
+	XXX_NoUnkeyedLiteral struct{}              `json:"-"`
+	XXX_unrecognized     []byte                `json:"-"`
+	XXX_sizecache        int32                 `json:"-"`
+}
+
+func (m *Settlement_Tx) Reset()         { *m = Settlement_Tx{} }
+func (m *Settlement_Tx) String() string { return proto.CompactTextString(m) }
+func (*Settlement_Tx) ProtoMessage()    {}
+func (*Settlement_Tx) Descriptor() ([]byte, []int) {
+	return fileDescriptor_437c556d7375b726, []int{8, 2}
+}
+func (m *Settlement_Tx) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *Settlement_Tx) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *Settlement_Tx) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Settlement_Tx.Merge(m, src)
+}
+func (m *Settlement_Tx) XXX_Size() int {
+	return m.Size()
+}
+func (m *Settlement_Tx) XXX_DiscardUnknown() {
+	xxx_messageInfo_Settlement_Tx.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Settlement_Tx proto.InternalMessageInfo
+
+func (m *Settlement_Tx) GetFrom() string {
+	if m != nil {
+		return m.From
+	}
+	return ""
+}
+
+func (m *Settlement_Tx) GetContainer() Settlement_Container {
+	if m != nil {
+		return m.Container
+	}
+	return Settlement_Container{}
+}
+
+func (m *Settlement_Tx) GetReceivers() []Settlement_Receiver {
+	if m != nil {
+		return m.Receivers
+	}
+	return nil
+}
+
+type ContainerCreateTarget struct {
+	CID                  CID      `protobuf:"bytes,1,opt,name=CID,proto3,customtype=CID" json:"CID"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *ContainerCreateTarget) Reset()         { *m = ContainerCreateTarget{} }
+func (m *ContainerCreateTarget) String() string { return proto.CompactTextString(m) }
+func (*ContainerCreateTarget) ProtoMessage()    {}
+func (*ContainerCreateTarget) Descriptor() ([]byte, []int) {
+	return fileDescriptor_437c556d7375b726, []int{9}
+}
+func (m *ContainerCreateTarget) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *ContainerCreateTarget) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *ContainerCreateTarget) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_ContainerCreateTarget.Merge(m, src)
+}
+func (m *ContainerCreateTarget) XXX_Size() int {
+	return m.Size()
+}
+func (m *ContainerCreateTarget) XXX_DiscardUnknown() {
+	xxx_messageInfo_ContainerCreateTarget.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ContainerCreateTarget proto.InternalMessageInfo
+
+type WithdrawTarget struct {
+	Cheque               string   `protobuf:"bytes,1,opt,name=Cheque,proto3" json:"Cheque,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *WithdrawTarget) Reset()         { *m = WithdrawTarget{} }
+func (m *WithdrawTarget) String() string { return proto.CompactTextString(m) }
+func (*WithdrawTarget) ProtoMessage()    {}
+func (*WithdrawTarget) Descriptor() ([]byte, []int) {
+	return fileDescriptor_437c556d7375b726, []int{10}
+}
+func (m *WithdrawTarget) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *WithdrawTarget) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *WithdrawTarget) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_WithdrawTarget.Merge(m, src)
+}
+func (m *WithdrawTarget) XXX_Size() int {
+	return m.Size()
+}
+func (m *WithdrawTarget) XXX_DiscardUnknown() {
+	xxx_messageInfo_WithdrawTarget.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_WithdrawTarget proto.InternalMessageInfo
+
+func (m *WithdrawTarget) GetCheque() string {
+	if m != nil {
+		return m.Cheque
+	}
+	return ""
+}
+
+func init() {
+	proto.RegisterEnum("accounting.Lifetime_Unit", Lifetime_Unit_name, Lifetime_Unit_value)
+	proto.RegisterEnum("accounting.Tx_Type", Tx_Type_name, Tx_Type_value)
+	proto.RegisterType((*Account)(nil), "accounting.Account")
+	proto.RegisterType((*LockTarget)(nil), "accounting.LockTarget")
+	proto.RegisterType((*Balances)(nil), "accounting.Balances")
+	proto.RegisterType((*PayIO)(nil), "accounting.PayIO")
+	proto.RegisterType((*Clearing)(nil), "accounting.Clearing")
+	proto.RegisterType((*Withdraw)(nil), "accounting.Withdraw")
+	proto.RegisterType((*Lifetime)(nil), "accounting.Lifetime")
+	proto.RegisterType((*Tx)(nil), "accounting.Tx")
+	proto.RegisterType((*Settlement)(nil), "accounting.Settlement")
+	proto.RegisterType((*Settlement_Receiver)(nil), "accounting.Settlement.Receiver")
+	proto.RegisterType((*Settlement_Container)(nil), "accounting.Settlement.Container")
+	proto.RegisterType((*Settlement_Tx)(nil), "accounting.Settlement.Tx")
+	proto.RegisterType((*ContainerCreateTarget)(nil), "accounting.ContainerCreateTarget")
+	proto.RegisterType((*WithdrawTarget)(nil), "accounting.WithdrawTarget")
+}
+
+func init() { proto.RegisterFile("accounting/types.proto", fileDescriptor_437c556d7375b726) }
+
+var fileDescriptor_437c556d7375b726 = []byte{
+	// 866 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x55, 0x4d, 0x73, 0x22, 0x45,
+	0x18, 0xa6, 0x87, 0x09, 0x0c, 0x2f, 0x2c, 0x52, 0xbd, 0xbb, 0x29, 0xa4, 0x4a, 0x82, 0x53, 0x1e,
+	0xb0, 0xac, 0x80, 0x66, 0xcb, 0xc4, 0x8b, 0x07, 0x3e, 0x8c, 0x4b, 0xb9, 0x95, 0x4d, 0x75, 0x88,
+	0x96, 0x7a, 0x1a, 0x86, 0x0e, 0xe9, 0x0a, 0x74, 0xe3, 0x4c, 0x93, 0x6c, 0xfe, 0x84, 0x67, 0x2f,
+	0x9e, 0xfc, 0x11, 0xfe, 0x85, 0x3d, 0xea, 0xcd, 0xf2, 0x90, 0xb2, 0xf0, 0x8f, 0x58, 0xdd, 0xd3,
+	0x33, 0xcc, 0xec, 0x82, 0x7a, 0x81, 0xf7, 0xe3, 0x79, 0x9f, 0x7e, 0xbf, 0xba, 0x07, 0xf6, 0x3d,
+	0xdf, 0x17, 0x2b, 0x2e, 0x19, 0x9f, 0x75, 0xe5, 0xfd, 0x92, 0x86, 0x9d, 0x65, 0x20, 0xa4, 0xc0,
+	0xb0, 0xb1, 0x37, 0x9e, 0x4e, 0xa9, 0xcf, 0x16, 0xde, 0xbc, 0x6b, 0xfe, 0x23, 0x48, 0xe3, 0x70,
+	0xc6, 0xe4, 0xf5, 0x6a, 0xd2, 0xf1, 0xc5, 0xa2, 0x3b, 0x13, 0x33, 0xd1, 0xd5, 0xe6, 0xc9, 0xea,
+	0x4a, 0x6b, 0x5a, 0xd1, 0x52, 0x04, 0x77, 0x7f, 0xb7, 0xa0, 0xd8, 0x8b, 0x48, 0xf1, 0x87, 0x50,
+	0x7c, 0x79, 0xc7, 0x69, 0x30, 0x1a, 0xd6, 0x51, 0x0b, 0xb5, 0x2b, 0xfd, 0x77, 0x5e, 0x3f, 0x1c,
+	0xe4, 0xfe, 0x7c, 0x38, 0x88, 0xcd, 0x24, 0x16, 0x70, 0x1d, 0x8a, 0xbd, 0xe9, 0x34, 0xa0, 0x61,
+	0x58, 0xb7, 0x5a, 0xa8, 0x5d, 0x22, 0xb1, 0x8a, 0x3f, 0x80, 0x47, 0xe7, 0x5e, 0x40, 0xb9, 0x8c,
+	0xfd, 0x79, 0xed, 0xcf, 0x1a, 0xf1, 0x11, 0x94, 0x7b, 0xbe, 0x64, 0xb7, 0xf4, 0x74, 0xc5, 0xa7,
+	0x61, 0xdd, 0x6e, 0xa1, 0x76, 0xf9, 0xa8, 0xd6, 0x89, 0x4b, 0x19, 0x46, 0xff, 0x24, 0x0d, 0xc2,
+	0xc7, 0xe0, 0xbc, 0x60, 0x57, 0x54, 0xb2, 0x05, 0xad, 0xef, 0xe9, 0x80, 0x27, 0x9d, 0x4d, 0x3f,
+	0x3a, 0xb1, 0xaf, 0x6f, 0xab, 0xac, 0x49, 0x82, 0xc5, 0xc7, 0x00, 0x2f, 0x84, 0x7f, 0x33, 0xf6,
+	0x82, 0x19, 0x95, 0xf5, 0x82, 0x8e, 0xdc, 0xcf, 0x44, 0x26, 0x5e, 0x92, 0x42, 0xe2, 0x13, 0xa8,
+	0x28, 0xcd, 0x74, 0x27, 0xac, 0x17, 0x5b, 0xf9, 0x76, 0xf9, 0xe8, 0x71, 0x3a, 0xd2, 0xf8, 0x48,
+	0x06, 0xe8, 0xfe, 0x8a, 0xd2, 0x27, 0xe2, 0x21, 0x54, 0xbf, 0x61, 0xf2, 0x7a, 0x1a, 0x78, 0x77,
+	0x26, 0x07, 0xa4, 0x73, 0x68, 0xa4, 0x99, 0xb2, 0x88, 0xe7, 0x39, 0xf2, 0x46, 0x0c, 0xfe, 0x16,
+	0x9e, 0x0e, 0x04, 0x97, 0x1e, 0xe3, 0x34, 0x18, 0x04, 0xd4, 0x93, 0xd4, 0x90, 0x59, 0x9a, 0xec,
+	0xfd, 0x34, 0xd9, 0x56, 0xe0, 0xf3, 0x1c, 0xd9, 0xce, 0xd0, 0x77, 0xa0, 0x10, 0x49, 0x6e, 0x0f,
+	0x9c, 0xbe, 0x37, 0xf7, 0xb8, 0x4f, 0x43, 0xfc, 0x29, 0x38, 0x49, 0xe9, 0x68, 0x67, 0xe9, 0x71,
+	0xb7, 0x93, 0xe2, 0xbf, 0x87, 0xbd, 0x73, 0xef, 0x7e, 0xf4, 0x52, 0xad, 0x48, 0x7f, 0x2e, 0xfc,
+	0x1b, 0xb3, 0x4d, 0x36, 0x89, 0x55, 0xfc, 0x19, 0x54, 0xc6, 0x81, 0xc7, 0x43, 0xcf, 0x97, 0x4c,
+	0x70, 0xb5, 0x41, 0x8a, 0xbd, 0x9a, 0x66, 0x1f, 0xbf, 0x32, 0xc4, 0x19, 0xa4, 0x3b, 0x04, 0x67,
+	0x30, 0xa7, 0x5e, 0xc0, 0xf8, 0xec, 0x2d, 0x16, 0xf4, 0xbf, 0x59, 0x26, 0xe0, 0xc4, 0xcd, 0xc5,
+	0x55, 0xb0, 0x4c, 0x82, 0x25, 0x62, 0x8d, 0x86, 0xf8, 0x09, 0xec, 0x7d, 0xb1, 0x14, 0xfe, 0xb5,
+	0x6e, 0xab, 0x4d, 0x22, 0x05, 0x7f, 0x0c, 0xe5, 0x14, 0x83, 0x5e, 0xe9, 0xb7, 0x8e, 0x22, 0x69,
+	0x88, 0xfb, 0x23, 0xda, 0x6c, 0x2b, 0x3e, 0x01, 0x7b, 0xc5, 0x59, 0x34, 0xf7, 0xea, 0xd1, 0xbb,
+	0xdb, 0xb6, 0xb6, 0x73, 0xc9, 0x99, 0xec, 0x3b, 0xeb, 0x87, 0x03, 0x5b, 0x49, 0x44, 0x07, 0xa8,
+	0x6c, 0xbe, 0xf6, 0xe6, 0x2b, 0xaa, 0xb3, 0xc9, 0x93, 0x48, 0x71, 0x9f, 0x81, 0xc6, 0xe0, 0x47,
+	0x50, 0xba, 0xe4, 0x73, 0xb6, 0x60, 0x92, 0x4e, 0x6b, 0x39, 0x5c, 0x05, 0x38, 0xa3, 0xe2, 0xf4,
+	0x42, 0xa7, 0x5c, 0x43, 0xb8, 0x02, 0xce, 0x19, 0x15, 0xba, 0xe9, 0x35, 0xcb, 0x7d, 0x40, 0x60,
+	0x8d, 0x5f, 0xe1, 0x4f, 0xc0, 0x56, 0x0f, 0x8a, 0x49, 0xe5, 0x71, 0xb6, 0x84, 0xce, 0xf8, 0x7e,
+	0x49, 0xa3, 0x24, 0x94, 0x44, 0x34, 0x14, 0x63, 0xb0, 0x4f, 0x03, 0xb1, 0x30, 0x17, 0x5d, 0xcb,
+	0xaa, 0x6d, 0x63, 0x61, 0xae, 0xb6, 0x35, 0x16, 0xb8, 0x0d, 0x85, 0xde, 0x42, 0x11, 0xed, 0xbc,
+	0xca, 0xc6, 0x8f, 0x9b, 0x00, 0xe7, 0xab, 0xc9, 0x9c, 0xf9, 0x5f, 0xd1, 0xfb, 0x50, 0xdf, 0xe3,
+	0x0a, 0x49, 0x59, 0xdc, 0x13, 0xd0, 0x67, 0xe3, 0x32, 0x14, 0x2f, 0xf9, 0x0d, 0x17, 0x77, 0xbc,
+	0x96, 0x53, 0xa5, 0xc4, 0x13, 0xab, 0x21, 0x5c, 0x32, 0x2b, 0x56, 0xb3, 0x94, 0x38, 0xe2, 0x9c,
+	0x06, 0xb5, 0xbc, 0xfb, 0x73, 0x1e, 0xe0, 0x82, 0x4a, 0x39, 0xa7, 0x0b, 0xca, 0xe5, 0x66, 0x90,
+	0x28, 0x3d, 0xc8, 0xcf, 0xb7, 0xae, 0x5e, 0x66, 0x22, 0x1b, 0x0e, 0x35, 0xd4, 0x0c, 0xbc, 0x31,
+	0x04, 0x87, 0x50, 0x9f, 0xb2, 0x5b, 0x1a, 0x98, 0x16, 0xa0, 0x2d, 0x2d, 0xb0, 0xfe, 0xbd, 0x05,
+	0x8d, 0x33, 0x28, 0x25, 0x17, 0x11, 0xbf, 0x07, 0xf9, 0x41, 0xf2, 0xe0, 0x96, 0xcd, 0x83, 0xab,
+	0x4c, 0x44, 0xfd, 0x60, 0x17, 0xf6, 0x2e, 0xbe, 0x1c, 0x0d, 0xa3, 0x4c, 0x2b, 0xfd, 0x8a, 0x01,
+	0xd8, 0xca, 0x48, 0x22, 0x57, 0xe3, 0x97, 0x68, 0xb4, 0xf1, 0x9c, 0x50, 0x6a, 0x4e, 0xc3, 0xd4,
+	0x51, 0x26, 0xaf, 0xd6, 0x8e, 0x62, 0x13, 0x9c, 0xb9, 0x33, 0xa9, 0x1c, 0x07, 0x50, 0x8a, 0xcb,
+	0x56, 0xef, 0xb9, 0x6a, 0xd9, 0xc1, 0x0e, 0x96, 0x18, 0x17, 0x93, 0x24, 0x71, 0xee, 0xf1, 0x8e,
+	0x07, 0xec, 0x3f, 0x3a, 0xe0, 0xb6, 0xdf, 0x7c, 0x3e, 0xf1, 0x3e, 0x14, 0x06, 0xd7, 0xf4, 0x87,
+	0x15, 0x35, 0xa5, 0x1a, 0xad, 0xdf, 0x7b, 0xbd, 0x6e, 0xa2, 0xdf, 0xd6, 0x4d, 0xf4, 0xc7, 0xba,
+	0x89, 0xfe, 0x5a, 0x37, 0xd1, 0x4f, 0x7f, 0x37, 0x73, 0xdf, 0x7d, 0x94, 0xfa, 0x20, 0xf2, 0x70,
+	0xe9, 0xfb, 0x87, 0x53, 0x7a, 0xdb, 0xe5, 0x54, 0x5c, 0x85, 0x87, 0xd1, 0xe7, 0x70, 0x53, 0xc9,
+	0xa4, 0xa0, 0x2d, 0xcf, 0xfe, 0x09, 0x00, 0x00, 0xff, 0xff, 0x66, 0x69, 0x27, 0xa6, 0x81, 0x07,
+	0x00, 0x00,
+}
+
+func (m *Account) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *Account) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *Account) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if len(m.LockAccounts) > 0 {
+		for iNdEx := len(m.LockAccounts) - 1; iNdEx >= 0; iNdEx-- {
+			{
+				size, err := m.LockAccounts[iNdEx].MarshalToSizedBuffer(dAtA[:i])
+				if err != nil {
+					return 0, err
+				}
+				i -= size
+				i = encodeVarintTypes(dAtA, i, uint64(size))
+			}
+			i--
+			dAtA[i] = 0x3a
+		}
+	}
+	if m.LockTarget != nil {
+		{
+			size, err := m.LockTarget.MarshalToSizedBuffer(dAtA[:i])
+			if err != nil {
+				return 0, err
+			}
+			i -= size
+			i = encodeVarintTypes(dAtA, i, uint64(size))
+		}
+		i--
+		dAtA[i] = 0x32
+	}
+	{
+		size, err := m.Lifetime.MarshalToSizedBuffer(dAtA[:i])
+		if err != nil {
+			return 0, err
+		}
+		i -= size
+		i = encodeVarintTypes(dAtA, i, uint64(size))
+	}
+	i--
+	dAtA[i] = 0x2a
+	if m.ActiveFunds != nil {
+		{
+			size, err := m.ActiveFunds.MarshalToSizedBuffer(dAtA[:i])
+			if err != nil {
+				return 0, err
+			}
+			i -= size
+			i = encodeVarintTypes(dAtA, i, uint64(size))
+		}
+		i--
+		dAtA[i] = 0x22
+	}
+	if len(m.ParentAddress) > 0 {
+		i -= len(m.ParentAddress)
+		copy(dAtA[i:], m.ParentAddress)
+		i = encodeVarintTypes(dAtA, i, uint64(len(m.ParentAddress)))
+		i--
+		dAtA[i] = 0x1a
+	}
+	if len(m.Address) > 0 {
+		i -= len(m.Address)
+		copy(dAtA[i:], m.Address)
+		i = encodeVarintTypes(dAtA, i, uint64(len(m.Address)))
+		i--
+		dAtA[i] = 0x12
+	}
+	{
+		size := m.OwnerID.Size()
+		i -= size
+		if _, err := m.OwnerID.MarshalTo(dAtA[i:]); err != nil {
+			return 0, err
+		}
+		i = encodeVarintTypes(dAtA, i, uint64(size))
+	}
+	i--
+	dAtA[i] = 0xa
+	return len(dAtA) - i, nil
+}
+
+func (m *LockTarget) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *LockTarget) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *LockTarget) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if m.Target != nil {
+		{
+			size := m.Target.Size()
+			i -= size
+			if _, err := m.Target.MarshalTo(dAtA[i:]); err != nil {
+				return 0, err
+			}
+		}
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *LockTarget_WithdrawTarget) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *LockTarget_WithdrawTarget) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	if m.WithdrawTarget != nil {
+		{
+			size, err := m.WithdrawTarget.MarshalToSizedBuffer(dAtA[:i])
+			if err != nil {
+				return 0, err
+			}
+			i -= size
+			i = encodeVarintTypes(dAtA, i, uint64(size))
+		}
+		i--
+		dAtA[i] = 0xa
+	}
+	return len(dAtA) - i, nil
+}
+func (m *LockTarget_ContainerCreateTarget) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *LockTarget_ContainerCreateTarget) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	if m.ContainerCreateTarget != nil {
+		{
+			size, err := m.ContainerCreateTarget.MarshalToSizedBuffer(dAtA[:i])
+			if err != nil {
+				return 0, err
+			}
+			i -= size
+			i = encodeVarintTypes(dAtA, i, uint64(size))
+		}
+		i--
+		dAtA[i] = 0x12
+	}
+	return len(dAtA) - i, nil
+}
+func (m *Balances) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *Balances) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *Balances) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if len(m.Accounts) > 0 {
+		for iNdEx := len(m.Accounts) - 1; iNdEx >= 0; iNdEx-- {
+			{
+				size, err := m.Accounts[iNdEx].MarshalToSizedBuffer(dAtA[:i])
+				if err != nil {
+					return 0, err
+				}
+				i -= size
+				i = encodeVarintTypes(dAtA, i, uint64(size))
+			}
+			i--
+			dAtA[i] = 0xa
+		}
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *PayIO) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *PayIO) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *PayIO) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if len(m.Transactions) > 0 {
+		for iNdEx := len(m.Transactions) - 1; iNdEx >= 0; iNdEx-- {
+			{
+				size, err := m.Transactions[iNdEx].MarshalToSizedBuffer(dAtA[:i])
+				if err != nil {
+					return 0, err
+				}
+				i -= size
+				i = encodeVarintTypes(dAtA, i, uint64(size))
+			}
+			i--
+			dAtA[i] = 0x12
+		}
+	}
+	if m.BlockID != 0 {
+		i = encodeVarintTypes(dAtA, i, uint64(m.BlockID))
+		i--
+		dAtA[i] = 0x8
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *Clearing) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *Clearing) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *Clearing) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if len(m.Transactions) > 0 {
+		for iNdEx := len(m.Transactions) - 1; iNdEx >= 0; iNdEx-- {
+			{
+				size, err := m.Transactions[iNdEx].MarshalToSizedBuffer(dAtA[:i])
+				if err != nil {
+					return 0, err
+				}
+				i -= size
+				i = encodeVarintTypes(dAtA, i, uint64(size))
+			}
+			i--
+			dAtA[i] = 0xa
+		}
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *Withdraw) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *Withdraw) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *Withdraw) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if m.Transaction != nil {
+		{
+			size, err := m.Transaction.MarshalToSizedBuffer(dAtA[:i])
+			if err != nil {
+				return 0, err
+			}
+			i -= size
+			i = encodeVarintTypes(dAtA, i, uint64(size))
+		}
+		i--
+		dAtA[i] = 0x1a
+	}
+	if m.Epoch != 0 {
+		i = encodeVarintTypes(dAtA, i, uint64(m.Epoch))
+		i--
+		dAtA[i] = 0x10
+	}
+	if len(m.ID) > 0 {
+		i -= len(m.ID)
+		copy(dAtA[i:], m.ID)
+		i = encodeVarintTypes(dAtA, i, uint64(len(m.ID)))
+		i--
+		dAtA[i] = 0xa
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *Lifetime) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *Lifetime) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *Lifetime) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if m.Value != 0 {
+		i = encodeVarintTypes(dAtA, i, uint64(m.Value))
+		i--
+		dAtA[i] = 0x10
+	}
+	if m.Unit != 0 {
+		i = encodeVarintTypes(dAtA, i, uint64(m.Unit))
+		i--
+		dAtA[i] = 0x8
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *Tx) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *Tx) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *Tx) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if len(m.PublicKeys) > 0 {
+		i -= len(m.PublicKeys)
+		copy(dAtA[i:], m.PublicKeys)
+		i = encodeVarintTypes(dAtA, i, uint64(len(m.PublicKeys)))
+		i--
+		dAtA[i] = 0x2a
+	}
+	if m.Amount != nil {
+		{
+			size, err := m.Amount.MarshalToSizedBuffer(dAtA[:i])
+			if err != nil {
+				return 0, err
+			}
+			i -= size
+			i = encodeVarintTypes(dAtA, i, uint64(size))
+		}
+		i--
+		dAtA[i] = 0x22
+	}
+	if len(m.To) > 0 {
+		i -= len(m.To)
+		copy(dAtA[i:], m.To)
+		i = encodeVarintTypes(dAtA, i, uint64(len(m.To)))
+		i--
+		dAtA[i] = 0x1a
+	}
+	if len(m.From) > 0 {
+		i -= len(m.From)
+		copy(dAtA[i:], m.From)
+		i = encodeVarintTypes(dAtA, i, uint64(len(m.From)))
+		i--
+		dAtA[i] = 0x12
+	}
+	if m.Type != 0 {
+		i = encodeVarintTypes(dAtA, i, uint64(m.Type))
+		i--
+		dAtA[i] = 0x8
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *Settlement) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *Settlement) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *Settlement) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if len(m.Transactions) > 0 {
+		for iNdEx := len(m.Transactions) - 1; iNdEx >= 0; iNdEx-- {
+			{
+				size, err := m.Transactions[iNdEx].MarshalToSizedBuffer(dAtA[:i])
+				if err != nil {
+					return 0, err
+				}
+				i -= size
+				i = encodeVarintTypes(dAtA, i, uint64(size))
+			}
+			i--
+			dAtA[i] = 0x12
+		}
+	}
+	if m.Epoch != 0 {
+		i = encodeVarintTypes(dAtA, i, uint64(m.Epoch))
+		i--
+		dAtA[i] = 0x8
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *Settlement_Receiver) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *Settlement_Receiver) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *Settlement_Receiver) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if m.Amount != nil {
+		{
+			size, err := m.Amount.MarshalToSizedBuffer(dAtA[:i])
+			if err != nil {
+				return 0, err
+			}
+			i -= size
+			i = encodeVarintTypes(dAtA, i, uint64(size))
+		}
+		i--
+		dAtA[i] = 0x12
+	}
+	if len(m.To) > 0 {
+		i -= len(m.To)
+		copy(dAtA[i:], m.To)
+		i = encodeVarintTypes(dAtA, i, uint64(len(m.To)))
+		i--
+		dAtA[i] = 0xa
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *Settlement_Container) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *Settlement_Container) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *Settlement_Container) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if len(m.SGIDs) > 0 {
+		for iNdEx := len(m.SGIDs) - 1; iNdEx >= 0; iNdEx-- {
+			{
+				size := m.SGIDs[iNdEx].Size()
+				i -= size
+				if _, err := m.SGIDs[iNdEx].MarshalTo(dAtA[i:]); err != nil {
+					return 0, err
+				}
+				i = encodeVarintTypes(dAtA, i, uint64(size))
+			}
+			i--
+			dAtA[i] = 0x12
+		}
+	}
+	{
+		size := m.CID.Size()
+		i -= size
+		if _, err := m.CID.MarshalTo(dAtA[i:]); err != nil {
+			return 0, err
+		}
+		i = encodeVarintTypes(dAtA, i, uint64(size))
+	}
+	i--
+	dAtA[i] = 0xa
+	return len(dAtA) - i, nil
+}
+
+func (m *Settlement_Tx) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *Settlement_Tx) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *Settlement_Tx) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if len(m.Receivers) > 0 {
+		for iNdEx := len(m.Receivers) - 1; iNdEx >= 0; iNdEx-- {
+			{
+				size, err := m.Receivers[iNdEx].MarshalToSizedBuffer(dAtA[:i])
+				if err != nil {
+					return 0, err
+				}
+				i -= size
+				i = encodeVarintTypes(dAtA, i, uint64(size))
+			}
+			i--
+			dAtA[i] = 0x1a
+		}
+	}
+	{
+		size, err := m.Container.MarshalToSizedBuffer(dAtA[:i])
+		if err != nil {
+			return 0, err
+		}
+		i -= size
+		i = encodeVarintTypes(dAtA, i, uint64(size))
+	}
+	i--
+	dAtA[i] = 0x12
+	if len(m.From) > 0 {
+		i -= len(m.From)
+		copy(dAtA[i:], m.From)
+		i = encodeVarintTypes(dAtA, i, uint64(len(m.From)))
+		i--
+		dAtA[i] = 0xa
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *ContainerCreateTarget) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *ContainerCreateTarget) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *ContainerCreateTarget) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	{
+		size := m.CID.Size()
+		i -= size
+		if _, err := m.CID.MarshalTo(dAtA[i:]); err != nil {
+			return 0, err
+		}
+		i = encodeVarintTypes(dAtA, i, uint64(size))
+	}
+	i--
+	dAtA[i] = 0xa
+	return len(dAtA) - i, nil
+}
+
+func (m *WithdrawTarget) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *WithdrawTarget) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *WithdrawTarget) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if len(m.Cheque) > 0 {
+		i -= len(m.Cheque)
+		copy(dAtA[i:], m.Cheque)
+		i = encodeVarintTypes(dAtA, i, uint64(len(m.Cheque)))
+		i--
+		dAtA[i] = 0xa
+	}
+	return len(dAtA) - i, nil
+}
+
+func encodeVarintTypes(dAtA []byte, offset int, v uint64) int {
+	offset -= sovTypes(v)
+	base := offset
+	for v >= 1<<7 {
+		dAtA[offset] = uint8(v&0x7f | 0x80)
+		v >>= 7
+		offset++
+	}
+	dAtA[offset] = uint8(v)
+	return base
+}
+func (m *Account) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = m.OwnerID.Size()
+	n += 1 + l + sovTypes(uint64(l))
+	l = len(m.Address)
+	if l > 0 {
+		n += 1 + l + sovTypes(uint64(l))
+	}
+	l = len(m.ParentAddress)
+	if l > 0 {
+		n += 1 + l + sovTypes(uint64(l))
+	}
+	if m.ActiveFunds != nil {
+		l = m.ActiveFunds.Size()
+		n += 1 + l + sovTypes(uint64(l))
+	}
+	l = m.Lifetime.Size()
+	n += 1 + l + sovTypes(uint64(l))
+	if m.LockTarget != nil {
+		l = m.LockTarget.Size()
+		n += 1 + l + sovTypes(uint64(l))
+	}
+	if len(m.LockAccounts) > 0 {
+		for _, e := range m.LockAccounts {
+			l = e.Size()
+			n += 1 + l + sovTypes(uint64(l))
+		}
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *LockTarget) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.Target != nil {
+		n += m.Target.Size()
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *LockTarget_WithdrawTarget) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.WithdrawTarget != nil {
+		l = m.WithdrawTarget.Size()
+		n += 1 + l + sovTypes(uint64(l))
+	}
+	return n
+}
+func (m *LockTarget_ContainerCreateTarget) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.ContainerCreateTarget != nil {
+		l = m.ContainerCreateTarget.Size()
+		n += 1 + l + sovTypes(uint64(l))
+	}
+	return n
+}
+func (m *Balances) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if len(m.Accounts) > 0 {
+		for _, e := range m.Accounts {
+			l = e.Size()
+			n += 1 + l + sovTypes(uint64(l))
+		}
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *PayIO) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.BlockID != 0 {
+		n += 1 + sovTypes(uint64(m.BlockID))
+	}
+	if len(m.Transactions) > 0 {
+		for _, e := range m.Transactions {
+			l = e.Size()
+			n += 1 + l + sovTypes(uint64(l))
+		}
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *Clearing) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if len(m.Transactions) > 0 {
+		for _, e := range m.Transactions {
+			l = e.Size()
+			n += 1 + l + sovTypes(uint64(l))
+		}
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *Withdraw) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = len(m.ID)
+	if l > 0 {
+		n += 1 + l + sovTypes(uint64(l))
+	}
+	if m.Epoch != 0 {
+		n += 1 + sovTypes(uint64(m.Epoch))
+	}
+	if m.Transaction != nil {
+		l = m.Transaction.Size()
+		n += 1 + l + sovTypes(uint64(l))
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *Lifetime) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.Unit != 0 {
+		n += 1 + sovTypes(uint64(m.Unit))
+	}
+	if m.Value != 0 {
+		n += 1 + sovTypes(uint64(m.Value))
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *Tx) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.Type != 0 {
+		n += 1 + sovTypes(uint64(m.Type))
+	}
+	l = len(m.From)
+	if l > 0 {
+		n += 1 + l + sovTypes(uint64(l))
+	}
+	l = len(m.To)
+	if l > 0 {
+		n += 1 + l + sovTypes(uint64(l))
+	}
+	if m.Amount != nil {
+		l = m.Amount.Size()
+		n += 1 + l + sovTypes(uint64(l))
+	}
+	l = len(m.PublicKeys)
+	if l > 0 {
+		n += 1 + l + sovTypes(uint64(l))
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *Settlement) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.Epoch != 0 {
+		n += 1 + sovTypes(uint64(m.Epoch))
+	}
+	if len(m.Transactions) > 0 {
+		for _, e := range m.Transactions {
+			l = e.Size()
+			n += 1 + l + sovTypes(uint64(l))
+		}
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *Settlement_Receiver) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = len(m.To)
+	if l > 0 {
+		n += 1 + l + sovTypes(uint64(l))
+	}
+	if m.Amount != nil {
+		l = m.Amount.Size()
+		n += 1 + l + sovTypes(uint64(l))
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *Settlement_Container) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = m.CID.Size()
+	n += 1 + l + sovTypes(uint64(l))
+	if len(m.SGIDs) > 0 {
+		for _, e := range m.SGIDs {
+			l = e.Size()
+			n += 1 + l + sovTypes(uint64(l))
+		}
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *Settlement_Tx) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = len(m.From)
+	if l > 0 {
+		n += 1 + l + sovTypes(uint64(l))
+	}
+	l = m.Container.Size()
+	n += 1 + l + sovTypes(uint64(l))
+	if len(m.Receivers) > 0 {
+		for _, e := range m.Receivers {
+			l = e.Size()
+			n += 1 + l + sovTypes(uint64(l))
+		}
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *ContainerCreateTarget) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = m.CID.Size()
+	n += 1 + l + sovTypes(uint64(l))
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *WithdrawTarget) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = len(m.Cheque)
+	if l > 0 {
+		n += 1 + l + sovTypes(uint64(l))
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func sovTypes(x uint64) (n int) {
+	return (math_bits.Len64(x|1) + 6) / 7
+}
+func sozTypes(x uint64) (n int) {
+	return sovTypes(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+func (m *Account) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowTypes
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: Account: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: Account: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field OwnerID", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.OwnerID.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Address = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 3:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field ParentAddress", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.ParentAddress = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 4:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field ActiveFunds", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if m.ActiveFunds == nil {
+				m.ActiveFunds = &decimal.Decimal{}
+			}
+			if err := m.ActiveFunds.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 5:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Lifetime", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.Lifetime.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 6:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field LockTarget", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if m.LockTarget == nil {
+				m.LockTarget = &LockTarget{}
+			}
+			if err := m.LockTarget.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 7:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field LockAccounts", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.LockAccounts = append(m.LockAccounts, &Account{})
+			if err := m.LockAccounts[len(m.LockAccounts)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipTypes(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *LockTarget) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowTypes
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: LockTarget: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: LockTarget: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field WithdrawTarget", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			v := &WithdrawTarget{}
+			if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			m.Target = &LockTarget_WithdrawTarget{v}
+			iNdEx = postIndex
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field ContainerCreateTarget", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			v := &ContainerCreateTarget{}
+			if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			m.Target = &LockTarget_ContainerCreateTarget{v}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipTypes(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *Balances) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowTypes
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: Balances: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: Balances: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Accounts", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Accounts = append(m.Accounts, Account{})
+			if err := m.Accounts[len(m.Accounts)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipTypes(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *PayIO) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowTypes
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: PayIO: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: PayIO: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field BlockID", wireType)
+			}
+			m.BlockID = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.BlockID |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Transactions", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Transactions = append(m.Transactions, Tx{})
+			if err := m.Transactions[len(m.Transactions)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipTypes(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *Clearing) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowTypes
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: Clearing: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: Clearing: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Transactions", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Transactions = append(m.Transactions, Tx{})
+			if err := m.Transactions[len(m.Transactions)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipTypes(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *Withdraw) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowTypes
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: Withdraw: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: Withdraw: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.ID = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 2:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Epoch", wireType)
+			}
+			m.Epoch = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.Epoch |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		case 3:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Transaction", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if m.Transaction == nil {
+				m.Transaction = &Tx{}
+			}
+			if err := m.Transaction.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipTypes(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *Lifetime) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowTypes
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: Lifetime: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: Lifetime: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Unit", wireType)
+			}
+			m.Unit = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.Unit |= Lifetime_Unit(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		case 2:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType)
+			}
+			m.Value = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.Value |= int64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		default:
+			iNdEx = preIndex
+			skippy, err := skipTypes(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *Tx) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowTypes
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: Tx: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: Tx: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType)
+			}
+			m.Type = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.Type |= Tx_Type(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field From", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.From = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 3:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field To", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.To = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 4:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if m.Amount == nil {
+				m.Amount = &decimal.Decimal{}
+			}
+			if err := m.Amount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 5:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field PublicKeys", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.PublicKeys = append(m.PublicKeys[:0], dAtA[iNdEx:postIndex]...)
+			if m.PublicKeys == nil {
+				m.PublicKeys = []byte{}
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipTypes(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *Settlement) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowTypes
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: Settlement: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: Settlement: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Epoch", wireType)
+			}
+			m.Epoch = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.Epoch |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Transactions", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Transactions = append(m.Transactions, &Settlement_Tx{})
+			if err := m.Transactions[len(m.Transactions)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipTypes(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *Settlement_Receiver) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowTypes
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: Receiver: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: Receiver: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field To", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.To = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if m.Amount == nil {
+				m.Amount = &decimal.Decimal{}
+			}
+			if err := m.Amount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipTypes(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *Settlement_Container) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowTypes
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: Container: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: Container: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field CID", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.CID.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field SGIDs", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			var v SGID
+			m.SGIDs = append(m.SGIDs, v)
+			if err := m.SGIDs[len(m.SGIDs)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipTypes(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *Settlement_Tx) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowTypes
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: Tx: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: Tx: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field From", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.From = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Container", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.Container.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 3:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Receivers", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Receivers = append(m.Receivers, Settlement_Receiver{})
+			if err := m.Receivers[len(m.Receivers)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipTypes(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *ContainerCreateTarget) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowTypes
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: ContainerCreateTarget: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: ContainerCreateTarget: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field CID", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.CID.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipTypes(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *WithdrawTarget) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowTypes
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: WithdrawTarget: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: WithdrawTarget: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Cheque", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Cheque = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipTypes(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func skipTypes(dAtA []byte) (n int, err error) {
+	l := len(dAtA)
+	iNdEx := 0
+	depth := 0
+	for iNdEx < l {
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return 0, ErrIntOverflowTypes
+			}
+			if iNdEx >= l {
+				return 0, io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= (uint64(b) & 0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		wireType := int(wire & 0x7)
+		switch wireType {
+		case 0:
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return 0, ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return 0, io.ErrUnexpectedEOF
+				}
+				iNdEx++
+				if dAtA[iNdEx-1] < 0x80 {
+					break
+				}
+			}
+		case 1:
+			iNdEx += 8
+		case 2:
+			var length int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return 0, ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return 0, io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				length |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if length < 0 {
+				return 0, ErrInvalidLengthTypes
+			}
+			iNdEx += length
+		case 3:
+			depth++
+		case 4:
+			if depth == 0 {
+				return 0, ErrUnexpectedEndOfGroupTypes
+			}
+			depth--
+		case 5:
+			iNdEx += 4
+		default:
+			return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+		}
+		if iNdEx < 0 {
+			return 0, ErrInvalidLengthTypes
+		}
+		if depth == 0 {
+			return iNdEx, nil
+		}
+	}
+	return 0, io.ErrUnexpectedEOF
+}
+
+var (
+	ErrInvalidLengthTypes        = fmt.Errorf("proto: negative length found during unmarshaling")
+	ErrIntOverflowTypes          = fmt.Errorf("proto: integer overflow")
+	ErrUnexpectedEndOfGroupTypes = fmt.Errorf("proto: unexpected end of group")
+)
diff --git a/accounting/types.proto b/accounting/types.proto
new file mode 100644
index 00000000..1b4e7838
--- /dev/null
+++ b/accounting/types.proto
@@ -0,0 +1,106 @@
+syntax = "proto3";
+package accounting;
+option go_package = "github.com/nspcc-dev/neofs-proto/accounting";
+
+import "decimal/decimal.proto";
+import "github.com/gogo/protobuf/gogoproto/gogo.proto";
+
+option (gogoproto.stable_marshaler_all) = true;
+
+// Snapshot accounting messages
+message Account {
+    bytes OwnerID                 = 1 [(gogoproto.customtype) = "OwnerID",  (gogoproto.nullable) = false];
+    string Address                = 2;
+    string ParentAddress          = 3;
+    decimal.Decimal ActiveFunds   = 4;
+    Lifetime Lifetime             = 5 [(gogoproto.nullable) = false];
+    LockTarget LockTarget         = 6;
+    repeated Account LockAccounts = 7;
+}
+
+message LockTarget {
+    oneof Target {
+        WithdrawTarget WithdrawTarget = 1;
+        ContainerCreateTarget ContainerCreateTarget = 2;
+    }
+}
+
+// Snapshot balance messages
+message Balances {
+    repeated Account Accounts = 1 [(gogoproto.nullable) = false];
+}
+
+// PayIn / PayOut messages
+message PayIO {
+    uint64 BlockID = 1;
+    repeated Tx Transactions = 2 [(gogoproto.nullable) = false];
+}
+
+// Clearing messages
+message Clearing {
+    repeated Tx Transactions = 1 [(gogoproto.nullable) = false];
+}
+
+// Clearing messages
+message Withdraw {
+    string ID = 1;
+    uint64 Epoch = 2;
+    Tx Transaction = 3;
+}
+
+// Lifetime of locks
+message Lifetime {
+    enum Unit {
+        Unlimited = 0;
+        NeoFSEpoch = 1;
+        NeoBlock = 2;
+    }
+
+    Unit unit = 1 [(gogoproto.customname) = "Unit"];
+    int64 Value = 2;
+}
+
+// Transaction messages
+message Tx {
+    enum Type {
+        Unknown  = 0;
+        Withdraw = 1;
+        PayIO    = 2;
+        Inner    = 3;
+    }
+
+    Type type              = 1 [(gogoproto.customname) = "Type"];
+    string From            = 2;
+    string To              = 3;
+    decimal.Decimal Amount = 4;
+    bytes PublicKeys       = 5; // of sender
+}
+
+message Settlement {
+    message Receiver {
+        string To              = 1;
+        decimal.Decimal Amount = 2;
+    }
+
+    message Container {
+        bytes CID            = 1 [(gogoproto.customtype) = "CID", (gogoproto.nullable) = false];
+        repeated bytes SGIDs = 2 [(gogoproto.customtype) = "SGID", (gogoproto.nullable) = false];
+    }
+
+    message Tx {
+        string From                 = 1;
+        Container Container         = 2 [(gogoproto.nullable) = false];
+        repeated Receiver Receivers = 3 [(gogoproto.nullable) = false];
+    }
+
+    uint64 Epoch             = 1;
+    repeated Tx Transactions = 2;
+}
+
+message ContainerCreateTarget {
+    bytes CID = 1 [(gogoproto.customtype) = "CID", (gogoproto.nullable) = false];
+}
+
+message WithdrawTarget {
+    string Cheque = 1;
+}
diff --git a/accounting/types_test.go b/accounting/types_test.go
new file mode 100644
index 00000000..c78e5b40
--- /dev/null
+++ b/accounting/types_test.go
@@ -0,0 +1,84 @@
+package accounting
+
+import (
+	"io/ioutil"
+	"testing"
+
+	"github.com/mr-tron/base58"
+	"github.com/nspcc-dev/neofs-crypto/test"
+	"github.com/nspcc-dev/neofs-proto/chain"
+	"github.com/nspcc-dev/neofs-proto/decimal"
+	"github.com/nspcc-dev/neofs-proto/refs"
+	"github.com/stretchr/testify/require"
+)
+
+func TestCheque(t *testing.T) {
+	t.Run("new/valid", func(t *testing.T) {
+		id, err := NewChequeID()
+		require.NoError(t, err)
+		require.True(t, id.Valid())
+
+		d := make([]byte, chain.AddressLength+1)
+
+		// expected size + 1 byte
+		str := base58.Encode(d)
+		require.False(t, ChequeID(str).Valid())
+
+		// expected size - 1 byte
+		str = base58.Encode(d[:len(d)-2])
+		require.False(t, ChequeID(str).Valid())
+
+		// wrong encoding
+		d = d[:len(d)-1] // normal size
+		require.False(t, ChequeID(string(d)).Valid())
+	})
+
+	t.Run("marshal/unmarshal", func(t *testing.T) {
+		var b2 = new(Cheque)
+
+		key1 := test.DecodeKey(0)
+		key2 := test.DecodeKey(1)
+
+		id, err := NewChequeID()
+		require.NoError(t, err)
+
+		owner, err := refs.NewOwnerID(&key1.PublicKey)
+		require.NoError(t, err)
+
+		b1 := &Cheque{
+			ID:     id,
+			Owner:  owner,
+			Height: 100,
+			Amount: decimal.NewGAS(100),
+		}
+
+		require.NoError(t, b1.Sign(key1))
+		require.NoError(t, b1.Sign(key2))
+
+		data, err := b1.MarshalBinary()
+		require.NoError(t, err)
+
+		require.Len(t, data, b1.Size())
+		require.NoError(t, b2.UnmarshalBinary(data))
+		require.Equal(t, b1, b2)
+
+		require.NoError(t, b1.Verify())
+		require.NoError(t, b2.Verify())
+	})
+
+	t.Run("example from SC", func(t *testing.T) {
+		var pathToCheque = "fixtures/cheque_data"
+		expect, err := ioutil.ReadFile(pathToCheque)
+		require.NoError(t, err)
+
+		var cheque Cheque
+		require.NoError(t, cheque.UnmarshalBinary(expect))
+
+		actual, err := cheque.MarshalBinary()
+		require.NoError(t, err)
+
+		require.Equal(t, expect, actual)
+
+		require.NoError(t, cheque.Verify())
+	})
+}
diff --git a/accounting/withdraw.go b/accounting/withdraw.go
new file mode 100644
index 00000000..3cd27666
--- /dev/null
+++ b/accounting/withdraw.go
@@ -0,0 +1,53 @@
+package accounting
+
+import (
+	"encoding/binary"
+
+	"github.com/nspcc-dev/neofs-proto/refs"
+)
+
+type (
+	// MessageID type alias.
+	MessageID = refs.MessageID
+)
+
+// SetTTL sets ttl to GetRequest to satisfy TTLRequest interface.
+func (m *GetRequest) SetTTL(v uint32) { m.TTL = v }
+
+// SetTTL sets ttl to PutRequest to satisfy TTLRequest interface.
+func (m *PutRequest) SetTTL(v uint32) { m.TTL = v }
+
+// SetTTL sets ttl to ListRequest to satisfy TTLRequest interface.
+func (m *ListRequest) SetTTL(v uint32) { m.TTL = v }
+
+// SetTTL sets ttl to DeleteRequest to satisfy TTLRequest interface.
+func (m *DeleteRequest) SetTTL(v uint32) { m.TTL = v }
+
+// SetSignature sets signature to PutRequest to satisfy SignedRequest interface.
+func (m *PutRequest) SetSignature(v []byte) { m.Signature = v }
+
+// SetSignature sets signature to DeleteRequest to satisfy SignedRequest interface.
+func (m *DeleteRequest) SetSignature(v []byte) { m.Signature = v }
+
+// PrepareData prepares bytes representation of PutRequest to satisfy SignedRequest interface.
+func (m *PutRequest) PrepareData() ([]byte, error) {
+	var offset int
+	// MessageID-len + OwnerID-len + Amount + Height
+	buf := make([]byte, refs.UUIDSize+refs.OwnerIDSize+binary.MaxVarintLen64+binary.MaxVarintLen64)
+	offset += copy(buf[offset:], m.MessageID.Bytes())
+	offset += copy(buf[offset:], m.OwnerID.Bytes())
+	offset += binary.PutVarint(buf[offset:], m.Amount.Value)
+	binary.PutUvarint(buf[offset:], m.Height)
+	return buf, nil
+}
+
+// PrepareData prepares bytes representation of DeleteRequest to satisfy SignedRequest interface.
+func (m *DeleteRequest) PrepareData() ([]byte, error) {
+	var offset int
+	// ID-len + OwnerID-len + MessageID-len
+	buf := make([]byte, refs.UUIDSize+refs.OwnerIDSize+refs.UUIDSize)
+	offset += copy(buf[offset:], m.ID.Bytes())
+	offset += copy(buf[offset:], m.OwnerID.Bytes())
+	copy(buf[offset:], m.MessageID.Bytes())
+	return buf, nil
+}
diff --git a/accounting/withdraw.pb.go b/accounting/withdraw.pb.go
new file mode 100644
index 00000000..967a2ce0
--- /dev/null
+++ b/accounting/withdraw.pb.go
@@ -0,0 +1,2641 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: accounting/withdraw.proto
+
+package accounting
+
+import (
+	context "context"
+	fmt "fmt"
+	_ "github.com/gogo/protobuf/gogoproto"
+	proto "github.com/golang/protobuf/proto"
+	decimal "github.com/nspcc-dev/neofs-proto/decimal"
+	grpc "google.golang.org/grpc"
+	codes "google.golang.org/grpc/codes"
+	status "google.golang.org/grpc/status"
+	io "io"
+	math "math"
+	math_bits "math/bits"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
+
+type Item struct {
+	ID                   ChequeID         `protobuf:"bytes,1,opt,name=ID,proto3,customtype=ChequeID" json:"ID"`
+	OwnerID              OwnerID          `protobuf:"bytes,2,opt,name=OwnerID,proto3,customtype=OwnerID" json:"OwnerID"`
+	Amount               *decimal.Decimal `protobuf:"bytes,3,opt,name=Amount,proto3" json:"Amount,omitempty"`
+	Height               uint64           `protobuf:"varint,4,opt,name=Height,proto3" json:"Height,omitempty"`
+	Payload              []byte           `protobuf:"bytes,5,opt,name=Payload,proto3" json:"Payload,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}         `json:"-"`
+	XXX_unrecognized     []byte           `json:"-"`
+	XXX_sizecache        int32            `json:"-"`
+}
+
+func (m *Item) Reset()         { *m = Item{} }
+func (m *Item) String() string { return proto.CompactTextString(m) }
+func (*Item) ProtoMessage()    {}
+func (*Item) Descriptor() ([]byte, []int) {
+	return fileDescriptor_b3a38a4dc2575267, []int{0}
+}
+func (m *Item) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *Item) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *Item) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Item.Merge(m, src)
+}
+func (m *Item) XXX_Size() int {
+	return m.Size()
+}
+func (m *Item) XXX_DiscardUnknown() {
+	xxx_messageInfo_Item.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Item proto.InternalMessageInfo
+
+func (m *Item) GetAmount() *decimal.Decimal {
+	if m != nil {
+		return m.Amount
+	}
+	return nil
+}
+
+func (m *Item) GetHeight() uint64 {
+	if m != nil {
+		return m.Height
+	}
+	return 0
+}
+
+func (m *Item) GetPayload() []byte {
+	if m != nil {
+		return m.Payload
+	}
+	return nil
+}
+
+type GetRequest struct {
+	ID                   ChequeID `protobuf:"bytes,1,opt,name=ID,proto3,customtype=ChequeID" json:"ID"`
+	OwnerID              OwnerID  `protobuf:"bytes,2,opt,name=OwnerID,proto3,customtype=OwnerID" json:"OwnerID"`
+	TTL                  uint32   `protobuf:"varint,3,opt,name=TTL,proto3" json:"TTL,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *GetRequest) Reset()         { *m = GetRequest{} }
+func (m *GetRequest) String() string { return proto.CompactTextString(m) }
+func (*GetRequest) ProtoMessage()    {}
+func (*GetRequest) Descriptor() ([]byte, []int) {
+	return fileDescriptor_b3a38a4dc2575267, []int{1}
+}
+func (m *GetRequest) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *GetRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *GetRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_GetRequest.Merge(m, src)
+}
+func (m *GetRequest) XXX_Size() int {
+	return m.Size()
+}
+func (m *GetRequest) XXX_DiscardUnknown() {
+	xxx_messageInfo_GetRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetRequest proto.InternalMessageInfo
+
+func (m *GetRequest) GetTTL() uint32 {
+	if m != nil {
+		return m.TTL
+	}
+	return 0
+}
+
+type GetResponse struct {
+	Withdraw             *Item    `protobuf:"bytes,1,opt,name=Withdraw,proto3" json:"Withdraw,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *GetResponse) Reset()         { *m = GetResponse{} }
+func (m *GetResponse) String() string { return proto.CompactTextString(m) }
+func (*GetResponse) ProtoMessage()    {}
+func (*GetResponse) Descriptor() ([]byte, []int) {
+	return fileDescriptor_b3a38a4dc2575267, []int{2}
+}
+func (m *GetResponse) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *GetResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *GetResponse) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_GetResponse.Merge(m, src)
+}
+func (m *GetResponse) XXX_Size() int {
+	return m.Size()
+}
+func (m *GetResponse) XXX_DiscardUnknown() {
+	xxx_messageInfo_GetResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetResponse proto.InternalMessageInfo
+
+func (m *GetResponse) GetWithdraw() *Item {
+	if m != nil {
+		return m.Withdraw
+	}
+	return nil
+}
+
+type PutRequest struct {
+	OwnerID              OwnerID          `protobuf:"bytes,1,opt,name=OwnerID,proto3,customtype=OwnerID" json:"OwnerID"`
+	Amount               *decimal.Decimal `protobuf:"bytes,2,opt,name=Amount,proto3" json:"Amount,omitempty"`
+	Height               uint64           `protobuf:"varint,3,opt,name=Height,proto3" json:"Height,omitempty"`
+	MessageID            MessageID        `protobuf:"bytes,4,opt,name=MessageID,proto3,customtype=MessageID" json:"MessageID"`
+	Signature            []byte           `protobuf:"bytes,5,opt,name=Signature,proto3" json:"Signature,omitempty"`
+	TTL                  uint32           `protobuf:"varint,6,opt,name=TTL,proto3" json:"TTL,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}         `json:"-"`
+	XXX_unrecognized     []byte           `json:"-"`
+	XXX_sizecache        int32            `json:"-"`
+}
+
+func (m *PutRequest) Reset()         { *m = PutRequest{} }
+func (m *PutRequest) String() string { return proto.CompactTextString(m) }
+func (*PutRequest) ProtoMessage()    {}
+func (*PutRequest) Descriptor() ([]byte, []int) {
+	return fileDescriptor_b3a38a4dc2575267, []int{3}
+}
+func (m *PutRequest) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *PutRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *PutRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_PutRequest.Merge(m, src)
+}
+func (m *PutRequest) XXX_Size() int {
+	return m.Size()
+}
+func (m *PutRequest) XXX_DiscardUnknown() {
+	xxx_messageInfo_PutRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_PutRequest proto.InternalMessageInfo
+
+func (m *PutRequest) GetAmount() *decimal.Decimal {
+	if m != nil {
+		return m.Amount
+	}
+	return nil
+}
+
+func (m *PutRequest) GetHeight() uint64 {
+	if m != nil {
+		return m.Height
+	}
+	return 0
+}
+
+func (m *PutRequest) GetSignature() []byte {
+	if m != nil {
+		return m.Signature
+	}
+	return nil
+}
+
+func (m *PutRequest) GetTTL() uint32 {
+	if m != nil {
+		return m.TTL
+	}
+	return 0
+}
+
+type PutResponse struct {
+	ID                   ChequeID `protobuf:"bytes,1,opt,name=ID,proto3,customtype=ChequeID" json:"ID"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *PutResponse) Reset()         { *m = PutResponse{} }
+func (m *PutResponse) String() string { return proto.CompactTextString(m) }
+func (*PutResponse) ProtoMessage()    {}
+func (*PutResponse) Descriptor() ([]byte, []int) {
+	return fileDescriptor_b3a38a4dc2575267, []int{4}
+}
+func (m *PutResponse) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *PutResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *PutResponse) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_PutResponse.Merge(m, src)
+}
+func (m *PutResponse) XXX_Size() int {
+	return m.Size()
+}
+func (m *PutResponse) XXX_DiscardUnknown() {
+	xxx_messageInfo_PutResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_PutResponse proto.InternalMessageInfo
+
+type ListRequest struct {
+	OwnerID              OwnerID  `protobuf:"bytes,1,opt,name=OwnerID,proto3,customtype=OwnerID" json:"OwnerID"`
+	TTL                  uint32   `protobuf:"varint,2,opt,name=TTL,proto3" json:"TTL,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *ListRequest) Reset()         { *m = ListRequest{} }
+func (m *ListRequest) String() string { return proto.CompactTextString(m) }
+func (*ListRequest) ProtoMessage()    {}
+func (*ListRequest) Descriptor() ([]byte, []int) {
+	return fileDescriptor_b3a38a4dc2575267, []int{5}
+}
+func (m *ListRequest) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *ListRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *ListRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_ListRequest.Merge(m, src)
+}
+func (m *ListRequest) XXX_Size() int {
+	return m.Size()
+}
+func (m *ListRequest) XXX_DiscardUnknown() {
+	xxx_messageInfo_ListRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ListRequest proto.InternalMessageInfo
+
+func (m *ListRequest) GetTTL() uint32 {
+	if m != nil {
+		return m.TTL
+	}
+	return 0
+}
+
+type ListResponse struct {
+	Items                []*Item  `protobuf:"bytes,1,rep,name=Items,proto3" json:"Items,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *ListResponse) Reset()         { *m = ListResponse{} }
+func (m *ListResponse) String() string { return proto.CompactTextString(m) }
+func (*ListResponse) ProtoMessage()    {}
+func (*ListResponse) Descriptor() ([]byte, []int) {
+	return fileDescriptor_b3a38a4dc2575267, []int{6}
+}
+func (m *ListResponse) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *ListResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *ListResponse) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_ListResponse.Merge(m, src)
+}
+func (m *ListResponse) XXX_Size() int {
+	return m.Size()
+}
+func (m *ListResponse) XXX_DiscardUnknown() {
+	xxx_messageInfo_ListResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ListResponse proto.InternalMessageInfo
+
+func (m *ListResponse) GetItems() []*Item {
+	if m != nil {
+		return m.Items
+	}
+	return nil
+}
+
+type DeleteRequest struct {
+	ID                   ChequeID  `protobuf:"bytes,1,opt,name=ID,proto3,customtype=ChequeID" json:"ID"`
+	OwnerID              OwnerID   `protobuf:"bytes,2,opt,name=OwnerID,proto3,customtype=OwnerID" json:"OwnerID"`
+	MessageID            MessageID `protobuf:"bytes,3,opt,name=MessageID,proto3,customtype=MessageID" json:"MessageID"`
+	Signature            []byte    `protobuf:"bytes,4,opt,name=Signature,proto3" json:"Signature,omitempty"`
+	TTL                  uint32    `protobuf:"varint,5,opt,name=TTL,proto3" json:"TTL,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}  `json:"-"`
+	XXX_unrecognized     []byte    `json:"-"`
+	XXX_sizecache        int32     `json:"-"`
+}
+
+func (m *DeleteRequest) Reset()         { *m = DeleteRequest{} }
+func (m *DeleteRequest) String() string { return proto.CompactTextString(m) }
+func (*DeleteRequest) ProtoMessage()    {}
+func (*DeleteRequest) Descriptor() ([]byte, []int) {
+	return fileDescriptor_b3a38a4dc2575267, []int{7}
+}
+func (m *DeleteRequest) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *DeleteRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *DeleteRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_DeleteRequest.Merge(m, src)
+}
+func (m *DeleteRequest) XXX_Size() int {
+	return m.Size()
+}
+func (m *DeleteRequest) XXX_DiscardUnknown() {
+	xxx_messageInfo_DeleteRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_DeleteRequest proto.InternalMessageInfo
+
+func (m *DeleteRequest) GetSignature() []byte {
+	if m != nil {
+		return m.Signature
+	}
+	return nil
+}
+
+func (m *DeleteRequest) GetTTL() uint32 {
+	if m != nil {
+		return m.TTL
+	}
+	return 0
+}
+
+type DeleteResponse struct {
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *DeleteResponse) Reset()         { *m = DeleteResponse{} }
+func (m *DeleteResponse) String() string { return proto.CompactTextString(m) }
+func (*DeleteResponse) ProtoMessage()    {}
+func (*DeleteResponse) Descriptor() ([]byte, []int) {
+	return fileDescriptor_b3a38a4dc2575267, []int{8}
+}
+func (m *DeleteResponse) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *DeleteResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *DeleteResponse) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_DeleteResponse.Merge(m, src)
+}
+func (m *DeleteResponse) XXX_Size() int {
+	return m.Size()
+}
+func (m *DeleteResponse) XXX_DiscardUnknown() {
+	xxx_messageInfo_DeleteResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_DeleteResponse proto.InternalMessageInfo
+
+func init() {
+	proto.RegisterType((*Item)(nil), "accounting.Item")
+	proto.RegisterType((*GetRequest)(nil), "accounting.GetRequest")
+	proto.RegisterType((*GetResponse)(nil), "accounting.GetResponse")
+	proto.RegisterType((*PutRequest)(nil), "accounting.PutRequest")
+	proto.RegisterType((*PutResponse)(nil), "accounting.PutResponse")
+	proto.RegisterType((*ListRequest)(nil), "accounting.ListRequest")
+	proto.RegisterType((*ListResponse)(nil), "accounting.ListResponse")
+	proto.RegisterType((*DeleteRequest)(nil), "accounting.DeleteRequest")
+	proto.RegisterType((*DeleteResponse)(nil), "accounting.DeleteResponse")
+}
+
+func init() { proto.RegisterFile("accounting/withdraw.proto", fileDescriptor_b3a38a4dc2575267) }
+
+var fileDescriptor_b3a38a4dc2575267 = []byte{
+	// 550 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x94, 0xcd, 0x6e, 0xd3, 0x40,
+	0x10, 0xc7, 0xbb, 0xb6, 0xe3, 0xb6, 0x93, 0x14, 0xc2, 0x4a, 0x14, 0xd7, 0x42, 0xae, 0xe5, 0x03,
+	0x0a, 0x82, 0xc4, 0x52, 0x91, 0x22, 0x21, 0x0e, 0xa8, 0xc1, 0x52, 0x31, 0x2a, 0x22, 0x32, 0x95,
+	0x90, 0xb8, 0x39, 0xce, 0xd6, 0xb1, 0x48, 0xec, 0x10, 0xaf, 0x89, 0x78, 0x13, 0xde, 0x82, 0x27,
+	0xe0, 0xde, 0x23, 0x47, 0xd4, 0x43, 0x85, 0xc2, 0x3b, 0x70, 0x46, 0x5e, 0xaf, 0xbb, 0x36, 0x2d,
+	0xa2, 0x20, 0x38, 0x79, 0xe7, 0x63, 0x77, 0x66, 0x7e, 0xff, 0xf5, 0xc2, 0x8e, 0x1f, 0x04, 0x49,
+	0x16, 0xd3, 0x28, 0x0e, 0xed, 0x65, 0x44, 0x27, 0xe3, 0x85, 0xbf, 0xec, 0xcd, 0x17, 0x09, 0x4d,
+	0x30, 0x88, 0x90, 0x7e, 0x73, 0x4c, 0x82, 0x68, 0xe6, 0x4f, 0x6d, 0xfe, 0x2d, 0x52, 0xf4, 0x6e,
+	0x18, 0xd1, 0x49, 0x36, 0xea, 0x05, 0xc9, 0xcc, 0x0e, 0x93, 0x30, 0xb1, 0x99, 0x7b, 0x94, 0x1d,
+	0x33, 0x8b, 0x19, 0x6c, 0x55, 0xa4, 0x5b, 0x1f, 0x11, 0x28, 0x2e, 0x25, 0x33, 0x6c, 0x82, 0xe4,
+	0x3a, 0x1a, 0x32, 0x51, 0xa7, 0x35, 0x68, 0x9f, 0x9c, 0xed, 0xae, 0x9d, 0x9e, 0xed, 0x6e, 0x3c,
+	0x99, 0x90, 0xb7, 0x19, 0x71, 0x1d, 0x4f, 0x72, 0x1d, 0x7c, 0x17, 0xd6, 0x5f, 0x2c, 0x63, 0xb2,
+	0x70, 0x1d, 0x4d, 0x62, 0x69, 0xd7, 0x79, 0x5a, 0xe9, 0xf6, 0xca, 0x05, 0xee, 0x80, 0xba, 0x3f,
+	0xcb, 0x1b, 0xd5, 0x64, 0x13, 0x75, 0x9a, 0x7b, 0xed, 0x5e, 0xd9, 0xa4, 0x53, 0x7c, 0x3d, 0x1e,
+	0xc7, 0xdb, 0xa0, 0x3e, 0x25, 0x51, 0x38, 0xa1, 0x9a, 0x62, 0xa2, 0x8e, 0xe2, 0x71, 0x0b, 0x6b,
+	0xb0, 0x3e, 0xf4, 0xdf, 0x4f, 0x13, 0x7f, 0xac, 0x35, 0xf2, 0x62, 0x5e, 0x69, 0x5a, 0x6f, 0x00,
+	0x0e, 0x08, 0xf5, 0xf2, 0xc6, 0x52, 0xfa, 0x6f, 0xdb, 0x6e, 0x83, 0x7c, 0x74, 0x74, 0xc8, 0x7a,
+	0xde, 0xf2, 0xf2, 0xa5, 0xf5, 0x08, 0x9a, 0xac, 0x58, 0x3a, 0x4f, 0xe2, 0x94, 0xe0, 0xfb, 0xb0,
+	0xf1, 0x8a, 0x2b, 0xc2, 0x6a, 0xe6, 0x93, 0x09, 0x49, 0x7a, 0x39, 0x48, 0xef, 0x3c, 0xc3, 0x3a,
+	0x45, 0x00, 0xc3, 0xec, 0xbc, 0xd5, 0x4a, 0x23, 0xe8, 0xca, 0xfc, 0xa4, 0x2b, 0xf3, 0x93, 0x6b,
+	0xfc, 0x6c, 0xd8, 0x7c, 0x4e, 0xd2, 0xd4, 0x0f, 0x89, 0xeb, 0x30, 0xb4, 0xad, 0xc1, 0x0d, 0x5e,
+	0x4e, 0x04, 0x3c, 0xb1, 0xc4, 0xb7, 0x61, 0xf3, 0x65, 0x14, 0xc6, 0x3e, 0xcd, 0x16, 0x84, 0x23,
+	0x17, 0x8e, 0x92, 0x8c, 0x2a, 0xc8, 0xd8, 0xd0, 0x64, 0xb3, 0x71, 0x32, 0xbf, 0xd5, 0xc1, 0x7a,
+	0x06, 0xcd, 0xc3, 0x28, 0xfd, 0x1b, 0x1a, 0xbc, 0xb8, 0x24, 0x8a, 0xf7, 0xa1, 0x55, 0x9c, 0xc5,
+	0xab, 0xdf, 0x81, 0x46, 0xce, 0x3e, 0xd5, 0x90, 0x29, 0x5f, 0x2a, 0x4a, 0x11, 0xb6, 0x3e, 0x21,
+	0xd8, 0x72, 0xc8, 0x94, 0x50, 0xf2, 0x5f, 0xee, 0x4f, 0x0d, 0xba, 0xfc, 0xa7, 0xd0, 0x95, 0x5f,
+	0x40, 0x6f, 0x88, 0xb9, 0xdb, 0x70, 0xad, 0x6c, 0xbf, 0x98, 0x7c, 0xef, 0x3b, 0x12, 0x57, 0x12,
+	0xf7, 0x41, 0x3e, 0x20, 0x14, 0x6f, 0x57, 0xc7, 0x17, 0xff, 0x8a, 0x7e, 0xeb, 0x82, 0x9f, 0xe3,
+	0xeb, 0x83, 0x3c, 0xcc, 0x7e, 0xda, 0x27, 0x2e, 0x6e, 0x7d, 0x5f, 0x55, 0xf4, 0x87, 0xa0, 0xe4,
+	0x32, 0xe0, 0x5a, 0x42, 0x45, 0x64, 0x5d, 0xbb, 0x18, 0xe0, 0x5b, 0x1f, 0x83, 0x5a, 0x4c, 0x82,
+	0x77, 0xaa, 0x39, 0x35, 0x71, 0x74, 0xfd, 0xb2, 0x50, 0x71, 0xc0, 0x60, 0xff, 0x64, 0x65, 0xa0,
+	0xcf, 0x2b, 0x03, 0x7d, 0x59, 0x19, 0xe8, 0xeb, 0xca, 0x40, 0x1f, 0xbe, 0x19, 0x6b, 0xaf, 0xef,
+	0x55, 0x5e, 0xbf, 0x38, 0x9d, 0x07, 0x41, 0x77, 0x4c, 0xde, 0xd9, 0x31, 0x49, 0x8e, 0xd3, 0x6e,
+	0xf1, 0xf6, 0x89, 0x13, 0x47, 0x2a, 0xf3, 0x3c, 0xf8, 0x11, 0x00, 0x00, 0xff, 0xff, 0xd9, 0xcf,
+	0xde, 0x66, 0x71, 0x05, 0x00, 0x00,
+}
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ context.Context
+var _ grpc.ClientConn
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the grpc package it is being compiled against.
+const _ = grpc.SupportPackageIsVersion4
+
+// WithdrawClient is the client API for Withdraw service.
+//
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
+type WithdrawClient interface {
+	Get(ctx context.Context, in *GetRequest, opts ...grpc.CallOption) (*GetResponse, error)
+	Put(ctx context.Context, in *PutRequest, opts ...grpc.CallOption) (*PutResponse, error)
+	List(ctx context.Context, in *ListRequest, opts ...grpc.CallOption) (*ListResponse, error)
+	Delete(ctx context.Context, in *DeleteRequest, opts ...grpc.CallOption) (*DeleteResponse, error)
+}
+
+type withdrawClient struct {
+	cc *grpc.ClientConn
+}
+
+func NewWithdrawClient(cc *grpc.ClientConn) WithdrawClient {
+	return &withdrawClient{cc}
+}
+
+func (c *withdrawClient) Get(ctx context.Context, in *GetRequest, opts ...grpc.CallOption) (*GetResponse, error) {
+	out := new(GetResponse)
+	err := c.cc.Invoke(ctx, "/accounting.Withdraw/Get", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *withdrawClient) Put(ctx context.Context, in *PutRequest, opts ...grpc.CallOption) (*PutResponse, error) {
+	out := new(PutResponse)
+	err := c.cc.Invoke(ctx, "/accounting.Withdraw/Put", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *withdrawClient) List(ctx context.Context, in *ListRequest, opts ...grpc.CallOption) (*ListResponse, error) {
+	out := new(ListResponse)
+	err := c.cc.Invoke(ctx, "/accounting.Withdraw/List", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *withdrawClient) Delete(ctx context.Context, in *DeleteRequest, opts ...grpc.CallOption) (*DeleteResponse, error) {
+	out := new(DeleteResponse)
+	err := c.cc.Invoke(ctx, "/accounting.Withdraw/Delete", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+// WithdrawServer is the server API for Withdraw service.
+type WithdrawServer interface {
+	Get(context.Context, *GetRequest) (*GetResponse, error)
+	Put(context.Context, *PutRequest) (*PutResponse, error)
+	List(context.Context, *ListRequest) (*ListResponse, error)
+	Delete(context.Context, *DeleteRequest) (*DeleteResponse, error)
+}
+
+// UnimplementedWithdrawServer can be embedded to have forward compatible implementations.
+type UnimplementedWithdrawServer struct {
+}
+
+func (*UnimplementedWithdrawServer) Get(ctx context.Context, req *GetRequest) (*GetResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method Get not implemented")
+}
+func (*UnimplementedWithdrawServer) Put(ctx context.Context, req *PutRequest) (*PutResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method Put not implemented")
+}
+func (*UnimplementedWithdrawServer) List(ctx context.Context, req *ListRequest) (*ListResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method List not implemented")
+}
+func (*UnimplementedWithdrawServer) Delete(ctx context.Context, req *DeleteRequest) (*DeleteResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method Delete not implemented")
+}
+
+func RegisterWithdrawServer(s *grpc.Server, srv WithdrawServer) {
+	s.RegisterService(&_Withdraw_serviceDesc, srv)
+}
+
+func _Withdraw_Get_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(GetRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(WithdrawServer).Get(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/accounting.Withdraw/Get",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(WithdrawServer).Get(ctx, req.(*GetRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _Withdraw_Put_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(PutRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(WithdrawServer).Put(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/accounting.Withdraw/Put",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(WithdrawServer).Put(ctx, req.(*PutRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _Withdraw_List_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(ListRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(WithdrawServer).List(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/accounting.Withdraw/List",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(WithdrawServer).List(ctx, req.(*ListRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _Withdraw_Delete_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(DeleteRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(WithdrawServer).Delete(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/accounting.Withdraw/Delete",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(WithdrawServer).Delete(ctx, req.(*DeleteRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+var _Withdraw_serviceDesc = grpc.ServiceDesc{
+	ServiceName: "accounting.Withdraw",
+	HandlerType: (*WithdrawServer)(nil),
+	Methods: []grpc.MethodDesc{
+		{
+			MethodName: "Get",
+			Handler:    _Withdraw_Get_Handler,
+		},
+		{
+			MethodName: "Put",
+			Handler:    _Withdraw_Put_Handler,
+		},
+		{
+			MethodName: "List",
+			Handler:    _Withdraw_List_Handler,
+		},
+		{
+			MethodName: "Delete",
+			Handler:    _Withdraw_Delete_Handler,
+		},
+	},
+	Streams:  []grpc.StreamDesc{},
+	Metadata: "accounting/withdraw.proto",
+}
+
+func (m *Item) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *Item) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *Item) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if len(m.Payload) > 0 {
+		i -= len(m.Payload)
+		copy(dAtA[i:], m.Payload)
+		i = encodeVarintWithdraw(dAtA, i, uint64(len(m.Payload)))
+		i--
+		dAtA[i] = 0x2a
+	}
+	if m.Height != 0 {
+		i = encodeVarintWithdraw(dAtA, i, uint64(m.Height))
+		i--
+		dAtA[i] = 0x20
+	}
+	if m.Amount != nil {
+		{
+			size, err := m.Amount.MarshalToSizedBuffer(dAtA[:i])
+			if err != nil {
+				return 0, err
+			}
+			i -= size
+			i = encodeVarintWithdraw(dAtA, i, uint64(size))
+		}
+		i--
+		dAtA[i] = 0x1a
+	}
+	{
+		size := m.OwnerID.Size()
+		i -= size
+		if _, err := m.OwnerID.MarshalTo(dAtA[i:]); err != nil {
+			return 0, err
+		}
+		i = encodeVarintWithdraw(dAtA, i, uint64(size))
+	}
+	i--
+	dAtA[i] = 0x12
+	{
+		size := m.ID.Size()
+		i -= size
+		if _, err := m.ID.MarshalTo(dAtA[i:]); err != nil {
+			return 0, err
+		}
+		i = encodeVarintWithdraw(dAtA, i, uint64(size))
+	}
+	i--
+	dAtA[i] = 0xa
+	return len(dAtA) - i, nil
+}
+
+func (m *GetRequest) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *GetRequest) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *GetRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if m.TTL != 0 {
+		i = encodeVarintWithdraw(dAtA, i, uint64(m.TTL))
+		i--
+		dAtA[i] = 0x18
+	}
+	{
+		size := m.OwnerID.Size()
+		i -= size
+		if _, err := m.OwnerID.MarshalTo(dAtA[i:]); err != nil {
+			return 0, err
+		}
+		i = encodeVarintWithdraw(dAtA, i, uint64(size))
+	}
+	i--
+	dAtA[i] = 0x12
+	{
+		size := m.ID.Size()
+		i -= size
+		if _, err := m.ID.MarshalTo(dAtA[i:]); err != nil {
+			return 0, err
+		}
+		i = encodeVarintWithdraw(dAtA, i, uint64(size))
+	}
+	i--
+	dAtA[i] = 0xa
+	return len(dAtA) - i, nil
+}
+
+func (m *GetResponse) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *GetResponse) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *GetResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if m.Withdraw != nil {
+		{
+			size, err := m.Withdraw.MarshalToSizedBuffer(dAtA[:i])
+			if err != nil {
+				return 0, err
+			}
+			i -= size
+			i = encodeVarintWithdraw(dAtA, i, uint64(size))
+		}
+		i--
+		dAtA[i] = 0xa
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *PutRequest) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *PutRequest) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *PutRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if m.TTL != 0 {
+		i = encodeVarintWithdraw(dAtA, i, uint64(m.TTL))
+		i--
+		dAtA[i] = 0x30
+	}
+	if len(m.Signature) > 0 {
+		i -= len(m.Signature)
+		copy(dAtA[i:], m.Signature)
+		i = encodeVarintWithdraw(dAtA, i, uint64(len(m.Signature)))
+		i--
+		dAtA[i] = 0x2a
+	}
+	{
+		size := m.MessageID.Size()
+		i -= size
+		if _, err := m.MessageID.MarshalTo(dAtA[i:]); err != nil {
+			return 0, err
+		}
+		i = encodeVarintWithdraw(dAtA, i, uint64(size))
+	}
+	i--
+	dAtA[i] = 0x22
+	if m.Height != 0 {
+		i = encodeVarintWithdraw(dAtA, i, uint64(m.Height))
+		i--
+		dAtA[i] = 0x18
+	}
+	if m.Amount != nil {
+		{
+			size, err := m.Amount.MarshalToSizedBuffer(dAtA[:i])
+			if err != nil {
+				return 0, err
+			}
+			i -= size
+			i = encodeVarintWithdraw(dAtA, i, uint64(size))
+		}
+		i--
+		dAtA[i] = 0x12
+	}
+	{
+		size := m.OwnerID.Size()
+		i -= size
+		if _, err := m.OwnerID.MarshalTo(dAtA[i:]); err != nil {
+			return 0, err
+		}
+		i = encodeVarintWithdraw(dAtA, i, uint64(size))
+	}
+	i--
+	dAtA[i] = 0xa
+	return len(dAtA) - i, nil
+}
+
+func (m *PutResponse) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *PutResponse) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *PutResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	{
+		size := m.ID.Size()
+		i -= size
+		if _, err := m.ID.MarshalTo(dAtA[i:]); err != nil {
+			return 0, err
+		}
+		i = encodeVarintWithdraw(dAtA, i, uint64(size))
+	}
+	i--
+	dAtA[i] = 0xa
+	return len(dAtA) - i, nil
+}
+
+func (m *ListRequest) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *ListRequest) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *ListRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if m.TTL != 0 {
+		i = encodeVarintWithdraw(dAtA, i, uint64(m.TTL))
+		i--
+		dAtA[i] = 0x10
+	}
+	{
+		size := m.OwnerID.Size()
+		i -= size
+		if _, err := m.OwnerID.MarshalTo(dAtA[i:]); err != nil {
+			return 0, err
+		}
+		i = encodeVarintWithdraw(dAtA, i, uint64(size))
+	}
+	i--
+	dAtA[i] = 0xa
+	return len(dAtA) - i, nil
+}
+
+func (m *ListResponse) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *ListResponse) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *ListResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if len(m.Items) > 0 {
+		for iNdEx := len(m.Items) - 1; iNdEx >= 0; iNdEx-- {
+			{
+				size, err := m.Items[iNdEx].MarshalToSizedBuffer(dAtA[:i])
+				if err != nil {
+					return 0, err
+				}
+				i -= size
+				i = encodeVarintWithdraw(dAtA, i, uint64(size))
+			}
+			i--
+			dAtA[i] = 0xa
+		}
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *DeleteRequest) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *DeleteRequest) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *DeleteRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if m.TTL != 0 {
+		i = encodeVarintWithdraw(dAtA, i, uint64(m.TTL))
+		i--
+		dAtA[i] = 0x28
+	}
+	if len(m.Signature) > 0 {
+		i -= len(m.Signature)
+		copy(dAtA[i:], m.Signature)
+		i = encodeVarintWithdraw(dAtA, i, uint64(len(m.Signature)))
+		i--
+		dAtA[i] = 0x22
+	}
+	{
+		size := m.MessageID.Size()
+		i -= size
+		if _, err := m.MessageID.MarshalTo(dAtA[i:]); err != nil {
+			return 0, err
+		}
+		i = encodeVarintWithdraw(dAtA, i, uint64(size))
+	}
+	i--
+	dAtA[i] = 0x1a
+	{
+		size := m.OwnerID.Size()
+		i -= size
+		if _, err := m.OwnerID.MarshalTo(dAtA[i:]); err != nil {
+			return 0, err
+		}
+		i = encodeVarintWithdraw(dAtA, i, uint64(size))
+	}
+	i--
+	dAtA[i] = 0x12
+	{
+		size := m.ID.Size()
+		i -= size
+		if _, err := m.ID.MarshalTo(dAtA[i:]); err != nil {
+			return 0, err
+		}
+		i = encodeVarintWithdraw(dAtA, i, uint64(size))
+	}
+	i--
+	dAtA[i] = 0xa
+	return len(dAtA) - i, nil
+}
+
+func (m *DeleteResponse) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *DeleteResponse) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *DeleteResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	return len(dAtA) - i, nil
+}
+
+func encodeVarintWithdraw(dAtA []byte, offset int, v uint64) int {
+	offset -= sovWithdraw(v)
+	base := offset
+	for v >= 1<<7 {
+		dAtA[offset] = uint8(v&0x7f | 0x80)
+		v >>= 7
+		offset++
+	}
+	dAtA[offset] = uint8(v)
+	return base
+}
+func (m *Item) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = m.ID.Size()
+	n += 1 + l + sovWithdraw(uint64(l))
+	l = m.OwnerID.Size()
+	n += 1 + l + sovWithdraw(uint64(l))
+	if m.Amount != nil {
+		l = m.Amount.Size()
+		n += 1 + l + sovWithdraw(uint64(l))
+	}
+	if m.Height != 0 {
+		n += 1 + sovWithdraw(uint64(m.Height))
+	}
+	l = len(m.Payload)
+	if l > 0 {
+		n += 1 + l + sovWithdraw(uint64(l))
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *GetRequest) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = m.ID.Size()
+	n += 1 + l + sovWithdraw(uint64(l))
+	l = m.OwnerID.Size()
+	n += 1 + l + sovWithdraw(uint64(l))
+	if m.TTL != 0 {
+		n += 1 + sovWithdraw(uint64(m.TTL))
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *GetResponse) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.Withdraw != nil {
+		l = m.Withdraw.Size()
+		n += 1 + l + sovWithdraw(uint64(l))
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *PutRequest) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = m.OwnerID.Size()
+	n += 1 + l + sovWithdraw(uint64(l))
+	if m.Amount != nil {
+		l = m.Amount.Size()
+		n += 1 + l + sovWithdraw(uint64(l))
+	}
+	if m.Height != 0 {
+		n += 1 + sovWithdraw(uint64(m.Height))
+	}
+	l = m.MessageID.Size()
+	n += 1 + l + sovWithdraw(uint64(l))
+	l = len(m.Signature)
+	if l > 0 {
+		n += 1 + l + sovWithdraw(uint64(l))
+	}
+	if m.TTL != 0 {
+		n += 1 + sovWithdraw(uint64(m.TTL))
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *PutResponse) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = m.ID.Size()
+	n += 1 + l + sovWithdraw(uint64(l))
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *ListRequest) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = m.OwnerID.Size()
+	n += 1 + l + sovWithdraw(uint64(l))
+	if m.TTL != 0 {
+		n += 1 + sovWithdraw(uint64(m.TTL))
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *ListResponse) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if len(m.Items) > 0 {
+		for _, e := range m.Items {
+			l = e.Size()
+			n += 1 + l + sovWithdraw(uint64(l))
+		}
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *DeleteRequest) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = m.ID.Size()
+	n += 1 + l + sovWithdraw(uint64(l))
+	l = m.OwnerID.Size()
+	n += 1 + l + sovWithdraw(uint64(l))
+	l = m.MessageID.Size()
+	n += 1 + l + sovWithdraw(uint64(l))
+	l = len(m.Signature)
+	if l > 0 {
+		n += 1 + l + sovWithdraw(uint64(l))
+	}
+	if m.TTL != 0 {
+		n += 1 + sovWithdraw(uint64(m.TTL))
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *DeleteResponse) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func sovWithdraw(x uint64) (n int) {
+	return (math_bits.Len64(x|1) + 6) / 7
+}
+func sozWithdraw(x uint64) (n int) {
+	return sovWithdraw(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+func (m *Item) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowWithdraw
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: Item: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: Item: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowWithdraw
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthWithdraw
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthWithdraw
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.ID.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field OwnerID", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowWithdraw
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthWithdraw
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthWithdraw
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.OwnerID.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 3:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowWithdraw
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthWithdraw
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthWithdraw
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if m.Amount == nil {
+				m.Amount = &decimal.Decimal{}
+			}
+			if err := m.Amount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 4:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType)
+			}
+			m.Height = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowWithdraw
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.Height |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		case 5:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Payload", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowWithdraw
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthWithdraw
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthWithdraw
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Payload = append(m.Payload[:0], dAtA[iNdEx:postIndex]...)
+			if m.Payload == nil {
+				m.Payload = []byte{}
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipWithdraw(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthWithdraw
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthWithdraw
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *GetRequest) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowWithdraw
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: GetRequest: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: GetRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowWithdraw
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthWithdraw
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthWithdraw
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.ID.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field OwnerID", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowWithdraw
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthWithdraw
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthWithdraw
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.OwnerID.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 3:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field TTL", wireType)
+			}
+			m.TTL = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowWithdraw
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.TTL |= uint32(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		default:
+			iNdEx = preIndex
+			skippy, err := skipWithdraw(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthWithdraw
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthWithdraw
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *GetResponse) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowWithdraw
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: GetResponse: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: GetResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Withdraw", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowWithdraw
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthWithdraw
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthWithdraw
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if m.Withdraw == nil {
+				m.Withdraw = &Item{}
+			}
+			if err := m.Withdraw.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipWithdraw(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthWithdraw
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthWithdraw
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *PutRequest) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowWithdraw
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: PutRequest: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: PutRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field OwnerID", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowWithdraw
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthWithdraw
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthWithdraw
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.OwnerID.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowWithdraw
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthWithdraw
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthWithdraw
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if m.Amount == nil {
+				m.Amount = &decimal.Decimal{}
+			}
+			if err := m.Amount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 3:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType)
+			}
+			m.Height = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowWithdraw
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.Height |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		case 4:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field MessageID", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowWithdraw
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthWithdraw
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthWithdraw
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.MessageID.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 5:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Signature", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowWithdraw
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthWithdraw
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthWithdraw
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Signature = append(m.Signature[:0], dAtA[iNdEx:postIndex]...)
+			if m.Signature == nil {
+				m.Signature = []byte{}
+			}
+			iNdEx = postIndex
+		case 6:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field TTL", wireType)
+			}
+			m.TTL = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowWithdraw
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.TTL |= uint32(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		default:
+			iNdEx = preIndex
+			skippy, err := skipWithdraw(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthWithdraw
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthWithdraw
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *PutResponse) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowWithdraw
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: PutResponse: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: PutResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowWithdraw
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthWithdraw
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthWithdraw
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.ID.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipWithdraw(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthWithdraw
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthWithdraw
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *ListRequest) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowWithdraw
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: ListRequest: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: ListRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field OwnerID", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowWithdraw
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthWithdraw
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthWithdraw
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.OwnerID.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 2:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field TTL", wireType)
+			}
+			m.TTL = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowWithdraw
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.TTL |= uint32(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		default:
+			iNdEx = preIndex
+			skippy, err := skipWithdraw(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthWithdraw
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthWithdraw
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *ListResponse) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowWithdraw
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: ListResponse: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: ListResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Items", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowWithdraw
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthWithdraw
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthWithdraw
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Items = append(m.Items, &Item{})
+			if err := m.Items[len(m.Items)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipWithdraw(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthWithdraw
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthWithdraw
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *DeleteRequest) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowWithdraw
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: DeleteRequest: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: DeleteRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowWithdraw
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthWithdraw
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthWithdraw
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.ID.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field OwnerID", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowWithdraw
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthWithdraw
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthWithdraw
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.OwnerID.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 3:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field MessageID", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowWithdraw
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthWithdraw
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthWithdraw
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.MessageID.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 4:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Signature", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowWithdraw
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthWithdraw
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthWithdraw
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Signature = append(m.Signature[:0], dAtA[iNdEx:postIndex]...)
+			if m.Signature == nil {
+				m.Signature = []byte{}
+			}
+			iNdEx = postIndex
+		case 5:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field TTL", wireType)
+			}
+			m.TTL = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowWithdraw
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.TTL |= uint32(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		default:
+			iNdEx = preIndex
+			skippy, err := skipWithdraw(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthWithdraw
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthWithdraw
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *DeleteResponse) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowWithdraw
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: DeleteResponse: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: DeleteResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		default:
+			iNdEx = preIndex
+			skippy, err := skipWithdraw(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthWithdraw
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthWithdraw
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func skipWithdraw(dAtA []byte) (n int, err error) {
+	l := len(dAtA)
+	iNdEx := 0
+	depth := 0
+	for iNdEx < l {
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return 0, ErrIntOverflowWithdraw
+			}
+			if iNdEx >= l {
+				return 0, io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= (uint64(b) & 0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		wireType := int(wire & 0x7)
+		switch wireType {
+		case 0:
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return 0, ErrIntOverflowWithdraw
+				}
+				if iNdEx >= l {
+					return 0, io.ErrUnexpectedEOF
+				}
+				iNdEx++
+				if dAtA[iNdEx-1] < 0x80 {
+					break
+				}
+			}
+		case 1:
+			iNdEx += 8
+		case 2:
+			var length int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return 0, ErrIntOverflowWithdraw
+				}
+				if iNdEx >= l {
+					return 0, io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				length |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if length < 0 {
+				return 0, ErrInvalidLengthWithdraw
+			}
+			iNdEx += length
+		case 3:
+			depth++
+		case 4:
+			if depth == 0 {
+				return 0, ErrUnexpectedEndOfGroupWithdraw
+			}
+			depth--
+		case 5:
+			iNdEx += 4
+		default:
+			return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+		}
+		if iNdEx < 0 {
+			return 0, ErrInvalidLengthWithdraw
+		}
+		if depth == 0 {
+			return iNdEx, nil
+		}
+	}
+	return 0, io.ErrUnexpectedEOF
+}
+
+var (
+	ErrInvalidLengthWithdraw        = fmt.Errorf("proto: negative length found during unmarshaling")
+	ErrIntOverflowWithdraw          = fmt.Errorf("proto: integer overflow")
+	ErrUnexpectedEndOfGroupWithdraw = fmt.Errorf("proto: unexpected end of group")
+)
diff --git a/accounting/withdraw.proto b/accounting/withdraw.proto
new file mode 100644
index 00000000..c099ef7c
--- /dev/null
+++ b/accounting/withdraw.proto
@@ -0,0 +1,61 @@
+syntax = "proto3";
+package accounting;
+option go_package = "github.com/nspcc-dev/neofs-proto/accounting";
+
+import "decimal/decimal.proto";
+import "github.com/gogo/protobuf/gogoproto/gogo.proto";
+
+option (gogoproto.stable_marshaler_all) = true;
+
+service Withdraw {
+    rpc Get(GetRequest) returns (GetResponse);
+    rpc Put(PutRequest) returns (PutResponse);
+    rpc List(ListRequest) returns (ListResponse);
+    rpc Delete(DeleteRequest) returns (DeleteResponse);
+}
+
+message Item {
+    bytes ID               = 1 [(gogoproto.customtype) = "ChequeID", (gogoproto.nullable) = false];
+    bytes OwnerID          = 2 [(gogoproto.customtype) = "OwnerID", (gogoproto.nullable) = false];
+    decimal.Decimal Amount = 3;
+    uint64 Height          = 4;
+    bytes Payload          = 5;
+}
+
+message GetRequest {
+    bytes ID      = 1 [(gogoproto.customtype) = "ChequeID", (gogoproto.nullable) = false];
+    bytes OwnerID = 2 [(gogoproto.customtype) = "OwnerID", (gogoproto.nullable) = false];
+    uint32 TTL    = 3;
+}
+message GetResponse {
+    Item Withdraw = 1;
+}
+
+message PutRequest {
+    bytes OwnerID          = 1 [(gogoproto.customtype) = "OwnerID", (gogoproto.nullable) = false];
+    decimal.Decimal Amount = 2;
+    uint64 Height          = 3;
+    bytes MessageID        = 4 [(gogoproto.customtype) = "MessageID", (gogoproto.nullable) = false];
+    bytes Signature        = 5;
+    uint32 TTL             = 6;
+}
+message PutResponse {
+    bytes ID = 1 [(gogoproto.customtype) = "ChequeID", (gogoproto.nullable) = false];
+}
+
+message ListRequest {
+    bytes OwnerID = 1 [(gogoproto.customtype) = "OwnerID", (gogoproto.nullable) = false];
+    uint32 TTL    = 2;
+}
+message ListResponse {
+    repeated Item Items = 1;
+}
+
+message DeleteRequest {
+    bytes ID        = 1 [(gogoproto.customtype) = "ChequeID", (gogoproto.nullable) = false];
+    bytes OwnerID   = 2 [(gogoproto.customtype) = "OwnerID", (gogoproto.nullable) = false];
+    bytes MessageID = 3 [(gogoproto.customtype) = "MessageID", (gogoproto.nullable) = false];
+    bytes Signature = 4;
+    uint32 TTL      = 5;
+}
+message DeleteResponse {}
diff --git a/bootstrap/service.go b/bootstrap/service.go
new file mode 100644
index 00000000..6d0d3ca9
--- /dev/null
+++ b/bootstrap/service.go
@@ -0,0 +1,11 @@
+package bootstrap
+
+import (
+	"github.com/nspcc-dev/neofs-proto/service"
+)
+
+// NodeType type alias.
+type NodeType = service.NodeRole
+
+// SetTTL sets ttl to Request to satisfy TTLRequest interface.
+func (m *Request) SetTTL(v uint32) { m.TTL = v }
diff --git a/bootstrap/service.pb.go b/bootstrap/service.pb.go
new file mode 100644
index 00000000..2fcdb4d2
--- /dev/null
+++ b/bootstrap/service.pb.go
@@ -0,0 +1,483 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: bootstrap/service.proto
+
+package bootstrap
+
+import (
+	context "context"
+	fmt "fmt"
+	_ "github.com/gogo/protobuf/gogoproto"
+	proto "github.com/golang/protobuf/proto"
+	grpc "google.golang.org/grpc"
+	codes "google.golang.org/grpc/codes"
+	status "google.golang.org/grpc/status"
+	io "io"
+	math "math"
+	math_bits "math/bits"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
+
+// Request message to communicate between DHT nodes
+type Request struct {
+	Type                 NodeType `protobuf:"varint,1,opt,name=type,proto3,customtype=NodeType" json:"type"`
+	Info                 NodeInfo `protobuf:"bytes,2,opt,name=info,proto3" json:"info"`
+	TTL                  uint32   `protobuf:"varint,3,opt,name=TTL,proto3" json:"TTL,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *Request) Reset()         { *m = Request{} }
+func (m *Request) String() string { return proto.CompactTextString(m) }
+func (*Request) ProtoMessage()    {}
+func (*Request) Descriptor() ([]byte, []int) {
+	return fileDescriptor_21bce759c9d8eb63, []int{0}
+}
+func (m *Request) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *Request) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *Request) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Request.Merge(m, src)
+}
+func (m *Request) XXX_Size() int {
+	return m.Size()
+}
+func (m *Request) XXX_DiscardUnknown() {
+	xxx_messageInfo_Request.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Request proto.InternalMessageInfo
+
+func (m *Request) GetInfo() NodeInfo {
+	if m != nil {
+		return m.Info
+	}
+	return NodeInfo{}
+}
+
+func (m *Request) GetTTL() uint32 {
+	if m != nil {
+		return m.TTL
+	}
+	return 0
+}
+
+func init() {
+	proto.RegisterType((*Request)(nil), "bootstrap.Request")
+}
+
+func init() { proto.RegisterFile("bootstrap/service.proto", fileDescriptor_21bce759c9d8eb63) }
+
+var fileDescriptor_21bce759c9d8eb63 = []byte{
+	// 284 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x4f, 0xca, 0xcf, 0x2f,
+	0x29, 0x2e, 0x29, 0x4a, 0x2c, 0xd0, 0x2f, 0x4e, 0x2d, 0x2a, 0xcb, 0x4c, 0x4e, 0xd5, 0x2b, 0x28,
+	0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x84, 0x4b, 0x48, 0x89, 0x22, 0xd4, 0x94, 0x54, 0x16, 0xa4, 0x16,
+	0x43, 0x54, 0x48, 0xe9, 0xa6, 0x67, 0x96, 0x64, 0x94, 0x26, 0xe9, 0x25, 0xe7, 0xe7, 0xea, 0xa7,
+	0xe7, 0xa7, 0xe7, 0xeb, 0x83, 0x85, 0x93, 0x4a, 0xd3, 0xc0, 0x3c, 0x30, 0x07, 0xcc, 0x82, 0x28,
+	0x57, 0xaa, 0xe0, 0x62, 0x0f, 0x4a, 0x2d, 0x2c, 0x4d, 0x2d, 0x2e, 0x11, 0xd2, 0xe1, 0x62, 0x01,
+	0x19, 0x24, 0xc1, 0xa8, 0xc0, 0xa8, 0xc1, 0xea, 0x24, 0x71, 0xe2, 0x9e, 0x3c, 0xc3, 0xad, 0x7b,
+	0xf2, 0x1c, 0x7e, 0xf9, 0x29, 0xa9, 0x21, 0x95, 0x05, 0xa9, 0x8f, 0xee, 0xc9, 0xb3, 0x80, 0xe8,
+	0x20, 0xb0, 0x2a, 0x21, 0x5d, 0x2e, 0x96, 0xcc, 0xbc, 0xb4, 0x7c, 0x09, 0x26, 0x05, 0x46, 0x0d,
+	0x6e, 0x23, 0x61, 0x3d, 0xb8, 0x6b, 0xf4, 0x40, 0x1a, 0x3c, 0xf3, 0xd2, 0xf2, 0x9d, 0x58, 0x40,
+	0x46, 0x04, 0x81, 0x95, 0x09, 0x09, 0x70, 0x31, 0x87, 0x84, 0xf8, 0x48, 0x30, 0x2b, 0x30, 0x6a,
+	0xf0, 0x06, 0x81, 0x98, 0x46, 0x0e, 0x5c, 0x9c, 0x4e, 0x30, 0x3d, 0x42, 0xc6, 0x5c, 0xec, 0x01,
+	0x45, 0xf9, 0xc9, 0xa9, 0xc5, 0xc5, 0x42, 0x42, 0x48, 0x46, 0x41, 0x9d, 0x26, 0x25, 0x82, 0x24,
+	0x16, 0x5c, 0x50, 0x94, 0x9a, 0x98, 0xe2, 0x9b, 0x58, 0xe0, 0xe4, 0x70, 0xe2, 0x91, 0x1c, 0xe3,
+	0x85, 0x47, 0x72, 0x8c, 0x37, 0x1e, 0xc9, 0x31, 0x3e, 0x78, 0x24, 0xc7, 0x38, 0xe3, 0xb1, 0x1c,
+	0x43, 0x94, 0x16, 0x52, 0x00, 0xe4, 0x15, 0x17, 0x24, 0x27, 0xeb, 0xa6, 0xa4, 0x96, 0xe9, 0xe7,
+	0xa5, 0xe6, 0xa7, 0x15, 0xeb, 0x42, 0xbc, 0x0f, 0x37, 0x2b, 0x89, 0x0d, 0x2c, 0x60, 0x0c, 0x08,
+	0x00, 0x00, 0xff, 0xff, 0xdf, 0x93, 0xe2, 0x48, 0x70, 0x01, 0x00, 0x00,
+}
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ context.Context
+var _ grpc.ClientConn
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the grpc package it is being compiled against.
+const _ = grpc.SupportPackageIsVersion4
+
+// BootstrapClient is the client API for Bootstrap service.
+//
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
+type BootstrapClient interface {
+	Process(ctx context.Context, in *Request, opts ...grpc.CallOption) (*SpreadMap, error)
+}
+
+type bootstrapClient struct {
+	cc *grpc.ClientConn
+}
+
+func NewBootstrapClient(cc *grpc.ClientConn) BootstrapClient {
+	return &bootstrapClient{cc}
+}
+
+func (c *bootstrapClient) Process(ctx context.Context, in *Request, opts ...grpc.CallOption) (*SpreadMap, error) {
+	out := new(SpreadMap)
+	err := c.cc.Invoke(ctx, "/bootstrap.Bootstrap/Process", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+// BootstrapServer is the server API for Bootstrap service.
+type BootstrapServer interface {
+	Process(context.Context, *Request) (*SpreadMap, error)
+}
+
+// UnimplementedBootstrapServer can be embedded to have forward compatible implementations.
+type UnimplementedBootstrapServer struct {
+}
+
+func (*UnimplementedBootstrapServer) Process(ctx context.Context, req *Request) (*SpreadMap, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method Process not implemented")
+}
+
+func RegisterBootstrapServer(s *grpc.Server, srv BootstrapServer) {
+	s.RegisterService(&_Bootstrap_serviceDesc, srv)
+}
+
+func _Bootstrap_Process_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(Request)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(BootstrapServer).Process(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/bootstrap.Bootstrap/Process",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(BootstrapServer).Process(ctx, req.(*Request))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+var _Bootstrap_serviceDesc = grpc.ServiceDesc{
+	ServiceName: "bootstrap.Bootstrap",
+	HandlerType: (*BootstrapServer)(nil),
+	Methods: []grpc.MethodDesc{
+		{
+			MethodName: "Process",
+			Handler:    _Bootstrap_Process_Handler,
+		},
+	},
+	Streams:  []grpc.StreamDesc{},
+	Metadata: "bootstrap/service.proto",
+}
+
+func (m *Request) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *Request) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *Request) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if m.TTL != 0 {
+		i = encodeVarintService(dAtA, i, uint64(m.TTL))
+		i--
+		dAtA[i] = 0x18
+	}
+	{
+		size, err := m.Info.MarshalToSizedBuffer(dAtA[:i])
+		if err != nil {
+			return 0, err
+		}
+		i -= size
+		i = encodeVarintService(dAtA, i, uint64(size))
+	}
+	i--
+	dAtA[i] = 0x12
+	if m.Type != 0 {
+		i = encodeVarintService(dAtA, i, uint64(m.Type))
+		i--
+		dAtA[i] = 0x8
+	}
+	return len(dAtA) - i, nil
+}
+
+func encodeVarintService(dAtA []byte, offset int, v uint64) int {
+	offset -= sovService(v)
+	base := offset
+	for v >= 1<<7 {
+		dAtA[offset] = uint8(v&0x7f | 0x80)
+		v >>= 7
+		offset++
+	}
+	dAtA[offset] = uint8(v)
+	return base
+}
+func (m *Request) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.Type != 0 {
+		n += 1 + sovService(uint64(m.Type))
+	}
+	l = m.Info.Size()
+	n += 1 + l + sovService(uint64(l))
+	if m.TTL != 0 {
+		n += 1 + sovService(uint64(m.TTL))
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func sovService(x uint64) (n int) {
+	return (math_bits.Len64(x|1) + 6) / 7
+}
+func sozService(x uint64) (n int) {
+	return sovService(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+func (m *Request) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowService
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: Request: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: Request: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType)
+			}
+			m.Type = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.Type |= NodeType(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Info", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthService
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthService
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.Info.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 3:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field TTL", wireType)
+			}
+			m.TTL = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.TTL |= uint32(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		default:
+			iNdEx = preIndex
+			skippy, err := skipService(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func skipService(dAtA []byte) (n int, err error) {
+	l := len(dAtA)
+	iNdEx := 0
+	depth := 0
+	for iNdEx < l {
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return 0, ErrIntOverflowService
+			}
+			if iNdEx >= l {
+				return 0, io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= (uint64(b) & 0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		wireType := int(wire & 0x7)
+		switch wireType {
+		case 0:
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return 0, ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return 0, io.ErrUnexpectedEOF
+				}
+				iNdEx++
+				if dAtA[iNdEx-1] < 0x80 {
+					break
+				}
+			}
+		case 1:
+			iNdEx += 8
+		case 2:
+			var length int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return 0, ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return 0, io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				length |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if length < 0 {
+				return 0, ErrInvalidLengthService
+			}
+			iNdEx += length
+		case 3:
+			depth++
+		case 4:
+			if depth == 0 {
+				return 0, ErrUnexpectedEndOfGroupService
+			}
+			depth--
+		case 5:
+			iNdEx += 4
+		default:
+			return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+		}
+		if iNdEx < 0 {
+			return 0, ErrInvalidLengthService
+		}
+		if depth == 0 {
+			return iNdEx, nil
+		}
+	}
+	return 0, io.ErrUnexpectedEOF
+}
+
+var (
+	ErrInvalidLengthService        = fmt.Errorf("proto: negative length found during unmarshaling")
+	ErrIntOverflowService          = fmt.Errorf("proto: integer overflow")
+	ErrUnexpectedEndOfGroupService = fmt.Errorf("proto: unexpected end of group")
+)
diff --git a/bootstrap/service.proto b/bootstrap/service.proto
new file mode 100644
index 00000000..3c9dcedc
--- /dev/null
+++ b/bootstrap/service.proto
@@ -0,0 +1,20 @@
+syntax = "proto3";
+package bootstrap;
+option go_package = "github.com/nspcc-dev/neofs-proto/bootstrap";
+
+import "bootstrap/types.proto";
+import "github.com/gogo/protobuf/gogoproto/gogo.proto";
+
+option (gogoproto.stable_marshaler_all) = true;
+
+// The Bootstrap service definition.
+service Bootstrap {
+    rpc Process(Request) returns (bootstrap.SpreadMap);
+}
+
+// Request message to communicate between DHT nodes
+message Request {
+    int32              type = 1 [(gogoproto.customname) = "Type" , (gogoproto.nullable) = false, (gogoproto.customtype) = "NodeType"];
+    bootstrap.NodeInfo info = 2 [(gogoproto.nullable) = false];
+    uint32 TTL           = 3;
+}
diff --git a/bootstrap/types.go b/bootstrap/types.go
new file mode 100644
index 00000000..6fcf0ed2
--- /dev/null
+++ b/bootstrap/types.go
@@ -0,0 +1,100 @@
+package bootstrap
+
+import (
+	"bytes"
+	"encoding/hex"
+	"strconv"
+	"strings"
+
+	"github.com/golang/protobuf/proto"
+	"github.com/nspcc-dev/neofs-proto/object"
+)
+
+type (
+	// NodeStatus is a bitwise status field of the node.
+	NodeStatus uint64
+)
+
+const (
+	storageFullMask = 0x1
+
+	optionCapacity = "/Capacity:"
+	optionPrice    = "/Price:"
+)
+
+var (
+	_ proto.Message = (*NodeInfo)(nil)
+	_ proto.Message = (*SpreadMap)(nil)
+)
+
+// Equals checks whether two NodeInfo has same address.
+func (m NodeInfo) Equals(n1 NodeInfo) bool {
+	return m.Address == n1.Address && bytes.Equal(m.PubKey, n1.PubKey)
+}
+
+// Full checks if node has enough space for storing users objects.
+func (n NodeStatus) Full() bool {
+	return n&storageFullMask > 0
+}
+
+// SetFull changes state of node to indicate if node has enough space for storing users objects.
+// If value is true - there's not enough space.
+func (n *NodeStatus) SetFull(value bool) {
+	switch value {
+	case true:
+		*n |= NodeStatus(storageFullMask)
+	case false:
+		*n &= NodeStatus(^uint64(storageFullMask))
+	}
+}
+
+// Price returns price in 1e-8*GAS/Megabyte per month.
+// User set price in GAS/Terabyte per month.
+func (m NodeInfo) Price() uint64 {
+	for i := range m.Options {
+		if strings.HasPrefix(m.Options[i], optionPrice) {
+			n, err := strconv.ParseFloat(m.Options[i][len(optionPrice):], 64)
+			if err != nil {
+				return 0
+			}
+			return uint64(n*1e8) / uint64(object.UnitsMB) // UnitsMB == megabytes in 1 terabyte
+		}
+	}
+	return 0
+}
+
+// Capacity returns node's capacity as reported by user.
+func (m NodeInfo) Capacity() uint64 {
+	for i := range m.Options {
+		if strings.HasPrefix(m.Options[i], optionCapacity) {
+			n, err := strconv.ParseUint(m.Options[i][len(optionCapacity):], 10, 64)
+			if err != nil {
+				return 0
+			}
+			return n
+		}
+	}
+	return 0
+}
+
+// String returns string representation of NodeInfo.
+func (m NodeInfo) String() string {
+	return "(NodeInfo)<" +
+		"Address:" + m.Address +
+		", " +
+		"PublicKey:" + hex.EncodeToString(m.PubKey) +
+		", " +
+		"Options: [" + strings.Join(m.Options, ",") + "]>"
+}
+
+// String returns string representation of SpreadMap.
+func (m SpreadMap) String() string {
+	result := make([]string, 0, len(m.NetMap))
+	for i := range m.NetMap {
+		result = append(result, m.NetMap[i].String())
+	}
+	return "(SpreadMap)<" +
+		"Epoch: " + strconv.FormatUint(m.Epoch, 10) +
+		", " +
+		"Netmap: [" + strings.Join(result, ",") + "]>"
+}
diff --git a/bootstrap/types.pb.go b/bootstrap/types.pb.go
new file mode 100644
index 00000000..a90de05b
--- /dev/null
+++ b/bootstrap/types.pb.go
@@ -0,0 +1,697 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: bootstrap/types.proto
+
+package bootstrap
+
+import (
+	fmt "fmt"
+	_ "github.com/gogo/protobuf/gogoproto"
+	proto "github.com/golang/protobuf/proto"
+	io "io"
+	math "math"
+	math_bits "math/bits"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
+
+type SpreadMap struct {
+	Epoch                uint64     `protobuf:"varint,1,opt,name=Epoch,proto3" json:"Epoch,omitempty"`
+	NetMap               []NodeInfo `protobuf:"bytes,2,rep,name=NetMap,proto3" json:"NetMap"`
+	XXX_NoUnkeyedLiteral struct{}   `json:"-"`
+	XXX_unrecognized     []byte     `json:"-"`
+	XXX_sizecache        int32      `json:"-"`
+}
+
+func (m *SpreadMap) Reset()      { *m = SpreadMap{} }
+func (*SpreadMap) ProtoMessage() {}
+func (*SpreadMap) Descriptor() ([]byte, []int) {
+	return fileDescriptor_423083266369adee, []int{0}
+}
+func (m *SpreadMap) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *SpreadMap) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *SpreadMap) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_SpreadMap.Merge(m, src)
+}
+func (m *SpreadMap) XXX_Size() int {
+	return m.Size()
+}
+func (m *SpreadMap) XXX_DiscardUnknown() {
+	xxx_messageInfo_SpreadMap.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_SpreadMap proto.InternalMessageInfo
+
+func (m *SpreadMap) GetEpoch() uint64 {
+	if m != nil {
+		return m.Epoch
+	}
+	return 0
+}
+
+func (m *SpreadMap) GetNetMap() []NodeInfo {
+	if m != nil {
+		return m.NetMap
+	}
+	return nil
+}
+
+type NodeInfo struct {
+	Address              string     `protobuf:"bytes,1,opt,name=Address,proto3" json:"address"`
+	PubKey               []byte     `protobuf:"bytes,2,opt,name=PubKey,proto3" json:"pubkey,omitempty"`
+	Options              []string   `protobuf:"bytes,3,rep,name=Options,proto3" json:"options,omitempty"`
+	Status               NodeStatus `protobuf:"varint,4,opt,name=Status,proto3,customtype=NodeStatus" json:"status"`
+	XXX_NoUnkeyedLiteral struct{}   `json:"-"`
+	XXX_unrecognized     []byte     `json:"-"`
+	XXX_sizecache        int32      `json:"-"`
+}
+
+func (m *NodeInfo) Reset()      { *m = NodeInfo{} }
+func (*NodeInfo) ProtoMessage() {}
+func (*NodeInfo) Descriptor() ([]byte, []int) {
+	return fileDescriptor_423083266369adee, []int{1}
+}
+func (m *NodeInfo) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *NodeInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *NodeInfo) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_NodeInfo.Merge(m, src)
+}
+func (m *NodeInfo) XXX_Size() int {
+	return m.Size()
+}
+func (m *NodeInfo) XXX_DiscardUnknown() {
+	xxx_messageInfo_NodeInfo.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_NodeInfo proto.InternalMessageInfo
+
+func (m *NodeInfo) GetAddress() string {
+	if m != nil {
+		return m.Address
+	}
+	return ""
+}
+
+func (m *NodeInfo) GetPubKey() []byte {
+	if m != nil {
+		return m.PubKey
+	}
+	return nil
+}
+
+func (m *NodeInfo) GetOptions() []string {
+	if m != nil {
+		return m.Options
+	}
+	return nil
+}
+
+func init() {
+	proto.RegisterType((*SpreadMap)(nil), "bootstrap.SpreadMap")
+	proto.RegisterType((*NodeInfo)(nil), "bootstrap.NodeInfo")
+}
+
+func init() { proto.RegisterFile("bootstrap/types.proto", fileDescriptor_423083266369adee) }
+
+var fileDescriptor_423083266369adee = []byte{
+	// 345 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x4c, 0x90, 0xcb, 0x4a, 0xc3, 0x40,
+	0x18, 0x85, 0x33, 0x6d, 0x4d, 0xcd, 0xd4, 0x85, 0xc6, 0x16, 0x82, 0x48, 0x12, 0x0a, 0x42, 0x90,
+	0x36, 0xc1, 0xcb, 0x0b, 0x18, 0x10, 0x14, 0x69, 0x95, 0xd4, 0x95, 0xbb, 0x5c, 0xa6, 0x17, 0xa4,
+	0xf9, 0x87, 0xcc, 0x44, 0xc8, 0xce, 0xc7, 0xf0, 0x89, 0xa4, 0x4b, 0x97, 0xc5, 0x45, 0xd0, 0xb8,
+	0xcb, 0x53, 0x48, 0x27, 0x6d, 0xe9, 0xee, 0x3f, 0xe7, 0x7c, 0x33, 0xf3, 0xcf, 0xc1, 0x9d, 0x00,
+	0x80, 0x33, 0x9e, 0xf8, 0xd4, 0xe1, 0x19, 0x25, 0xcc, 0xa6, 0x09, 0x70, 0x50, 0x95, 0xad, 0x7d,
+	0xd2, 0x9f, 0xcc, 0xf8, 0x34, 0x0d, 0xec, 0x10, 0xe6, 0xce, 0x04, 0x26, 0xe0, 0x08, 0x22, 0x48,
+	0xc7, 0x42, 0x09, 0x21, 0xa6, 0xea, 0x64, 0xf7, 0x19, 0x2b, 0x23, 0x9a, 0x10, 0x3f, 0x1a, 0xf8,
+	0x54, 0x6d, 0xe3, 0xbd, 0x5b, 0x0a, 0xe1, 0x54, 0x43, 0x26, 0xb2, 0x1a, 0x5e, 0x25, 0xd4, 0x0b,
+	0x2c, 0x0f, 0x09, 0x1f, 0xf8, 0x54, 0xab, 0x99, 0x75, 0xab, 0x75, 0x79, 0x6c, 0x6f, 0x5f, 0xb3,
+	0x87, 0x10, 0x91, 0xfb, 0x78, 0x0c, 0x6e, 0x63, 0x91, 0x1b, 0x92, 0xb7, 0x06, 0xbb, 0x9f, 0x08,
+	0xef, 0x6f, 0x22, 0xf5, 0x0c, 0x37, 0x6f, 0xa2, 0x28, 0x21, 0x8c, 0x89, 0x7b, 0x15, 0xb7, 0x55,
+	0xe6, 0x46, 0xd3, 0xaf, 0x2c, 0x6f, 0x93, 0xa9, 0x3d, 0x2c, 0x3f, 0xa5, 0xc1, 0x03, 0xc9, 0xb4,
+	0x9a, 0x89, 0xac, 0x03, 0xb7, 0x5d, 0xe6, 0xc6, 0x21, 0x4d, 0x83, 0x57, 0x92, 0xf5, 0x60, 0x3e,
+	0xe3, 0x64, 0x4e, 0x79, 0xe6, 0xad, 0x19, 0xd5, 0xc1, 0xcd, 0x47, 0xca, 0x67, 0x10, 0x33, 0xad,
+	0x6e, 0xd6, 0x2d, 0xc5, 0xed, 0x94, 0xb9, 0x71, 0x04, 0x95, 0xb5, 0xc3, 0x6f, 0x28, 0xf5, 0x1a,
+	0xcb, 0x23, 0xee, 0xf3, 0x94, 0x69, 0x8d, 0xd5, 0xe7, 0xdc, 0xd3, 0xd5, 0xc2, 0xdf, 0xb9, 0x81,
+	0x57, 0x7b, 0x56, 0x49, 0x99, 0x1b, 0x32, 0x13, 0x93, 0xb7, 0x66, 0xdd, 0xbb, 0xe5, 0xaf, 0x2e,
+	0xbd, 0x17, 0xba, 0xb4, 0x28, 0x74, 0xf4, 0x55, 0xe8, 0x68, 0x59, 0xe8, 0xe8, 0xa7, 0xd0, 0xd1,
+	0xc7, 0x9f, 0x2e, 0xbd, 0x9c, 0xef, 0x74, 0x1d, 0x33, 0x1a, 0x86, 0xfd, 0x88, 0xbc, 0x39, 0x31,
+	0x81, 0x31, 0xeb, 0x57, 0x4d, 0x6f, 0x9b, 0x0a, 0x64, 0x61, 0x5c, 0xfd, 0x07, 0x00, 0x00, 0xff,
+	0xff, 0x71, 0xeb, 0x37, 0x57, 0xc2, 0x01, 0x00, 0x00,
+}
+
+func (m *SpreadMap) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *SpreadMap) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *SpreadMap) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if len(m.NetMap) > 0 {
+		for iNdEx := len(m.NetMap) - 1; iNdEx >= 0; iNdEx-- {
+			{
+				size, err := m.NetMap[iNdEx].MarshalToSizedBuffer(dAtA[:i])
+				if err != nil {
+					return 0, err
+				}
+				i -= size
+				i = encodeVarintTypes(dAtA, i, uint64(size))
+			}
+			i--
+			dAtA[i] = 0x12
+		}
+	}
+	if m.Epoch != 0 {
+		i = encodeVarintTypes(dAtA, i, uint64(m.Epoch))
+		i--
+		dAtA[i] = 0x8
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *NodeInfo) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *NodeInfo) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *NodeInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if m.Status != 0 {
+		i = encodeVarintTypes(dAtA, i, uint64(m.Status))
+		i--
+		dAtA[i] = 0x20
+	}
+	if len(m.Options) > 0 {
+		for iNdEx := len(m.Options) - 1; iNdEx >= 0; iNdEx-- {
+			i -= len(m.Options[iNdEx])
+			copy(dAtA[i:], m.Options[iNdEx])
+			i = encodeVarintTypes(dAtA, i, uint64(len(m.Options[iNdEx])))
+			i--
+			dAtA[i] = 0x1a
+		}
+	}
+	if len(m.PubKey) > 0 {
+		i -= len(m.PubKey)
+		copy(dAtA[i:], m.PubKey)
+		i = encodeVarintTypes(dAtA, i, uint64(len(m.PubKey)))
+		i--
+		dAtA[i] = 0x12
+	}
+	if len(m.Address) > 0 {
+		i -= len(m.Address)
+		copy(dAtA[i:], m.Address)
+		i = encodeVarintTypes(dAtA, i, uint64(len(m.Address)))
+		i--
+		dAtA[i] = 0xa
+	}
+	return len(dAtA) - i, nil
+}
+
+func encodeVarintTypes(dAtA []byte, offset int, v uint64) int {
+	offset -= sovTypes(v)
+	base := offset
+	for v >= 1<<7 {
+		dAtA[offset] = uint8(v&0x7f | 0x80)
+		v >>= 7
+		offset++
+	}
+	dAtA[offset] = uint8(v)
+	return base
+}
+func (m *SpreadMap) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.Epoch != 0 {
+		n += 1 + sovTypes(uint64(m.Epoch))
+	}
+	if len(m.NetMap) > 0 {
+		for _, e := range m.NetMap {
+			l = e.Size()
+			n += 1 + l + sovTypes(uint64(l))
+		}
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *NodeInfo) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = len(m.Address)
+	if l > 0 {
+		n += 1 + l + sovTypes(uint64(l))
+	}
+	l = len(m.PubKey)
+	if l > 0 {
+		n += 1 + l + sovTypes(uint64(l))
+	}
+	if len(m.Options) > 0 {
+		for _, s := range m.Options {
+			l = len(s)
+			n += 1 + l + sovTypes(uint64(l))
+		}
+	}
+	if m.Status != 0 {
+		n += 1 + sovTypes(uint64(m.Status))
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func sovTypes(x uint64) (n int) {
+	return (math_bits.Len64(x|1) + 6) / 7
+}
+func sozTypes(x uint64) (n int) {
+	return sovTypes(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+func (m *SpreadMap) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowTypes
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: SpreadMap: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: SpreadMap: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Epoch", wireType)
+			}
+			m.Epoch = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.Epoch |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field NetMap", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.NetMap = append(m.NetMap, NodeInfo{})
+			if err := m.NetMap[len(m.NetMap)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipTypes(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *NodeInfo) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowTypes
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: NodeInfo: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: NodeInfo: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Address = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field PubKey", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.PubKey = append(m.PubKey[:0], dAtA[iNdEx:postIndex]...)
+			if m.PubKey == nil {
+				m.PubKey = []byte{}
+			}
+			iNdEx = postIndex
+		case 3:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Options", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Options = append(m.Options, string(dAtA[iNdEx:postIndex]))
+			iNdEx = postIndex
+		case 4:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Status", wireType)
+			}
+			m.Status = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.Status |= NodeStatus(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		default:
+			iNdEx = preIndex
+			skippy, err := skipTypes(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func skipTypes(dAtA []byte) (n int, err error) {
+	l := len(dAtA)
+	iNdEx := 0
+	depth := 0
+	for iNdEx < l {
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return 0, ErrIntOverflowTypes
+			}
+			if iNdEx >= l {
+				return 0, io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= (uint64(b) & 0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		wireType := int(wire & 0x7)
+		switch wireType {
+		case 0:
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return 0, ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return 0, io.ErrUnexpectedEOF
+				}
+				iNdEx++
+				if dAtA[iNdEx-1] < 0x80 {
+					break
+				}
+			}
+		case 1:
+			iNdEx += 8
+		case 2:
+			var length int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return 0, ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return 0, io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				length |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if length < 0 {
+				return 0, ErrInvalidLengthTypes
+			}
+			iNdEx += length
+		case 3:
+			depth++
+		case 4:
+			if depth == 0 {
+				return 0, ErrUnexpectedEndOfGroupTypes
+			}
+			depth--
+		case 5:
+			iNdEx += 4
+		default:
+			return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+		}
+		if iNdEx < 0 {
+			return 0, ErrInvalidLengthTypes
+		}
+		if depth == 0 {
+			return iNdEx, nil
+		}
+	}
+	return 0, io.ErrUnexpectedEOF
+}
+
+var (
+	ErrInvalidLengthTypes        = fmt.Errorf("proto: negative length found during unmarshaling")
+	ErrIntOverflowTypes          = fmt.Errorf("proto: integer overflow")
+	ErrUnexpectedEndOfGroupTypes = fmt.Errorf("proto: unexpected end of group")
+)
diff --git a/bootstrap/types.proto b/bootstrap/types.proto
new file mode 100644
index 00000000..4d6e458b
--- /dev/null
+++ b/bootstrap/types.proto
@@ -0,0 +1,22 @@
+syntax = "proto3";
+package bootstrap;
+option go_package = "github.com/nspcc-dev/neofs-proto/bootstrap";
+
+import "github.com/gogo/protobuf/gogoproto/gogo.proto";
+
+option (gogoproto.stable_marshaler_all) = true;;
+
+option (gogoproto.stringer_all) =  false;
+option (gogoproto.goproto_stringer_all) = false;
+
+message SpreadMap {
+    uint64 Epoch = 1;
+    repeated NodeInfo NetMap = 2 [(gogoproto.nullable) = false];
+}
+
+message NodeInfo {
+    string Address          = 1 [(gogoproto.jsontag) = "address"];
+    bytes PubKey            = 2 [(gogoproto.jsontag) = "pubkey,omitempty"];
+    repeated string Options = 3 [(gogoproto.jsontag) = "options,omitempty"];
+    uint64 Status           = 4 [(gogoproto.jsontag) = "status", (gogoproto.nullable) = false, (gogoproto.customtype) = "NodeStatus"];
+}
diff --git a/chain/address.go b/chain/address.go
new file mode 100644
index 00000000..e760d698
--- /dev/null
+++ b/chain/address.go
@@ -0,0 +1,185 @@
+package chain
+
+import (
+	"bytes"
+	"crypto/ecdsa"
+	"crypto/sha256"
+	"encoding/hex"
+
+	"github.com/mr-tron/base58"
+	crypto "github.com/nspcc-dev/neofs-crypto"
+	"github.com/nspcc-dev/neofs-proto/internal"
+	"github.com/pkg/errors"
+	"golang.org/x/crypto/ripemd160"
+)
+
+// WalletAddress implements NEO address.
+type WalletAddress [AddressLength]byte
+
+const (
+	// AddressLength contains size of address,
+	// 0x17 byte (address version) + 20 bytes of ScriptHash + 4 bytes of checksum.
+	AddressLength = 25
+
+	// ScriptHashLength contains size of ScriptHash.
+	ScriptHashLength = 20
+
+	// ErrEmptyAddress is raised when empty Address is passed.
+	ErrEmptyAddress = internal.Error("empty address")
+
+	// ErrAddressLength is raised when passed address has wrong size.
+	ErrAddressLength = internal.Error("wrong address length")
+)
+
+func checksum(sign []byte) []byte {
+	hash := sha256.Sum256(sign)
+	hash = sha256.Sum256(hash[:])
+	return hash[:4]
+}
+
+// FetchPublicKeys tries to parse public keys from verification script.
+func FetchPublicKeys(vs []byte) []*ecdsa.PublicKey {
+	var (
+		count  int
+		offset int
+		ln     = len(vs)
+		result []*ecdsa.PublicKey
+	)
+
+	switch {
+	case ln < 1: // wrong data size
+		return nil
+	case vs[ln-1] == 0xac: // last byte is CHECKSIG
+		count = 1
+	case vs[ln-1] == 0xae: // last byte is CHECKMULTISIG
+		// 2nd byte from the end indicates about PK's count
+		count = int(vs[ln-2] - 0x50)
+		// ignores CHECKMULTISIG
+		offset = 1
+	default: // unknown type
+		return nil
+	}
+
+	result = make([]*ecdsa.PublicKey, 0, count)
+	for i := 0; i < count; i++ {
+		// ignores PUSHBYTE33 and tries to parse
+		from, to := offset+1, offset+1+crypto.PublicKeyCompressedSize
+
+		// when passed VerificationScript has wrong size
+		if len(vs) < to {
+			return nil
+		}
+
+		key := crypto.UnmarshalPublicKey(vs[from:to])
+		// when wrong public key is passed
+		if key == nil {
+			return nil
+		}
+		result = append(result, key)
+
+		offset += 1 + crypto.PublicKeyCompressedSize
+	}
+	return result
+}
+
+// VerificationScript returns VerificationScript composed from public keys.
+func VerificationScript(pubs ...*ecdsa.PublicKey) []byte {
+	var (
+		pre    []byte
+		suf    []byte
+		body   []byte
+		offset int
+		lnPK   = len(pubs)
+		ln     = crypto.PublicKeyCompressedSize*lnPK + lnPK // 33 * count + count * 1 (PUSHBYTES33)
+	)
+
+	if len(pubs) > 1 {
+		pre = []byte{0x51}                    // one address
+		suf = []byte{byte(0x50 + lnPK), 0xae} // count of PK's + CHECKMULTISIG
+	} else {
+		suf = []byte{0xac} // CHECKSIG
+	}
+
+	ln += len(pre) + len(suf)
+
+	body = make([]byte, ln)
+	offset += copy(body, pre)
+
+	for i := range pubs {
+		body[offset] = 0x21
+		offset++
+		offset += copy(body[offset:], crypto.MarshalPublicKey(pubs[i]))
+	}
+
+	copy(body[offset:], suf)
+
+	return body
+}
+
+// KeysToAddress return NEO address composed from public keys.
+func KeysToAddress(pubs ...*ecdsa.PublicKey) string {
+	if len(pubs) == 0 {
+		return ""
+	}
+	return Address(VerificationScript(pubs...))
+}
+
+// Address returns NEO address based on passed VerificationScript.
+func Address(verificationScript []byte) string {
+	sign := [AddressLength]byte{0x17}
+	hash := sha256.Sum256(verificationScript)
+	ripe := ripemd160.New()
+	ripe.Write(hash[:])
+	copy(sign[1:], ripe.Sum(nil))
+	copy(sign[21:], checksum(sign[:21]))
+	return base58.Encode(sign[:])
+}
+
+// ReversedScriptHashToAddress parses script hash and returns valid NEO address.
+func ReversedScriptHashToAddress(sc string) (addr string, err error) {
+	var data []byte
+	if data, err = DecodeScriptHash(sc); err != nil {
+		return
+	}
+	sign := [AddressLength]byte{0x17}
+	copy(sign[1:], data)
+	copy(sign[1+ScriptHashLength:], checksum(sign[:1+ScriptHashLength]))
+	return base58.Encode(sign[:]), nil
+}
+
+// IsAddress checks that passed NEO Address is valid.
+func IsAddress(s string) error {
+	if s == "" {
+		return ErrEmptyAddress
+	} else if addr, err := base58.Decode(s); err != nil {
+		return errors.Wrap(err, "base58 decode")
+	} else if ln := len(addr); ln != AddressLength {
+		return errors.Wrapf(ErrAddressLength, "length %d != %d", AddressLength, ln)
+	} else if sum := checksum(addr[:21]); !bytes.Equal(addr[21:], sum) {
+		return errors.Errorf("wrong checksum %0x != %0x",
+			addr[21:], sum)
+	}
+
+	return nil
+}
+
+// ReverseBytes returns reversed []byte of given.
+func ReverseBytes(data []byte) []byte {
+	for i, j := 0, len(data)-1; i < j; i, j = i+1, j-1 {
+		data[i], data[j] = data[j], data[i]
+	}
+	return data
+}
+
+// DecodeScriptHash parses script hash into slice of bytes.
+func DecodeScriptHash(s string) ([]byte, error) {
+	if s == "" {
+		return nil, ErrEmptyAddress
+	} else if addr, err := hex.DecodeString(s); err != nil {
+		return nil, errors.Wrap(err, "hex decode")
+	} else if ln := len(addr); ln != ScriptHashLength {
+		return nil, errors.Wrapf(ErrAddressLength, "length %d != %d", ScriptHashLength, ln)
+	} else {
+		return addr, nil
+	}
+}
diff --git a/chain/address_test.go b/chain/address_test.go
new file mode 100644
index 00000000..f83b1ddf
--- /dev/null
+++ b/chain/address_test.go
@@ -0,0 +1,292 @@
+package chain
+
+import (
+	"crypto/ecdsa"
+	"encoding/hex"
+	"testing"
+
+	crypto "github.com/nspcc-dev/neofs-crypto"
+	"github.com/nspcc-dev/neofs-crypto/test"
+	"github.com/stretchr/testify/require"
+)
+
+func TestAddress(t *testing.T) {
+	var (
+		multiSigVerificationScript = "512103c02a93134f98d9c78ec54b1b1f97fc64cd81360f53a293f41e4ad54aac3c57172103fea219d4ccfd7641cebbb2439740bb4bd7c4730c1abd6ca1dc44386533816df952ae"
+		multiSigAddress            = "ANbvKqa2SfgTUkq43NRUhCiyxPrpUPn7S3"
+
+		normalVerificationScript = "2102a33413277a319cc6fd4c54a2feb9032eba668ec587f307e319dc48733087fa61ac"
+		normalAddress            = "AcraNnCuPKnUYtPYyrACRCVJhLpvskbfhu"
+	)
+
+	t.Run("check multi-sig address", func(t *testing.T) {
+		data, err := hex.DecodeString(multiSigVerificationScript)
+		require.NoError(t, err)
+		require.Equal(t, multiSigAddress, Address(data))
+	})
+
+	t.Run("check normal address", func(t *testing.T) {
+		data, err := hex.DecodeString(normalVerificationScript)
+		require.NoError(t, err)
+		require.Equal(t, normalAddress, Address(data))
+	})
+}
+
+func TestVerificationScript(t *testing.T) {
+	t.Run("check normal", func(t *testing.T) {
+		pkString := "02a33413277a319cc6fd4c54a2feb9032eba668ec587f307e319dc48733087fa61"
+
+		pkBytes, err := hex.DecodeString(pkString)
+		require.NoError(t, err)
+
+		pk := crypto.UnmarshalPublicKey(pkBytes)
+
+		expect, err := hex.DecodeString(
+			"21" + pkString + // PUSHBYTES33
+				"ac", // CHECKSIG
+		)
+
+		require.Equal(t, expect, VerificationScript(pk))
+	})
+
+	t.Run("check multisig", func(t *testing.T) {
+		pk1String := "03c02a93134f98d9c78ec54b1b1f97fc64cd81360f53a293f41e4ad54aac3c5717"
+		pk2String := "03fea219d4ccfd7641cebbb2439740bb4bd7c4730c1abd6ca1dc44386533816df9"
+
+		pk1Bytes, err := hex.DecodeString(pk1String)
+		require.NoError(t, err)
+
+		pk1 := crypto.UnmarshalPublicKey(pk1Bytes)
+
+		pk2Bytes, err := hex.DecodeString(pk2String)
+		require.NoError(t, err)
+
+		pk2 := crypto.UnmarshalPublicKey(pk2Bytes)
+
+		expect, err := hex.DecodeString(
+			"51" + // one address
+				"21" + pk1String + // PUSHBYTES33
+				"21" + pk2String + // PUSHBYTES33
+				"52" + // 2 PublicKeys
+				"ae", // CHECKMULTISIG
+		)
+
+		require.Equal(t, expect, VerificationScript(pk1, pk2))
+	})
+}
+
+func TestKeysToAddress(t *testing.T) {
+	t.Run("check normal", func(t *testing.T) {
+		pkString := "02a33413277a319cc6fd4c54a2feb9032eba668ec587f307e319dc48733087fa61"
+
+		pkBytes, err := hex.DecodeString(pkString)
+		require.NoError(t, err)
+
+		pk := crypto.UnmarshalPublicKey(pkBytes)
+
+		expect := "AcraNnCuPKnUYtPYyrACRCVJhLpvskbfhu"
+
+		actual := KeysToAddress(pk)
+		require.Equal(t, expect, actual)
+		require.NoError(t, IsAddress(actual))
+	})
+
+	t.Run("check multisig", func(t *testing.T) {
+		pk1String := "03c02a93134f98d9c78ec54b1b1f97fc64cd81360f53a293f41e4ad54aac3c5717"
+		pk2String := "03fea219d4ccfd7641cebbb2439740bb4bd7c4730c1abd6ca1dc44386533816df9"
+
+		pk1Bytes, err := hex.DecodeString(pk1String)
+		require.NoError(t, err)
+
+		pk1 := crypto.UnmarshalPublicKey(pk1Bytes)
+
+		pk2Bytes, err := hex.DecodeString(pk2String)
+		require.NoError(t, err)
+
+		pk2 := crypto.UnmarshalPublicKey(pk2Bytes)
+
+		expect := "ANbvKqa2SfgTUkq43NRUhCiyxPrpUPn7S3"
+		actual := KeysToAddress(pk1, pk2)
+		require.Equal(t, expect, actual)
+		require.NoError(t, IsAddress(actual))
+	})
+}
+
+func TestFetchPublicKeys(t *testing.T) {
+	var (
+		multiSigVerificationScript = "512103c02a93134f98d9c78ec54b1b1f97fc64cd81360f53a293f41e4ad54aac3c57172103fea219d4ccfd7641cebbb2439740bb4bd7c4730c1abd6ca1dc44386533816df952ae"
+		normalVerificationScript   = "2102a33413277a319cc6fd4c54a2feb9032eba668ec587f307e319dc48733087fa61ac"
+
+		pk1String = "03c02a93134f98d9c78ec54b1b1f97fc64cd81360f53a293f41e4ad54aac3c5717"
+		pk2String = "03fea219d4ccfd7641cebbb2439740bb4bd7c4730c1abd6ca1dc44386533816df9"
+		pk3String = "02a33413277a319cc6fd4c54a2feb9032eba668ec587f307e319dc48733087fa61"
+	)
+
+	t.Run("shouls not fail", func(t *testing.T) {
+		wrongVS, err := hex.DecodeString(multiSigVerificationScript)
+		require.NoError(t, err)
+
+		wrongVS[len(wrongVS)-1] = 0x1
+
+		wrongPK, err := hex.DecodeString(multiSigVerificationScript)
+		require.NoError(t, err)
+		wrongPK[2] = 0x1
+
+		var testCases = []struct {
+			name  string
+			value []byte
+		}{
+			{name: "empty VerificationScript"},
+			{
+				name:  "wrong size VerificationScript",
+				value: []byte{0x1},
+			},
+			{
+				name:  "wrong VerificationScript type",
+				value: wrongVS,
+			},
+			{
+				name:  "wrong public key in VerificationScript",
+				value: wrongPK,
+			},
+		}
+
+		for i := range testCases {
+			tt := testCases[i]
+			t.Run(tt.name, func(t *testing.T) {
+				var keys []*ecdsa.PublicKey
+				require.NotPanics(t, func() {
+					keys = FetchPublicKeys(tt.value)
+				})
+				require.Nil(t, keys)
+			})
+		}
+	})
+
+	t.Run("check multi-sig address", func(t *testing.T) {
+		data, err := hex.DecodeString(multiSigVerificationScript)
+		require.NoError(t, err)
+
+		pk1Bytes, err := hex.DecodeString(pk1String)
+		require.NoError(t, err)
+
+		pk2Bytes, err := hex.DecodeString(pk2String)
+		require.NoError(t, err)
+
+		pk1 := crypto.UnmarshalPublicKey(pk1Bytes)
+		pk2 := crypto.UnmarshalPublicKey(pk2Bytes)
+
+		keys := FetchPublicKeys(data)
+		require.Len(t, keys, 2)
+		require.Equal(t, keys[0], pk1)
+		require.Equal(t, keys[1], pk2)
+	})
+
+	t.Run("check normal address", func(t *testing.T) {
+		data, err := hex.DecodeString(normalVerificationScript)
+		require.NoError(t, err)
+
+		pkBytes, err := hex.DecodeString(pk3String)
+		require.NoError(t, err)
+
+		pk := crypto.UnmarshalPublicKey(pkBytes)
+
+		keys := FetchPublicKeys(data)
+		require.Len(t, keys, 1)
+		require.Equal(t, keys[0], pk)
+	})
+
+	t.Run("generate 10 keys VerificationScript and try parse it", func(t *testing.T) {
+		var (
+			count  = 10
+			expect = make([]*ecdsa.PublicKey, 0, count)
+		)
+
+		for i := 0; i < count; i++ {
+			key := test.DecodeKey(i)
+			expect = append(expect, &key.PublicKey)
+		}
+
+		vs := VerificationScript(expect...)
+
+		actual := FetchPublicKeys(vs)
+		require.Equal(t, expect, actual)
+	})
+}
+
+func TestReversedScriptHashToAddress(t *testing.T) {
+	var testCases = []struct {
+		name   string
+		value  string
+		expect string
+	}{
+		{
+			name:   "first",
+			expect: "APfiG5imQgn8dzTTfaDfqHnxo3QDUkF69A",
+			value:  "5696acd07f0927fd5f01946828638c9e2c90c5dc",
+		},
+
+		{
+			name:   "second",
+			expect: "AK2nJJpJr6o664CWJKi1QRXjqeic2zRp8y",
+			value:  "23ba2703c53263e8d6e522dc32203339dcd8eee9",
+		},
+	}
+
+	for i := range testCases {
+		tt := testCases[i]
+		t.Run(tt.name, func(t *testing.T) {
+			actual, err := ReversedScriptHashToAddress(tt.value)
+			require.NoError(t, err)
+			require.Equal(t, tt.expect, actual)
+			require.NoError(t, IsAddress(actual))
+		})
+	}
+}
+
+func TestReverseBytes(t *testing.T) {
+	var testCases = []struct {
+		name   string
+		value  []byte
+		expect []byte
+	}{
+		{name: "empty"},
+		{
+			name:   "single byte",
+			expect: []byte{0x1},
+			value:  []byte{0x1},
+		},
+
+		{
+			name:   "two bytes",
+			expect: []byte{0x2, 0x1},
+			value:  []byte{0x1, 0x2},
+		},
+
+		{
+			name:   "three bytes",
+			expect: []byte{0x3, 0x2, 0x1},
+			value:  []byte{0x1, 0x2, 0x3},
+		},
+
+		{
+			name:   "five bytes",
+			expect: []byte{0x5, 0x4, 0x3, 0x2, 0x1},
+			value:  []byte{0x1, 0x2, 0x3, 0x4, 0x5},
+		},
+
+		{
+			name:   "eight bytes",
+			expect: []byte{0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1},
+			value:  []byte{0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8},
+		},
+	}
+
+	for i := range testCases {
+		tt := testCases[i]
+		t.Run(tt.name, func(t *testing.T) {
+			actual := ReverseBytes(tt.value)
+			require.Equal(t, tt.expect, actual)
+		})
+	}
+}
diff --git a/container/service.go b/container/service.go
new file mode 100644
index 00000000..527377a7
--- /dev/null
+++ b/container/service.go
@@ -0,0 +1,68 @@
+package container
+
+import (
+	"bytes"
+	"encoding/binary"
+
+	"github.com/nspcc-dev/neofs-proto/refs"
+	"github.com/pkg/errors"
+)
+
+type (
+	// CID type alias.
+	CID = refs.CID
+	// UUID type alias.
+	UUID = refs.UUID
+	// OwnerID type alias.
+	OwnerID = refs.OwnerID
+	// OwnerID type alias.
+	MessageID = refs.MessageID
+)
+
+// SetTTL sets ttl to GetRequest to satisfy TTLRequest interface.
+func (m *GetRequest) SetTTL(v uint32) { m.TTL = v }
+
+// SetTTL sets ttl to PutRequest to satisfy TTLRequest interface.
+func (m *PutRequest) SetTTL(v uint32) { m.TTL = v }
+
+// SetTTL sets ttl to ListRequest to satisfy TTLRequest interface.
+func (m *ListRequest) SetTTL(v uint32) { m.TTL = v }
+
+// SetTTL sets ttl to DeleteRequest to satisfy TTLRequest interface.
+func (m *DeleteRequest) SetTTL(v uint32) { m.TTL = v }
+
+// SetSignature sets signature to PutRequest to satisfy SignedRequest interface.
+func (m *PutRequest) SetSignature(v []byte) { m.Signature = v }
+
+// SetSignature sets signature to DeleteRequest to satisfy SignedRequest interface.
+func (m *DeleteRequest) SetSignature(v []byte) { m.Signature = v }
+
+// PrepareData prepares bytes representation of PutRequest to satisfy SignedRequest interface.
+func (m *PutRequest) PrepareData() ([]byte, error) {
+	var (
+		err      error
+		buf      = new(bytes.Buffer)
+		capBytes = make([]byte, 8)
+	)
+
+	binary.BigEndian.PutUint64(capBytes, m.Capacity)
+
+	if _, err = buf.Write(m.MessageID.Bytes()); err != nil {
+		return nil, errors.Wrap(err, "could not write message id")
+	} else if _, err = buf.Write(capBytes); err != nil {
+		return nil, errors.Wrap(err, "could not write capacity")
+	} else if _, err = buf.Write(m.OwnerID.Bytes()); err != nil {
+		return nil, errors.Wrap(err, "could not write pub")
+	} else if data, err := m.Rules.Marshal(); err != nil {
+		return nil, errors.Wrap(err, "could not marshal placement")
+	} else if _, err = buf.Write(data); err != nil {
+		return nil, errors.Wrap(err, "could not write placement")
+	}
+
+	return buf.Bytes(), nil
+}
+
+// PrepareData prepares bytes representation of DeleteRequest to satisfy SignedRequest interface.
+func (m *DeleteRequest) PrepareData() ([]byte, error) {
+	return m.CID.Bytes(), nil
+}
diff --git a/container/service.pb.go b/container/service.pb.go
new file mode 100644
index 00000000..bc2e8315
--- /dev/null
+++ b/container/service.pb.go
@@ -0,0 +1,2131 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: container/service.proto
+
+package container
+
+import (
+	context "context"
+	fmt "fmt"
+	_ "github.com/gogo/protobuf/gogoproto"
+	proto "github.com/golang/protobuf/proto"
+	netmap "github.com/nspcc-dev/netmap"
+	grpc "google.golang.org/grpc"
+	codes "google.golang.org/grpc/codes"
+	status "google.golang.org/grpc/status"
+	io "io"
+	math "math"
+	math_bits "math/bits"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
+
+// NewRequest message to create new container
+type PutRequest struct {
+	MessageID            MessageID            `protobuf:"bytes,1,opt,name=MessageID,proto3,customtype=MessageID" json:"MessageID"`
+	Capacity             uint64               `protobuf:"varint,2,opt,name=Capacity,proto3" json:"Capacity,omitempty"`
+	OwnerID              OwnerID              `protobuf:"bytes,3,opt,name=OwnerID,proto3,customtype=OwnerID" json:"OwnerID"`
+	Rules                netmap.PlacementRule `protobuf:"bytes,4,opt,name=rules,proto3" json:"rules"`
+	Signature            []byte               `protobuf:"bytes,5,opt,name=Signature,proto3" json:"Signature,omitempty"`
+	TTL                  uint32               `protobuf:"varint,6,opt,name=TTL,proto3" json:"TTL,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}             `json:"-"`
+	XXX_unrecognized     []byte               `json:"-"`
+	XXX_sizecache        int32                `json:"-"`
+}
+
+func (m *PutRequest) Reset()         { *m = PutRequest{} }
+func (m *PutRequest) String() string { return proto.CompactTextString(m) }
+func (*PutRequest) ProtoMessage()    {}
+func (*PutRequest) Descriptor() ([]byte, []int) {
+	return fileDescriptor_e1fa9d7ab2e7ae06, []int{0}
+}
+func (m *PutRequest) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *PutRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *PutRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_PutRequest.Merge(m, src)
+}
+func (m *PutRequest) XXX_Size() int {
+	return m.Size()
+}
+func (m *PutRequest) XXX_DiscardUnknown() {
+	xxx_messageInfo_PutRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_PutRequest proto.InternalMessageInfo
+
+func (m *PutRequest) GetCapacity() uint64 {
+	if m != nil {
+		return m.Capacity
+	}
+	return 0
+}
+
+func (m *PutRequest) GetRules() netmap.PlacementRule {
+	if m != nil {
+		return m.Rules
+	}
+	return netmap.PlacementRule{}
+}
+
+func (m *PutRequest) GetSignature() []byte {
+	if m != nil {
+		return m.Signature
+	}
+	return nil
+}
+
+func (m *PutRequest) GetTTL() uint32 {
+	if m != nil {
+		return m.TTL
+	}
+	return 0
+}
+
+// PutResponse message to respond about container uuid
+type PutResponse struct {
+	CID                  CID      `protobuf:"bytes,1,opt,name=CID,proto3,customtype=CID" json:"CID"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *PutResponse) Reset()         { *m = PutResponse{} }
+func (m *PutResponse) String() string { return proto.CompactTextString(m) }
+func (*PutResponse) ProtoMessage()    {}
+func (*PutResponse) Descriptor() ([]byte, []int) {
+	return fileDescriptor_e1fa9d7ab2e7ae06, []int{1}
+}
+func (m *PutResponse) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *PutResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *PutResponse) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_PutResponse.Merge(m, src)
+}
+func (m *PutResponse) XXX_Size() int {
+	return m.Size()
+}
+func (m *PutResponse) XXX_DiscardUnknown() {
+	xxx_messageInfo_PutResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_PutResponse proto.InternalMessageInfo
+
+type DeleteRequest struct {
+	CID                  CID      `protobuf:"bytes,1,opt,name=CID,proto3,customtype=CID" json:"CID"`
+	TTL                  uint32   `protobuf:"varint,2,opt,name=TTL,proto3" json:"TTL,omitempty"`
+	Signature            []byte   `protobuf:"bytes,3,opt,name=Signature,proto3" json:"Signature,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *DeleteRequest) Reset()         { *m = DeleteRequest{} }
+func (m *DeleteRequest) String() string { return proto.CompactTextString(m) }
+func (*DeleteRequest) ProtoMessage()    {}
+func (*DeleteRequest) Descriptor() ([]byte, []int) {
+	return fileDescriptor_e1fa9d7ab2e7ae06, []int{2}
+}
+func (m *DeleteRequest) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *DeleteRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *DeleteRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_DeleteRequest.Merge(m, src)
+}
+func (m *DeleteRequest) XXX_Size() int {
+	return m.Size()
+}
+func (m *DeleteRequest) XXX_DiscardUnknown() {
+	xxx_messageInfo_DeleteRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_DeleteRequest proto.InternalMessageInfo
+
+func (m *DeleteRequest) GetTTL() uint32 {
+	if m != nil {
+		return m.TTL
+	}
+	return 0
+}
+
+func (m *DeleteRequest) GetSignature() []byte {
+	if m != nil {
+		return m.Signature
+	}
+	return nil
+}
+
+type DeleteResponse struct {
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *DeleteResponse) Reset()         { *m = DeleteResponse{} }
+func (m *DeleteResponse) String() string { return proto.CompactTextString(m) }
+func (*DeleteResponse) ProtoMessage()    {}
+func (*DeleteResponse) Descriptor() ([]byte, []int) {
+	return fileDescriptor_e1fa9d7ab2e7ae06, []int{3}
+}
+func (m *DeleteResponse) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *DeleteResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *DeleteResponse) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_DeleteResponse.Merge(m, src)
+}
+func (m *DeleteResponse) XXX_Size() int {
+	return m.Size()
+}
+func (m *DeleteResponse) XXX_DiscardUnknown() {
+	xxx_messageInfo_DeleteResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_DeleteResponse proto.InternalMessageInfo
+
+// GetRequest message to fetch container placement rules
+type GetRequest struct {
+	CID                  CID      `protobuf:"bytes,1,opt,name=CID,proto3,customtype=CID" json:"CID"`
+	TTL                  uint32   `protobuf:"varint,2,opt,name=TTL,proto3" json:"TTL,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *GetRequest) Reset()         { *m = GetRequest{} }
+func (m *GetRequest) String() string { return proto.CompactTextString(m) }
+func (*GetRequest) ProtoMessage()    {}
+func (*GetRequest) Descriptor() ([]byte, []int) {
+	return fileDescriptor_e1fa9d7ab2e7ae06, []int{4}
+}
+func (m *GetRequest) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *GetRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *GetRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_GetRequest.Merge(m, src)
+}
+func (m *GetRequest) XXX_Size() int {
+	return m.Size()
+}
+func (m *GetRequest) XXX_DiscardUnknown() {
+	xxx_messageInfo_GetRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetRequest proto.InternalMessageInfo
+
+func (m *GetRequest) GetTTL() uint32 {
+	if m != nil {
+		return m.TTL
+	}
+	return 0
+}
+
+// GetResponse message with container structure
+type GetResponse struct {
+	Container            *Container `protobuf:"bytes,1,opt,name=Container,proto3" json:"Container,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}   `json:"-"`
+	XXX_unrecognized     []byte     `json:"-"`
+	XXX_sizecache        int32      `json:"-"`
+}
+
+func (m *GetResponse) Reset()         { *m = GetResponse{} }
+func (m *GetResponse) String() string { return proto.CompactTextString(m) }
+func (*GetResponse) ProtoMessage()    {}
+func (*GetResponse) Descriptor() ([]byte, []int) {
+	return fileDescriptor_e1fa9d7ab2e7ae06, []int{5}
+}
+func (m *GetResponse) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *GetResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *GetResponse) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_GetResponse.Merge(m, src)
+}
+func (m *GetResponse) XXX_Size() int {
+	return m.Size()
+}
+func (m *GetResponse) XXX_DiscardUnknown() {
+	xxx_messageInfo_GetResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetResponse proto.InternalMessageInfo
+
+func (m *GetResponse) GetContainer() *Container {
+	if m != nil {
+		return m.Container
+	}
+	return nil
+}
+
+// ListRequest message to list containers for user
+type ListRequest struct {
+	OwnerID              OwnerID  `protobuf:"bytes,1,opt,name=OwnerID,proto3,customtype=OwnerID" json:"OwnerID"`
+	TTL                  uint32   `protobuf:"varint,2,opt,name=TTL,proto3" json:"TTL,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *ListRequest) Reset()         { *m = ListRequest{} }
+func (m *ListRequest) String() string { return proto.CompactTextString(m) }
+func (*ListRequest) ProtoMessage()    {}
+func (*ListRequest) Descriptor() ([]byte, []int) {
+	return fileDescriptor_e1fa9d7ab2e7ae06, []int{6}
+}
+func (m *ListRequest) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *ListRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *ListRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_ListRequest.Merge(m, src)
+}
+func (m *ListRequest) XXX_Size() int {
+	return m.Size()
+}
+func (m *ListRequest) XXX_DiscardUnknown() {
+	xxx_messageInfo_ListRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ListRequest proto.InternalMessageInfo
+
+func (m *ListRequest) GetTTL() uint32 {
+	if m != nil {
+		return m.TTL
+	}
+	return 0
+}
+
+// ListResponse message to respond about all user containers
+type ListResponse struct {
+	CID                  []CID    `protobuf:"bytes,1,rep,name=CID,proto3,customtype=CID" json:"CID"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *ListResponse) Reset()         { *m = ListResponse{} }
+func (m *ListResponse) String() string { return proto.CompactTextString(m) }
+func (*ListResponse) ProtoMessage()    {}
+func (*ListResponse) Descriptor() ([]byte, []int) {
+	return fileDescriptor_e1fa9d7ab2e7ae06, []int{7}
+}
+func (m *ListResponse) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *ListResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *ListResponse) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_ListResponse.Merge(m, src)
+}
+func (m *ListResponse) XXX_Size() int {
+	return m.Size()
+}
+func (m *ListResponse) XXX_DiscardUnknown() {
+	xxx_messageInfo_ListResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ListResponse proto.InternalMessageInfo
+
+func init() {
+	proto.RegisterType((*PutRequest)(nil), "container.PutRequest")
+	proto.RegisterType((*PutResponse)(nil), "container.PutResponse")
+	proto.RegisterType((*DeleteRequest)(nil), "container.DeleteRequest")
+	proto.RegisterType((*DeleteResponse)(nil), "container.DeleteResponse")
+	proto.RegisterType((*GetRequest)(nil), "container.GetRequest")
+	proto.RegisterType((*GetResponse)(nil), "container.GetResponse")
+	proto.RegisterType((*ListRequest)(nil), "container.ListRequest")
+	proto.RegisterType((*ListResponse)(nil), "container.ListResponse")
+}
+
+func init() { proto.RegisterFile("container/service.proto", fileDescriptor_e1fa9d7ab2e7ae06) }
+
+var fileDescriptor_e1fa9d7ab2e7ae06 = []byte{
+	// 520 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x53, 0xcf, 0x6e, 0xd3, 0x4e,
+	0x10, 0xee, 0xd6, 0x69, 0xfa, 0xcb, 0xb8, 0xfd, 0x51, 0x56, 0x84, 0x1a, 0x0b, 0xdc, 0xc8, 0xa7,
+	0x80, 0x88, 0x2d, 0x42, 0x25, 0x4e, 0x95, 0x20, 0x89, 0x54, 0x15, 0x15, 0x11, 0x6d, 0x7b, 0xe2,
+	0x80, 0xe4, 0x98, 0xa9, 0xb1, 0xe4, 0xd8, 0xc6, 0xbb, 0x2e, 0xea, 0x9b, 0xf0, 0x48, 0x3d, 0x72,
+	0x44, 0x1c, 0x2a, 0x14, 0x0e, 0x9c, 0x78, 0x07, 0x64, 0xaf, 0xff, 0x25, 0x2d, 0x20, 0x71, 0x59,
+	0xcd, 0xce, 0x7c, 0xf3, 0xcd, 0x37, 0x33, 0xbb, 0xb0, 0xeb, 0x46, 0xa1, 0x70, 0xfc, 0x10, 0x13,
+	0x9b, 0x63, 0x72, 0xee, 0xbb, 0x68, 0xc5, 0x49, 0x24, 0x22, 0xda, 0xa9, 0x02, 0x7a, 0xb7, 0xc6,
+	0x88, 0x8b, 0x18, 0xb9, 0x44, 0xe8, 0x8f, 0x3c, 0x5f, 0xbc, 0x4f, 0x67, 0x96, 0x1b, 0xcd, 0xed,
+	0x90, 0xc7, 0xae, 0x3b, 0x78, 0x87, 0xe7, 0x76, 0x88, 0x62, 0xee, 0xc4, 0x36, 0xc7, 0x00, 0x5d,
+	0x11, 0x25, 0x05, 0x76, 0xd0, 0xc0, 0x7a, 0x91, 0x17, 0xd9, 0xb9, 0x7b, 0x96, 0x9e, 0xe5, 0xb7,
+	0xfc, 0x92, 0x5b, 0x12, 0x6e, 0xfe, 0x20, 0x00, 0xd3, 0x54, 0x30, 0xfc, 0x90, 0x22, 0x17, 0xd4,
+	0x86, 0xce, 0x2b, 0xe4, 0xdc, 0xf1, 0xf0, 0x68, 0xa2, 0x91, 0x1e, 0xe9, 0x6f, 0x8d, 0x6e, 0x5f,
+	0x5e, 0xed, 0xad, 0x7d, 0xbd, 0xda, 0xab, 0x03, 0xac, 0x36, 0xa9, 0x0e, 0xff, 0x8d, 0x9d, 0xd8,
+	0x71, 0x7d, 0x71, 0xa1, 0xad, 0xf7, 0x48, 0xbf, 0xc5, 0xaa, 0x3b, 0x7d, 0x08, 0x9b, 0xaf, 0x3f,
+	0x86, 0x98, 0x1c, 0x4d, 0x34, 0x25, 0xa7, 0xba, 0x55, 0x50, 0x95, 0x6e, 0x56, 0x1a, 0xf4, 0x09,
+	0x6c, 0x24, 0x69, 0x80, 0x5c, 0x6b, 0xf5, 0x48, 0x5f, 0x1d, 0x76, 0x2d, 0xd9, 0x9c, 0x35, 0x0d,
+	0x1c, 0x17, 0xe7, 0x18, 0x0a, 0x96, 0x06, 0x38, 0x6a, 0x65, 0xf9, 0x4c, 0x22, 0xe9, 0x7d, 0xe8,
+	0x9c, 0xf8, 0x5e, 0xe8, 0x88, 0x34, 0x41, 0x6d, 0x23, 0xe3, 0x67, 0xb5, 0x83, 0xee, 0x80, 0x72,
+	0x7a, 0x7a, 0xac, 0xb5, 0x7b, 0xa4, 0xbf, 0xcd, 0x32, 0xd3, 0x7c, 0x0c, 0x6a, 0xde, 0x28, 0x8f,
+	0xa3, 0x90, 0x23, 0x7d, 0x00, 0xca, 0xb8, 0xea, 0x51, 0x2d, 0x84, 0x65, 0x2e, 0x96, 0x1d, 0xe6,
+	0x5b, 0xd8, 0x9e, 0x60, 0x80, 0x02, 0xcb, 0xc9, 0xfc, 0x19, 0x5f, 0xd6, 0x5b, 0xaf, 0xea, 0x2d,
+	0xeb, 0x53, 0x56, 0xf4, 0x99, 0x3b, 0xf0, 0x7f, 0xc9, 0x2f, 0x05, 0x99, 0x07, 0x00, 0x87, 0x28,
+	0xfe, 0xb5, 0x9c, 0xf9, 0x02, 0xd4, 0x3c, 0xbd, 0x68, 0x6f, 0x08, 0x9d, 0x71, 0xf9, 0x96, 0x72,
+	0x16, 0x75, 0x78, 0xc7, 0xaa, 0x5e, 0x97, 0x55, 0xc5, 0x58, 0x0d, 0x33, 0x5f, 0x82, 0x7a, 0xec,
+	0xf3, 0x4a, 0x42, 0x63, 0x7d, 0xe4, 0x2f, 0xeb, 0xbb, 0x2e, 0x67, 0x00, 0x5b, 0x92, 0x6b, 0x75,
+	0xdc, 0xca, 0x4d, 0xfd, 0x0c, 0x7f, 0x12, 0xd8, 0x3c, 0x91, 0xbf, 0x82, 0xee, 0x83, 0x32, 0x4d,
+	0x05, 0xed, 0x36, 0xe4, 0xd6, 0x2f, 0x54, 0xbf, 0xbb, 0xea, 0x2e, 0x0a, 0x1c, 0x40, 0x5b, 0x0e,
+	0x94, 0x6a, 0x0d, 0xc4, 0xd2, 0x0e, 0xf5, 0x7b, 0x37, 0x44, 0x8a, 0xf4, 0x7d, 0x50, 0x0e, 0x71,
+	0xb9, 0x68, 0xbd, 0x8d, 0xa5, 0xa2, 0xcd, 0x29, 0x3f, 0x83, 0x56, 0xd6, 0x25, 0x6d, 0xc6, 0x1b,
+	0x23, 0xd4, 0x77, 0xaf, 0xf9, 0x65, 0xe2, 0xe8, 0xf9, 0xe5, 0xc2, 0x20, 0x9f, 0x17, 0x06, 0xf9,
+	0xb2, 0x30, 0xc8, 0xb7, 0x85, 0x41, 0x3e, 0x7d, 0x37, 0xd6, 0xde, 0xfc, 0xee, 0x9f, 0x47, 0x67,
+	0x7c, 0x20, 0x7f, 0x6e, 0x45, 0x37, 0x6b, 0xe7, 0x8e, 0xa7, 0xbf, 0x02, 0x00, 0x00, 0xff, 0xff,
+	0xa3, 0xe9, 0x55, 0x5c, 0x57, 0x04, 0x00, 0x00,
+}
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ context.Context
+var _ grpc.ClientConn
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the grpc package it is being compiled against.
+const _ = grpc.SupportPackageIsVersion4
+
+// ServiceClient is the client API for Service service.
+//
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
+type ServiceClient interface {
+	// Create container
+	Put(ctx context.Context, in *PutRequest, opts ...grpc.CallOption) (*PutResponse, error)
+	// Delete container ... discuss implementation later
+	Delete(ctx context.Context, in *DeleteRequest, opts ...grpc.CallOption) (*DeleteResponse, error)
+	// Get container
+	Get(ctx context.Context, in *GetRequest, opts ...grpc.CallOption) (*GetResponse, error)
+	List(ctx context.Context, in *ListRequest, opts ...grpc.CallOption) (*ListResponse, error)
+}
+
+type serviceClient struct {
+	cc *grpc.ClientConn
+}
+
+func NewServiceClient(cc *grpc.ClientConn) ServiceClient {
+	return &serviceClient{cc}
+}
+
+func (c *serviceClient) Put(ctx context.Context, in *PutRequest, opts ...grpc.CallOption) (*PutResponse, error) {
+	out := new(PutResponse)
+	err := c.cc.Invoke(ctx, "/container.Service/Put", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *serviceClient) Delete(ctx context.Context, in *DeleteRequest, opts ...grpc.CallOption) (*DeleteResponse, error) {
+	out := new(DeleteResponse)
+	err := c.cc.Invoke(ctx, "/container.Service/Delete", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *serviceClient) Get(ctx context.Context, in *GetRequest, opts ...grpc.CallOption) (*GetResponse, error) {
+	out := new(GetResponse)
+	err := c.cc.Invoke(ctx, "/container.Service/Get", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *serviceClient) List(ctx context.Context, in *ListRequest, opts ...grpc.CallOption) (*ListResponse, error) {
+	out := new(ListResponse)
+	err := c.cc.Invoke(ctx, "/container.Service/List", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+// ServiceServer is the server API for Service service.
+type ServiceServer interface {
+	// Create container
+	Put(context.Context, *PutRequest) (*PutResponse, error)
+	// Delete container ... discuss implementation later
+	Delete(context.Context, *DeleteRequest) (*DeleteResponse, error)
+	// Get container
+	Get(context.Context, *GetRequest) (*GetResponse, error)
+	List(context.Context, *ListRequest) (*ListResponse, error)
+}
+
+// UnimplementedServiceServer can be embedded to have forward compatible implementations.
+type UnimplementedServiceServer struct {
+}
+
+func (*UnimplementedServiceServer) Put(ctx context.Context, req *PutRequest) (*PutResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method Put not implemented")
+}
+func (*UnimplementedServiceServer) Delete(ctx context.Context, req *DeleteRequest) (*DeleteResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method Delete not implemented")
+}
+func (*UnimplementedServiceServer) Get(ctx context.Context, req *GetRequest) (*GetResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method Get not implemented")
+}
+func (*UnimplementedServiceServer) List(ctx context.Context, req *ListRequest) (*ListResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method List not implemented")
+}
+
+func RegisterServiceServer(s *grpc.Server, srv ServiceServer) {
+	s.RegisterService(&_Service_serviceDesc, srv)
+}
+
+func _Service_Put_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(PutRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(ServiceServer).Put(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/container.Service/Put",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(ServiceServer).Put(ctx, req.(*PutRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _Service_Delete_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(DeleteRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(ServiceServer).Delete(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/container.Service/Delete",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(ServiceServer).Delete(ctx, req.(*DeleteRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _Service_Get_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(GetRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(ServiceServer).Get(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/container.Service/Get",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(ServiceServer).Get(ctx, req.(*GetRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _Service_List_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(ListRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(ServiceServer).List(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/container.Service/List",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(ServiceServer).List(ctx, req.(*ListRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+var _Service_serviceDesc = grpc.ServiceDesc{
+	ServiceName: "container.Service",
+	HandlerType: (*ServiceServer)(nil),
+	Methods: []grpc.MethodDesc{
+		{
+			MethodName: "Put",
+			Handler:    _Service_Put_Handler,
+		},
+		{
+			MethodName: "Delete",
+			Handler:    _Service_Delete_Handler,
+		},
+		{
+			MethodName: "Get",
+			Handler:    _Service_Get_Handler,
+		},
+		{
+			MethodName: "List",
+			Handler:    _Service_List_Handler,
+		},
+	},
+	Streams:  []grpc.StreamDesc{},
+	Metadata: "container/service.proto",
+}
+
+func (m *PutRequest) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *PutRequest) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *PutRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if m.TTL != 0 {
+		i = encodeVarintService(dAtA, i, uint64(m.TTL))
+		i--
+		dAtA[i] = 0x30
+	}
+	if len(m.Signature) > 0 {
+		i -= len(m.Signature)
+		copy(dAtA[i:], m.Signature)
+		i = encodeVarintService(dAtA, i, uint64(len(m.Signature)))
+		i--
+		dAtA[i] = 0x2a
+	}
+	{
+		size, err := m.Rules.MarshalToSizedBuffer(dAtA[:i])
+		if err != nil {
+			return 0, err
+		}
+		i -= size
+		i = encodeVarintService(dAtA, i, uint64(size))
+	}
+	i--
+	dAtA[i] = 0x22
+	{
+		size := m.OwnerID.Size()
+		i -= size
+		if _, err := m.OwnerID.MarshalTo(dAtA[i:]); err != nil {
+			return 0, err
+		}
+		i = encodeVarintService(dAtA, i, uint64(size))
+	}
+	i--
+	dAtA[i] = 0x1a
+	if m.Capacity != 0 {
+		i = encodeVarintService(dAtA, i, uint64(m.Capacity))
+		i--
+		dAtA[i] = 0x10
+	}
+	{
+		size := m.MessageID.Size()
+		i -= size
+		if _, err := m.MessageID.MarshalTo(dAtA[i:]); err != nil {
+			return 0, err
+		}
+		i = encodeVarintService(dAtA, i, uint64(size))
+	}
+	i--
+	dAtA[i] = 0xa
+	return len(dAtA) - i, nil
+}
+
+func (m *PutResponse) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *PutResponse) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *PutResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	{
+		size := m.CID.Size()
+		i -= size
+		if _, err := m.CID.MarshalTo(dAtA[i:]); err != nil {
+			return 0, err
+		}
+		i = encodeVarintService(dAtA, i, uint64(size))
+	}
+	i--
+	dAtA[i] = 0xa
+	return len(dAtA) - i, nil
+}
+
+func (m *DeleteRequest) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *DeleteRequest) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *DeleteRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if len(m.Signature) > 0 {
+		i -= len(m.Signature)
+		copy(dAtA[i:], m.Signature)
+		i = encodeVarintService(dAtA, i, uint64(len(m.Signature)))
+		i--
+		dAtA[i] = 0x1a
+	}
+	if m.TTL != 0 {
+		i = encodeVarintService(dAtA, i, uint64(m.TTL))
+		i--
+		dAtA[i] = 0x10
+	}
+	{
+		size := m.CID.Size()
+		i -= size
+		if _, err := m.CID.MarshalTo(dAtA[i:]); err != nil {
+			return 0, err
+		}
+		i = encodeVarintService(dAtA, i, uint64(size))
+	}
+	i--
+	dAtA[i] = 0xa
+	return len(dAtA) - i, nil
+}
+
+func (m *DeleteResponse) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *DeleteResponse) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *DeleteResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *GetRequest) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *GetRequest) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *GetRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if m.TTL != 0 {
+		i = encodeVarintService(dAtA, i, uint64(m.TTL))
+		i--
+		dAtA[i] = 0x10
+	}
+	{
+		size := m.CID.Size()
+		i -= size
+		if _, err := m.CID.MarshalTo(dAtA[i:]); err != nil {
+			return 0, err
+		}
+		i = encodeVarintService(dAtA, i, uint64(size))
+	}
+	i--
+	dAtA[i] = 0xa
+	return len(dAtA) - i, nil
+}
+
+func (m *GetResponse) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *GetResponse) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *GetResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if m.Container != nil {
+		{
+			size, err := m.Container.MarshalToSizedBuffer(dAtA[:i])
+			if err != nil {
+				return 0, err
+			}
+			i -= size
+			i = encodeVarintService(dAtA, i, uint64(size))
+		}
+		i--
+		dAtA[i] = 0xa
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *ListRequest) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *ListRequest) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *ListRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if m.TTL != 0 {
+		i = encodeVarintService(dAtA, i, uint64(m.TTL))
+		i--
+		dAtA[i] = 0x10
+	}
+	{
+		size := m.OwnerID.Size()
+		i -= size
+		if _, err := m.OwnerID.MarshalTo(dAtA[i:]); err != nil {
+			return 0, err
+		}
+		i = encodeVarintService(dAtA, i, uint64(size))
+	}
+	i--
+	dAtA[i] = 0xa
+	return len(dAtA) - i, nil
+}
+
+func (m *ListResponse) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *ListResponse) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *ListResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if len(m.CID) > 0 {
+		for iNdEx := len(m.CID) - 1; iNdEx >= 0; iNdEx-- {
+			{
+				size := m.CID[iNdEx].Size()
+				i -= size
+				if _, err := m.CID[iNdEx].MarshalTo(dAtA[i:]); err != nil {
+					return 0, err
+				}
+				i = encodeVarintService(dAtA, i, uint64(size))
+			}
+			i--
+			dAtA[i] = 0xa
+		}
+	}
+	return len(dAtA) - i, nil
+}
+
+func encodeVarintService(dAtA []byte, offset int, v uint64) int {
+	offset -= sovService(v)
+	base := offset
+	for v >= 1<<7 {
+		dAtA[offset] = uint8(v&0x7f | 0x80)
+		v >>= 7
+		offset++
+	}
+	dAtA[offset] = uint8(v)
+	return base
+}
+func (m *PutRequest) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = m.MessageID.Size()
+	n += 1 + l + sovService(uint64(l))
+	if m.Capacity != 0 {
+		n += 1 + sovService(uint64(m.Capacity))
+	}
+	l = m.OwnerID.Size()
+	n += 1 + l + sovService(uint64(l))
+	l = m.Rules.Size()
+	n += 1 + l + sovService(uint64(l))
+	l = len(m.Signature)
+	if l > 0 {
+		n += 1 + l + sovService(uint64(l))
+	}
+	if m.TTL != 0 {
+		n += 1 + sovService(uint64(m.TTL))
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *PutResponse) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = m.CID.Size()
+	n += 1 + l + sovService(uint64(l))
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *DeleteRequest) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = m.CID.Size()
+	n += 1 + l + sovService(uint64(l))
+	if m.TTL != 0 {
+		n += 1 + sovService(uint64(m.TTL))
+	}
+	l = len(m.Signature)
+	if l > 0 {
+		n += 1 + l + sovService(uint64(l))
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *DeleteResponse) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *GetRequest) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = m.CID.Size()
+	n += 1 + l + sovService(uint64(l))
+	if m.TTL != 0 {
+		n += 1 + sovService(uint64(m.TTL))
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *GetResponse) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.Container != nil {
+		l = m.Container.Size()
+		n += 1 + l + sovService(uint64(l))
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *ListRequest) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = m.OwnerID.Size()
+	n += 1 + l + sovService(uint64(l))
+	if m.TTL != 0 {
+		n += 1 + sovService(uint64(m.TTL))
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *ListResponse) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if len(m.CID) > 0 {
+		for _, e := range m.CID {
+			l = e.Size()
+			n += 1 + l + sovService(uint64(l))
+		}
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func sovService(x uint64) (n int) {
+	return (math_bits.Len64(x|1) + 6) / 7
+}
+func sozService(x uint64) (n int) {
+	return sovService(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+func (m *PutRequest) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowService
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: PutRequest: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: PutRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field MessageID", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthService
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthService
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.MessageID.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 2:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Capacity", wireType)
+			}
+			m.Capacity = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.Capacity |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		case 3:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field OwnerID", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthService
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthService
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.OwnerID.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 4:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Rules", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthService
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthService
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.Rules.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 5:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Signature", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthService
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthService
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Signature = append(m.Signature[:0], dAtA[iNdEx:postIndex]...)
+			if m.Signature == nil {
+				m.Signature = []byte{}
+			}
+			iNdEx = postIndex
+		case 6:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field TTL", wireType)
+			}
+			m.TTL = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.TTL |= uint32(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		default:
+			iNdEx = preIndex
+			skippy, err := skipService(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *PutResponse) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowService
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: PutResponse: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: PutResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field CID", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthService
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthService
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.CID.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipService(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *DeleteRequest) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowService
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: DeleteRequest: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: DeleteRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field CID", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthService
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthService
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.CID.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 2:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field TTL", wireType)
+			}
+			m.TTL = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.TTL |= uint32(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		case 3:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Signature", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthService
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthService
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Signature = append(m.Signature[:0], dAtA[iNdEx:postIndex]...)
+			if m.Signature == nil {
+				m.Signature = []byte{}
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipService(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *DeleteResponse) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowService
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: DeleteResponse: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: DeleteResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		default:
+			iNdEx = preIndex
+			skippy, err := skipService(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *GetRequest) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowService
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: GetRequest: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: GetRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field CID", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthService
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthService
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.CID.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 2:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field TTL", wireType)
+			}
+			m.TTL = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.TTL |= uint32(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		default:
+			iNdEx = preIndex
+			skippy, err := skipService(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *GetResponse) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowService
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: GetResponse: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: GetResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Container", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthService
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthService
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if m.Container == nil {
+				m.Container = &Container{}
+			}
+			if err := m.Container.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipService(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *ListRequest) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowService
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: ListRequest: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: ListRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field OwnerID", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthService
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthService
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.OwnerID.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 2:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field TTL", wireType)
+			}
+			m.TTL = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.TTL |= uint32(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		default:
+			iNdEx = preIndex
+			skippy, err := skipService(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *ListResponse) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowService
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: ListResponse: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: ListResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field CID", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthService
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthService
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			var v CID
+			m.CID = append(m.CID, v)
+			if err := m.CID[len(m.CID)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipService(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func skipService(dAtA []byte) (n int, err error) {
+	l := len(dAtA)
+	iNdEx := 0
+	depth := 0
+	for iNdEx < l {
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return 0, ErrIntOverflowService
+			}
+			if iNdEx >= l {
+				return 0, io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= (uint64(b) & 0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		wireType := int(wire & 0x7)
+		switch wireType {
+		case 0:
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return 0, ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return 0, io.ErrUnexpectedEOF
+				}
+				iNdEx++
+				if dAtA[iNdEx-1] < 0x80 {
+					break
+				}
+			}
+		case 1:
+			iNdEx += 8
+		case 2:
+			var length int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return 0, ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return 0, io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				length |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if length < 0 {
+				return 0, ErrInvalidLengthService
+			}
+			iNdEx += length
+		case 3:
+			depth++
+		case 4:
+			if depth == 0 {
+				return 0, ErrUnexpectedEndOfGroupService
+			}
+			depth--
+		case 5:
+			iNdEx += 4
+		default:
+			return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+		}
+		if iNdEx < 0 {
+			return 0, ErrInvalidLengthService
+		}
+		if depth == 0 {
+			return iNdEx, nil
+		}
+	}
+	return 0, io.ErrUnexpectedEOF
+}
+
+var (
+	ErrInvalidLengthService        = fmt.Errorf("proto: negative length found during unmarshaling")
+	ErrIntOverflowService          = fmt.Errorf("proto: integer overflow")
+	ErrUnexpectedEndOfGroupService = fmt.Errorf("proto: unexpected end of group")
+)
diff --git a/container/service.proto b/container/service.proto
new file mode 100644
index 00000000..a3b72ca8
--- /dev/null
+++ b/container/service.proto
@@ -0,0 +1,68 @@
+syntax = "proto3";
+package container;
+option go_package = "github.com/nspcc-dev/neofs-proto/container";
+
+import "container/types.proto";
+import "github.com/nspcc-dev/netmap/selector.proto";
+import "github.com/gogo/protobuf/gogoproto/gogo.proto";
+
+option (gogoproto.stable_marshaler_all) = true;
+
+service Service {
+    // Create container
+    rpc Put(PutRequest) returns (PutResponse);
+
+    // Delete container ... discuss implementation later
+    rpc Delete(DeleteRequest) returns (DeleteResponse);
+
+    // Get container
+    rpc Get(GetRequest) returns (GetResponse);
+
+    rpc List(ListRequest) returns (ListResponse);
+}
+
+// NewRequest message to create new container
+message PutRequest {
+    bytes MessageID            = 1 [(gogoproto.customtype) = "MessageID", (gogoproto.nullable) = false];
+    uint64 Capacity            = 2; // not actual size in megabytes, but probability of storage availability
+    bytes OwnerID              = 3 [(gogoproto.customtype) = "OwnerID", (gogoproto.nullable) = false];
+    netmap.PlacementRule rules = 4 [(gogoproto.nullable) = false];
+    bytes Signature            = 5;
+    uint32 TTL                 = 6;
+}
+
+// PutResponse message to respond about container uuid
+message PutResponse {
+    bytes CID = 1 [(gogoproto.customtype) = "CID", (gogoproto.nullable) = false];
+}
+
+message DeleteRequest {
+    bytes CID       = 1 [(gogoproto.customtype) = "CID", (gogoproto.nullable) = false];
+    uint32 TTL      = 2;
+    bytes Signature = 3;
+}
+
+message DeleteResponse { }
+
+
+// GetRequest message to fetch container placement rules
+message GetRequest {
+    bytes CID  = 1 [(gogoproto.customtype) = "CID", (gogoproto.nullable) = false];
+    uint32 TTL = 2;
+}
+
+// GetResponse message with container structure
+message GetResponse {
+    container.Container Container = 1;
+}
+
+// ListRequest message to list containers for user
+message ListRequest {
+    bytes OwnerID = 1 [(gogoproto.customtype) = "OwnerID", (gogoproto.nullable) = false];
+    uint32 TTL    = 2;
+}
+
+// ListResponse message to respond about all user containers
+message ListResponse {
+    repeated bytes CID = 1 [(gogoproto.customtype) = "CID", (gogoproto.nullable) = false];
+}
diff --git a/container/types.go b/container/types.go
new file mode 100644
index 00000000..1ffcafe6
--- /dev/null
+++ b/container/types.go
@@ -0,0 +1,94 @@
+package container
+
+import (
+	"bytes"
+
+	"github.com/google/uuid"
+	"github.com/nspcc-dev/neofs-crypto/test"
+	"github.com/nspcc-dev/neofs-proto/internal"
+	"github.com/nspcc-dev/neofs-proto/refs"
+	"github.com/nspcc-dev/netmap"
+	"github.com/pkg/errors"
+)
+
+var (
+	_ internal.Custom = (*Container)(nil)
+
+	emptySalt  = (UUID{}).Bytes()
+	emptyOwner = (OwnerID{}).Bytes()
+)
+
+// New creates new user container based on capacity, OwnerID and PlacementRules.
+func New(cap uint64, owner OwnerID, rules netmap.PlacementRule) (*Container, error) {
+	if bytes.Equal(owner[:], emptyOwner) {
+		return nil, refs.ErrEmptyOwner
+	} else if cap == 0 {
+		return nil, refs.ErrEmptyCapacity
+	}
+
+	salt, err := uuid.NewRandom()
+	if err != nil {
+		return nil, errors.Wrap(err, "could not create salt")
+	}
+
+	return &Container{
+		OwnerID:  owner,
+		Salt:     UUID(salt),
+		Capacity: cap,
+		Rules:    rules,
+	}, nil
+}
+
+// Bytes returns bytes representation of Container.
+func (m *Container) Bytes() []byte {
+	data, err := m.Marshal()
+	if err != nil {
+		return nil
+	}
+
+	return data
+}
+
+// ID returns generated ContainerID based on Container (data).
+func (m *Container) ID() (CID, error) {
+	if m.Empty() {
+		return CID{}, refs.ErrEmptyContainer
+	}
+	data, err := m.Marshal()
+	if err != nil {
+		return CID{}, err
+	}
+
+	return refs.CIDForBytes(data), nil
+}
+
+// Empty checks that container is empty.
+func (m *Container) Empty() bool {
+	return m.Capacity == 0 || bytes.Equal(m.Salt.Bytes(), emptySalt) || bytes.Equal(m.OwnerID.Bytes(), emptyOwner)
+}
+
+// -- Test container definition -- //
+// NewTestContainer returns test container.
+//
+// WARNING: DON'T USE THIS OUTSIDE TESTS.
+func NewTestContainer() (*Container, error) {
+	key := test.DecodeKey(0)
+	owner, err := refs.NewOwnerID(&key.PublicKey)
+	if err != nil {
+		return nil, err
+	}
+	return New(100, owner, netmap.PlacementRule{
+		ReplFactor: 2,
+		SFGroups: []netmap.SFGroup{
+			{
+				Selectors: []netmap.Select{
+					{Key: "Country", Count: 1},
+					{Key: netmap.NodesBucket, Count: 2},
+				},
+				Filters: []netmap.Filter{
+					{Key: "Country", F: netmap.FilterIn("USA")},
+				},
+			},
+		},
+	})
+}
diff --git a/container/types.pb.go b/container/types.pb.go
new file mode 100644
index 00000000..8c4775cc
--- /dev/null
+++ b/container/types.pb.go
@@ -0,0 +1,464 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: container/types.proto
+
+package container
+
+import (
+	fmt "fmt"
+	_ "github.com/gogo/protobuf/gogoproto"
+	proto "github.com/golang/protobuf/proto"
+	netmap "github.com/nspcc-dev/netmap"
+	io "io"
+	math "math"
+	math_bits "math/bits"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
+
+// The Container service definition.
+type Container struct {
+	OwnerID              OwnerID              `protobuf:"bytes,1,opt,name=OwnerID,proto3,customtype=OwnerID" json:"OwnerID"`
+	Salt                 UUID                 `protobuf:"bytes,2,opt,name=Salt,proto3,customtype=UUID" json:"Salt"`
+	Capacity             uint64               `protobuf:"varint,3,opt,name=Capacity,proto3" json:"Capacity,omitempty"`
+	Rules                netmap.PlacementRule `protobuf:"bytes,4,opt,name=Rules,proto3" json:"Rules"`
+	XXX_NoUnkeyedLiteral struct{}             `json:"-"`
+	XXX_unrecognized     []byte               `json:"-"`
+	XXX_sizecache        int32                `json:"-"`
+}
+
+func (m *Container) Reset()         { *m = Container{} }
+func (m *Container) String() string { return proto.CompactTextString(m) }
+func (*Container) ProtoMessage()    {}
+func (*Container) Descriptor() ([]byte, []int) {
+	return fileDescriptor_1432e52ab0b53e3e, []int{0}
+}
+func (m *Container) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *Container) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *Container) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Container.Merge(m, src)
+}
+func (m *Container) XXX_Size() int {
+	return m.Size()
+}
+func (m *Container) XXX_DiscardUnknown() {
+	xxx_messageInfo_Container.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Container proto.InternalMessageInfo
+
+func (m *Container) GetCapacity() uint64 {
+	if m != nil {
+		return m.Capacity
+	}
+	return 0
+}
+
+func (m *Container) GetRules() netmap.PlacementRule {
+	if m != nil {
+		return m.Rules
+	}
+	return netmap.PlacementRule{}
+}
+
+func init() {
+	proto.RegisterType((*Container)(nil), "container.Container")
+}
+
+func init() { proto.RegisterFile("container/types.proto", fileDescriptor_1432e52ab0b53e3e) }
+
+var fileDescriptor_1432e52ab0b53e3e = []byte{
+	// 275 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x4d, 0xce, 0xcf, 0x2b,
+	0x49, 0xcc, 0xcc, 0x4b, 0x2d, 0xd2, 0x2f, 0xa9, 0x2c, 0x48, 0x2d, 0xd6, 0x2b, 0x28, 0xca, 0x2f,
+	0xc9, 0x17, 0xe2, 0x84, 0x0b, 0x4b, 0x69, 0xa5, 0x67, 0x96, 0x64, 0x94, 0x26, 0xe9, 0x25, 0xe7,
+	0xe7, 0xea, 0xe7, 0x15, 0x17, 0x24, 0x27, 0xeb, 0xa6, 0xa4, 0x96, 0xe9, 0xe7, 0xa5, 0x96, 0xe4,
+	0x26, 0x16, 0xe8, 0x17, 0xa7, 0xe6, 0xa4, 0x26, 0x97, 0xe4, 0x17, 0x41, 0xb4, 0x49, 0xe9, 0x22,
+	0xa9, 0x4d, 0xcf, 0x4f, 0xcf, 0xd7, 0x07, 0x0b, 0x27, 0x95, 0xa6, 0x81, 0x79, 0x60, 0x0e, 0x98,
+	0x05, 0x51, 0xae, 0xb4, 0x9c, 0x91, 0x8b, 0xd3, 0x19, 0x66, 0x91, 0x90, 0x26, 0x17, 0xbb, 0x7f,
+	0x79, 0x5e, 0x6a, 0x91, 0xa7, 0x8b, 0x04, 0xa3, 0x02, 0xa3, 0x06, 0x8f, 0x13, 0xff, 0x89, 0x7b,
+	0xf2, 0x0c, 0xb7, 0xee, 0xc9, 0xc3, 0x84, 0x83, 0x60, 0x0c, 0x21, 0x05, 0x2e, 0x96, 0xe0, 0xc4,
+	0x9c, 0x12, 0x09, 0x26, 0xb0, 0x3a, 0x1e, 0xa8, 0x3a, 0x96, 0xd0, 0x50, 0x4f, 0x97, 0x20, 0xb0,
+	0x8c, 0x90, 0x14, 0x17, 0x87, 0x73, 0x62, 0x41, 0x62, 0x72, 0x66, 0x49, 0xa5, 0x04, 0xb3, 0x02,
+	0xa3, 0x06, 0x4b, 0x10, 0x9c, 0x2f, 0x64, 0xc8, 0xc5, 0x1a, 0x54, 0x9a, 0x93, 0x5a, 0x2c, 0xc1,
+	0xa2, 0xc0, 0xa8, 0xc1, 0x6d, 0x24, 0xaa, 0x07, 0xf1, 0x8c, 0x5e, 0x40, 0x4e, 0x62, 0x72, 0x6a,
+	0x6e, 0x6a, 0x5e, 0x09, 0x48, 0xd6, 0x89, 0x05, 0x64, 0x6a, 0x10, 0x44, 0xa5, 0x93, 0xc3, 0x89,
+	0x47, 0x72, 0x8c, 0x17, 0x1e, 0xc9, 0x31, 0xde, 0x78, 0x24, 0xc7, 0xf8, 0xe0, 0x91, 0x1c, 0xe3,
+	0x8c, 0xc7, 0x72, 0x0c, 0x51, 0xb8, 0x82, 0x26, 0x3f, 0xad, 0x58, 0x17, 0xe2, 0x59, 0x78, 0x30,
+	0x26, 0xb1, 0x81, 0x05, 0x8c, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0x29, 0x6b, 0x4d, 0x08, 0x71,
+	0x01, 0x00, 0x00,
+}
+
+func (m *Container) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *Container) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *Container) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	{
+		size, err := m.Rules.MarshalToSizedBuffer(dAtA[:i])
+		if err != nil {
+			return 0, err
+		}
+		i -= size
+		i = encodeVarintTypes(dAtA, i, uint64(size))
+	}
+	i--
+	dAtA[i] = 0x22
+	if m.Capacity != 0 {
+		i = encodeVarintTypes(dAtA, i, uint64(m.Capacity))
+		i--
+		dAtA[i] = 0x18
+	}
+	{
+		size := m.Salt.Size()
+		i -= size
+		if _, err := m.Salt.MarshalTo(dAtA[i:]); err != nil {
+			return 0, err
+		}
+		i = encodeVarintTypes(dAtA, i, uint64(size))
+	}
+	i--
+	dAtA[i] = 0x12
+	{
+		size := m.OwnerID.Size()
+		i -= size
+		if _, err := m.OwnerID.MarshalTo(dAtA[i:]); err != nil {
+			return 0, err
+		}
+		i = encodeVarintTypes(dAtA, i, uint64(size))
+	}
+	i--
+	dAtA[i] = 0xa
+	return len(dAtA) - i, nil
+}
+
+func encodeVarintTypes(dAtA []byte, offset int, v uint64) int {
+	offset -= sovTypes(v)
+	base := offset
+	for v >= 1<<7 {
+		dAtA[offset] = uint8(v&0x7f | 0x80)
+		v >>= 7
+		offset++
+	}
+	dAtA[offset] = uint8(v)
+	return base
+}
+func (m *Container) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = m.OwnerID.Size()
+	n += 1 + l + sovTypes(uint64(l))
+	l = m.Salt.Size()
+	n += 1 + l + sovTypes(uint64(l))
+	if m.Capacity != 0 {
+		n += 1 + sovTypes(uint64(m.Capacity))
+	}
+	l = m.Rules.Size()
+	n += 1 + l + sovTypes(uint64(l))
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func sovTypes(x uint64) (n int) {
+	return (math_bits.Len64(x|1) + 6) / 7
+}
+func sozTypes(x uint64) (n int) {
+	return sovTypes(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+func (m *Container) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowTypes
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: Container: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: Container: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field OwnerID", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.OwnerID.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Salt", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.Salt.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 3:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Capacity", wireType)
+			}
+			m.Capacity = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.Capacity |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		case 4:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Rules", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.Rules.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipTypes(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func skipTypes(dAtA []byte) (n int, err error) {
+	l := len(dAtA)
+	iNdEx := 0
+	depth := 0
+	for iNdEx < l {
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return 0, ErrIntOverflowTypes
+			}
+			if iNdEx >= l {
+				return 0, io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= (uint64(b) & 0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		wireType := int(wire & 0x7)
+		switch wireType {
+		case 0:
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return 0, ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return 0, io.ErrUnexpectedEOF
+				}
+				iNdEx++
+				if dAtA[iNdEx-1] < 0x80 {
+					break
+				}
+			}
+		case 1:
+			iNdEx += 8
+		case 2:
+			var length int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return 0, ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return 0, io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				length |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if length < 0 {
+				return 0, ErrInvalidLengthTypes
+			}
+			iNdEx += length
+		case 3:
+			depth++
+		case 4:
+			if depth == 0 {
+				return 0, ErrUnexpectedEndOfGroupTypes
+			}
+			depth--
+		case 5:
+			iNdEx += 4
+		default:
+			return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+		}
+		if iNdEx < 0 {
+			return 0, ErrInvalidLengthTypes
+		}
+		if depth == 0 {
+			return iNdEx, nil
+		}
+	}
+	return 0, io.ErrUnexpectedEOF
+}
+
+var (
+	ErrInvalidLengthTypes        = fmt.Errorf("proto: negative length found during unmarshaling")
+	ErrIntOverflowTypes          = fmt.Errorf("proto: integer overflow")
+	ErrUnexpectedEndOfGroupTypes = fmt.Errorf("proto: unexpected end of group")
+)
diff --git a/container/types.proto b/container/types.proto
new file mode 100644
index 00000000..b05001fb
--- /dev/null
+++ b/container/types.proto
@@ -0,0 +1,16 @@
+syntax = "proto3";
+package container;
+option go_package = "github.com/nspcc-dev/neofs-proto/container";
+
+import "github.com/nspcc-dev/netmap/selector.proto";
+import "github.com/gogo/protobuf/gogoproto/gogo.proto";
+
+option (gogoproto.stable_marshaler_all) = true;
+
+// The Container service definition.
+message Container {
+    bytes OwnerID              = 1 [(gogoproto.customtype) = "OwnerID", (gogoproto.nullable) = false];
+    bytes Salt                 = 2 [(gogoproto.customtype) = "UUID",    (gogoproto.nullable) = false];
+    uint64 Capacity            = 3;
+    netmap.PlacementRule Rules = 4 [(gogoproto.nullable) = false];
+}
diff --git a/container/types_test.go b/container/types_test.go
new file mode 100644
index 00000000..c7dbbf8f
--- /dev/null
+++ b/container/types_test.go
@@ -0,0 +1,57 @@
+package container
+
+import (
+	"testing"
+
+	"github.com/gogo/protobuf/proto"
+	"github.com/nspcc-dev/neofs-crypto/test"
+	"github.com/nspcc-dev/neofs-proto/refs"
+	"github.com/nspcc-dev/netmap"
+	"github.com/stretchr/testify/require"
+)
+
+func TestCID(t *testing.T) {
+	t.Run("check that marshal/unmarshal works like expected", func(t *testing.T) {
+		var (
+			c2   Container
+			cid2 CID
+			key  = test.DecodeKey(0)
+		)
+
+		rules := netmap.PlacementRule{
+			ReplFactor: 2,
+			SFGroups: []netmap.SFGroup{
+				{
+					Selectors: []netmap.Select{
+						{Key: "Country", Count: 1},
+						{Key: netmap.NodesBucket, Count: 2},
+					},
+					Filters: []netmap.Filter{
+						{Key: "Country", F: netmap.FilterIn("USA")},
+					},
+				},
+			},
+		}
+
+		owner, err := refs.NewOwnerID(&key.PublicKey)
+		require.NoError(t, err)
+
+		c1, err := New(10, owner, rules)
+		require.NoError(t, err)
+
+		data, err := proto.Marshal(c1)
+		require.NoError(t, err)
+
+		require.NoError(t, c2.Unmarshal(data))
+		require.Equal(t, c1, &c2)
+
+		cid1, err := c1.ID()
+		require.NoError(t, err)
+
+		data, err = proto.Marshal(&cid1)
+		require.NoError(t, err)
+		require.NoError(t, cid2.Unmarshal(data))
+
+		require.Equal(t, cid1, cid2)
+	})
+}
diff --git a/decimal/decimal.go b/decimal/decimal.go
new file mode 100644
index 00000000..2ee00884
--- /dev/null
+++ b/decimal/decimal.go
@@ -0,0 +1,110 @@
+package decimal
+
+import (
+	"math"
+	"strconv"
+	"strings"
+)
+
+// GASPrecision contains precision for NEO Gas token.
+const GASPrecision = 8
+
+// Zero is empty Decimal value.
+var Zero = &Decimal{}
+
+// New returns new Decimal (in satoshi).
+func New(v int64) *Decimal {
+	return NewWithPrecision(v, GASPrecision)
+}
+
+// NewGAS returns new Decimal * 1e8 (in GAS).
+func NewGAS(v int64) *Decimal {
+	v *= int64(math.Pow10(GASPrecision))
+	return NewWithPrecision(v, GASPrecision)
+}
+
+// NewWithPrecision returns new Decimal with custom precision.
+func NewWithPrecision(v int64, p uint32) *Decimal {
+	return &Decimal{Value: v, Precision: p}
+}
+
+// ParseFloat return new Decimal parsed from float64 * 1e8 (in GAS).
+func ParseFloat(v float64) *Decimal {
+	return new(Decimal).Parse(v, GASPrecision)
+}
+
+// ParseFloatWithPrecision returns new Decimal parsed from float64 * 1^p.
+func ParseFloatWithPrecision(v float64, p int) *Decimal {
+	return new(Decimal).Parse(v, p)
+}
+
+// Copy returns copy of current Decimal.
+func (m *Decimal) Copy() *Decimal { return &Decimal{Value: m.Value, Precision: m.Precision} }
+
+// Parse returns parsed Decimal from float64 * 1^p.
+func (m *Decimal) Parse(v float64, p int) *Decimal {
+	m.Value = int64(v * math.Pow10(p))
+	m.Precision = uint32(p)
+	return m
+}
+
+// String returns string representation of Decimal.
+func (m Decimal) String() string {
+	buf := new(strings.Builder)
+	val := m.Value
+	dec := int64(math.Pow10(int(m.Precision)))
+	if val < 0 {
+		buf.WriteRune('-')
+		val = -val
+	}
+	str := strconv.FormatInt(val/dec, 10)
+	buf.WriteString(str)
+	val %= dec
+	if val > 0 {
+		buf.WriteRune('.')
+		str = strconv.FormatInt(val, 10)
+		for i := len(str); i < int(m.Precision); i++ {
+			buf.WriteRune('0')
+		}
+		buf.WriteString(strings.TrimRight(str, "0"))
+	}
+	return buf.String()
+}
+
+// Add returns d + m.
+func (m Decimal) Add(d *Decimal) *Decimal {
+	precision := m.Precision
+	if precision < d.Precision {
+		precision = d.Precision
+	}
+	return &Decimal{
+		Value:     m.Value + d.Value,
+		Precision: precision,
+	}
+}
+
+// Zero checks that Decimal is empty.
+func (m Decimal) Zero() bool { return m.Value == 0 }
+
+// Equal checks that current Decimal is equal to passed Decimal.
+func (m Decimal) Equal(v *Decimal) bool { return m.Value == v.Value && m.Precision == v.Precision }
+
+// GT checks that m > v.
+func (m Decimal) GT(v *Decimal) bool { return m.Value > v.Value }
+
+// GTE checks that m >= v.
+func (m Decimal) GTE(v *Decimal) bool { return m.Value >= v.Value }
+
+// LT checks that m < v.
+func (m Decimal) LT(v *Decimal) bool { return m.Value < v.Value }
+
+// LTE checks that m <= v.
+func (m Decimal) LTE(v *Decimal) bool { return m.Value <= v.Value }
+
+// Neg returns negative representation of current Decimal (m * -1).
+func (m Decimal) Neg() *Decimal {
+	return &Decimal{
+		Value:     m.Value * -1,
+		Precision: m.Precision,
+	}
+}
diff --git a/decimal/decimal.pb.go b/decimal/decimal.pb.go
new file mode 100644
index 00000000..e125af41
--- /dev/null
+++ b/decimal/decimal.pb.go
@@ -0,0 +1,345 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: decimal/decimal.proto
+
+package decimal
+
+import (
+	fmt "fmt"
+	_ "github.com/gogo/protobuf/gogoproto"
+	proto "github.com/golang/protobuf/proto"
+	io "io"
+	math "math"
+	math_bits "math/bits"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
+
+type Decimal struct {
+	Value                int64    `protobuf:"varint,1,opt,name=Value,proto3" json:"Value,omitempty"`
+	Precision            uint32   `protobuf:"varint,2,opt,name=Precision,proto3" json:"Precision,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *Decimal) Reset()      { *m = Decimal{} }
+func (*Decimal) ProtoMessage() {}
+func (*Decimal) Descriptor() ([]byte, []int) {
+	return fileDescriptor_e7e70e1773836c80, []int{0}
+}
+func (m *Decimal) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *Decimal) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *Decimal) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Decimal.Merge(m, src)
+}
+func (m *Decimal) XXX_Size() int {
+	return m.Size()
+}
+func (m *Decimal) XXX_DiscardUnknown() {
+	xxx_messageInfo_Decimal.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Decimal proto.InternalMessageInfo
+
+func (m *Decimal) GetValue() int64 {
+	if m != nil {
+		return m.Value
+	}
+	return 0
+}
+
+func (m *Decimal) GetPrecision() uint32 {
+	if m != nil {
+		return m.Precision
+	}
+	return 0
+}
+
+func init() {
+	proto.RegisterType((*Decimal)(nil), "decimal.Decimal")
+}
+
+func init() { proto.RegisterFile("decimal/decimal.proto", fileDescriptor_e7e70e1773836c80) }
+
+var fileDescriptor_e7e70e1773836c80 = []byte{
+	// 181 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x4d, 0x49, 0x4d, 0xce,
+	0xcc, 0x4d, 0xcc, 0xd1, 0x87, 0xd2, 0x7a, 0x05, 0x45, 0xf9, 0x25, 0xf9, 0x42, 0xec, 0x50, 0xae,
+	0x94, 0x6e, 0x7a, 0x66, 0x49, 0x46, 0x69, 0x92, 0x5e, 0x72, 0x7e, 0xae, 0x7e, 0x7a, 0x7e, 0x7a,
+	0xbe, 0x3e, 0x58, 0x3e, 0xa9, 0x34, 0x0d, 0xcc, 0x03, 0x73, 0xc0, 0x2c, 0x88, 0x3e, 0x25, 0x67,
+	0x2e, 0x76, 0x17, 0x88, 0x4e, 0x21, 0x11, 0x2e, 0xd6, 0xb0, 0xc4, 0x9c, 0xd2, 0x54, 0x09, 0x46,
+	0x05, 0x46, 0x0d, 0xe6, 0x20, 0x08, 0x47, 0x48, 0x86, 0x8b, 0x33, 0xa0, 0x28, 0x35, 0x39, 0xb3,
+	0x38, 0x33, 0x3f, 0x4f, 0x82, 0x49, 0x81, 0x51, 0x83, 0x37, 0x08, 0x21, 0x60, 0xc5, 0x32, 0x63,
+	0x81, 0x3c, 0x83, 0x93, 0xdd, 0x89, 0x47, 0x72, 0x8c, 0x17, 0x1e, 0xc9, 0x31, 0xde, 0x78, 0x24,
+	0xc7, 0xf8, 0xe0, 0x91, 0x1c, 0xe3, 0x8c, 0xc7, 0x72, 0x0c, 0x51, 0x1a, 0x48, 0x2e, 0xc9, 0x2b,
+	0x2e, 0x48, 0x4e, 0xd6, 0x4d, 0x49, 0x2d, 0xd3, 0xcf, 0x4b, 0xcd, 0x4f, 0x2b, 0xd6, 0x85, 0xb8,
+	0x03, 0xea, 0xe6, 0x24, 0x36, 0x30, 0xd7, 0x18, 0x10, 0x00, 0x00, 0xff, 0xff, 0xac, 0x68, 0x21,
+	0x20, 0xdc, 0x00, 0x00, 0x00,
+}
+
+func (m *Decimal) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *Decimal) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *Decimal) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if m.Precision != 0 {
+		i = encodeVarintDecimal(dAtA, i, uint64(m.Precision))
+		i--
+		dAtA[i] = 0x10
+	}
+	if m.Value != 0 {
+		i = encodeVarintDecimal(dAtA, i, uint64(m.Value))
+		i--
+		dAtA[i] = 0x8
+	}
+	return len(dAtA) - i, nil
+}
+
+func encodeVarintDecimal(dAtA []byte, offset int, v uint64) int {
+	offset -= sovDecimal(v)
+	base := offset
+	for v >= 1<<7 {
+		dAtA[offset] = uint8(v&0x7f | 0x80)
+		v >>= 7
+		offset++
+	}
+	dAtA[offset] = uint8(v)
+	return base
+}
+func (m *Decimal) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.Value != 0 {
+		n += 1 + sovDecimal(uint64(m.Value))
+	}
+	if m.Precision != 0 {
+		n += 1 + sovDecimal(uint64(m.Precision))
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func sovDecimal(x uint64) (n int) {
+	return (math_bits.Len64(x|1) + 6) / 7
+}
+func sozDecimal(x uint64) (n int) {
+	return sovDecimal(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+func (m *Decimal) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowDecimal
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: Decimal: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: Decimal: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType)
+			}
+			m.Value = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowDecimal
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.Value |= int64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		case 2:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Precision", wireType)
+			}
+			m.Precision = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowDecimal
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.Precision |= uint32(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		default:
+			iNdEx = preIndex
+			skippy, err := skipDecimal(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthDecimal
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthDecimal
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func skipDecimal(dAtA []byte) (n int, err error) {
+	l := len(dAtA)
+	iNdEx := 0
+	depth := 0
+	for iNdEx < l {
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return 0, ErrIntOverflowDecimal
+			}
+			if iNdEx >= l {
+				return 0, io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= (uint64(b) & 0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		wireType := int(wire & 0x7)
+		switch wireType {
+		case 0:
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return 0, ErrIntOverflowDecimal
+				}
+				if iNdEx >= l {
+					return 0, io.ErrUnexpectedEOF
+				}
+				iNdEx++
+				if dAtA[iNdEx-1] < 0x80 {
+					break
+				}
+			}
+		case 1:
+			iNdEx += 8
+		case 2:
+			var length int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return 0, ErrIntOverflowDecimal
+				}
+				if iNdEx >= l {
+					return 0, io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				length |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if length < 0 {
+				return 0, ErrInvalidLengthDecimal
+			}
+			iNdEx += length
+		case 3:
+			depth++
+		case 4:
+			if depth == 0 {
+				return 0, ErrUnexpectedEndOfGroupDecimal
+			}
+			depth--
+		case 5:
+			iNdEx += 4
+		default:
+			return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+		}
+		if iNdEx < 0 {
+			return 0, ErrInvalidLengthDecimal
+		}
+		if depth == 0 {
+			return iNdEx, nil
+		}
+	}
+	return 0, io.ErrUnexpectedEOF
+}
+
+var (
+	ErrInvalidLengthDecimal        = fmt.Errorf("proto: negative length found during unmarshaling")
+	ErrIntOverflowDecimal          = fmt.Errorf("proto: integer overflow")
+	ErrUnexpectedEndOfGroupDecimal = fmt.Errorf("proto: unexpected end of group")
+)
diff --git a/decimal/decimal.proto b/decimal/decimal.proto
new file mode 100644
index 00000000..31bb9636
--- /dev/null
+++ b/decimal/decimal.proto
@@ -0,0 +1,14 @@
+syntax = "proto3";
+package decimal;
+option go_package = "github.com/nspcc-dev/neofs-proto/decimal";
+
+import "github.com/gogo/protobuf/gogoproto/gogo.proto";
+
+option (gogoproto.stable_marshaler_all) = true;
+
+message Decimal {
+    option (gogoproto.goproto_stringer) = false;
+
+    int64 Value = 1;
+    uint32 Precision = 2;
+}
diff --git a/decimal/decimal_test.go b/decimal/decimal_test.go
new file mode 100644
index 00000000..c5ffef72
--- /dev/null
+++ b/decimal/decimal_test.go
@@ -0,0 +1,445 @@
+package decimal
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/require"
+)
+
+func TestDecimal_Parse(t *testing.T) {
+	tests := []struct {
+		value  float64
+		name   string
+		expect *Decimal
+	}{
+		{name: "empty", expect: &Decimal{Precision: GASPrecision}},
+
+		{
+			value:  100,
+			name:   "100 GAS",
+			expect: &Decimal{Value: 1e10, Precision: GASPrecision},
+		},
+	}
+	for i := range tests {
+		tt := tests[i]
+		t.Run(tt.name, func(t *testing.T) {
+			require.Equal(t, tt.expect, ParseFloat(tt.value))
+		})
+	}
+}
+
+func TestDecimal_ParseWithPrecision(t *testing.T) {
+	type args struct {
+		v float64
+		p int
+	}
+	tests := []struct {
+		args   args
+		name   string
+		expect *Decimal
+	}{
+		{name: "empty", expect: &Decimal{}},
+
+		{
+			name:   "empty precision",
+			expect: &Decimal{Value: 0, Precision: 0},
+		},
+
+		{
+			name:   "100 GAS",
+			args:   args{100, GASPrecision},
+			expect: &Decimal{Value: 1e10, Precision: GASPrecision},
+		},
+	}
+	for i := range tests {
+		tt := tests[i]
+		t.Run(tt.name, func(t *testing.T) {
+			require.Equal(t, tt.expect,
+				ParseFloatWithPrecision(tt.args.v, tt.args.p))
+		})
+	}
+}
+
+func TestNew(t *testing.T) {
+	tests := []struct {
+		name   string
+		val    int64
+		expect *Decimal
+	}{
+		{name: "empty", expect: &Decimal{Value: 0, Precision: GASPrecision}},
+		{name: "100 GAS", val: 1e10, expect: &Decimal{Value: 1e10, Precision: GASPrecision}},
+	}
+	for i := range tests {
+		tt := tests[i]
+		t.Run(tt.name, func(t *testing.T) {
+			require.Equalf(t, tt.expect, New(tt.val), tt.name)
+		})
+	}
+}
+
+func TestNewGAS(t *testing.T) {
+	tests := []struct {
+		name   string
+		val    int64
+		expect *Decimal
+	}{
+		{name: "empty", expect: &Decimal{Value: 0, Precision: GASPrecision}},
+		{name: "100 GAS", val: 100, expect: &Decimal{Value: 1e10, Precision: GASPrecision}},
+	}
+	for i := range tests {
+		tt := tests[i]
+		t.Run(tt.name, func(t *testing.T) {
+			require.Equalf(t, tt.expect, NewGAS(tt.val), tt.name)
+		})
+	}
+}
+func TestNewWithPrecision(t *testing.T) {
+	tests := []struct {
+		name   string
+		val    int64
+		pre    uint32
+		expect *Decimal
+	}{
+		{name: "empty", expect: &Decimal{}},
+		{name: "100 GAS", val: 1e10, pre: GASPrecision, expect: &Decimal{Value: 1e10, Precision: GASPrecision}},
+	}
+	for i := range tests {
+		tt := tests[i]
+		t.Run(tt.name, func(t *testing.T) {
+			require.Equalf(t, tt.expect, NewWithPrecision(tt.val, tt.pre), tt.name)
+		})
+	}
+}
+
+func TestDecimal_Neg(t *testing.T) {
+	tests := []struct {
+		name   string
+		val    int64
+		expect *Decimal
+	}{
+		{name: "empty", expect: &Decimal{Value: 0, Precision: GASPrecision}},
+		{name: "100 GAS", val: 1e10, expect: &Decimal{Value: -1e10, Precision: GASPrecision}},
+	}
+	for i := range tests {
+		tt := tests[i]
+		t.Run(tt.name, func(t *testing.T) {
+			require.NotPanicsf(t, func() {
+				require.Equalf(t, tt.expect, New(tt.val).Neg(), tt.name)
+			}, tt.name)
+		})
+	}
+}
+
+func TestDecimal_String(t *testing.T) {
+	tests := []struct {
+		name   string
+		expect string
+		value  *Decimal
+	}{
+		{name: "empty", expect: "0", value: &Decimal{}},
+		{name: "100 GAS", expect: "100", value: &Decimal{Value: 1e10, Precision: GASPrecision}},
+		{name: "-100 GAS", expect: "-100", value: &Decimal{Value: -1e10, Precision: GASPrecision}},
+	}
+	for i := range tests {
+		tt := tests[i]
+		t.Run(tt.name, func(t *testing.T) {
+			require.Equalf(t, tt.expect, tt.value.String(), tt.name)
+		})
+	}
+}
+
+const SomethingElsePrecision = 5
+
+func TestDecimal_Add(t *testing.T) {
+	tests := []struct {
+		name   string
+		expect *Decimal
+		values [2]*Decimal
+	}{
+		{name: "empty", expect: &Decimal{}, values: [2]*Decimal{{}, {}}},
+		{
+			name:   "5 GAS + 2 GAS",
+			expect: &Decimal{Value: 7e8, Precision: GASPrecision},
+			values: [2]*Decimal{
+				{Value: 2e8, Precision: GASPrecision},
+				{Value: 5e8, Precision: GASPrecision},
+			},
+		},
+		{
+			name:   "1e2 + 1e3",
+			expect: &Decimal{Value: 1.1e3, Precision: 3},
+			values: [2]*Decimal{
+				{Value: 1e2, Precision: 2},
+				{Value: 1e3, Precision: 3},
+			},
+		},
+		{
+			name:   "5 GAS + 10 SomethingElse",
+			expect: &Decimal{Value: 5.01e8, Precision: GASPrecision},
+			values: [2]*Decimal{
+				{Value: 5e8, Precision: GASPrecision},
+				{Value: 1e6, Precision: SomethingElsePrecision},
+			},
+		},
+	}
+	for i := range tests {
+		tt := tests[i]
+		t.Run(tt.name, func(t *testing.T) {
+			require.NotPanicsf(t, func() {
+				{ // A + B
+					one := tt.values[0]
+					two := tt.values[1]
+					require.Equalf(t, tt.expect, one.Add(two), tt.name)
+					t.Log(one.Add(two))
+				}
+
+				{ // B + A
+					one := tt.values[0]
+					two := tt.values[1]
+					require.Equalf(t, tt.expect, two.Add(one), tt.name)
+					t.Log(two.Add(one))
+				}
+			}, tt.name)
+		})
+	}
+}
+
+func TestDecimal_Copy(t *testing.T) {
+	tests := []struct {
+		name   string
+		expect *Decimal
+		value  *Decimal
+	}{
+		{name: "zero", expect: Zero},
+		{
+			name:   "5 GAS",
+			expect: &Decimal{Value: 5e8, Precision: GASPrecision},
+		},
+		{
+			name:   "100 GAS",
+			expect: &Decimal{Value: 1e10, Precision: GASPrecision},
+		},
+	}
+	for i := range tests {
+		tt := tests[i]
+		t.Run(tt.name, func(t *testing.T) {
+			require.NotPanicsf(t, func() {
+				require.Equal(t, tt.expect, tt.expect.Copy())
+			}, tt.name)
+		})
+	}
+}
+
+func TestDecimal_Zero(t *testing.T) {
+	tests := []struct {
+		name   string
+		expect bool
+		value  *Decimal
+	}{
+		{name: "zero", expect: true, value: Zero},
+		{
+			name:   "5 GAS",
+			expect: false,
+			value:  &Decimal{Value: 5e8, Precision: GASPrecision},
+		},
+		{
+			name:   "100 GAS",
+			expect: false,
+			value:  &Decimal{Value: 1e10, Precision: GASPrecision},
+		},
+	}
+	for i := range tests {
+		tt := tests[i]
+		t.Run(tt.name, func(t *testing.T) {
+			require.NotPanicsf(t, func() {
+				require.Truef(t, tt.expect == tt.value.Zero(), tt.name)
+			}, tt.name)
+		})
+	}
+}
+
+func TestDecimal_Equal(t *testing.T) {
+	tests := []struct {
+		name   string
+		expect bool
+		values [2]*Decimal
+	}{
+		{name: "zero == zero", expect: true, values: [2]*Decimal{Zero, Zero}},
+		{
+			name:   "5 GAS != 2 GAS",
+			expect: false,
+			values: [2]*Decimal{
+				{Value: 5e8, Precision: GASPrecision},
+				{Value: 2e8, Precision: GASPrecision},
+			},
+		},
+		{
+			name:   "100 GAS == 100 GAS",
+			expect: true,
+			values: [2]*Decimal{
+				{Value: 1e10, Precision: GASPrecision},
+				{Value: 1e10, Precision: GASPrecision},
+			},
+		},
+	}
+	for i := range tests {
+		tt := tests[i]
+		t.Run(tt.name, func(t *testing.T) {
+			require.NotPanicsf(t, func() {
+				require.Truef(t, tt.expect == (tt.values[0].Equal(tt.values[1])), tt.name)
+			}, tt.name)
+		})
+	}
+}
+
+func TestDecimal_GT(t *testing.T) {
+	tests := []struct {
+		name   string
+		expect bool
+		values [2]*Decimal
+	}{
+		{name: "two zeros", expect: false, values: [2]*Decimal{Zero, Zero}},
+		{
+			name:   "5 GAS > 2 GAS",
+			expect: true,
+			values: [2]*Decimal{
+				{Value: 5e8, Precision: GASPrecision},
+				{Value: 2e8, Precision: GASPrecision},
+			},
+		},
+		{
+			name:   "100 GAS !> 100 GAS",
+			expect: false,
+			values: [2]*Decimal{
+				{Value: 1e10, Precision: GASPrecision},
+				{Value: 1e10, Precision: GASPrecision},
+			},
+		},
+	}
+	for i := range tests {
+		tt := tests[i]
+		t.Run(tt.name, func(t *testing.T) {
+			require.NotPanicsf(t, func() {
+				require.Truef(t, tt.expect == (tt.values[0].GT(tt.values[1])), tt.name)
+			}, tt.name)
+		})
+	}
+}
+
+func TestDecimal_GTE(t *testing.T) {
+	tests := []struct {
+		name   string
+		expect bool
+		values [2]*Decimal
+	}{
+		{name: "two zeros", expect: true, values: [2]*Decimal{Zero, Zero}},
+		{
+			name:   "5 GAS >= 2 GAS",
+			expect: true,
+			values: [2]*Decimal{
+				{Value: 5e8, Precision: GASPrecision},
+				{Value: 2e8, Precision: GASPrecision},
+			},
+		},
+		{
+			name:   "1 GAS !>= 100 GAS",
+			expect: false,
+			values: [2]*Decimal{
+				{Value: 1e8, Precision: GASPrecision},
+				{Value: 1e10, Precision: GASPrecision},
+			},
+		},
+	}
+	for i := range tests {
+		tt := tests[i]
+		t.Run(tt.name, func(t *testing.T) {
+			require.NotPanicsf(t, func() {
+				require.Truef(t, tt.expect == (tt.values[0].GTE(tt.values[1])), tt.name)
+			}, tt.name)
+		})
+	}
+}
+
+func TestDecimal_LT(t *testing.T) {
+	tests := []struct {
+		name   string
+		expect bool
+		values [2]*Decimal
+	}{
+		{name: "two zeros", expect: false, values: [2]*Decimal{Zero, Zero}},
+		{
+			name:   "5 GAS !< 2 GAS",
+			expect: false,
+			values: [2]*Decimal{
+				{Value: 5e8, Precision: GASPrecision},
+				{Value: 2e8, Precision: GASPrecision},
+			},
+		},
+		{
+			name:   "1 GAS < 100 GAS",
+			expect: true,
+			values: [2]*Decimal{
+				{Value: 1e8, Precision: GASPrecision},
+				{Value: 1e10, Precision: GASPrecision},
+			},
+		},
+		{
+			name:   "100 GAS !< 100 GAS",
+			expect: false,
+			values: [2]*Decimal{
+				{Value: 1e10, Precision: GASPrecision},
+				{Value: 1e10, Precision: GASPrecision},
+			},
+		},
+	}
+	for i := range tests {
+		tt := tests[i]
+		t.Run(tt.name, func(t *testing.T) {
+			require.NotPanicsf(t, func() {
+				require.Truef(t, tt.expect == (tt.values[0].LT(tt.values[1])), tt.name)
+			}, tt.name)
+		})
+	}
+}
+
+func TestDecimal_LTE(t *testing.T) {
+	tests := []struct {
+		name   string
+		expect bool
+		values [2]*Decimal
+	}{
+		{name: "two zeros", expect: true, values: [2]*Decimal{Zero, Zero}},
+		{
+			name:   "5 GAS <= 2 GAS",
+			expect: false,
+			values: [2]*Decimal{
+				{Value: 5e8, Precision: GASPrecision},
+				{Value: 2e8, Precision: GASPrecision},
+			},
+		},
+		{
+			name:   "1 GAS <= 100 GAS",
+			expect: true,
+			values: [2]*Decimal{
+				{Value: 1e8, Precision: GASPrecision},
+				{Value: 1e10, Precision: GASPrecision},
+			},
+		},
+		{
+			name:   "100 GAS !<= 1 GAS",
+			expect: false,
+			values: [2]*Decimal{
+				{Value: 1e10, Precision: GASPrecision},
+				{Value: 1e8, Precision: GASPrecision},
+			},
+		},
+	}
+	for i := range tests {
+		tt := tests[i]
+		t.Run(tt.name, func(t *testing.T) {
+			require.NotPanicsf(t, func() {
+				require.Truef(t, tt.expect == (tt.values[0].LTE(tt.values[1])), tt.name)
+			}, tt.name)
+		})
+	}
+}
diff --git a/go.mod b/go.mod
new file mode 100644
index 00000000..46490042
--- /dev/null
+++ b/go.mod
@@ -0,0 +1,22 @@
+module github.com/nspcc-dev/neofs-proto
+
+go 1.13
+
+require (
+	code.cloudfoundry.org/bytefmt v0.0.0-20190819182555-854d396b647c
+	github.com/gogo/protobuf v1.3.1
+	github.com/golang/protobuf v1.3.2
+	github.com/google/uuid v1.1.1
+	github.com/mr-tron/base58 v1.1.2
+	github.com/nspcc-dev/neofs-crypto v0.2.1
+	github.com/nspcc-dev/netmap v1.6.1
+	github.com/nspcc-dev/tzhash v1.3.0
+	github.com/onsi/ginkgo v1.10.2 // indirect
+	github.com/onsi/gomega v1.7.0 // indirect
+	github.com/pkg/errors v0.8.1
+	github.com/prometheus/client_golang v1.2.1
+	github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4
+	github.com/stretchr/testify v1.4.0
+	golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550
+	google.golang.org/grpc v1.24.0
+)
diff --git a/go.sum b/go.sum
new file mode 100644
index 00000000..6b48f3f5
--- /dev/null
+++ b/go.sum
@@ -0,0 +1,165 @@
+cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+code.cloudfoundry.org/bytefmt v0.0.0-20190819182555-854d396b647c h1:2RuXx1+tSNWRjxhY0Bx52kjV2odJQ0a6MTbfTPhGAkg=
+code.cloudfoundry.org/bytefmt v0.0.0-20190819182555-854d396b647c/go.mod h1:wN/zk7mhREp/oviagqUXY3EwuHhWyOvAdsn5Y4CzOrc=
+github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
+github.com/abiosoft/ishell v2.0.0+incompatible/go.mod h1:HQR9AqF2R3P4XXpMpI0NAzgHf/aS6+zVXRj14cVk9qg=
+github.com/abiosoft/readline v0.0.0-20180607040430-155bce2042db/go.mod h1:rB3B4rKii8V21ydCbIzH5hZiCQE7f5E9SzUb/ZZx530=
+github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
+github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
+github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
+github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
+github.com/awalterschulze/gographviz v0.0.0-20181013152038-b2885df04310 h1:t+qxRrRtwNiUYA+Xh2jSXhoG2grnMCMKX4Fg6lx9X1U=
+github.com/awalterschulze/gographviz v0.0.0-20181013152038-b2885df04310/go.mod h1:GEV5wmg4YquNw7v1kkyoX9etIk8yVmXj+AkDHuuETHs=
+github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
+github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
+github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
+github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
+github.com/cespare/xxhash/v2 v2.1.0 h1:yTUvW7Vhb89inJ+8irsUqiWjh8iT6sQPZiQzI6ReGkA=
+github.com/cespare/xxhash/v2 v2.1.0/go.mod h1:dgIUBU3pDso/gPgZ1osOZ0iQf77oPR28Tjxl5dIMyVM=
+github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
+github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
+github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
+github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
+github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:rZfgFAXFS/z/lEd6LJmf9HVZ1LkgYiHx5pHhV5DR16M=
+github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
+github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
+github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
+github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
+github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
+github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
+github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
+github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
+github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
+github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
+github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
+github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
+github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
+github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
+github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
+github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
+github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
+github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
+github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
+github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
+github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
+github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
+github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
+github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
+github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
+github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
+github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
+github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
+github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/mr-tron/base58 v1.1.2 h1:ZEw4I2EgPKDJ2iEw0cNmLB3ROrEmkOtXIkaG7wZg+78=
+github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
+github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
+github.com/nspcc-dev/hrw v1.0.8 h1:vwRuJXZXgkMvf473vFzeWGCfY1WBVeSHAEHvR4u3/Cg=
+github.com/nspcc-dev/hrw v1.0.8/go.mod h1:l/W2vx83vMQo6aStyx2AuZrJ+07lGv2JQGlVkPG06MU=
+github.com/nspcc-dev/neofs-crypto v0.2.1 h1:NxKexcW88vlHO/u7EYjx5Q1UaOQ7XhYrCsLSVgOcCxw=
+github.com/nspcc-dev/neofs-crypto v0.2.1/go.mod h1:F/96fUzPM3wR+UGsPi3faVNmFlA9KAEAUQR7dMxZmNA=
+github.com/nspcc-dev/netmap v1.6.1 h1:Pigqpqi6QSdRiusbq5XlO20A18k6Eyu7j9MzOfAE3CM=
+github.com/nspcc-dev/netmap v1.6.1/go.mod h1:mhV3UOg9ljQmu0teQShD6+JYX09XY5gu2I4hIByCH9M=
+github.com/nspcc-dev/rfc6979 v0.1.0 h1:Lwg7esRRoyK1Up/IN1vAef1EmvrBeMHeeEkek2fAJ6c=
+github.com/nspcc-dev/rfc6979 v0.1.0/go.mod h1:exhIh1PdpDC5vQmyEsGvc4YDM/lyQp/452QxGq/UEso=
+github.com/nspcc-dev/tzhash v1.3.0 h1:n6FTHsfPYbMi5Jmo6SwGVVRQD8i2w1P2ScCaW6rz69Q=
+github.com/nspcc-dev/tzhash v1.3.0/go.mod h1:Lc4DersKS8MNIrunTmsAzANO56qnG+LZ4GOE/WYGVzU=
+github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/ginkgo v1.10.2 h1:uqH7bpe+ERSiDa34FDOF7RikN6RzXgduUF8yarlZp94=
+github.com/onsi/ginkgo v1.10.2/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME=
+github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
+github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
+github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
+github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
+github.com/prometheus/client_golang v1.2.1 h1:JnMpQc6ppsNgw9QPAGF6Dod479itz7lvlsMzzNayLOI=
+github.com/prometheus/client_golang v1.2.1/go.mod h1:XMU6Z2MjaRKVu/dC1qupJI9SiNkDYzz3xecMgSW/F+U=
+github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
+github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4 h1:gQz4mCbXsO+nc9n1hCxHcGA3Zx3Eo+UHZoInFGUIXNM=
+github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
+github.com/prometheus/common v0.7.0 h1:L+1lyG48J1zAQXA3RBX/nG/B3gjlHq0zTt2tlbJLyCY=
+github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
+github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
+github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
+github.com/prometheus/procfs v0.0.5 h1:3+auTFlqw+ZaQYJARz6ArODtkaIwtvBTx3N2NehQlL8=
+github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
+github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
+github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
+github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
+github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
+github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190613194153-d28f0bde5980 h1:dfGZHvZk057jK2MCeWus/TowKpJ8y4AmooUzdBSR9GU=
+golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
+golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20181228144115-9a3f9b0469bb/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191010194322-b09406accb47 h1:/XfQ9z7ib8eEJX2hdgFTZJ/ntt0swNk5oYBziWeTCvY=
+golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
+google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc=
+google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/grpc v1.24.0 h1:vb/1TCsVn3DcJlQ0Gs1yB1pKI6Do2/QNwxdKqmc/b0s=
+google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA=
+gopkg.in/abiosoft/ishell.v2 v2.0.0/go.mod h1:sFp+cGtH6o4s1FtpVPTMcHq2yue+c4DGOVohJCPUzwY=
+gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
+gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
+gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
+gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
+gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
diff --git a/hash/hash.go b/hash/hash.go
new file mode 100644
index 00000000..36884431
--- /dev/null
+++ b/hash/hash.go
@@ -0,0 +1,98 @@
+package hash
+
+import (
+	"bytes"
+
+	"github.com/mr-tron/base58"
+	"github.com/nspcc-dev/neofs-proto/internal"
+	"github.com/nspcc-dev/tzhash/tz"
+	"github.com/pkg/errors"
+)
+
+// HomomorphicHashSize contains size of HH.
+const HomomorphicHashSize = 64
+
+// Hash is implementation of HomomorphicHash.
+type Hash [HomomorphicHashSize]byte
+
+// ErrWrongDataSize raised when wrong size of bytes is passed to unmarshal HH.
+const ErrWrongDataSize = internal.Error("wrong data size")
+
+var (
+	_ internal.Custom = (*Hash)(nil)
+
+	emptyHH [HomomorphicHashSize]byte
+)
+
+// Size returns size of Hash (HomomorphicHashSize).
+func (h Hash) Size() int { return HomomorphicHashSize }
+
+// Empty checks that Hash is empty.
+func (h Hash) Empty() bool { return bytes.Equal(h.Bytes(), emptyHH[:]) }
+
+// Reset sets current Hash to empty value.
+func (h *Hash) Reset() { *h = Hash{} }
+
+// ProtoMessage method to satisfy proto.Message interface.
+func (h Hash) ProtoMessage() {}
+
+// Bytes represents Hash as bytes.
+func (h Hash) Bytes() []byte {
+	buf := make([]byte, HomomorphicHashSize)
+	copy(buf, h[:])
+	return h[:]
+}
+
+// Marshal returns bytes representation of Hash.
+func (h Hash) Marshal() ([]byte, error) { return h.Bytes(), nil }
+
+// MarshalTo tries to marshal Hash into passed bytes and returns count of copied bytes.
+func (h *Hash) MarshalTo(data []byte) (int, error) { return copy(data, h.Bytes()), nil }
+
+// Unmarshal tries to parse bytes into valid Hash.
+func (h *Hash) Unmarshal(data []byte) error {
+	if ln := len(data); ln != HomomorphicHashSize {
+		return errors.Wrapf(ErrWrongDataSize, "expect=%d, actual=%d", HomomorphicHashSize, ln)
+	}
+
+	copy((*h)[:], data)
+	return nil
+}
+
+// String returns string representation of Hash.
+func (h Hash) String() string { return base58.Encode(h[:]) }
+
+// Equal checks that current Hash is equal to passed Hash.
+func (h Hash) Equal(hash Hash) bool { return h == hash }
+
+// Verify validates if current hash generated from passed data.
+func (h Hash) Verify(data []byte) bool { return h.Equal(Sum(data)) }
+
+// Validate checks if combined hashes are equal to current Hash.
+func (h Hash) Validate(hashes []Hash) bool {
+	var hashBytes = make([][]byte, 0, len(hashes))
+	for i := range hashes {
+		hashBytes = append(hashBytes, hashes[i].Bytes())
+	}
+	ok, err := tz.Validate(h.Bytes(), hashBytes)
+	return err == nil && ok
+}
+
+// Sum returns Tillich-Zémor checksum of data.
+func Sum(data []byte) Hash { return tz.Sum(data) }
+
+// Concat combines hashes based on homomorphic property.
+func Concat(hashes []Hash) (Hash, error) {
+	var (
+		hash Hash
+		h    = make([][]byte, 0, len(hashes))
+	)
+	for i := range hashes {
+		h = append(h, hashes[i].Bytes())
+	}
+	cat, err := tz.Concat(h)
+	if err != nil {
+		return hash, err
+	}
+	return hash, hash.Unmarshal(cat)
+}
diff --git a/hash/hash_test.go b/hash/hash_test.go
new file mode 100644
index 00000000..b3ef7035
--- /dev/null
+++ b/hash/hash_test.go
@@ -0,0 +1,166 @@
+package hash
+
+import (
+	"bytes"
+	"crypto/rand"
+	"testing"
+
+	"github.com/pkg/errors"
+	"github.com/stretchr/testify/require"
+)
+
+func Test_Sum(t *testing.T) {
+	var (
+		data = []byte("Hello world")
+		sum  = Sum(data)
+		hash = []byte{0, 0, 0, 0, 1, 79, 16, 173, 134, 90, 176, 77, 114, 165, 253, 114, 0, 0, 0, 0, 0, 148,
+			172, 222, 98, 248, 15, 99, 205, 129, 66, 91, 0, 0, 0, 0, 0, 138, 173, 39, 228, 231, 239, 123,
+			170, 96, 186, 61, 0, 0, 0, 0, 0, 90, 69, 237, 131, 90, 161, 73, 38, 164, 185, 55}
+	)
+
+	require.Equal(t, hash, sum.Bytes())
+}
+
+func Test_Validate(t *testing.T) {
+	var (
+		data   = []byte("Hello world")
+		hash   = Sum(data)
+		pieces = splitData(data, 2)
+		ln     = len(pieces)
+		hashes = make([]Hash, 0, ln)
+	)
+
+	for i := 0; i < ln; i++ {
+		hashes = append(hashes, Sum(pieces[i]))
+	}
+
+	require.True(t, hash.Validate(hashes))
+}
+
+func Test_Concat(t *testing.T) {
+	var (
+		data   = []byte("Hello world")
+		hash   = Sum(data)
+		pieces = splitData(data, 2)
+		ln     = len(pieces)
+		hashes = make([]Hash, 0, ln)
+	)
+
+	for i := 0; i < ln; i++ {
+		hashes = append(hashes, Sum(pieces[i]))
+	}
+
+	res, err := Concat(hashes)
+	require.NoError(t, err)
+	require.Equal(t, hash, res)
+}
+
+func Test_HashChunks(t *testing.T) {
+	var (
+		chars = []byte("+")
+		size  = 1400
+		data  = bytes.Repeat(chars, size)
+		hash  = Sum(data)
+		count = 150
+	)
+
+	hashes, err := dataHashes(data, count)
+	require.NoError(t, err)
+	require.Len(t, hashes, count)
+
+	require.True(t, hash.Validate(hashes))
+
+	// 100 / 150 = 0
+	hashes, err = dataHashes(data[:100], count)
+	require.Error(t, err)
+	require.Nil(t, hashes)
+}
+
+func TestXOR(t *testing.T) {
+	var (
+		dl   = 10
+		data = make([]byte, dl)
+	)
+
+	_, err := rand.Read(data)
+	require.NoError(t, err)
+
+	t.Run("XOR with <nil> salt", func(t *testing.T) {
+		res := SaltXOR(data, nil)
+		require.Equal(t, res, data)
+	})
+
+	t.Run("XOR with empty salt", func(t *testing.T) {
+		xorWithSalt(t, data, 0)
+	})
+
+	t.Run("XOR with salt same data size", func(t *testing.T) {
+		xorWithSalt(t, data, dl)
+	})
+
+	t.Run("XOR with salt shorter than data aliquot", func(t *testing.T) {
+		xorWithSalt(t, data, dl/2)
+	})
+
+	t.Run("XOR with salt shorter than data aliquant", func(t *testing.T) {
+		xorWithSalt(t, data, dl/3/+1)
+	})
+
+	t.Run("XOR with salt longer than data aliquot", func(t *testing.T) {
+		xorWithSalt(t, data, dl*2)
+	})
+
+	t.Run("XOR with salt longer than data aliquant", func(t *testing.T) {
+		xorWithSalt(t, data, dl*2-1)
+	})
+}
+
+func xorWithSalt(t *testing.T, data []byte, saltSize int) {
+	var (
+		direct, reverse []byte
+		salt            = make([]byte, saltSize)
+	)
+
+	_, err := rand.Read(salt)
+	require.NoError(t, err)
+
+	direct = SaltXOR(data, salt)
+	require.Len(t, direct, len(data))
+
+	reverse = SaltXOR(direct, salt)
+	require.Len(t, reverse, len(data))
+
+	require.Equal(t, reverse, data)
+}
+
+func splitData(buf []byte, lim int) [][]byte {
+	var piece []byte
+	pieces := make([][]byte, 0, len(buf)/lim+1)
+	for len(buf) >= lim {
+		piece, buf = buf[:lim], buf[lim:]
+		pieces = append(pieces, piece)
+	}
+	if len(buf) > 0 {
+		pieces = append(pieces, buf)
+	}
+	return pieces
+}
+
+func dataHashes(data []byte, count int) ([]Hash, error) {
+	var (
+		ln     = len(data)
+		mis    = ln / count
+		off    = (count - 1) * mis
+		hashes = make([]Hash, 0, count)
+	)
+	if mis == 0 {
+		return nil, errors.Errorf("could not split %d bytes to %d pieces", ln, count)
+	}
+
+	pieces := splitData(data[:off], mis)
+	pieces = append(pieces, data[off:])
+	for i := 0; i < count; i++ {
+		hashes = append(hashes, Sum(pieces[i]))
+	}
+	return hashes, nil
+}
diff --git a/hash/hashesslice.go b/hash/hashesslice.go
new file mode 100644
index 00000000..83bf4c5b
--- /dev/null
+++ b/hash/hashesslice.go
@@ -0,0 +1,20 @@
+package hash
+
+import (
+	"bytes"
+)
+
+// HashesSlice is a collection that satisfies sort.Interface and can be
+// sorted by the routines in sort package.
+type HashesSlice []Hash
+
+// -- HashesSlice -- an inner type to sort Objects
+// Len is the number of elements in the collection.
+func (hs HashesSlice) Len() int { return len(hs) }
+
+// Less reports whether the element with
+// index i should be sorted before the element with index j.
+func (hs HashesSlice) Less(i, j int) bool { return bytes.Compare(hs[i].Bytes(), hs[j].Bytes()) == -1 }
+
+// Swap swaps the elements with indexes i and j.
+func (hs HashesSlice) Swap(i, j int) { hs[i], hs[j] = hs[j], hs[i] }
diff --git a/hash/salt.go b/hash/salt.go
new file mode 100644
index 00000000..5b6eeb0b
--- /dev/null
+++ b/hash/salt.go
@@ -0,0 +1,17 @@
+package hash
+
+// SaltXOR xors bits of data with salt
+// repeating salt if necessary.
+func SaltXOR(data, salt []byte) (result []byte) {
+	result = make([]byte, len(data))
+	ls := len(salt)
+	if ls == 0 {
+		copy(result, data)
+		return
+	}
+
+	for i := range result {
+		result[i] = data[i] ^ salt[i%ls]
+	}
+	return
+}
diff --git a/internal/error.go b/internal/error.go
new file mode 100644
index 00000000..7df16033
--- /dev/null
+++ b/internal/error.go
@@ -0,0 +1,7 @@
+package internal
+
+// Error is a custom error.
+type Error string
+
+// Error is an implementation of error interface.
+func (e Error) Error() string { return string(e) }
diff --git a/internal/proto.go b/internal/proto.go
new file mode 100644
index 00000000..951168b8
--- /dev/null
+++ b/internal/proto.go
@@ -0,0 +1,16 @@
+package internal
+
+import "github.com/gogo/protobuf/proto"
+
+// Custom contains methods to satisfy proto.Message
+// including custom methods to satisfy protobuf for
+// non-proto defined types.
+type Custom interface {
+	Size() int
+	Empty() bool
+	Bytes() []byte
+	Marshal() ([]byte, error)
+	MarshalTo(data []byte) (int, error)
+	Unmarshal(data []byte) error
+	proto.Message
+}
diff --git a/object/doc.go b/object/doc.go
new file mode 100644
index 00000000..d81495b0
--- /dev/null
+++ b/object/doc.go
@@ -0,0 +1,143 @@
+/*
+Package object manages main storage structure in the system. All storage
+operations are performed with the objects. During lifetime object might be
+transformed into another object by cutting its payload or adding meta
+information. All transformation may be reversed, therefore source object
+will be able to restore.
+
+Object structure
+
+Object consists of Payload and Header. Payload is unlimited but storage nodes
+may have a policy to store objects with a limited payload. In this case object
+with large payload will be transformed into the chain of objects with small
+payload.
+
+Headers are simple key-value fields that divided into two groups: system
+headers and extended headers. System headers contain information about
+protocol version, object id, payload length in bytes, owner id, container id
+and object creation timestamp (both in epochs and unix time). All these fields
+must be set up in the correct object.
+
+    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
+    | System Headers                                                   |
+    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
+    | Version        : 1                                               |
+    | Payload Length : 21673465                                        |
+    | Object ID      : 465208e2-ba4f-4f99-ad47-82a59f4192d4            |
+    | Owner ID       : AShvoCbSZ7VfRiPkVb1tEcBLiJrcbts1tt              |
+    | Container ID   : FGobtRZA6sBZv2i9k4L7TiTtnuP6E788qa278xfj3Fxj    |
+    | Created At     : Epoch#10, 1573033162                            |
+    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
+    | Extended Headers                                                 |
+    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
+    | User Header         : <user-defined-key>, <user-defined-value>   |
+    | Verification Header : <session public key>, <owner's signature>  |
+    | Homomorphic Hash    : 0x23d35a56ae...                            |
+    | Payload Checksum    : 0x1bd34abs75...                            |
+    | Integrity Header    : <header checksum>, <session signature>     |
+    | Transformation      : Payload Split                              |
+    | Link-parent         : cae08935-b4ba-499a-bf6c-98276c1e6c0b       |
+    | Link-next           : c3b40fbf-3798-4b61-a189-2992b5fb5070       |
+    | Payload Checksum    : 0x1f387a5c36...                            |
+    | Integrity Header    : <header checksum>, <session signature>     |
+    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
+    | Payload                                                          |
+    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
+    | 0xd1581963a342d231...                                            |
+    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
+
+There are different kinds of extended headers. A correct object must contain
+verification header, homomorphic hash header, payload checksum and
+integrity header. The order of headers is matter. Let's look through all
+these headers.
+
+Link header points to the connected objects. During object transformation, large
+object might be transformed into the chain of smaller objects. One of these
+objects drops payload and has several "Child" links. We call this object as
+zero-object. Others will have "Parent" link to the zero-object, "Previous"
+and "Next" links in the payload chain.
+
+    [ Object ID:1 ] = > transformed
+    `- [ Zero-Object ID:1 ]
+        `- Link-child    ID:2
+        `- Link-child    ID:3
+        `- Link-child    ID:4
+        `- Payload [null]
+    `- [ Object ID:2 ]
+        `- Link-parent   ID:1
+        `- Link-next     ID:3
+        `- Payload [ 0x13ba... ]
+    `- [ Object ID:3 ]
+        `- Link-parent   ID:1
+        `- Link-previous ID:2
+        `- Link-next     ID:4
+        `- Payload [ 0xcd34... ]
+    `- [ Object ID:4 ]
+        `- Link-parent   ID:1
+        `- Link-previous ID:3
+        `- Payload [ 0xef86... ]
+
+Storage groups are also objects. They have "Storage Group" links to all
+objects in the group. Links are set by nodes during transformations and,
+in general, they should not be set by user manually.
+
+Redirect headers are not used yet, they will be implemented and described
+later.
+
+User header is a key-value pair of string that can be defined by user. User
+can use these headers as search attribute. You can store any meta information
+about object there, e.g. object's nicename.
+
+Transformation header notifies that object was transformed by some pre-defined
+way. This header sets up before object is transformed and all headers after
+transformation must be located after transformation header. During reverse
+transformation, all headers under transformation header will be cut out.
+
+     +-+-+-+-+-+-+-+-+-+-       +-+-+-+-+-+-+-+-+-+-+     +-+-+-+-+-+-+-+-+-+-+
+     | Payload checksum |       | Payload checksum  |     | Payload checksum  |
+     | Integrity header |   =>  | Integrity header  |  +  | Integrity header  |
+     +-+-+-+-+-+-+-+-+-+-       | Transformation    |     | Transformation    |
+     | Large payload    |       | New Checksum      |     | New Checksum      |
+     +-+-+-+-+-+-+-+-+-+-       | New Integrity     |     | New Integrity     |
+                                +-+-+-+-+-+-+-+-+-+-+     +-+-+-+-+-+-+-+-+-+-+
+                                | Small payload     |     | Small payload     |
+                                +-+-+-+-+-+-+-+-+-+-+     +-+-+-+-+-+-+-+-+-+-+
+
+For now, we use only one type of transformation: payload split transformation.
+This header set up by node automatically.
+
+Tombstone header notifies that this object was deleted by user. Objects with
+tombstone header do not have payload, but they still contain meta information
+in the headers. This way we implement two-phase commit for object removal.
+Storage nodes will eventually delete all tombstone objects. If you want to
+delete object, you must create new object with the same object id, with
+tombstone header, correct signatures and without payload.
+
+Verification header contains session information. To put the object in
+the system user must create session. It is required because objects might
+be transformed and therefore must be re-signed. To do that node creates
+a pair of session public and private keys. Object owner delegates permission to
+re-sign objects by signing session public key. This header contains session
+public key and owner's signature of this key. You must specify this header
+manually.
+
+Homomorphic hash header contains homomorphic hash of the source object.
+Transformations do not affect this header. This header used by data audit and
+set by node automatically.
+
+Payload checksum contains checksum of the actual object payload. All payload
+transformation must set new payload checksum headers. This header set by node
+automatically.
+
+Integrity header contains checksum of the header and signature of the
+session key. This header must be last in the list of extended headers.
+Checksum is calculated by marshaling all above headers, including system
+headers. This header set by node automatically.
+
+Storage group header is presented in storage group objects. It contains
+information for data audit: size of validated data, homomorphic has of this
+data, storage group expiration time in epochs or unix time.
+
+
+*/
+package object
diff --git a/object/extensions.go b/object/extensions.go
new file mode 100644
index 00000000..1d896833
--- /dev/null
+++ b/object/extensions.go
@@ -0,0 +1,84 @@
+package object
+
+import (
+	"github.com/nspcc-dev/neofs-proto/hash"
+)
+
+// IsLinking checks if object has children links to another objects.
+// We have to check payload size because zero-object must have zero
+// payload and non-zero payload length field in system header.
+func (m Object) IsLinking() bool {
+	for i := range m.Headers {
+		switch v := m.Headers[i].Value.(type) {
+		case *Header_Link:
+			if v.Link.GetType() == Link_Child {
+				return m.SystemHeader.PayloadLength > 0 && len(m.Payload) == 0
+			}
+		}
+	}
+	return false
+}
+
+// VerificationHeader returns verification header if it is presented in extended headers.
+func (m Object) VerificationHeader() (*VerificationHeader, error) {
+	_, vh := m.LastHeader(HeaderType(VerifyHdr))
+	if vh == nil {
+		return nil, ErrHeaderNotFound
+	}
+	return vh.Value.(*Header_Verify).Verify, nil
+}
+
+// SetVerificationHeader sets verification header in the object.
+// It will replace existing verification header or add a new one.
+func (m *Object) SetVerificationHeader(header *VerificationHeader) {
+	m.SetHeader(&Header{Value: &Header_Verify{Verify: header}})
+}
+
+// Links returns slice of ids of specified link type
+func (m *Object) Links(t Link_Type) []ID {
+	var res []ID
+	for i := range m.Headers {
+		switch v := m.Headers[i].Value.(type) {
+		case *Header_Link:
+			if v.Link.GetType() == t {
+				res = append(res, v.Link.ID)
+			}
+		}
+	}
+	return res
+}
+
+// Tombstone returns tombstone header if it is presented in extended headers.
+func (m Object) Tombstone() *Tombstone {
+	_, h := m.LastHeader(HeaderType(TombstoneHdr))
+	if h != nil {
+		return h.Value.(*Header_Tombstone).Tombstone
+	}
+	return nil
+}
+
+// IsTombstone checks if object has tombstone header.
+func (m Object) IsTombstone() bool {
+	n, _ := m.LastHeader(HeaderType(TombstoneHdr))
+	return n != -1
+}
+
+// StorageGroup returns storage group structure if it is presented in extended headers.
+func (m Object) StorageGroup() (*StorageGroup, error) {
+	_, sgHdr := m.LastHeader(HeaderType(StorageGroupHdr))
+	if sgHdr == nil {
+		return nil, ErrHeaderNotFound
+	}
+	return sgHdr.Value.(*Header_StorageGroup).StorageGroup, nil
+}
+
+// SetStorageGroup sets storage group header in the object.
+// It will replace existing storage group header or add a new one.
+func (m *Object) SetStorageGroup(sg *StorageGroup) {
+	m.SetHeader(&Header{Value: &Header_StorageGroup{StorageGroup: sg}})
+}
+
+// Empty checks if storage group has some data for validation.
+func (m StorageGroup) Empty() bool {
+	return m.ValidationDataSize == 0 && m.ValidationHash.Equal(hash.Hash{})
+}
diff --git a/object/service.go b/object/service.go
new file mode 100644
index 00000000..098f9c31
--- /dev/null
+++ b/object/service.go
@@ -0,0 +1,215 @@
+package object
+
+import (
+	"github.com/nspcc-dev/neofs-proto/hash"
+	"github.com/nspcc-dev/neofs-proto/internal"
+	"github.com/nspcc-dev/neofs-proto/refs"
+	"github.com/nspcc-dev/neofs-proto/service"
+	"github.com/nspcc-dev/neofs-proto/session"
+)
+
+type (
+	// ID is a type alias of object id.
+	ID = refs.ObjectID
+
+	// CID is a type alias of container id.
+	CID = refs.CID
+
+	// SGID is a type alias of storage group id.
+	SGID = refs.SGID
+
+	// OwnerID is a type alias of owner id.
+	OwnerID = refs.OwnerID
+
+	// Hash is a type alias of Homomorphic hash.
+	Hash = hash.Hash
+
+	// Token is a type alias of session token.
+	Token = session.Token
+
+	// Request defines object rpc requests.
+	// All object operations must have TTL, Epoch, Container ID and
+	// permission of usage previous network map.
+	Request interface {
+		service.TTLRequest
+		service.EpochRequest
+
+		CID() CID
+		AllowPreviousNetMap() bool
+	}
+)
+
+const (
+	// UnitsB starts enum for amount of bytes.
+	UnitsB int64 = 1 << (10 * iota)
+
+	// UnitsKB defines amount of bytes in one kilobyte.
+	UnitsKB
+
+	// UnitsMB defines amount of bytes in one megabyte.
+	UnitsMB
+
+	// UnitsGB defines amount of bytes in one gigabyte.
+	UnitsGB
+
+	// UnitsTB defines amount of bytes in one terabyte.
+	UnitsTB
+)
+
+const (
+	// ErrNotFound is raised when object is not found in the system.
+	ErrNotFound = internal.Error("could not find object")
+
+	// ErrHeaderExpected is raised when first message in protobuf stream does not contain user header.
+	ErrHeaderExpected = internal.Error("expected header as a first message in stream")
+
+	// KeyStorageGroup is a key for a search object by storage group id.
+	KeyStorageGroup = "STORAGE_GROUP"
+
+	// KeyNoChildren is a key for searching object that have no children links.
+	KeyNoChildren = "LEAF"
+
+	// KeyParent is a key for searching object by id of parent object.
+	KeyParent = "PARENT"
+
+	// KeyHasParent is a key for searching object that have parent link.
+	KeyHasParent = "HAS_PAR"
+
+	// KeyTombstone is a key for searching object that have tombstone header.
+	KeyTombstone = "TOMBSTONE"
+
+	// KeyChild is a key for searching object by id of child link.
+	KeyChild = "CHILD"
+
+	// KeyPrev is a key for searching object by id of previous link.
+	KeyPrev = "PREV"
+
+	// KeyNext is a key for searching object by id of next link.
+	KeyNext = "NEXT"
+
+	// KeyID is a key for searching object by object id.
+	KeyID = "ID"
+
+	// KeyCID is a key for searching object by container id.
+	KeyCID = "CID"
+
+	// KeyOwnerID is a key for searching object by owner id.
+	KeyOwnerID = "OWNERID"
+
+	// KeyRootObject is a key for searching object that are zero-object or do
+	// not have any children.
+	KeyRootObject = "ROOT_OBJECT"
+)
+
+func checkIsNotFull(v interface{}) bool {
+	var obj *Object
+
+	switch t := v.(type) {
+	case *GetResponse:
+		obj = t.GetObject()
+	case *PutRequest:
+		if h := t.GetHeader(); h != nil {
+			obj = h.Object
+		}
+	default:
+		panic("unknown type")
+	}
+
+	return obj == nil || obj.SystemHeader.PayloadLength != uint64(len(obj.Payload)) && !obj.IsLinking()
+}
+
+// NotFull checks if protobuf stream provided whole object for get operation.
+func (m *GetResponse) NotFull() bool { return checkIsNotFull(m) }
+
+// NotFull checks if protobuf stream provided whole object for put operation.
+func (m *PutRequest) NotFull() bool { return checkIsNotFull(m) }
+
+// GetTTL returns TTL value from object put request.
+func (m *PutRequest) GetTTL() uint32 { return m.GetHeader().TTL }
+
+// GetEpoch returns epoch value from object put request.
+func (m *PutRequest) GetEpoch() uint64 { return m.GetHeader().GetEpoch() }
+
+// SetTTL sets TTL value into object put request.
+func (m *PutRequest) SetTTL(ttl uint32) { m.GetHeader().TTL = ttl }
+
+// SetTTL sets TTL value into object get request.
+func (m *GetRequest) SetTTL(ttl uint32) { m.TTL = ttl }
+
+// SetTTL sets TTL value into object head request.
+func (m *HeadRequest) SetTTL(ttl uint32) { m.TTL = ttl }
+
+// SetTTL sets TTL value into object search request.
+func (m *SearchRequest) SetTTL(ttl uint32) { m.TTL = ttl }
+
+// SetTTL sets TTL value into object delete request.
+func (m *DeleteRequest) SetTTL(ttl uint32) { m.TTL = ttl }
+
+// SetTTL sets TTL value into object get range request.
+func (m *GetRangeRequest) SetTTL(ttl uint32) { m.TTL = ttl }
+
+// SetTTL sets TTL value into object get range hash request.
+func (m *GetRangeHashRequest) SetTTL(ttl uint32) { m.TTL = ttl }
+
+// SetEpoch sets epoch value into object put request.
+func (m *PutRequest) SetEpoch(v uint64) { m.GetHeader().Epoch = v }
+
+// SetEpoch sets epoch value into object get request.
+func (m *GetRequest) SetEpoch(v uint64) { m.Epoch = v }
+
+// SetEpoch sets epoch value into object head request.
+func (m *HeadRequest) SetEpoch(v uint64) { m.Epoch = v }
+
+// SetEpoch sets epoch value into object search request.
+func (m *SearchRequest) SetEpoch(v uint64) { m.Epoch = v }
+
+// SetEpoch sets epoch value into object delete request.
+func (m *DeleteRequest) SetEpoch(v uint64) { m.Epoch = v }
+
+// SetEpoch sets epoch value into object get range request.
+func (m *GetRangeRequest) SetEpoch(v uint64) { m.Epoch = v }
+
+// SetEpoch sets epoch value into object get range hash request.
+func (m *GetRangeHashRequest) SetEpoch(v uint64) { m.Epoch = v }
+
+// CID returns container id value from object put request.
+func (m *PutRequest) CID() CID { return m.GetHeader().Object.SystemHeader.CID }
+
+// CID returns container id value from object get request.
+func (m *GetRequest) CID() CID { return m.Address.CID }
+
+// CID returns container id value from object head request.
+func (m *HeadRequest) CID() CID { return m.Address.CID }
+
+// CID returns container id value from object search request.
+func (m *SearchRequest) CID() CID { return m.ContainerID }
+
+// CID returns container id value from object delete request.
+func (m *DeleteRequest) CID() CID { return m.Address.CID }
+
+// CID returns container id value from object get range request.
+func (m *GetRangeRequest) CID() CID { return m.Address.CID }
+
+// CID returns container id value from object get range hash request.
+func (m *GetRangeHashRequest) CID() CID { return m.Address.CID }
+
+// AllowPreviousNetMap returns permission to use previous network map in object put request.
+func (m *PutRequest) AllowPreviousNetMap() bool { return false }
+
+// AllowPreviousNetMap returns permission to use previous network map in object get request.
+func (m *GetRequest) AllowPreviousNetMap() bool { return true }
+
+// AllowPreviousNetMap returns permission to use previous network map in object head request.
+func (m *HeadRequest) AllowPreviousNetMap() bool { return true }
+
+// AllowPreviousNetMap returns permission to use previous network map in object search request.
+func (m *SearchRequest) AllowPreviousNetMap() bool { return true }
+
+// AllowPreviousNetMap returns permission to use previous network map in object delete request.
+func (m *DeleteRequest) AllowPreviousNetMap() bool { return false }
+
+// AllowPreviousNetMap returns permission to use previous network map in object get range request.
+func (m *GetRangeRequest) AllowPreviousNetMap() bool { return false }
+
+// AllowPreviousNetMap returns permission to use previous network map in object get range hash request.
+func (m *GetRangeHashRequest) AllowPreviousNetMap() bool { return false }
diff --git a/object/service.pb.go b/object/service.pb.go
new file mode 100644
index 00000000..aede5cda
--- /dev/null
+++ b/object/service.pb.go
@@ -0,0 +1,4491 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: object/service.proto
+
+package object
+
+import (
+	context "context"
+	fmt "fmt"
+	_ "github.com/gogo/protobuf/gogoproto"
+	proto "github.com/golang/protobuf/proto"
+	refs "github.com/nspcc-dev/neofs-proto/refs"
+	session "github.com/nspcc-dev/neofs-proto/session"
+	grpc "google.golang.org/grpc"
+	codes "google.golang.org/grpc/codes"
+	status "google.golang.org/grpc/status"
+	io "io"
+	math "math"
+	math_bits "math/bits"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
+
+type GetRequest struct {
+	Epoch                uint64       `protobuf:"varint,1,opt,name=Epoch,proto3" json:"Epoch,omitempty"`
+	Address              refs.Address `protobuf:"bytes,2,opt,name=Address,proto3" json:"Address"`
+	TTL                  uint32       `protobuf:"varint,3,opt,name=TTL,proto3" json:"TTL,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}     `json:"-"`
+	XXX_unrecognized     []byte       `json:"-"`
+	XXX_sizecache        int32        `json:"-"`
+}
+
+func (m *GetRequest) Reset()         { *m = GetRequest{} }
+func (m *GetRequest) String() string { return proto.CompactTextString(m) }
+func (*GetRequest) ProtoMessage()    {}
+func (*GetRequest) Descriptor() ([]byte, []int) {
+	return fileDescriptor_dfcdf610ade6a9ce, []int{0}
+}
+func (m *GetRequest) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *GetRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *GetRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_GetRequest.Merge(m, src)
+}
+func (m *GetRequest) XXX_Size() int {
+	return m.Size()
+}
+func (m *GetRequest) XXX_DiscardUnknown() {
+	xxx_messageInfo_GetRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetRequest proto.InternalMessageInfo
+
+func (m *GetRequest) GetEpoch() uint64 {
+	if m != nil {
+		return m.Epoch
+	}
+	return 0
+}
+
+func (m *GetRequest) GetAddress() refs.Address {
+	if m != nil {
+		return m.Address
+	}
+	return refs.Address{}
+}
+
+func (m *GetRequest) GetTTL() uint32 {
+	if m != nil {
+		return m.TTL
+	}
+	return 0
+}
+
+type GetResponse struct {
+	// Types that are valid to be assigned to R:
+	//	*GetResponse_Object
+	//	*GetResponse_Chunk
+	R                    isGetResponse_R `protobuf_oneof:"R"`
+	XXX_NoUnkeyedLiteral struct{}        `json:"-"`
+	XXX_unrecognized     []byte          `json:"-"`
+	XXX_sizecache        int32           `json:"-"`
+}
+
+func (m *GetResponse) Reset()         { *m = GetResponse{} }
+func (m *GetResponse) String() string { return proto.CompactTextString(m) }
+func (*GetResponse) ProtoMessage()    {}
+func (*GetResponse) Descriptor() ([]byte, []int) {
+	return fileDescriptor_dfcdf610ade6a9ce, []int{1}
+}
+func (m *GetResponse) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *GetResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *GetResponse) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_GetResponse.Merge(m, src)
+}
+func (m *GetResponse) XXX_Size() int {
+	return m.Size()
+}
+func (m *GetResponse) XXX_DiscardUnknown() {
+	xxx_messageInfo_GetResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetResponse proto.InternalMessageInfo
+
+type isGetResponse_R interface {
+	isGetResponse_R()
+	MarshalTo([]byte) (int, error)
+	Size() int
+}
+
+type GetResponse_Object struct {
+	Object *Object `protobuf:"bytes,1,opt,name=object,proto3,oneof" json:"object,omitempty"`
+}
+type GetResponse_Chunk struct {
+	Chunk []byte `protobuf:"bytes,2,opt,name=Chunk,proto3,oneof" json:"Chunk,omitempty"`
+}
+
+func (*GetResponse_Object) isGetResponse_R() {}
+func (*GetResponse_Chunk) isGetResponse_R()  {}
+
+func (m *GetResponse) GetR() isGetResponse_R {
+	if m != nil {
+		return m.R
+	}
+	return nil
+}
+
+func (m *GetResponse) GetObject() *Object {
+	if x, ok := m.GetR().(*GetResponse_Object); ok {
+		return x.Object
+	}
+	return nil
+}
+
+func (m *GetResponse) GetChunk() []byte {
+	if x, ok := m.GetR().(*GetResponse_Chunk); ok {
+		return x.Chunk
+	}
+	return nil
+}
+
+// XXX_OneofWrappers is for the internal use of the proto package.
+func (*GetResponse) XXX_OneofWrappers() []interface{} {
+	return []interface{}{
+		(*GetResponse_Object)(nil),
+		(*GetResponse_Chunk)(nil),
+	}
+}
+
+type PutRequest struct {
+	// Types that are valid to be assigned to R:
+	//	*PutRequest_Header
+	//	*PutRequest_Chunk
+	R                    isPutRequest_R `protobuf_oneof:"R"`
+	XXX_NoUnkeyedLiteral struct{}       `json:"-"`
+	XXX_unrecognized     []byte         `json:"-"`
+	XXX_sizecache        int32          `json:"-"`
+}
+
+func (m *PutRequest) Reset()         { *m = PutRequest{} }
+func (m *PutRequest) String() string { return proto.CompactTextString(m) }
+func (*PutRequest) ProtoMessage()    {}
+func (*PutRequest) Descriptor() ([]byte, []int) {
+	return fileDescriptor_dfcdf610ade6a9ce, []int{2}
+}
+func (m *PutRequest) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *PutRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *PutRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_PutRequest.Merge(m, src)
+}
+func (m *PutRequest) XXX_Size() int {
+	return m.Size()
+}
+func (m *PutRequest) XXX_DiscardUnknown() {
+	xxx_messageInfo_PutRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_PutRequest proto.InternalMessageInfo
+
+type isPutRequest_R interface {
+	isPutRequest_R()
+	MarshalTo([]byte) (int, error)
+	Size() int
+}
+
+type PutRequest_Header struct {
+	Header *PutRequest_PutHeader `protobuf:"bytes,1,opt,name=Header,proto3,oneof" json:"Header,omitempty"`
+}
+type PutRequest_Chunk struct {
+	Chunk []byte `protobuf:"bytes,2,opt,name=Chunk,proto3,oneof" json:"Chunk,omitempty"`
+}
+
+func (*PutRequest_Header) isPutRequest_R() {}
+func (*PutRequest_Chunk) isPutRequest_R()  {}
+
+func (m *PutRequest) GetR() isPutRequest_R {
+	if m != nil {
+		return m.R
+	}
+	return nil
+}
+
+func (m *PutRequest) GetHeader() *PutRequest_PutHeader {
+	if x, ok := m.GetR().(*PutRequest_Header); ok {
+		return x.Header
+	}
+	return nil
+}
+
+func (m *PutRequest) GetChunk() []byte {
+	if x, ok := m.GetR().(*PutRequest_Chunk); ok {
+		return x.Chunk
+	}
+	return nil
+}
+
+// XXX_OneofWrappers is for the internal use of the proto package.
+func (*PutRequest) XXX_OneofWrappers() []interface{} {
+	return []interface{}{
+		(*PutRequest_Header)(nil),
+		(*PutRequest_Chunk)(nil),
+	}
+}
+
+type PutRequest_PutHeader struct {
+	Epoch                uint64         `protobuf:"varint,1,opt,name=Epoch,proto3" json:"Epoch,omitempty"`
+	Object               *Object        `protobuf:"bytes,2,opt,name=Object,proto3" json:"Object,omitempty"`
+	TTL                  uint32         `protobuf:"varint,3,opt,name=TTL,proto3" json:"TTL,omitempty"`
+	Token                *session.Token `protobuf:"bytes,4,opt,name=Token,proto3" json:"Token,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}       `json:"-"`
+	XXX_unrecognized     []byte         `json:"-"`
+	XXX_sizecache        int32          `json:"-"`
+}
+
+func (m *PutRequest_PutHeader) Reset()         { *m = PutRequest_PutHeader{} }
+func (m *PutRequest_PutHeader) String() string { return proto.CompactTextString(m) }
+func (*PutRequest_PutHeader) ProtoMessage()    {}
+func (*PutRequest_PutHeader) Descriptor() ([]byte, []int) {
+	return fileDescriptor_dfcdf610ade6a9ce, []int{2, 0}
+}
+func (m *PutRequest_PutHeader) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *PutRequest_PutHeader) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *PutRequest_PutHeader) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_PutRequest_PutHeader.Merge(m, src)
+}
+func (m *PutRequest_PutHeader) XXX_Size() int {
+	return m.Size()
+}
+func (m *PutRequest_PutHeader) XXX_DiscardUnknown() {
+	xxx_messageInfo_PutRequest_PutHeader.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_PutRequest_PutHeader proto.InternalMessageInfo
+
+func (m *PutRequest_PutHeader) GetEpoch() uint64 {
+	if m != nil {
+		return m.Epoch
+	}
+	return 0
+}
+
+func (m *PutRequest_PutHeader) GetObject() *Object {
+	if m != nil {
+		return m.Object
+	}
+	return nil
+}
+
+func (m *PutRequest_PutHeader) GetTTL() uint32 {
+	if m != nil {
+		return m.TTL
+	}
+	return 0
+}
+
+func (m *PutRequest_PutHeader) GetToken() *session.Token {
+	if m != nil {
+		return m.Token
+	}
+	return nil
+}
+
+type PutResponse struct {
+	Address              refs.Address `protobuf:"bytes,1,opt,name=Address,proto3" json:"Address"`
+	XXX_NoUnkeyedLiteral struct{}     `json:"-"`
+	XXX_unrecognized     []byte       `json:"-"`
+	XXX_sizecache        int32        `json:"-"`
+}
+
+func (m *PutResponse) Reset()         { *m = PutResponse{} }
+func (m *PutResponse) String() string { return proto.CompactTextString(m) }
+func (*PutResponse) ProtoMessage()    {}
+func (*PutResponse) Descriptor() ([]byte, []int) {
+	return fileDescriptor_dfcdf610ade6a9ce, []int{3}
+}
+func (m *PutResponse) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *PutResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *PutResponse) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_PutResponse.Merge(m, src)
+}
+func (m *PutResponse) XXX_Size() int {
+	return m.Size()
+}
+func (m *PutResponse) XXX_DiscardUnknown() {
+	xxx_messageInfo_PutResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_PutResponse proto.InternalMessageInfo
+
+func (m *PutResponse) GetAddress() refs.Address {
+	if m != nil {
+		return m.Address
+	}
+	return refs.Address{}
+}
+
+type DeleteRequest struct {
+	Epoch                uint64         `protobuf:"varint,1,opt,name=Epoch,proto3" json:"Epoch,omitempty"`
+	Address              refs.Address   `protobuf:"bytes,2,opt,name=Address,proto3" json:"Address"`
+	OwnerID              OwnerID        `protobuf:"bytes,3,opt,name=OwnerID,proto3,customtype=OwnerID" json:"OwnerID"`
+	TTL                  uint32         `protobuf:"varint,4,opt,name=TTL,proto3" json:"TTL,omitempty"`
+	Token                *session.Token `protobuf:"bytes,5,opt,name=Token,proto3" json:"Token,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}       `json:"-"`
+	XXX_unrecognized     []byte         `json:"-"`
+	XXX_sizecache        int32          `json:"-"`
+}
+
+func (m *DeleteRequest) Reset()         { *m = DeleteRequest{} }
+func (m *DeleteRequest) String() string { return proto.CompactTextString(m) }
+func (*DeleteRequest) ProtoMessage()    {}
+func (*DeleteRequest) Descriptor() ([]byte, []int) {
+	return fileDescriptor_dfcdf610ade6a9ce, []int{4}
+}
+func (m *DeleteRequest) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *DeleteRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *DeleteRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_DeleteRequest.Merge(m, src)
+}
+func (m *DeleteRequest) XXX_Size() int {
+	return m.Size()
+}
+func (m *DeleteRequest) XXX_DiscardUnknown() {
+	xxx_messageInfo_DeleteRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_DeleteRequest proto.InternalMessageInfo
+
+func (m *DeleteRequest) GetEpoch() uint64 {
+	if m != nil {
+		return m.Epoch
+	}
+	return 0
+}
+
+func (m *DeleteRequest) GetAddress() refs.Address {
+	if m != nil {
+		return m.Address
+	}
+	return refs.Address{}
+}
+
+func (m *DeleteRequest) GetTTL() uint32 {
+	if m != nil {
+		return m.TTL
+	}
+	return 0
+}
+
+func (m *DeleteRequest) GetToken() *session.Token {
+	if m != nil {
+		return m.Token
+	}
+	return nil
+}
+
+type DeleteResponse struct {
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *DeleteResponse) Reset()         { *m = DeleteResponse{} }
+func (m *DeleteResponse) String() string { return proto.CompactTextString(m) }
+func (*DeleteResponse) ProtoMessage()    {}
+func (*DeleteResponse) Descriptor() ([]byte, []int) {
+	return fileDescriptor_dfcdf610ade6a9ce, []int{5}
+}
+func (m *DeleteResponse) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *DeleteResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *DeleteResponse) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_DeleteResponse.Merge(m, src)
+}
+func (m *DeleteResponse) XXX_Size() int {
+	return m.Size()
+}
+func (m *DeleteResponse) XXX_DiscardUnknown() {
+	xxx_messageInfo_DeleteResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_DeleteResponse proto.InternalMessageInfo
+
+// HeadRequest.FullHeader == true, for fetch all headers
+type HeadRequest struct {
+	Epoch                uint64   `protobuf:"varint,1,opt,name=Epoch,proto3" json:"Epoch,omitempty"`
+	Address              Address  `protobuf:"bytes,2,opt,name=Address,proto3,customtype=Address" json:"Address"`
+	FullHeaders          bool     `protobuf:"varint,3,opt,name=FullHeaders,proto3" json:"FullHeaders,omitempty"`
+	TTL                  uint32   `protobuf:"varint,4,opt,name=TTL,proto3" json:"TTL,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *HeadRequest) Reset()         { *m = HeadRequest{} }
+func (m *HeadRequest) String() string { return proto.CompactTextString(m) }
+func (*HeadRequest) ProtoMessage()    {}
+func (*HeadRequest) Descriptor() ([]byte, []int) {
+	return fileDescriptor_dfcdf610ade6a9ce, []int{6}
+}
+func (m *HeadRequest) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *HeadRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *HeadRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_HeadRequest.Merge(m, src)
+}
+func (m *HeadRequest) XXX_Size() int {
+	return m.Size()
+}
+func (m *HeadRequest) XXX_DiscardUnknown() {
+	xxx_messageInfo_HeadRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_HeadRequest proto.InternalMessageInfo
+
+func (m *HeadRequest) GetEpoch() uint64 {
+	if m != nil {
+		return m.Epoch
+	}
+	return 0
+}
+
+func (m *HeadRequest) GetFullHeaders() bool {
+	if m != nil {
+		return m.FullHeaders
+	}
+	return false
+}
+
+func (m *HeadRequest) GetTTL() uint32 {
+	if m != nil {
+		return m.TTL
+	}
+	return 0
+}
+
+type HeadResponse struct {
+	Object               *Object  `protobuf:"bytes,1,opt,name=Object,proto3" json:"Object,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *HeadResponse) Reset()         { *m = HeadResponse{} }
+func (m *HeadResponse) String() string { return proto.CompactTextString(m) }
+func (*HeadResponse) ProtoMessage()    {}
+func (*HeadResponse) Descriptor() ([]byte, []int) {
+	return fileDescriptor_dfcdf610ade6a9ce, []int{7}
+}
+func (m *HeadResponse) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *HeadResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *HeadResponse) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_HeadResponse.Merge(m, src)
+}
+func (m *HeadResponse) XXX_Size() int {
+	return m.Size()
+}
+func (m *HeadResponse) XXX_DiscardUnknown() {
+	xxx_messageInfo_HeadResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_HeadResponse proto.InternalMessageInfo
+
+func (m *HeadResponse) GetObject() *Object {
+	if m != nil {
+		return m.Object
+	}
+	return nil
+}
+
+type SearchRequest struct {
+	Epoch                uint64   `protobuf:"varint,1,opt,name=Epoch,proto3" json:"Epoch,omitempty"`
+	Version              uint32   `protobuf:"varint,2,opt,name=Version,proto3" json:"Version,omitempty"`
+	ContainerID          CID      `protobuf:"bytes,3,opt,name=ContainerID,proto3,customtype=CID" json:"ContainerID"`
+	Query                []byte   `protobuf:"bytes,4,opt,name=Query,proto3" json:"Query,omitempty"`
+	TTL                  uint32   `protobuf:"varint,5,opt,name=TTL,proto3" json:"TTL,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *SearchRequest) Reset()         { *m = SearchRequest{} }
+func (m *SearchRequest) String() string { return proto.CompactTextString(m) }
+func (*SearchRequest) ProtoMessage()    {}
+func (*SearchRequest) Descriptor() ([]byte, []int) {
+	return fileDescriptor_dfcdf610ade6a9ce, []int{8}
+}
+func (m *SearchRequest) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *SearchRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *SearchRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_SearchRequest.Merge(m, src)
+}
+func (m *SearchRequest) XXX_Size() int {
+	return m.Size()
+}
+func (m *SearchRequest) XXX_DiscardUnknown() {
+	xxx_messageInfo_SearchRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_SearchRequest proto.InternalMessageInfo
+
+func (m *SearchRequest) GetEpoch() uint64 {
+	if m != nil {
+		return m.Epoch
+	}
+	return 0
+}
+
+func (m *SearchRequest) GetVersion() uint32 {
+	if m != nil {
+		return m.Version
+	}
+	return 0
+}
+
+func (m *SearchRequest) GetQuery() []byte {
+	if m != nil {
+		return m.Query
+	}
+	return nil
+}
+
+func (m *SearchRequest) GetTTL() uint32 {
+	if m != nil {
+		return m.TTL
+	}
+	return 0
+}
+
+type SearchResponse struct {
+	Addresses            []refs.Address `protobuf:"bytes,1,rep,name=Addresses,proto3" json:"Addresses"`
+	XXX_NoUnkeyedLiteral struct{}       `json:"-"`
+	XXX_unrecognized     []byte         `json:"-"`
+	XXX_sizecache        int32          `json:"-"`
+}
+
+func (m *SearchResponse) Reset()         { *m = SearchResponse{} }
+func (m *SearchResponse) String() string { return proto.CompactTextString(m) }
+func (*SearchResponse) ProtoMessage()    {}
+func (*SearchResponse) Descriptor() ([]byte, []int) {
+	return fileDescriptor_dfcdf610ade6a9ce, []int{9}
+}
+func (m *SearchResponse) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *SearchResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *SearchResponse) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_SearchResponse.Merge(m, src)
+}
+func (m *SearchResponse) XXX_Size() int {
+	return m.Size()
+}
+func (m *SearchResponse) XXX_DiscardUnknown() {
+	xxx_messageInfo_SearchResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_SearchResponse proto.InternalMessageInfo
+
+func (m *SearchResponse) GetAddresses() []refs.Address {
+	if m != nil {
+		return m.Addresses
+	}
+	return nil
+}
+
+type GetRangeRequest struct {
+	Epoch                uint64       `protobuf:"varint,1,opt,name=Epoch,proto3" json:"Epoch,omitempty"`
+	Address              refs.Address `protobuf:"bytes,2,opt,name=Address,proto3" json:"Address"`
+	Ranges               []Range      `protobuf:"bytes,3,rep,name=Ranges,proto3" json:"Ranges"`
+	TTL                  uint32       `protobuf:"varint,4,opt,name=TTL,proto3" json:"TTL,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}     `json:"-"`
+	XXX_unrecognized     []byte       `json:"-"`
+	XXX_sizecache        int32        `json:"-"`
+}
+
+func (m *GetRangeRequest) Reset()         { *m = GetRangeRequest{} }
+func (m *GetRangeRequest) String() string { return proto.CompactTextString(m) }
+func (*GetRangeRequest) ProtoMessage()    {}
+func (*GetRangeRequest) Descriptor() ([]byte, []int) {
+	return fileDescriptor_dfcdf610ade6a9ce, []int{10}
+}
+func (m *GetRangeRequest) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *GetRangeRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *GetRangeRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_GetRangeRequest.Merge(m, src)
+}
+func (m *GetRangeRequest) XXX_Size() int {
+	return m.Size()
+}
+func (m *GetRangeRequest) XXX_DiscardUnknown() {
+	xxx_messageInfo_GetRangeRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetRangeRequest proto.InternalMessageInfo
+
+func (m *GetRangeRequest) GetEpoch() uint64 {
+	if m != nil {
+		return m.Epoch
+	}
+	return 0
+}
+
+func (m *GetRangeRequest) GetAddress() refs.Address {
+	if m != nil {
+		return m.Address
+	}
+	return refs.Address{}
+}
+
+func (m *GetRangeRequest) GetRanges() []Range {
+	if m != nil {
+		return m.Ranges
+	}
+	return nil
+}
+
+func (m *GetRangeRequest) GetTTL() uint32 {
+	if m != nil {
+		return m.TTL
+	}
+	return 0
+}
+
+type GetRangeResponse struct {
+	Fragments            [][]byte `protobuf:"bytes,1,rep,name=Fragments,proto3" json:"Fragments,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *GetRangeResponse) Reset()         { *m = GetRangeResponse{} }
+func (m *GetRangeResponse) String() string { return proto.CompactTextString(m) }
+func (*GetRangeResponse) ProtoMessage()    {}
+func (*GetRangeResponse) Descriptor() ([]byte, []int) {
+	return fileDescriptor_dfcdf610ade6a9ce, []int{11}
+}
+func (m *GetRangeResponse) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *GetRangeResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *GetRangeResponse) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_GetRangeResponse.Merge(m, src)
+}
+func (m *GetRangeResponse) XXX_Size() int {
+	return m.Size()
+}
+func (m *GetRangeResponse) XXX_DiscardUnknown() {
+	xxx_messageInfo_GetRangeResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetRangeResponse proto.InternalMessageInfo
+
+func (m *GetRangeResponse) GetFragments() [][]byte {
+	if m != nil {
+		return m.Fragments
+	}
+	return nil
+}
+
+type GetRangeHashRequest struct {
+	Epoch                uint64       `protobuf:"varint,1,opt,name=Epoch,proto3" json:"Epoch,omitempty"`
+	Address              refs.Address `protobuf:"bytes,2,opt,name=Address,proto3" json:"Address"`
+	Ranges               []Range      `protobuf:"bytes,3,rep,name=Ranges,proto3" json:"Ranges"`
+	Salt                 []byte       `protobuf:"bytes,4,opt,name=Salt,proto3" json:"Salt,omitempty"`
+	TTL                  uint32       `protobuf:"varint,5,opt,name=TTL,proto3" json:"TTL,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}     `json:"-"`
+	XXX_unrecognized     []byte       `json:"-"`
+	XXX_sizecache        int32        `json:"-"`
+}
+
+func (m *GetRangeHashRequest) Reset()         { *m = GetRangeHashRequest{} }
+func (m *GetRangeHashRequest) String() string { return proto.CompactTextString(m) }
+func (*GetRangeHashRequest) ProtoMessage()    {}
+func (*GetRangeHashRequest) Descriptor() ([]byte, []int) {
+	return fileDescriptor_dfcdf610ade6a9ce, []int{12}
+}
+func (m *GetRangeHashRequest) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *GetRangeHashRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *GetRangeHashRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_GetRangeHashRequest.Merge(m, src)
+}
+func (m *GetRangeHashRequest) XXX_Size() int {
+	return m.Size()
+}
+func (m *GetRangeHashRequest) XXX_DiscardUnknown() {
+	xxx_messageInfo_GetRangeHashRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetRangeHashRequest proto.InternalMessageInfo
+
+func (m *GetRangeHashRequest) GetEpoch() uint64 {
+	if m != nil {
+		return m.Epoch
+	}
+	return 0
+}
+
+func (m *GetRangeHashRequest) GetAddress() refs.Address {
+	if m != nil {
+		return m.Address
+	}
+	return refs.Address{}
+}
+
+func (m *GetRangeHashRequest) GetRanges() []Range {
+	if m != nil {
+		return m.Ranges
+	}
+	return nil
+}
+
+func (m *GetRangeHashRequest) GetSalt() []byte {
+	if m != nil {
+		return m.Salt
+	}
+	return nil
+}
+
+func (m *GetRangeHashRequest) GetTTL() uint32 {
+	if m != nil {
+		return m.TTL
+	}
+	return 0
+}
+
+type GetRangeHashResponse struct {
+	Hashes               []Hash   `protobuf:"bytes,1,rep,name=Hashes,proto3,customtype=Hash" json:"Hashes"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *GetRangeHashResponse) Reset()         { *m = GetRangeHashResponse{} }
+func (m *GetRangeHashResponse) String() string { return proto.CompactTextString(m) }
+func (*GetRangeHashResponse) ProtoMessage()    {}
+func (*GetRangeHashResponse) Descriptor() ([]byte, []int) {
+	return fileDescriptor_dfcdf610ade6a9ce, []int{13}
+}
+func (m *GetRangeHashResponse) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *GetRangeHashResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *GetRangeHashResponse) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_GetRangeHashResponse.Merge(m, src)
+}
+func (m *GetRangeHashResponse) XXX_Size() int {
+	return m.Size()
+}
+func (m *GetRangeHashResponse) XXX_DiscardUnknown() {
+	xxx_messageInfo_GetRangeHashResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetRangeHashResponse proto.InternalMessageInfo
+
+func init() {
+	proto.RegisterType((*GetRequest)(nil), "object.GetRequest")
+	proto.RegisterType((*GetResponse)(nil), "object.GetResponse")
+	proto.RegisterType((*PutRequest)(nil), "object.PutRequest")
+	proto.RegisterType((*PutRequest_PutHeader)(nil), "object.PutRequest.PutHeader")
+	proto.RegisterType((*PutResponse)(nil), "object.PutResponse")
+	proto.RegisterType((*DeleteRequest)(nil), "object.DeleteRequest")
+	proto.RegisterType((*DeleteResponse)(nil), "object.DeleteResponse")
+	proto.RegisterType((*HeadRequest)(nil), "object.HeadRequest")
+	proto.RegisterType((*HeadResponse)(nil), "object.HeadResponse")
+	proto.RegisterType((*SearchRequest)(nil), "object.SearchRequest")
+	proto.RegisterType((*SearchResponse)(nil), "object.SearchResponse")
+	proto.RegisterType((*GetRangeRequest)(nil), "object.GetRangeRequest")
+	proto.RegisterType((*GetRangeResponse)(nil), "object.GetRangeResponse")
+	proto.RegisterType((*GetRangeHashRequest)(nil), "object.GetRangeHashRequest")
+	proto.RegisterType((*GetRangeHashResponse)(nil), "object.GetRangeHashResponse")
+}
+
+func init() { proto.RegisterFile("object/service.proto", fileDescriptor_dfcdf610ade6a9ce) }
+
+var fileDescriptor_dfcdf610ade6a9ce = []byte{
+	// 793 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x55, 0xc1, 0x4e, 0xdb, 0x4c,
+	0x10, 0xce, 0xfe, 0x49, 0x1c, 0x18, 0x3b, 0x10, 0x2d, 0xf9, 0xf9, 0x23, 0xff, 0x28, 0x44, 0x16,
+	0x6a, 0x53, 0x55, 0x49, 0x28, 0x95, 0xa0, 0x07, 0x38, 0x34, 0xa1, 0x10, 0xa4, 0x4a, 0xd0, 0x25,
+	0xea, 0xa1, 0xb7, 0xc4, 0x59, 0x92, 0x94, 0x60, 0xa7, 0x5e, 0x9b, 0x8a, 0x63, 0x1f, 0xa1, 0x87,
+	0x56, 0x3d, 0xf4, 0x15, 0x7a, 0xee, 0x2b, 0x70, 0xec, 0xb1, 0xea, 0x01, 0x55, 0xa9, 0xfa, 0x1e,
+	0x95, 0x77, 0xd7, 0xb1, 0x13, 0x42, 0xb8, 0x20, 0xf5, 0xe4, 0x9d, 0x6f, 0x66, 0x77, 0xe6, 0x9b,
+	0x6f, 0xbc, 0x0b, 0x59, 0xbb, 0xf5, 0x9a, 0x9a, 0x6e, 0x85, 0x51, 0xe7, 0xbc, 0x67, 0xd2, 0xf2,
+	0xc0, 0xb1, 0x5d, 0x1b, 0x2b, 0x02, 0xd5, 0x33, 0x0e, 0x3d, 0x61, 0x15, 0xf7, 0x62, 0x40, 0x99,
+	0xf0, 0xe8, 0x58, 0xc6, 0x47, 0xb1, 0x25, 0x46, 0x19, 0xeb, 0xd9, 0xd6, 0x18, 0x58, 0xea, 0xf4,
+	0xdc, 0xae, 0xd7, 0x2a, 0x9b, 0xf6, 0x59, 0xa5, 0x63, 0x77, 0xec, 0x0a, 0x87, 0x5b, 0xde, 0x09,
+	0xb7, 0xb8, 0xc1, 0x57, 0x22, 0xdc, 0x30, 0x01, 0xf6, 0xa9, 0x4b, 0xe8, 0x1b, 0x8f, 0x32, 0x17,
+	0x67, 0x21, 0xf9, 0x6c, 0x60, 0x9b, 0xdd, 0x1c, 0x2a, 0xa0, 0x62, 0x82, 0x08, 0x03, 0x97, 0x20,
+	0xf5, 0xb4, 0xdd, 0x76, 0x28, 0x63, 0xb9, 0x7f, 0x0a, 0xa8, 0xa8, 0x6e, 0xa4, 0xcb, 0x7e, 0x7d,
+	0x65, 0x09, 0x56, 0x13, 0x97, 0x57, 0xab, 0x31, 0x12, 0xc4, 0xe0, 0x0c, 0xc4, 0x1b, 0x8d, 0xe7,
+	0xb9, 0x78, 0x01, 0x15, 0xd3, 0xc4, 0x5f, 0x1a, 0x0d, 0x50, 0x79, 0x12, 0x36, 0xb0, 0x2d, 0x46,
+	0x71, 0x11, 0x24, 0x4f, 0x9e, 0x46, 0xdd, 0x58, 0x28, 0x0b, 0xb3, 0x7c, 0xc8, 0x3f, 0xf5, 0x18,
+	0x91, 0x7e, 0xbc, 0x0c, 0xc9, 0x5a, 0xd7, 0xb3, 0x4e, 0x79, 0x5e, 0xad, 0x1e, 0x23, 0xc2, 0xac,
+	0xc6, 0x01, 0x11, 0xe3, 0x37, 0x02, 0x38, 0xf2, 0x46, 0xb5, 0x6f, 0x82, 0x52, 0xa7, 0xcd, 0x36,
+	0x75, 0xe4, 0xa9, 0x2b, 0xc1, 0xa9, 0x61, 0x8c, 0xbf, 0x14, 0x31, 0x7e, 0x0e, 0xb1, 0xba, 0x29,
+	0x87, 0xfe, 0x0e, 0xc1, 0xfc, 0x28, 0xfe, 0x86, 0xce, 0xdc, 0x03, 0x45, 0xd4, 0x2c, 0x1b, 0x33,
+	0xc1, 0x84, 0x48, 0xef, 0xf5, 0x96, 0xe0, 0x35, 0x48, 0x36, 0xec, 0x53, 0x6a, 0xe5, 0x12, 0x72,
+	0xa3, 0xd4, 0xb2, 0xcc, 0x51, 0x22, 0x9c, 0x82, 0xe7, 0x36, 0xa8, 0x9c, 0x82, 0xec, 0x5e, 0x44,
+	0x0d, 0x74, 0xbb, 0x1a, 0xc6, 0x57, 0x04, 0xe9, 0x5d, 0xda, 0xa7, 0x2e, 0xbd, 0x53, 0x91, 0x1f,
+	0x40, 0xea, 0xf0, 0xad, 0x45, 0x9d, 0x83, 0x5d, 0xce, 0x4a, 0xab, 0x2e, 0xfa, 0xfe, 0x1f, 0x57,
+	0xab, 0x01, 0x4c, 0x82, 0x45, 0x40, 0x3e, 0x31, 0x85, 0x7c, 0x72, 0x06, 0x79, 0x23, 0x03, 0x0b,
+	0x41, 0xe1, 0x82, 0xba, 0xf1, 0x1e, 0x81, 0xea, 0xeb, 0x31, 0x9b, 0xc9, 0x93, 0x5b, 0x98, 0x8c,
+	0x2a, 0x95, 0x40, 0x48, 0xaa, 0x00, 0xea, 0x9e, 0xd7, 0xef, 0x0b, 0xc9, 0x19, 0x27, 0x36, 0x47,
+	0xa2, 0xd0, 0x75, 0x2e, 0xc6, 0x26, 0x68, 0xa2, 0x24, 0x29, 0x4f, 0x38, 0x12, 0x68, 0xd6, 0x48,
+	0x18, 0x1f, 0x11, 0xa4, 0x8f, 0x69, 0xd3, 0x31, 0xbb, 0xb3, 0xd9, 0xe4, 0x20, 0xf5, 0x92, 0x3a,
+	0x7e, 0x77, 0x38, 0x9b, 0x34, 0x09, 0x4c, 0x5c, 0x02, 0xb5, 0x66, 0x5b, 0x6e, 0xb3, 0x17, 0x95,
+	0x41, 0x95, 0xe4, 0xe2, 0xb5, 0x83, 0x5d, 0x12, 0xf5, 0xfb, 0xc7, 0xbf, 0xf0, 0xa8, 0x73, 0xc1,
+	0x8b, 0xd7, 0x88, 0x30, 0x02, 0x42, 0xc9, 0x90, 0x50, 0x0d, 0x16, 0x82, 0xba, 0x24, 0xa5, 0x47,
+	0x30, 0x2f, 0x3b, 0x44, 0xfd, 0x99, 0x8b, 0xdf, 0x34, 0x1c, 0x61, 0x94, 0xf1, 0x01, 0xc1, 0xa2,
+	0xff, 0xcb, 0x37, 0xad, 0xce, 0xdd, 0xce, 0xdd, 0x43, 0x50, 0xf8, 0xa1, 0xbe, 0x3a, 0xa2, 0x10,
+	0xd9, 0x5e, 0x8e, 0xca, 0x68, 0x19, 0x32, 0x45, 0xad, 0x75, 0xc8, 0x84, 0x65, 0x49, 0x7a, 0x2b,
+	0x30, 0xbf, 0xe7, 0x34, 0x3b, 0x67, 0xd4, 0x72, 0x05, 0x3d, 0x8d, 0x84, 0x80, 0xf1, 0x05, 0xc1,
+	0x52, 0xb0, 0xa5, 0xde, 0x64, 0xdd, 0xbf, 0xc7, 0x06, 0x43, 0xe2, 0xb8, 0xd9, 0x77, 0xa5, 0x7e,
+	0x7c, 0x3d, 0x45, 0xbe, 0x6d, 0xc8, 0x8e, 0x97, 0x2b, 0x59, 0xae, 0x81, 0xe2, 0xdb, 0x52, 0x41,
+	0xad, 0xaa, 0xc9, 0x41, 0x49, 0xf0, 0x28, 0xe9, 0xdb, 0xf8, 0x1c, 0x87, 0xd4, 0xb1, 0x78, 0x92,
+	0xf0, 0x3a, 0xc4, 0xf7, 0xa9, 0x8b, 0x71, 0x50, 0x53, 0xf8, 0x4e, 0xe8, 0x4b, 0x63, 0x98, 0xc8,
+	0xb0, 0x8e, 0xfc, 0x1d, 0x47, 0x5e, 0x64, 0x47, 0x78, 0xf3, 0x86, 0x3b, 0x22, 0x57, 0x59, 0x11,
+	0xe1, 0x2d, 0x50, 0xc4, 0x3f, 0x8e, 0xff, 0x0d, 0x02, 0xc6, 0x2e, 0x2b, 0x7d, 0x79, 0x12, 0x1e,
+	0xcd, 0x64, 0xc2, 0xff, 0xed, 0xf0, 0xe8, 0xdc, 0xc8, 0xbd, 0xa0, 0x67, 0xc7, 0x41, 0xb9, 0x65,
+	0x0b, 0x14, 0x31, 0xd8, 0x61, 0xae, 0xb1, 0x1f, 0x30, 0xcc, 0x35, 0x31, 0xff, 0x3b, 0x30, 0x17,
+	0xb4, 0x14, 0xff, 0x17, 0x65, 0x1e, 0x99, 0x6e, 0x3d, 0x77, 0xdd, 0x21, 0xb7, 0x1f, 0x80, 0x16,
+	0x55, 0x04, 0xff, 0x3f, 0x19, 0x19, 0x19, 0x2b, 0x7d, 0x65, 0xba, 0x53, 0x1c, 0x55, 0xdd, 0xb9,
+	0x1c, 0xe6, 0xd1, 0xb7, 0x61, 0x1e, 0x7d, 0x1f, 0xe6, 0xd1, 0xcf, 0x61, 0x1e, 0x7d, 0xfa, 0x95,
+	0x8f, 0xbd, 0xba, 0x1f, 0x79, 0xf2, 0x2d, 0x36, 0x30, 0xcd, 0x52, 0x9b, 0x9e, 0x57, 0x2c, 0x6a,
+	0x9f, 0xb0, 0x92, 0x78, 0xf0, 0xc5, 0x99, 0x2d, 0x85, 0x5b, 0x8f, 0xff, 0x04, 0x00, 0x00, 0xff,
+	0xff, 0x37, 0xfc, 0x5a, 0x85, 0x7d, 0x08, 0x00, 0x00,
+}
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ context.Context
+var _ grpc.ClientConn
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the grpc package it is being compiled against.
+const _ = grpc.SupportPackageIsVersion4
+
+// ServiceClient is the client API for Service service.
+//
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
+type ServiceClient interface {
+	// Get the object from a container
+	Get(ctx context.Context, in *GetRequest, opts ...grpc.CallOption) (Service_GetClient, error)
+	// Put the object into a container
+	Put(ctx context.Context, opts ...grpc.CallOption) (Service_PutClient, error)
+	// Delete the object from a container
+	Delete(ctx context.Context, in *DeleteRequest, opts ...grpc.CallOption) (*DeleteResponse, error)
+	// Get MetaInfo
+	Head(ctx context.Context, in *HeadRequest, opts ...grpc.CallOption) (*HeadResponse, error)
+	// Search by MetaInfo
+	Search(ctx context.Context, in *SearchRequest, opts ...grpc.CallOption) (*SearchResponse, error)
+	// Get ranges of object payload
+	GetRange(ctx context.Context, in *GetRangeRequest, opts ...grpc.CallOption) (*GetRangeResponse, error)
+	// Get hashes of object ranges
+	GetRangeHash(ctx context.Context, in *GetRangeHashRequest, opts ...grpc.CallOption) (*GetRangeHashResponse, error)
+}
+
+type serviceClient struct {
+	cc *grpc.ClientConn
+}
+
+func NewServiceClient(cc *grpc.ClientConn) ServiceClient {
+	return &serviceClient{cc}
+}
+
+func (c *serviceClient) Get(ctx context.Context, in *GetRequest, opts ...grpc.CallOption) (Service_GetClient, error) {
+	stream, err := c.cc.NewStream(ctx, &_Service_serviceDesc.Streams[0], "/object.Service/Get", opts...)
+	if err != nil {
+		return nil, err
+	}
+	x := &serviceGetClient{stream}
+	if err := x.ClientStream.SendMsg(in); err != nil {
+		return nil, err
+	}
+	if err := x.ClientStream.CloseSend(); err != nil {
+		return nil, err
+	}
+	return x, nil
+}
+
+type Service_GetClient interface {
+	Recv() (*GetResponse, error)
+	grpc.ClientStream
+}
+
+type serviceGetClient struct {
+	grpc.ClientStream
+}
+
+func (x *serviceGetClient) Recv() (*GetResponse, error) {
+	m := new(GetResponse)
+	if err := x.ClientStream.RecvMsg(m); err != nil {
+		return nil, err
+	}
+	return m, nil
+}
+
+func (c *serviceClient) Put(ctx context.Context, opts ...grpc.CallOption) (Service_PutClient, error) {
+	stream, err := c.cc.NewStream(ctx, &_Service_serviceDesc.Streams[1], "/object.Service/Put", opts...)
+	if err != nil {
+		return nil, err
+	}
+	x := &servicePutClient{stream}
+	return x, nil
+}
+
+type Service_PutClient interface {
+	Send(*PutRequest) error
+	CloseAndRecv() (*PutResponse, error)
+	grpc.ClientStream
+}
+
+type servicePutClient struct {
+	grpc.ClientStream
+}
+
+func (x *servicePutClient) Send(m *PutRequest) error {
+	return x.ClientStream.SendMsg(m)
+}
+
+func (x *servicePutClient) CloseAndRecv() (*PutResponse, error) {
+	if err := x.ClientStream.CloseSend(); err != nil {
+		return nil, err
+	}
+	m := new(PutResponse)
+	if err := x.ClientStream.RecvMsg(m); err != nil {
+		return nil, err
+	}
+	return m, nil
+}
+
+func (c *serviceClient) Delete(ctx context.Context, in *DeleteRequest, opts ...grpc.CallOption) (*DeleteResponse, error) {
+	out := new(DeleteResponse)
+	err := c.cc.Invoke(ctx, "/object.Service/Delete", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *serviceClient) Head(ctx context.Context, in *HeadRequest, opts ...grpc.CallOption) (*HeadResponse, error) {
+	out := new(HeadResponse)
+	err := c.cc.Invoke(ctx, "/object.Service/Head", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *serviceClient) Search(ctx context.Context, in *SearchRequest, opts ...grpc.CallOption) (*SearchResponse, error) {
+	out := new(SearchResponse)
+	err := c.cc.Invoke(ctx, "/object.Service/Search", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *serviceClient) GetRange(ctx context.Context, in *GetRangeRequest, opts ...grpc.CallOption) (*GetRangeResponse, error) {
+	out := new(GetRangeResponse)
+	err := c.cc.Invoke(ctx, "/object.Service/GetRange", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *serviceClient) GetRangeHash(ctx context.Context, in *GetRangeHashRequest, opts ...grpc.CallOption) (*GetRangeHashResponse, error) {
+	out := new(GetRangeHashResponse)
+	err := c.cc.Invoke(ctx, "/object.Service/GetRangeHash", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+// ServiceServer is the server API for Service service.
+type ServiceServer interface {
+	// Get the object from a container
+	Get(*GetRequest, Service_GetServer) error
+	// Put the object into a container
+	Put(Service_PutServer) error
+	// Delete the object from a container
+	Delete(context.Context, *DeleteRequest) (*DeleteResponse, error)
+	// Get MetaInfo
+	Head(context.Context, *HeadRequest) (*HeadResponse, error)
+	// Search by MetaInfo
+	Search(context.Context, *SearchRequest) (*SearchResponse, error)
+	// Get ranges of object payload
+	GetRange(context.Context, *GetRangeRequest) (*GetRangeResponse, error)
+	// Get hashes of object ranges
+	GetRangeHash(context.Context, *GetRangeHashRequest) (*GetRangeHashResponse, error)
+}
+
+// UnimplementedServiceServer can be embedded to have forward compatible implementations.
+type UnimplementedServiceServer struct {
+}
+
+func (*UnimplementedServiceServer) Get(req *GetRequest, srv Service_GetServer) error {
+	return status.Errorf(codes.Unimplemented, "method Get not implemented")
+}
+func (*UnimplementedServiceServer) Put(srv Service_PutServer) error {
+	return status.Errorf(codes.Unimplemented, "method Put not implemented")
+}
+func (*UnimplementedServiceServer) Delete(ctx context.Context, req *DeleteRequest) (*DeleteResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method Delete not implemented")
+}
+func (*UnimplementedServiceServer) Head(ctx context.Context, req *HeadRequest) (*HeadResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method Head not implemented")
+}
+func (*UnimplementedServiceServer) Search(ctx context.Context, req *SearchRequest) (*SearchResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method Search not implemented")
+}
+func (*UnimplementedServiceServer) GetRange(ctx context.Context, req *GetRangeRequest) (*GetRangeResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method GetRange not implemented")
+}
+func (*UnimplementedServiceServer) GetRangeHash(ctx context.Context, req *GetRangeHashRequest) (*GetRangeHashResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method GetRangeHash not implemented")
+}
+
+func RegisterServiceServer(s *grpc.Server, srv ServiceServer) {
+	s.RegisterService(&_Service_serviceDesc, srv)
+}
+
+func _Service_Get_Handler(srv interface{}, stream grpc.ServerStream) error {
+	m := new(GetRequest)
+	if err := stream.RecvMsg(m); err != nil {
+		return err
+	}
+	return srv.(ServiceServer).Get(m, &serviceGetServer{stream})
+}
+
+type Service_GetServer interface {
+	Send(*GetResponse) error
+	grpc.ServerStream
+}
+
+type serviceGetServer struct {
+	grpc.ServerStream
+}
+
+func (x *serviceGetServer) Send(m *GetResponse) error {
+	return x.ServerStream.SendMsg(m)
+}
+
+func _Service_Put_Handler(srv interface{}, stream grpc.ServerStream) error {
+	return srv.(ServiceServer).Put(&servicePutServer{stream})
+}
+
+type Service_PutServer interface {
+	SendAndClose(*PutResponse) error
+	Recv() (*PutRequest, error)
+	grpc.ServerStream
+}
+
+type servicePutServer struct {
+	grpc.ServerStream
+}
+
+func (x *servicePutServer) SendAndClose(m *PutResponse) error {
+	return x.ServerStream.SendMsg(m)
+}
+
+func (x *servicePutServer) Recv() (*PutRequest, error) {
+	m := new(PutRequest)
+	if err := x.ServerStream.RecvMsg(m); err != nil {
+		return nil, err
+	}
+	return m, nil
+}
+
+func _Service_Delete_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(DeleteRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(ServiceServer).Delete(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/object.Service/Delete",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(ServiceServer).Delete(ctx, req.(*DeleteRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _Service_Head_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(HeadRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(ServiceServer).Head(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/object.Service/Head",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(ServiceServer).Head(ctx, req.(*HeadRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _Service_Search_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(SearchRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(ServiceServer).Search(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/object.Service/Search",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(ServiceServer).Search(ctx, req.(*SearchRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _Service_GetRange_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(GetRangeRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(ServiceServer).GetRange(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/object.Service/GetRange",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(ServiceServer).GetRange(ctx, req.(*GetRangeRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _Service_GetRangeHash_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(GetRangeHashRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(ServiceServer).GetRangeHash(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/object.Service/GetRangeHash",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(ServiceServer).GetRangeHash(ctx, req.(*GetRangeHashRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+var _Service_serviceDesc = grpc.ServiceDesc{
+	ServiceName: "object.Service",
+	HandlerType: (*ServiceServer)(nil),
+	Methods: []grpc.MethodDesc{
+		{
+			MethodName: "Delete",
+			Handler:    _Service_Delete_Handler,
+		},
+		{
+			MethodName: "Head",
+			Handler:    _Service_Head_Handler,
+		},
+		{
+			MethodName: "Search",
+			Handler:    _Service_Search_Handler,
+		},
+		{
+			MethodName: "GetRange",
+			Handler:    _Service_GetRange_Handler,
+		},
+		{
+			MethodName: "GetRangeHash",
+			Handler:    _Service_GetRangeHash_Handler,
+		},
+	},
+	Streams: []grpc.StreamDesc{
+		{
+			StreamName:    "Get",
+			Handler:       _Service_Get_Handler,
+			ServerStreams: true,
+		},
+		{
+			StreamName:    "Put",
+			Handler:       _Service_Put_Handler,
+			ClientStreams: true,
+		},
+	},
+	Metadata: "object/service.proto",
+}
+
+func (m *GetRequest) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *GetRequest) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *GetRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if m.TTL != 0 {
+		i = encodeVarintService(dAtA, i, uint64(m.TTL))
+		i--
+		dAtA[i] = 0x18
+	}
+	{
+		size, err := m.Address.MarshalToSizedBuffer(dAtA[:i])
+		if err != nil {
+			return 0, err
+		}
+		i -= size
+		i = encodeVarintService(dAtA, i, uint64(size))
+	}
+	i--
+	dAtA[i] = 0x12
+	if m.Epoch != 0 {
+		i = encodeVarintService(dAtA, i, uint64(m.Epoch))
+		i--
+		dAtA[i] = 0x8
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *GetResponse) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *GetResponse) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *GetResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if m.R != nil {
+		{
+			size := m.R.Size()
+			i -= size
+			if _, err := m.R.MarshalTo(dAtA[i:]); err != nil {
+				return 0, err
+			}
+		}
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *GetResponse_Object) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *GetResponse_Object) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	if m.Object != nil {
+		{
+			size, err := m.Object.MarshalToSizedBuffer(dAtA[:i])
+			if err != nil {
+				return 0, err
+			}
+			i -= size
+			i = encodeVarintService(dAtA, i, uint64(size))
+		}
+		i--
+		dAtA[i] = 0xa
+	}
+	return len(dAtA) - i, nil
+}
+func (m *GetResponse_Chunk) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *GetResponse_Chunk) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	if m.Chunk != nil {
+		i -= len(m.Chunk)
+		copy(dAtA[i:], m.Chunk)
+		i = encodeVarintService(dAtA, i, uint64(len(m.Chunk)))
+		i--
+		dAtA[i] = 0x12
+	}
+	return len(dAtA) - i, nil
+}
+func (m *PutRequest) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *PutRequest) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *PutRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if m.R != nil {
+		{
+			size := m.R.Size()
+			i -= size
+			if _, err := m.R.MarshalTo(dAtA[i:]); err != nil {
+				return 0, err
+			}
+		}
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *PutRequest_Header) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *PutRequest_Header) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	if m.Header != nil {
+		{
+			size, err := m.Header.MarshalToSizedBuffer(dAtA[:i])
+			if err != nil {
+				return 0, err
+			}
+			i -= size
+			i = encodeVarintService(dAtA, i, uint64(size))
+		}
+		i--
+		dAtA[i] = 0xa
+	}
+	return len(dAtA) - i, nil
+}
+func (m *PutRequest_Chunk) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *PutRequest_Chunk) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	if m.Chunk != nil {
+		i -= len(m.Chunk)
+		copy(dAtA[i:], m.Chunk)
+		i = encodeVarintService(dAtA, i, uint64(len(m.Chunk)))
+		i--
+		dAtA[i] = 0x12
+	}
+	return len(dAtA) - i, nil
+}
+func (m *PutRequest_PutHeader) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *PutRequest_PutHeader) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *PutRequest_PutHeader) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if m.Token != nil {
+		{
+			size, err := m.Token.MarshalToSizedBuffer(dAtA[:i])
+			if err != nil {
+				return 0, err
+			}
+			i -= size
+			i = encodeVarintService(dAtA, i, uint64(size))
+		}
+		i--
+		dAtA[i] = 0x22
+	}
+	if m.TTL != 0 {
+		i = encodeVarintService(dAtA, i, uint64(m.TTL))
+		i--
+		dAtA[i] = 0x18
+	}
+	if m.Object != nil {
+		{
+			size, err := m.Object.MarshalToSizedBuffer(dAtA[:i])
+			if err != nil {
+				return 0, err
+			}
+			i -= size
+			i = encodeVarintService(dAtA, i, uint64(size))
+		}
+		i--
+		dAtA[i] = 0x12
+	}
+	if m.Epoch != 0 {
+		i = encodeVarintService(dAtA, i, uint64(m.Epoch))
+		i--
+		dAtA[i] = 0x8
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *PutResponse) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *PutResponse) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *PutResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	{
+		size, err := m.Address.MarshalToSizedBuffer(dAtA[:i])
+		if err != nil {
+			return 0, err
+		}
+		i -= size
+		i = encodeVarintService(dAtA, i, uint64(size))
+	}
+	i--
+	dAtA[i] = 0xa
+	return len(dAtA) - i, nil
+}
+
+func (m *DeleteRequest) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *DeleteRequest) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *DeleteRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if m.Token != nil {
+		{
+			size, err := m.Token.MarshalToSizedBuffer(dAtA[:i])
+			if err != nil {
+				return 0, err
+			}
+			i -= size
+			i = encodeVarintService(dAtA, i, uint64(size))
+		}
+		i--
+		dAtA[i] = 0x2a
+	}
+	if m.TTL != 0 {
+		i = encodeVarintService(dAtA, i, uint64(m.TTL))
+		i--
+		dAtA[i] = 0x20
+	}
+	{
+		size := m.OwnerID.Size()
+		i -= size
+		if _, err := m.OwnerID.MarshalTo(dAtA[i:]); err != nil {
+			return 0, err
+		}
+		i = encodeVarintService(dAtA, i, uint64(size))
+	}
+	i--
+	dAtA[i] = 0x1a
+	{
+		size, err := m.Address.MarshalToSizedBuffer(dAtA[:i])
+		if err != nil {
+			return 0, err
+		}
+		i -= size
+		i = encodeVarintService(dAtA, i, uint64(size))
+	}
+	i--
+	dAtA[i] = 0x12
+	if m.Epoch != 0 {
+		i = encodeVarintService(dAtA, i, uint64(m.Epoch))
+		i--
+		dAtA[i] = 0x8
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *DeleteResponse) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *DeleteResponse) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *DeleteResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *HeadRequest) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *HeadRequest) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *HeadRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if m.TTL != 0 {
+		i = encodeVarintService(dAtA, i, uint64(m.TTL))
+		i--
+		dAtA[i] = 0x20
+	}
+	if m.FullHeaders {
+		i--
+		if m.FullHeaders {
+			dAtA[i] = 1
+		} else {
+			dAtA[i] = 0
+		}
+		i--
+		dAtA[i] = 0x18
+	}
+	{
+		size := m.Address.Size()
+		i -= size
+		if _, err := m.Address.MarshalTo(dAtA[i:]); err != nil {
+			return 0, err
+		}
+		i = encodeVarintService(dAtA, i, uint64(size))
+	}
+	i--
+	dAtA[i] = 0x12
+	if m.Epoch != 0 {
+		i = encodeVarintService(dAtA, i, uint64(m.Epoch))
+		i--
+		dAtA[i] = 0x8
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *HeadResponse) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *HeadResponse) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *HeadResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if m.Object != nil {
+		{
+			size, err := m.Object.MarshalToSizedBuffer(dAtA[:i])
+			if err != nil {
+				return 0, err
+			}
+			i -= size
+			i = encodeVarintService(dAtA, i, uint64(size))
+		}
+		i--
+		dAtA[i] = 0xa
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *SearchRequest) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *SearchRequest) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *SearchRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if m.TTL != 0 {
+		i = encodeVarintService(dAtA, i, uint64(m.TTL))
+		i--
+		dAtA[i] = 0x28
+	}
+	if len(m.Query) > 0 {
+		i -= len(m.Query)
+		copy(dAtA[i:], m.Query)
+		i = encodeVarintService(dAtA, i, uint64(len(m.Query)))
+		i--
+		dAtA[i] = 0x22
+	}
+	{
+		size := m.ContainerID.Size()
+		i -= size
+		if _, err := m.ContainerID.MarshalTo(dAtA[i:]); err != nil {
+			return 0, err
+		}
+		i = encodeVarintService(dAtA, i, uint64(size))
+	}
+	i--
+	dAtA[i] = 0x1a
+	if m.Version != 0 {
+		i = encodeVarintService(dAtA, i, uint64(m.Version))
+		i--
+		dAtA[i] = 0x10
+	}
+	if m.Epoch != 0 {
+		i = encodeVarintService(dAtA, i, uint64(m.Epoch))
+		i--
+		dAtA[i] = 0x8
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *SearchResponse) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *SearchResponse) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *SearchResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if len(m.Addresses) > 0 {
+		for iNdEx := len(m.Addresses) - 1; iNdEx >= 0; iNdEx-- {
+			{
+				size, err := m.Addresses[iNdEx].MarshalToSizedBuffer(dAtA[:i])
+				if err != nil {
+					return 0, err
+				}
+				i -= size
+				i = encodeVarintService(dAtA, i, uint64(size))
+			}
+			i--
+			dAtA[i] = 0xa
+		}
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *GetRangeRequest) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *GetRangeRequest) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *GetRangeRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if m.TTL != 0 {
+		i = encodeVarintService(dAtA, i, uint64(m.TTL))
+		i--
+		dAtA[i] = 0x20
+	}
+	if len(m.Ranges) > 0 {
+		for iNdEx := len(m.Ranges) - 1; iNdEx >= 0; iNdEx-- {
+			{
+				size, err := m.Ranges[iNdEx].MarshalToSizedBuffer(dAtA[:i])
+				if err != nil {
+					return 0, err
+				}
+				i -= size
+				i = encodeVarintService(dAtA, i, uint64(size))
+			}
+			i--
+			dAtA[i] = 0x1a
+		}
+	}
+	{
+		size, err := m.Address.MarshalToSizedBuffer(dAtA[:i])
+		if err != nil {
+			return 0, err
+		}
+		i -= size
+		i = encodeVarintService(dAtA, i, uint64(size))
+	}
+	i--
+	dAtA[i] = 0x12
+	if m.Epoch != 0 {
+		i = encodeVarintService(dAtA, i, uint64(m.Epoch))
+		i--
+		dAtA[i] = 0x8
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *GetRangeResponse) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *GetRangeResponse) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *GetRangeResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if len(m.Fragments) > 0 {
+		for iNdEx := len(m.Fragments) - 1; iNdEx >= 0; iNdEx-- {
+			i -= len(m.Fragments[iNdEx])
+			copy(dAtA[i:], m.Fragments[iNdEx])
+			i = encodeVarintService(dAtA, i, uint64(len(m.Fragments[iNdEx])))
+			i--
+			dAtA[i] = 0xa
+		}
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *GetRangeHashRequest) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *GetRangeHashRequest) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *GetRangeHashRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if m.TTL != 0 {
+		i = encodeVarintService(dAtA, i, uint64(m.TTL))
+		i--
+		dAtA[i] = 0x28
+	}
+	if len(m.Salt) > 0 {
+		i -= len(m.Salt)
+		copy(dAtA[i:], m.Salt)
+		i = encodeVarintService(dAtA, i, uint64(len(m.Salt)))
+		i--
+		dAtA[i] = 0x22
+	}
+	if len(m.Ranges) > 0 {
+		for iNdEx := len(m.Ranges) - 1; iNdEx >= 0; iNdEx-- {
+			{
+				size, err := m.Ranges[iNdEx].MarshalToSizedBuffer(dAtA[:i])
+				if err != nil {
+					return 0, err
+				}
+				i -= size
+				i = encodeVarintService(dAtA, i, uint64(size))
+			}
+			i--
+			dAtA[i] = 0x1a
+		}
+	}
+	{
+		size, err := m.Address.MarshalToSizedBuffer(dAtA[:i])
+		if err != nil {
+			return 0, err
+		}
+		i -= size
+		i = encodeVarintService(dAtA, i, uint64(size))
+	}
+	i--
+	dAtA[i] = 0x12
+	if m.Epoch != 0 {
+		i = encodeVarintService(dAtA, i, uint64(m.Epoch))
+		i--
+		dAtA[i] = 0x8
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *GetRangeHashResponse) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *GetRangeHashResponse) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *GetRangeHashResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if len(m.Hashes) > 0 {
+		for iNdEx := len(m.Hashes) - 1; iNdEx >= 0; iNdEx-- {
+			{
+				size := m.Hashes[iNdEx].Size()
+				i -= size
+				if _, err := m.Hashes[iNdEx].MarshalTo(dAtA[i:]); err != nil {
+					return 0, err
+				}
+				i = encodeVarintService(dAtA, i, uint64(size))
+			}
+			i--
+			dAtA[i] = 0xa
+		}
+	}
+	return len(dAtA) - i, nil
+}
+
+func encodeVarintService(dAtA []byte, offset int, v uint64) int {
+	offset -= sovService(v)
+	base := offset
+	for v >= 1<<7 {
+		dAtA[offset] = uint8(v&0x7f | 0x80)
+		v >>= 7
+		offset++
+	}
+	dAtA[offset] = uint8(v)
+	return base
+}
+func (m *GetRequest) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.Epoch != 0 {
+		n += 1 + sovService(uint64(m.Epoch))
+	}
+	l = m.Address.Size()
+	n += 1 + l + sovService(uint64(l))
+	if m.TTL != 0 {
+		n += 1 + sovService(uint64(m.TTL))
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *GetResponse) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.R != nil {
+		n += m.R.Size()
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *GetResponse_Object) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.Object != nil {
+		l = m.Object.Size()
+		n += 1 + l + sovService(uint64(l))
+	}
+	return n
+}
+func (m *GetResponse_Chunk) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.Chunk != nil {
+		l = len(m.Chunk)
+		n += 1 + l + sovService(uint64(l))
+	}
+	return n
+}
+func (m *PutRequest) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.R != nil {
+		n += m.R.Size()
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *PutRequest_Header) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.Header != nil {
+		l = m.Header.Size()
+		n += 1 + l + sovService(uint64(l))
+	}
+	return n
+}
+func (m *PutRequest_Chunk) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.Chunk != nil {
+		l = len(m.Chunk)
+		n += 1 + l + sovService(uint64(l))
+	}
+	return n
+}
+func (m *PutRequest_PutHeader) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.Epoch != 0 {
+		n += 1 + sovService(uint64(m.Epoch))
+	}
+	if m.Object != nil {
+		l = m.Object.Size()
+		n += 1 + l + sovService(uint64(l))
+	}
+	if m.TTL != 0 {
+		n += 1 + sovService(uint64(m.TTL))
+	}
+	if m.Token != nil {
+		l = m.Token.Size()
+		n += 1 + l + sovService(uint64(l))
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *PutResponse) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = m.Address.Size()
+	n += 1 + l + sovService(uint64(l))
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *DeleteRequest) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.Epoch != 0 {
+		n += 1 + sovService(uint64(m.Epoch))
+	}
+	l = m.Address.Size()
+	n += 1 + l + sovService(uint64(l))
+	l = m.OwnerID.Size()
+	n += 1 + l + sovService(uint64(l))
+	if m.TTL != 0 {
+		n += 1 + sovService(uint64(m.TTL))
+	}
+	if m.Token != nil {
+		l = m.Token.Size()
+		n += 1 + l + sovService(uint64(l))
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *DeleteResponse) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *HeadRequest) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.Epoch != 0 {
+		n += 1 + sovService(uint64(m.Epoch))
+	}
+	l = m.Address.Size()
+	n += 1 + l + sovService(uint64(l))
+	if m.FullHeaders {
+		n += 2
+	}
+	if m.TTL != 0 {
+		n += 1 + sovService(uint64(m.TTL))
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *HeadResponse) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.Object != nil {
+		l = m.Object.Size()
+		n += 1 + l + sovService(uint64(l))
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *SearchRequest) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.Epoch != 0 {
+		n += 1 + sovService(uint64(m.Epoch))
+	}
+	if m.Version != 0 {
+		n += 1 + sovService(uint64(m.Version))
+	}
+	l = m.ContainerID.Size()
+	n += 1 + l + sovService(uint64(l))
+	l = len(m.Query)
+	if l > 0 {
+		n += 1 + l + sovService(uint64(l))
+	}
+	if m.TTL != 0 {
+		n += 1 + sovService(uint64(m.TTL))
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *SearchResponse) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if len(m.Addresses) > 0 {
+		for _, e := range m.Addresses {
+			l = e.Size()
+			n += 1 + l + sovService(uint64(l))
+		}
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *GetRangeRequest) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.Epoch != 0 {
+		n += 1 + sovService(uint64(m.Epoch))
+	}
+	l = m.Address.Size()
+	n += 1 + l + sovService(uint64(l))
+	if len(m.Ranges) > 0 {
+		for _, e := range m.Ranges {
+			l = e.Size()
+			n += 1 + l + sovService(uint64(l))
+		}
+	}
+	if m.TTL != 0 {
+		n += 1 + sovService(uint64(m.TTL))
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *GetRangeResponse) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if len(m.Fragments) > 0 {
+		for _, b := range m.Fragments {
+			l = len(b)
+			n += 1 + l + sovService(uint64(l))
+		}
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *GetRangeHashRequest) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.Epoch != 0 {
+		n += 1 + sovService(uint64(m.Epoch))
+	}
+	l = m.Address.Size()
+	n += 1 + l + sovService(uint64(l))
+	if len(m.Ranges) > 0 {
+		for _, e := range m.Ranges {
+			l = e.Size()
+			n += 1 + l + sovService(uint64(l))
+		}
+	}
+	l = len(m.Salt)
+	if l > 0 {
+		n += 1 + l + sovService(uint64(l))
+	}
+	if m.TTL != 0 {
+		n += 1 + sovService(uint64(m.TTL))
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *GetRangeHashResponse) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if len(m.Hashes) > 0 {
+		for _, e := range m.Hashes {
+			l = e.Size()
+			n += 1 + l + sovService(uint64(l))
+		}
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func sovService(x uint64) (n int) {
+	return (math_bits.Len64(x|1) + 6) / 7
+}
+func sozService(x uint64) (n int) {
+	return sovService(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+func (m *GetRequest) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowService
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: GetRequest: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: GetRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Epoch", wireType)
+			}
+			m.Epoch = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.Epoch |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthService
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthService
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.Address.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 3:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field TTL", wireType)
+			}
+			m.TTL = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.TTL |= uint32(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		default:
+			iNdEx = preIndex
+			skippy, err := skipService(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *GetResponse) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowService
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: GetResponse: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: GetResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Object", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthService
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthService
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			v := &Object{}
+			if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			m.R = &GetResponse_Object{v}
+			iNdEx = postIndex
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Chunk", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthService
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthService
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			v := make([]byte, postIndex-iNdEx)
+			copy(v, dAtA[iNdEx:postIndex])
+			m.R = &GetResponse_Chunk{v}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipService(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *PutRequest) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowService
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: PutRequest: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: PutRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Header", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthService
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthService
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			v := &PutRequest_PutHeader{}
+			if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			m.R = &PutRequest_Header{v}
+			iNdEx = postIndex
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Chunk", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthService
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthService
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			v := make([]byte, postIndex-iNdEx)
+			copy(v, dAtA[iNdEx:postIndex])
+			m.R = &PutRequest_Chunk{v}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipService(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *PutRequest_PutHeader) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowService
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: PutHeader: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: PutHeader: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Epoch", wireType)
+			}
+			m.Epoch = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.Epoch |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Object", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthService
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthService
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if m.Object == nil {
+				m.Object = &Object{}
+			}
+			if err := m.Object.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 3:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field TTL", wireType)
+			}
+			m.TTL = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.TTL |= uint32(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		case 4:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Token", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthService
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthService
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if m.Token == nil {
+				m.Token = &session.Token{}
+			}
+			if err := m.Token.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipService(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *PutResponse) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowService
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: PutResponse: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: PutResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthService
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthService
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.Address.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipService(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *DeleteRequest) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowService
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: DeleteRequest: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: DeleteRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Epoch", wireType)
+			}
+			m.Epoch = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.Epoch |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthService
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthService
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.Address.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 3:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field OwnerID", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthService
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthService
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.OwnerID.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 4:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field TTL", wireType)
+			}
+			m.TTL = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.TTL |= uint32(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		case 5:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Token", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthService
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthService
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if m.Token == nil {
+				m.Token = &session.Token{}
+			}
+			if err := m.Token.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipService(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *DeleteResponse) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowService
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: DeleteResponse: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: DeleteResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		default:
+			iNdEx = preIndex
+			skippy, err := skipService(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *HeadRequest) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowService
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: HeadRequest: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: HeadRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Epoch", wireType)
+			}
+			m.Epoch = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.Epoch |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthService
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthService
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.Address.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 3:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field FullHeaders", wireType)
+			}
+			var v int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				v |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			m.FullHeaders = bool(v != 0)
+		case 4:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field TTL", wireType)
+			}
+			m.TTL = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.TTL |= uint32(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		default:
+			iNdEx = preIndex
+			skippy, err := skipService(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *HeadResponse) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowService
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: HeadResponse: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: HeadResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Object", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthService
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthService
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if m.Object == nil {
+				m.Object = &Object{}
+			}
+			if err := m.Object.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipService(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *SearchRequest) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowService
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: SearchRequest: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: SearchRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Epoch", wireType)
+			}
+			m.Epoch = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.Epoch |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		case 2:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Version", wireType)
+			}
+			m.Version = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.Version |= uint32(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		case 3:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field ContainerID", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthService
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthService
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.ContainerID.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 4:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Query", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthService
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthService
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Query = append(m.Query[:0], dAtA[iNdEx:postIndex]...)
+			if m.Query == nil {
+				m.Query = []byte{}
+			}
+			iNdEx = postIndex
+		case 5:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field TTL", wireType)
+			}
+			m.TTL = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.TTL |= uint32(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		default:
+			iNdEx = preIndex
+			skippy, err := skipService(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *SearchResponse) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowService
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: SearchResponse: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: SearchResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Addresses", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthService
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthService
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Addresses = append(m.Addresses, refs.Address{})
+			if err := m.Addresses[len(m.Addresses)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipService(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *GetRangeRequest) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowService
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: GetRangeRequest: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: GetRangeRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Epoch", wireType)
+			}
+			m.Epoch = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.Epoch |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthService
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthService
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.Address.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 3:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Ranges", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthService
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthService
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Ranges = append(m.Ranges, Range{})
+			if err := m.Ranges[len(m.Ranges)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 4:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field TTL", wireType)
+			}
+			m.TTL = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.TTL |= uint32(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		default:
+			iNdEx = preIndex
+			skippy, err := skipService(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *GetRangeResponse) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowService
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: GetRangeResponse: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: GetRangeResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Fragments", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthService
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthService
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Fragments = append(m.Fragments, make([]byte, postIndex-iNdEx))
+			copy(m.Fragments[len(m.Fragments)-1], dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipService(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *GetRangeHashRequest) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowService
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: GetRangeHashRequest: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: GetRangeHashRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Epoch", wireType)
+			}
+			m.Epoch = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.Epoch |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthService
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthService
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.Address.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 3:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Ranges", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthService
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthService
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Ranges = append(m.Ranges, Range{})
+			if err := m.Ranges[len(m.Ranges)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 4:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Salt", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthService
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthService
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Salt = append(m.Salt[:0], dAtA[iNdEx:postIndex]...)
+			if m.Salt == nil {
+				m.Salt = []byte{}
+			}
+			iNdEx = postIndex
+		case 5:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field TTL", wireType)
+			}
+			m.TTL = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.TTL |= uint32(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		default:
+			iNdEx = preIndex
+			skippy, err := skipService(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *GetRangeHashResponse) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowService
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: GetRangeHashResponse: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: GetRangeHashResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Hashes", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthService
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthService
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			var v Hash
+			m.Hashes = append(m.Hashes, v)
+			if err := m.Hashes[len(m.Hashes)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipService(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func skipService(dAtA []byte) (n int, err error) {
+	l := len(dAtA)
+	iNdEx := 0
+	depth := 0
+	for iNdEx < l {
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return 0, ErrIntOverflowService
+			}
+			if iNdEx >= l {
+				return 0, io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= (uint64(b) & 0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		wireType := int(wire & 0x7)
+		switch wireType {
+		case 0:
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return 0, ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return 0, io.ErrUnexpectedEOF
+				}
+				iNdEx++
+				if dAtA[iNdEx-1] < 0x80 {
+					break
+				}
+			}
+		case 1:
+			iNdEx += 8
+		case 2:
+			var length int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return 0, ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return 0, io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				length |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if length < 0 {
+				return 0, ErrInvalidLengthService
+			}
+			iNdEx += length
+		case 3:
+			depth++
+		case 4:
+			if depth == 0 {
+				return 0, ErrUnexpectedEndOfGroupService
+			}
+			depth--
+		case 5:
+			iNdEx += 4
+		default:
+			return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+		}
+		if iNdEx < 0 {
+			return 0, ErrInvalidLengthService
+		}
+		if depth == 0 {
+			return iNdEx, nil
+		}
+	}
+	return 0, io.ErrUnexpectedEOF
+}
+
+var (
+	ErrInvalidLengthService        = fmt.Errorf("proto: negative length found during unmarshaling")
+	ErrIntOverflowService          = fmt.Errorf("proto: integer overflow")
+	ErrUnexpectedEndOfGroupService = fmt.Errorf("proto: unexpected end of group")
+)
diff --git a/object/service.proto b/object/service.proto
new file mode 100644
index 00000000..0a033838
--- /dev/null
+++ b/object/service.proto
@@ -0,0 +1,119 @@
+syntax = "proto3";
+package object;
+option go_package = "github.com/nspcc-dev/neofs-proto/object";
+
+import "refs/types.proto";
+import "object/types.proto";
+import "session/types.proto";
+import "github.com/gogo/protobuf/gogoproto/gogo.proto";
+
+option (gogoproto.stable_marshaler_all) = true;
+
+service Service {
+    // Get the object from a container
+    rpc Get(GetRequest) returns (stream GetResponse);
+
+    // Put the object into a container
+    rpc Put(stream PutRequest) returns (PutResponse);
+
+    // Delete the object from a container
+    rpc Delete(DeleteRequest) returns (DeleteResponse);
+
+    // Get MetaInfo
+    rpc Head(HeadRequest) returns (HeadResponse);
+
+    // Search by MetaInfo
+    rpc Search(SearchRequest) returns (SearchResponse);
+
+    // Get ranges of object payload
+    rpc GetRange(GetRangeRequest) returns (GetRangeResponse);
+
+    // Get hashes of object ranges
+    rpc GetRangeHash(GetRangeHashRequest) returns (GetRangeHashResponse);
+}
+
+message GetRequest {
+    uint64 Epoch         = 1;
+    refs.Address Address = 2 [(gogoproto.nullable) = false];
+    uint32 TTL           = 3;
+}
+
+message GetResponse {
+    oneof R {
+        Object object = 1;
+        bytes Chunk   = 2;
+    }
+}
+
+message PutRequest {
+    message PutHeader {
+        uint64 Epoch        = 1;
+        Object Object       = 2;
+        uint32 TTL          = 3;
+        session.Token Token = 4;
+    }
+
+    oneof R {
+        PutHeader Header = 1;
+        bytes Chunk      = 2;
+    }
+}
+
+message PutResponse {
+    refs.Address Address = 1 [(gogoproto.nullable) = false];
+}
+message DeleteRequest {
+    uint64 Epoch         = 1;
+    refs.Address Address = 2 [(gogoproto.nullable) = false];
+    bytes OwnerID        = 3 [(gogoproto.nullable) = false, (gogoproto.customtype) = "OwnerID"];
+    uint32 TTL           = 4;
+    session.Token Token  = 5;
+}
+message DeleteResponse {}
+
+// HeadRequest.FullHeader == true, for fetch all headers
+message HeadRequest {
+    uint64 Epoch         = 1;
+    refs.Address Address = 2 [(gogoproto.nullable) = false, (gogoproto.customtype) = "Address"];
+    bool FullHeaders     = 3;
+    uint32 TTL           = 4;
+}
+message HeadResponse {
+    Object Object = 1;
+}
+
+message SearchRequest {
+    uint64 Epoch         = 1;
+    uint32 Version       = 2;
+    bytes ContainerID    = 3 [(gogoproto.nullable) = false, (gogoproto.customtype) = "CID"];
+    bytes Query          = 4;
+    uint32 TTL           = 5;
+}
+
+message SearchResponse {
+    repeated refs.Address Addresses = 1 [(gogoproto.nullable) = false];
+}
+
+message GetRangeRequest {
+    uint64 Epoch          = 1;
+    refs.Address Address  = 2 [(gogoproto.nullable) = false];
+    repeated Range Ranges = 3 [(gogoproto.nullable) = false];
+    uint32 TTL            = 4;
+}
+
+message GetRangeResponse {
+    repeated bytes Fragments = 1;
+}
+
+message GetRangeHashRequest {
+    uint64 Epoch          = 1;
+    refs.Address Address  = 2 [(gogoproto.nullable) = false];
+    repeated Range Ranges = 3 [(gogoproto.nullable) = false];
+    bytes Salt            = 4;
+    uint32 TTL            = 5;
+}
+
+message GetRangeHashResponse {
+    repeated bytes Hashes = 1 [(gogoproto.customtype) = "Hash", (gogoproto.nullable) = false];
+}
+
diff --git a/object/sg.go b/object/sg.go
new file mode 100644
index 00000000..1b48b3ee
--- /dev/null
+++ b/object/sg.go
@@ -0,0 +1,66 @@
+package object
+
+import (
+	"bytes"
+	"sort"
+)
+
+// Here are defined getter functions for objects that contain storage group
+// information.
+
+type (
+	// IDList is a slice of object ids, that can be sorted.
+	IDList []ID
+
+	// ZoneInfo provides validation info of storage group.
+	ZoneInfo struct {
+		Hash
+		Size uint64
+	}
+
+	// IdentificationInfo provides meta information about storage group.
+	IdentificationInfo struct {
+		SGID
+		CID
+		OwnerID
+	}
+)
+
+// Len returns amount of object ids in IDList.
+func (s IDList) Len() int { return len(s) }
+
+// Less returns byte comparision between IDList[i] and IDList[j].
+func (s IDList) Less(i, j int) bool { return bytes.Compare(s[i].Bytes(), s[j].Bytes()) == -1 }
+
+// Swap swaps element with i and j index in IDList.
+func (s IDList) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
+
+// Group returns slice of object ids that are part of a storage group.
+func (m *Object) Group() []ID {
+	sgLinks := m.Links(Link_StorageGroup)
+	sort.Sort(IDList(sgLinks))
+	return sgLinks
+}
+
+// Zones returns validation zones of storage group.
+func (m *Object) Zones() []ZoneInfo {
+	sgInfo, err := m.StorageGroup()
+	if err != nil {
+		return nil
+	}
+	return []ZoneInfo{
+		{
+			Hash: sgInfo.ValidationHash,
+			Size: sgInfo.ValidationDataSize,
+		},
+	}
+}
+
+// IDInfo returns meta information about storage group.
+func (m *Object) IDInfo() *IdentificationInfo {
+	return &IdentificationInfo{
+		SGID:    m.SystemHeader.ID,
+		CID:     m.SystemHeader.CID,
+		OwnerID: m.SystemHeader.OwnerID,
+	}
+}
diff --git a/object/sg_test.go b/object/sg_test.go
new file mode 100644
index 00000000..58e20427
--- /dev/null
+++ b/object/sg_test.go
@@ -0,0 +1,87 @@
+package object
+
+import (
+	"math/rand"
+	"sort"
+	"testing"
+
+	"github.com/nspcc-dev/neofs-proto/hash"
+	"github.com/stretchr/testify/require"
+)
+
+func TestObject_StorageGroup(t *testing.T) {
+	t.Run("group method", func(t *testing.T) {
+		var linkCount byte = 100
+
+		obj := &Object{Headers: make([]Header, 0, linkCount)}
+		require.Empty(t, obj.Group())
+
+		idList := make([]ID, linkCount)
+		for i := byte(0); i < linkCount; i++ {
+			idList[i] = ID{i}
+			obj.Headers = append(obj.Headers, Header{
+				Value: &Header_Link{Link: &Link{
+					Type: Link_StorageGroup,
+					ID:   idList[i],
+				}},
+			})
+		}
+
+		rand.Shuffle(len(obj.Headers), func(i, j int) { obj.Headers[i], obj.Headers[j] = obj.Headers[j], obj.Headers[i] })
+		sort.Sort(IDList(idList))
+		require.Equal(t, idList, obj.Group())
+	})
+	t.Run("identification method", func(t *testing.T) {
+		oid, cid, owner := ID{1}, CID{2}, OwnerID{3}
+		obj := &Object{
+			SystemHeader: SystemHeader{
+				ID:      oid,
+				OwnerID: owner,
+				CID:     cid,
+			},
+		}
+
+		idInfo := obj.IDInfo()
+		require.Equal(t, oid, idInfo.SGID)
+		require.Equal(t, cid, idInfo.CID)
+		require.Equal(t, owner, idInfo.OwnerID)
+	})
+	t.Run("zones method", func(t *testing.T) {
+		sgSize := uint64(100)
+
+		d := make([]byte, sgSize)
+		_, err := rand.Read(d)
+		require.NoError(t, err)
+		sgHash := hash.Sum(d)
+
+		obj := &Object{
+			Headers: []Header{
+				{
+					Value: &Header_StorageGroup{
+						StorageGroup: &StorageGroup{
+							ValidationDataSize: sgSize,
+							ValidationHash:     sgHash,
+						},
+					},
+				},
+			},
+		}
+
+		var (
+			sumSize uint64
+			zones   = obj.Zones()
+			hashes  = make([]Hash, len(zones))
+		)
+
+		for i := range zones {
+			sumSize += zones[i].Size
+			hashes[i] = zones[i].Hash
+		}
+
+		sumHash, err := hash.Concat(hashes)
+		require.NoError(t, err)
+
+		require.Equal(t, sgSize, sumSize)
+		require.Equal(t, sgHash, sumHash)
+	})
+}
diff --git a/object/types.go b/object/types.go
new file mode 100644
index 00000000..f433b9c9
--- /dev/null
+++ b/object/types.go
@@ -0,0 +1,219 @@
+package object
+
+import (
+	"bytes"
+	"context"
+
+	"github.com/gogo/protobuf/proto"
+	"github.com/nspcc-dev/neofs-proto/internal"
+	"github.com/nspcc-dev/neofs-proto/refs"
+	"github.com/nspcc-dev/neofs-proto/session"
+)
+
+type (
+	// Pred defines a predicate function that can check if passed header
+	// satisfies predicate condition. It is used to find headers of
+	// specific type.
+	Pred = func(*Header) bool
+
+	// Address is a type alias of object Address.
+	Address = refs.Address
+
+	// VerificationHeader is a type alias of session's verification header.
+	VerificationHeader = session.VerificationHeader
+
+	// PositionReader defines object reader that returns slice of bytes
+	// for specified object and data range.
+	PositionReader interface {
+		PRead(ctx context.Context, addr refs.Address, rng Range) ([]byte, error)
+	}
+
+	headerType int
+)
+
+const (
+	// ErrVerifyPayload is raised when payload checksum cannot be verified.
+	ErrVerifyPayload = internal.Error("can't verify payload")
+
+	// ErrVerifyHeader is raised when object integrity cannot be verified.
+	ErrVerifyHeader = internal.Error("can't verify header")
+
+	// ErrHeaderNotFound is raised when requested header not found.
+	ErrHeaderNotFound = internal.Error("header not found")
+
+	// ErrVerifySignature is raised when signature cannot be verified.
+	ErrVerifySignature = internal.Error("can't verify signature")
+)
+
+const (
+	_ headerType = iota
+	// LinkHdr is a link header type.
+	LinkHdr
+	// RedirectHdr is a redirect header type.
+	RedirectHdr
+	// UserHdr is a user defined header type.
+	UserHdr
+	// TransformHdr is a transformation header type.
+	TransformHdr
+	// TombstoneHdr is a tombstone header type.
+	TombstoneHdr
+	// VerifyHdr is a verification header type.
+	VerifyHdr
+	// HomoHashHdr is a homomorphic hash header type.
+	HomoHashHdr
+	// PayloadChecksumHdr is a payload checksum header type.
+	PayloadChecksumHdr
+	// IntegrityHdr is a integrity header type.
+	IntegrityHdr
+	// StorageGroupHdr is a storage group header type.
+	StorageGroupHdr
+)
+
+var (
+	_ internal.Custom = (*Object)(nil)
+
+	emptyObject = new(Object).Bytes()
+)
+
+// Bytes returns marshaled object in a binary format.
+func (m Object) Bytes() []byte { data, _ := m.Marshal(); return data }
+
+// Empty checks if object does not contain any information.
+func (m Object) Empty() bool { return bytes.Equal(m.Bytes(), emptyObject) }
+
+// LastHeader returns last header of the specified type. Type must be
+// specified as a Pred function.
+func (m Object) LastHeader(f Pred) (int, *Header) {
+	for i := len(m.Headers) - 1; i >= 0; i-- {
+		if f != nil && f(&m.Headers[i]) {
+			return i, &m.Headers[i]
+		}
+	}
+	return -1, nil
+}
+
+// AddHeader adds passed header to the end of extended header list.
+func (m *Object) AddHeader(h *Header) {
+	m.Headers = append(m.Headers, *h)
+}
+
+// SetPayload sets payload field and payload length in the system header.
+func (m *Object) SetPayload(payload []byte) {
+	m.Payload = payload
+	m.SystemHeader.PayloadLength = uint64(len(payload))
+}
+
+// SetHeader replaces existing extended header or adds new one to the end of
+// extended header list.
+func (m *Object) SetHeader(h *Header) {
+	// looking for the header of that type
+	for i := range m.Headers {
+		if m.Headers[i].typeOf(h.Value) {
+			// if we found one - set it with new value and return
+			m.Headers[i] = *h
+			return
+		}
+	}
+	// if we did not find one - add this header
+	m.AddHeader(h)
+}
+
+func (m Header) typeOf(t isHeader_Value) (ok bool) {
+	switch t.(type) {
+	case *Header_Link:
+		_, ok = m.Value.(*Header_Link)
+	case *Header_Redirect:
+		_, ok = m.Value.(*Header_Redirect)
+	case *Header_UserHeader:
+		_, ok = m.Value.(*Header_UserHeader)
+	case *Header_Transform:
+		_, ok = m.Value.(*Header_Transform)
+	case *Header_Tombstone:
+		_, ok = m.Value.(*Header_Tombstone)
+	case *Header_Verify:
+		_, ok = m.Value.(*Header_Verify)
+	case *Header_HomoHash:
+		_, ok = m.Value.(*Header_HomoHash)
+	case *Header_PayloadChecksum:
+		_, ok = m.Value.(*Header_PayloadChecksum)
+	case *Header_Integrity:
+		_, ok = m.Value.(*Header_Integrity)
+	case *Header_StorageGroup:
+		_, ok = m.Value.(*Header_StorageGroup)
+	}
+	return
+}
+
+// HeaderType returns predicate that check if extended header is a header
+// of specified type.
+func HeaderType(t headerType) Pred {
+	switch t {
+	case LinkHdr:
+		return func(h *Header) bool { _, ok := h.Value.(*Header_Link); return ok }
+	case RedirectHdr:
+		return func(h *Header) bool { _, ok := h.Value.(*Header_Redirect); return ok }
+	case UserHdr:
+		return func(h *Header) bool { _, ok := h.Value.(*Header_UserHeader); return ok }
+	case TransformHdr:
+		return func(h *Header) bool { _, ok := h.Value.(*Header_Transform); return ok }
+	case TombstoneHdr:
+		return func(h *Header) bool { _, ok := h.Value.(*Header_Tombstone); return ok }
+	case VerifyHdr:
+		return func(h *Header) bool { _, ok := h.Value.(*Header_Verify); return ok }
+	case HomoHashHdr:
+		return func(h *Header) bool { _, ok := h.Value.(*Header_HomoHash); return ok }
+	case PayloadChecksumHdr:
+		return func(h *Header) bool { _, ok := h.Value.(*Header_PayloadChecksum); return ok }
+	case IntegrityHdr:
+		return func(h *Header) bool { _, ok := h.Value.(*Header_Integrity); return ok }
+	case StorageGroupHdr:
+		return func(h *Header) bool { _, ok := h.Value.(*Header_StorageGroup); return ok }
+	default:
+		return nil
+	}
+}
+
+// Copy creates full copy of the object.
+func (m *Object) Copy() (obj *Object) {
+	obj = new(Object)
+	m.CopyTo(obj)
+	return
+}
+
+// CopyTo creates fills passed object with the data from the current object.
+// This function creates copies on every available data slice.
+func (m *Object) CopyTo(o *Object) {
+	o.SystemHeader = m.SystemHeader
+	o.Headers = make([]Header, len(m.Headers))
+	o.Payload = make([]byte, len(m.Payload))
+
+	for i := range m.Headers {
+		switch v := m.Headers[i].Value.(type) {
+		case *Header_Link:
+			link := *v.Link
+			o.Headers[i] = Header{
+				Value: &Header_Link{
+					Link: &link,
+				},
+			}
+		case *Header_HomoHash:
+			o.Headers[i] = Header{
+				Value: &Header_HomoHash{
+					HomoHash: v.HomoHash,
+				},
+			}
+		default:
+			o.Headers[i] = *proto.Clone(&m.Headers[i]).(*Header)
+		}
+	}
+
+	copy(o.Payload, m.Payload)
+}
+
+// Address returns object's address.
+func (m Object) Address() *refs.Address {
+	return &refs.Address{
+		ObjectID: m.SystemHeader.ID,
+		CID:      m.SystemHeader.CID,
+	}
+}
diff --git a/object/types.pb.go b/object/types.pb.go
new file mode 100644
index 00000000..99b6c90f
--- /dev/null
+++ b/object/types.pb.go
@@ -0,0 +1,3814 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: object/types.proto
+
+package object
+
+import (
+	fmt "fmt"
+	_ "github.com/gogo/protobuf/gogoproto"
+	proto "github.com/golang/protobuf/proto"
+	refs "github.com/nspcc-dev/neofs-proto/refs"
+	session "github.com/nspcc-dev/neofs-proto/session"
+	io "io"
+	math "math"
+	math_bits "math/bits"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
+
+type Link_Type int32
+
+const (
+	Link_Unknown      Link_Type = 0
+	Link_Parent       Link_Type = 1
+	Link_Previous     Link_Type = 2
+	Link_Next         Link_Type = 3
+	Link_Child        Link_Type = 4
+	Link_StorageGroup Link_Type = 5
+)
+
+var Link_Type_name = map[int32]string{
+	0: "Unknown",
+	1: "Parent",
+	2: "Previous",
+	3: "Next",
+	4: "Child",
+	5: "StorageGroup",
+}
+
+var Link_Type_value = map[string]int32{
+	"Unknown":      0,
+	"Parent":       1,
+	"Previous":     2,
+	"Next":         3,
+	"Child":        4,
+	"StorageGroup": 5,
+}
+
+func (x Link_Type) String() string {
+	return proto.EnumName(Link_Type_name, int32(x))
+}
+
+func (Link_Type) EnumDescriptor() ([]byte, []int) {
+	return fileDescriptor_02021a1d39b1aee0, []int{7, 0}
+}
+
+type Transform_Type int32
+
+const (
+	Transform_Unknown Transform_Type = 0
+	Transform_Split   Transform_Type = 1
+	Transform_Sign    Transform_Type = 2
+	Transform_Mould   Transform_Type = 3
+)
+
+var Transform_Type_name = map[int32]string{
+	0: "Unknown",
+	1: "Split",
+	2: "Sign",
+	3: "Mould",
+}
+
+var Transform_Type_value = map[string]int32{
+	"Unknown": 0,
+	"Split":   1,
+	"Sign":    2,
+	"Mould":   3,
+}
+
+func (x Transform_Type) String() string {
+	return proto.EnumName(Transform_Type_name, int32(x))
+}
+
+func (Transform_Type) EnumDescriptor() ([]byte, []int) {
+	return fileDescriptor_02021a1d39b1aee0, []int{8, 0}
+}
+
+type StorageGroup_Lifetime_Unit int32
+
+const (
+	StorageGroup_Lifetime_Unlimited  StorageGroup_Lifetime_Unit = 0
+	StorageGroup_Lifetime_NeoFSEpoch StorageGroup_Lifetime_Unit = 1
+	StorageGroup_Lifetime_UnixTime   StorageGroup_Lifetime_Unit = 2
+)
+
+var StorageGroup_Lifetime_Unit_name = map[int32]string{
+	0: "Unlimited",
+	1: "NeoFSEpoch",
+	2: "UnixTime",
+}
+
+var StorageGroup_Lifetime_Unit_value = map[string]int32{
+	"Unlimited":  0,
+	"NeoFSEpoch": 1,
+	"UnixTime":   2,
+}
+
+func (x StorageGroup_Lifetime_Unit) String() string {
+	return proto.EnumName(StorageGroup_Lifetime_Unit_name, int32(x))
+}
+
+func (StorageGroup_Lifetime_Unit) EnumDescriptor() ([]byte, []int) {
+	return fileDescriptor_02021a1d39b1aee0, []int{10, 0, 0}
+}
+
+type Range struct {
+	Offset               uint64   `protobuf:"varint,1,opt,name=Offset,proto3" json:"Offset,omitempty"`
+	Length               uint64   `protobuf:"varint,2,opt,name=Length,proto3" json:"Length,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *Range) Reset()         { *m = Range{} }
+func (m *Range) String() string { return proto.CompactTextString(m) }
+func (*Range) ProtoMessage()    {}
+func (*Range) Descriptor() ([]byte, []int) {
+	return fileDescriptor_02021a1d39b1aee0, []int{0}
+}
+func (m *Range) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *Range) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *Range) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Range.Merge(m, src)
+}
+func (m *Range) XXX_Size() int {
+	return m.Size()
+}
+func (m *Range) XXX_DiscardUnknown() {
+	xxx_messageInfo_Range.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Range proto.InternalMessageInfo
+
+func (m *Range) GetOffset() uint64 {
+	if m != nil {
+		return m.Offset
+	}
+	return 0
+}
+
+func (m *Range) GetLength() uint64 {
+	if m != nil {
+		return m.Length
+	}
+	return 0
+}
+
+type UserHeader struct {
+	Key                  string   `protobuf:"bytes,1,opt,name=Key,proto3" json:"Key,omitempty"`
+	Value                string   `protobuf:"bytes,2,opt,name=Value,proto3" json:"Value,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *UserHeader) Reset()         { *m = UserHeader{} }
+func (m *UserHeader) String() string { return proto.CompactTextString(m) }
+func (*UserHeader) ProtoMessage()    {}
+func (*UserHeader) Descriptor() ([]byte, []int) {
+	return fileDescriptor_02021a1d39b1aee0, []int{1}
+}
+func (m *UserHeader) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *UserHeader) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *UserHeader) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_UserHeader.Merge(m, src)
+}
+func (m *UserHeader) XXX_Size() int {
+	return m.Size()
+}
+func (m *UserHeader) XXX_DiscardUnknown() {
+	xxx_messageInfo_UserHeader.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_UserHeader proto.InternalMessageInfo
+
+func (m *UserHeader) GetKey() string {
+	if m != nil {
+		return m.Key
+	}
+	return ""
+}
+
+func (m *UserHeader) GetValue() string {
+	if m != nil {
+		return m.Value
+	}
+	return ""
+}
+
+type Header struct {
+	// Types that are valid to be assigned to Value:
+	//	*Header_Link
+	//	*Header_Redirect
+	//	*Header_UserHeader
+	//	*Header_Transform
+	//	*Header_Tombstone
+	//	*Header_Verify
+	//	*Header_HomoHash
+	//	*Header_PayloadChecksum
+	//	*Header_Integrity
+	//	*Header_StorageGroup
+	Value                isHeader_Value `protobuf_oneof:"Value"`
+	XXX_NoUnkeyedLiteral struct{}       `json:"-"`
+	XXX_unrecognized     []byte         `json:"-"`
+	XXX_sizecache        int32          `json:"-"`
+}
+
+func (m *Header) Reset()         { *m = Header{} }
+func (m *Header) String() string { return proto.CompactTextString(m) }
+func (*Header) ProtoMessage()    {}
+func (*Header) Descriptor() ([]byte, []int) {
+	return fileDescriptor_02021a1d39b1aee0, []int{2}
+}
+func (m *Header) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *Header) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *Header) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Header.Merge(m, src)
+}
+func (m *Header) XXX_Size() int {
+	return m.Size()
+}
+func (m *Header) XXX_DiscardUnknown() {
+	xxx_messageInfo_Header.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Header proto.InternalMessageInfo
+
+type isHeader_Value interface {
+	isHeader_Value()
+	MarshalTo([]byte) (int, error)
+	Size() int
+}
+
+type Header_Link struct {
+	Link *Link `protobuf:"bytes,1,opt,name=Link,proto3,oneof" json:"Link,omitempty"`
+}
+type Header_Redirect struct {
+	Redirect *refs.Address `protobuf:"bytes,2,opt,name=Redirect,proto3,oneof" json:"Redirect,omitempty"`
+}
+type Header_UserHeader struct {
+	UserHeader *UserHeader `protobuf:"bytes,3,opt,name=UserHeader,proto3,oneof" json:"UserHeader,omitempty"`
+}
+type Header_Transform struct {
+	Transform *Transform `protobuf:"bytes,4,opt,name=Transform,proto3,oneof" json:"Transform,omitempty"`
+}
+type Header_Tombstone struct {
+	Tombstone *Tombstone `protobuf:"bytes,5,opt,name=Tombstone,proto3,oneof" json:"Tombstone,omitempty"`
+}
+type Header_Verify struct {
+	Verify *session.VerificationHeader `protobuf:"bytes,6,opt,name=Verify,proto3,oneof" json:"Verify,omitempty"`
+}
+type Header_HomoHash struct {
+	HomoHash Hash `protobuf:"bytes,7,opt,name=HomoHash,proto3,oneof,customtype=Hash" json:"HomoHash,omitempty"`
+}
+type Header_PayloadChecksum struct {
+	PayloadChecksum []byte `protobuf:"bytes,8,opt,name=PayloadChecksum,proto3,oneof" json:"PayloadChecksum,omitempty"`
+}
+type Header_Integrity struct {
+	Integrity *IntegrityHeader `protobuf:"bytes,9,opt,name=Integrity,proto3,oneof" json:"Integrity,omitempty"`
+}
+type Header_StorageGroup struct {
+	StorageGroup *StorageGroup `protobuf:"bytes,10,opt,name=StorageGroup,proto3,oneof" json:"StorageGroup,omitempty"`
+}
+
+func (*Header_Link) isHeader_Value()            {}
+func (*Header_Redirect) isHeader_Value()        {}
+func (*Header_UserHeader) isHeader_Value()      {}
+func (*Header_Transform) isHeader_Value()       {}
+func (*Header_Tombstone) isHeader_Value()       {}
+func (*Header_Verify) isHeader_Value()          {}
+func (*Header_HomoHash) isHeader_Value()        {}
+func (*Header_PayloadChecksum) isHeader_Value() {}
+func (*Header_Integrity) isHeader_Value()       {}
+func (*Header_StorageGroup) isHeader_Value()    {}
+
+func (m *Header) GetValue() isHeader_Value {
+	if m != nil {
+		return m.Value
+	}
+	return nil
+}
+
+func (m *Header) GetLink() *Link {
+	if x, ok := m.GetValue().(*Header_Link); ok {
+		return x.Link
+	}
+	return nil
+}
+
+func (m *Header) GetRedirect() *refs.Address {
+	if x, ok := m.GetValue().(*Header_Redirect); ok {
+		return x.Redirect
+	}
+	return nil
+}
+
+func (m *Header) GetUserHeader() *UserHeader {
+	if x, ok := m.GetValue().(*Header_UserHeader); ok {
+		return x.UserHeader
+	}
+	return nil
+}
+
+func (m *Header) GetTransform() *Transform {
+	if x, ok := m.GetValue().(*Header_Transform); ok {
+		return x.Transform
+	}
+	return nil
+}
+
+func (m *Header) GetTombstone() *Tombstone {
+	if x, ok := m.GetValue().(*Header_Tombstone); ok {
+		return x.Tombstone
+	}
+	return nil
+}
+
+func (m *Header) GetVerify() *session.VerificationHeader {
+	if x, ok := m.GetValue().(*Header_Verify); ok {
+		return x.Verify
+	}
+	return nil
+}
+
+func (m *Header) GetPayloadChecksum() []byte {
+	if x, ok := m.GetValue().(*Header_PayloadChecksum); ok {
+		return x.PayloadChecksum
+	}
+	return nil
+}
+
+func (m *Header) GetIntegrity() *IntegrityHeader {
+	if x, ok := m.GetValue().(*Header_Integrity); ok {
+		return x.Integrity
+	}
+	return nil
+}
+
+func (m *Header) GetStorageGroup() *StorageGroup {
+	if x, ok := m.GetValue().(*Header_StorageGroup); ok {
+		return x.StorageGroup
+	}
+	return nil
+}
+
+// XXX_OneofWrappers is for the internal use of the proto package.
+func (*Header) XXX_OneofWrappers() []interface{} {
+	return []interface{}{
+		(*Header_Link)(nil),
+		(*Header_Redirect)(nil),
+		(*Header_UserHeader)(nil),
+		(*Header_Transform)(nil),
+		(*Header_Tombstone)(nil),
+		(*Header_Verify)(nil),
+		(*Header_HomoHash)(nil),
+		(*Header_PayloadChecksum)(nil),
+		(*Header_Integrity)(nil),
+		(*Header_StorageGroup)(nil),
+	}
+}
+
+type Tombstone struct {
+	Epoch                uint64   `protobuf:"varint,1,opt,name=Epoch,proto3" json:"Epoch,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *Tombstone) Reset()         { *m = Tombstone{} }
+func (m *Tombstone) String() string { return proto.CompactTextString(m) }
+func (*Tombstone) ProtoMessage()    {}
+func (*Tombstone) Descriptor() ([]byte, []int) {
+	return fileDescriptor_02021a1d39b1aee0, []int{3}
+}
+func (m *Tombstone) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *Tombstone) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *Tombstone) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Tombstone.Merge(m, src)
+}
+func (m *Tombstone) XXX_Size() int {
+	return m.Size()
+}
+func (m *Tombstone) XXX_DiscardUnknown() {
+	xxx_messageInfo_Tombstone.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Tombstone proto.InternalMessageInfo
+
+func (m *Tombstone) GetEpoch() uint64 {
+	if m != nil {
+		return m.Epoch
+	}
+	return 0
+}
+
+type SystemHeader struct {
+	Version              uint64        `protobuf:"varint,1,opt,name=Version,proto3" json:"Version,omitempty"`
+	PayloadLength        uint64        `protobuf:"varint,2,opt,name=PayloadLength,proto3" json:"PayloadLength,omitempty"`
+	ID                   ID            `protobuf:"bytes,3,opt,name=ID,proto3,customtype=ID" json:"ID"`
+	OwnerID              OwnerID       `protobuf:"bytes,4,opt,name=OwnerID,proto3,customtype=OwnerID" json:"OwnerID"`
+	CID                  CID           `protobuf:"bytes,5,opt,name=CID,proto3,customtype=CID" json:"CID"`
+	CreatedAt            CreationPoint `protobuf:"bytes,6,opt,name=CreatedAt,proto3" json:"CreatedAt"`
+	XXX_NoUnkeyedLiteral struct{}      `json:"-"`
+	XXX_unrecognized     []byte        `json:"-"`
+	XXX_sizecache        int32         `json:"-"`
+}
+
+func (m *SystemHeader) Reset()         { *m = SystemHeader{} }
+func (m *SystemHeader) String() string { return proto.CompactTextString(m) }
+func (*SystemHeader) ProtoMessage()    {}
+func (*SystemHeader) Descriptor() ([]byte, []int) {
+	return fileDescriptor_02021a1d39b1aee0, []int{4}
+}
+func (m *SystemHeader) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *SystemHeader) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *SystemHeader) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_SystemHeader.Merge(m, src)
+}
+func (m *SystemHeader) XXX_Size() int {
+	return m.Size()
+}
+func (m *SystemHeader) XXX_DiscardUnknown() {
+	xxx_messageInfo_SystemHeader.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_SystemHeader proto.InternalMessageInfo
+
+func (m *SystemHeader) GetVersion() uint64 {
+	if m != nil {
+		return m.Version
+	}
+	return 0
+}
+
+func (m *SystemHeader) GetPayloadLength() uint64 {
+	if m != nil {
+		return m.PayloadLength
+	}
+	return 0
+}
+
+func (m *SystemHeader) GetCreatedAt() CreationPoint {
+	if m != nil {
+		return m.CreatedAt
+	}
+	return CreationPoint{}
+}
+
+type CreationPoint struct {
+	UnixTime             int64    `protobuf:"varint,1,opt,name=UnixTime,proto3" json:"UnixTime,omitempty"`
+	Epoch                uint64   `protobuf:"varint,2,opt,name=Epoch,proto3" json:"Epoch,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *CreationPoint) Reset()         { *m = CreationPoint{} }
+func (m *CreationPoint) String() string { return proto.CompactTextString(m) }
+func (*CreationPoint) ProtoMessage()    {}
+func (*CreationPoint) Descriptor() ([]byte, []int) {
+	return fileDescriptor_02021a1d39b1aee0, []int{5}
+}
+func (m *CreationPoint) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *CreationPoint) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *CreationPoint) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_CreationPoint.Merge(m, src)
+}
+func (m *CreationPoint) XXX_Size() int {
+	return m.Size()
+}
+func (m *CreationPoint) XXX_DiscardUnknown() {
+	xxx_messageInfo_CreationPoint.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_CreationPoint proto.InternalMessageInfo
+
+func (m *CreationPoint) GetUnixTime() int64 {
+	if m != nil {
+		return m.UnixTime
+	}
+	return 0
+}
+
+func (m *CreationPoint) GetEpoch() uint64 {
+	if m != nil {
+		return m.Epoch
+	}
+	return 0
+}
+
+type IntegrityHeader struct {
+	HeadersChecksum      []byte   `protobuf:"bytes,1,opt,name=HeadersChecksum,proto3" json:"HeadersChecksum,omitempty"`
+	ChecksumSignature    []byte   `protobuf:"bytes,2,opt,name=ChecksumSignature,proto3" json:"ChecksumSignature,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *IntegrityHeader) Reset()         { *m = IntegrityHeader{} }
+func (m *IntegrityHeader) String() string { return proto.CompactTextString(m) }
+func (*IntegrityHeader) ProtoMessage()    {}
+func (*IntegrityHeader) Descriptor() ([]byte, []int) {
+	return fileDescriptor_02021a1d39b1aee0, []int{6}
+}
+func (m *IntegrityHeader) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *IntegrityHeader) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *IntegrityHeader) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_IntegrityHeader.Merge(m, src)
+}
+func (m *IntegrityHeader) XXX_Size() int {
+	return m.Size()
+}
+func (m *IntegrityHeader) XXX_DiscardUnknown() {
+	xxx_messageInfo_IntegrityHeader.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_IntegrityHeader proto.InternalMessageInfo
+
+func (m *IntegrityHeader) GetHeadersChecksum() []byte {
+	if m != nil {
+		return m.HeadersChecksum
+	}
+	return nil
+}
+
+func (m *IntegrityHeader) GetChecksumSignature() []byte {
+	if m != nil {
+		return m.ChecksumSignature
+	}
+	return nil
+}
+
+type Link struct {
+	Type                 Link_Type `protobuf:"varint,1,opt,name=type,proto3,enum=object.Link_Type" json:"type,omitempty"`
+	ID                   ID        `protobuf:"bytes,2,opt,name=ID,proto3,customtype=ID" json:"ID"`
+	XXX_NoUnkeyedLiteral struct{}  `json:"-"`
+	XXX_unrecognized     []byte    `json:"-"`
+	XXX_sizecache        int32     `json:"-"`
+}
+
+func (m *Link) Reset()         { *m = Link{} }
+func (m *Link) String() string { return proto.CompactTextString(m) }
+func (*Link) ProtoMessage()    {}
+func (*Link) Descriptor() ([]byte, []int) {
+	return fileDescriptor_02021a1d39b1aee0, []int{7}
+}
+func (m *Link) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *Link) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *Link) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Link.Merge(m, src)
+}
+func (m *Link) XXX_Size() int {
+	return m.Size()
+}
+func (m *Link) XXX_DiscardUnknown() {
+	xxx_messageInfo_Link.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Link proto.InternalMessageInfo
+
+func (m *Link) GetType() Link_Type {
+	if m != nil {
+		return m.Type
+	}
+	return Link_Unknown
+}
+
+type Transform struct {
+	Type                 Transform_Type `protobuf:"varint,1,opt,name=type,proto3,enum=object.Transform_Type" json:"type,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}       `json:"-"`
+	XXX_unrecognized     []byte         `json:"-"`
+	XXX_sizecache        int32          `json:"-"`
+}
+
+func (m *Transform) Reset()         { *m = Transform{} }
+func (m *Transform) String() string { return proto.CompactTextString(m) }
+func (*Transform) ProtoMessage()    {}
+func (*Transform) Descriptor() ([]byte, []int) {
+	return fileDescriptor_02021a1d39b1aee0, []int{8}
+}
+func (m *Transform) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *Transform) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *Transform) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Transform.Merge(m, src)
+}
+func (m *Transform) XXX_Size() int {
+	return m.Size()
+}
+func (m *Transform) XXX_DiscardUnknown() {
+	xxx_messageInfo_Transform.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Transform proto.InternalMessageInfo
+
+func (m *Transform) GetType() Transform_Type {
+	if m != nil {
+		return m.Type
+	}
+	return Transform_Unknown
+}
+
+type Object struct {
+	SystemHeader         SystemHeader `protobuf:"bytes,1,opt,name=SystemHeader,proto3" json:"SystemHeader"`
+	Headers              []Header     `protobuf:"bytes,2,rep,name=Headers,proto3" json:"Headers"`
+	Payload              []byte       `protobuf:"bytes,3,opt,name=Payload,proto3" json:"Payload,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}     `json:"-"`
+	XXX_unrecognized     []byte       `json:"-"`
+	XXX_sizecache        int32        `json:"-"`
+}
+
+func (m *Object) Reset()         { *m = Object{} }
+func (m *Object) String() string { return proto.CompactTextString(m) }
+func (*Object) ProtoMessage()    {}
+func (*Object) Descriptor() ([]byte, []int) {
+	return fileDescriptor_02021a1d39b1aee0, []int{9}
+}
+func (m *Object) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *Object) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *Object) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Object.Merge(m, src)
+}
+func (m *Object) XXX_Size() int {
+	return m.Size()
+}
+func (m *Object) XXX_DiscardUnknown() {
+	xxx_messageInfo_Object.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Object proto.InternalMessageInfo
+
+func (m *Object) GetSystemHeader() SystemHeader {
+	if m != nil {
+		return m.SystemHeader
+	}
+	return SystemHeader{}
+}
+
+func (m *Object) GetHeaders() []Header {
+	if m != nil {
+		return m.Headers
+	}
+	return nil
+}
+
+func (m *Object) GetPayload() []byte {
+	if m != nil {
+		return m.Payload
+	}
+	return nil
+}
+
+type StorageGroup struct {
+	ValidationDataSize   uint64                 `protobuf:"varint,1,opt,name=ValidationDataSize,proto3" json:"ValidationDataSize,omitempty"`
+	ValidationHash       Hash                   `protobuf:"bytes,2,opt,name=ValidationHash,proto3,customtype=Hash" json:"ValidationHash"`
+	Lifetime             *StorageGroup_Lifetime `protobuf:"bytes,3,opt,name=lifetime,proto3" json:"lifetime,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}               `json:"-"`
+	XXX_unrecognized     []byte                 `json:"-"`
+	XXX_sizecache        int32                  `json:"-"`
+}
+
+func (m *StorageGroup) Reset()         { *m = StorageGroup{} }
+func (m *StorageGroup) String() string { return proto.CompactTextString(m) }
+func (*StorageGroup) ProtoMessage()    {}
+func (*StorageGroup) Descriptor() ([]byte, []int) {
+	return fileDescriptor_02021a1d39b1aee0, []int{10}
+}
+func (m *StorageGroup) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *StorageGroup) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *StorageGroup) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_StorageGroup.Merge(m, src)
+}
+func (m *StorageGroup) XXX_Size() int {
+	return m.Size()
+}
+func (m *StorageGroup) XXX_DiscardUnknown() {
+	xxx_messageInfo_StorageGroup.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_StorageGroup proto.InternalMessageInfo
+
+func (m *StorageGroup) GetValidationDataSize() uint64 {
+	if m != nil {
+		return m.ValidationDataSize
+	}
+	return 0
+}
+
+func (m *StorageGroup) GetLifetime() *StorageGroup_Lifetime {
+	if m != nil {
+		return m.Lifetime
+	}
+	return nil
+}
+
+type StorageGroup_Lifetime struct {
+	Unit                 StorageGroup_Lifetime_Unit `protobuf:"varint,1,opt,name=unit,proto3,enum=object.StorageGroup_Lifetime_Unit" json:"unit,omitempty"`
+	Value                int64                      `protobuf:"varint,2,opt,name=Value,proto3" json:"Value,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}                   `json:"-"`
+	XXX_unrecognized     []byte                     `json:"-"`
+	XXX_sizecache        int32                      `json:"-"`
+}
+
+func (m *StorageGroup_Lifetime) Reset()         { *m = StorageGroup_Lifetime{} }
+func (m *StorageGroup_Lifetime) String() string { return proto.CompactTextString(m) }
+func (*StorageGroup_Lifetime) ProtoMessage()    {}
+func (*StorageGroup_Lifetime) Descriptor() ([]byte, []int) {
+	return fileDescriptor_02021a1d39b1aee0, []int{10, 0}
+}
+func (m *StorageGroup_Lifetime) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *StorageGroup_Lifetime) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *StorageGroup_Lifetime) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_StorageGroup_Lifetime.Merge(m, src)
+}
+func (m *StorageGroup_Lifetime) XXX_Size() int {
+	return m.Size()
+}
+func (m *StorageGroup_Lifetime) XXX_DiscardUnknown() {
+	xxx_messageInfo_StorageGroup_Lifetime.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_StorageGroup_Lifetime proto.InternalMessageInfo
+
+func (m *StorageGroup_Lifetime) GetUnit() StorageGroup_Lifetime_Unit {
+	if m != nil {
+		return m.Unit
+	}
+	return StorageGroup_Lifetime_Unlimited
+}
+
+func (m *StorageGroup_Lifetime) GetValue() int64 {
+	if m != nil {
+		return m.Value
+	}
+	return 0
+}
+
+func init() {
+	proto.RegisterEnum("object.Link_Type", Link_Type_name, Link_Type_value)
+	proto.RegisterEnum("object.Transform_Type", Transform_Type_name, Transform_Type_value)
+	proto.RegisterEnum("object.StorageGroup_Lifetime_Unit", StorageGroup_Lifetime_Unit_name, StorageGroup_Lifetime_Unit_value)
+	proto.RegisterType((*Range)(nil), "object.Range")
+	proto.RegisterType((*UserHeader)(nil), "object.UserHeader")
+	proto.RegisterType((*Header)(nil), "object.Header")
+	proto.RegisterType((*Tombstone)(nil), "object.Tombstone")
+	proto.RegisterType((*SystemHeader)(nil), "object.SystemHeader")
+	proto.RegisterType((*CreationPoint)(nil), "object.CreationPoint")
+	proto.RegisterType((*IntegrityHeader)(nil), "object.IntegrityHeader")
+	proto.RegisterType((*Link)(nil), "object.Link")
+	proto.RegisterType((*Transform)(nil), "object.Transform")
+	proto.RegisterType((*Object)(nil), "object.Object")
+	proto.RegisterType((*StorageGroup)(nil), "object.StorageGroup")
+	proto.RegisterType((*StorageGroup_Lifetime)(nil), "object.StorageGroup.Lifetime")
+}
+
+func init() { proto.RegisterFile("object/types.proto", fileDescriptor_02021a1d39b1aee0) }
+
+var fileDescriptor_02021a1d39b1aee0 = []byte{
+	// 996 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x55, 0xdf, 0x6e, 0xe3, 0xc4,
+	0x17, 0xb6, 0x1d, 0x27, 0x71, 0x4e, 0xdd, 0xd6, 0x3b, 0xbf, 0xfd, 0x2d, 0x56, 0xd1, 0xb6, 0xc5,
+	0xe2, 0x4f, 0x59, 0xa8, 0x2b, 0xda, 0x45, 0x2b, 0x90, 0x40, 0x34, 0x0d, 0x6c, 0x22, 0xca, 0xb6,
+	0x9a, 0xb4, 0xbd, 0xe0, 0xce, 0x89, 0x27, 0xc9, 0xd0, 0x64, 0x26, 0xb2, 0x27, 0xbb, 0x1b, 0x1e,
+	0x83, 0x1b, 0xb8, 0xe3, 0x75, 0xf6, 0x92, 0x3b, 0xd0, 0x5e, 0x44, 0x28, 0x3c, 0x00, 0x6f, 0x80,
+	0xd0, 0x8c, 0xc7, 0x49, 0x9c, 0xad, 0xb8, 0x89, 0xe6, 0x9c, 0xef, 0xfb, 0x46, 0x27, 0xe7, 0x7c,
+	0x67, 0x0c, 0x88, 0x77, 0x7e, 0x20, 0x5d, 0x71, 0x24, 0xa6, 0x63, 0x92, 0x86, 0xe3, 0x84, 0x0b,
+	0x8e, 0x2a, 0x59, 0x6e, 0xc7, 0x4b, 0x48, 0x2f, 0x5d, 0x45, 0x76, 0xfe, 0x97, 0x92, 0x34, 0xa5,
+	0x9c, 0x15, 0x92, 0x87, 0x7d, 0x2a, 0x06, 0x93, 0x4e, 0xd8, 0xe5, 0xa3, 0xa3, 0x3e, 0xef, 0xf3,
+	0x23, 0x95, 0xee, 0x4c, 0x7a, 0x2a, 0x52, 0x81, 0x3a, 0x65, 0xf4, 0xe0, 0x09, 0x94, 0x71, 0xc4,
+	0xfa, 0x04, 0x3d, 0x80, 0xca, 0x45, 0xaf, 0x97, 0x12, 0xe1, 0x9b, 0xfb, 0xe6, 0x81, 0x8d, 0x75,
+	0x24, 0xf3, 0xe7, 0x84, 0xf5, 0xc5, 0xc0, 0xb7, 0xb2, 0x7c, 0x16, 0x05, 0x8f, 0x01, 0xae, 0x53,
+	0x92, 0x34, 0x49, 0x14, 0x93, 0x04, 0x79, 0x50, 0xfa, 0x96, 0x4c, 0x95, 0xb4, 0x86, 0xe5, 0x11,
+	0xdd, 0x87, 0xf2, 0x4d, 0x34, 0x9c, 0x10, 0x25, 0xab, 0xe1, 0x2c, 0x08, 0xfe, 0x29, 0x41, 0x45,
+	0x4b, 0x02, 0xb0, 0xcf, 0x29, 0xbb, 0x55, 0x9a, 0x8d, 0x63, 0x37, 0xcc, 0xfe, 0x66, 0x28, 0x73,
+	0x4d, 0x03, 0x2b, 0x0c, 0x7d, 0x04, 0x0e, 0x26, 0x31, 0x4d, 0x48, 0x57, 0xa8, 0x7b, 0x36, 0x8e,
+	0x37, 0x43, 0xd9, 0x86, 0xf0, 0x34, 0x8e, 0x13, 0x92, 0xa6, 0x4d, 0x03, 0x2f, 0x08, 0xa8, 0x50,
+	0x91, 0x5f, 0x52, 0x74, 0x94, 0x5f, 0xbb, 0x44, 0x9a, 0x06, 0x5e, 0xad, 0xfc, 0x13, 0xa8, 0x5d,
+	0x25, 0x11, 0x4b, 0x7b, 0x3c, 0x19, 0xf9, 0xb6, 0x12, 0xdd, 0xcb, 0x45, 0x0b, 0xa0, 0x69, 0xe0,
+	0x25, 0x4b, 0x49, 0xf8, 0xa8, 0x93, 0x0a, 0xce, 0x88, 0x5f, 0x5e, 0x93, 0xe4, 0x80, 0x92, 0xe4,
+	0x01, 0xfa, 0x14, 0x2a, 0x37, 0x24, 0xa1, 0xbd, 0xa9, 0x5f, 0x51, 0xfc, 0xb7, 0x43, 0x3d, 0xbb,
+	0x50, 0xa5, 0x69, 0x37, 0x12, 0x94, 0xb3, 0x45, 0x81, 0x9a, 0x8c, 0xde, 0x07, 0xa7, 0xc9, 0x47,
+	0xbc, 0x19, 0xa5, 0x03, 0xbf, 0xba, 0x6f, 0x1e, 0xb8, 0x75, 0xe7, 0xf5, 0x6c, 0xcf, 0x96, 0xb1,
+	0xfc, 0xeb, 0x39, 0x86, 0x1e, 0xc1, 0xf6, 0x65, 0x34, 0x1d, 0xf2, 0x28, 0x3e, 0x1b, 0x90, 0xee,
+	0x6d, 0x3a, 0x19, 0xf9, 0x8e, 0xa4, 0x37, 0x0d, 0xbc, 0x0e, 0xa0, 0x27, 0x50, 0x6b, 0x31, 0x41,
+	0xfa, 0x09, 0x15, 0x53, 0xbf, 0xa6, 0xaa, 0x79, 0x2b, 0xaf, 0x7e, 0x01, 0x2c, 0x2a, 0x59, 0x72,
+	0xd1, 0xe7, 0xe0, 0xb6, 0x05, 0x4f, 0xa2, 0x3e, 0x79, 0x9a, 0xf0, 0xc9, 0xd8, 0x07, 0xa5, 0xbd,
+	0x9f, 0x6b, 0x57, 0xb1, 0xa6, 0x81, 0x0b, 0xdc, 0x7a, 0x55, 0xbb, 0x21, 0x78, 0x67, 0xa5, 0x77,
+	0xd2, 0x23, 0x5f, 0x8f, 0x79, 0x77, 0xa0, 0x2d, 0x97, 0x05, 0xc1, 0xdf, 0x26, 0xb8, 0xed, 0x69,
+	0x2a, 0xc8, 0x48, 0x8f, 0xc8, 0x87, 0xea, 0x0d, 0x49, 0x64, 0xb7, 0x34, 0x31, 0x0f, 0xd1, 0xbb,
+	0xb0, 0xa9, 0xff, 0x5e, 0xc1, 0xa3, 0xc5, 0x24, 0xda, 0x01, 0xab, 0xd5, 0x50, 0x86, 0x70, 0xeb,
+	0xf0, 0x6a, 0xb6, 0x67, 0xbc, 0x9e, 0xed, 0x59, 0xad, 0x06, 0xb6, 0x5a, 0x0d, 0xf4, 0x21, 0x54,
+	0x2f, 0x5e, 0x30, 0x92, 0xb4, 0x1a, 0x6a, 0xf8, 0x6e, 0x7d, 0x5b, 0x13, 0xf2, 0x34, 0xce, 0x0f,
+	0xe8, 0x21, 0x94, 0xce, 0x5a, 0x0d, 0x35, 0x70, 0xb7, 0xbe, 0xa1, 0x69, 0x32, 0x85, 0xe5, 0x0f,
+	0xfa, 0x0c, 0x6a, 0x67, 0x09, 0x89, 0x04, 0x89, 0x4f, 0x85, 0x9e, 0xf2, 0xff, 0xf3, 0xde, 0x28,
+	0x80, 0x72, 0x76, 0xc9, 0x29, 0x13, 0x75, 0x5b, 0x6a, 0xf1, 0x92, 0x1d, 0x9c, 0xc2, 0x66, 0x81,
+	0x81, 0x76, 0xc0, 0xb9, 0x66, 0xf4, 0xe5, 0x15, 0x1d, 0x11, 0xf5, 0x97, 0x4b, 0x78, 0x11, 0x2f,
+	0x9b, 0x66, 0xad, 0x36, 0x8d, 0xc2, 0xf6, 0xda, 0xf0, 0xd0, 0x01, 0x6c, 0x67, 0xa7, 0x74, 0x61,
+	0x0a, 0x79, 0x97, 0x8b, 0xd7, 0xd3, 0xe8, 0x63, 0xb8, 0x97, 0x9f, 0xdb, 0xb4, 0xcf, 0x22, 0x31,
+	0x49, 0xb2, 0xbd, 0x75, 0xf1, 0x9b, 0x40, 0xf0, 0xab, 0x99, 0x6d, 0x2e, 0x7a, 0x0f, 0x6c, 0xf9,
+	0xf2, 0xa8, 0x5b, 0xb7, 0x96, 0x2b, 0x20, 0xb1, 0xf0, 0x6a, 0x3a, 0x26, 0x58, 0xc1, 0xba, 0xfd,
+	0xd6, 0x5d, 0xed, 0x0f, 0xae, 0xc0, 0x96, 0x4c, 0xb4, 0x01, 0xd5, 0x6b, 0x76, 0xcb, 0xf8, 0x0b,
+	0xe6, 0x19, 0x08, 0xa0, 0x72, 0x19, 0x25, 0x84, 0x09, 0xcf, 0x44, 0x2e, 0x38, 0x97, 0x09, 0x79,
+	0x4e, 0xf9, 0x24, 0xf5, 0x2c, 0xe4, 0x80, 0xfd, 0x8c, 0xbc, 0x14, 0x5e, 0x09, 0xd5, 0xa0, 0x7c,
+	0x36, 0xa0, 0xc3, 0xd8, 0xb3, 0x91, 0x57, 0xf4, 0xa5, 0x57, 0x0e, 0x86, 0x2b, 0x3b, 0x8d, 0x1e,
+	0x15, 0xaa, 0x7c, 0xf0, 0xc6, 0x6e, 0xaf, 0x94, 0x1a, 0x9c, 0xdc, 0x55, 0x4e, 0x0d, 0xca, 0xed,
+	0xf1, 0x90, 0xca, 0x6a, 0x1c, 0xb0, 0x65, 0x1f, 0x3c, 0x4b, 0x26, 0xbf, 0xe3, 0x93, 0x61, 0xec,
+	0x95, 0x82, 0x9f, 0x4c, 0xa8, 0x5c, 0xa8, 0x4b, 0xd1, 0x97, 0x45, 0xe7, 0xea, 0xb7, 0x6d, 0xb9,
+	0x22, 0x2b, 0x98, 0x76, 0x41, 0xd1, 0xe9, 0x21, 0x54, 0xf5, 0x6c, 0x7c, 0x6b, 0xbf, 0x74, 0xb0,
+	0x71, 0xbc, 0x95, 0x4b, 0x0b, 0xa2, 0x9c, 0x24, 0x37, 0x43, 0x5b, 0x3d, 0xb3, 0x37, 0xce, 0xc3,
+	0xe0, 0x77, 0xab, 0xd8, 0x15, 0x14, 0x02, 0xba, 0x89, 0x86, 0x34, 0x56, 0x2e, 0x6b, 0x44, 0x22,
+	0x6a, 0xd3, 0x1f, 0x89, 0xde, 0xa7, 0x3b, 0x10, 0xf4, 0x18, 0xb6, 0x96, 0x59, 0xf5, 0x00, 0x65,
+	0x13, 0x74, 0xf5, 0x04, 0xd5, 0x23, 0x84, 0xd7, 0x38, 0xe8, 0x29, 0x38, 0x43, 0xda, 0x23, 0x42,
+	0x1a, 0x37, 0x7b, 0x81, 0x1f, 0xde, 0xf5, 0x3e, 0x84, 0xe7, 0x9a, 0x54, 0x77, 0xe7, 0xb3, 0x3d,
+	0x27, 0x8f, 0xf0, 0x42, 0xbc, 0xf3, 0xb3, 0x09, 0x8b, 0x34, 0xfa, 0x0a, 0xec, 0x09, 0xa3, 0x42,
+	0x8f, 0x30, 0xf8, 0xcf, 0x1b, 0xc3, 0x6b, 0x46, 0x45, 0xdd, 0x99, 0xcf, 0xf6, 0x6c, 0x79, 0xc2,
+	0x4a, 0x59, 0xfc, 0x1a, 0x95, 0xf2, 0xaf, 0xd1, 0x09, 0x28, 0x0e, 0xda, 0x84, 0xda, 0x35, 0x1b,
+	0xd2, 0x11, 0x15, 0x24, 0xf6, 0x0c, 0xb4, 0x05, 0xf0, 0x8c, 0xf0, 0x6f, 0xda, 0x6a, 0xb3, 0x32,
+	0x0f, 0xe6, 0xdb, 0xe7, 0x59, 0xf5, 0x2f, 0x5e, 0xcd, 0x77, 0xcd, 0xdf, 0xe6, 0xbb, 0xe6, 0x1f,
+	0xf3, 0x5d, 0xf3, 0xcf, 0xf9, 0xae, 0xf9, 0xcb, 0x5f, 0xbb, 0xc6, 0xf7, 0x1f, 0xac, 0x7c, 0x76,
+	0x59, 0x3a, 0xee, 0x76, 0x0f, 0x63, 0xf2, 0xfc, 0x88, 0x11, 0xde, 0x4b, 0x0f, 0xb3, 0x8f, 0x6e,
+	0x56, 0x74, 0xa7, 0xa2, 0xa2, 0x93, 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff, 0xbb, 0x65, 0xf4, 0xeb,
+	0xeb, 0x07, 0x00, 0x00,
+}
+
+func (m *Range) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *Range) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *Range) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if m.Length != 0 {
+		i = encodeVarintTypes(dAtA, i, uint64(m.Length))
+		i--
+		dAtA[i] = 0x10
+	}
+	if m.Offset != 0 {
+		i = encodeVarintTypes(dAtA, i, uint64(m.Offset))
+		i--
+		dAtA[i] = 0x8
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *UserHeader) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *UserHeader) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *UserHeader) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if len(m.Value) > 0 {
+		i -= len(m.Value)
+		copy(dAtA[i:], m.Value)
+		i = encodeVarintTypes(dAtA, i, uint64(len(m.Value)))
+		i--
+		dAtA[i] = 0x12
+	}
+	if len(m.Key) > 0 {
+		i -= len(m.Key)
+		copy(dAtA[i:], m.Key)
+		i = encodeVarintTypes(dAtA, i, uint64(len(m.Key)))
+		i--
+		dAtA[i] = 0xa
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *Header) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *Header) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *Header) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if m.Value != nil {
+		{
+			size := m.Value.Size()
+			i -= size
+			if _, err := m.Value.MarshalTo(dAtA[i:]); err != nil {
+				return 0, err
+			}
+		}
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *Header_Link) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *Header_Link) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	if m.Link != nil {
+		{
+			size, err := m.Link.MarshalToSizedBuffer(dAtA[:i])
+			if err != nil {
+				return 0, err
+			}
+			i -= size
+			i = encodeVarintTypes(dAtA, i, uint64(size))
+		}
+		i--
+		dAtA[i] = 0xa
+	}
+	return len(dAtA) - i, nil
+}
+func (m *Header_Redirect) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *Header_Redirect) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	if m.Redirect != nil {
+		{
+			size, err := m.Redirect.MarshalToSizedBuffer(dAtA[:i])
+			if err != nil {
+				return 0, err
+			}
+			i -= size
+			i = encodeVarintTypes(dAtA, i, uint64(size))
+		}
+		i--
+		dAtA[i] = 0x12
+	}
+	return len(dAtA) - i, nil
+}
+func (m *Header_UserHeader) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *Header_UserHeader) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	if m.UserHeader != nil {
+		{
+			size, err := m.UserHeader.MarshalToSizedBuffer(dAtA[:i])
+			if err != nil {
+				return 0, err
+			}
+			i -= size
+			i = encodeVarintTypes(dAtA, i, uint64(size))
+		}
+		i--
+		dAtA[i] = 0x1a
+	}
+	return len(dAtA) - i, nil
+}
+func (m *Header_Transform) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *Header_Transform) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	if m.Transform != nil {
+		{
+			size, err := m.Transform.MarshalToSizedBuffer(dAtA[:i])
+			if err != nil {
+				return 0, err
+			}
+			i -= size
+			i = encodeVarintTypes(dAtA, i, uint64(size))
+		}
+		i--
+		dAtA[i] = 0x22
+	}
+	return len(dAtA) - i, nil
+}
+func (m *Header_Tombstone) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *Header_Tombstone) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	if m.Tombstone != nil {
+		{
+			size, err := m.Tombstone.MarshalToSizedBuffer(dAtA[:i])
+			if err != nil {
+				return 0, err
+			}
+			i -= size
+			i = encodeVarintTypes(dAtA, i, uint64(size))
+		}
+		i--
+		dAtA[i] = 0x2a
+	}
+	return len(dAtA) - i, nil
+}
+func (m *Header_Verify) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *Header_Verify) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	if m.Verify != nil {
+		{
+			size, err := m.Verify.MarshalToSizedBuffer(dAtA[:i])
+			if err != nil {
+				return 0, err
+			}
+			i -= size
+			i = encodeVarintTypes(dAtA, i, uint64(size))
+		}
+		i--
+		dAtA[i] = 0x32
+	}
+	return len(dAtA) - i, nil
+}
+func (m *Header_HomoHash) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *Header_HomoHash) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	{
+		size := m.HomoHash.Size()
+		i -= size
+		if _, err := m.HomoHash.MarshalTo(dAtA[i:]); err != nil {
+			return 0, err
+		}
+		i = encodeVarintTypes(dAtA, i, uint64(size))
+	}
+	i--
+	dAtA[i] = 0x3a
+	return len(dAtA) - i, nil
+}
+func (m *Header_PayloadChecksum) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *Header_PayloadChecksum) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	if m.PayloadChecksum != nil {
+		i -= len(m.PayloadChecksum)
+		copy(dAtA[i:], m.PayloadChecksum)
+		i = encodeVarintTypes(dAtA, i, uint64(len(m.PayloadChecksum)))
+		i--
+		dAtA[i] = 0x42
+	}
+	return len(dAtA) - i, nil
+}
+func (m *Header_Integrity) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *Header_Integrity) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	if m.Integrity != nil {
+		{
+			size, err := m.Integrity.MarshalToSizedBuffer(dAtA[:i])
+			if err != nil {
+				return 0, err
+			}
+			i -= size
+			i = encodeVarintTypes(dAtA, i, uint64(size))
+		}
+		i--
+		dAtA[i] = 0x4a
+	}
+	return len(dAtA) - i, nil
+}
+func (m *Header_StorageGroup) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *Header_StorageGroup) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	if m.StorageGroup != nil {
+		{
+			size, err := m.StorageGroup.MarshalToSizedBuffer(dAtA[:i])
+			if err != nil {
+				return 0, err
+			}
+			i -= size
+			i = encodeVarintTypes(dAtA, i, uint64(size))
+		}
+		i--
+		dAtA[i] = 0x52
+	}
+	return len(dAtA) - i, nil
+}
+func (m *Tombstone) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *Tombstone) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *Tombstone) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if m.Epoch != 0 {
+		i = encodeVarintTypes(dAtA, i, uint64(m.Epoch))
+		i--
+		dAtA[i] = 0x8
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *SystemHeader) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *SystemHeader) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *SystemHeader) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	{
+		size, err := m.CreatedAt.MarshalToSizedBuffer(dAtA[:i])
+		if err != nil {
+			return 0, err
+		}
+		i -= size
+		i = encodeVarintTypes(dAtA, i, uint64(size))
+	}
+	i--
+	dAtA[i] = 0x32
+	{
+		size := m.CID.Size()
+		i -= size
+		if _, err := m.CID.MarshalTo(dAtA[i:]); err != nil {
+			return 0, err
+		}
+		i = encodeVarintTypes(dAtA, i, uint64(size))
+	}
+	i--
+	dAtA[i] = 0x2a
+	{
+		size := m.OwnerID.Size()
+		i -= size
+		if _, err := m.OwnerID.MarshalTo(dAtA[i:]); err != nil {
+			return 0, err
+		}
+		i = encodeVarintTypes(dAtA, i, uint64(size))
+	}
+	i--
+	dAtA[i] = 0x22
+	{
+		size := m.ID.Size()
+		i -= size
+		if _, err := m.ID.MarshalTo(dAtA[i:]); err != nil {
+			return 0, err
+		}
+		i = encodeVarintTypes(dAtA, i, uint64(size))
+	}
+	i--
+	dAtA[i] = 0x1a
+	if m.PayloadLength != 0 {
+		i = encodeVarintTypes(dAtA, i, uint64(m.PayloadLength))
+		i--
+		dAtA[i] = 0x10
+	}
+	if m.Version != 0 {
+		i = encodeVarintTypes(dAtA, i, uint64(m.Version))
+		i--
+		dAtA[i] = 0x8
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *CreationPoint) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *CreationPoint) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *CreationPoint) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if m.Epoch != 0 {
+		i = encodeVarintTypes(dAtA, i, uint64(m.Epoch))
+		i--
+		dAtA[i] = 0x10
+	}
+	if m.UnixTime != 0 {
+		i = encodeVarintTypes(dAtA, i, uint64(m.UnixTime))
+		i--
+		dAtA[i] = 0x8
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *IntegrityHeader) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *IntegrityHeader) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *IntegrityHeader) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if len(m.ChecksumSignature) > 0 {
+		i -= len(m.ChecksumSignature)
+		copy(dAtA[i:], m.ChecksumSignature)
+		i = encodeVarintTypes(dAtA, i, uint64(len(m.ChecksumSignature)))
+		i--
+		dAtA[i] = 0x12
+	}
+	if len(m.HeadersChecksum) > 0 {
+		i -= len(m.HeadersChecksum)
+		copy(dAtA[i:], m.HeadersChecksum)
+		i = encodeVarintTypes(dAtA, i, uint64(len(m.HeadersChecksum)))
+		i--
+		dAtA[i] = 0xa
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *Link) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *Link) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *Link) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	{
+		size := m.ID.Size()
+		i -= size
+		if _, err := m.ID.MarshalTo(dAtA[i:]); err != nil {
+			return 0, err
+		}
+		i = encodeVarintTypes(dAtA, i, uint64(size))
+	}
+	i--
+	dAtA[i] = 0x12
+	if m.Type != 0 {
+		i = encodeVarintTypes(dAtA, i, uint64(m.Type))
+		i--
+		dAtA[i] = 0x8
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *Transform) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *Transform) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *Transform) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if m.Type != 0 {
+		i = encodeVarintTypes(dAtA, i, uint64(m.Type))
+		i--
+		dAtA[i] = 0x8
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *Object) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *Object) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *Object) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if len(m.Payload) > 0 {
+		i -= len(m.Payload)
+		copy(dAtA[i:], m.Payload)
+		i = encodeVarintTypes(dAtA, i, uint64(len(m.Payload)))
+		i--
+		dAtA[i] = 0x1a
+	}
+	if len(m.Headers) > 0 {
+		for iNdEx := len(m.Headers) - 1; iNdEx >= 0; iNdEx-- {
+			{
+				size, err := m.Headers[iNdEx].MarshalToSizedBuffer(dAtA[:i])
+				if err != nil {
+					return 0, err
+				}
+				i -= size
+				i = encodeVarintTypes(dAtA, i, uint64(size))
+			}
+			i--
+			dAtA[i] = 0x12
+		}
+	}
+	{
+		size, err := m.SystemHeader.MarshalToSizedBuffer(dAtA[:i])
+		if err != nil {
+			return 0, err
+		}
+		i -= size
+		i = encodeVarintTypes(dAtA, i, uint64(size))
+	}
+	i--
+	dAtA[i] = 0xa
+	return len(dAtA) - i, nil
+}
+
+func (m *StorageGroup) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *StorageGroup) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *StorageGroup) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if m.Lifetime != nil {
+		{
+			size, err := m.Lifetime.MarshalToSizedBuffer(dAtA[:i])
+			if err != nil {
+				return 0, err
+			}
+			i -= size
+			i = encodeVarintTypes(dAtA, i, uint64(size))
+		}
+		i--
+		dAtA[i] = 0x1a
+	}
+	{
+		size := m.ValidationHash.Size()
+		i -= size
+		if _, err := m.ValidationHash.MarshalTo(dAtA[i:]); err != nil {
+			return 0, err
+		}
+		i = encodeVarintTypes(dAtA, i, uint64(size))
+	}
+	i--
+	dAtA[i] = 0x12
+	if m.ValidationDataSize != 0 {
+		i = encodeVarintTypes(dAtA, i, uint64(m.ValidationDataSize))
+		i--
+		dAtA[i] = 0x8
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *StorageGroup_Lifetime) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *StorageGroup_Lifetime) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *StorageGroup_Lifetime) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if m.Value != 0 {
+		i = encodeVarintTypes(dAtA, i, uint64(m.Value))
+		i--
+		dAtA[i] = 0x10
+	}
+	if m.Unit != 0 {
+		i = encodeVarintTypes(dAtA, i, uint64(m.Unit))
+		i--
+		dAtA[i] = 0x8
+	}
+	return len(dAtA) - i, nil
+}
+
+func encodeVarintTypes(dAtA []byte, offset int, v uint64) int {
+	offset -= sovTypes(v)
+	base := offset
+	for v >= 1<<7 {
+		dAtA[offset] = uint8(v&0x7f | 0x80)
+		v >>= 7
+		offset++
+	}
+	dAtA[offset] = uint8(v)
+	return base
+}
+func (m *Range) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.Offset != 0 {
+		n += 1 + sovTypes(uint64(m.Offset))
+	}
+	if m.Length != 0 {
+		n += 1 + sovTypes(uint64(m.Length))
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *UserHeader) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = len(m.Key)
+	if l > 0 {
+		n += 1 + l + sovTypes(uint64(l))
+	}
+	l = len(m.Value)
+	if l > 0 {
+		n += 1 + l + sovTypes(uint64(l))
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *Header) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.Value != nil {
+		n += m.Value.Size()
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *Header_Link) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.Link != nil {
+		l = m.Link.Size()
+		n += 1 + l + sovTypes(uint64(l))
+	}
+	return n
+}
+func (m *Header_Redirect) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.Redirect != nil {
+		l = m.Redirect.Size()
+		n += 1 + l + sovTypes(uint64(l))
+	}
+	return n
+}
+func (m *Header_UserHeader) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.UserHeader != nil {
+		l = m.UserHeader.Size()
+		n += 1 + l + sovTypes(uint64(l))
+	}
+	return n
+}
+func (m *Header_Transform) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.Transform != nil {
+		l = m.Transform.Size()
+		n += 1 + l + sovTypes(uint64(l))
+	}
+	return n
+}
+func (m *Header_Tombstone) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.Tombstone != nil {
+		l = m.Tombstone.Size()
+		n += 1 + l + sovTypes(uint64(l))
+	}
+	return n
+}
+func (m *Header_Verify) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.Verify != nil {
+		l = m.Verify.Size()
+		n += 1 + l + sovTypes(uint64(l))
+	}
+	return n
+}
+func (m *Header_HomoHash) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = m.HomoHash.Size()
+	n += 1 + l + sovTypes(uint64(l))
+	return n
+}
+func (m *Header_PayloadChecksum) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.PayloadChecksum != nil {
+		l = len(m.PayloadChecksum)
+		n += 1 + l + sovTypes(uint64(l))
+	}
+	return n
+}
+func (m *Header_Integrity) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.Integrity != nil {
+		l = m.Integrity.Size()
+		n += 1 + l + sovTypes(uint64(l))
+	}
+	return n
+}
+func (m *Header_StorageGroup) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.StorageGroup != nil {
+		l = m.StorageGroup.Size()
+		n += 1 + l + sovTypes(uint64(l))
+	}
+	return n
+}
+func (m *Tombstone) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.Epoch != 0 {
+		n += 1 + sovTypes(uint64(m.Epoch))
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *SystemHeader) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.Version != 0 {
+		n += 1 + sovTypes(uint64(m.Version))
+	}
+	if m.PayloadLength != 0 {
+		n += 1 + sovTypes(uint64(m.PayloadLength))
+	}
+	l = m.ID.Size()
+	n += 1 + l + sovTypes(uint64(l))
+	l = m.OwnerID.Size()
+	n += 1 + l + sovTypes(uint64(l))
+	l = m.CID.Size()
+	n += 1 + l + sovTypes(uint64(l))
+	l = m.CreatedAt.Size()
+	n += 1 + l + sovTypes(uint64(l))
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *CreationPoint) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.UnixTime != 0 {
+		n += 1 + sovTypes(uint64(m.UnixTime))
+	}
+	if m.Epoch != 0 {
+		n += 1 + sovTypes(uint64(m.Epoch))
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *IntegrityHeader) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = len(m.HeadersChecksum)
+	if l > 0 {
+		n += 1 + l + sovTypes(uint64(l))
+	}
+	l = len(m.ChecksumSignature)
+	if l > 0 {
+		n += 1 + l + sovTypes(uint64(l))
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *Link) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.Type != 0 {
+		n += 1 + sovTypes(uint64(m.Type))
+	}
+	l = m.ID.Size()
+	n += 1 + l + sovTypes(uint64(l))
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *Transform) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.Type != 0 {
+		n += 1 + sovTypes(uint64(m.Type))
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *Object) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = m.SystemHeader.Size()
+	n += 1 + l + sovTypes(uint64(l))
+	if len(m.Headers) > 0 {
+		for _, e := range m.Headers {
+			l = e.Size()
+			n += 1 + l + sovTypes(uint64(l))
+		}
+	}
+	l = len(m.Payload)
+	if l > 0 {
+		n += 1 + l + sovTypes(uint64(l))
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *StorageGroup) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.ValidationDataSize != 0 {
+		n += 1 + sovTypes(uint64(m.ValidationDataSize))
+	}
+	l = m.ValidationHash.Size()
+	n += 1 + l + sovTypes(uint64(l))
+	if m.Lifetime != nil {
+		l = m.Lifetime.Size()
+		n += 1 + l + sovTypes(uint64(l))
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *StorageGroup_Lifetime) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.Unit != 0 {
+		n += 1 + sovTypes(uint64(m.Unit))
+	}
+	if m.Value != 0 {
+		n += 1 + sovTypes(uint64(m.Value))
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func sovTypes(x uint64) (n int) {
+	return (math_bits.Len64(x|1) + 6) / 7
+}
+func sozTypes(x uint64) (n int) {
+	return sovTypes(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+func (m *Range) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowTypes
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: Range: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: Range: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Offset", wireType)
+			}
+			m.Offset = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.Offset |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		case 2:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Length", wireType)
+			}
+			m.Length = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.Length |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		default:
+			iNdEx = preIndex
+			skippy, err := skipTypes(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *UserHeader) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowTypes
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: UserHeader: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: UserHeader: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Key = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Value = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipTypes(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *Header) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowTypes
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: Header: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: Header: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Link", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			v := &Link{}
+			if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			m.Value = &Header_Link{v}
+			iNdEx = postIndex
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Redirect", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			v := &refs.Address{}
+			if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			m.Value = &Header_Redirect{v}
+			iNdEx = postIndex
+		case 3:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field UserHeader", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			v := &UserHeader{}
+			if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			m.Value = &Header_UserHeader{v}
+			iNdEx = postIndex
+		case 4:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Transform", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			v := &Transform{}
+			if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			m.Value = &Header_Transform{v}
+			iNdEx = postIndex
+		case 5:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Tombstone", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			v := &Tombstone{}
+			if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			m.Value = &Header_Tombstone{v}
+			iNdEx = postIndex
+		case 6:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Verify", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			v := &session.VerificationHeader{}
+			if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			m.Value = &Header_Verify{v}
+			iNdEx = postIndex
+		case 7:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field HomoHash", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			var vv Hash
+			v := &vv
+			if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			m.Value = &Header_HomoHash{*v}
+			iNdEx = postIndex
+		case 8:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field PayloadChecksum", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			v := make([]byte, postIndex-iNdEx)
+			copy(v, dAtA[iNdEx:postIndex])
+			m.Value = &Header_PayloadChecksum{v}
+			iNdEx = postIndex
+		case 9:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Integrity", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			v := &IntegrityHeader{}
+			if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			m.Value = &Header_Integrity{v}
+			iNdEx = postIndex
+		case 10:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field StorageGroup", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			v := &StorageGroup{}
+			if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			m.Value = &Header_StorageGroup{v}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipTypes(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *Tombstone) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowTypes
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: Tombstone: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: Tombstone: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Epoch", wireType)
+			}
+			m.Epoch = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.Epoch |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		default:
+			iNdEx = preIndex
+			skippy, err := skipTypes(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *SystemHeader) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowTypes
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: SystemHeader: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: SystemHeader: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Version", wireType)
+			}
+			m.Version = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.Version |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		case 2:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field PayloadLength", wireType)
+			}
+			m.PayloadLength = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.PayloadLength |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		case 3:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.ID.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 4:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field OwnerID", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.OwnerID.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 5:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field CID", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.CID.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 6:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field CreatedAt", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.CreatedAt.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipTypes(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *CreationPoint) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowTypes
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: CreationPoint: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: CreationPoint: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field UnixTime", wireType)
+			}
+			m.UnixTime = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.UnixTime |= int64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		case 2:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Epoch", wireType)
+			}
+			m.Epoch = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.Epoch |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		default:
+			iNdEx = preIndex
+			skippy, err := skipTypes(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *IntegrityHeader) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowTypes
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: IntegrityHeader: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: IntegrityHeader: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field HeadersChecksum", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.HeadersChecksum = append(m.HeadersChecksum[:0], dAtA[iNdEx:postIndex]...)
+			if m.HeadersChecksum == nil {
+				m.HeadersChecksum = []byte{}
+			}
+			iNdEx = postIndex
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field ChecksumSignature", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.ChecksumSignature = append(m.ChecksumSignature[:0], dAtA[iNdEx:postIndex]...)
+			if m.ChecksumSignature == nil {
+				m.ChecksumSignature = []byte{}
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipTypes(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *Link) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowTypes
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: Link: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: Link: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType)
+			}
+			m.Type = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.Type |= Link_Type(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.ID.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipTypes(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *Transform) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowTypes
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: Transform: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: Transform: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType)
+			}
+			m.Type = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.Type |= Transform_Type(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		default:
+			iNdEx = preIndex
+			skippy, err := skipTypes(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *Object) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowTypes
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: Object: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: Object: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field SystemHeader", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.SystemHeader.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Headers", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Headers = append(m.Headers, Header{})
+			if err := m.Headers[len(m.Headers)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 3:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Payload", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Payload = append(m.Payload[:0], dAtA[iNdEx:postIndex]...)
+			if m.Payload == nil {
+				m.Payload = []byte{}
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipTypes(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *StorageGroup) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowTypes
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: StorageGroup: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: StorageGroup: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field ValidationDataSize", wireType)
+			}
+			m.ValidationDataSize = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.ValidationDataSize |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field ValidationHash", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.ValidationHash.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 3:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Lifetime", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if m.Lifetime == nil {
+				m.Lifetime = &StorageGroup_Lifetime{}
+			}
+			if err := m.Lifetime.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipTypes(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *StorageGroup_Lifetime) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowTypes
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: Lifetime: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: Lifetime: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Unit", wireType)
+			}
+			m.Unit = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.Unit |= StorageGroup_Lifetime_Unit(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		case 2:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType)
+			}
+			m.Value = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.Value |= int64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		default:
+			iNdEx = preIndex
+			skippy, err := skipTypes(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func skipTypes(dAtA []byte) (n int, err error) {
+	l := len(dAtA)
+	iNdEx := 0
+	depth := 0
+	for iNdEx < l {
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return 0, ErrIntOverflowTypes
+			}
+			if iNdEx >= l {
+				return 0, io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= (uint64(b) & 0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		wireType := int(wire & 0x7)
+		switch wireType {
+		case 0:
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return 0, ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return 0, io.ErrUnexpectedEOF
+				}
+				iNdEx++
+				if dAtA[iNdEx-1] < 0x80 {
+					break
+				}
+			}
+		case 1:
+			iNdEx += 8
+		case 2:
+			var length int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return 0, ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return 0, io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				length |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if length < 0 {
+				return 0, ErrInvalidLengthTypes
+			}
+			iNdEx += length
+		case 3:
+			depth++
+		case 4:
+			if depth == 0 {
+				return 0, ErrUnexpectedEndOfGroupTypes
+			}
+			depth--
+		case 5:
+			iNdEx += 4
+		default:
+			return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+		}
+		if iNdEx < 0 {
+			return 0, ErrInvalidLengthTypes
+		}
+		if depth == 0 {
+			return iNdEx, nil
+		}
+	}
+	return 0, io.ErrUnexpectedEOF
+}
+
+var (
+	ErrInvalidLengthTypes        = fmt.Errorf("proto: negative length found during unmarshaling")
+	ErrIntOverflowTypes          = fmt.Errorf("proto: integer overflow")
+	ErrUnexpectedEndOfGroupTypes = fmt.Errorf("proto: unexpected end of group")
+)
diff --git a/object/types.proto b/object/types.proto
new file mode 100644
index 00000000..a7cbd8c7
--- /dev/null
+++ b/object/types.proto
@@ -0,0 +1,107 @@
+syntax = "proto3";
+package object;
+option go_package = "github.com/nspcc-dev/neofs-proto/object";
+
+import "refs/types.proto";
+import "session/types.proto";
+import "github.com/gogo/protobuf/gogoproto/gogo.proto";
+
+option (gogoproto.stable_marshaler_all) = true;
+
+message Range {
+    uint64 Offset = 1;
+    uint64 Length = 2;
+}
+
+message UserHeader {
+    string Key = 1;
+    string Value = 2;
+}
+
+message Header {
+    oneof Value {
+        Link Link                         = 1;
+        refs.Address Redirect             = 2;
+        UserHeader UserHeader             = 3;
+        Transform Transform               = 4;
+        Tombstone Tombstone               = 5;
+        // session-related info: session.VerificationHeader
+        session.VerificationHeader Verify = 6;
+        // integrity-related info
+        bytes HomoHash                    = 7 [(gogoproto.customtype) = "Hash"];
+        bytes PayloadChecksum             = 8;
+        IntegrityHeader Integrity         = 9;
+        StorageGroup StorageGroup         = 10;
+    }
+}
+
+message Tombstone {
+    uint64 Epoch = 1;
+}
+
+message SystemHeader {
+    uint64 Version       = 1;
+    uint64 PayloadLength = 2;
+
+    bytes ID        = 3 [(gogoproto.customtype) = "ID", (gogoproto.nullable) = false];
+    bytes OwnerID   = 4 [(gogoproto.customtype) = "OwnerID",  (gogoproto.nullable) = false];
+    bytes CID       = 5 [(gogoproto.customtype) = "CID",      (gogoproto.nullable) = false];
+    CreationPoint CreatedAt = 6 [(gogoproto.nullable) = false];
+}
+
+message CreationPoint {
+    int64 UnixTime = 1;
+    uint64 Epoch = 2;
+}
+
+message IntegrityHeader {
+    bytes HeadersChecksum   = 1;
+    bytes ChecksumSignature = 2;
+}
+
+message Link {
+    enum Type {
+        Unknown      = 0;
+        Parent       = 1;
+        Previous     = 2;
+        Next         = 3;
+        Child        = 4;
+        StorageGroup = 5;
+    }
+    Type type  = 1;
+    bytes ID = 2 [(gogoproto.customtype) = "ID", (gogoproto.nullable) = false];
+}
+
+message Transform {
+    enum Type {
+        Unknown = 0;
+        Split   = 1;
+        Sign    = 2;
+        Mould   = 3;
+    }
+    Type type  = 1;
+}
+
+message Object {
+    SystemHeader SystemHeader = 1 [(gogoproto.nullable) = false];
+    repeated Header Headers   = 2 [(gogoproto.nullable) = false];
+    bytes Payload             = 3;
+}
+
+message StorageGroup {
+    uint64 ValidationDataSize = 1;
+    bytes ValidationHash = 2 [(gogoproto.customtype) = "Hash", (gogoproto.nullable) = false];
+
+    message Lifetime {
+        enum Unit {
+            Unlimited = 0;
+            NeoFSEpoch = 1;
+            UnixTime = 2;
+        }
+
+        Unit unit = 1 [(gogoproto.customname) = "Unit"];
+        int64 Value = 2;
+    }
+
+    Lifetime lifetime = 3 [(gogoproto.customname) = "Lifetime"];
+}
diff --git a/object/utils.go b/object/utils.go
new file mode 100644
index 00000000..1799b24f
--- /dev/null
+++ b/object/utils.go
@@ -0,0 +1,107 @@
+package object
+
+import (
+	"io"
+
+	"code.cloudfoundry.org/bytefmt"
+	"github.com/nspcc-dev/neofs-proto/session"
+	"github.com/pkg/errors"
+)
+
+const maxGetPayloadSize = 3584 * 1024 // 3.5 MiB
+
+func splitBytes(data []byte, maxSize int) (result [][]byte) {
+	l := len(data)
+	if l == 0 {
+		return [][]byte{data}
+	}
+	for i := 0; i < l; i += maxSize {
+		last := i + maxSize
+		if last > l {
+			last = l
+		}
+		result = append(result, data[i:last])
+	}
+	return
+}
+
+// SendPutRequest prepares object and sends it in chunks through protobuf stream.
+func SendPutRequest(s Service_PutClient, obj *Object, epoch uint64, ttl uint32) (*PutResponse, error) {
+	// TODO split must take into account size of the marshalled Object
+	chunks := splitBytes(obj.Payload, maxGetPayloadSize)
+	obj.Payload = chunks[0]
+	if err := s.Send(MakePutRequestHeader(obj, epoch, ttl, nil)); err != nil {
+		return nil, err
+	}
+	for i := range chunks[1:] {
+		if err := s.Send(MakePutRequestChunk(chunks[i+1])); err != nil {
+			return nil, err
+		}
+	}
+	resp, err := s.CloseAndRecv()
+	if err != nil && err != io.EOF {
+		return nil, err
+	}
+	return resp, nil
+}
+
+// MakePutRequestHeader combines object, epoch, ttl and session token value
+// into header of object put request.
+func MakePutRequestHeader(obj *Object, epoch uint64, ttl uint32, token *session.Token) *PutRequest {
+	return &PutRequest{
+		R: &PutRequest_Header{
+			Header: &PutRequest_PutHeader{
+				Epoch:  epoch,
+				Object: obj,
+				TTL:    ttl,
+				Token:  token,
+			},
+		},
+	}
+}
+
+// MakePutRequestChunk splits data into chunks that will be transferred
+// in the protobuf stream.
+func MakePutRequestChunk(chunk []byte) *PutRequest {
+	return &PutRequest{R: &PutRequest_Chunk{Chunk: chunk}}
+}
+
+func errMaxSizeExceeded(size uint64) error {
+	return errors.Errorf("object payload size exceed: %s", bytefmt.ByteSize(size))
+}
+
+// ReceiveGetResponse receives object by chunks from the protobuf stream
+// and combine it into single get response structure.
+func ReceiveGetResponse(c Service_GetClient, maxSize uint64) (*GetResponse, error) {
+	res, err := c.Recv()
+	if err == io.EOF {
+		return res, err
+	} else if err != nil {
+		return nil, err
+	}
+
+	obj := res.GetObject()
+	if obj == nil {
+		return nil, ErrHeaderExpected
+	}
+
+	if obj.SystemHeader.PayloadLength > maxSize {
+		return nil, errMaxSizeExceeded(maxSize)
+	}
+
+	if res.NotFull() {
+		payload := make([]byte, obj.SystemHeader.PayloadLength)
+		offset := copy(payload, obj.Payload)
+
+		var r *GetResponse
+		for r, err = c.Recv(); err == nil; r, err = c.Recv() {
+			offset += copy(payload[offset:], r.GetChunk())
+		}
+		if err != io.EOF {
+			return nil, err
+		}
+		obj.Payload = payload
+	}
+
+	return res, nil
+}
diff --git a/object/verification.go b/object/verification.go
new file mode 100644
index 00000000..761c04e2
--- /dev/null
+++ b/object/verification.go
@@ -0,0 +1,132 @@
+package object
+
+import (
+	"bytes"
+	"crypto/ecdsa"
+	"crypto/sha256"
+
+	crypto "github.com/nspcc-dev/neofs-crypto"
+	"github.com/pkg/errors"
+)
+
+func (m Object) headersData(check bool) ([]byte, error) {
+	var bytebuf = new(bytes.Buffer)
+
+	// fixme: we must marshal fields one by one without protobuf marshaling
+	//        protobuf marshaling does not guarantee the same result
+
+	if sysheader, err := m.SystemHeader.Marshal(); err != nil {
+		return nil, err
+	} else if _, err := bytebuf.Write(sysheader); err != nil {
+		return nil, err
+	}
+
+	n, _ := m.LastHeader(HeaderType(IntegrityHdr))
+	for i := range m.Headers {
+		if check && i == n {
+			// ignore last integrity header in order to check headers data
+			continue
+		}
+
+		if header, err := m.Headers[i].Marshal(); err != nil {
+			return nil, err
+		} else if _, err := bytebuf.Write(header); err != nil {
+			return nil, err
+		}
+	}
+	return bytebuf.Bytes(), nil
+}
+
+func (m Object) headersChecksum(check bool) ([]byte, error) {
+	data, err := m.headersData(check)
+	if err != nil {
+		return nil, err
+	}
+	checksum := sha256.Sum256(data)
+	return checksum[:], nil
+}
+
+// PayloadChecksum calculates sha256 checksum of object payload.
+func (m Object) PayloadChecksum() []byte {
+	checksum := sha256.Sum256(m.Payload)
+	return checksum[:]
+}
+
+func (m Object) verifySignature(key []byte, ih *IntegrityHeader) error {
+	pk := crypto.UnmarshalPublicKey(key)
+	if crypto.Verify(pk, ih.HeadersChecksum, ih.ChecksumSignature) == nil {
+		return nil
+	}
+	return ErrVerifySignature
+}
+
+// Verify performs local integrity check by finding verification header and
+// integrity header. If header integrity is passed, function verifies
+// checksum of the object payload.
+func (m Object) Verify() error {
+	var (
+		err      error
+		checksum []byte
+	)
+	// Prepare structures
+	_, vh := m.LastHeader(HeaderType(VerifyHdr))
+	if vh == nil {
+		return ErrHeaderNotFound
+	}
+	verify := vh.Value.(*Header_Verify).Verify
+
+	_, ih := m.LastHeader(HeaderType(IntegrityHdr))
+	if ih == nil {
+		return ErrHeaderNotFound
+	}
+	integrity := ih.Value.(*Header_Integrity).Integrity
+
+	// Verify signature
+	err = m.verifySignature(verify.PublicKey, integrity)
+	if err != nil {
+		return errors.Wrapf(err, "public key: %x", verify.PublicKey)
+	}
+
+	// Verify checksum of header
+	checksum, err = m.headersChecksum(true)
+	if err != nil {
+		return err
+	}
+	if !bytes.Equal(integrity.HeadersChecksum, checksum) {
+		return ErrVerifyHeader
+	}
+
+	// Verify checksum of payload
+	if m.SystemHeader.PayloadLength > 0 && !m.IsLinking() {
+		checksum = m.PayloadChecksum()
+
+		_, ph := m.LastHeader(HeaderType(PayloadChecksumHdr))
+		if ph == nil {
+			return ErrHeaderNotFound
+		}
+		if !bytes.Equal(ph.Value.(*Header_PayloadChecksum).PayloadChecksum, checksum) {
+			return ErrVerifyPayload
+		}
+	}
+	return nil
+}
+
+// Sign creates new integrity header and adds it to the end of the list of
+// extended headers.
+func (m *Object) Sign(key *ecdsa.PrivateKey) error {
+	headerChecksum, err := m.headersChecksum(false)
+	if err != nil {
+		return err
+	}
+	headerChecksumSignature, err := crypto.Sign(key, headerChecksum)
+	if err != nil {
+		return err
+	}
+	m.AddHeader(&Header{Value: &Header_Integrity{
+		Integrity: &IntegrityHeader{
+			HeadersChecksum:   headerChecksum,
+			ChecksumSignature: headerChecksumSignature,
+		},
+	}})
+	return nil
+}
diff --git a/object/verification_test.go b/object/verification_test.go
new file mode 100644
index 00000000..f91e0518
--- /dev/null
+++ b/object/verification_test.go
@@ -0,0 +1,105 @@
+package object
+
+import (
+	"testing"
+
+	"github.com/google/uuid"
+	crypto "github.com/nspcc-dev/neofs-crypto"
+	"github.com/nspcc-dev/neofs-crypto/test"
+	"github.com/nspcc-dev/neofs-proto/container"
+	"github.com/nspcc-dev/neofs-proto/refs"
+	"github.com/nspcc-dev/neofs-proto/session"
+	"github.com/stretchr/testify/require"
+)
+
+func TestObject_Verify(t *testing.T) {
+	key := test.DecodeKey(0)
+	sessionkey := test.DecodeKey(1)
+
+	payload := make([]byte, 1024*1024)
+
+	cnr, err := container.NewTestContainer()
+	require.NoError(t, err)
+
+	cid, err := cnr.ID()
+	require.NoError(t, err)
+
+	id, err := uuid.NewRandom()
+	uid := refs.UUID(id)
+	require.NoError(t, err)
+
+	obj := &Object{
+		SystemHeader: SystemHeader{
+			ID:      uid,
+			CID:     cid,
+			OwnerID: refs.OwnerID([refs.OwnerIDSize]byte{}),
+		},
+		Headers: []Header{
+			{
+				Value: &Header_UserHeader{
+					UserHeader: &UserHeader{
+						Key:   "Profession",
+						Value: "Developer",
+					},
+				},
+			},
+			{
+				Value: &Header_UserHeader{
+					UserHeader: &UserHeader{
+						Key:   "Language",
+						Value: "GO",
+					},
+				},
+			},
+		},
+	}
+	obj.SetPayload(payload)
+	obj.SetHeader(&Header{Value: &Header_PayloadChecksum{[]byte("incorrect checksum")}})
+
+	t.Run("error no integrity header", func(t *testing.T) {
+		err = obj.Verify()
+		require.EqualError(t, err, ErrHeaderNotFound.Error())
+	})
+
+	badHeaderChecksum := []byte("incorrect checksum")
+	signature, err := crypto.Sign(sessionkey, badHeaderChecksum)
+	require.NoError(t, err)
+	ih := &IntegrityHeader{
+		HeadersChecksum:   badHeaderChecksum,
+		ChecksumSignature: signature,
+	}
+	obj.SetHeader(&Header{Value: &Header_Integrity{ih}})
+
+	t.Run("error no validation header", func(t *testing.T) {
+		err = obj.Verify()
+		require.EqualError(t, err, ErrHeaderNotFound.Error())
+	})
+
+	dataPK := crypto.MarshalPublicKey(&sessionkey.PublicKey)
+	signature, err = crypto.Sign(key, dataPK)
+	vh := &session.VerificationHeader{
+		PublicKey:    dataPK,
+		KeySignature: signature,
+	}
+	obj.SetVerificationHeader(vh)
+
+	t.Run("error invalid header checksum", func(t *testing.T) {
+		err = obj.Verify()
+		require.EqualError(t, err, ErrVerifyHeader.Error())
+	})
+
+	require.NoError(t, obj.Sign(sessionkey))
+
+	t.Run("error invalid payload checksum", func(t *testing.T) {
+		err = obj.Verify()
+		require.EqualError(t, err, ErrVerifyPayload.Error())
+	})
+
+	obj.SetHeader(&Header{Value: &Header_PayloadChecksum{obj.PayloadChecksum()}})
+	require.NoError(t, obj.Sign(sessionkey))
+
+	t.Run("correct", func(t *testing.T) {
+		err = obj.Verify()
+		require.NoError(t, err)
+	})
+}
diff --git a/proto.go b/proto.go
new file mode 100644
index 00000000..b15f22a7
--- /dev/null
+++ b/proto.go
@@ -0,0 +1,7 @@
+package neofs_proto // import "github.com/nspcc-dev/neofs-proto"
+
+import (
+	_ "github.com/gogo/protobuf/gogoproto"
+	_ "github.com/gogo/protobuf/proto"
+	_ "github.com/golang/protobuf/proto"
+)
diff --git a/query/types.go b/query/types.go
new file mode 100644
index 00000000..15a54f65
--- /dev/null
+++ b/query/types.go
@@ -0,0 +1,43 @@
+package query
+
+import (
+	"strings"
+
+	"github.com/gogo/protobuf/proto"
+)
+
+var (
+	_ proto.Message = (*Query)(nil)
+	_ proto.Message = (*Filter)(nil)
+)
+
+// String returns string representation of Filter.
+func (m Filter) String() string {
+	b := new(strings.Builder)
+	b.WriteString("<Filter '$" + m.Name + "' ")
+	switch m.Type {
+	case Filter_Exact:
+		b.WriteString("==")
+	case Filter_Regex:
+		b.WriteString("~=")
+	default:
+		b.WriteString("??")
+	}
+	b.WriteString(" '" + m.Value + "'>")
+	return b.String()
+}
+
+// String returns string representation of Query.
+func (m Query) String() string {
+	b := new(strings.Builder)
+	b.WriteString("<Query [")
+	ln := len(m.Filters)
+	for i := 0; i < ln; i++ {
+		b.WriteString(m.Filters[i].String())
+		if ln-1 != i {
+			b.WriteByte(',')
+		}
+	}
+	b.WriteByte(']')
+	return b.String()
+}
diff --git a/query/types.pb.go b/query/types.pb.go
new file mode 100644
index 00000000..51f682eb
--- /dev/null
+++ b/query/types.pb.go
@@ -0,0 +1,634 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: query/types.proto
+
+package query
+
+import (
+	fmt "fmt"
+	_ "github.com/gogo/protobuf/gogoproto"
+	proto "github.com/golang/protobuf/proto"
+	io "io"
+	math "math"
+	math_bits "math/bits"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
+
+type Filter_Type int32
+
+const (
+	Filter_Exact Filter_Type = 0
+	Filter_Regex Filter_Type = 1
+)
+
+var Filter_Type_name = map[int32]string{
+	0: "Exact",
+	1: "Regex",
+}
+
+var Filter_Type_value = map[string]int32{
+	"Exact": 0,
+	"Regex": 1,
+}
+
+func (x Filter_Type) String() string {
+	return proto.EnumName(Filter_Type_name, int32(x))
+}
+
+func (Filter_Type) EnumDescriptor() ([]byte, []int) {
+	return fileDescriptor_c682aeaf51d46f4d, []int{0, 0}
+}
+
+type Filter struct {
+	Type                 Filter_Type `protobuf:"varint,1,opt,name=type,proto3,enum=query.Filter_Type" json:"type,omitempty"`
+	Name                 string      `protobuf:"bytes,2,opt,name=Name,proto3" json:"Name,omitempty"`
+	Value                string      `protobuf:"bytes,3,opt,name=Value,proto3" json:"Value,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}    `json:"-"`
+	XXX_unrecognized     []byte      `json:"-"`
+	XXX_sizecache        int32       `json:"-"`
+}
+
+func (m *Filter) Reset()      { *m = Filter{} }
+func (*Filter) ProtoMessage() {}
+func (*Filter) Descriptor() ([]byte, []int) {
+	return fileDescriptor_c682aeaf51d46f4d, []int{0}
+}
+func (m *Filter) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *Filter) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *Filter) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Filter.Merge(m, src)
+}
+func (m *Filter) XXX_Size() int {
+	return m.Size()
+}
+func (m *Filter) XXX_DiscardUnknown() {
+	xxx_messageInfo_Filter.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Filter proto.InternalMessageInfo
+
+func (m *Filter) GetType() Filter_Type {
+	if m != nil {
+		return m.Type
+	}
+	return Filter_Exact
+}
+
+func (m *Filter) GetName() string {
+	if m != nil {
+		return m.Name
+	}
+	return ""
+}
+
+func (m *Filter) GetValue() string {
+	if m != nil {
+		return m.Value
+	}
+	return ""
+}
+
+type Query struct {
+	Filters              []Filter `protobuf:"bytes,1,rep,name=Filters,proto3" json:"Filters"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *Query) Reset()      { *m = Query{} }
+func (*Query) ProtoMessage() {}
+func (*Query) Descriptor() ([]byte, []int) {
+	return fileDescriptor_c682aeaf51d46f4d, []int{1}
+}
+func (m *Query) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *Query) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *Query) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Query.Merge(m, src)
+}
+func (m *Query) XXX_Size() int {
+	return m.Size()
+}
+func (m *Query) XXX_DiscardUnknown() {
+	xxx_messageInfo_Query.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Query proto.InternalMessageInfo
+
+func (m *Query) GetFilters() []Filter {
+	if m != nil {
+		return m.Filters
+	}
+	return nil
+}
+
+func init() {
+	proto.RegisterEnum("query.Filter_Type", Filter_Type_name, Filter_Type_value)
+	proto.RegisterType((*Filter)(nil), "query.Filter")
+	proto.RegisterType((*Query)(nil), "query.Query")
+}
+
+func init() { proto.RegisterFile("query/types.proto", fileDescriptor_c682aeaf51d46f4d) }
+
+var fileDescriptor_c682aeaf51d46f4d = []byte{
+	// 275 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x2c, 0x2c, 0x4d, 0x2d,
+	0xaa, 0xd4, 0x2f, 0xa9, 0x2c, 0x48, 0x2d, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x05,
+	0x0b, 0x49, 0xe9, 0xa6, 0x67, 0x96, 0x64, 0x94, 0x26, 0xe9, 0x25, 0xe7, 0xe7, 0xea, 0xa7, 0xe7,
+	0xa7, 0xe7, 0xeb, 0x83, 0x65, 0x93, 0x4a, 0xd3, 0xc0, 0x3c, 0x30, 0x07, 0xcc, 0x82, 0xe8, 0x52,
+	0xea, 0x60, 0xe4, 0x62, 0x73, 0xcb, 0xcc, 0x29, 0x49, 0x2d, 0x12, 0x32, 0xe0, 0x62, 0x01, 0x99,
+	0x27, 0xc1, 0xa8, 0xc0, 0xa8, 0xc1, 0x67, 0x24, 0xa4, 0x07, 0x36, 0x4f, 0x0f, 0x22, 0xa9, 0x17,
+	0x52, 0x59, 0x90, 0xea, 0xc4, 0xf1, 0xe8, 0x9e, 0x3c, 0x0b, 0x88, 0x15, 0x04, 0x56, 0x29, 0x24,
+	0xc4, 0xc5, 0xe2, 0x97, 0x98, 0x9b, 0x2a, 0xc1, 0xa4, 0xc0, 0xa8, 0xc1, 0x19, 0x04, 0x66, 0x0b,
+	0x89, 0x70, 0xb1, 0x86, 0x25, 0xe6, 0x94, 0xa6, 0x4a, 0x30, 0x83, 0x05, 0x21, 0x1c, 0x25, 0x19,
+	0x2e, 0xb0, 0x3e, 0x21, 0x4e, 0x2e, 0x56, 0xd7, 0x8a, 0xc4, 0xe4, 0x12, 0x01, 0x06, 0x10, 0x33,
+	0x28, 0x35, 0x3d, 0xb5, 0x42, 0x80, 0xd1, 0x8a, 0x65, 0xc6, 0x02, 0x79, 0x06, 0x25, 0x1b, 0x2e,
+	0xd6, 0x40, 0x90, 0x95, 0x42, 0xba, 0x5c, 0xec, 0x10, 0x5b, 0x8b, 0x25, 0x18, 0x15, 0x98, 0x35,
+	0xb8, 0x8d, 0x78, 0x51, 0xdc, 0xe2, 0xc4, 0x72, 0xe2, 0x9e, 0x3c, 0x43, 0x10, 0x4c, 0x0d, 0x44,
+	0xb7, 0x93, 0xcd, 0x89, 0x47, 0x72, 0x8c, 0x17, 0x1e, 0xc9, 0x31, 0xde, 0x78, 0x24, 0xc7, 0xf8,
+	0xe0, 0x91, 0x1c, 0xe3, 0x8c, 0xc7, 0x72, 0x0c, 0x51, 0x6a, 0x48, 0xa1, 0x91, 0x57, 0x5c, 0x90,
+	0x9c, 0xac, 0x9b, 0x92, 0x5a, 0xa6, 0x9f, 0x97, 0x9a, 0x9f, 0x56, 0xac, 0x0b, 0x09, 0x0b, 0xb0,
+	0xc9, 0x49, 0x6c, 0x60, 0x8e, 0x31, 0x20, 0x00, 0x00, 0xff, 0xff, 0xa6, 0xcd, 0xeb, 0xf6, 0x58,
+	0x01, 0x00, 0x00,
+}
+
+func (m *Filter) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *Filter) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *Filter) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if len(m.Value) > 0 {
+		i -= len(m.Value)
+		copy(dAtA[i:], m.Value)
+		i = encodeVarintTypes(dAtA, i, uint64(len(m.Value)))
+		i--
+		dAtA[i] = 0x1a
+	}
+	if len(m.Name) > 0 {
+		i -= len(m.Name)
+		copy(dAtA[i:], m.Name)
+		i = encodeVarintTypes(dAtA, i, uint64(len(m.Name)))
+		i--
+		dAtA[i] = 0x12
+	}
+	if m.Type != 0 {
+		i = encodeVarintTypes(dAtA, i, uint64(m.Type))
+		i--
+		dAtA[i] = 0x8
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *Query) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *Query) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *Query) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if len(m.Filters) > 0 {
+		for iNdEx := len(m.Filters) - 1; iNdEx >= 0; iNdEx-- {
+			{
+				size, err := m.Filters[iNdEx].MarshalToSizedBuffer(dAtA[:i])
+				if err != nil {
+					return 0, err
+				}
+				i -= size
+				i = encodeVarintTypes(dAtA, i, uint64(size))
+			}
+			i--
+			dAtA[i] = 0xa
+		}
+	}
+	return len(dAtA) - i, nil
+}
+
+func encodeVarintTypes(dAtA []byte, offset int, v uint64) int {
+	offset -= sovTypes(v)
+	base := offset
+	for v >= 1<<7 {
+		dAtA[offset] = uint8(v&0x7f | 0x80)
+		v >>= 7
+		offset++
+	}
+	dAtA[offset] = uint8(v)
+	return base
+}
+func (m *Filter) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.Type != 0 {
+		n += 1 + sovTypes(uint64(m.Type))
+	}
+	l = len(m.Name)
+	if l > 0 {
+		n += 1 + l + sovTypes(uint64(l))
+	}
+	l = len(m.Value)
+	if l > 0 {
+		n += 1 + l + sovTypes(uint64(l))
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *Query) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if len(m.Filters) > 0 {
+		for _, e := range m.Filters {
+			l = e.Size()
+			n += 1 + l + sovTypes(uint64(l))
+		}
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func sovTypes(x uint64) (n int) {
+	return (math_bits.Len64(x|1) + 6) / 7
+}
+func sozTypes(x uint64) (n int) {
+	return sovTypes(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+func (m *Filter) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowTypes
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: Filter: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: Filter: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType)
+			}
+			m.Type = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.Type |= Filter_Type(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Name = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 3:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Value = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipTypes(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *Query) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowTypes
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: Query: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: Query: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Filters", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Filters = append(m.Filters, Filter{})
+			if err := m.Filters[len(m.Filters)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipTypes(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func skipTypes(dAtA []byte) (n int, err error) {
+	l := len(dAtA)
+	iNdEx := 0
+	depth := 0
+	for iNdEx < l {
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return 0, ErrIntOverflowTypes
+			}
+			if iNdEx >= l {
+				return 0, io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= (uint64(b) & 0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		wireType := int(wire & 0x7)
+		switch wireType {
+		case 0:
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return 0, ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return 0, io.ErrUnexpectedEOF
+				}
+				iNdEx++
+				if dAtA[iNdEx-1] < 0x80 {
+					break
+				}
+			}
+		case 1:
+			iNdEx += 8
+		case 2:
+			var length int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return 0, ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return 0, io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				length |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if length < 0 {
+				return 0, ErrInvalidLengthTypes
+			}
+			iNdEx += length
+		case 3:
+			depth++
+		case 4:
+			if depth == 0 {
+				return 0, ErrUnexpectedEndOfGroupTypes
+			}
+			depth--
+		case 5:
+			iNdEx += 4
+		default:
+			return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+		}
+		if iNdEx < 0 {
+			return 0, ErrInvalidLengthTypes
+		}
+		if depth == 0 {
+			return iNdEx, nil
+		}
+	}
+	return 0, io.ErrUnexpectedEOF
+}
+
+var (
+	ErrInvalidLengthTypes        = fmt.Errorf("proto: negative length found during unmarshaling")
+	ErrIntOverflowTypes          = fmt.Errorf("proto: integer overflow")
+	ErrUnexpectedEndOfGroupTypes = fmt.Errorf("proto: unexpected end of group")
+)
diff --git a/query/types.proto b/query/types.proto
new file mode 100644
index 00000000..5f460724
--- /dev/null
+++ b/query/types.proto
@@ -0,0 +1,25 @@
+syntax = "proto3";
+package query;
+option go_package = "github.com/nspcc-dev/neofs-proto/query";
+
+import "github.com/gogo/protobuf/gogoproto/gogo.proto";
+
+option (gogoproto.stable_marshaler_all) = true;
+
+message Filter {
+    option (gogoproto.goproto_stringer) = false;
+
+    enum Type {
+        Exact = 0;
+        Regex = 1;
+    }
+    Type type = 1 [(gogoproto.customname) = "Type"];
+    string Name = 2;
+    string Value = 3;
+}
+
+message Query {
+    option (gogoproto.goproto_stringer) = false;
+
+    repeated Filter Filters = 1 [(gogoproto.nullable) = false];
+}
diff --git a/refs/address.go b/refs/address.go
new file mode 100644
index 00000000..be6b6a32
--- /dev/null
+++ b/refs/address.go
@@ -0,0 +1,68 @@
+package refs
+
+import (
+	"crypto/sha256"
+	"strings"
+
+	"github.com/nspcc-dev/neofs-proto/internal"
+)
+
+const (
+	joinSeparator = "/"
+
+	// ErrWrongAddress is raised when wrong address is passed to Address.Parse ParseAddress.
+	ErrWrongAddress = internal.Error("wrong address")
+
+	// ErrEmptyAddress is raised when empty address is passed to Address.Parse ParseAddress.
+	ErrEmptyAddress = internal.Error("empty address")
+)
+
+// ParseAddress parses address from string representation into new Address.
+func ParseAddress(str string) (*Address, error) {
+	var addr Address
+	return &addr, addr.Parse(str)
+}
+
+// Parse parses address from string representation into current Address.
+func (m *Address) Parse(addr string) error {
+	if m == nil {
+		return ErrEmptyAddress
+	}
+
+	items := strings.Split(addr, joinSeparator)
+	if len(items) != 2 {
+		return ErrWrongAddress
+	}
+
+	if err := m.CID.Parse(items[0]); err != nil {
+		return err
+	} else if err := m.ObjectID.Parse(items[1]); err != nil {
+		return err
+	}
+
+	return nil
+}
+
+// String returns string representation of Address.
+func (m Address) String() string {
+	return strings.Join([]string{m.CID.String(), m.ObjectID.String()}, joinSeparator)
+}
+
+// IsFull checks that ContainerID and ObjectID is not empty.
+func (m Address) IsFull() bool {
+	return !m.CID.Empty() && !m.ObjectID.Empty()
+}
+
+// Equal checks that current Address is equal to passed Address.
+func (m Address) Equal(a2 *Address) bool {
+	return m.CID.Equal(a2.CID) && m.ObjectID.Equal(a2.ObjectID)
+}
+
+// Hash returns []byte that used as a key for storage bucket.
+func (m Address) Hash() ([]byte, error) {
+	if !m.IsFull() {
+		return nil, ErrEmptyAddress
+	}
+	h := sha256.Sum256(append(m.ObjectID.Bytes(), m.CID.Bytes()...))
+	return h[:], nil
+}
diff --git a/refs/cid.go b/refs/cid.go
new file mode 100644
index 00000000..4f0cf39d
--- /dev/null
+++ b/refs/cid.go
@@ -0,0 +1,96 @@
+package refs
+
+import (
+	"bytes"
+	"crypto/sha256"
+
+	"github.com/mr-tron/base58"
+	"github.com/pkg/errors"
+)
+
+// CIDForBytes creates CID for passed bytes.
+func CIDForBytes(data []byte) CID { return sha256.Sum256(data) }
+
+// CIDFromBytes parses CID from passed bytes.
+func CIDFromBytes(data []byte) (cid CID, err error) {
+	if ln := len(data); ln != CIDSize {
+		return CID{}, errors.Wrapf(ErrWrongDataSize, "expect=%d, actual=%d", CIDSize, ln)
+	}
+
+	copy(cid[:], data)
+	return
+}
+
+// CIDFromString parses CID from string representation of CID.
+func CIDFromString(c string) (CID, error) {
+	var cid CID
+	decoded, err := base58.Decode(c)
+	if err != nil {
+		return cid, err
+	}
+	return CIDFromBytes(decoded)
+}
+
+// Size returns size of CID (CIDSize).
+func (c CID) Size() int { return CIDSize }
+
+// Parse tries to parse CID from string representation.
+func (c *CID) Parse(cid string) error {
+	var err error
+	if *c, err = CIDFromString(cid); err != nil {
+		return err
+	}
+	return nil
+}
+
+// Empty checks that current CID is empty.
+func (c CID) Empty() bool { return bytes.Equal(c.Bytes(), emptyCID) }
+
+// Equal checks that current CID is equal to passed CID.
+func (c CID) Equal(cid CID) bool { return bytes.Equal(c.Bytes(), cid.Bytes()) }
+
+// Marshal returns CID bytes representation.
+func (c CID) Marshal() ([]byte, error) { return c.Bytes(), nil }
+
+// MarshalBinary returns CID bytes representation.
+func (c CID) MarshalBinary() ([]byte, error) { return c.Bytes(), nil }
+
+// MarshalTo marshal CID to bytes representation into passed bytes.
+func (c *CID) MarshalTo(data []byte) (int, error) { return copy(data, c.Bytes()), nil }
+
+// ProtoMessage method to satisfy proto.Message interface.
+func (c CID) ProtoMessage() {}
+
+// String returns string representation of CID.
+func (c CID) String() string { return base58.Encode(c[:]) }
+
+// Reset resets current CID to zero value.
+func (c *CID) Reset() { *c = CID{} }
+
+// Bytes returns CID bytes representation.
+func (c CID) Bytes() []byte {
+	buf := make([]byte, CIDSize)
+	copy(buf, c[:])
+	return buf
+}
+
+// UnmarshalBinary tries to parse bytes representation of CID.
+func (c *CID) UnmarshalBinary(data []byte) error { return c.Unmarshal(data) }
+
+// Unmarshal tries to parse bytes representation of CID.
+func (c *CID) Unmarshal(data []byte) error {
+	if ln := len(data); ln != CIDSize {
+		return errors.Wrapf(ErrWrongDataSize, "expect=%d, actual=%d", CIDSize, ln)
+	}
+
+	copy((*c)[:], data)
+	return nil
+}
+
+// Verify validates that current CID is generated for passed bytes data.
+func (c CID) Verify(data []byte) error {
+	if id := CIDForBytes(data); !bytes.Equal(c[:], id[:]) {
+		return errors.New("wrong hash for data")
+	}
+	return nil
+}
diff --git a/refs/owner.go b/refs/owner.go
new file mode 100644
index 00000000..ff88446f
--- /dev/null
+++ b/refs/owner.go
@@ -0,0 +1,65 @@
+package refs
+
+import (
+	"bytes"
+	"crypto/ecdsa"
+
+	"github.com/mr-tron/base58"
+	"github.com/nspcc-dev/neofs-proto/chain"
+	"github.com/pkg/errors"
+)
+
+// NewOwnerID returns generated OwnerID from passed public keys.
+func NewOwnerID(keys ...*ecdsa.PublicKey) (owner OwnerID, err error) {
+	if len(keys) == 0 {
+		return
+	}
+	var d []byte
+	d, err = base58.Decode(chain.KeysToAddress(keys...))
+	if err != nil {
+		return
+	}
+	copy(owner[:], d)
+	return owner, nil
+}
+
+// Size returns OwnerID size in bytes (OwnerIDSize).
+func (OwnerID) Size() int { return OwnerIDSize }
+
+// Empty checks that current OwnerID is empty value.
+func (o OwnerID) Empty() bool { return bytes.Equal(o.Bytes(), emptyOwner) }
+
+// Equal checks that current OwnerID is equal to passed OwnerID.
+func (o OwnerID) Equal(id OwnerID) bool { return bytes.Equal(o.Bytes(), id.Bytes()) }
+
+// Reset sets current OwnerID to empty value.
+func (o *OwnerID) Reset() { *o = OwnerID{} }
+
+// ProtoMessage method to satisfy proto.Message interface.
+func (OwnerID) ProtoMessage() {}
+
+// Marshal returns OwnerID bytes representation.
+func (o OwnerID) Marshal() ([]byte, error) { return o.Bytes(), nil }
+
+// MarshalTo copies OwnerID bytes representation into passed slice of bytes.
+func (o OwnerID) MarshalTo(data []byte) (int, error) { return copy(data, o.Bytes()), nil }
+
+// String returns string representation of OwnerID.
+func (o OwnerID) String() string { return base58.Encode(o[:]) }
+
+// Bytes returns OwnerID bytes representation.
+func (o OwnerID) Bytes() []byte {
+	buf := make([]byte, OwnerIDSize)
+	copy(buf, o[:])
+	return buf
+}
+
+// Unmarshal tries to parse OwnerID bytes representation into current OwnerID.
+func (o *OwnerID) Unmarshal(data []byte) error {
+	if ln := len(data); ln != OwnerIDSize {
+		return errors.Wrapf(ErrWrongDataSize, "expect=%d, actual=%d", OwnerIDSize, ln)
+	}
+
+	copy((*o)[:], data)
+	return nil
+}
diff --git a/refs/sgid.go b/refs/sgid.go
new file mode 100644
index 00000000..d6fcf2d7
--- /dev/null
+++ b/refs/sgid.go
@@ -0,0 +1,14 @@
+package refs
+
+import (
+	"github.com/pkg/errors"
+)
+
+// SGIDFromBytes parse bytes representation of SGID into new SGID value.
+func SGIDFromBytes(data []byte) (sgid SGID, err error) {
+	if ln := len(data); ln != SGIDSize {
+		return SGID{}, errors.Wrapf(ErrWrongDataSize, "expect=%d, actual=%d", SGIDSize, ln)
+	}
+	copy(sgid[:], data)
+	return
+}
diff --git a/refs/types.go b/refs/types.go
new file mode 100644
index 00000000..785155c6
--- /dev/null
+++ b/refs/types.go
@@ -0,0 +1,106 @@
+// This package contains basic structures implemented in Go, such as
+//
+// CID - container id
+// OwnerID - owner id
+// ObjectID - object id
+// SGID - storage group id
+// Address - contains object id and container id
+// UUID - a 128 bit (16 byte) Universal Unique Identifier as defined in RFC 4122
+
+package refs
+
+import (
+	"crypto/sha256"
+
+	"github.com/google/uuid"
+	"github.com/nspcc-dev/neofs-proto/chain"
+	"github.com/nspcc-dev/neofs-proto/internal"
+)
+
+type (
+	// CID is implementation of ContainerID.
+	CID [CIDSize]byte
+
+	// UUID wrapper over github.com/google/uuid.UUID.
+	UUID uuid.UUID
+
+	// SGID is type alias of UUID.
+	SGID = UUID
+
+	// ObjectID is type alias of UUID.
+	ObjectID = UUID
+
+	// MessageID is type alias of UUID.
+	MessageID = UUID
+
+	// OwnerID is wrapper over neofs-proto/chain.WalletAddress.
+	OwnerID chain.WalletAddress
+)
+
+const (
+	// UUIDSize contains size of UUID.
+	UUIDSize = 16
+
+	// SGIDSize contains size of SGID.
+	SGIDSize = UUIDSize
+
+	// CIDSize contains size of CID.
+	CIDSize = sha256.Size
+
+	// OwnerIDSize contains size of OwnerID.
+	OwnerIDSize = chain.AddressLength
+
+	// ErrWrongDataSize is raised when passed bytes into Unmarshal have wrong size.
+	ErrWrongDataSize = internal.Error("wrong data size")
+
+	// ErrEmptyOwner is raised when empty OwnerID is passed into container.New.
+	ErrEmptyOwner = internal.Error("owner cant be empty")
+
+	// ErrEmptyCapacity is raised when empty Capacity is passed container.New.
+	ErrEmptyCapacity = internal.Error("capacity cant be empty")
+
+	// ErrEmptyContainer is raised when it CID method is called for an empty container.
+	ErrEmptyContainer = internal.Error("cannot return ID for empty container")
+)
+
+var (
+	emptyCID   = (CID{}).Bytes()
+	emptyUUID  = (UUID{}).Bytes()
+	emptyOwner = (OwnerID{}).Bytes()
+
+	_ internal.Custom = (*CID)(nil)
+	_ internal.Custom = (*SGID)(nil)
+	_ internal.Custom = (*UUID)(nil)
+	_ internal.Custom = (*OwnerID)(nil)
+	_ internal.Custom = (*ObjectID)(nil)
+	_ internal.Custom = (*MessageID)(nil)
+
+	// NewSGID method alias.
+	NewSGID = NewUUID
+
+	// NewObjectID method alias.
+	NewObjectID = NewUUID
+
+	// NewMessageID method alias.
+	NewMessageID = NewUUID
+)
+
+// NewUUID returns a Random (Version 4) UUID.
+//
+// The strength of the UUIDs is based on the strength of the crypto/rand
+// package.
+//
+// A note about uniqueness derived from the UUID Wikipedia entry:
+//
+//  Randomly generated UUIDs have 122 random bits.  One's annual risk of being
+//  hit by a meteorite is estimated to be one chance in 17 billion, that
+//  means the probability is about 0.00000000006 (6 × 10−11),
+//  equivalent to the odds of creating a few tens of trillions of UUIDs in a
+//  year and having one duplicate.
+func NewUUID() (UUID, error) {
+	id, err := uuid.NewRandom()
+	if err != nil {
+		return UUID{}, err
+	}
+	return UUID(id), nil
+}
diff --git a/refs/types.pb.go b/refs/types.pb.go
new file mode 100644
index 00000000..33f7578a
--- /dev/null
+++ b/refs/types.pb.go
@@ -0,0 +1,368 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: refs/types.proto
+
+package refs
+
+import (
+	fmt "fmt"
+	_ "github.com/gogo/protobuf/gogoproto"
+	proto "github.com/golang/protobuf/proto"
+	io "io"
+	math "math"
+	math_bits "math/bits"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
+
+type Address struct {
+	ObjectID             ObjectID `protobuf:"bytes,1,opt,name=ObjectID,proto3,customtype=ObjectID" json:"ObjectID"`
+	CID                  CID      `protobuf:"bytes,2,opt,name=CID,proto3,customtype=CID" json:"CID"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *Address) Reset()      { *m = Address{} }
+func (*Address) ProtoMessage() {}
+func (*Address) Descriptor() ([]byte, []int) {
+	return fileDescriptor_063a64a96d952d31, []int{0}
+}
+func (m *Address) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *Address) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *Address) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Address.Merge(m, src)
+}
+func (m *Address) XXX_Size() int {
+	return m.Size()
+}
+func (m *Address) XXX_DiscardUnknown() {
+	xxx_messageInfo_Address.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Address proto.InternalMessageInfo
+
+func init() {
+	proto.RegisterType((*Address)(nil), "refs.Address")
+}
+
+func init() { proto.RegisterFile("refs/types.proto", fileDescriptor_063a64a96d952d31) }
+
+var fileDescriptor_063a64a96d952d31 = []byte{
+	// 199 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x28, 0x4a, 0x4d, 0x2b,
+	0xd6, 0x2f, 0xa9, 0x2c, 0x48, 0x2d, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x01, 0x89,
+	0x48, 0xe9, 0xa6, 0x67, 0x96, 0x64, 0x94, 0x26, 0xe9, 0x25, 0xe7, 0xe7, 0xea, 0xa7, 0xe7, 0xa7,
+	0xe7, 0xeb, 0x83, 0x25, 0x93, 0x4a, 0xd3, 0xc0, 0x3c, 0x30, 0x07, 0xcc, 0x82, 0x68, 0x52, 0x0a,
+	0xe3, 0x62, 0x77, 0x4c, 0x49, 0x29, 0x4a, 0x2d, 0x2e, 0x16, 0xd2, 0xe1, 0xe2, 0xf0, 0x4f, 0xca,
+	0x4a, 0x4d, 0x2e, 0xf1, 0x74, 0x91, 0x60, 0x54, 0x60, 0xd4, 0xe0, 0x71, 0x12, 0x38, 0x71, 0x4f,
+	0x9e, 0xe1, 0xd6, 0x3d, 0x79, 0xb8, 0x78, 0x10, 0x9c, 0x25, 0x24, 0xcb, 0xc5, 0xec, 0xec, 0xe9,
+	0x22, 0xc1, 0x04, 0x56, 0xc8, 0x0d, 0x55, 0x08, 0x12, 0x0a, 0x02, 0x11, 0x4e, 0xce, 0x37, 0x1e,
+	0xca, 0x31, 0x34, 0x3c, 0x92, 0x63, 0x38, 0xf1, 0x48, 0x8e, 0xf1, 0xc2, 0x23, 0x39, 0xc6, 0x1b,
+	0x8f, 0xe4, 0x18, 0x1f, 0x3c, 0x92, 0x63, 0x9c, 0xf1, 0x58, 0x8e, 0x21, 0x4a, 0x15, 0xc9, 0x91,
+	0x79, 0xc5, 0x05, 0xc9, 0xc9, 0xba, 0x29, 0xa9, 0x65, 0xfa, 0x79, 0xa9, 0xf9, 0x69, 0xc5, 0xba,
+	0x10, 0x27, 0x82, 0xfc, 0x92, 0xc4, 0x06, 0x66, 0x1b, 0x03, 0x02, 0x00, 0x00, 0xff, 0xff, 0xfd,
+	0xb6, 0x0b, 0x68, 0xec, 0x00, 0x00, 0x00,
+}
+
+func (m *Address) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *Address) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *Address) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	{
+		size := m.CID.Size()
+		i -= size
+		if _, err := m.CID.MarshalTo(dAtA[i:]); err != nil {
+			return 0, err
+		}
+		i = encodeVarintTypes(dAtA, i, uint64(size))
+	}
+	i--
+	dAtA[i] = 0x12
+	{
+		size := m.ObjectID.Size()
+		i -= size
+		if _, err := m.ObjectID.MarshalTo(dAtA[i:]); err != nil {
+			return 0, err
+		}
+		i = encodeVarintTypes(dAtA, i, uint64(size))
+	}
+	i--
+	dAtA[i] = 0xa
+	return len(dAtA) - i, nil
+}
+
+func encodeVarintTypes(dAtA []byte, offset int, v uint64) int {
+	offset -= sovTypes(v)
+	base := offset
+	for v >= 1<<7 {
+		dAtA[offset] = uint8(v&0x7f | 0x80)
+		v >>= 7
+		offset++
+	}
+	dAtA[offset] = uint8(v)
+	return base
+}
+func (m *Address) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = m.ObjectID.Size()
+	n += 1 + l + sovTypes(uint64(l))
+	l = m.CID.Size()
+	n += 1 + l + sovTypes(uint64(l))
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func sovTypes(x uint64) (n int) {
+	return (math_bits.Len64(x|1) + 6) / 7
+}
+func sozTypes(x uint64) (n int) {
+	return sovTypes(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+func (m *Address) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowTypes
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: Address: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: Address: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field ObjectID", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.ObjectID.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field CID", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.CID.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipTypes(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func skipTypes(dAtA []byte) (n int, err error) {
+	l := len(dAtA)
+	iNdEx := 0
+	depth := 0
+	for iNdEx < l {
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return 0, ErrIntOverflowTypes
+			}
+			if iNdEx >= l {
+				return 0, io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= (uint64(b) & 0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		wireType := int(wire & 0x7)
+		switch wireType {
+		case 0:
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return 0, ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return 0, io.ErrUnexpectedEOF
+				}
+				iNdEx++
+				if dAtA[iNdEx-1] < 0x80 {
+					break
+				}
+			}
+		case 1:
+			iNdEx += 8
+		case 2:
+			var length int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return 0, ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return 0, io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				length |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if length < 0 {
+				return 0, ErrInvalidLengthTypes
+			}
+			iNdEx += length
+		case 3:
+			depth++
+		case 4:
+			if depth == 0 {
+				return 0, ErrUnexpectedEndOfGroupTypes
+			}
+			depth--
+		case 5:
+			iNdEx += 4
+		default:
+			return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+		}
+		if iNdEx < 0 {
+			return 0, ErrInvalidLengthTypes
+		}
+		if depth == 0 {
+			return iNdEx, nil
+		}
+	}
+	return 0, io.ErrUnexpectedEOF
+}
+
+var (
+	ErrInvalidLengthTypes        = fmt.Errorf("proto: negative length found during unmarshaling")
+	ErrIntOverflowTypes          = fmt.Errorf("proto: integer overflow")
+	ErrUnexpectedEndOfGroupTypes = fmt.Errorf("proto: unexpected end of group")
+)
diff --git a/refs/types.proto b/refs/types.proto
new file mode 100644
index 00000000..e607f349
--- /dev/null
+++ b/refs/types.proto
@@ -0,0 +1,15 @@
+syntax = "proto3";
+package refs;
+option go_package = "github.com/nspcc-dev/neofs-proto/refs";
+
+import "github.com/gogo/protobuf/gogoproto/gogo.proto";
+
+option (gogoproto.stable_marshaler_all) = true;
+
+option (gogoproto.stringer_all) =  false;
+option (gogoproto.goproto_stringer_all) = false;
+
+message Address {
+    bytes ObjectID = 1[(gogoproto.customtype) = "ObjectID", (gogoproto.nullable) = false]; // UUID
+    bytes CID      = 2[(gogoproto.customtype) = "CID",      (gogoproto.nullable) = false]; // sha256
+}
diff --git a/refs/types_test.go b/refs/types_test.go
new file mode 100644
index 00000000..2fd3cedf
--- /dev/null
+++ b/refs/types_test.go
@@ -0,0 +1,112 @@
+package refs
+
+import (
+	"strings"
+	"testing"
+
+	"github.com/gogo/protobuf/proto"
+	"github.com/google/uuid"
+	"github.com/nspcc-dev/neofs-crypto/test"
+	"github.com/stretchr/testify/require"
+)
+
+func TestSGID(t *testing.T) {
+	t.Run("check that marshal/unmarshal works like expected", func(t *testing.T) {
+		var sgid1, sgid2 UUID
+
+		sgid1, err := NewSGID()
+		require.NoError(t, err)
+
+		data, err := proto.Marshal(&sgid1)
+		require.NoError(t, err)
+
+		require.NoError(t, sgid2.Unmarshal(data))
+		require.Equal(t, sgid1, sgid2)
+	})
+}
+
+func TestUUID(t *testing.T) {
+	t.Run("parse should work like expected", func(t *testing.T) {
+		var u UUID
+
+		id, err := uuid.NewRandom()
+		require.NoError(t, err)
+
+		require.NoError(t, u.Parse(id.String()))
+		require.Equal(t, id.String(), u.String())
+	})
+
+	t.Run("check that marshal/unmarshal works like expected", func(t *testing.T) {
+		var u1, u2 UUID
+
+		u1 = UUID{0x8f, 0xe4, 0xeb, 0xa0, 0xb8, 0xfb, 0x49, 0x3b, 0xbb, 0x1d, 0x1d, 0x13, 0x6e, 0x69, 0xfc, 0xf7}
+
+		data, err := proto.Marshal(&u1)
+		require.NoError(t, err)
+
+		require.NoError(t, u2.Unmarshal(data))
+		require.Equal(t, u1, u2)
+	})
+
+	t.Run("check that marshal/unmarshal works like expected even for msg id", func(t *testing.T) {
+		var u2 MessageID
+
+		u1, err := NewMessageID()
+		require.NoError(t, err)
+
+		data, err := proto.Marshal(&u1)
+		require.NoError(t, err)
+
+		require.NoError(t, u2.Unmarshal(data))
+		require.Equal(t, u1, u2)
+	})
+}
+
+func TestOwnerID(t *testing.T) {
+	t.Run("check that marshal/unmarshal works like expected", func(t *testing.T) {
+		var u1, u2 OwnerID
+
+		owner, err := NewOwnerID()
+		require.NoError(t, err)
+		require.True(t, owner.Empty())
+
+		key := test.DecodeKey(0)
+
+		u1, err = NewOwnerID(&key.PublicKey)
+		require.NoError(t, err)
+		data, err := proto.Marshal(&u1)
+		require.NoError(t, err)
+
+		require.NoError(t, u2.Unmarshal(data))
+		require.Equal(t, u1, u2)
+	})
+}
+
+func TestAddress(t *testing.T) {
+	cid := CIDForBytes([]byte("test"))
+
+	id, err := NewObjectID()
+	require.NoError(t, err)
+
+	expect := strings.Join([]string{
+		cid.String(),
+		id.String(),
+	}, joinSeparator)
+
+	require.NotPanics(t, func() {
+		actual := (Address{
+			ObjectID: id,
+			CID:      cid,
+		}).String()
+
+		require.Equal(t, expect, actual)
+	})
+
+	var temp Address
+	require.NoError(t, temp.Parse(expect))
+	require.Equal(t, expect, temp.String())
+
+	actual, err := ParseAddress(expect)
+	require.NoError(t, err)
+	require.Equal(t, expect, actual.String())
+}
diff --git a/refs/uuid.go b/refs/uuid.go
new file mode 100644
index 00000000..2ffc525c
--- /dev/null
+++ b/refs/uuid.go
@@ -0,0 +1,76 @@
+package refs
+
+import (
+	"bytes"
+	"encoding/hex"
+
+	"github.com/google/uuid"
+	"github.com/pkg/errors"
+)
+
+func encodeHex(dst []byte, uuid UUID) {
+	hex.Encode(dst, uuid[:4])
+	dst[8] = '-'
+	hex.Encode(dst[9:13], uuid[4:6])
+	dst[13] = '-'
+	hex.Encode(dst[14:18], uuid[6:8])
+	dst[18] = '-'
+	hex.Encode(dst[19:23], uuid[8:10])
+	dst[23] = '-'
+	hex.Encode(dst[24:], uuid[10:])
+}
+
+// Size returns size in bytes of UUID (UUIDSize).
+func (UUID) Size() int { return UUIDSize }
+
+// Empty checks that current UUID is empty value.
+func (u UUID) Empty() bool { return bytes.Equal(u.Bytes(), emptyUUID) }
+
+// Reset sets current UUID to empty value.
+func (u *UUID) Reset() { *u = [UUIDSize]byte{} }
+
+// ProtoMessage method to satisfy proto.Message.
+func (UUID) ProtoMessage() {}
+
+// Marshal returns UUID bytes representation.
+func (u UUID) Marshal() ([]byte, error) { return u.Bytes(), nil }
+
+// MarshalTo returns UUID bytes representation.
+func (u UUID) MarshalTo(data []byte) (int, error) { return copy(data, u[:]), nil }
+
+// Bytes returns UUID bytes representation.
+func (u UUID) Bytes() []byte {
+	buf := make([]byte, UUIDSize)
+	copy(buf, u[:])
+	return buf
+}
+
+// Equal checks that current UUID is equal to passed UUID.
+func (u UUID) Equal(u2 UUID) bool { return bytes.Equal(u.Bytes(), u2.Bytes()) }
+
+func (u UUID) String() string {
+	var buf [36]byte
+	encodeHex(buf[:], u)
+	return string(buf[:])
+}
+
+// Unmarshal tries to parse UUID bytes representation.
+func (u *UUID) Unmarshal(data []byte) error {
+	if ln := len(data); ln != UUIDSize {
+		return errors.Wrapf(ErrWrongDataSize, "expect=%d, actual=%d", UUIDSize, ln)
+	}
+
+	copy((*u)[:], data)
+	return nil
+}
+
+// Parse tries to parse UUID string representation.
+func (u *UUID) Parse(id string) error {
+	tmp, err := uuid.Parse(id)
+	if err != nil {
+		return errors.Wrapf(err, "could not parse `%s`", id)
+	}
+
+	copy((*u)[:], tmp[:])
+	return nil
+}
diff --git a/service/epoch.go b/service/epoch.go
new file mode 100644
index 00000000..2fd43817
--- /dev/null
+++ b/service/epoch.go
@@ -0,0 +1,7 @@
+package service
+
+// EpochRequest interface gives possibility to get or set epoch in RPC Requests.
+type EpochRequest interface {
+	GetEpoch() uint64
+	SetEpoch(v uint64)
+}
diff --git a/service/role.go b/service/role.go
new file mode 100644
index 00000000..53bcdf55
--- /dev/null
+++ b/service/role.go
@@ -0,0 +1,24 @@
+package service
+
+// NodeRole to identify in Bootstrap service.
+type NodeRole int32
+
+const (
+	_ NodeRole = iota
+	// InnerRingNode that work like IR node.
+	InnerRingNode
+	// StorageNode that work like a storage node.
+	StorageNode
+)
+
+// String is method, that represent NodeRole as string.
+func (nt NodeRole) String() string {
+	switch nt {
+	case InnerRingNode:
+		return "InnerRingNode"
+	case StorageNode:
+		return "StorageNode"
+	default:
+		return "Unknown"
+	}
+}
diff --git a/service/role_test.go b/service/role_test.go
new file mode 100644
index 00000000..a1f1cc06
--- /dev/null
+++ b/service/role_test.go
@@ -0,0 +1,22 @@
+package service
+
+import (
+	"github.com/stretchr/testify/require"
+	"testing"
+)
+
+func TestNodeRole_String(t *testing.T) {
+	tests := []struct {
+		nt   NodeRole
+		want string
+	}{
+		{want: "Unknown"},
+		{nt: StorageNode, want: "StorageNode"},
+		{nt: InnerRingNode, want: "InnerRingNode"},
+	}
+	for _, tt := range tests {
+		t.Run(tt.want, func(t *testing.T) {
+			require.Equal(t, tt.want, tt.nt.String())
+		})
+	}
+}
diff --git a/service/sign.go b/service/sign.go
new file mode 100644
index 00000000..d8db94e8
--- /dev/null
+++ b/service/sign.go
@@ -0,0 +1,47 @@
+package service
+
+import (
+	"crypto/ecdsa"
+
+	crypto "github.com/nspcc-dev/neofs-crypto"
+	"github.com/nspcc-dev/neofs-proto/internal"
+	"github.com/pkg/errors"
+)
+
+// ErrWrongSignature should be raised when wrong signature is passed into VerifyRequest.
+const ErrWrongSignature = internal.Error("wrong signature")
+
+// SignedRequest interface allows sign and verify requests.
+type SignedRequest interface {
+	PrepareData() ([]byte, error)
+	GetSignature() []byte
+	SetSignature([]byte)
+}
+
+// SignRequest with passed private key.
+func SignRequest(r SignedRequest, key *ecdsa.PrivateKey) error {
+	var signature []byte
+	if data, err := r.PrepareData(); err != nil {
+		return err
+	} else if signature, err = crypto.Sign(key, data); err != nil {
+		return errors.Wrap(err, "could not sign data")
+	}
+
+	r.SetSignature(signature)
+
+	return nil
+}
+
+// VerifyRequest by passed public keys.
+func VerifyRequest(r SignedRequest, keys ...*ecdsa.PublicKey) bool {
+	data, err := r.PrepareData()
+	if err != nil {
+		return false
+	}
+	for i := range keys {
+		if err := crypto.Verify(keys[i], data, r.GetSignature()); err == nil {
+			return true
+		}
+	}
+	return false
+}
diff --git a/service/ttl.go b/service/ttl.go
new file mode 100644
index 00000000..8ddf1dec
--- /dev/null
+++ b/service/ttl.go
@@ -0,0 +1,45 @@
+package service
+
+import (
+	"github.com/nspcc-dev/neofs-proto/internal"
+	"google.golang.org/grpc/codes"
+	"google.golang.org/grpc/status"
+)
+
+// TTLRequest to verify and update ttl requests.
+type TTLRequest interface {
+	GetTTL() uint32
+	SetTTL(uint32)
+}
+
+const (
+	// ZeroTTL is empty ttl, should produce ErrZeroTTL.
+	ZeroTTL = iota
+
+	// NonForwardingTTL is a ttl that allows direct connections only.
+	NonForwardingTTL
+
+	// SingleForwardingTTL is a ttl that allows connections through another node.
+	SingleForwardingTTL
+
+	// ErrZeroTTL is raised when zero ttl is passed.
+	ErrZeroTTL = internal.Error("zero ttl")
+
+	// ErrIncorrectTTL is raised when NonForwardingTTL is passed and NodeRole != InnerRingNode.
+	ErrIncorrectTTL = internal.Error("incorrect ttl")
+)
+
+// CheckTTLRequest validates and update ttl requests.
+func CheckTTLRequest(req TTLRequest, role NodeRole) error {
+	var ttl = req.GetTTL()
+
+	if ttl == ZeroTTL {
+		return status.New(codes.InvalidArgument, ErrZeroTTL.Error()).Err()
+	} else if ttl == NonForwardingTTL && role != InnerRingNode {
+		return status.New(codes.InvalidArgument, ErrIncorrectTTL.Error()).Err()
+	}
+
+	req.SetTTL(ttl - 1)
+
+	return nil
+}
diff --git a/service/ttl_test.go b/service/ttl_test.go
new file mode 100644
index 00000000..13491984
--- /dev/null
+++ b/service/ttl_test.go
@@ -0,0 +1,72 @@
+package service
+
+import (
+	"github.com/stretchr/testify/require"
+	"google.golang.org/grpc/codes"
+	"google.golang.org/grpc/status"
+	"testing"
+)
+
+type mockedRequest struct {
+	msg  string
+	ttl  uint32
+	name string
+	role NodeRole
+	code codes.Code
+}
+
+func (m *mockedRequest) SetTTL(v uint32) { m.ttl = v }
+func (m mockedRequest) GetTTL() uint32   { return m.ttl }
+
+func TestCheckTTLRequest(t *testing.T) {
+	tests := []mockedRequest{
+		{
+			ttl:  NonForwardingTTL,
+			role: InnerRingNode,
+			name: "direct to ir node",
+		},
+		{
+			ttl:  NonForwardingTTL,
+			role: StorageNode,
+			code: codes.InvalidArgument,
+			msg:  ErrIncorrectTTL.Error(),
+			name: "direct to storage node",
+		},
+		{
+			ttl:  ZeroTTL,
+			role: StorageNode,
+			msg:  ErrZeroTTL.Error(),
+			code: codes.InvalidArgument,
+			name: "zero ttl",
+		},
+		{
+			ttl:  SingleForwardingTTL,
+			role: InnerRingNode,
+			name: "default to ir node",
+		},
+		{
+			ttl:  SingleForwardingTTL,
+			role: StorageNode,
+			name: "default to storage node",
+		},
+	}
+
+	for i := range tests {
+		tt := tests[i]
+		t.Run(tt.name, func(t *testing.T) {
+			before := tt.ttl
+			err := CheckTTLRequest(&tt, tt.role)
+			if tt.msg != "" {
+				require.Errorf(t, err, tt.msg)
+
+				state, ok := status.FromError(err)
+				require.True(t, ok)
+				require.Equal(t, state.Code(), tt.code)
+				require.Equal(t, state.Message(), tt.msg)
+			} else {
+				require.NoError(t, err)
+				require.NotEqualf(t, before, tt.ttl, "ttl should be changed: %d vs %d", before, tt.ttl)
+			}
+		})
+	}
+}
diff --git a/session/service.go b/session/service.go
new file mode 100644
index 00000000..1695c048
--- /dev/null
+++ b/session/service.go
@@ -0,0 +1,57 @@
+package session
+
+import (
+	"context"
+	"crypto/ecdsa"
+
+	crypto "github.com/nspcc-dev/neofs-crypto"
+	"github.com/nspcc-dev/neofs-proto/refs"
+)
+
+type (
+	// KeyStore is an interface that describes storage,
+	// that allows to fetch public keys by OwnerID.
+	KeyStore interface {
+		Get(ctx context.Context, id refs.OwnerID) ([]*ecdsa.PublicKey, error)
+	}
+
+	// TokenStore is a PToken storage manipulation interface.
+	TokenStore interface {
+		// New returns new token with specified parameters.
+		New(p TokenParams) *PToken
+
+		// Fetch tries to fetch a token with specified id.
+		Fetch(id TokenID) *PToken
+
+		// Remove removes token with id from store.
+		Remove(id TokenID)
+	}
+
+	// TokenParams contains params to create new PToken.
+	TokenParams struct {
+		FirstEpoch uint64
+		LastEpoch  uint64
+		ObjectID   []ObjectID
+		OwnerID    OwnerID
+	}
+)
+
+// NewInitRequest returns new initialization CreateRequest from passed Token.
+func NewInitRequest(t *Token) *CreateRequest {
+	return &CreateRequest{Message: &CreateRequest_Init{Init: t}}
+}
+
+// NewSignedRequest returns new signed CreateRequest from passed Token.
+func NewSignedRequest(t *Token) *CreateRequest {
+	return &CreateRequest{Message: &CreateRequest_Signed{Signed: t}}
+}
+
+// Sign signs contents of the header with the private key.
+func (m *VerificationHeader) Sign(key *ecdsa.PrivateKey) error {
+	s, err := crypto.Sign(key, m.PublicKey)
+	if err != nil {
+		return err
+	}
+	m.KeySignature = s
+	return nil
+}
diff --git a/session/service.pb.go b/session/service.pb.go
new file mode 100644
index 00000000..da85708c
--- /dev/null
+++ b/session/service.pb.go
@@ -0,0 +1,922 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: session/service.proto
+
+package session
+
+import (
+	context "context"
+	fmt "fmt"
+	_ "github.com/gogo/protobuf/gogoproto"
+	proto "github.com/golang/protobuf/proto"
+	grpc "google.golang.org/grpc"
+	codes "google.golang.org/grpc/codes"
+	status "google.golang.org/grpc/status"
+	io "io"
+	math "math"
+	math_bits "math/bits"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
+
+type CreateRequest struct {
+	// Types that are valid to be assigned to Message:
+	//	*CreateRequest_Init
+	//	*CreateRequest_Signed
+	Message              isCreateRequest_Message `protobuf_oneof:"Message"`
+	XXX_NoUnkeyedLiteral struct{}                `json:"-"`
+	XXX_unrecognized     []byte                  `json:"-"`
+	XXX_sizecache        int32                   `json:"-"`
+}
+
+func (m *CreateRequest) Reset()         { *m = CreateRequest{} }
+func (m *CreateRequest) String() string { return proto.CompactTextString(m) }
+func (*CreateRequest) ProtoMessage()    {}
+func (*CreateRequest) Descriptor() ([]byte, []int) {
+	return fileDescriptor_b329bee0fd1148e0, []int{0}
+}
+func (m *CreateRequest) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *CreateRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *CreateRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_CreateRequest.Merge(m, src)
+}
+func (m *CreateRequest) XXX_Size() int {
+	return m.Size()
+}
+func (m *CreateRequest) XXX_DiscardUnknown() {
+	xxx_messageInfo_CreateRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_CreateRequest proto.InternalMessageInfo
+
+type isCreateRequest_Message interface {
+	isCreateRequest_Message()
+	MarshalTo([]byte) (int, error)
+	Size() int
+}
+
+type CreateRequest_Init struct {
+	Init *Token `protobuf:"bytes,1,opt,name=Init,proto3,oneof" json:"Init,omitempty"`
+}
+type CreateRequest_Signed struct {
+	Signed *Token `protobuf:"bytes,2,opt,name=Signed,proto3,oneof" json:"Signed,omitempty"`
+}
+
+func (*CreateRequest_Init) isCreateRequest_Message()   {}
+func (*CreateRequest_Signed) isCreateRequest_Message() {}
+
+func (m *CreateRequest) GetMessage() isCreateRequest_Message {
+	if m != nil {
+		return m.Message
+	}
+	return nil
+}
+
+func (m *CreateRequest) GetInit() *Token {
+	if x, ok := m.GetMessage().(*CreateRequest_Init); ok {
+		return x.Init
+	}
+	return nil
+}
+
+func (m *CreateRequest) GetSigned() *Token {
+	if x, ok := m.GetMessage().(*CreateRequest_Signed); ok {
+		return x.Signed
+	}
+	return nil
+}
+
+// XXX_OneofWrappers is for the internal use of the proto package.
+func (*CreateRequest) XXX_OneofWrappers() []interface{} {
+	return []interface{}{
+		(*CreateRequest_Init)(nil),
+		(*CreateRequest_Signed)(nil),
+	}
+}
+
+type CreateResponse struct {
+	// Types that are valid to be assigned to Message:
+	//	*CreateResponse_Unsigned
+	//	*CreateResponse_Result
+	Message              isCreateResponse_Message `protobuf_oneof:"Message"`
+	XXX_NoUnkeyedLiteral struct{}                 `json:"-"`
+	XXX_unrecognized     []byte                   `json:"-"`
+	XXX_sizecache        int32                    `json:"-"`
+}
+
+func (m *CreateResponse) Reset()         { *m = CreateResponse{} }
+func (m *CreateResponse) String() string { return proto.CompactTextString(m) }
+func (*CreateResponse) ProtoMessage()    {}
+func (*CreateResponse) Descriptor() ([]byte, []int) {
+	return fileDescriptor_b329bee0fd1148e0, []int{1}
+}
+func (m *CreateResponse) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *CreateResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *CreateResponse) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_CreateResponse.Merge(m, src)
+}
+func (m *CreateResponse) XXX_Size() int {
+	return m.Size()
+}
+func (m *CreateResponse) XXX_DiscardUnknown() {
+	xxx_messageInfo_CreateResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_CreateResponse proto.InternalMessageInfo
+
+type isCreateResponse_Message interface {
+	isCreateResponse_Message()
+	MarshalTo([]byte) (int, error)
+	Size() int
+}
+
+type CreateResponse_Unsigned struct {
+	Unsigned *Token `protobuf:"bytes,1,opt,name=Unsigned,proto3,oneof" json:"Unsigned,omitempty"`
+}
+type CreateResponse_Result struct {
+	Result *Token `protobuf:"bytes,2,opt,name=Result,proto3,oneof" json:"Result,omitempty"`
+}
+
+func (*CreateResponse_Unsigned) isCreateResponse_Message() {}
+func (*CreateResponse_Result) isCreateResponse_Message()   {}
+
+func (m *CreateResponse) GetMessage() isCreateResponse_Message {
+	if m != nil {
+		return m.Message
+	}
+	return nil
+}
+
+func (m *CreateResponse) GetUnsigned() *Token {
+	if x, ok := m.GetMessage().(*CreateResponse_Unsigned); ok {
+		return x.Unsigned
+	}
+	return nil
+}
+
+func (m *CreateResponse) GetResult() *Token {
+	if x, ok := m.GetMessage().(*CreateResponse_Result); ok {
+		return x.Result
+	}
+	return nil
+}
+
+// XXX_OneofWrappers is for the internal use of the proto package.
+func (*CreateResponse) XXX_OneofWrappers() []interface{} {
+	return []interface{}{
+		(*CreateResponse_Unsigned)(nil),
+		(*CreateResponse_Result)(nil),
+	}
+}
+
+func init() {
+	proto.RegisterType((*CreateRequest)(nil), "session.CreateRequest")
+	proto.RegisterType((*CreateResponse)(nil), "session.CreateResponse")
+}
+
+func init() { proto.RegisterFile("session/service.proto", fileDescriptor_b329bee0fd1148e0) }
+
+var fileDescriptor_b329bee0fd1148e0 = []byte{
+	// 284 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x90, 0xbd, 0x4e, 0xc3, 0x30,
+	0x10, 0xc7, 0x6b, 0x84, 0x12, 0x30, 0xa2, 0x83, 0x11, 0x50, 0x65, 0xb0, 0x50, 0xc5, 0x90, 0x81,
+	0x24, 0xa8, 0xcc, 0x30, 0x94, 0xa5, 0x0c, 0x2c, 0x29, 0x2c, 0x6c, 0x4d, 0x7a, 0x35, 0xe6, 0xc3,
+	0x0e, 0x39, 0xa7, 0x12, 0x6f, 0xc2, 0x23, 0x31, 0x32, 0x32, 0xa2, 0xf0, 0x22, 0x08, 0x3b, 0xad,
+	0x82, 0x50, 0x36, 0xff, 0x3f, 0x7c, 0x3f, 0xfb, 0xe8, 0x3e, 0x02, 0xa2, 0xd4, 0x2a, 0x41, 0x28,
+	0x97, 0x32, 0x87, 0xb8, 0x28, 0xb5, 0xd1, 0xcc, 0x6f, 0xec, 0x60, 0x6f, 0x95, 0x9b, 0xd7, 0x02,
+	0xd0, 0xa5, 0x41, 0x24, 0xa4, 0xb9, 0xaf, 0xb2, 0x38, 0xd7, 0xcf, 0x89, 0xd0, 0x42, 0x27, 0xd6,
+	0xce, 0xaa, 0x85, 0x55, 0x56, 0xd8, 0x93, 0xab, 0x0f, 0x1f, 0xe8, 0xee, 0x65, 0x09, 0x33, 0x03,
+	0x29, 0xbc, 0x54, 0x80, 0x86, 0x1d, 0xd3, 0xcd, 0x2b, 0x25, 0xcd, 0x80, 0x1c, 0x91, 0x70, 0x67,
+	0xd4, 0x8f, 0x1b, 0x46, 0x7c, 0xa3, 0x1f, 0x41, 0x4d, 0x7a, 0xa9, 0x4d, 0x59, 0x48, 0xbd, 0xa9,
+	0x14, 0x0a, 0xe6, 0x83, 0x8d, 0x8e, 0x5e, 0x93, 0x8f, 0xb7, 0xa9, 0x7f, 0x0d, 0x88, 0x33, 0x01,
+	0x43, 0xa4, 0xfd, 0x15, 0x0b, 0x0b, 0xad, 0x10, 0xd8, 0x09, 0xdd, 0xba, 0x55, 0xe8, 0x06, 0x75,
+	0x01, 0xd7, 0x8d, 0x5f, 0x68, 0x0a, 0x58, 0x3d, 0x99, 0x6e, 0xa8, 0xcb, 0x5b, 0xd0, 0xd1, 0x84,
+	0xfa, 0x53, 0xd7, 0x62, 0xe7, 0xd4, 0x73, 0x7c, 0x76, 0xb0, 0xbe, 0xf9, 0xe7, 0xf3, 0xc1, 0xe1,
+	0x3f, 0xdf, 0x3d, 0x34, 0x24, 0xa7, 0x64, 0x7c, 0xf1, 0x5e, 0x73, 0xf2, 0x51, 0x73, 0xf2, 0x59,
+	0x73, 0xf2, 0x55, 0x73, 0xf2, 0xf6, 0xcd, 0x7b, 0x77, 0x61, 0x6b, 0xdf, 0x0a, 0x8b, 0x3c, 0x8f,
+	0xe6, 0xb0, 0x4c, 0x14, 0xe8, 0x05, 0x46, 0x6e, 0xdb, 0xcd, 0xc8, 0xcc, 0xb3, 0xf2, 0xec, 0x27,
+	0x00, 0x00, 0xff, 0xff, 0x74, 0x3d, 0x2a, 0x06, 0xd7, 0x01, 0x00, 0x00,
+}
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ context.Context
+var _ grpc.ClientConn
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the grpc package it is being compiled against.
+const _ = grpc.SupportPackageIsVersion4
+
+// SessionClient is the client API for Session service.
+//
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
+type SessionClient interface {
+	Create(ctx context.Context, opts ...grpc.CallOption) (Session_CreateClient, error)
+}
+
+type sessionClient struct {
+	cc *grpc.ClientConn
+}
+
+func NewSessionClient(cc *grpc.ClientConn) SessionClient {
+	return &sessionClient{cc}
+}
+
+func (c *sessionClient) Create(ctx context.Context, opts ...grpc.CallOption) (Session_CreateClient, error) {
+	stream, err := c.cc.NewStream(ctx, &_Session_serviceDesc.Streams[0], "/session.Session/Create", opts...)
+	if err != nil {
+		return nil, err
+	}
+	x := &sessionCreateClient{stream}
+	return x, nil
+}
+
+type Session_CreateClient interface {
+	Send(*CreateRequest) error
+	Recv() (*CreateResponse, error)
+	grpc.ClientStream
+}
+
+type sessionCreateClient struct {
+	grpc.ClientStream
+}
+
+func (x *sessionCreateClient) Send(m *CreateRequest) error {
+	return x.ClientStream.SendMsg(m)
+}
+
+func (x *sessionCreateClient) Recv() (*CreateResponse, error) {
+	m := new(CreateResponse)
+	if err := x.ClientStream.RecvMsg(m); err != nil {
+		return nil, err
+	}
+	return m, nil
+}
+
+// SessionServer is the server API for Session service.
+type SessionServer interface {
+	Create(Session_CreateServer) error
+}
+
+// UnimplementedSessionServer can be embedded to have forward compatible implementations.
+type UnimplementedSessionServer struct {
+}
+
+func (*UnimplementedSessionServer) Create(srv Session_CreateServer) error {
+	return status.Errorf(codes.Unimplemented, "method Create not implemented")
+}
+
+func RegisterSessionServer(s *grpc.Server, srv SessionServer) {
+	s.RegisterService(&_Session_serviceDesc, srv)
+}
+
+func _Session_Create_Handler(srv interface{}, stream grpc.ServerStream) error {
+	return srv.(SessionServer).Create(&sessionCreateServer{stream})
+}
+
+type Session_CreateServer interface {
+	Send(*CreateResponse) error
+	Recv() (*CreateRequest, error)
+	grpc.ServerStream
+}
+
+type sessionCreateServer struct {
+	grpc.ServerStream
+}
+
+func (x *sessionCreateServer) Send(m *CreateResponse) error {
+	return x.ServerStream.SendMsg(m)
+}
+
+func (x *sessionCreateServer) Recv() (*CreateRequest, error) {
+	m := new(CreateRequest)
+	if err := x.ServerStream.RecvMsg(m); err != nil {
+		return nil, err
+	}
+	return m, nil
+}
+
+var _Session_serviceDesc = grpc.ServiceDesc{
+	ServiceName: "session.Session",
+	HandlerType: (*SessionServer)(nil),
+	Methods:     []grpc.MethodDesc{},
+	Streams: []grpc.StreamDesc{
+		{
+			StreamName:    "Create",
+			Handler:       _Session_Create_Handler,
+			ServerStreams: true,
+			ClientStreams: true,
+		},
+	},
+	Metadata: "session/service.proto",
+}
+
+func (m *CreateRequest) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *CreateRequest) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *CreateRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if m.Message != nil {
+		{
+			size := m.Message.Size()
+			i -= size
+			if _, err := m.Message.MarshalTo(dAtA[i:]); err != nil {
+				return 0, err
+			}
+		}
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *CreateRequest_Init) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *CreateRequest_Init) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	if m.Init != nil {
+		{
+			size, err := m.Init.MarshalToSizedBuffer(dAtA[:i])
+			if err != nil {
+				return 0, err
+			}
+			i -= size
+			i = encodeVarintService(dAtA, i, uint64(size))
+		}
+		i--
+		dAtA[i] = 0xa
+	}
+	return len(dAtA) - i, nil
+}
+func (m *CreateRequest_Signed) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *CreateRequest_Signed) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	if m.Signed != nil {
+		{
+			size, err := m.Signed.MarshalToSizedBuffer(dAtA[:i])
+			if err != nil {
+				return 0, err
+			}
+			i -= size
+			i = encodeVarintService(dAtA, i, uint64(size))
+		}
+		i--
+		dAtA[i] = 0x12
+	}
+	return len(dAtA) - i, nil
+}
+func (m *CreateResponse) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *CreateResponse) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *CreateResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if m.Message != nil {
+		{
+			size := m.Message.Size()
+			i -= size
+			if _, err := m.Message.MarshalTo(dAtA[i:]); err != nil {
+				return 0, err
+			}
+		}
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *CreateResponse_Unsigned) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *CreateResponse_Unsigned) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	if m.Unsigned != nil {
+		{
+			size, err := m.Unsigned.MarshalToSizedBuffer(dAtA[:i])
+			if err != nil {
+				return 0, err
+			}
+			i -= size
+			i = encodeVarintService(dAtA, i, uint64(size))
+		}
+		i--
+		dAtA[i] = 0xa
+	}
+	return len(dAtA) - i, nil
+}
+func (m *CreateResponse_Result) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *CreateResponse_Result) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	if m.Result != nil {
+		{
+			size, err := m.Result.MarshalToSizedBuffer(dAtA[:i])
+			if err != nil {
+				return 0, err
+			}
+			i -= size
+			i = encodeVarintService(dAtA, i, uint64(size))
+		}
+		i--
+		dAtA[i] = 0x12
+	}
+	return len(dAtA) - i, nil
+}
+func encodeVarintService(dAtA []byte, offset int, v uint64) int {
+	offset -= sovService(v)
+	base := offset
+	for v >= 1<<7 {
+		dAtA[offset] = uint8(v&0x7f | 0x80)
+		v >>= 7
+		offset++
+	}
+	dAtA[offset] = uint8(v)
+	return base
+}
+func (m *CreateRequest) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.Message != nil {
+		n += m.Message.Size()
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *CreateRequest_Init) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.Init != nil {
+		l = m.Init.Size()
+		n += 1 + l + sovService(uint64(l))
+	}
+	return n
+}
+func (m *CreateRequest_Signed) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.Signed != nil {
+		l = m.Signed.Size()
+		n += 1 + l + sovService(uint64(l))
+	}
+	return n
+}
+func (m *CreateResponse) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.Message != nil {
+		n += m.Message.Size()
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *CreateResponse_Unsigned) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.Unsigned != nil {
+		l = m.Unsigned.Size()
+		n += 1 + l + sovService(uint64(l))
+	}
+	return n
+}
+func (m *CreateResponse_Result) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.Result != nil {
+		l = m.Result.Size()
+		n += 1 + l + sovService(uint64(l))
+	}
+	return n
+}
+
+func sovService(x uint64) (n int) {
+	return (math_bits.Len64(x|1) + 6) / 7
+}
+func sozService(x uint64) (n int) {
+	return sovService(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+func (m *CreateRequest) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowService
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: CreateRequest: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: CreateRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Init", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthService
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthService
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			v := &Token{}
+			if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			m.Message = &CreateRequest_Init{v}
+			iNdEx = postIndex
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Signed", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthService
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthService
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			v := &Token{}
+			if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			m.Message = &CreateRequest_Signed{v}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipService(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *CreateResponse) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowService
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: CreateResponse: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: CreateResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Unsigned", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthService
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthService
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			v := &Token{}
+			if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			m.Message = &CreateResponse_Unsigned{v}
+			iNdEx = postIndex
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Result", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthService
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthService
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			v := &Token{}
+			if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			m.Message = &CreateResponse_Result{v}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipService(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func skipService(dAtA []byte) (n int, err error) {
+	l := len(dAtA)
+	iNdEx := 0
+	depth := 0
+	for iNdEx < l {
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return 0, ErrIntOverflowService
+			}
+			if iNdEx >= l {
+				return 0, io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= (uint64(b) & 0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		wireType := int(wire & 0x7)
+		switch wireType {
+		case 0:
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return 0, ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return 0, io.ErrUnexpectedEOF
+				}
+				iNdEx++
+				if dAtA[iNdEx-1] < 0x80 {
+					break
+				}
+			}
+		case 1:
+			iNdEx += 8
+		case 2:
+			var length int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return 0, ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return 0, io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				length |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if length < 0 {
+				return 0, ErrInvalidLengthService
+			}
+			iNdEx += length
+		case 3:
+			depth++
+		case 4:
+			if depth == 0 {
+				return 0, ErrUnexpectedEndOfGroupService
+			}
+			depth--
+		case 5:
+			iNdEx += 4
+		default:
+			return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+		}
+		if iNdEx < 0 {
+			return 0, ErrInvalidLengthService
+		}
+		if depth == 0 {
+			return iNdEx, nil
+		}
+	}
+	return 0, io.ErrUnexpectedEOF
+}
+
+var (
+	ErrInvalidLengthService        = fmt.Errorf("proto: negative length found during unmarshaling")
+	ErrIntOverflowService          = fmt.Errorf("proto: integer overflow")
+	ErrUnexpectedEndOfGroupService = fmt.Errorf("proto: unexpected end of group")
+)
diff --git a/session/service.proto b/session/service.proto
new file mode 100644
index 00000000..ee56a220
--- /dev/null
+++ b/session/service.proto
@@ -0,0 +1,27 @@
+syntax = "proto3";
+package session;
+option go_package = "github.com/nspcc-dev/neofs-proto/session";
+
+import "session/types.proto";
+import "github.com/gogo/protobuf/gogoproto/gogo.proto";
+
+option (gogoproto.stable_marshaler_all) = true;
+
+service Session {
+    rpc Create (stream CreateRequest) returns (stream CreateResponse);
+}
+
+
+message CreateRequest {
+    oneof Message {
+        session.Token Init = 1;
+        session.Token Signed = 2;
+    }
+}
+
+message CreateResponse {
+    oneof Message {
+        session.Token Unsigned = 1;
+        session.Token Result = 2;
+    }
+}
diff --git a/session/store.go b/session/store.go
new file mode 100644
index 00000000..f12943fe
--- /dev/null
+++ b/session/store.go
@@ -0,0 +1,81 @@
+package session
+
+import (
+	"crypto/ecdsa"
+	"crypto/elliptic"
+	"crypto/rand"
+	"sync"
+
+	crypto "github.com/nspcc-dev/neofs-crypto"
+	"github.com/nspcc-dev/neofs-proto/refs"
+)
+
+type simpleStore struct {
+	*sync.RWMutex
+
+	tokens map[TokenID]*PToken
+}
+
+// TODO get curve from neofs-crypto
+func defaultCurve() elliptic.Curve {
+	return elliptic.P256()
+}
+
+// NewSimpleStore creates simple token storage
+func NewSimpleStore() TokenStore {
+	return &simpleStore{
+		RWMutex: new(sync.RWMutex),
+		tokens:  make(map[TokenID]*PToken),
+	}
+}
+
+// New returns new token with specified parameters.
+func (s *simpleStore) New(p TokenParams) *PToken {
+	tid, err := refs.NewUUID()
+	if err != nil {
+		return nil
+	}
+
+	key, err := ecdsa.GenerateKey(defaultCurve(), rand.Reader)
+	if err != nil {
+		return nil
+	}
+
+	if p.FirstEpoch > p.LastEpoch || p.OwnerID.Empty() {
+		return nil
+	}
+
+	t := &PToken{
+		mtx: new(sync.Mutex),
+		Token: Token{
+			ID:         tid,
+			Header:     VerificationHeader{PublicKey: crypto.MarshalPublicKey(&key.PublicKey)},
+			FirstEpoch: p.FirstEpoch,
+			LastEpoch:  p.LastEpoch,
+			ObjectID:   p.ObjectID,
+			OwnerID:    p.OwnerID,
+		},
+		PrivateKey: key,
+	}
+
+	s.Lock()
+	s.tokens[t.ID] = t
+	s.Unlock()
+
+	return t
+}
+
+// Fetch tries to fetch a token with specified id.
+func (s *simpleStore) Fetch(id TokenID) *PToken {
+	s.RLock()
+	defer s.RUnlock()
+
+	return s.tokens[id]
+}
+
+// Remove removes token with id from store.
+func (s *simpleStore) Remove(id TokenID) {
+	s.Lock()
+	delete(s.tokens, id)
+	s.Unlock()
+}
diff --git a/session/store_test.go b/session/store_test.go
new file mode 100644
index 00000000..1a9e9771
--- /dev/null
+++ b/session/store_test.go
@@ -0,0 +1,84 @@
+package session
+
+import (
+	"crypto/ecdsa"
+	"crypto/rand"
+	"testing"
+
+	crypto "github.com/nspcc-dev/neofs-crypto"
+	"github.com/nspcc-dev/neofs-proto/refs"
+	"github.com/stretchr/testify/require"
+)
+
+type testClient struct {
+	*ecdsa.PrivateKey
+	OwnerID OwnerID
+}
+
+func (c *testClient) Sign(data []byte) ([]byte, error) {
+	return crypto.Sign(c.PrivateKey, data)
+}
+
+func newTestClient(t *testing.T) *testClient {
+	key, err := ecdsa.GenerateKey(defaultCurve(), rand.Reader)
+	require.NoError(t, err)
+
+	owner, err := refs.NewOwnerID(&key.PublicKey)
+	require.NoError(t, err)
+
+	return &testClient{PrivateKey: key, OwnerID: owner}
+}
+
+func signToken(t *testing.T, token *PToken, c *testClient) {
+	require.NotNil(t, token)
+
+	signH, err := c.Sign(token.Header.PublicKey)
+	require.NoError(t, err)
+	require.NotNil(t, signH)
+
+	// data is not yet signed
+	require.False(t, token.Verify(&c.PublicKey))
+
+	signT, err := c.Sign(token.verificationData())
+	require.NoError(t, err)
+	require.NotNil(t, signT)
+
+	token.AddSignatures(signH, signT)
+	require.True(t, token.Verify(&c.PublicKey))
+}
+
+func TestTokenStore(t *testing.T) {
+	s := NewSimpleStore()
+
+	oid, err := refs.NewObjectID()
+	require.NoError(t, err)
+
+	c := newTestClient(t)
+	require.NotNil(t, c)
+
+	// create new token
+	token := s.New(TokenParams{ObjectID: []ObjectID{oid}, OwnerID: c.OwnerID})
+	signToken(t, token, c)
+
+	// check that it can be fetched
+	t1 := s.Fetch(token.ID)
+	require.NotNil(t, t1)
+	require.Equal(t, token, t1)
+
+	// create and sign another token by the same client
+	t1 = s.New(TokenParams{ObjectID: []ObjectID{oid}, OwnerID: c.OwnerID})
+	signToken(t, t1, c)
+
+	data := []byte{1, 2, 3}
+	sign, err := t1.SignData(data)
+	require.NoError(t, err)
+	require.Error(t, token.Header.VerifyData(data, sign))
+
+	sign, err = token.SignData(data)
+	require.NoError(t, err)
+	require.NoError(t, token.Header.VerifyData(data, sign))
+
+	s.Remove(token.ID)
+	require.Nil(t, s.Fetch(token.ID))
+	require.NotNil(t, s.Fetch(t1.ID))
+}
diff --git a/session/types.go b/session/types.go
new file mode 100644
index 00000000..ceb2944a
--- /dev/null
+++ b/session/types.go
@@ -0,0 +1,159 @@
+package session
+
+import (
+	"crypto/ecdsa"
+	"encoding/binary"
+	"sync"
+
+	crypto "github.com/nspcc-dev/neofs-crypto"
+	"github.com/nspcc-dev/neofs-proto/internal"
+	"github.com/nspcc-dev/neofs-proto/refs"
+	"github.com/pkg/errors"
+)
+
+type (
+	// ObjectID type alias.
+	ObjectID = refs.ObjectID
+	// OwnerID type alias.
+	OwnerID = refs.OwnerID
+	// TokenID type alias.
+	TokenID = refs.UUID
+
+	// PToken is a wrapper around Token that allows to sign data
+	// and to do thread-safe manipulations.
+	PToken struct {
+		Token
+
+		mtx        *sync.Mutex
+		PrivateKey *ecdsa.PrivateKey
+	}
+)
+
+const (
+	// ErrWrongFirstEpoch is raised when passed Token contains wrong first epoch.
+	// First epoch is an epoch since token is valid
+	ErrWrongFirstEpoch = internal.Error("wrong first epoch")
+
+	// ErrWrongLastEpoch is raised when passed Token contains wrong last epoch.
+	// Last epoch is an epoch until token is valid
+	ErrWrongLastEpoch = internal.Error("wrong last epoch")
+
+	// ErrWrongOwner is raised when passed Token contains wrong OwnerID.
+	ErrWrongOwner = internal.Error("wrong owner")
+
+	// ErrEmptyPublicKey is raised when passed Token contains wrong public key.
+	ErrEmptyPublicKey = internal.Error("empty public key")
+
+	// ErrWrongObjectsCount is raised when passed Token contains wrong objects count.
+	ErrWrongObjectsCount = internal.Error("wrong objects count")
+
+	// ErrWrongObjects is raised when passed Token contains wrong object ids.
+	ErrWrongObjects = internal.Error("wrong objects")
+
+	// ErrInvalidSignature is raised when wrong signature is passed to VerificationHeader.VerifyData().
+	ErrInvalidSignature = internal.Error("invalid signature")
+)
+
+// verificationData returns byte array to sign.
+// Note: protobuf serialization is inconsistent as
+// wire order is unspecified.
+func (m *Token) verificationData() (data []byte) {
+	var size int
+	if l := len(m.ObjectID); l > 0 {
+		size = m.ObjectID[0].Size()
+		data = make([]byte, 16+l*size)
+	} else {
+		data = make([]byte, 16)
+	}
+	binary.BigEndian.PutUint64(data, m.FirstEpoch)
+	binary.BigEndian.PutUint64(data[8:], m.LastEpoch)
+	for i := range m.ObjectID {
+		copy(data[16+i*size:], m.ObjectID[i].Bytes())
+	}
+	return
+}
+
+// IsSame checks if the passed token is valid and equal to current token
+func (m *Token) IsSame(t *Token) error {
+	switch {
+	case m.FirstEpoch != t.FirstEpoch:
+		return ErrWrongFirstEpoch
+	case m.LastEpoch != t.LastEpoch:
+		return ErrWrongLastEpoch
+	case !m.OwnerID.Equal(t.OwnerID):
+		return ErrWrongOwner
+	case m.Header.PublicKey == nil:
+		return ErrEmptyPublicKey
+	case len(m.ObjectID) != len(t.ObjectID):
+		return ErrWrongObjectsCount
+	default:
+		for i := range m.ObjectID {
+			if !m.ObjectID[i].Equal(t.ObjectID[i]) {
+				return errors.Wrapf(ErrWrongObjects, "expect %s, actual: %s", m.ObjectID[i], t.ObjectID[i])
+			}
+		}
+	}
+	return nil
+}
+
+// Sign tries to sign current Token data and stores signature inside it.
+func (m *Token) Sign(key *ecdsa.PrivateKey) error {
+	if err := m.Header.Sign(key); err != nil {
+		return err
+	}
+
+	s, err := crypto.Sign(key, m.verificationData())
+	if err != nil {
+		return err
+	}
+
+	m.Signature = s
+	return nil
+}
+
+// Verify checks if token is correct and signed.
+func (m *Token) Verify(keys ...*ecdsa.PublicKey) bool {
+	if m.FirstEpoch > m.LastEpoch {
+		return false
+	}
+	for i := range keys {
+		if m.Header.Verify(keys[i]) && crypto.Verify(keys[i], m.verificationData(), m.Signature) == nil {
+			return true
+		}
+	}
+	return false
+}
+
+// Sign adds token signatures.
+func (t *PToken) AddSignatures(signH, signT []byte) {
+	t.mtx.Lock()
+
+	t.Header.KeySignature = signH
+	t.Signature = signT
+
+	t.mtx.Unlock()
+}
+
+// SignData signs data with session private key.
+func (t *PToken) SignData(data []byte) ([]byte, error) {
+	return crypto.Sign(t.PrivateKey, data)
+}
+
+// VerifyData checks if signature of data by token t
+// is equal to sign.
+func (m *VerificationHeader) VerifyData(data, sign []byte) error {
+	if crypto.Verify(crypto.UnmarshalPublicKey(m.PublicKey), data, sign) != nil {
+		return ErrInvalidSignature
+	}
+	return nil
+}
+
+// Verify checks if verification header was issued by id.
+func (m *VerificationHeader) Verify(keys ...*ecdsa.PublicKey) bool {
+	for i := range keys {
+		if crypto.Verify(keys[i], m.PublicKey, m.KeySignature) == nil {
+			return true
+		}
+	}
+	return false
+}
diff --git a/session/types.pb.go b/session/types.pb.go
new file mode 100644
index 00000000..ce0e0a4e
--- /dev/null
+++ b/session/types.pb.go
@@ -0,0 +1,845 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: session/types.proto
+
+package session
+
+import (
+	fmt "fmt"
+	_ "github.com/gogo/protobuf/gogoproto"
+	proto "github.com/golang/protobuf/proto"
+	io "io"
+	math "math"
+	math_bits "math/bits"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
+
+type VerificationHeader struct {
+	PublicKey            []byte   `protobuf:"bytes,1,opt,name=PublicKey,proto3" json:"PublicKey,omitempty"`
+	KeySignature         []byte   `protobuf:"bytes,2,opt,name=KeySignature,proto3" json:"KeySignature,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *VerificationHeader) Reset()         { *m = VerificationHeader{} }
+func (m *VerificationHeader) String() string { return proto.CompactTextString(m) }
+func (*VerificationHeader) ProtoMessage()    {}
+func (*VerificationHeader) Descriptor() ([]byte, []int) {
+	return fileDescriptor_c0d9d9cb855cdad8, []int{0}
+}
+func (m *VerificationHeader) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *VerificationHeader) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *VerificationHeader) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_VerificationHeader.Merge(m, src)
+}
+func (m *VerificationHeader) XXX_Size() int {
+	return m.Size()
+}
+func (m *VerificationHeader) XXX_DiscardUnknown() {
+	xxx_messageInfo_VerificationHeader.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_VerificationHeader proto.InternalMessageInfo
+
+func (m *VerificationHeader) GetPublicKey() []byte {
+	if m != nil {
+		return m.PublicKey
+	}
+	return nil
+}
+
+func (m *VerificationHeader) GetKeySignature() []byte {
+	if m != nil {
+		return m.KeySignature
+	}
+	return nil
+}
+
+type Token struct {
+	Header               VerificationHeader `protobuf:"bytes,1,opt,name=Header,proto3" json:"Header"`
+	OwnerID              OwnerID            `protobuf:"bytes,2,opt,name=OwnerID,proto3,customtype=OwnerID" json:"OwnerID"`
+	FirstEpoch           uint64             `protobuf:"varint,3,opt,name=FirstEpoch,proto3" json:"FirstEpoch,omitempty"`
+	LastEpoch            uint64             `protobuf:"varint,4,opt,name=LastEpoch,proto3" json:"LastEpoch,omitempty"`
+	ObjectID             []ObjectID         `protobuf:"bytes,5,rep,name=ObjectID,proto3,customtype=ObjectID" json:"ObjectID"`
+	Signature            []byte             `protobuf:"bytes,6,opt,name=Signature,proto3" json:"Signature,omitempty"`
+	ID                   TokenID            `protobuf:"bytes,7,opt,name=ID,proto3,customtype=TokenID" json:"ID"`
+	XXX_NoUnkeyedLiteral struct{}           `json:"-"`
+	XXX_unrecognized     []byte             `json:"-"`
+	XXX_sizecache        int32              `json:"-"`
+}
+
+func (m *Token) Reset()         { *m = Token{} }
+func (m *Token) String() string { return proto.CompactTextString(m) }
+func (*Token) ProtoMessage()    {}
+func (*Token) Descriptor() ([]byte, []int) {
+	return fileDescriptor_c0d9d9cb855cdad8, []int{1}
+}
+func (m *Token) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *Token) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *Token) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Token.Merge(m, src)
+}
+func (m *Token) XXX_Size() int {
+	return m.Size()
+}
+func (m *Token) XXX_DiscardUnknown() {
+	xxx_messageInfo_Token.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Token proto.InternalMessageInfo
+
+func (m *Token) GetHeader() VerificationHeader {
+	if m != nil {
+		return m.Header
+	}
+	return VerificationHeader{}
+}
+
+func (m *Token) GetFirstEpoch() uint64 {
+	if m != nil {
+		return m.FirstEpoch
+	}
+	return 0
+}
+
+func (m *Token) GetLastEpoch() uint64 {
+	if m != nil {
+		return m.LastEpoch
+	}
+	return 0
+}
+
+func (m *Token) GetSignature() []byte {
+	if m != nil {
+		return m.Signature
+	}
+	return nil
+}
+
+func init() {
+	proto.RegisterType((*VerificationHeader)(nil), "session.VerificationHeader")
+	proto.RegisterType((*Token)(nil), "session.Token")
+}
+
+func init() { proto.RegisterFile("session/types.proto", fileDescriptor_c0d9d9cb855cdad8) }
+
+var fileDescriptor_c0d9d9cb855cdad8 = []byte{
+	// 344 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x64, 0x91, 0x4d, 0x4b, 0xc3, 0x30,
+	0x18, 0xc7, 0x97, 0xee, 0x4d, 0xe3, 0x40, 0x89, 0x97, 0xa2, 0xd2, 0x8d, 0x9d, 0x2a, 0xb8, 0x16,
+	0xf4, 0xe4, 0xc5, 0x43, 0xa9, 0x62, 0x99, 0x30, 0xa9, 0xb2, 0x83, 0xb7, 0x36, 0xcb, 0xba, 0xf8,
+	0x92, 0x94, 0x26, 0x55, 0xf6, 0x4d, 0xf6, 0x91, 0x76, 0xf4, 0x28, 0x1e, 0x86, 0xd4, 0x2f, 0x22,
+	0x4b, 0xbb, 0x75, 0xc3, 0xdb, 0xf3, 0xfc, 0xfe, 0xc9, 0xf3, 0xf2, 0x7f, 0xe0, 0xa1, 0x20, 0x42,
+	0x50, 0xce, 0x6c, 0x39, 0x8d, 0x89, 0xb0, 0xe2, 0x84, 0x4b, 0x8e, 0x9a, 0x05, 0x3c, 0xea, 0x45,
+	0x54, 0x4e, 0xd2, 0xd0, 0xc2, 0xfc, 0xcd, 0x8e, 0x78, 0xc4, 0x6d, 0xa5, 0x87, 0xe9, 0x58, 0x65,
+	0x2a, 0x51, 0x51, 0xfe, 0xaf, 0x3b, 0x84, 0x68, 0x48, 0x12, 0x3a, 0xa6, 0x38, 0x90, 0x94, 0xb3,
+	0x5b, 0x12, 0x8c, 0x48, 0x82, 0x4e, 0xe0, 0xee, 0x7d, 0x1a, 0xbe, 0x52, 0xdc, 0x27, 0x53, 0x1d,
+	0x74, 0x80, 0xd9, 0xf2, 0x4b, 0x80, 0xba, 0xb0, 0xd5, 0x27, 0xd3, 0x07, 0x1a, 0xb1, 0x40, 0xa6,
+	0x09, 0xd1, 0x35, 0xf5, 0x60, 0x8b, 0x75, 0x67, 0x1a, 0xac, 0x3f, 0xf2, 0x17, 0xc2, 0xd0, 0x25,
+	0x6c, 0xe4, 0x55, 0x55, 0xa1, 0xbd, 0xf3, 0x63, 0xab, 0x18, 0xd5, 0xfa, 0xdf, 0xd8, 0xa9, 0xcd,
+	0x17, 0xed, 0x8a, 0x5f, 0x7c, 0x40, 0xa7, 0xb0, 0x39, 0xf8, 0x60, 0x24, 0xf1, 0xdc, 0xbc, 0x87,
+	0xb3, 0xbf, 0x94, 0xbf, 0x17, 0xed, 0x15, 0xf6, 0x57, 0x01, 0x32, 0x20, 0xbc, 0xa1, 0x89, 0x90,
+	0xd7, 0x31, 0xc7, 0x13, 0xbd, 0xda, 0x01, 0x66, 0xcd, 0xdf, 0x20, 0xcb, 0x8d, 0xee, 0x82, 0x95,
+	0x5c, 0x53, 0x72, 0x09, 0xd0, 0x19, 0xdc, 0x19, 0x84, 0xcf, 0x04, 0x4b, 0xcf, 0xd5, 0xeb, 0x9d,
+	0xaa, 0xd9, 0x72, 0x0e, 0x8a, 0x4e, 0x6b, 0xee, 0xaf, 0xa3, 0x65, 0xad, 0x72, 0xf9, 0x46, 0xee,
+	0xce, 0x1a, 0xa0, 0x36, 0xd4, 0x3c, 0x57, 0x6f, 0x6e, 0xcf, 0xab, 0xac, 0xf0, 0x5c, 0x5f, 0xf3,
+	0x5c, 0xe7, 0x6a, 0x9e, 0x19, 0xe0, 0x33, 0x33, 0xc0, 0x57, 0x66, 0x80, 0x9f, 0xcc, 0x00, 0xb3,
+	0x5f, 0xa3, 0xf2, 0x64, 0x6e, 0xdc, 0x8d, 0x89, 0x18, 0xe3, 0xde, 0x88, 0xbc, 0xdb, 0x8c, 0xf0,
+	0xb1, 0xe8, 0xe5, 0x57, 0x2b, 0x6c, 0x0b, 0x1b, 0x2a, 0xbd, 0xf8, 0x0b, 0x00, 0x00, 0xff, 0xff,
+	0xc6, 0x87, 0x25, 0xf9, 0x08, 0x02, 0x00, 0x00,
+}
+
+func (m *VerificationHeader) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *VerificationHeader) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *VerificationHeader) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if len(m.KeySignature) > 0 {
+		i -= len(m.KeySignature)
+		copy(dAtA[i:], m.KeySignature)
+		i = encodeVarintTypes(dAtA, i, uint64(len(m.KeySignature)))
+		i--
+		dAtA[i] = 0x12
+	}
+	if len(m.PublicKey) > 0 {
+		i -= len(m.PublicKey)
+		copy(dAtA[i:], m.PublicKey)
+		i = encodeVarintTypes(dAtA, i, uint64(len(m.PublicKey)))
+		i--
+		dAtA[i] = 0xa
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *Token) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *Token) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *Token) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	{
+		size := m.ID.Size()
+		i -= size
+		if _, err := m.ID.MarshalTo(dAtA[i:]); err != nil {
+			return 0, err
+		}
+		i = encodeVarintTypes(dAtA, i, uint64(size))
+	}
+	i--
+	dAtA[i] = 0x3a
+	if len(m.Signature) > 0 {
+		i -= len(m.Signature)
+		copy(dAtA[i:], m.Signature)
+		i = encodeVarintTypes(dAtA, i, uint64(len(m.Signature)))
+		i--
+		dAtA[i] = 0x32
+	}
+	if len(m.ObjectID) > 0 {
+		for iNdEx := len(m.ObjectID) - 1; iNdEx >= 0; iNdEx-- {
+			{
+				size := m.ObjectID[iNdEx].Size()
+				i -= size
+				if _, err := m.ObjectID[iNdEx].MarshalTo(dAtA[i:]); err != nil {
+					return 0, err
+				}
+				i = encodeVarintTypes(dAtA, i, uint64(size))
+			}
+			i--
+			dAtA[i] = 0x2a
+		}
+	}
+	if m.LastEpoch != 0 {
+		i = encodeVarintTypes(dAtA, i, uint64(m.LastEpoch))
+		i--
+		dAtA[i] = 0x20
+	}
+	if m.FirstEpoch != 0 {
+		i = encodeVarintTypes(dAtA, i, uint64(m.FirstEpoch))
+		i--
+		dAtA[i] = 0x18
+	}
+	{
+		size := m.OwnerID.Size()
+		i -= size
+		if _, err := m.OwnerID.MarshalTo(dAtA[i:]); err != nil {
+			return 0, err
+		}
+		i = encodeVarintTypes(dAtA, i, uint64(size))
+	}
+	i--
+	dAtA[i] = 0x12
+	{
+		size, err := m.Header.MarshalToSizedBuffer(dAtA[:i])
+		if err != nil {
+			return 0, err
+		}
+		i -= size
+		i = encodeVarintTypes(dAtA, i, uint64(size))
+	}
+	i--
+	dAtA[i] = 0xa
+	return len(dAtA) - i, nil
+}
+
+func encodeVarintTypes(dAtA []byte, offset int, v uint64) int {
+	offset -= sovTypes(v)
+	base := offset
+	for v >= 1<<7 {
+		dAtA[offset] = uint8(v&0x7f | 0x80)
+		v >>= 7
+		offset++
+	}
+	dAtA[offset] = uint8(v)
+	return base
+}
+func (m *VerificationHeader) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = len(m.PublicKey)
+	if l > 0 {
+		n += 1 + l + sovTypes(uint64(l))
+	}
+	l = len(m.KeySignature)
+	if l > 0 {
+		n += 1 + l + sovTypes(uint64(l))
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *Token) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = m.Header.Size()
+	n += 1 + l + sovTypes(uint64(l))
+	l = m.OwnerID.Size()
+	n += 1 + l + sovTypes(uint64(l))
+	if m.FirstEpoch != 0 {
+		n += 1 + sovTypes(uint64(m.FirstEpoch))
+	}
+	if m.LastEpoch != 0 {
+		n += 1 + sovTypes(uint64(m.LastEpoch))
+	}
+	if len(m.ObjectID) > 0 {
+		for _, e := range m.ObjectID {
+			l = e.Size()
+			n += 1 + l + sovTypes(uint64(l))
+		}
+	}
+	l = len(m.Signature)
+	if l > 0 {
+		n += 1 + l + sovTypes(uint64(l))
+	}
+	l = m.ID.Size()
+	n += 1 + l + sovTypes(uint64(l))
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func sovTypes(x uint64) (n int) {
+	return (math_bits.Len64(x|1) + 6) / 7
+}
+func sozTypes(x uint64) (n int) {
+	return sovTypes(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+func (m *VerificationHeader) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowTypes
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: VerificationHeader: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: VerificationHeader: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field PublicKey", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.PublicKey = append(m.PublicKey[:0], dAtA[iNdEx:postIndex]...)
+			if m.PublicKey == nil {
+				m.PublicKey = []byte{}
+			}
+			iNdEx = postIndex
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field KeySignature", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.KeySignature = append(m.KeySignature[:0], dAtA[iNdEx:postIndex]...)
+			if m.KeySignature == nil {
+				m.KeySignature = []byte{}
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipTypes(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *Token) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowTypes
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: Token: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: Token: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Header", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field OwnerID", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.OwnerID.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 3:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field FirstEpoch", wireType)
+			}
+			m.FirstEpoch = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.FirstEpoch |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		case 4:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field LastEpoch", wireType)
+			}
+			m.LastEpoch = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.LastEpoch |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		case 5:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field ObjectID", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			var v ObjectID
+			m.ObjectID = append(m.ObjectID, v)
+			if err := m.ObjectID[len(m.ObjectID)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 6:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Signature", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Signature = append(m.Signature[:0], dAtA[iNdEx:postIndex]...)
+			if m.Signature == nil {
+				m.Signature = []byte{}
+			}
+			iNdEx = postIndex
+		case 7:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.ID.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipTypes(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func skipTypes(dAtA []byte) (n int, err error) {
+	l := len(dAtA)
+	iNdEx := 0
+	depth := 0
+	for iNdEx < l {
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return 0, ErrIntOverflowTypes
+			}
+			if iNdEx >= l {
+				return 0, io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= (uint64(b) & 0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		wireType := int(wire & 0x7)
+		switch wireType {
+		case 0:
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return 0, ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return 0, io.ErrUnexpectedEOF
+				}
+				iNdEx++
+				if dAtA[iNdEx-1] < 0x80 {
+					break
+				}
+			}
+		case 1:
+			iNdEx += 8
+		case 2:
+			var length int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return 0, ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return 0, io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				length |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if length < 0 {
+				return 0, ErrInvalidLengthTypes
+			}
+			iNdEx += length
+		case 3:
+			depth++
+		case 4:
+			if depth == 0 {
+				return 0, ErrUnexpectedEndOfGroupTypes
+			}
+			depth--
+		case 5:
+			iNdEx += 4
+		default:
+			return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+		}
+		if iNdEx < 0 {
+			return 0, ErrInvalidLengthTypes
+		}
+		if depth == 0 {
+			return iNdEx, nil
+		}
+	}
+	return 0, io.ErrUnexpectedEOF
+}
+
+var (
+	ErrInvalidLengthTypes        = fmt.Errorf("proto: negative length found during unmarshaling")
+	ErrIntOverflowTypes          = fmt.Errorf("proto: integer overflow")
+	ErrUnexpectedEndOfGroupTypes = fmt.Errorf("proto: unexpected end of group")
+)
diff --git a/session/types.proto b/session/types.proto
new file mode 100644
index 00000000..8989040d
--- /dev/null
+++ b/session/types.proto
@@ -0,0 +1,22 @@
+syntax = "proto3";
+package session;
+option go_package = "github.com/nspcc-dev/neofs-proto/session";
+
+import "github.com/gogo/protobuf/gogoproto/gogo.proto";
+
+option (gogoproto.stable_marshaler_all) = true;
+
+message VerificationHeader {
+    bytes PublicKey = 1;
+    bytes KeySignature = 2;
+}
+
+message Token {
+    VerificationHeader Header = 1 [(gogoproto.nullable) = false];
+    bytes OwnerID = 2 [(gogoproto.customtype) = "OwnerID", (gogoproto.nullable) = false];
+    uint64 FirstEpoch = 3;
+    uint64 LastEpoch = 4;
+    repeated bytes ObjectID = 5 [(gogoproto.customtype) = "ObjectID", (gogoproto.nullable) = false];
+    bytes Signature = 6;
+    bytes ID = 7 [(gogoproto.customtype) = "TokenID", (gogoproto.nullable) = false];
+}
diff --git a/state/service.go b/state/service.go
new file mode 100644
index 00000000..dd2ec9b7
--- /dev/null
+++ b/state/service.go
@@ -0,0 +1,48 @@
+package state
+
+import (
+	"github.com/golang/protobuf/proto"
+	"github.com/prometheus/client_golang/prometheus"
+	dto "github.com/prometheus/client_model/go"
+	"google.golang.org/grpc/codes"
+	"google.golang.org/grpc/status"
+)
+
+// MetricFamily is type alias for proto.Message generated
+// from github.com/prometheus/client_model/metrics.proto.
+type MetricFamily = dto.MetricFamily
+
+// EncodeMetrics encodes metrics from gatherer into MetricsResponse message,
+// if something went wrong returns gRPC Status error (can be returned from service).
+func EncodeMetrics(g prometheus.Gatherer) (*MetricsResponse, error) {
+	metrics, err := g.Gather()
+	if err != nil {
+		return nil, status.New(codes.Internal, err.Error()).Err()
+	}
+
+	results := make([][]byte, 0, len(metrics))
+	for _, mf := range metrics {
+		item, err := proto.Marshal(mf)
+		if err != nil {
+			return nil, status.New(codes.Internal, err.Error()).Err()
+		}
+
+		results = append(results, item)
+	}
+
+	return &MetricsResponse{Metrics: results}, nil
+}
+
+// DecodeMetrics decodes metrics from MetricsResponse to []MetricFamily,
+// if something went wrong returns error.
+func DecodeMetrics(r *MetricsResponse) ([]*MetricFamily, error) {
+	metrics := make([]*dto.MetricFamily, 0, len(r.Metrics))
+	for i := range r.Metrics {
+		mf := new(MetricFamily)
+		if err := proto.Unmarshal(r.Metrics[i], mf); err != nil {
+			return nil, err
+		}
+	}
+
+	return metrics, nil
+}
diff --git a/state/service.pb.go b/state/service.pb.go
new file mode 100644
index 00000000..f71dad6b
--- /dev/null
+++ b/state/service.pb.go
@@ -0,0 +1,1111 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: state/service.proto
+
+package state
+
+import (
+	context "context"
+	fmt "fmt"
+	_ "github.com/gogo/protobuf/gogoproto"
+	proto "github.com/golang/protobuf/proto"
+	bootstrap "github.com/nspcc-dev/neofs-proto/bootstrap"
+	grpc "google.golang.org/grpc"
+	codes "google.golang.org/grpc/codes"
+	status "google.golang.org/grpc/status"
+	io "io"
+	math "math"
+	math_bits "math/bits"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
+
+// NetmapRequest message to request current node netmap
+type NetmapRequest struct {
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *NetmapRequest) Reset()         { *m = NetmapRequest{} }
+func (m *NetmapRequest) String() string { return proto.CompactTextString(m) }
+func (*NetmapRequest) ProtoMessage()    {}
+func (*NetmapRequest) Descriptor() ([]byte, []int) {
+	return fileDescriptor_695592f6f2fc97b7, []int{0}
+}
+func (m *NetmapRequest) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *NetmapRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *NetmapRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_NetmapRequest.Merge(m, src)
+}
+func (m *NetmapRequest) XXX_Size() int {
+	return m.Size()
+}
+func (m *NetmapRequest) XXX_DiscardUnknown() {
+	xxx_messageInfo_NetmapRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_NetmapRequest proto.InternalMessageInfo
+
+// MetricsRequest message to request node metrics
+type MetricsRequest struct {
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *MetricsRequest) Reset()         { *m = MetricsRequest{} }
+func (m *MetricsRequest) String() string { return proto.CompactTextString(m) }
+func (*MetricsRequest) ProtoMessage()    {}
+func (*MetricsRequest) Descriptor() ([]byte, []int) {
+	return fileDescriptor_695592f6f2fc97b7, []int{1}
+}
+func (m *MetricsRequest) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *MetricsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *MetricsRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_MetricsRequest.Merge(m, src)
+}
+func (m *MetricsRequest) XXX_Size() int {
+	return m.Size()
+}
+func (m *MetricsRequest) XXX_DiscardUnknown() {
+	xxx_messageInfo_MetricsRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_MetricsRequest proto.InternalMessageInfo
+
+// MetricsResponse contains [][]byte,
+// every []byte is marshaled MetricFamily proto message
+// from github.com/prometheus/client_model/metrics.proto
+type MetricsResponse struct {
+	Metrics              [][]byte `protobuf:"bytes,1,rep,name=Metrics,proto3" json:"Metrics,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *MetricsResponse) Reset()         { *m = MetricsResponse{} }
+func (m *MetricsResponse) String() string { return proto.CompactTextString(m) }
+func (*MetricsResponse) ProtoMessage()    {}
+func (*MetricsResponse) Descriptor() ([]byte, []int) {
+	return fileDescriptor_695592f6f2fc97b7, []int{2}
+}
+func (m *MetricsResponse) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *MetricsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *MetricsResponse) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_MetricsResponse.Merge(m, src)
+}
+func (m *MetricsResponse) XXX_Size() int {
+	return m.Size()
+}
+func (m *MetricsResponse) XXX_DiscardUnknown() {
+	xxx_messageInfo_MetricsResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_MetricsResponse proto.InternalMessageInfo
+
+func (m *MetricsResponse) GetMetrics() [][]byte {
+	if m != nil {
+		return m.Metrics
+	}
+	return nil
+}
+
+// HealthRequest message to check current state
+type HealthRequest struct {
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *HealthRequest) Reset()         { *m = HealthRequest{} }
+func (m *HealthRequest) String() string { return proto.CompactTextString(m) }
+func (*HealthRequest) ProtoMessage()    {}
+func (*HealthRequest) Descriptor() ([]byte, []int) {
+	return fileDescriptor_695592f6f2fc97b7, []int{3}
+}
+func (m *HealthRequest) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *HealthRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *HealthRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_HealthRequest.Merge(m, src)
+}
+func (m *HealthRequest) XXX_Size() int {
+	return m.Size()
+}
+func (m *HealthRequest) XXX_DiscardUnknown() {
+	xxx_messageInfo_HealthRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_HealthRequest proto.InternalMessageInfo
+
+// HealthResponse message with current state
+type HealthResponse struct {
+	Healthy              bool     `protobuf:"varint,1,opt,name=Healthy,proto3" json:"Healthy,omitempty"`
+	Status               string   `protobuf:"bytes,2,opt,name=Status,proto3" json:"Status,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *HealthResponse) Reset()         { *m = HealthResponse{} }
+func (m *HealthResponse) String() string { return proto.CompactTextString(m) }
+func (*HealthResponse) ProtoMessage()    {}
+func (*HealthResponse) Descriptor() ([]byte, []int) {
+	return fileDescriptor_695592f6f2fc97b7, []int{4}
+}
+func (m *HealthResponse) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *HealthResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	b = b[:cap(b)]
+	n, err := m.MarshalToSizedBuffer(b)
+	if err != nil {
+		return nil, err
+	}
+	return b[:n], nil
+}
+func (m *HealthResponse) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_HealthResponse.Merge(m, src)
+}
+func (m *HealthResponse) XXX_Size() int {
+	return m.Size()
+}
+func (m *HealthResponse) XXX_DiscardUnknown() {
+	xxx_messageInfo_HealthResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_HealthResponse proto.InternalMessageInfo
+
+func (m *HealthResponse) GetHealthy() bool {
+	if m != nil {
+		return m.Healthy
+	}
+	return false
+}
+
+func (m *HealthResponse) GetStatus() string {
+	if m != nil {
+		return m.Status
+	}
+	return ""
+}
+
+func init() {
+	proto.RegisterType((*NetmapRequest)(nil), "state.NetmapRequest")
+	proto.RegisterType((*MetricsRequest)(nil), "state.MetricsRequest")
+	proto.RegisterType((*MetricsResponse)(nil), "state.MetricsResponse")
+	proto.RegisterType((*HealthRequest)(nil), "state.HealthRequest")
+	proto.RegisterType((*HealthResponse)(nil), "state.HealthResponse")
+}
+
+func init() { proto.RegisterFile("state/service.proto", fileDescriptor_695592f6f2fc97b7) }
+
+var fileDescriptor_695592f6f2fc97b7 = []byte{
+	// 320 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x5c, 0x91, 0xbf, 0x4e, 0xc3, 0x30,
+	0x10, 0xc6, 0x31, 0x88, 0x02, 0x06, 0x5a, 0x64, 0xda, 0x2a, 0xca, 0x10, 0x55, 0x1d, 0x50, 0x25,
+	0xd4, 0x44, 0x02, 0x06, 0x84, 0x98, 0xca, 0xc2, 0x52, 0x86, 0x74, 0x63, 0x73, 0xdc, 0xeb, 0x1f,
+	0x41, 0x6b, 0x13, 0x5f, 0x2a, 0xf5, 0x4d, 0x78, 0x10, 0x1e, 0x82, 0x91, 0x91, 0x11, 0x85, 0x17,
+	0x41, 0xd8, 0x71, 0x20, 0xdd, 0xf2, 0xfd, 0x2e, 0xdf, 0xf9, 0xbb, 0x3b, 0x7a, 0xaa, 0x91, 0x23,
+	0x44, 0x1a, 0xd2, 0xd5, 0x5c, 0x40, 0xa8, 0x52, 0x89, 0x92, 0xed, 0x1a, 0xe8, 0xb7, 0x12, 0x29,
+	0x51, 0x63, 0xca, 0x55, 0x84, 0x6b, 0x05, 0xda, 0x56, 0xfd, 0xfe, 0x74, 0x8e, 0xb3, 0x2c, 0x09,
+	0x85, 0x5c, 0x44, 0x53, 0x39, 0x95, 0x91, 0xc1, 0x49, 0x36, 0x31, 0xca, 0x08, 0xf3, 0x65, 0x7f,
+	0xef, 0x36, 0xe8, 0xf1, 0x03, 0xe0, 0x82, 0xab, 0x18, 0x5e, 0x32, 0xd0, 0xd8, 0x3d, 0xa1, 0xf5,
+	0x21, 0x60, 0x3a, 0x17, 0xda, 0x91, 0x73, 0xda, 0x28, 0x89, 0x56, 0x72, 0xa9, 0x81, 0x79, 0x74,
+	0xaf, 0x40, 0x1e, 0xe9, 0xec, 0xf4, 0x8e, 0x62, 0x27, 0x7f, 0xfb, 0xdd, 0x03, 0x7f, 0xc6, 0x99,
+	0x73, 0x0f, 0x68, 0xdd, 0x81, 0x3f, 0xb3, 0x25, 0x6b, 0x8f, 0x74, 0x48, 0x6f, 0x3f, 0x76, 0x92,
+	0xb5, 0x69, 0x6d, 0x84, 0x1c, 0x33, 0xed, 0x6d, 0x77, 0x48, 0xef, 0x20, 0x2e, 0xd4, 0xc5, 0x1b,
+	0x71, 0x05, 0x76, 0x45, 0x6b, 0x36, 0x2f, 0x6b, 0x86, 0x66, 0x0f, 0x61, 0x25, 0xbe, 0xdf, 0x0c,
+	0xcb, 0xb5, 0x84, 0x23, 0x95, 0x02, 0x1f, 0x0f, 0xb9, 0x62, 0xd7, 0x65, 0x5e, 0xd6, 0x2a, 0x6c,
+	0xd5, 0x21, 0xfd, 0xf6, 0x26, 0x2e, 0xc2, 0xde, 0xd0, 0x43, 0x9b, 0xee, 0x6e, 0x06, 0xe2, 0xa9,
+	0x7c, 0xb4, 0x32, 0xa3, 0xdf, 0xda, 0xa0, 0xd6, 0x3b, 0xb8, 0x7d, 0xcf, 0x03, 0xf2, 0x91, 0x07,
+	0xe4, 0x33, 0x0f, 0xc8, 0x57, 0x1e, 0x90, 0xd7, 0xef, 0x60, 0xeb, 0xf1, 0xec, 0xdf, 0x81, 0x96,
+	0x5a, 0x09, 0xd1, 0x1f, 0xc3, 0x2a, 0x5a, 0x82, 0x9c, 0xe8, 0xbe, 0x3d, 0x8f, 0x69, 0x96, 0xd4,
+	0x8c, 0xb8, 0xfc, 0x09, 0x00, 0x00, 0xff, 0xff, 0x73, 0xd9, 0x9d, 0xd0, 0x04, 0x02, 0x00, 0x00,
+}
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ context.Context
+var _ grpc.ClientConn
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the grpc package it is being compiled against.
+const _ = grpc.SupportPackageIsVersion4
+
+// StatusClient is the client API for Status service.
+//
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
+type StatusClient interface {
+	Netmap(ctx context.Context, in *NetmapRequest, opts ...grpc.CallOption) (*bootstrap.SpreadMap, error)
+	Metrics(ctx context.Context, in *MetricsRequest, opts ...grpc.CallOption) (*MetricsResponse, error)
+	HealthCheck(ctx context.Context, in *HealthRequest, opts ...grpc.CallOption) (*HealthResponse, error)
+}
+
+type statusClient struct {
+	cc *grpc.ClientConn
+}
+
+func NewStatusClient(cc *grpc.ClientConn) StatusClient {
+	return &statusClient{cc}
+}
+
+func (c *statusClient) Netmap(ctx context.Context, in *NetmapRequest, opts ...grpc.CallOption) (*bootstrap.SpreadMap, error) {
+	out := new(bootstrap.SpreadMap)
+	err := c.cc.Invoke(ctx, "/state.Status/Netmap", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *statusClient) Metrics(ctx context.Context, in *MetricsRequest, opts ...grpc.CallOption) (*MetricsResponse, error) {
+	out := new(MetricsResponse)
+	err := c.cc.Invoke(ctx, "/state.Status/Metrics", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *statusClient) HealthCheck(ctx context.Context, in *HealthRequest, opts ...grpc.CallOption) (*HealthResponse, error) {
+	out := new(HealthResponse)
+	err := c.cc.Invoke(ctx, "/state.Status/HealthCheck", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+// StatusServer is the server API for Status service.
+type StatusServer interface {
+	Netmap(context.Context, *NetmapRequest) (*bootstrap.SpreadMap, error)
+	Metrics(context.Context, *MetricsRequest) (*MetricsResponse, error)
+	HealthCheck(context.Context, *HealthRequest) (*HealthResponse, error)
+}
+
+// UnimplementedStatusServer can be embedded to have forward compatible implementations.
+type UnimplementedStatusServer struct {
+}
+
+func (*UnimplementedStatusServer) Netmap(ctx context.Context, req *NetmapRequest) (*bootstrap.SpreadMap, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method Netmap not implemented")
+}
+func (*UnimplementedStatusServer) Metrics(ctx context.Context, req *MetricsRequest) (*MetricsResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method Metrics not implemented")
+}
+func (*UnimplementedStatusServer) HealthCheck(ctx context.Context, req *HealthRequest) (*HealthResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method HealthCheck not implemented")
+}
+
+func RegisterStatusServer(s *grpc.Server, srv StatusServer) {
+	s.RegisterService(&_Status_serviceDesc, srv)
+}
+
+func _Status_Netmap_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(NetmapRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(StatusServer).Netmap(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/state.Status/Netmap",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(StatusServer).Netmap(ctx, req.(*NetmapRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _Status_Metrics_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(MetricsRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(StatusServer).Metrics(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/state.Status/Metrics",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(StatusServer).Metrics(ctx, req.(*MetricsRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _Status_HealthCheck_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(HealthRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(StatusServer).HealthCheck(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/state.Status/HealthCheck",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(StatusServer).HealthCheck(ctx, req.(*HealthRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+var _Status_serviceDesc = grpc.ServiceDesc{
+	ServiceName: "state.Status",
+	HandlerType: (*StatusServer)(nil),
+	Methods: []grpc.MethodDesc{
+		{
+			MethodName: "Netmap",
+			Handler:    _Status_Netmap_Handler,
+		},
+		{
+			MethodName: "Metrics",
+			Handler:    _Status_Metrics_Handler,
+		},
+		{
+			MethodName: "HealthCheck",
+			Handler:    _Status_HealthCheck_Handler,
+		},
+	},
+	Streams:  []grpc.StreamDesc{},
+	Metadata: "state/service.proto",
+}
+
+func (m *NetmapRequest) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *NetmapRequest) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *NetmapRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *MetricsRequest) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *MetricsRequest) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *MetricsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *MetricsResponse) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *MetricsResponse) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *MetricsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if len(m.Metrics) > 0 {
+		for iNdEx := len(m.Metrics) - 1; iNdEx >= 0; iNdEx-- {
+			i -= len(m.Metrics[iNdEx])
+			copy(dAtA[i:], m.Metrics[iNdEx])
+			i = encodeVarintService(dAtA, i, uint64(len(m.Metrics[iNdEx])))
+			i--
+			dAtA[i] = 0xa
+		}
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *HealthRequest) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *HealthRequest) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *HealthRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *HealthResponse) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *HealthResponse) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *HealthResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if len(m.Status) > 0 {
+		i -= len(m.Status)
+		copy(dAtA[i:], m.Status)
+		i = encodeVarintService(dAtA, i, uint64(len(m.Status)))
+		i--
+		dAtA[i] = 0x12
+	}
+	if m.Healthy {
+		i--
+		if m.Healthy {
+			dAtA[i] = 1
+		} else {
+			dAtA[i] = 0
+		}
+		i--
+		dAtA[i] = 0x8
+	}
+	return len(dAtA) - i, nil
+}
+
+func encodeVarintService(dAtA []byte, offset int, v uint64) int {
+	offset -= sovService(v)
+	base := offset
+	for v >= 1<<7 {
+		dAtA[offset] = uint8(v&0x7f | 0x80)
+		v >>= 7
+		offset++
+	}
+	dAtA[offset] = uint8(v)
+	return base
+}
+func (m *NetmapRequest) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *MetricsRequest) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *MetricsResponse) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if len(m.Metrics) > 0 {
+		for _, b := range m.Metrics {
+			l = len(b)
+			n += 1 + l + sovService(uint64(l))
+		}
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *HealthRequest) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *HealthResponse) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.Healthy {
+		n += 2
+	}
+	l = len(m.Status)
+	if l > 0 {
+		n += 1 + l + sovService(uint64(l))
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func sovService(x uint64) (n int) {
+	return (math_bits.Len64(x|1) + 6) / 7
+}
+func sozService(x uint64) (n int) {
+	return sovService(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+func (m *NetmapRequest) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowService
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: NetmapRequest: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: NetmapRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		default:
+			iNdEx = preIndex
+			skippy, err := skipService(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *MetricsRequest) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowService
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: MetricsRequest: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: MetricsRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		default:
+			iNdEx = preIndex
+			skippy, err := skipService(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *MetricsResponse) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowService
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: MetricsResponse: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: MetricsResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Metrics", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthService
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthService
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Metrics = append(m.Metrics, make([]byte, postIndex-iNdEx))
+			copy(m.Metrics[len(m.Metrics)-1], dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipService(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *HealthRequest) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowService
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: HealthRequest: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: HealthRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		default:
+			iNdEx = preIndex
+			skippy, err := skipService(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *HealthResponse) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowService
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: HealthResponse: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: HealthResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Healthy", wireType)
+			}
+			var v int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				v |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			m.Healthy = bool(v != 0)
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Status", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthService
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex < 0 {
+				return ErrInvalidLengthService
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Status = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipService(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthService
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func skipService(dAtA []byte) (n int, err error) {
+	l := len(dAtA)
+	iNdEx := 0
+	depth := 0
+	for iNdEx < l {
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return 0, ErrIntOverflowService
+			}
+			if iNdEx >= l {
+				return 0, io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= (uint64(b) & 0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		wireType := int(wire & 0x7)
+		switch wireType {
+		case 0:
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return 0, ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return 0, io.ErrUnexpectedEOF
+				}
+				iNdEx++
+				if dAtA[iNdEx-1] < 0x80 {
+					break
+				}
+			}
+		case 1:
+			iNdEx += 8
+		case 2:
+			var length int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return 0, ErrIntOverflowService
+				}
+				if iNdEx >= l {
+					return 0, io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				length |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if length < 0 {
+				return 0, ErrInvalidLengthService
+			}
+			iNdEx += length
+		case 3:
+			depth++
+		case 4:
+			if depth == 0 {
+				return 0, ErrUnexpectedEndOfGroupService
+			}
+			depth--
+		case 5:
+			iNdEx += 4
+		default:
+			return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+		}
+		if iNdEx < 0 {
+			return 0, ErrInvalidLengthService
+		}
+		if depth == 0 {
+			return iNdEx, nil
+		}
+	}
+	return 0, io.ErrUnexpectedEOF
+}
+
+var (
+	ErrInvalidLengthService        = fmt.Errorf("proto: negative length found during unmarshaling")
+	ErrIntOverflowService          = fmt.Errorf("proto: integer overflow")
+	ErrUnexpectedEndOfGroupService = fmt.Errorf("proto: unexpected end of group")
+)
diff --git a/state/service.proto b/state/service.proto
new file mode 100644
index 00000000..d0e59b4f
--- /dev/null
+++ b/state/service.proto
@@ -0,0 +1,37 @@
+syntax = "proto3";
+package state;
+option go_package = "github.com/nspcc-dev/neofs-proto/state";
+
+import "bootstrap/types.proto";
+import "github.com/gogo/protobuf/gogoproto/gogo.proto";
+
+option (gogoproto.stable_marshaler_all) = true;
+
+// The Status service definition.
+service Status {
+    rpc Netmap(NetmapRequest) returns (bootstrap.SpreadMap);
+    rpc Metrics(MetricsRequest) returns (MetricsResponse);
+    rpc HealthCheck(HealthRequest) returns (HealthResponse);
+}
+
+// NetmapRequest message to request current node netmap
+message NetmapRequest {}
+
+// MetricsRequest message to request node metrics
+message MetricsRequest {}
+
+// MetricsResponse contains [][]byte,
+// every []byte is marshaled MetricFamily proto message
+// from github.com/prometheus/client_model/metrics.proto
+message MetricsResponse {
+    repeated bytes Metrics = 1;
+}
+
+// HealthRequest message to check current state
+message HealthRequest {}
+
+// HealthResponse message with current state
+message HealthResponse {
+    bool Healthy  = 1;
+    string Status = 2;
+}