diff --git a/.github/markdown.tmpl b/.github/markdown.tmpl
new file mode 100644
index 0000000..f945c13
--- /dev/null
+++ b/.github/markdown.tmpl
@@ -0,0 +1,83 @@
+# Protocol Documentation
+<a name="top"></a>
+
+## Table of Contents
+{{range .Files}}
+{{$file_name := .Name}}- [{{.Name}}](#{{.Name}})
+{{if .Services}} - Services
+    {{range .Services}}- [{{.Name}}](#{{.FullName}})
+    {{end}}{{end}}
+{{if .Messages}}  - Messages
+    {{range .Messages}}- [{{.LongName}}](#{{.FullName}})
+    {{end}}{{end}}
+{{end}}
+- [Scalar Value Types](#scalar-value-types)
+
+{{range .Files}}
+{{$file_name := .Name}}
+<a name="{{.Name}}"></a>
+<p align="right"><a href="#top">Top</a></p>
+
+## {{.Name}}
+{{.Description}}
+
+{{range .Services}}
+
+<a name="{{.FullName}}"></a>
+
+### Service "{{.FullName}}"
+{{.Description}}
+
+```
+{{range .Methods -}}
+  rpc {{.Name}}({{if .RequestStreaming}}stream {{end}}{{.RequestLongType}}) returns ({{if .ResponseStreaming}}stream {{end}}{{.ResponseLongType}});
+{{end}}
+```
+
+{{range .Methods -}}
+#### Method {{.Name}}
+
+{{.Description}}
+
+| Name | Input | Output |
+| ---- | ----- | ------ |
+| {{.Name}} | [{{.RequestLongType}}](#{{.RequestFullType}}) | [{{.ResponseLongType}}](#{{.ResponseFullType}}) |
+{{end}}{{end}} <!-- end services -->
+
+{{range .Messages}}
+<a name="{{.FullName}}"></a>
+
+### Message {{.LongName}}
+{{.Description}}
+
+{{if .HasFields}}
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+{{range .Fields -}}
+  | {{.Name}} | [{{.LongType}}](#{{.FullType}}) | {{.Label}} | {{nobr .Description}}{{if .DefaultValue}} Default: {{.DefaultValue}}{{end}} |
+{{end}}{{end}}
+{{end}} <!-- end messages -->
+
+{{range .Enums}}
+<a name="{{.FullName}}"></a>
+
+### {{.LongName}}
+{{.Description}}
+
+| Name | Number | Description |
+| ---- | ------ | ----------- |
+{{range .Values -}}
+  | {{.Name}} | {{.Number}} | {{nobr .Description}} |
+{{end}}
+
+{{end}} <!-- end enums -->
+
+{{end}}
+
+## Scalar Value Types
+
+| .proto Type | Notes | C++ Type | Java Type | Python Type |
+| ----------- | ----- | -------- | --------- | ----------- |
+{{range .Scalars -}}
+  | <a name="{{.ProtoType}}" /> {{.ProtoType}} | {{.Notes}} | {{.CppType}} | {{.JavaType}} | {{.PythonType}} |
+{{end}}
diff --git a/Makefile b/Makefile
index c17477a..64b0939 100644
--- a/Makefile
+++ b/Makefile
@@ -1,3 +1,26 @@
+B=\033[0;1m
+G=\033[0;92m
+R=\033[0m
+
+# Reformat code
+format:
+	@[ ! -z `which goimports` ] || (echo "install goimports" && exit 2)
+	@for f in `find . -type f -name '*.go' -not -path './vendor/*' -not -name '*.pb.go' -prune`; do \
+		echo "${B}${G}⇒ Processing $$f ${R}"; \
+		goimports -w $$f; \
+	done
+
+# Regenerate documentation for protot files:
+docgen:
+	@for f in `find . -type f -name '*.proto' -not -path './vendor/*' -exec dirname {} \; | sort -u `; do \
+		echo "${B}${G}⇒ Documentation for $$(basename $$f) ${R}"; \
+		protoc \
+			--doc_opt=.github/markdown.tmpl,$${f}.md \
+			--proto_path=.:./vendor:/usr/local/include \
+			--doc_out=docs/ $${f}/*.proto; \
+	done
+
+# Regenerate proto files:
 protoc:
 	@go mod tidy -v
 	@go mod vendor
@@ -6,7 +29,9 @@ protoc:
 	# 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:. '{}' \;
+	@for f in `find . -type f -name '*.proto' -not -path './vendor/*'`; do \
+		echo "${B}${G}⇒ Processing $$f ${R}"; \
+		protoc \
+			--proto_path=.:./vendor:/usr/local/include \
+			--gofast_out=plugins=grpc,paths=source_relative:. $$f; \
+	done
diff --git a/README.md b/README.md
index 9247a10..a6662c3 100644
--- a/README.md
+++ b/README.md
@@ -9,6 +9,8 @@ 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. 
 
+There is a auto-generated documentation for protobuf files in [docs](docs).
+
 ### Accounting
 
 Accounting package defines services and structures for accounting operations: 
@@ -17,11 +19,22 @@ 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. 
 
+#### API
+Accounting package defines: 
+- [Accounting service](docs/accounting.md#accounting.Accounting)
+- [Withdraw service](docs/accounting.md#accounting.Withdraw)
+
+
 ### Bootstrap
 
 Bootstrap package defines bootstrap service which is used by storage nodes to
 connect to the storage network. 
 
+#### API
+Bootstrap package defines:
+- [Bootstrap service](docs/bootstrap.md#bootstrap.Bootstrap)
+
+
 ### Chain
 
 Chain package contains util functions for operations with NEO Blockchain types:
@@ -33,6 +46,10 @@ Container package defines service and structures for operations with containers.
 Objects in NeoFS are stored in containers. Container defines storage 
 policy for the objects. 
 
+#### API
+Bootstrap package defines:
+- [Container service](docs/container.md#container.Service)
+
 ### Decimal
 
 Decimal defines custom decimal implementation which is used in accounting
@@ -53,6 +70,10 @@ 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.
 
+#### API
+Object package defines:
+- [Object service](docs/object.md#object.Service)
+
 ### Query
 
 Query package defines structure for object search requests. 
@@ -72,10 +93,18 @@ 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. 
 
+#### API
+Session package defines:
+- [Session service](docs/session.md#session.Session)
+
 ### State
 
 State package defines service and structures for metrics gathering. 
 
+#### API
+State package defines:
+- [Status service](docs/state.md#state.Status)
+
 ## How to use
 
 NeoFS-proto packages contain godoc documentation. Examples of using most of 
diff --git a/accounting/service.pb.go b/accounting/service.pb.go
index 8708db3..ea86a8e 100644
--- a/accounting/service.pb.go
+++ b/accounting/service.pb.go
@@ -29,7 +29,9 @@ var _ = math.Inf
 const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
 
 type BalanceRequest struct {
-	OwnerID              OwnerID  `protobuf:"bytes,1,opt,name=OwnerID,proto3,customtype=OwnerID" json:"OwnerID"`
+	// OwnerID is a wallet address
+	OwnerID OwnerID `protobuf:"bytes,1,opt,name=OwnerID,proto3,customtype=OwnerID" json:"OwnerID"`
+	// TTL must be larger than zero, it decreased in every neofs-node
 	TTL                  uint32   `protobuf:"varint,2,opt,name=TTL,proto3" json:"TTL,omitempty"`
 	XXX_NoUnkeyedLiteral struct{} `json:"-"`
 	XXX_unrecognized     []byte   `json:"-"`
@@ -73,11 +75,14 @@ func (m *BalanceRequest) GetTTL() uint32 {
 }
 
 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:"-"`
+	// Balance contains current account balance state
+	Balance *decimal.Decimal `protobuf:"bytes,1,opt,name=Balance,proto3" json:"Balance,omitempty"`
+	// LockAccounts contains information about locked funds. Locked funds appear
+	// when user pays for storage or withdraw assets.
+	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{} }
@@ -166,6 +171,7 @@ const _ = grpc.SupportPackageIsVersion4
 //
 // 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 returns current balance status of the NeoFS user
 	Balance(ctx context.Context, in *BalanceRequest, opts ...grpc.CallOption) (*BalanceResponse, error)
 }
 
@@ -188,6 +194,7 @@ func (c *accountingClient) Balance(ctx context.Context, in *BalanceRequest, opts
 
 // AccountingServer is the server API for Accounting service.
 type AccountingServer interface {
+	// Balance returns current balance status of the NeoFS user
 	Balance(context.Context, *BalanceRequest) (*BalanceResponse, error)
 }
 
diff --git a/accounting/service.proto b/accounting/service.proto
index b75bf9c..f975c23 100644
--- a/accounting/service.proto
+++ b/accounting/service.proto
@@ -8,16 +8,24 @@ import "github.com/gogo/protobuf/gogoproto/gogo.proto";
 
 option (gogoproto.stable_marshaler_all) = true;
 
+// Accounting is a service that provides access for accounting balance
+// information
 service Accounting {
+    // Balance returns current balance status of the NeoFS user
     rpc Balance(BalanceRequest) returns (BalanceResponse);
 }
 
 message BalanceRequest {
+    // OwnerID is a wallet address
     bytes OwnerID = 1 [(gogoproto.customtype) = "OwnerID", (gogoproto.nullable) = false];
+    // TTL must be larger than zero, it decreased in every neofs-node
     uint32 TTL    = 2;
 }
 
 message BalanceResponse {
+    // Balance contains current account balance state
     decimal.Decimal Balance       = 1;
+    // LockAccounts contains information about locked funds. Locked funds appear
+    // when user pays for storage or withdraw assets.
     repeated Account LockAccounts = 2;
 }
diff --git a/accounting/types.pb.go b/accounting/types.pb.go
index cb4b0c8..dd020ec 100644
--- a/accounting/types.pb.go
+++ b/accounting/types.pb.go
@@ -24,6 +24,7 @@ var _ = math.Inf
 // proto package needs to be updated.
 const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
 
+// Unit can be Unlimited, based on NeoFS epoch or Neo block
 type Lifetime_Unit int32
 
 const (
@@ -49,9 +50,10 @@ func (x Lifetime_Unit) String() string {
 }
 
 func (Lifetime_Unit) EnumDescriptor() ([]byte, []int) {
-	return fileDescriptor_437c556d7375b726, []int{6, 0}
+	return fileDescriptor_437c556d7375b726, []int{4, 0}
 }
 
+// Type can be withdrawal, payIO or inner
 type Tx_Type int32
 
 const (
@@ -80,21 +82,27 @@ func (x Tx_Type) String() string {
 }
 
 func (Tx_Type) EnumDescriptor() ([]byte, []int) {
-	return fileDescriptor_437c556d7375b726, []int{7, 0}
+	return fileDescriptor_437c556d7375b726, []int{5, 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:"-"`
+	// OwnerID is a wallet address
+	OwnerID OwnerID `protobuf:"bytes,1,opt,name=OwnerID,proto3,customtype=OwnerID" json:"OwnerID"`
+	// Address is identifier of accounting record
+	Address string `protobuf:"bytes,2,opt,name=Address,proto3" json:"Address,omitempty"`
+	// ParentAddress is identifier of parent accounting record
+	ParentAddress string `protobuf:"bytes,3,opt,name=ParentAddress,proto3" json:"ParentAddress,omitempty"`
+	// ActiveFunds is amount of active (non locked) funds for account
+	ActiveFunds *decimal.Decimal `protobuf:"bytes,4,opt,name=ActiveFunds,proto3" json:"ActiveFunds,omitempty"`
+	// Lifetime is time until account is valid (used for lock accounts)
+	Lifetime Lifetime `protobuf:"bytes,5,opt,name=Lifetime,proto3" json:"Lifetime"`
+	// LockTarget is the purpose of lock funds (it might be withdraw or payment for storage)
+	LockTarget *LockTarget `protobuf:"bytes,6,opt,name=LockTarget,proto3" json:"LockTarget,omitempty"`
+	// LockAccounts contains child accounts with locked funds
+	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{} }
@@ -168,6 +176,7 @@ func (m *Account) GetLockAccounts() []*Account {
 	return nil
 }
 
+// LockTarget must be one of two options
 type LockTarget struct {
 	// Types that are valid to be assigned to Target:
 	//	*LockTarget_WithdrawTarget
@@ -252,8 +261,8 @@ func (*LockTarget) XXX_OneofWrappers() []interface{} {
 	}
 }
 
-// Snapshot balance messages
 type Balances struct {
+	// Accounts contains multiple account snapshots
 	Accounts             []Account `protobuf:"bytes,1,rep,name=Accounts,proto3" json:"Accounts"`
 	XXX_NoUnkeyedLiteral struct{}  `json:"-"`
 	XXX_unrecognized     []byte    `json:"-"`
@@ -296,9 +305,12 @@ func (m *Balances) GetAccounts() []Account {
 	return nil
 }
 
-// PayIn / PayOut messages
 type PayIO struct {
-	BlockID              uint64   `protobuf:"varint,1,opt,name=BlockID,proto3" json:"BlockID,omitempty"`
+	// BlockID contains id of the NEO block where withdraw or deposit
+	// call was invoked
+	BlockID uint64 `protobuf:"varint,1,opt,name=BlockID,proto3" json:"BlockID,omitempty"`
+	// Transactions contains all transactions that founded in block
+	// and used for PayIO
 	Transactions         []Tx     `protobuf:"bytes,2,rep,name=Transactions,proto3" json:"Transactions"`
 	XXX_NoUnkeyedLiteral struct{} `json:"-"`
 	XXX_unrecognized     []byte   `json:"-"`
@@ -348,124 +360,21 @@ func (m *PayIO) GetTransactions() []Tx {
 	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:"-"`
+	// Unit describes how lifetime is measured in account
+	Unit Lifetime_Unit `protobuf:"varint,1,opt,name=unit,proto3,enum=accounting.Lifetime_Unit" json:"unit,omitempty"`
+	// Value describes how long lifetime will be valid
+	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}
+	return fileDescriptor_437c556d7375b726, []int{4}
 }
 func (m *Lifetime) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -504,23 +413,27 @@ func (m *Lifetime) GetValue() int64 {
 	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:"-"`
+	// Type describes target of transaction
+	Type Tx_Type `protobuf:"varint,1,opt,name=type,proto3,enum=accounting.Tx_Type" json:"type,omitempty"`
+	// From describes sender of funds
+	From string `protobuf:"bytes,2,opt,name=From,proto3" json:"From,omitempty"`
+	// To describes receiver of funds
+	To string `protobuf:"bytes,3,opt,name=To,proto3" json:"To,omitempty"`
+	// Amount describes amount of funds
+	Amount *decimal.Decimal `protobuf:"bytes,4,opt,name=Amount,proto3" json:"Amount,omitempty"`
+	// PublicKeys contains public key of sender
+	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}
+	return fileDescriptor_437c556d7375b726, []int{5}
 }
 func (m *Tx) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -581,7 +494,9 @@ func (m *Tx) GetPublicKeys() []byte {
 }
 
 type Settlement struct {
-	Epoch                uint64           `protobuf:"varint,1,opt,name=Epoch,proto3" json:"Epoch,omitempty"`
+	// Epoch contains an epoch when settlement was accepted
+	Epoch uint64 `protobuf:"varint,1,opt,name=Epoch,proto3" json:"Epoch,omitempty"`
+	// Transactions is a set of transactions
 	Transactions         []*Settlement_Tx `protobuf:"bytes,2,rep,name=Transactions,proto3" json:"Transactions,omitempty"`
 	XXX_NoUnkeyedLiteral struct{}         `json:"-"`
 	XXX_unrecognized     []byte           `json:"-"`
@@ -592,7 +507,7 @@ 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}
+	return fileDescriptor_437c556d7375b726, []int{6}
 }
 func (m *Settlement) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -632,7 +547,9 @@ func (m *Settlement) GetTransactions() []*Settlement_Tx {
 }
 
 type Settlement_Receiver struct {
-	To                   string           `protobuf:"bytes,1,opt,name=To,proto3" json:"To,omitempty"`
+	// To is the address of funds recipient
+	To string `protobuf:"bytes,1,opt,name=To,proto3" json:"To,omitempty"`
+	// Amount is the amount of funds that will be sent
 	Amount               *decimal.Decimal `protobuf:"bytes,2,opt,name=Amount,proto3" json:"Amount,omitempty"`
 	XXX_NoUnkeyedLiteral struct{}         `json:"-"`
 	XXX_unrecognized     []byte           `json:"-"`
@@ -643,7 +560,7 @@ 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}
+	return fileDescriptor_437c556d7375b726, []int{6, 0}
 }
 func (m *Settlement_Receiver) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -683,7 +600,9 @@ func (m *Settlement_Receiver) GetAmount() *decimal.Decimal {
 }
 
 type Settlement_Container struct {
-	CID                  CID      `protobuf:"bytes,1,opt,name=CID,proto3,customtype=CID" json:"CID"`
+	// CID is container identifier
+	CID CID `protobuf:"bytes,1,opt,name=CID,proto3,customtype=CID" json:"CID"`
+	// SGIDs is a set of storage groups that successfully passed the audit
 	SGIDs                []SGID   `protobuf:"bytes,2,rep,name=SGIDs,proto3,customtype=SGID" json:"SGIDs"`
 	XXX_NoUnkeyedLiteral struct{} `json:"-"`
 	XXX_unrecognized     []byte   `json:"-"`
@@ -694,7 +613,7 @@ 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}
+	return fileDescriptor_437c556d7375b726, []int{6, 1}
 }
 func (m *Settlement_Container) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -720,8 +639,11 @@ func (m *Settlement_Container) XXX_DiscardUnknown() {
 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"`
+	// From is the address of the sender of funds
+	From string `protobuf:"bytes,1,opt,name=From,proto3" json:"From,omitempty"`
+	// Container that successfully had passed the audit
+	Container Settlement_Container `protobuf:"bytes,2,opt,name=Container,proto3" json:"Container"`
+	// Receivers is a set of addresses of funds recipients
 	Receivers            []Settlement_Receiver `protobuf:"bytes,3,rep,name=Receivers,proto3" json:"Receivers"`
 	XXX_NoUnkeyedLiteral struct{}              `json:"-"`
 	XXX_unrecognized     []byte                `json:"-"`
@@ -732,7 +654,7 @@ 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}
+	return fileDescriptor_437c556d7375b726, []int{6, 2}
 }
 func (m *Settlement_Tx) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -779,6 +701,7 @@ func (m *Settlement_Tx) GetReceivers() []Settlement_Receiver {
 }
 
 type ContainerCreateTarget struct {
+	// CID is container identifier
 	CID                  CID      `protobuf:"bytes,1,opt,name=CID,proto3,customtype=CID" json:"CID"`
 	XXX_NoUnkeyedLiteral struct{} `json:"-"`
 	XXX_unrecognized     []byte   `json:"-"`
@@ -789,7 +712,7 @@ 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}
+	return fileDescriptor_437c556d7375b726, []int{7}
 }
 func (m *ContainerCreateTarget) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -815,6 +738,7 @@ func (m *ContainerCreateTarget) XXX_DiscardUnknown() {
 var xxx_messageInfo_ContainerCreateTarget proto.InternalMessageInfo
 
 type WithdrawTarget struct {
+	// Cheque is a string representation of cheque id
 	Cheque               string   `protobuf:"bytes,1,opt,name=Cheque,proto3" json:"Cheque,omitempty"`
 	XXX_NoUnkeyedLiteral struct{} `json:"-"`
 	XXX_unrecognized     []byte   `json:"-"`
@@ -825,7 +749,7 @@ 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}
+	return fileDescriptor_437c556d7375b726, []int{8}
 }
 func (m *WithdrawTarget) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -864,8 +788,6 @@ func init() {
 	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")
@@ -879,62 +801,59 @@ func init() {
 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,
+	// 821 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x55, 0x4d, 0x6f, 0xe3, 0x44,
+	0x18, 0xce, 0x38, 0x69, 0x3e, 0xde, 0x64, 0x83, 0x35, 0xbb, 0x5b, 0x85, 0x48, 0xa4, 0xc1, 0xe2,
+	0x10, 0x84, 0xea, 0x88, 0xae, 0x68, 0xb9, 0x70, 0x88, 0x13, 0xca, 0x56, 0xac, 0xba, 0xd5, 0xd4,
+	0x05, 0x01, 0x27, 0xd7, 0x99, 0xa6, 0x56, 0x93, 0x99, 0x60, 0x8f, 0xfb, 0xf1, 0x27, 0x38, 0x73,
+	0xe1, 0xc4, 0x8f, 0xe0, 0x2f, 0xec, 0x11, 0x6e, 0x88, 0x43, 0x85, 0xc2, 0x1f, 0x41, 0x33, 0x1e,
+	0x3b, 0x76, 0x95, 0xc0, 0x25, 0x79, 0x3f, 0x9e, 0xf7, 0x99, 0xf7, 0x6b, 0xc6, 0xb0, 0xeb, 0xf9,
+	0x3e, 0x8f, 0x99, 0x08, 0xd8, 0x6c, 0x28, 0x1e, 0x96, 0x34, 0xb2, 0x97, 0x21, 0x17, 0x1c, 0xc3,
+	0xda, 0xde, 0x7d, 0x39, 0xa5, 0x7e, 0xb0, 0xf0, 0xe6, 0x43, 0xfd, 0x9f, 0x40, 0xba, 0xfb, 0xb3,
+	0x40, 0x5c, 0xc7, 0x97, 0xb6, 0xcf, 0x17, 0xc3, 0x19, 0x9f, 0xf1, 0xa1, 0x32, 0x5f, 0xc6, 0x57,
+	0x4a, 0x53, 0x8a, 0x92, 0x12, 0xb8, 0xf5, 0x87, 0x01, 0xb5, 0x51, 0x42, 0x8a, 0x3f, 0x86, 0xda,
+	0xdb, 0x3b, 0x46, 0xc3, 0x93, 0x49, 0x07, 0xf5, 0xd1, 0xa0, 0xe5, 0xbc, 0xf7, 0xee, 0x71, 0xaf,
+	0xf4, 0xd7, 0xe3, 0x5e, 0x6a, 0x26, 0xa9, 0x80, 0x3b, 0x50, 0x1b, 0x4d, 0xa7, 0x21, 0x8d, 0xa2,
+	0x8e, 0xd1, 0x47, 0x83, 0x06, 0x49, 0x55, 0xfc, 0x11, 0x3c, 0x3b, 0xf3, 0x42, 0xca, 0x44, 0xea,
+	0x2f, 0x2b, 0x7f, 0xd1, 0x88, 0x0f, 0xa0, 0x39, 0xf2, 0x45, 0x70, 0x4b, 0x8f, 0x63, 0x36, 0x8d,
+	0x3a, 0x95, 0x3e, 0x1a, 0x34, 0x0f, 0x4c, 0x3b, 0x2d, 0x65, 0x92, 0xfc, 0x93, 0x3c, 0x08, 0x1f,
+	0x42, 0xfd, 0x4d, 0x70, 0x45, 0x45, 0xb0, 0xa0, 0x9d, 0x1d, 0x15, 0xf0, 0xc2, 0x5e, 0xf7, 0xc3,
+	0x4e, 0x7d, 0x4e, 0x45, 0x66, 0x4d, 0x32, 0x2c, 0x3e, 0x04, 0x78, 0xc3, 0xfd, 0x1b, 0xd7, 0x0b,
+	0x67, 0x54, 0x74, 0xaa, 0x2a, 0x72, 0xb7, 0x10, 0x99, 0x79, 0x49, 0x0e, 0x89, 0x8f, 0xa0, 0x25,
+	0x35, 0xdd, 0x9d, 0xa8, 0x53, 0xeb, 0x97, 0x07, 0xcd, 0x83, 0xe7, 0xf9, 0x48, 0xed, 0x23, 0x05,
+	0xa0, 0xf5, 0x1b, 0xca, 0x9f, 0x88, 0x27, 0xd0, 0xfe, 0x36, 0x10, 0xd7, 0xd3, 0xd0, 0xbb, 0xd3,
+	0x39, 0x20, 0x95, 0x43, 0x37, 0xcf, 0x54, 0x44, 0xbc, 0x2e, 0x91, 0x27, 0x31, 0xf8, 0x3b, 0x78,
+	0x39, 0xe6, 0x4c, 0x78, 0x01, 0xa3, 0xe1, 0x38, 0xa4, 0x9e, 0xa0, 0x9a, 0xcc, 0x50, 0x64, 0x1f,
+	0xe6, 0xc9, 0x36, 0x02, 0x5f, 0x97, 0xc8, 0x66, 0x06, 0xa7, 0x0e, 0xd5, 0x44, 0xb2, 0x46, 0x50,
+	0x77, 0xbc, 0xb9, 0xc7, 0x7c, 0x1a, 0xe1, 0xcf, 0xa0, 0x9e, 0x95, 0x8e, 0xb6, 0x96, 0x9e, 0x76,
+	0x3b, 0x2b, 0xfe, 0x07, 0xd8, 0x39, 0xf3, 0x1e, 0x4e, 0xde, 0xca, 0x15, 0x71, 0xe6, 0xdc, 0xbf,
+	0xd1, 0xdb, 0x54, 0x21, 0xa9, 0x8a, 0x3f, 0x87, 0x96, 0x1b, 0x7a, 0x2c, 0xf2, 0x7c, 0x11, 0x70,
+	0x26, 0x37, 0x48, 0xb2, 0xb7, 0xf3, 0xec, 0xee, 0xbd, 0x26, 0x2e, 0x20, 0xad, 0x9f, 0xd0, 0x7a,
+	0x07, 0xf0, 0x11, 0x54, 0x62, 0x16, 0x24, 0xdd, 0x6c, 0x1f, 0xbc, 0xbf, 0x69, 0x17, 0xec, 0x0b,
+	0x16, 0x08, 0xa7, 0xbe, 0x7a, 0xdc, 0xab, 0x48, 0x89, 0xa8, 0x00, 0xfc, 0x02, 0x76, 0xbe, 0xf1,
+	0xe6, 0x31, 0x55, 0xad, 0x2b, 0x93, 0x44, 0xb1, 0x5e, 0x81, 0xc2, 0xe0, 0x67, 0xd0, 0xb8, 0x60,
+	0xf3, 0x60, 0x11, 0x08, 0x3a, 0x35, 0x4b, 0xb8, 0x0d, 0x70, 0x4a, 0xf9, 0xf1, 0xf9, 0x97, 0x4b,
+	0xee, 0x5f, 0x9b, 0x08, 0xb7, 0xa0, 0x7e, 0x4a, 0xb9, 0x2a, 0xc5, 0x34, 0xac, 0x47, 0x04, 0x86,
+	0x7b, 0x8f, 0x3f, 0x85, 0x8a, 0xbc, 0xa6, 0x3a, 0x95, 0xe7, 0xc5, 0x4a, 0x6c, 0xf7, 0x61, 0x49,
+	0x93, 0x24, 0xa4, 0x44, 0x14, 0x14, 0x63, 0xa8, 0x1c, 0x87, 0x7c, 0xa1, 0xaf, 0x8f, 0x92, 0x71,
+	0x1b, 0x0c, 0x97, 0xeb, 0x0b, 0x63, 0xb8, 0x1c, 0x0f, 0xa0, 0x3a, 0x5a, 0x48, 0xa2, 0xad, 0x17,
+	0x44, 0xfb, 0x71, 0x0f, 0xe0, 0x2c, 0xbe, 0x9c, 0x07, 0xfe, 0xd7, 0xf4, 0x21, 0x52, 0xb7, 0xa3,
+	0x45, 0x72, 0x16, 0xeb, 0x08, 0xd4, 0xd9, 0xb8, 0x09, 0xb5, 0x0b, 0x76, 0xc3, 0xf8, 0x1d, 0x33,
+	0x4b, 0xb2, 0x94, 0x74, 0xc9, 0x4c, 0x84, 0x1b, 0x7a, 0x70, 0xa6, 0x21, 0xc5, 0x13, 0xc6, 0x68,
+	0x68, 0x96, 0xad, 0x5f, 0xca, 0x00, 0xe7, 0x54, 0x88, 0x39, 0x5d, 0x50, 0xa6, 0x5a, 0xa7, 0x1a,
+	0xa1, 0x47, 0x9a, 0x28, 0xf8, 0x8b, 0x8d, 0x03, 0x2d, 0x4c, 0x64, 0xcd, 0x61, 0xbb, 0xf7, 0xc5,
+	0xa9, 0x76, 0x27, 0x50, 0x27, 0xd4, 0xa7, 0xc1, 0x2d, 0x0d, 0x75, 0x0b, 0xd0, 0x86, 0x16, 0x18,
+	0xff, 0xdd, 0x82, 0xee, 0x29, 0x34, 0xb2, 0xf5, 0xc6, 0x1f, 0x40, 0x79, 0x9c, 0x3d, 0x63, 0x4d,
+	0xfd, 0x8c, 0x49, 0x13, 0x91, 0x3f, 0xd8, 0x82, 0x9d, 0xf3, 0xaf, 0x4e, 0x26, 0x49, 0xa6, 0x2d,
+	0xa7, 0xa5, 0x01, 0x15, 0x69, 0x24, 0x89, 0xab, 0xfb, 0x6b, 0x32, 0xda, 0x74, 0x4e, 0x28, 0x37,
+	0xa7, 0x49, 0xee, 0x28, 0x9d, 0x57, 0x7f, 0x4b, 0xb1, 0x19, 0x4e, 0xef, 0x73, 0x2e, 0xc7, 0x31,
+	0x34, 0xd2, 0xb2, 0xe5, 0x2b, 0x29, 0x5b, 0xb6, 0xb7, 0x85, 0x25, 0xc5, 0xa5, 0x24, 0x59, 0x9c,
+	0x75, 0xb8, 0xe5, 0x59, 0xf8, 0x9f, 0x0e, 0x58, 0x83, 0xa7, 0x8f, 0x12, 0xde, 0x85, 0xea, 0xf8,
+	0x9a, 0xfe, 0x18, 0x53, 0x5d, 0xaa, 0xd6, 0x9c, 0xd1, 0xbb, 0x55, 0x0f, 0xfd, 0xbe, 0xea, 0xa1,
+	0x3f, 0x57, 0x3d, 0xf4, 0xf7, 0xaa, 0x87, 0x7e, 0xfe, 0xa7, 0x57, 0xfa, 0xfe, 0x93, 0xdc, 0x67,
+	0x86, 0x45, 0x4b, 0xdf, 0xdf, 0x9f, 0xd2, 0xdb, 0x21, 0xa3, 0xfc, 0x2a, 0xda, 0x4f, 0x3e, 0x32,
+	0xeb, 0x4a, 0x2e, 0xab, 0xca, 0xf2, 0xea, 0xdf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x3c, 0x2d, 0x7e,
+	0x6b, 0xd7, 0x06, 0x00, 0x00,
 }
 
 func (m *Account) Marshal() (dAtA []byte, err error) {
@@ -1201,98 +1120,6 @@ func (m *PayIO) MarshalToSizedBuffer(dAtA []byte) (int, error) {
 	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)
@@ -1794,47 +1621,6 @@ func (m *PayIO) Size() (n int) {
 	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
@@ -2614,235 +2400,6 @@ func (m *PayIO) Unmarshal(dAtA []byte) error {
 	}
 	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
diff --git a/accounting/types.proto b/accounting/types.proto
index 1b4e783..ac512b9 100644
--- a/accounting/types.proto
+++ b/accounting/types.proto
@@ -7,61 +7,63 @@ import "github.com/gogo/protobuf/gogoproto/gogo.proto";
 
 option (gogoproto.stable_marshaler_all) = true;
 
-// Snapshot accounting messages
 message Account {
+    // OwnerID is a wallet address
     bytes OwnerID                 = 1 [(gogoproto.customtype) = "OwnerID",  (gogoproto.nullable) = false];
+    // Address is identifier of accounting record
     string Address                = 2;
+    // ParentAddress is identifier of parent accounting record
     string ParentAddress          = 3;
+    // ActiveFunds is amount of active (non locked) funds for account
     decimal.Decimal ActiveFunds   = 4;
+    // Lifetime is time until account is valid (used for lock accounts)
     Lifetime Lifetime             = 5 [(gogoproto.nullable) = false];
+    // LockTarget is the purpose of lock funds (it might be withdraw or payment for storage)
     LockTarget LockTarget         = 6;
+    // LockAccounts contains child accounts with locked funds
     repeated Account LockAccounts = 7;
 }
 
+// LockTarget must be one of two options
 message LockTarget {
     oneof Target {
+        // WithdrawTarget used when user requested withdraw
         WithdrawTarget WithdrawTarget = 1;
+        // ContainerCreateTarget used when user requested creation of container
         ContainerCreateTarget ContainerCreateTarget = 2;
     }
 }
 
-// Snapshot balance messages
 message Balances {
+    // Accounts contains multiple account snapshots
     repeated Account Accounts = 1 [(gogoproto.nullable) = false];
 }
 
-// PayIn / PayOut messages
 message PayIO {
+    // BlockID contains id of the NEO block where withdraw or deposit
+    // call was invoked
     uint64 BlockID = 1;
+    // Transactions contains all transactions that founded in block
+    // and used for PayIO
     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 {
+    // Unit can be Unlimited, based on NeoFS epoch or Neo block
     enum Unit {
         Unlimited = 0;
         NeoFSEpoch = 1;
         NeoBlock = 2;
     }
 
+    // Unit describes how lifetime is measured in account
     Unit unit = 1 [(gogoproto.customname) = "Unit"];
+    // Value describes how long lifetime will be valid
     int64 Value = 2;
 }
 
-// Transaction messages
 message Tx {
+    // Type can be withdrawal, payIO or inner
     enum Type {
         Unknown  = 0;
         Withdraw = 1;
@@ -69,38 +71,54 @@ message Tx {
         Inner    = 3;
     }
 
+    // Type describes target of transaction
     Type type              = 1 [(gogoproto.customname) = "Type"];
+    // From describes sender of funds
     string From            = 2;
+    // To describes receiver of funds
     string To              = 3;
+    // Amount describes amount of funds
     decimal.Decimal Amount = 4;
-    bytes PublicKeys       = 5; // of sender
+    // PublicKeys contains public key of sender
+    bytes PublicKeys       = 5;
 }
 
 message Settlement {
     message Receiver {
+        // To is the address of funds recipient 
         string To              = 1;
+        // Amount is the amount of funds that will be sent
         decimal.Decimal Amount = 2;
     }
 
     message Container {
+        // CID is container identifier
         bytes CID            = 1 [(gogoproto.customtype) = "CID", (gogoproto.nullable) = false];
+        // SGIDs is a set of storage groups that successfully passed the audit
         repeated bytes SGIDs = 2 [(gogoproto.customtype) = "SGID", (gogoproto.nullable) = false];
     }
 
     message Tx {
+        // From is the address of the sender of funds
         string From                 = 1;
+        // Container that successfully had passed the audit
         Container Container         = 2 [(gogoproto.nullable) = false];
+        // Receivers is a set of addresses of funds recipients
         repeated Receiver Receivers = 3 [(gogoproto.nullable) = false];
     }
 
+    // Epoch contains an epoch when settlement was accepted
     uint64 Epoch             = 1;
+    // Transactions is a set of transactions
     repeated Tx Transactions = 2;
 }
 
 message ContainerCreateTarget {
+    // CID is container identifier
     bytes CID = 1 [(gogoproto.customtype) = "CID", (gogoproto.nullable) = false];
 }
 
 message WithdrawTarget {
+    // Cheque is a string representation of cheque id
     string Cheque = 1;
 }
diff --git a/accounting/withdraw.pb.go b/accounting/withdraw.pb.go
index 967a2ce..b50bc1c 100644
--- a/accounting/withdraw.pb.go
+++ b/accounting/withdraw.pb.go
@@ -29,14 +29,19 @@ var _ = math.Inf
 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:"-"`
+	// ID is a cheque identifier
+	ID ChequeID `protobuf:"bytes,1,opt,name=ID,proto3,customtype=ChequeID" json:"ID"`
+	// OwnerID is a wallet address
+	OwnerID OwnerID `protobuf:"bytes,2,opt,name=OwnerID,proto3,customtype=OwnerID" json:"OwnerID"`
+	// Amount of funds
+	Amount *decimal.Decimal `protobuf:"bytes,3,opt,name=Amount,proto3" json:"Amount,omitempty"`
+	// Height is the neo blockchain height until the cheque is valid
+	Height uint64 `protobuf:"varint,4,opt,name=Height,proto3" json:"Height,omitempty"`
+	// Payload contains cheque representation in bytes
+	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{} }
@@ -90,8 +95,11 @@ func (m *Item) GetPayload() []byte {
 }
 
 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"`
+	// ID is cheque identifier
+	ID ChequeID `protobuf:"bytes,1,opt,name=ID,proto3,customtype=ChequeID" json:"ID"`
+	// OwnerID is a wallet address
+	OwnerID OwnerID `protobuf:"bytes,2,opt,name=OwnerID,proto3,customtype=OwnerID" json:"OwnerID"`
+	// TTL must be larger than zero, it decreased in every neofs-node
 	TTL                  uint32   `protobuf:"varint,3,opt,name=TTL,proto3" json:"TTL,omitempty"`
 	XXX_NoUnkeyedLiteral struct{} `json:"-"`
 	XXX_unrecognized     []byte   `json:"-"`
@@ -135,6 +143,7 @@ func (m *GetRequest) GetTTL() uint32 {
 }
 
 type GetResponse struct {
+	// Item is cheque with meta information
 	Withdraw             *Item    `protobuf:"bytes,1,opt,name=Withdraw,proto3" json:"Withdraw,omitempty"`
 	XXX_NoUnkeyedLiteral struct{} `json:"-"`
 	XXX_unrecognized     []byte   `json:"-"`
@@ -178,15 +187,21 @@ func (m *GetResponse) GetWithdraw() *Item {
 }
 
 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:"-"`
+	// OwnerID is a wallet address
+	OwnerID OwnerID `protobuf:"bytes,1,opt,name=OwnerID,proto3,customtype=OwnerID" json:"OwnerID"`
+	// Amount of funds
+	Amount *decimal.Decimal `protobuf:"bytes,2,opt,name=Amount,proto3" json:"Amount,omitempty"`
+	// Height is the neo blockchain height until the cheque is valid
+	Height uint64 `protobuf:"varint,3,opt,name=Height,proto3" json:"Height,omitempty"`
+	// MessageID is a nonce for uniq request (UUIDv4)
+	MessageID MessageID `protobuf:"bytes,4,opt,name=MessageID,proto3,customtype=MessageID" json:"MessageID"`
+	// Signature is a signature of the sent request
+	Signature []byte `protobuf:"bytes,5,opt,name=Signature,proto3" json:"Signature,omitempty"`
+	// TTL must be larger than zero, it decreased in every neofs-node
+	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{} }
@@ -247,6 +262,7 @@ func (m *PutRequest) GetTTL() uint32 {
 }
 
 type PutResponse struct {
+	// ID is cheque identifier
 	ID                   ChequeID `protobuf:"bytes,1,opt,name=ID,proto3,customtype=ChequeID" json:"ID"`
 	XXX_NoUnkeyedLiteral struct{} `json:"-"`
 	XXX_unrecognized     []byte   `json:"-"`
@@ -283,7 +299,9 @@ func (m *PutResponse) XXX_DiscardUnknown() {
 var xxx_messageInfo_PutResponse proto.InternalMessageInfo
 
 type ListRequest struct {
-	OwnerID              OwnerID  `protobuf:"bytes,1,opt,name=OwnerID,proto3,customtype=OwnerID" json:"OwnerID"`
+	// OwnerID is a wallet address
+	OwnerID OwnerID `protobuf:"bytes,1,opt,name=OwnerID,proto3,customtype=OwnerID" json:"OwnerID"`
+	// TTL must be larger than zero, it decreased in every neofs-node
 	TTL                  uint32   `protobuf:"varint,2,opt,name=TTL,proto3" json:"TTL,omitempty"`
 	XXX_NoUnkeyedLiteral struct{} `json:"-"`
 	XXX_unrecognized     []byte   `json:"-"`
@@ -327,6 +345,7 @@ func (m *ListRequest) GetTTL() uint32 {
 }
 
 type ListResponse struct {
+	// Item is a set of cheques with meta information
 	Items                []*Item  `protobuf:"bytes,1,rep,name=Items,proto3" json:"Items,omitempty"`
 	XXX_NoUnkeyedLiteral struct{} `json:"-"`
 	XXX_unrecognized     []byte   `json:"-"`
@@ -370,14 +389,19 @@ func (m *ListResponse) GetItems() []*Item {
 }
 
 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:"-"`
+	// ID is cheque identifier
+	ID ChequeID `protobuf:"bytes,1,opt,name=ID,proto3,customtype=ChequeID" json:"ID"`
+	// OwnerID is a wallet address
+	OwnerID OwnerID `protobuf:"bytes,2,opt,name=OwnerID,proto3,customtype=OwnerID" json:"OwnerID"`
+	// MessageID is a nonce for uniq request (UUIDv4)
+	MessageID MessageID `protobuf:"bytes,3,opt,name=MessageID,proto3,customtype=MessageID" json:"MessageID"`
+	// Signature is a signature of the sent request
+	Signature []byte `protobuf:"bytes,4,opt,name=Signature,proto3" json:"Signature,omitempty"`
+	// TTL must be larger than zero, it decreased in every neofs-node
+	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{} }
@@ -423,6 +447,7 @@ func (m *DeleteRequest) GetTTL() uint32 {
 	return 0
 }
 
+// DeleteResponse is empty
 type DeleteResponse struct {
 	XXX_NoUnkeyedLiteral struct{} `json:"-"`
 	XXX_unrecognized     []byte   `json:"-"`
@@ -523,9 +548,13 @@ const _ = grpc.SupportPackageIsVersion4
 //
 // 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 returns cheque if it was signed by inner ring nodes
 	Get(ctx context.Context, in *GetRequest, opts ...grpc.CallOption) (*GetResponse, error)
+	// Put ask inner ring nodes to sign a cheque for withdraw invoke
 	Put(ctx context.Context, in *PutRequest, opts ...grpc.CallOption) (*PutResponse, error)
+	// List shows all user's checks
 	List(ctx context.Context, in *ListRequest, opts ...grpc.CallOption) (*ListResponse, error)
+	// Delete allows user to remove unused cheque
 	Delete(ctx context.Context, in *DeleteRequest, opts ...grpc.CallOption) (*DeleteResponse, error)
 }
 
@@ -575,9 +604,13 @@ func (c *withdrawClient) Delete(ctx context.Context, in *DeleteRequest, opts ...
 
 // WithdrawServer is the server API for Withdraw service.
 type WithdrawServer interface {
+	// Get returns cheque if it was signed by inner ring nodes
 	Get(context.Context, *GetRequest) (*GetResponse, error)
+	// Put ask inner ring nodes to sign a cheque for withdraw invoke
 	Put(context.Context, *PutRequest) (*PutResponse, error)
+	// List shows all user's checks
 	List(context.Context, *ListRequest) (*ListResponse, error)
+	// Delete allows user to remove unused cheque
 	Delete(context.Context, *DeleteRequest) (*DeleteResponse, error)
 }
 
diff --git a/accounting/withdraw.proto b/accounting/withdraw.proto
index c099ef7..33ce402 100644
--- a/accounting/withdraw.proto
+++ b/accounting/withdraw.proto
@@ -7,55 +7,88 @@ import "github.com/gogo/protobuf/gogoproto/gogo.proto";
 
 option (gogoproto.stable_marshaler_all) = true;
 
+// Withdraw is a service that provides withdraw assets operations from the NeoFS
 service Withdraw {
+    // Get returns cheque if it was signed by inner ring nodes
     rpc Get(GetRequest) returns (GetResponse);
+    // Put ask inner ring nodes to sign a cheque for withdraw invoke
     rpc Put(PutRequest) returns (PutResponse);
+    // List shows all user's checks
     rpc List(ListRequest) returns (ListResponse);
+    // Delete allows user to remove unused cheque
     rpc Delete(DeleteRequest) returns (DeleteResponse);
 }
 
 message Item {
+    // ID is a cheque identifier
     bytes ID               = 1 [(gogoproto.customtype) = "ChequeID", (gogoproto.nullable) = false];
+    // OwnerID is a wallet address
     bytes OwnerID          = 2 [(gogoproto.customtype) = "OwnerID", (gogoproto.nullable) = false];
+    // Amount of funds
     decimal.Decimal Amount = 3;
+    // Height is the neo blockchain height until the cheque is valid
     uint64 Height          = 4;
+    // Payload contains cheque representation in bytes
     bytes Payload          = 5;
 }
 
 message GetRequest {
+    // ID is cheque identifier
     bytes ID      = 1 [(gogoproto.customtype) = "ChequeID", (gogoproto.nullable) = false];
+    // OwnerID is a wallet address
     bytes OwnerID = 2 [(gogoproto.customtype) = "OwnerID", (gogoproto.nullable) = false];
+    // TTL must be larger than zero, it decreased in every neofs-node
     uint32 TTL    = 3;
 }
+
 message GetResponse {
+    // Item is cheque with meta information
     Item Withdraw = 1;
 }
 
 message PutRequest {
+    // OwnerID is a wallet address
     bytes OwnerID          = 1 [(gogoproto.customtype) = "OwnerID", (gogoproto.nullable) = false];
+    // Amount of funds
     decimal.Decimal Amount = 2;
+    // Height is the neo blockchain height until the cheque is valid
     uint64 Height          = 3;
+    // MessageID is a nonce for uniq request (UUIDv4)
     bytes MessageID        = 4 [(gogoproto.customtype) = "MessageID", (gogoproto.nullable) = false];
+    // Signature is a signature of the sent request
     bytes Signature        = 5;
+    // TTL must be larger than zero, it decreased in every neofs-node
     uint32 TTL             = 6;
 }
 message PutResponse {
+    // ID is cheque identifier
     bytes ID = 1 [(gogoproto.customtype) = "ChequeID", (gogoproto.nullable) = false];
 }
 
 message ListRequest {
+    // OwnerID is a wallet address
     bytes OwnerID = 1 [(gogoproto.customtype) = "OwnerID", (gogoproto.nullable) = false];
+    // TTL must be larger than zero, it decreased in every neofs-node
     uint32 TTL    = 2;
 }
+
 message ListResponse {
+    // Item is a set of cheques with meta information
     repeated Item Items = 1;
 }
 
 message DeleteRequest {
+    // ID is cheque identifier
     bytes ID        = 1 [(gogoproto.customtype) = "ChequeID", (gogoproto.nullable) = false];
+    // OwnerID is a wallet address
     bytes OwnerID   = 2 [(gogoproto.customtype) = "OwnerID", (gogoproto.nullable) = false];
+    // MessageID is a nonce for uniq request (UUIDv4)
     bytes MessageID = 3 [(gogoproto.customtype) = "MessageID", (gogoproto.nullable) = false];
+    // Signature is a signature of the sent request
     bytes Signature = 4;
+    // TTL must be larger than zero, it decreased in every neofs-node
     uint32 TTL      = 5;
 }
+
+// DeleteResponse is empty
 message DeleteResponse {}
diff --git a/bootstrap/service.pb.go b/bootstrap/service.pb.go
index 2fcdb4d..14f8e9e 100644
--- a/bootstrap/service.pb.go
+++ b/bootstrap/service.pb.go
@@ -27,10 +27,12 @@ var _ = math.Inf
 // 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"`
+	// Type is NodeType, can be InnerRingNode (type=1) or StorageNode (type=2)
+	Type NodeType `protobuf:"varint,1,opt,name=type,proto3,customtype=NodeType" json:"type"`
+	// Info contains information about node
+	Info NodeInfo `protobuf:"bytes,2,opt,name=info,proto3" json:"info"`
+	// TTL must be larger than zero, it decreased in every neofs-node
 	TTL                  uint32   `protobuf:"varint,3,opt,name=TTL,proto3" json:"TTL,omitempty"`
 	XXX_NoUnkeyedLiteral struct{} `json:"-"`
 	XXX_unrecognized     []byte   `json:"-"`
@@ -120,6 +122,7 @@ const _ = grpc.SupportPackageIsVersion4
 //
 // 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 is method that allows to register node in the network and receive actual netmap
 	Process(ctx context.Context, in *Request, opts ...grpc.CallOption) (*SpreadMap, error)
 }
 
@@ -142,6 +145,7 @@ func (c *bootstrapClient) Process(ctx context.Context, in *Request, opts ...grpc
 
 // BootstrapServer is the server API for Bootstrap service.
 type BootstrapServer interface {
+	// Process is method that allows to register node in the network and receive actual netmap
 	Process(context.Context, *Request) (*SpreadMap, error)
 }
 
diff --git a/bootstrap/service.proto b/bootstrap/service.proto
index 3c9dced..a0f82dc 100644
--- a/bootstrap/service.proto
+++ b/bootstrap/service.proto
@@ -7,14 +7,19 @@ import "github.com/gogo/protobuf/gogoproto/gogo.proto";
 
 option (gogoproto.stable_marshaler_all) = true;
 
-// The Bootstrap service definition.
+// Bootstrap service allows neofs-node to connect to the network. Node should
+// perform at least one bootstrap request in the epoch to stay in the network
+// for the next epoch.
 service Bootstrap {
+    // Process is method that allows to register node in the network and receive actual netmap
     rpc Process(Request) returns (bootstrap.SpreadMap);
 }
 
-// Request message to communicate between DHT nodes
 message Request {
+    // Type is NodeType, can be InnerRingNode (type=1) or StorageNode (type=2)
     int32              type = 1 [(gogoproto.customname) = "Type" , (gogoproto.nullable) = false, (gogoproto.customtype) = "NodeType"];
+    // Info contains information about node
     bootstrap.NodeInfo info = 2 [(gogoproto.nullable) = false];
+    // TTL must be larger than zero, it decreased in every neofs-node
     uint32 TTL           = 3;
 }
diff --git a/bootstrap/types.pb.go b/bootstrap/types.pb.go
index a90de05..f279919 100644
--- a/bootstrap/types.pb.go
+++ b/bootstrap/types.pb.go
@@ -24,7 +24,9 @@ var _ = math.Inf
 const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
 
 type SpreadMap struct {
-	Epoch                uint64     `protobuf:"varint,1,opt,name=Epoch,proto3" json:"Epoch,omitempty"`
+	// Epoch is current epoch for netmap
+	Epoch uint64 `protobuf:"varint,1,opt,name=Epoch,proto3" json:"Epoch,omitempty"`
+	// NetMap is a set of NodeInfos
 	NetMap               []NodeInfo `protobuf:"bytes,2,rep,name=NetMap,proto3" json:"NetMap"`
 	XXX_NoUnkeyedLiteral struct{}   `json:"-"`
 	XXX_unrecognized     []byte     `json:"-"`
@@ -74,9 +76,13 @@ func (m *SpreadMap) GetNetMap() []NodeInfo {
 }
 
 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"`
+	// Address is a node [multi-address](https://github.com/multiformats/multiaddr)
+	Address string `protobuf:"bytes,1,opt,name=Address,proto3" json:"address"`
+	// PubKey is a compressed public key representation in bytes
+	PubKey []byte `protobuf:"bytes,2,opt,name=PubKey,proto3" json:"pubkey,omitempty"`
+	// Options is set of node optional information, such as storage capacity, node location, price and etc
+	Options []string `protobuf:"bytes,3,rep,name=Options,proto3" json:"options,omitempty"`
+	// Status is bitmap status of the node
 	Status               NodeStatus `protobuf:"varint,4,opt,name=Status,proto3,customtype=NodeStatus" json:"status"`
 	XXX_NoUnkeyedLiteral struct{}   `json:"-"`
 	XXX_unrecognized     []byte     `json:"-"`
diff --git a/bootstrap/types.proto b/bootstrap/types.proto
index 4d6e458..5a566da 100644
--- a/bootstrap/types.proto
+++ b/bootstrap/types.proto
@@ -10,13 +10,19 @@ option (gogoproto.stringer_all) =  false;
 option (gogoproto.goproto_stringer_all) = false;
 
 message SpreadMap {
+    // Epoch is current epoch for netmap
     uint64 Epoch = 1;
+    // NetMap is a set of NodeInfos
     repeated NodeInfo NetMap = 2 [(gogoproto.nullable) = false];
 }
 
 message NodeInfo {
+    // Address is a node [multi-address](https://github.com/multiformats/multiaddr)
     string Address          = 1 [(gogoproto.jsontag) = "address"];
+    // PubKey is a compressed public key representation in bytes
     bytes PubKey            = 2 [(gogoproto.jsontag) = "pubkey,omitempty"];
+    // Options is set of node optional information, such as storage capacity, node location, price and etc
     repeated string Options = 3 [(gogoproto.jsontag) = "options,omitempty"];
+    // Status is bitmap status of the node
     uint64 Status           = 4 [(gogoproto.jsontag) = "status", (gogoproto.nullable) = false, (gogoproto.customtype) = "NodeStatus"];
 }
diff --git a/container/service.pb.go b/container/service.pb.go
index bc2e831..9cc6991 100644
--- a/container/service.pb.go
+++ b/container/service.pb.go
@@ -28,17 +28,22 @@ var _ = math.Inf
 // 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:"-"`
+	// MessageID is a nonce for uniq container id calculation
+	MessageID MessageID `protobuf:"bytes,1,opt,name=MessageID,proto3,customtype=MessageID" json:"MessageID"`
+	// Capacity defines amount of data that can be stored in the container (doesn't used for now).
+	Capacity uint64 `protobuf:"varint,2,opt,name=Capacity,proto3" json:"Capacity,omitempty"`
+	// OwnerID is a wallet address
+	OwnerID OwnerID `protobuf:"bytes,3,opt,name=OwnerID,proto3,customtype=OwnerID" json:"OwnerID"`
+	// Rules define storage policy for the object inside the container.
+	Rules netmap.PlacementRule `protobuf:"bytes,4,opt,name=rules,proto3" json:"rules"`
+	// Signature of the user (owner id)
+	Signature []byte `protobuf:"bytes,5,opt,name=Signature,proto3" json:"Signature,omitempty"`
+	// TTL must be larger than zero, it decreased in every neofs-node
+	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{} }
@@ -98,8 +103,8 @@ func (m *PutRequest) GetTTL() uint32 {
 	return 0
 }
 
-// PutResponse message to respond about container uuid
 type PutResponse struct {
+	// CID (container id) is a SHA256 hash of the container structure
 	CID                  CID      `protobuf:"bytes,1,opt,name=CID,proto3,customtype=CID" json:"CID"`
 	XXX_NoUnkeyedLiteral struct{} `json:"-"`
 	XXX_unrecognized     []byte   `json:"-"`
@@ -136,8 +141,11 @@ func (m *PutResponse) XXX_DiscardUnknown() {
 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"`
+	// CID (container id) is a SHA256 hash of the container structure
+	CID CID `protobuf:"bytes,1,opt,name=CID,proto3,customtype=CID" json:"CID"`
+	// TTL must be larger than zero, it decreased in every neofs-node
+	TTL uint32 `protobuf:"varint,2,opt,name=TTL,proto3" json:"TTL,omitempty"`
+	// Signature of the container owner
 	Signature            []byte   `protobuf:"bytes,3,opt,name=Signature,proto3" json:"Signature,omitempty"`
 	XXX_NoUnkeyedLiteral struct{} `json:"-"`
 	XXX_unrecognized     []byte   `json:"-"`
@@ -187,6 +195,8 @@ func (m *DeleteRequest) GetSignature() []byte {
 	return nil
 }
 
+// DeleteResponse is empty because delete operation is asynchronous and done
+// via consensus in inner ring nodes
 type DeleteResponse struct {
 	XXX_NoUnkeyedLiteral struct{} `json:"-"`
 	XXX_unrecognized     []byte   `json:"-"`
@@ -222,9 +232,10 @@ func (m *DeleteResponse) XXX_DiscardUnknown() {
 
 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"`
+	// CID (container id) is a SHA256 hash of the container structure
+	CID CID `protobuf:"bytes,1,opt,name=CID,proto3,customtype=CID" json:"CID"`
+	// TTL must be larger than zero, it decreased in every neofs-node
 	TTL                  uint32   `protobuf:"varint,2,opt,name=TTL,proto3" json:"TTL,omitempty"`
 	XXX_NoUnkeyedLiteral struct{} `json:"-"`
 	XXX_unrecognized     []byte   `json:"-"`
@@ -267,8 +278,8 @@ func (m *GetRequest) GetTTL() uint32 {
 	return 0
 }
 
-// GetResponse message with container structure
 type GetResponse struct {
+	// Container is a structure that contains placement rules and owner id
 	Container            *Container `protobuf:"bytes,1,opt,name=Container,proto3" json:"Container,omitempty"`
 	XXX_NoUnkeyedLiteral struct{}   `json:"-"`
 	XXX_unrecognized     []byte     `json:"-"`
@@ -311,9 +322,10 @@ func (m *GetResponse) GetContainer() *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"`
+	// OwnerID is a wallet address
+	OwnerID OwnerID `protobuf:"bytes,1,opt,name=OwnerID,proto3,customtype=OwnerID" json:"OwnerID"`
+	// TTL must be larger than zero, it decreased in every neofs-node
 	TTL                  uint32   `protobuf:"varint,2,opt,name=TTL,proto3" json:"TTL,omitempty"`
 	XXX_NoUnkeyedLiteral struct{} `json:"-"`
 	XXX_unrecognized     []byte   `json:"-"`
@@ -356,8 +368,8 @@ func (m *ListRequest) GetTTL() uint32 {
 	return 0
 }
 
-// ListResponse message to respond about all user containers
 type ListResponse struct {
+	// CID (container id) is list of SHA256 hashes of the container structures
 	CID                  []CID    `protobuf:"bytes,1,rep,name=CID,proto3,customtype=CID" json:"CID"`
 	XXX_NoUnkeyedLiteral struct{} `json:"-"`
 	XXX_unrecognized     []byte   `json:"-"`
@@ -455,12 +467,16 @@ const _ = grpc.SupportPackageIsVersion4
 //
 // 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 request proposes container to the inner ring nodes. They will
+	// accept new container if user has enough deposit. All containers
+	// are accepted by the consensus, therefore it is asynchronous process.
 	Put(ctx context.Context, in *PutRequest, opts ...grpc.CallOption) (*PutResponse, error)
-	// Delete container ... discuss implementation later
+	// Delete container removes it from the inner ring container storage. It
+	// also asynchronous process done by consensus.
 	Delete(ctx context.Context, in *DeleteRequest, opts ...grpc.CallOption) (*DeleteResponse, error)
-	// Get container
+	// Get container returns container instance
 	Get(ctx context.Context, in *GetRequest, opts ...grpc.CallOption) (*GetResponse, error)
+	// List returns all user's containers
 	List(ctx context.Context, in *ListRequest, opts ...grpc.CallOption) (*ListResponse, error)
 }
 
@@ -510,12 +526,16 @@ func (c *serviceClient) List(ctx context.Context, in *ListRequest, opts ...grpc.
 
 // ServiceServer is the server API for Service service.
 type ServiceServer interface {
-	// Create container
+	// Put request proposes container to the inner ring nodes. They will
+	// accept new container if user has enough deposit. All containers
+	// are accepted by the consensus, therefore it is asynchronous process.
 	Put(context.Context, *PutRequest) (*PutResponse, error)
-	// Delete container ... discuss implementation later
+	// Delete container removes it from the inner ring container storage. It
+	// also asynchronous process done by consensus.
 	Delete(context.Context, *DeleteRequest) (*DeleteResponse, error)
-	// Get container
+	// Get container returns container instance
 	Get(context.Context, *GetRequest) (*GetResponse, error)
+	// List returns all user's containers
 	List(context.Context, *ListRequest) (*ListResponse, error)
 }
 
diff --git a/container/service.proto b/container/service.proto
index a3b72ca..72c0899 100644
--- a/container/service.proto
+++ b/container/service.proto
@@ -8,61 +8,87 @@ import "github.com/gogo/protobuf/gogoproto/gogo.proto";
 
 option (gogoproto.stable_marshaler_all) = true;
 
+// Container service provides API for manipulating with the container.
 service Service {
-    // Create container
+    // Put request proposes container to the inner ring nodes. They will
+    // accept new container if user has enough deposit. All containers
+    // are accepted by the consensus, therefore it is asynchronous process.
     rpc Put(PutRequest) returns (PutResponse);
 
-    // Delete container ... discuss implementation later
+    // Delete container removes it from the inner ring container storage. It
+    // also asynchronous process done by consensus.
     rpc Delete(DeleteRequest) returns (DeleteResponse);
 
-    // Get container
+    // Get container returns container instance
     rpc Get(GetRequest) returns (GetResponse);
 
+    // List returns all user's containers
     rpc List(ListRequest) returns (ListResponse);
 }
 
-// NewRequest message to create new container
 message PutRequest {
+    // MessageID is a nonce for uniq container id calculation
     bytes MessageID            = 1 [(gogoproto.customtype) = "MessageID", (gogoproto.nullable) = false];
-    uint64 Capacity            = 2; // not actual size in megabytes, but probability of storage availability
+
+    // Capacity defines amount of data that can be stored in the container (doesn't used for now).
+    uint64 Capacity            = 2;
+
+    // OwnerID is a wallet address
     bytes OwnerID              = 3 [(gogoproto.customtype) = "OwnerID", (gogoproto.nullable) = false];
+
+    // Rules define storage policy for the object inside the container.
     netmap.PlacementRule rules = 4 [(gogoproto.nullable) = false];
+
+    // Signature of the user (owner id)
     bytes Signature            = 5;
+
+    // TTL must be larger than zero, it decreased in every neofs-node
     uint32 TTL                 = 6;
 }
 
-// PutResponse message to respond about container uuid
 message PutResponse {
+    // CID (container id) is a SHA256 hash of the container structure
     bytes CID = 1 [(gogoproto.customtype) = "CID", (gogoproto.nullable) = false];
 }
 
 message DeleteRequest {
+    // CID (container id) is a SHA256 hash of the container structure
     bytes CID       = 1 [(gogoproto.customtype) = "CID", (gogoproto.nullable) = false];
+
+    // TTL must be larger than zero, it decreased in every neofs-node
     uint32 TTL      = 2;
+
+    // Signature of the container owner
     bytes Signature = 3;
 }
 
+// DeleteResponse is empty because delete operation is asynchronous and done
+// via consensus in inner ring nodes
 message DeleteResponse { }
 
 
-// GetRequest message to fetch container placement rules
 message GetRequest {
+    // CID (container id) is a SHA256 hash of the container structure
     bytes CID  = 1 [(gogoproto.customtype) = "CID", (gogoproto.nullable) = false];
+
+    // TTL must be larger than zero, it decreased in every neofs-node
     uint32 TTL = 2;
 }
 
-// GetResponse message with container structure
 message GetResponse {
+    // Container is a structure that contains placement rules and owner id
     container.Container Container = 1;
 }
 
-// ListRequest message to list containers for user
 message ListRequest {
+    // OwnerID is a wallet address
     bytes OwnerID = 1 [(gogoproto.customtype) = "OwnerID", (gogoproto.nullable) = false];
+
+    // TTL must be larger than zero, it decreased in every neofs-node
     uint32 TTL    = 2;
 }
 
-// ListResponse message to respond about all user containers
 message ListResponse {
+    // CID (container id) is list of SHA256 hashes of the container structures
     repeated bytes CID = 1 [(gogoproto.customtype) = "CID", (gogoproto.nullable) = false];
 }
diff --git a/container/types.proto b/container/types.proto
index b05001f..efcaee8 100644
--- a/container/types.proto
+++ b/container/types.proto
@@ -9,8 +9,8 @@ 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];
+    bytes OwnerID              = 1 [(gogoproto.customtype) = "OwnerID", (gogoproto.nullable) = false]; // OwnerID is a wallet address.
+    bytes Salt                 = 2 [(gogoproto.customtype) = "UUID",    (gogoproto.nullable) = false]; // Salt is a nonce for unique container id calculation.
+    uint64 Capacity            = 3; // Capacity defines amount of data that can be stored in the container (doesn't used for now).
+    netmap.PlacementRule Rules = 4 [(gogoproto.nullable) = false]; // Rules define storage policy for the object inside the container.
 }
diff --git a/decimal/decimal.pb.go b/decimal/decimal.pb.go
index e125af4..d2bed7d 100644
--- a/decimal/decimal.pb.go
+++ b/decimal/decimal.pb.go
@@ -23,8 +23,11 @@ var _ = math.Inf
 // proto package needs to be updated.
 const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
 
+// Decimal is a structure used for representation of assets amount
 type Decimal struct {
-	Value                int64    `protobuf:"varint,1,opt,name=Value,proto3" json:"Value,omitempty"`
+	// Value is value number
+	Value int64 `protobuf:"varint,1,opt,name=Value,proto3" json:"Value,omitempty"`
+	// Precision is precision number
 	Precision            uint32   `protobuf:"varint,2,opt,name=Precision,proto3" json:"Precision,omitempty"`
 	XXX_NoUnkeyedLiteral struct{} `json:"-"`
 	XXX_unrecognized     []byte   `json:"-"`
diff --git a/decimal/decimal.proto b/decimal/decimal.proto
index 31bb963..42cf2df 100644
--- a/decimal/decimal.proto
+++ b/decimal/decimal.proto
@@ -6,9 +6,12 @@ import "github.com/gogo/protobuf/gogoproto/gogo.proto";
 
 option (gogoproto.stable_marshaler_all) = true;
 
+// Decimal is a structure used for representation of assets amount
 message Decimal {
     option (gogoproto.goproto_stringer) = false;
 
+    // Value is value number
     int64 Value = 1;
+    // Precision is precision number
     uint32 Precision = 2;
 }
diff --git a/docs/.gitkeep b/docs/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/docs/accounting.md b/docs/accounting.md
new file mode 100644
index 0000000..f08bd52
--- /dev/null
+++ b/docs/accounting.md
@@ -0,0 +1,488 @@
+# Protocol Documentation
+<a name="top"></a>
+
+## Table of Contents
+
+- [accounting/service.proto](#accounting/service.proto)
+ - Services
+    - [Accounting](#accounting.Accounting)
+    
+  - Messages
+    - [BalanceRequest](#accounting.BalanceRequest)
+    - [BalanceResponse](#accounting.BalanceResponse)
+    
+
+- [accounting/types.proto](#accounting/types.proto)
+
+  - Messages
+    - [Account](#accounting.Account)
+    - [Balances](#accounting.Balances)
+    - [ContainerCreateTarget](#accounting.ContainerCreateTarget)
+    - [Lifetime](#accounting.Lifetime)
+    - [LockTarget](#accounting.LockTarget)
+    - [PayIO](#accounting.PayIO)
+    - [Settlement](#accounting.Settlement)
+    - [Settlement.Container](#accounting.Settlement.Container)
+    - [Settlement.Receiver](#accounting.Settlement.Receiver)
+    - [Settlement.Tx](#accounting.Settlement.Tx)
+    - [Tx](#accounting.Tx)
+    - [WithdrawTarget](#accounting.WithdrawTarget)
+    
+
+- [accounting/withdraw.proto](#accounting/withdraw.proto)
+ - Services
+    - [Withdraw](#accounting.Withdraw)
+    
+  - Messages
+    - [DeleteRequest](#accounting.DeleteRequest)
+    - [DeleteResponse](#accounting.DeleteResponse)
+    - [GetRequest](#accounting.GetRequest)
+    - [GetResponse](#accounting.GetResponse)
+    - [Item](#accounting.Item)
+    - [ListRequest](#accounting.ListRequest)
+    - [ListResponse](#accounting.ListResponse)
+    - [PutRequest](#accounting.PutRequest)
+    - [PutResponse](#accounting.PutResponse)
+    
+
+- [Scalar Value Types](#scalar-value-types)
+
+
+
+<a name="accounting/service.proto"></a>
+<p align="right"><a href="#top">Top</a></p>
+
+## accounting/service.proto
+
+
+
+
+<a name="accounting.Accounting"></a>
+
+### Service "accounting.Accounting"
+Accounting is a service that provides access for accounting balance
+information
+
+```
+rpc Balance(BalanceRequest) returns (BalanceResponse);
+
+```
+
+#### Method Balance
+
+Balance returns current balance status of the NeoFS user
+
+| Name | Input | Output |
+| ---- | ----- | ------ |
+| Balance | [BalanceRequest](#accounting.BalanceRequest) | [BalanceResponse](#accounting.BalanceResponse) |
+ <!-- end services -->
+
+
+<a name="accounting.BalanceRequest"></a>
+
+### Message BalanceRequest
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| OwnerID | [bytes](#bytes) |  | OwnerID is a wallet address |
+| TTL | [uint32](#uint32) |  | TTL must be larger than zero, it decreased in every neofs-node |
+
+
+<a name="accounting.BalanceResponse"></a>
+
+### Message BalanceResponse
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| Balance | [decimal.Decimal](#decimal.Decimal) |  | Balance contains current account balance state |
+| LockAccounts | [Account](#accounting.Account) | repeated | LockAccounts contains information about locked funds. Locked funds appear when user pays for storage or withdraw assets. |
+
+ <!-- end messages -->
+
+ <!-- end enums -->
+
+
+
+<a name="accounting/types.proto"></a>
+<p align="right"><a href="#top">Top</a></p>
+
+## accounting/types.proto
+
+
+ <!-- end services -->
+
+
+<a name="accounting.Account"></a>
+
+### Message Account
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| OwnerID | [bytes](#bytes) |  | OwnerID is a wallet address |
+| Address | [string](#string) |  | Address is identifier of accounting record |
+| ParentAddress | [string](#string) |  | ParentAddress is identifier of parent accounting record |
+| ActiveFunds | [decimal.Decimal](#decimal.Decimal) |  | ActiveFunds is amount of active (non locked) funds for account |
+| Lifetime | [Lifetime](#accounting.Lifetime) |  | Lifetime is time until account is valid (used for lock accounts) |
+| LockTarget | [LockTarget](#accounting.LockTarget) |  | LockTarget is the purpose of lock funds (it might be withdraw or payment for storage) |
+| LockAccounts | [Account](#accounting.Account) | repeated | LockAccounts contains child accounts with locked funds |
+
+
+<a name="accounting.Balances"></a>
+
+### Message Balances
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| Accounts | [Account](#accounting.Account) | repeated | Accounts contains multiple account snapshots |
+
+
+<a name="accounting.ContainerCreateTarget"></a>
+
+### Message ContainerCreateTarget
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| CID | [bytes](#bytes) |  | CID is container identifier |
+
+
+<a name="accounting.Lifetime"></a>
+
+### Message Lifetime
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| unit | [Lifetime.Unit](#accounting.Lifetime.Unit) |  | Unit describes how lifetime is measured in account |
+| Value | [int64](#int64) |  | Value describes how long lifetime will be valid |
+
+
+<a name="accounting.LockTarget"></a>
+
+### Message LockTarget
+LockTarget must be one of two options
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| WithdrawTarget | [WithdrawTarget](#accounting.WithdrawTarget) |  | WithdrawTarget used when user requested withdraw |
+| ContainerCreateTarget | [ContainerCreateTarget](#accounting.ContainerCreateTarget) |  | ContainerCreateTarget used when user requested creation of container |
+
+
+<a name="accounting.PayIO"></a>
+
+### Message PayIO
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| BlockID | [uint64](#uint64) |  | BlockID contains id of the NEO block where withdraw or deposit call was invoked |
+| Transactions | [Tx](#accounting.Tx) | repeated | Transactions contains all transactions that founded in block and used for PayIO |
+
+
+<a name="accounting.Settlement"></a>
+
+### Message Settlement
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| Epoch | [uint64](#uint64) |  | Epoch contains an epoch when settlement was accepted |
+| Transactions | [Settlement.Tx](#accounting.Settlement.Tx) | repeated | Transactions is a set of transactions |
+
+
+<a name="accounting.Settlement.Container"></a>
+
+### Message Settlement.Container
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| CID | [bytes](#bytes) |  | CID is container identifier |
+| SGIDs | [bytes](#bytes) | repeated | SGIDs is a set of storage groups that successfully passed the audit |
+
+
+<a name="accounting.Settlement.Receiver"></a>
+
+### Message Settlement.Receiver
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| To | [string](#string) |  | To is the address of funds recipient |
+| Amount | [decimal.Decimal](#decimal.Decimal) |  | Amount is the amount of funds that will be sent |
+
+
+<a name="accounting.Settlement.Tx"></a>
+
+### Message Settlement.Tx
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| From | [string](#string) |  | From is the address of the sender of funds |
+| Container | [Settlement.Container](#accounting.Settlement.Container) |  | Container that successfully had passed the audit |
+| Receivers | [Settlement.Receiver](#accounting.Settlement.Receiver) | repeated | Receivers is a set of addresses of funds recipients |
+
+
+<a name="accounting.Tx"></a>
+
+### Message Tx
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| type | [Tx.Type](#accounting.Tx.Type) |  | Type describes target of transaction |
+| From | [string](#string) |  | From describes sender of funds |
+| To | [string](#string) |  | To describes receiver of funds |
+| Amount | [decimal.Decimal](#decimal.Decimal) |  | Amount describes amount of funds |
+| PublicKeys | [bytes](#bytes) |  | PublicKeys contains public key of sender |
+
+
+<a name="accounting.WithdrawTarget"></a>
+
+### Message WithdrawTarget
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| Cheque | [string](#string) |  | Cheque is a string representation of cheque id |
+
+ <!-- end messages -->
+
+
+<a name="accounting.Lifetime.Unit"></a>
+
+### Lifetime.Unit
+Unit can be Unlimited, based on NeoFS epoch or Neo block
+
+| Name | Number | Description |
+| ---- | ------ | ----------- |
+| Unlimited | 0 |  |
+| NeoFSEpoch | 1 |  |
+| NeoBlock | 2 |  |
+
+
+
+<a name="accounting.Tx.Type"></a>
+
+### Tx.Type
+Type can be withdrawal, payIO or inner
+
+| Name | Number | Description |
+| ---- | ------ | ----------- |
+| Unknown | 0 |  |
+| Withdraw | 1 |  |
+| PayIO | 2 |  |
+| Inner | 3 |  |
+
+
+ <!-- end enums -->
+
+
+
+<a name="accounting/withdraw.proto"></a>
+<p align="right"><a href="#top">Top</a></p>
+
+## accounting/withdraw.proto
+
+
+
+
+<a name="accounting.Withdraw"></a>
+
+### Service "accounting.Withdraw"
+Withdraw is a service that provides withdraw assets operations from the NeoFS
+
+```
+rpc Get(GetRequest) returns (GetResponse);
+rpc Put(PutRequest) returns (PutResponse);
+rpc List(ListRequest) returns (ListResponse);
+rpc Delete(DeleteRequest) returns (DeleteResponse);
+
+```
+
+#### Method Get
+
+Get returns cheque if it was signed by inner ring nodes
+
+| Name | Input | Output |
+| ---- | ----- | ------ |
+| Get | [GetRequest](#accounting.GetRequest) | [GetResponse](#accounting.GetResponse) |
+#### Method Put
+
+Put ask inner ring nodes to sign a cheque for withdraw invoke
+
+| Name | Input | Output |
+| ---- | ----- | ------ |
+| Put | [PutRequest](#accounting.PutRequest) | [PutResponse](#accounting.PutResponse) |
+#### Method List
+
+List shows all user's checks
+
+| Name | Input | Output |
+| ---- | ----- | ------ |
+| List | [ListRequest](#accounting.ListRequest) | [ListResponse](#accounting.ListResponse) |
+#### Method Delete
+
+Delete allows user to remove unused cheque
+
+| Name | Input | Output |
+| ---- | ----- | ------ |
+| Delete | [DeleteRequest](#accounting.DeleteRequest) | [DeleteResponse](#accounting.DeleteResponse) |
+ <!-- end services -->
+
+
+<a name="accounting.DeleteRequest"></a>
+
+### Message DeleteRequest
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| ID | [bytes](#bytes) |  | ID is cheque identifier |
+| OwnerID | [bytes](#bytes) |  | OwnerID is a wallet address |
+| MessageID | [bytes](#bytes) |  | MessageID is a nonce for uniq request (UUIDv4) |
+| Signature | [bytes](#bytes) |  | Signature is a signature of the sent request |
+| TTL | [uint32](#uint32) |  | TTL must be larger than zero, it decreased in every neofs-node |
+
+
+<a name="accounting.DeleteResponse"></a>
+
+### Message DeleteResponse
+DeleteResponse is empty
+
+
+
+<a name="accounting.GetRequest"></a>
+
+### Message GetRequest
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| ID | [bytes](#bytes) |  | ID is cheque identifier |
+| OwnerID | [bytes](#bytes) |  | OwnerID is a wallet address |
+| TTL | [uint32](#uint32) |  | TTL must be larger than zero, it decreased in every neofs-node |
+
+
+<a name="accounting.GetResponse"></a>
+
+### Message GetResponse
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| Withdraw | [Item](#accounting.Item) |  | Item is cheque with meta information |
+
+
+<a name="accounting.Item"></a>
+
+### Message Item
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| ID | [bytes](#bytes) |  | ID is a cheque identifier |
+| OwnerID | [bytes](#bytes) |  | OwnerID is a wallet address |
+| Amount | [decimal.Decimal](#decimal.Decimal) |  | Amount of funds |
+| Height | [uint64](#uint64) |  | Height is the neo blockchain height until the cheque is valid |
+| Payload | [bytes](#bytes) |  | Payload contains cheque representation in bytes |
+
+
+<a name="accounting.ListRequest"></a>
+
+### Message ListRequest
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| OwnerID | [bytes](#bytes) |  | OwnerID is a wallet address |
+| TTL | [uint32](#uint32) |  | TTL must be larger than zero, it decreased in every neofs-node |
+
+
+<a name="accounting.ListResponse"></a>
+
+### Message ListResponse
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| Items | [Item](#accounting.Item) | repeated | Item is a set of cheques with meta information |
+
+
+<a name="accounting.PutRequest"></a>
+
+### Message PutRequest
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| OwnerID | [bytes](#bytes) |  | OwnerID is a wallet address |
+| Amount | [decimal.Decimal](#decimal.Decimal) |  | Amount of funds |
+| Height | [uint64](#uint64) |  | Height is the neo blockchain height until the cheque is valid |
+| MessageID | [bytes](#bytes) |  | MessageID is a nonce for uniq request (UUIDv4) |
+| Signature | [bytes](#bytes) |  | Signature is a signature of the sent request |
+| TTL | [uint32](#uint32) |  | TTL must be larger than zero, it decreased in every neofs-node |
+
+
+<a name="accounting.PutResponse"></a>
+
+### Message PutResponse
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| ID | [bytes](#bytes) |  | ID is cheque identifier |
+
+ <!-- end messages -->
+
+ <!-- end enums -->
+
+
+
+## Scalar Value Types
+
+| .proto Type | Notes | C++ Type | Java Type | Python Type |
+| ----------- | ----- | -------- | --------- | ----------- |
+| <a name="double" /> double |  | double | double | float |
+| <a name="float" /> float |  | float | float | float |
+| <a name="int32" /> int32 | Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint32 instead. | int32 | int | int |
+| <a name="int64" /> int64 | Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint64 instead. | int64 | long | int/long |
+| <a name="uint32" /> uint32 | Uses variable-length encoding. | uint32 | int | int/long |
+| <a name="uint64" /> uint64 | Uses variable-length encoding. | uint64 | long | int/long |
+| <a name="sint32" /> sint32 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s. | int32 | int | int |
+| <a name="sint64" /> sint64 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s. | int64 | long | int/long |
+| <a name="fixed32" /> fixed32 | Always four bytes. More efficient than uint32 if values are often greater than 2^28. | uint32 | int | int |
+| <a name="fixed64" /> fixed64 | Always eight bytes. More efficient than uint64 if values are often greater than 2^56. | uint64 | long | int/long |
+| <a name="sfixed32" /> sfixed32 | Always four bytes. | int32 | int | int |
+| <a name="sfixed64" /> sfixed64 | Always eight bytes. | int64 | long | int/long |
+| <a name="bool" /> bool |  | bool | boolean | boolean |
+| <a name="string" /> string | A string must always contain UTF-8 encoded or 7-bit ASCII text. | string | String | str/unicode |
+| <a name="bytes" /> bytes | May contain any arbitrary sequence of bytes. | string | ByteString | str |
+
diff --git a/docs/bootstrap.md b/docs/bootstrap.md
new file mode 100644
index 0000000..dfada2c
--- /dev/null
+++ b/docs/bootstrap.md
@@ -0,0 +1,132 @@
+# Protocol Documentation
+<a name="top"></a>
+
+## Table of Contents
+
+- [bootstrap/service.proto](#bootstrap/service.proto)
+ - Services
+    - [Bootstrap](#bootstrap.Bootstrap)
+    
+  - Messages
+    - [Request](#bootstrap.Request)
+    
+
+- [bootstrap/types.proto](#bootstrap/types.proto)
+
+  - Messages
+    - [NodeInfo](#bootstrap.NodeInfo)
+    - [SpreadMap](#bootstrap.SpreadMap)
+    
+
+- [Scalar Value Types](#scalar-value-types)
+
+
+
+<a name="bootstrap/service.proto"></a>
+<p align="right"><a href="#top">Top</a></p>
+
+## bootstrap/service.proto
+
+
+
+
+<a name="bootstrap.Bootstrap"></a>
+
+### Service "bootstrap.Bootstrap"
+Bootstrap service allows neofs-node to connect to the network. Node should
+perform at least one bootstrap request in the epoch to stay in the network
+for the next epoch.
+
+```
+rpc Process(Request) returns (SpreadMap);
+
+```
+
+#### Method Process
+
+Process is method that allows to register node in the network and receive actual netmap
+
+| Name | Input | Output |
+| ---- | ----- | ------ |
+| Process | [Request](#bootstrap.Request) | [SpreadMap](#bootstrap.SpreadMap) |
+ <!-- end services -->
+
+
+<a name="bootstrap.Request"></a>
+
+### Message Request
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| type | [int32](#int32) |  | Type is NodeType, can be InnerRingNode (type=1) or StorageNode (type=2) |
+| info | [NodeInfo](#bootstrap.NodeInfo) |  | Info contains information about node |
+| TTL | [uint32](#uint32) |  | TTL must be larger than zero, it decreased in every neofs-node |
+
+ <!-- end messages -->
+
+ <!-- end enums -->
+
+
+
+<a name="bootstrap/types.proto"></a>
+<p align="right"><a href="#top">Top</a></p>
+
+## bootstrap/types.proto
+
+
+ <!-- end services -->
+
+
+<a name="bootstrap.NodeInfo"></a>
+
+### Message NodeInfo
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| Address | [string](#string) |  | Address is a node [multi-address](https://github.com/multiformats/multiaddr) |
+| PubKey | [bytes](#bytes) |  | PubKey is a compressed public key representation in bytes |
+| Options | [string](#string) | repeated | Options is set of node optional information, such as storage capacity, node location, price and etc |
+| Status | [uint64](#uint64) |  | Status is bitmap status of the node |
+
+
+<a name="bootstrap.SpreadMap"></a>
+
+### Message SpreadMap
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| Epoch | [uint64](#uint64) |  | Epoch is current epoch for netmap |
+| NetMap | [NodeInfo](#bootstrap.NodeInfo) | repeated | NetMap is a set of NodeInfos |
+
+ <!-- end messages -->
+
+ <!-- end enums -->
+
+
+
+## Scalar Value Types
+
+| .proto Type | Notes | C++ Type | Java Type | Python Type |
+| ----------- | ----- | -------- | --------- | ----------- |
+| <a name="double" /> double |  | double | double | float |
+| <a name="float" /> float |  | float | float | float |
+| <a name="int32" /> int32 | Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint32 instead. | int32 | int | int |
+| <a name="int64" /> int64 | Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint64 instead. | int64 | long | int/long |
+| <a name="uint32" /> uint32 | Uses variable-length encoding. | uint32 | int | int/long |
+| <a name="uint64" /> uint64 | Uses variable-length encoding. | uint64 | long | int/long |
+| <a name="sint32" /> sint32 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s. | int32 | int | int |
+| <a name="sint64" /> sint64 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s. | int64 | long | int/long |
+| <a name="fixed32" /> fixed32 | Always four bytes. More efficient than uint32 if values are often greater than 2^28. | uint32 | int | int |
+| <a name="fixed64" /> fixed64 | Always eight bytes. More efficient than uint64 if values are often greater than 2^56. | uint64 | long | int/long |
+| <a name="sfixed32" /> sfixed32 | Always four bytes. | int32 | int | int |
+| <a name="sfixed64" /> sfixed64 | Always eight bytes. | int64 | long | int/long |
+| <a name="bool" /> bool |  | bool | boolean | boolean |
+| <a name="string" /> string | A string must always contain UTF-8 encoded or 7-bit ASCII text. | string | String | str/unicode |
+| <a name="bytes" /> bytes | May contain any arbitrary sequence of bytes. | string | ByteString | str |
+
diff --git a/docs/container.md b/docs/container.md
new file mode 100644
index 0000000..5ff0d89
--- /dev/null
+++ b/docs/container.md
@@ -0,0 +1,232 @@
+# Protocol Documentation
+<a name="top"></a>
+
+## Table of Contents
+
+- [container/service.proto](#container/service.proto)
+ - Services
+    - [Service](#container.Service)
+    
+  - Messages
+    - [DeleteRequest](#container.DeleteRequest)
+    - [DeleteResponse](#container.DeleteResponse)
+    - [GetRequest](#container.GetRequest)
+    - [GetResponse](#container.GetResponse)
+    - [ListRequest](#container.ListRequest)
+    - [ListResponse](#container.ListResponse)
+    - [PutRequest](#container.PutRequest)
+    - [PutResponse](#container.PutResponse)
+    
+
+- [container/types.proto](#container/types.proto)
+
+  - Messages
+    - [Container](#container.Container)
+    
+
+- [Scalar Value Types](#scalar-value-types)
+
+
+
+<a name="container/service.proto"></a>
+<p align="right"><a href="#top">Top</a></p>
+
+## container/service.proto
+
+
+
+
+<a name="container.Service"></a>
+
+### Service "container.Service"
+Container service provides API for manipulating with the container.
+
+```
+rpc Put(PutRequest) returns (PutResponse);
+rpc Delete(DeleteRequest) returns (DeleteResponse);
+rpc Get(GetRequest) returns (GetResponse);
+rpc List(ListRequest) returns (ListResponse);
+
+```
+
+#### Method Put
+
+Put request proposes container to the inner ring nodes. They will
+accept new container if user has enough deposit. All containers
+are accepted by the consensus, therefore it is asynchronous process.
+
+| Name | Input | Output |
+| ---- | ----- | ------ |
+| Put | [PutRequest](#container.PutRequest) | [PutResponse](#container.PutResponse) |
+#### Method Delete
+
+Delete container removes it from the inner ring container storage. It
+also asynchronous process done by consensus.
+
+| Name | Input | Output |
+| ---- | ----- | ------ |
+| Delete | [DeleteRequest](#container.DeleteRequest) | [DeleteResponse](#container.DeleteResponse) |
+#### Method Get
+
+Get container returns container instance
+
+| Name | Input | Output |
+| ---- | ----- | ------ |
+| Get | [GetRequest](#container.GetRequest) | [GetResponse](#container.GetResponse) |
+#### Method List
+
+List returns all user's containers
+
+| Name | Input | Output |
+| ---- | ----- | ------ |
+| List | [ListRequest](#container.ListRequest) | [ListResponse](#container.ListResponse) |
+ <!-- end services -->
+
+
+<a name="container.DeleteRequest"></a>
+
+### Message DeleteRequest
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| CID | [bytes](#bytes) |  | CID (container id) is a SHA256 hash of the container structure |
+| TTL | [uint32](#uint32) |  | TTL must be larger than zero, it decreased in every neofs-node |
+| Signature | [bytes](#bytes) |  | Signature of the container owner |
+
+
+<a name="container.DeleteResponse"></a>
+
+### Message DeleteResponse
+DeleteResponse is empty because delete operation is asynchronous and done
+via consensus in inner ring nodes
+
+
+
+<a name="container.GetRequest"></a>
+
+### Message GetRequest
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| CID | [bytes](#bytes) |  | CID (container id) is a SHA256 hash of the container structure |
+| TTL | [uint32](#uint32) |  | TTL must be larger than zero, it decreased in every neofs-node |
+
+
+<a name="container.GetResponse"></a>
+
+### Message GetResponse
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| Container | [Container](#container.Container) |  | Container is a structure that contains placement rules and owner id |
+
+
+<a name="container.ListRequest"></a>
+
+### Message ListRequest
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| OwnerID | [bytes](#bytes) |  | OwnerID is a wallet address |
+| TTL | [uint32](#uint32) |  | TTL must be larger than zero, it decreased in every neofs-node |
+
+
+<a name="container.ListResponse"></a>
+
+### Message ListResponse
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| CID | [bytes](#bytes) | repeated | CID (container id) is list of SHA256 hashes of the container structures |
+
+
+<a name="container.PutRequest"></a>
+
+### Message PutRequest
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| MessageID | [bytes](#bytes) |  | MessageID is a nonce for uniq container id calculation |
+| Capacity | [uint64](#uint64) |  | Capacity defines amount of data that can be stored in the container (doesn't used for now). |
+| OwnerID | [bytes](#bytes) |  | OwnerID is a wallet address |
+| rules | [netmap.PlacementRule](#netmap.PlacementRule) |  | Rules define storage policy for the object inside the container. |
+| Signature | [bytes](#bytes) |  | Signature of the user (owner id) |
+| TTL | [uint32](#uint32) |  | TTL must be larger than zero, it decreased in every neofs-node |
+
+
+<a name="container.PutResponse"></a>
+
+### Message PutResponse
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| CID | [bytes](#bytes) |  | CID (container id) is a SHA256 hash of the container structure |
+
+ <!-- end messages -->
+
+ <!-- end enums -->
+
+
+
+<a name="container/types.proto"></a>
+<p align="right"><a href="#top">Top</a></p>
+
+## container/types.proto
+
+
+ <!-- end services -->
+
+
+<a name="container.Container"></a>
+
+### Message Container
+The Container service definition.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| OwnerID | [bytes](#bytes) |  | OwnerID is a wallet address. |
+| Salt | [bytes](#bytes) |  | Salt is a nonce for unique container id calculation. |
+| Capacity | [uint64](#uint64) |  | Capacity defines amount of data that can be stored in the container (doesn't used for now). |
+| Rules | [netmap.PlacementRule](#netmap.PlacementRule) |  | Rules define storage policy for the object inside the container. |
+
+ <!-- end messages -->
+
+ <!-- end enums -->
+
+
+
+## Scalar Value Types
+
+| .proto Type | Notes | C++ Type | Java Type | Python Type |
+| ----------- | ----- | -------- | --------- | ----------- |
+| <a name="double" /> double |  | double | double | float |
+| <a name="float" /> float |  | float | float | float |
+| <a name="int32" /> int32 | Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint32 instead. | int32 | int | int |
+| <a name="int64" /> int64 | Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint64 instead. | int64 | long | int/long |
+| <a name="uint32" /> uint32 | Uses variable-length encoding. | uint32 | int | int/long |
+| <a name="uint64" /> uint64 | Uses variable-length encoding. | uint64 | long | int/long |
+| <a name="sint32" /> sint32 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s. | int32 | int | int |
+| <a name="sint64" /> sint64 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s. | int64 | long | int/long |
+| <a name="fixed32" /> fixed32 | Always four bytes. More efficient than uint32 if values are often greater than 2^28. | uint32 | int | int |
+| <a name="fixed64" /> fixed64 | Always eight bytes. More efficient than uint64 if values are often greater than 2^56. | uint64 | long | int/long |
+| <a name="sfixed32" /> sfixed32 | Always four bytes. | int32 | int | int |
+| <a name="sfixed64" /> sfixed64 | Always eight bytes. | int64 | long | int/long |
+| <a name="bool" /> bool |  | bool | boolean | boolean |
+| <a name="string" /> string | A string must always contain UTF-8 encoded or 7-bit ASCII text. | string | String | str/unicode |
+| <a name="bytes" /> bytes | May contain any arbitrary sequence of bytes. | string | ByteString | str |
+
diff --git a/docs/decimal.md b/docs/decimal.md
new file mode 100644
index 0000000..62acb86
--- /dev/null
+++ b/docs/decimal.md
@@ -0,0 +1,61 @@
+# Protocol Documentation
+<a name="top"></a>
+
+## Table of Contents
+
+- [decimal/decimal.proto](#decimal/decimal.proto)
+
+  - Messages
+    - [Decimal](#decimal.Decimal)
+    
+
+- [Scalar Value Types](#scalar-value-types)
+
+
+
+<a name="decimal/decimal.proto"></a>
+<p align="right"><a href="#top">Top</a></p>
+
+## decimal/decimal.proto
+
+
+ <!-- end services -->
+
+
+<a name="decimal.Decimal"></a>
+
+### Message Decimal
+Decimal is a structure used for representation of assets amount
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| Value | [int64](#int64) |  | Value is value number |
+| Precision | [uint32](#uint32) |  | Precision is precision number |
+
+ <!-- end messages -->
+
+ <!-- end enums -->
+
+
+
+## Scalar Value Types
+
+| .proto Type | Notes | C++ Type | Java Type | Python Type |
+| ----------- | ----- | -------- | --------- | ----------- |
+| <a name="double" /> double |  | double | double | float |
+| <a name="float" /> float |  | float | float | float |
+| <a name="int32" /> int32 | Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint32 instead. | int32 | int | int |
+| <a name="int64" /> int64 | Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint64 instead. | int64 | long | int/long |
+| <a name="uint32" /> uint32 | Uses variable-length encoding. | uint32 | int | int/long |
+| <a name="uint64" /> uint64 | Uses variable-length encoding. | uint64 | long | int/long |
+| <a name="sint32" /> sint32 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s. | int32 | int | int |
+| <a name="sint64" /> sint64 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s. | int64 | long | int/long |
+| <a name="fixed32" /> fixed32 | Always four bytes. More efficient than uint32 if values are often greater than 2^28. | uint32 | int | int |
+| <a name="fixed64" /> fixed64 | Always eight bytes. More efficient than uint64 if values are often greater than 2^56. | uint64 | long | int/long |
+| <a name="sfixed32" /> sfixed32 | Always four bytes. | int32 | int | int |
+| <a name="sfixed64" /> sfixed64 | Always eight bytes. | int64 | long | int/long |
+| <a name="bool" /> bool |  | bool | boolean | boolean |
+| <a name="string" /> string | A string must always contain UTF-8 encoded or 7-bit ASCII text. | string | String | str/unicode |
+| <a name="bytes" /> bytes | May contain any arbitrary sequence of bytes. | string | ByteString | str |
+
diff --git a/docs/object.md b/docs/object.md
new file mode 100644
index 0000000..5ba1845
--- /dev/null
+++ b/docs/object.md
@@ -0,0 +1,566 @@
+# Protocol Documentation
+<a name="top"></a>
+
+## Table of Contents
+
+- [object/service.proto](#object/service.proto)
+ - Services
+    - [Service](#object.Service)
+    
+  - Messages
+    - [DeleteRequest](#object.DeleteRequest)
+    - [DeleteResponse](#object.DeleteResponse)
+    - [GetRangeHashRequest](#object.GetRangeHashRequest)
+    - [GetRangeHashResponse](#object.GetRangeHashResponse)
+    - [GetRangeRequest](#object.GetRangeRequest)
+    - [GetRangeResponse](#object.GetRangeResponse)
+    - [GetRequest](#object.GetRequest)
+    - [GetResponse](#object.GetResponse)
+    - [HeadRequest](#object.HeadRequest)
+    - [HeadResponse](#object.HeadResponse)
+    - [PutRequest](#object.PutRequest)
+    - [PutRequest.PutHeader](#object.PutRequest.PutHeader)
+    - [PutResponse](#object.PutResponse)
+    - [SearchRequest](#object.SearchRequest)
+    - [SearchResponse](#object.SearchResponse)
+    
+
+- [object/types.proto](#object/types.proto)
+
+  - Messages
+    - [CreationPoint](#object.CreationPoint)
+    - [Header](#object.Header)
+    - [IntegrityHeader](#object.IntegrityHeader)
+    - [Link](#object.Link)
+    - [Object](#object.Object)
+    - [Range](#object.Range)
+    - [StorageGroup](#object.StorageGroup)
+    - [StorageGroup.Lifetime](#object.StorageGroup.Lifetime)
+    - [SystemHeader](#object.SystemHeader)
+    - [Tombstone](#object.Tombstone)
+    - [Transform](#object.Transform)
+    - [UserHeader](#object.UserHeader)
+    
+
+- [Scalar Value Types](#scalar-value-types)
+
+
+
+<a name="object/service.proto"></a>
+<p align="right"><a href="#top">Top</a></p>
+
+## object/service.proto
+
+
+
+
+<a name="object.Service"></a>
+
+### Service "object.Service"
+Object service provides API for manipulating with the object.
+
+```
+rpc Get(GetRequest) returns (stream GetResponse);
+rpc Put(stream PutRequest) returns (PutResponse);
+rpc Delete(DeleteRequest) returns (DeleteResponse);
+rpc Head(HeadRequest) returns (HeadResponse);
+rpc Search(SearchRequest) returns (SearchResponse);
+rpc GetRange(GetRangeRequest) returns (GetRangeResponse);
+rpc GetRangeHash(GetRangeHashRequest) returns (GetRangeHashResponse);
+
+```
+
+#### Method Get
+
+Get the object from container. Response uses gRPC stream. First response
+message carry object of requested address. Chunk messages are parts of
+the object's payload if it is needed. All messages except first carry
+chunks. Requested object can be restored by concatenation of object
+message payload and all chunks keeping receiving order.
+
+| Name | Input | Output |
+| ---- | ----- | ------ |
+| Get | [GetRequest](#object.GetRequest) | [GetResponse](#object.GetResponse) |
+#### Method Put
+
+Put the object into container. Request uses gRPC stream. First message
+SHOULD BE type of PutHeader. Container id and Owner id of object SHOULD
+BE set. Session token SHOULD BE obtained before put operation (see
+session package). Chunk messages considered by server as part of object
+payload. All messages except first SHOULD BE chunks. Chunk messages
+SHOULD BE sent in direct order of fragmentation.
+
+| Name | Input | Output |
+| ---- | ----- | ------ |
+| Put | [PutRequest](#object.PutRequest) | [PutResponse](#object.PutResponse) |
+#### Method Delete
+
+Delete the object from a container
+
+| Name | Input | Output |
+| ---- | ----- | ------ |
+| Delete | [DeleteRequest](#object.DeleteRequest) | [DeleteResponse](#object.DeleteResponse) |
+#### Method Head
+
+Head returns the object without data payload. Object in the
+response has system header only. If full headers flag is set, extended
+headers are also present.
+
+| Name | Input | Output |
+| ---- | ----- | ------ |
+| Head | [HeadRequest](#object.HeadRequest) | [HeadResponse](#object.HeadResponse) |
+#### Method Search
+
+Search objects in container. Version of query language format SHOULD BE
+set to 1. Search query represented in serialized format (see query
+package).
+
+| Name | Input | Output |
+| ---- | ----- | ------ |
+| Search | [SearchRequest](#object.SearchRequest) | [SearchResponse](#object.SearchResponse) |
+#### Method GetRange
+
+GetRange of data payload. Ranges are set of pairs (offset, length).
+Fragments order in response corresponds to ranges order in request.
+
+| Name | Input | Output |
+| ---- | ----- | ------ |
+| GetRange | [GetRangeRequest](#object.GetRangeRequest) | [GetRangeResponse](#object.GetRangeResponse) |
+#### Method GetRangeHash
+
+GetRangeHash returns homomorphic hash of object payload range after XOR
+operation. Ranges are set of pairs (offset, length). Hashes order in
+response corresponds to ranges order in request. Homomorphic hash is
+calculated for XORed data.
+
+| Name | Input | Output |
+| ---- | ----- | ------ |
+| GetRangeHash | [GetRangeHashRequest](#object.GetRangeHashRequest) | [GetRangeHashResponse](#object.GetRangeHashResponse) |
+ <!-- end services -->
+
+
+<a name="object.DeleteRequest"></a>
+
+### Message DeleteRequest
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| Epoch | [uint64](#uint64) |  | Epoch is set by user to 0, node set epoch to the actual value |
+| Address | [refs.Address](#refs.Address) |  | Address of object (container id + object id) |
+| OwnerID | [bytes](#bytes) |  | OwnerID is a wallet address |
+| TTL | [uint32](#uint32) |  | TTL must be larger than zero, it decreased in every neofs-node |
+| Token | [session.Token](#session.Token) |  | Token with session public key and user's signature |
+
+
+<a name="object.DeleteResponse"></a>
+
+### Message DeleteResponse
+DeleteResponse is empty because we cannot guarantee permanent object removal
+in distributed system.
+
+
+
+<a name="object.GetRangeHashRequest"></a>
+
+### Message GetRangeHashRequest
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| Epoch | [uint64](#uint64) |  | Epoch is set by user to 0, node set epoch to the actual value |
+| Address | [refs.Address](#refs.Address) |  | Address of object (container id + object id) |
+| Ranges | [Range](#object.Range) | repeated | Ranges of object's payload to calculate homomorphic hash |
+| Salt | [bytes](#bytes) |  | Salt is used to XOR object's payload ranges before hashing, it can be nil |
+| TTL | [uint32](#uint32) |  | TTL must be larger than zero, it decreased in every neofs-node |
+
+
+<a name="object.GetRangeHashResponse"></a>
+
+### Message GetRangeHashResponse
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| Hashes | [bytes](#bytes) | repeated | Homomorphic hashes of all ranges |
+
+
+<a name="object.GetRangeRequest"></a>
+
+### Message GetRangeRequest
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| Epoch | [uint64](#uint64) |  | Epoch is set by user to 0, node set epoch to the actual value |
+| Address | [refs.Address](#refs.Address) |  | Address of object (container id + object id) |
+| Ranges | [Range](#object.Range) | repeated | Ranges of object's payload to return |
+| TTL | [uint32](#uint32) |  | TTL must be larger than zero, it decreased in every neofs-node |
+
+
+<a name="object.GetRangeResponse"></a>
+
+### Message GetRangeResponse
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| Fragments | [bytes](#bytes) | repeated | Fragments of object's payload |
+
+
+<a name="object.GetRequest"></a>
+
+### Message GetRequest
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| Epoch | [uint64](#uint64) |  | Epoch is set by user to 0, node set epoch to the actual value |
+| Address | [refs.Address](#refs.Address) |  | Address of object (container id + object id) |
+| TTL | [uint32](#uint32) |  | TTL must be larger than zero, it decreased in every neofs-node |
+
+
+<a name="object.GetResponse"></a>
+
+### Message GetResponse
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| object | [Object](#object.Object) |  | Object header and some payload |
+| Chunk | [bytes](#bytes) |  | Chunk of remaining payload |
+
+
+<a name="object.HeadRequest"></a>
+
+### Message HeadRequest
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| Epoch | [uint64](#uint64) |  | Epoch is set by user to 0, node set epoch to the actual value |
+| Address | [refs.Address](#refs.Address) |  | Address of object (container id + object id) |
+| FullHeaders | [bool](#bool) |  | FullHeaders can be set true for extended headers in the object |
+| TTL | [uint32](#uint32) |  | TTL must be larger than zero, it decreased in every neofs-node |
+
+
+<a name="object.HeadResponse"></a>
+
+### Message HeadResponse
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| Object | [Object](#object.Object) |  | Object without payload |
+
+
+<a name="object.PutRequest"></a>
+
+### Message PutRequest
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| Header | [PutRequest.PutHeader](#object.PutRequest.PutHeader) |  | Header should be the first message in the stream |
+| Chunk | [bytes](#bytes) |  | Chunk should be a remaining message in stream should be chunks |
+
+
+<a name="object.PutRequest.PutHeader"></a>
+
+### Message PutRequest.PutHeader
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| Epoch | [uint64](#uint64) |  | Epoch is set by user to 0, node set epoch to the actual value |
+| Object | [Object](#object.Object) |  | Object with at least container id and owner id fields |
+| TTL | [uint32](#uint32) |  | TTL must be larger than zero, it decreased in every neofs-node |
+| Token | [session.Token](#session.Token) |  | Token with session public key and user's signature |
+
+
+<a name="object.PutResponse"></a>
+
+### Message PutResponse
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| Address | [refs.Address](#refs.Address) |  | Address of object (container id + object id) |
+
+
+<a name="object.SearchRequest"></a>
+
+### Message SearchRequest
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| Epoch | [uint64](#uint64) |  | Epoch is set by user to 0, node set epoch to the actual value |
+| Version | [uint32](#uint32) |  | Version of search query format |
+| ContainerID | [bytes](#bytes) |  | ContainerID for searching the object |
+| Query | [bytes](#bytes) |  | Query in the binary serialized format |
+| TTL | [uint32](#uint32) |  | TTL must be larger than zero, it decreased in every neofs-node |
+
+
+<a name="object.SearchResponse"></a>
+
+### Message SearchResponse
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| Addresses | [refs.Address](#refs.Address) | repeated | Addresses of found objects |
+
+ <!-- end messages -->
+
+ <!-- end enums -->
+
+
+
+<a name="object/types.proto"></a>
+<p align="right"><a href="#top">Top</a></p>
+
+## object/types.proto
+
+
+ <!-- end services -->
+
+
+<a name="object.CreationPoint"></a>
+
+### Message CreationPoint
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| UnixTime | [int64](#int64) |  | Date of creation in unixtime format |
+| Epoch | [uint64](#uint64) |  | Date of creation in NeoFS epochs |
+
+
+<a name="object.Header"></a>
+
+### Message Header
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| Link | [Link](#object.Link) |  | Link to other objects |
+| Redirect | [refs.Address](#refs.Address) |  | RedirectNot used yet |
+| UserHeader | [UserHeader](#object.UserHeader) |  | UserHeader defined by user |
+| Transform | [Transform](#object.Transform) |  | Transform defines transform operation (e.g. payload split) |
+| Tombstone | [Tombstone](#object.Tombstone) |  | Tombstone header that set up in deleted objects |
+| Verify | [session.VerificationHeader](#session.VerificationHeader) |  | Verify header that contains session public key and user's signature |
+| HomoHash | [bytes](#bytes) |  | Homomorphic hash of original object payload |
+| PayloadChecksum | [bytes](#bytes) |  | PayloadChecksum of actual object's payload |
+| Integrity | [IntegrityHeader](#object.IntegrityHeader) |  | Integrity header with checksum of all above headers in the object |
+| StorageGroup | [StorageGroup](#object.StorageGroup) |  | StorageGroup contains meta information for the data audit |
+
+
+<a name="object.IntegrityHeader"></a>
+
+### Message IntegrityHeader
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| HeadersChecksum | [bytes](#bytes) |  | Checksum of all above headers in the object |
+| ChecksumSignature | [bytes](#bytes) |  | User's signature of checksum to verify if it is correct |
+
+
+<a name="object.Link"></a>
+
+### Message Link
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| type | [Link.Type](#object.Link.Type) |  | Link type |
+| ID | [bytes](#bytes) |  | Object id |
+
+
+<a name="object.Object"></a>
+
+### Message Object
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| SystemHeader | [SystemHeader](#object.SystemHeader) |  | System header |
+| Headers | [Header](#object.Header) | repeated | Extended headers |
+| Payload | [bytes](#bytes) |  | Object's payload |
+
+
+<a name="object.Range"></a>
+
+### Message Range
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| Offset | [uint64](#uint64) |  | Offset of the data range |
+| Length | [uint64](#uint64) |  | Length of the data range |
+
+
+<a name="object.StorageGroup"></a>
+
+### Message StorageGroup
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| ValidationDataSize | [uint64](#uint64) |  | Size of the all object's payloads included into storage group |
+| ValidationHash | [bytes](#bytes) |  | Homomorphic hash of all object's payloads included into storage group |
+| lifetime | [StorageGroup.Lifetime](#object.StorageGroup.Lifetime) |  | Time until storage group is valid |
+
+
+<a name="object.StorageGroup.Lifetime"></a>
+
+### Message StorageGroup.Lifetime
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| unit | [StorageGroup.Lifetime.Unit](#object.StorageGroup.Lifetime.Unit) |  | Lifetime type |
+| Value | [int64](#int64) |  | Lifetime value |
+
+
+<a name="object.SystemHeader"></a>
+
+### Message SystemHeader
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| Version | [uint64](#uint64) |  | Version of the object structure |
+| PayloadLength | [uint64](#uint64) |  | Object payload length |
+| ID | [bytes](#bytes) |  | ObjectID is a UUID |
+| OwnerID | [bytes](#bytes) |  | OwnerID is a wallet address |
+| CID | [bytes](#bytes) |  | ContainerID is a SHA256 hash of the container structure |
+| CreatedAt | [CreationPoint](#object.CreationPoint) |  | Timestamp of object creation |
+
+
+<a name="object.Tombstone"></a>
+
+### Message Tombstone
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| Epoch | [uint64](#uint64) |  | Epoch when tombstone was created |
+
+
+<a name="object.Transform"></a>
+
+### Message Transform
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| type | [Transform.Type](#object.Transform.Type) |  | Type of object transformation |
+
+
+<a name="object.UserHeader"></a>
+
+### Message UserHeader
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| Key | [string](#string) |  | Key of the user's header |
+| Value | [string](#string) |  | Value of the user's header |
+
+ <!-- end messages -->
+
+
+<a name="object.Link.Type"></a>
+
+### Link.Type
+
+
+| Name | Number | Description |
+| ---- | ------ | ----------- |
+| Unknown | 0 |  |
+| Parent | 1 | Parent object created during object transformation |
+| Previous | 2 | Previous object in the linked list created during object transformation |
+| Next | 3 | Next object in the linked list created during object transformation |
+| Child | 4 | Child object created during object transformation |
+| StorageGroup | 5 | Object that included into this storage group |
+
+
+
+<a name="object.StorageGroup.Lifetime.Unit"></a>
+
+### StorageGroup.Lifetime.Unit
+
+
+| Name | Number | Description |
+| ---- | ------ | ----------- |
+| Unlimited | 0 | Storage group always valid |
+| NeoFSEpoch | 1 | Storage group is valid until lifetime NeoFS epoch |
+| UnixTime | 2 | Storage group is valid until lifetime unix timestamp |
+
+
+
+<a name="object.Transform.Type"></a>
+
+### Transform.Type
+
+
+| Name | Number | Description |
+| ---- | ------ | ----------- |
+| Unknown | 0 |  |
+| Split | 1 | Object created after payload split |
+| Sign | 2 | Object created after re-signing (doesn't used) |
+| Mould | 3 | Object created after filling missing headers in the object |
+
+
+ <!-- end enums -->
+
+
+
+## Scalar Value Types
+
+| .proto Type | Notes | C++ Type | Java Type | Python Type |
+| ----------- | ----- | -------- | --------- | ----------- |
+| <a name="double" /> double |  | double | double | float |
+| <a name="float" /> float |  | float | float | float |
+| <a name="int32" /> int32 | Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint32 instead. | int32 | int | int |
+| <a name="int64" /> int64 | Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint64 instead. | int64 | long | int/long |
+| <a name="uint32" /> uint32 | Uses variable-length encoding. | uint32 | int | int/long |
+| <a name="uint64" /> uint64 | Uses variable-length encoding. | uint64 | long | int/long |
+| <a name="sint32" /> sint32 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s. | int32 | int | int |
+| <a name="sint64" /> sint64 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s. | int64 | long | int/long |
+| <a name="fixed32" /> fixed32 | Always four bytes. More efficient than uint32 if values are often greater than 2^28. | uint32 | int | int |
+| <a name="fixed64" /> fixed64 | Always eight bytes. More efficient than uint64 if values are often greater than 2^56. | uint64 | long | int/long |
+| <a name="sfixed32" /> sfixed32 | Always four bytes. | int32 | int | int |
+| <a name="sfixed64" /> sfixed64 | Always eight bytes. | int64 | long | int/long |
+| <a name="bool" /> bool |  | bool | boolean | boolean |
+| <a name="string" /> string | A string must always contain UTF-8 encoded or 7-bit ASCII text. | string | String | str/unicode |
+| <a name="bytes" /> bytes | May contain any arbitrary sequence of bytes. | string | ByteString | str |
+
diff --git a/docs/query.md b/docs/query.md
new file mode 100644
index 0000000..9deb2c1
--- /dev/null
+++ b/docs/query.md
@@ -0,0 +1,86 @@
+# Protocol Documentation
+<a name="top"></a>
+
+## Table of Contents
+
+- [query/types.proto](#query/types.proto)
+
+  - Messages
+    - [Filter](#query.Filter)
+    - [Query](#query.Query)
+    
+
+- [Scalar Value Types](#scalar-value-types)
+
+
+
+<a name="query/types.proto"></a>
+<p align="right"><a href="#top">Top</a></p>
+
+## query/types.proto
+
+
+ <!-- end services -->
+
+
+<a name="query.Filter"></a>
+
+### Message Filter
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| type | [Filter.Type](#query.Filter.Type) |  | Type of filter |
+| Name | [string](#string) |  | Name of field that should be filtered |
+| Value | [string](#string) |  | Value that should be used for filter |
+
+
+<a name="query.Query"></a>
+
+### Message Query
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| Filters | [Filter](#query.Filter) | repeated | Filters is set of filters, should not be empty |
+
+ <!-- end messages -->
+
+
+<a name="query.Filter.Type"></a>
+
+### Filter.Type
+Type can be Exact or Regex
+
+| Name | Number | Description |
+| ---- | ------ | ----------- |
+| Exact | 0 |  |
+| Regex | 1 |  |
+
+
+ <!-- end enums -->
+
+
+
+## Scalar Value Types
+
+| .proto Type | Notes | C++ Type | Java Type | Python Type |
+| ----------- | ----- | -------- | --------- | ----------- |
+| <a name="double" /> double |  | double | double | float |
+| <a name="float" /> float |  | float | float | float |
+| <a name="int32" /> int32 | Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint32 instead. | int32 | int | int |
+| <a name="int64" /> int64 | Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint64 instead. | int64 | long | int/long |
+| <a name="uint32" /> uint32 | Uses variable-length encoding. | uint32 | int | int/long |
+| <a name="uint64" /> uint64 | Uses variable-length encoding. | uint64 | long | int/long |
+| <a name="sint32" /> sint32 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s. | int32 | int | int |
+| <a name="sint64" /> sint64 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s. | int64 | long | int/long |
+| <a name="fixed32" /> fixed32 | Always four bytes. More efficient than uint32 if values are often greater than 2^28. | uint32 | int | int |
+| <a name="fixed64" /> fixed64 | Always eight bytes. More efficient than uint64 if values are often greater than 2^56. | uint64 | long | int/long |
+| <a name="sfixed32" /> sfixed32 | Always four bytes. | int32 | int | int |
+| <a name="sfixed64" /> sfixed64 | Always eight bytes. | int64 | long | int/long |
+| <a name="bool" /> bool |  | bool | boolean | boolean |
+| <a name="string" /> string | A string must always contain UTF-8 encoded or 7-bit ASCII text. | string | String | str/unicode |
+| <a name="bytes" /> bytes | May contain any arbitrary sequence of bytes. | string | ByteString | str |
+
diff --git a/docs/refs.md b/docs/refs.md
new file mode 100644
index 0000000..c3051ab
--- /dev/null
+++ b/docs/refs.md
@@ -0,0 +1,61 @@
+# Protocol Documentation
+<a name="top"></a>
+
+## Table of Contents
+
+- [refs/types.proto](#refs/types.proto)
+
+  - Messages
+    - [Address](#refs.Address)
+    
+
+- [Scalar Value Types](#scalar-value-types)
+
+
+
+<a name="refs/types.proto"></a>
+<p align="right"><a href="#top">Top</a></p>
+
+## refs/types.proto
+
+
+ <!-- end services -->
+
+
+<a name="refs.Address"></a>
+
+### Message Address
+Address of object (container id + object id)
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| ObjectID | [bytes](#bytes) |  | ObjectID is an object identifier |
+| CID | [bytes](#bytes) |  | CID is container identifier |
+
+ <!-- end messages -->
+
+ <!-- end enums -->
+
+
+
+## Scalar Value Types
+
+| .proto Type | Notes | C++ Type | Java Type | Python Type |
+| ----------- | ----- | -------- | --------- | ----------- |
+| <a name="double" /> double |  | double | double | float |
+| <a name="float" /> float |  | float | float | float |
+| <a name="int32" /> int32 | Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint32 instead. | int32 | int | int |
+| <a name="int64" /> int64 | Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint64 instead. | int64 | long | int/long |
+| <a name="uint32" /> uint32 | Uses variable-length encoding. | uint32 | int | int/long |
+| <a name="uint64" /> uint64 | Uses variable-length encoding. | uint64 | long | int/long |
+| <a name="sint32" /> sint32 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s. | int32 | int | int |
+| <a name="sint64" /> sint64 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s. | int64 | long | int/long |
+| <a name="fixed32" /> fixed32 | Always four bytes. More efficient than uint32 if values are often greater than 2^28. | uint32 | int | int |
+| <a name="fixed64" /> fixed64 | Always eight bytes. More efficient than uint64 if values are often greater than 2^56. | uint64 | long | int/long |
+| <a name="sfixed32" /> sfixed32 | Always four bytes. | int32 | int | int |
+| <a name="sfixed64" /> sfixed64 | Always eight bytes. | int64 | long | int/long |
+| <a name="bool" /> bool |  | bool | boolean | boolean |
+| <a name="string" /> string | A string must always contain UTF-8 encoded or 7-bit ASCII text. | string | String | str/unicode |
+| <a name="bytes" /> bytes | May contain any arbitrary sequence of bytes. | string | ByteString | str |
+
diff --git a/docs/session.md b/docs/session.md
new file mode 100644
index 0000000..8ea703e
--- /dev/null
+++ b/docs/session.md
@@ -0,0 +1,149 @@
+# Protocol Documentation
+<a name="top"></a>
+
+## Table of Contents
+
+- [session/service.proto](#session/service.proto)
+ - Services
+    - [Session](#session.Session)
+    
+  - Messages
+    - [CreateRequest](#session.CreateRequest)
+    - [CreateResponse](#session.CreateResponse)
+    
+
+- [session/types.proto](#session/types.proto)
+
+  - Messages
+    - [Token](#session.Token)
+    - [VerificationHeader](#session.VerificationHeader)
+    
+
+- [Scalar Value Types](#scalar-value-types)
+
+
+
+<a name="session/service.proto"></a>
+<p align="right"><a href="#top">Top</a></p>
+
+## session/service.proto
+
+
+
+
+<a name="session.Session"></a>
+
+### Service "session.Session"
+Open a trusted session to manipulate an object. In order to put or
+delete object client have to obtain session token with trusted node.
+Trusted node will modify client's object (add missing headers, checksums,
+homomorphic hash) and sign id with session key. Session is established
+during 4-step handshake in one gRPC stream
+
+```
+rpc Create(stream CreateRequest) returns (stream CreateResponse);
+
+```
+
+#### Method Create
+
+
+
+| Name | Input | Output |
+| ---- | ----- | ------ |
+| Create | [CreateRequest](#session.CreateRequest) | [CreateResponse](#session.CreateResponse) |
+ <!-- end services -->
+
+
+<a name="session.CreateRequest"></a>
+
+### Message CreateRequest
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| Init | [Token](#session.Token) |  | Message to init session opening. Carry: owner of manipulation object; ID of manipulation object; token lifetime bounds. |
+| Signed | [Token](#session.Token) |  | Signed Init message response (Unsigned) from server with user private key |
+
+
+<a name="session.CreateResponse"></a>
+
+### Message CreateResponse
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| Unsigned | [Token](#session.Token) |  | Unsigned token with token ID and session public key generated on server side |
+| Result | [Token](#session.Token) |  | Resulting token which can be used for object placing through an trusted intermediary |
+
+ <!-- end messages -->
+
+ <!-- end enums -->
+
+
+
+<a name="session/types.proto"></a>
+<p align="right"><a href="#top">Top</a></p>
+
+## session/types.proto
+
+
+ <!-- end services -->
+
+
+<a name="session.Token"></a>
+
+### Message Token
+User token granting rights for object manipulation
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| Header | [VerificationHeader](#session.VerificationHeader) |  | Header carries verification data of session key |
+| OwnerID | [bytes](#bytes) |  | Owner of manipulation object |
+| FirstEpoch | [uint64](#uint64) |  | Initial epoch of token lifetime |
+| LastEpoch | [uint64](#uint64) |  | Last epoch of token lifetime |
+| ObjectID | [bytes](#bytes) | repeated | ID of manipulation object |
+| Signature | [bytes](#bytes) |  | Token signature. Signed by owner of manipulation object |
+| ID | [bytes](#bytes) |  | Token ID (UUID) |
+
+
+<a name="session.VerificationHeader"></a>
+
+### Message VerificationHeader
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| PublicKey | [bytes](#bytes) |  | Session public key |
+| KeySignature | [bytes](#bytes) |  | Session public key signature. Signed by trusted side |
+
+ <!-- end messages -->
+
+ <!-- end enums -->
+
+
+
+## Scalar Value Types
+
+| .proto Type | Notes | C++ Type | Java Type | Python Type |
+| ----------- | ----- | -------- | --------- | ----------- |
+| <a name="double" /> double |  | double | double | float |
+| <a name="float" /> float |  | float | float | float |
+| <a name="int32" /> int32 | Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint32 instead. | int32 | int | int |
+| <a name="int64" /> int64 | Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint64 instead. | int64 | long | int/long |
+| <a name="uint32" /> uint32 | Uses variable-length encoding. | uint32 | int | int/long |
+| <a name="uint64" /> uint64 | Uses variable-length encoding. | uint64 | long | int/long |
+| <a name="sint32" /> sint32 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s. | int32 | int | int |
+| <a name="sint64" /> sint64 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s. | int64 | long | int/long |
+| <a name="fixed32" /> fixed32 | Always four bytes. More efficient than uint32 if values are often greater than 2^28. | uint32 | int | int |
+| <a name="fixed64" /> fixed64 | Always eight bytes. More efficient than uint64 if values are often greater than 2^56. | uint64 | long | int/long |
+| <a name="sfixed32" /> sfixed32 | Always four bytes. | int32 | int | int |
+| <a name="sfixed64" /> sfixed64 | Always eight bytes. | int64 | long | int/long |
+| <a name="bool" /> bool |  | bool | boolean | boolean |
+| <a name="string" /> string | A string must always contain UTF-8 encoded or 7-bit ASCII text. | string | String | str/unicode |
+| <a name="bytes" /> bytes | May contain any arbitrary sequence of bytes. | string | ByteString | str |
+
diff --git a/docs/state.md b/docs/state.md
new file mode 100644
index 0000000..6d240c1
--- /dev/null
+++ b/docs/state.md
@@ -0,0 +1,137 @@
+# Protocol Documentation
+<a name="top"></a>
+
+## Table of Contents
+
+- [state/service.proto](#state/service.proto)
+ - Services
+    - [Status](#state.Status)
+    
+  - Messages
+    - [HealthRequest](#state.HealthRequest)
+    - [HealthResponse](#state.HealthResponse)
+    - [MetricsRequest](#state.MetricsRequest)
+    - [MetricsResponse](#state.MetricsResponse)
+    - [NetmapRequest](#state.NetmapRequest)
+    
+
+- [Scalar Value Types](#scalar-value-types)
+
+
+
+<a name="state/service.proto"></a>
+<p align="right"><a href="#top">Top</a></p>
+
+## state/service.proto
+
+
+
+
+<a name="state.Status"></a>
+
+### Service "state.Status"
+Status service provides node's healthcheck and status info
+
+```
+rpc Netmap(NetmapRequest) returns (.bootstrap.SpreadMap);
+rpc Metrics(MetricsRequest) returns (MetricsResponse);
+rpc HealthCheck(HealthRequest) returns (HealthResponse);
+
+```
+
+#### Method Netmap
+
+Netmap request allows to receive current [bootstrap.SpreadMap](bootstrap.md#bootstrap.SpreadMap)
+
+| Name | Input | Output |
+| ---- | ----- | ------ |
+| Netmap | [NetmapRequest](#state.NetmapRequest) | [.bootstrap.SpreadMap](#bootstrap.SpreadMap) |
+#### Method Metrics
+
+Metrics request allows to receive metrics in prometheus format
+
+| Name | Input | Output |
+| ---- | ----- | ------ |
+| Metrics | [MetricsRequest](#state.MetricsRequest) | [MetricsResponse](#state.MetricsResponse) |
+#### Method HealthCheck
+
+HealthCheck request allows to check health status of the node.
+If node unhealthy field Status would contains detailed info.
+
+| Name | Input | Output |
+| ---- | ----- | ------ |
+| HealthCheck | [HealthRequest](#state.HealthRequest) | [HealthResponse](#state.HealthResponse) |
+ <!-- end services -->
+
+
+<a name="state.HealthRequest"></a>
+
+### Message HealthRequest
+HealthRequest message to check current state
+
+
+
+<a name="state.HealthResponse"></a>
+
+### Message HealthResponse
+HealthResponse message with current state
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| Healthy | [bool](#bool) |  | Healthy is true when node alive and healthy |
+| Status | [string](#string) |  | Status contains detailed information about health status |
+
+
+<a name="state.MetricsRequest"></a>
+
+### Message MetricsRequest
+MetricsRequest message to request node metrics
+
+
+
+<a name="state.MetricsResponse"></a>
+
+### Message MetricsResponse
+MetricsResponse contains [][]byte,
+every []byte is marshaled MetricFamily proto message
+from github.com/prometheus/client_model/metrics.proto
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| Metrics | [bytes](#bytes) | repeated |  |
+
+
+<a name="state.NetmapRequest"></a>
+
+### Message NetmapRequest
+NetmapRequest message to request current node netmap
+
+
+ <!-- end messages -->
+
+ <!-- end enums -->
+
+
+
+## Scalar Value Types
+
+| .proto Type | Notes | C++ Type | Java Type | Python Type |
+| ----------- | ----- | -------- | --------- | ----------- |
+| <a name="double" /> double |  | double | double | float |
+| <a name="float" /> float |  | float | float | float |
+| <a name="int32" /> int32 | Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint32 instead. | int32 | int | int |
+| <a name="int64" /> int64 | Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint64 instead. | int64 | long | int/long |
+| <a name="uint32" /> uint32 | Uses variable-length encoding. | uint32 | int | int/long |
+| <a name="uint64" /> uint64 | Uses variable-length encoding. | uint64 | long | int/long |
+| <a name="sint32" /> sint32 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s. | int32 | int | int |
+| <a name="sint64" /> sint64 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s. | int64 | long | int/long |
+| <a name="fixed32" /> fixed32 | Always four bytes. More efficient than uint32 if values are often greater than 2^28. | uint32 | int | int |
+| <a name="fixed64" /> fixed64 | Always eight bytes. More efficient than uint64 if values are often greater than 2^56. | uint64 | long | int/long |
+| <a name="sfixed32" /> sfixed32 | Always four bytes. | int32 | int | int |
+| <a name="sfixed64" /> sfixed64 | Always eight bytes. | int64 | long | int/long |
+| <a name="bool" /> bool |  | bool | boolean | boolean |
+| <a name="string" /> string | A string must always contain UTF-8 encoded or 7-bit ASCII text. | string | String | str/unicode |
+| <a name="bytes" /> bytes | May contain any arbitrary sequence of bytes. | string | ByteString | str |
+
diff --git a/object/service.pb.go b/object/service.pb.go
index aede5cd..8301ebb 100644
--- a/object/service.pb.go
+++ b/object/service.pb.go
@@ -434,6 +434,8 @@ func (m *DeleteRequest) GetToken() *session.Token {
 	return nil
 }
 
+// DeleteResponse is empty because we cannot guarantee permanent object removal
+// in distributed system.
 type DeleteResponse struct {
 	XXX_NoUnkeyedLiteral struct{} `json:"-"`
 	XXX_unrecognized     []byte   `json:"-"`
@@ -469,7 +471,6 @@ func (m *DeleteResponse) XXX_DiscardUnknown() {
 
 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"`
@@ -991,19 +992,36 @@ const _ = grpc.SupportPackageIsVersion4
 //
 // 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 the object from container. Response uses gRPC stream. First response
+	// message carry object of requested address. Chunk messages are parts of
+	// the object's payload if it is needed. All messages except first carry
+	// chunks. Requested object can be restored by concatenation of object
+	// message payload and all chunks keeping receiving order.
 	Get(ctx context.Context, in *GetRequest, opts ...grpc.CallOption) (Service_GetClient, error)
-	// Put the object into a container
+	// Put the object into container. Request uses gRPC stream. First message
+	// SHOULD BE type of PutHeader. Container id and Owner id of object SHOULD
+	// BE set. Session token SHOULD BE obtained before put operation (see
+	// session package). Chunk messages considered by server as part of object
+	// payload. All messages except first SHOULD BE chunks. Chunk messages
+	// SHOULD BE sent in direct order of fragmentation.
 	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 returns the object without data payload. Object in the
+	// response has system header only. If full headers flag is set, extended
+	// headers are also present.
 	Head(ctx context.Context, in *HeadRequest, opts ...grpc.CallOption) (*HeadResponse, error)
-	// Search by MetaInfo
+	// Search objects in container. Version of query language format SHOULD BE
+	// set to 1. Search query represented in serialized format (see query
+	// package).
 	Search(ctx context.Context, in *SearchRequest, opts ...grpc.CallOption) (*SearchResponse, error)
-	// Get ranges of object payload
+	// GetRange of data payload. Ranges are set of pairs (offset, length).
+	// Fragments order in response corresponds to ranges order in request.
 	GetRange(ctx context.Context, in *GetRangeRequest, opts ...grpc.CallOption) (*GetRangeResponse, error)
-	// Get hashes of object ranges
+	// GetRangeHash returns homomorphic hash of object payload range after XOR
+	// operation. Ranges are set of pairs (offset, length). Hashes order in
+	// response corresponds to ranges order in request. Homomorphic hash is
+	// calculated for XORed data.
 	GetRangeHash(ctx context.Context, in *GetRangeHashRequest, opts ...grpc.CallOption) (*GetRangeHashResponse, error)
 }
 
@@ -1128,19 +1146,36 @@ func (c *serviceClient) GetRangeHash(ctx context.Context, in *GetRangeHashReques
 
 // ServiceServer is the server API for Service service.
 type ServiceServer interface {
-	// Get the object from a container
+	// Get the object from container. Response uses gRPC stream. First response
+	// message carry object of requested address. Chunk messages are parts of
+	// the object's payload if it is needed. All messages except first carry
+	// chunks. Requested object can be restored by concatenation of object
+	// message payload and all chunks keeping receiving order.
 	Get(*GetRequest, Service_GetServer) error
-	// Put the object into a container
+	// Put the object into container. Request uses gRPC stream. First message
+	// SHOULD BE type of PutHeader. Container id and Owner id of object SHOULD
+	// BE set. Session token SHOULD BE obtained before put operation (see
+	// session package). Chunk messages considered by server as part of object
+	// payload. All messages except first SHOULD BE chunks. Chunk messages
+	// SHOULD BE sent in direct order of fragmentation.
 	Put(Service_PutServer) error
 	// Delete the object from a container
 	Delete(context.Context, *DeleteRequest) (*DeleteResponse, error)
-	// Get MetaInfo
+	// Head returns the object without data payload. Object in the
+	// response has system header only. If full headers flag is set, extended
+	// headers are also present.
 	Head(context.Context, *HeadRequest) (*HeadResponse, error)
-	// Search by MetaInfo
+	// Search objects in container. Version of query language format SHOULD BE
+	// set to 1. Search query represented in serialized format (see query
+	// package).
 	Search(context.Context, *SearchRequest) (*SearchResponse, error)
-	// Get ranges of object payload
+	// GetRange of data payload. Ranges are set of pairs (offset, length).
+	// Fragments order in response corresponds to ranges order in request.
 	GetRange(context.Context, *GetRangeRequest) (*GetRangeResponse, error)
-	// Get hashes of object ranges
+	// GetRangeHash returns homomorphic hash of object payload range after XOR
+	// operation. Ranges are set of pairs (offset, length). Hashes order in
+	// response corresponds to ranges order in request. Homomorphic hash is
+	// calculated for XORed data.
 	GetRangeHash(context.Context, *GetRangeHashRequest) (*GetRangeHashResponse, error)
 }
 
diff --git a/object/service.proto b/object/service.proto
index 0a03383..6f13d55 100644
--- a/object/service.proto
+++ b/object/service.proto
@@ -9,111 +9,132 @@ import "github.com/gogo/protobuf/gogoproto/gogo.proto";
 
 option (gogoproto.stable_marshaler_all) = true;
 
+// Object service provides API for manipulating with the object.
 service Service {
-    // Get the object from a container
+
+    // Get the object from container. Response uses gRPC stream. First response
+    // message carry object of requested address. Chunk messages are parts of
+    // the object's payload if it is needed. All messages except first carry
+    // chunks. Requested object can be restored by concatenation of object
+    // message payload and all chunks keeping receiving order.
     rpc Get(GetRequest) returns (stream GetResponse);
 
-    // Put the object into a container
+    // Put the object into container. Request uses gRPC stream. First message
+    // SHOULD BE type of PutHeader. Container id and Owner id of object SHOULD
+    // BE set. Session token SHOULD BE obtained before put operation (see
+    // session package). Chunk messages considered by server as part of object
+    // payload. All messages except first SHOULD BE chunks. Chunk messages
+    // SHOULD BE sent in direct order of fragmentation.
     rpc Put(stream PutRequest) returns (PutResponse);
 
     // Delete the object from a container
     rpc Delete(DeleteRequest) returns (DeleteResponse);
 
-    // Get MetaInfo
+    // Head returns the object without data payload. Object in the
+    // response has system header only. If full headers flag is set, extended
+    // headers are also present.
     rpc Head(HeadRequest) returns (HeadResponse);
 
-    // Search by MetaInfo
+    // Search objects in container. Version of query language format SHOULD BE
+    // set to 1. Search query represented in serialized format (see query
+    // package).
     rpc Search(SearchRequest) returns (SearchResponse);
 
-    // Get ranges of object payload
+    // GetRange of data payload. Ranges are set of pairs (offset, length).
+    // Fragments order in response corresponds to ranges order in request.
     rpc GetRange(GetRangeRequest) returns (GetRangeResponse);
 
-    // Get hashes of object ranges
+    // GetRangeHash returns homomorphic hash of object payload range after XOR
+    // operation. Ranges are set of pairs (offset, length). Hashes order in
+    // response corresponds to ranges order in request. Homomorphic hash is
+    // calculated for XORed data.
     rpc GetRangeHash(GetRangeHashRequest) returns (GetRangeHashResponse);
 }
 
 message GetRequest {
-    uint64 Epoch         = 1;
-    refs.Address Address = 2 [(gogoproto.nullable) = false];
-    uint32 TTL           = 3;
+    uint64 Epoch         = 1; // Epoch is set by user to 0, node set epoch to the actual value
+    refs.Address Address = 2 [(gogoproto.nullable) = false]; // Address of object (container id + object id)
+    uint32 TTL           = 3; // TTL must be larger than zero, it decreased in every neofs-node
 }
 
 message GetResponse {
     oneof R {
-        Object object = 1;
-        bytes Chunk   = 2;
+        Object object = 1; // Object header and some payload
+        bytes Chunk   = 2; // Chunk of remaining payload
     }
 }
 
 message PutRequest {
     message PutHeader {
-        uint64 Epoch        = 1;
-        Object Object       = 2;
-        uint32 TTL          = 3;
-        session.Token Token = 4;
+        uint64 Epoch        = 1; // Epoch is set by user to 0, node set epoch to the actual value
+        Object Object       = 2; // Object with at least container id and owner id fields
+        uint32 TTL          = 3; // TTL must be larger than zero, it decreased in every neofs-node
+        session.Token Token = 4; // Token with session public key and user's signature
     }
 
     oneof R {
-        PutHeader Header = 1;
-        bytes Chunk      = 2;
+        PutHeader Header = 1; // Header should be the first message in the stream
+        bytes Chunk      = 2; // Chunk should be a remaining message in stream should be chunks
     }
 }
 
 message PutResponse {
-    refs.Address Address = 1 [(gogoproto.nullable) = false];
+    refs.Address Address = 1 [(gogoproto.nullable) = false]; // Address of object (container id + object id)
 }
 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;
+    uint64 Epoch         = 1; // Epoch is set by user to 0, node set epoch to the actual value
+    refs.Address Address = 2 [(gogoproto.nullable) = false]; // Address of object (container id + object id)
+    bytes OwnerID        = 3 [(gogoproto.nullable) = false, (gogoproto.customtype) = "OwnerID"]; // OwnerID is a wallet address
+    uint32 TTL           = 4; // TTL must be larger than zero, it decreased in every neofs-node
+    session.Token Token  = 5; // Token with session public key and user's signature
 }
+
+// DeleteResponse is empty because we cannot guarantee permanent object removal
+// in distributed system.
 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;
+    uint64 Epoch         = 1; // Epoch is set by user to 0, node set epoch to the actual value
+    refs.Address Address = 2 [(gogoproto.nullable) = false, (gogoproto.customtype) = "Address"]; // Address of object (container id + object id)
+    bool FullHeaders     = 3; // FullHeaders can be set true for extended headers in the object
+    uint32 TTL           = 4; // TTL must be larger than zero, it decreased in every neofs-node
 }
 message HeadResponse {
-    Object Object = 1;
+    Object Object = 1; // Object without payload
 }
 
 message SearchRequest {
-    uint64 Epoch         = 1;
-    uint32 Version       = 2;
-    bytes ContainerID    = 3 [(gogoproto.nullable) = false, (gogoproto.customtype) = "CID"];
-    bytes Query          = 4;
-    uint32 TTL           = 5;
+    uint64 Epoch         = 1; // Epoch is set by user to 0, node set epoch to the actual value
+    uint32 Version       = 2; // Version of search query format
+    bytes ContainerID    = 3 [(gogoproto.nullable) = false, (gogoproto.customtype) = "CID"]; // ContainerID for searching the object
+    bytes Query          = 4; // Query in the binary serialized format
+    uint32 TTL           = 5; // TTL must be larger than zero, it decreased in every neofs-node
 }
 
 message SearchResponse {
-    repeated refs.Address Addresses = 1 [(gogoproto.nullable) = false];
+    repeated refs.Address Addresses = 1 [(gogoproto.nullable) = false]; // Addresses of found objects
 }
 
 message GetRangeRequest {
-    uint64 Epoch          = 1;
-    refs.Address Address  = 2 [(gogoproto.nullable) = false];
-    repeated Range Ranges = 3 [(gogoproto.nullable) = false];
-    uint32 TTL            = 4;
+    uint64 Epoch          = 1; // Epoch is set by user to 0, node set epoch to the actual value
+    refs.Address Address  = 2 [(gogoproto.nullable) = false]; // Address of object (container id + object id)
+    repeated Range Ranges = 3 [(gogoproto.nullable) = false]; // Ranges of object's payload to return
+    uint32 TTL            = 4; // TTL must be larger than zero, it decreased in every neofs-node
 }
 
 message GetRangeResponse {
-    repeated bytes Fragments = 1;
+    repeated bytes Fragments = 1; // Fragments of object's payload
 }
 
 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;
+    uint64 Epoch          = 1; // Epoch is set by user to 0, node set epoch to the actual value
+    refs.Address Address  = 2 [(gogoproto.nullable) = false]; // Address of object (container id + object id)
+    repeated Range Ranges = 3 [(gogoproto.nullable) = false]; // Ranges of object's payload to calculate homomorphic hash
+    bytes Salt            = 4; // Salt is used to XOR object's payload ranges before hashing, it can be nil
+    uint32 TTL            = 5; // TTL must be larger than zero, it decreased in every neofs-node
 }
 
 message GetRangeHashResponse {
-    repeated bytes Hashes = 1 [(gogoproto.customtype) = "Hash", (gogoproto.nullable) = false];
+    repeated bytes Hashes = 1 [(gogoproto.customtype) = "Hash", (gogoproto.nullable) = false]; // Homomorphic hashes of all ranges
 }
 
diff --git a/object/types.proto b/object/types.proto
index a7cbd8c..30e468e 100644
--- a/object/types.proto
+++ b/object/types.proto
@@ -9,99 +9,97 @@ import "github.com/gogo/protobuf/gogoproto/gogo.proto";
 option (gogoproto.stable_marshaler_all) = true;
 
 message Range {
-    uint64 Offset = 1;
-    uint64 Length = 2;
+    uint64 Offset = 1; // Offset of the data range
+    uint64 Length = 2; // Length of the data range
 }
 
 message UserHeader {
-    string Key = 1;
-    string Value = 2;
+    string Key   = 1; // Key of the user's header
+    string Value = 2; // Value of the user's header
 }
 
 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;
+        Link Link                         = 1;  // Link to other objects
+        refs.Address Redirect             = 2;  // RedirectNot used yet
+        UserHeader UserHeader             = 3;  // UserHeader defined by user
+        Transform Transform               = 4;  // Transform defines transform operation (e.g. payload split)
+        Tombstone Tombstone               = 5;  // Tombstone header that set up in deleted objects
+        session.VerificationHeader Verify = 6;  // Verify header that contains session public key and user's signature
+        bytes HomoHash                    = 7 [(gogoproto.customtype) = "Hash"]; // Homomorphic hash of original object payload
+        bytes PayloadChecksum             = 8;  // PayloadChecksum of actual object's payload
+        IntegrityHeader Integrity         = 9;  // Integrity header with checksum of all above headers in the object
+        StorageGroup StorageGroup         = 10; // StorageGroup contains meta information for the data audit
     }
 }
 
 message Tombstone {
-    uint64 Epoch = 1;
+    uint64 Epoch = 1; // Epoch when tombstone was created
 }
 
 message SystemHeader {
-    uint64 Version       = 1;
-    uint64 PayloadLength = 2;
+    uint64 Version       = 1; // Version of the object structure
+    uint64 PayloadLength = 2; // Object payload length
 
-    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];
+    bytes ID        = 3 [(gogoproto.customtype) = "ID", (gogoproto.nullable) = false]; // ObjectID is a UUID
+    bytes OwnerID   = 4 [(gogoproto.customtype) = "OwnerID",  (gogoproto.nullable) = false]; // OwnerID is a wallet address
+    bytes CID       = 5 [(gogoproto.customtype) = "CID",      (gogoproto.nullable) = false]; // ContainerID is a SHA256 hash of the container structure
+    CreationPoint CreatedAt = 6 [(gogoproto.nullable) = false]; // Timestamp of object creation
 }
 
 message CreationPoint {
-    int64 UnixTime = 1;
-    uint64 Epoch = 2;
+    int64 UnixTime = 1; // Date of creation in unixtime format
+    uint64 Epoch   = 2; // Date of creation in NeoFS epochs
 }
 
 message IntegrityHeader {
-    bytes HeadersChecksum   = 1;
-    bytes ChecksumSignature = 2;
+    bytes HeadersChecksum   = 1; // Checksum of all above headers in the object
+    bytes ChecksumSignature = 2; // User's signature of checksum to verify if it is correct
 }
 
 message Link {
     enum Type {
         Unknown      = 0;
-        Parent       = 1;
-        Previous     = 2;
-        Next         = 3;
-        Child        = 4;
-        StorageGroup = 5;
+        Parent       = 1; // Parent object created during object transformation
+        Previous     = 2; // Previous object in the linked list created during object transformation
+        Next         = 3; // Next object in the linked list created during object transformation
+        Child        = 4; // Child object created during object transformation
+        StorageGroup = 5; // Object that included into this storage group
     }
-    Type type  = 1;
-    bytes ID = 2 [(gogoproto.customtype) = "ID", (gogoproto.nullable) = false];
+    Type type  = 1; // Link type
+    bytes ID = 2 [(gogoproto.customtype) = "ID", (gogoproto.nullable) = false]; // Object id
 }
 
 message Transform {
     enum Type {
         Unknown = 0;
-        Split   = 1;
-        Sign    = 2;
-        Mould   = 3;
+        Split   = 1; // Object created after payload split
+        Sign    = 2; // Object created after re-signing (doesn't used)
+        Mould   = 3; // Object created after filling missing headers in the object
     }
-    Type type  = 1;
+    Type type  = 1; // Type of object transformation
 }
 
 message Object {
-    SystemHeader SystemHeader = 1 [(gogoproto.nullable) = false];
-    repeated Header Headers   = 2 [(gogoproto.nullable) = false];
-    bytes Payload             = 3;
+    SystemHeader SystemHeader = 1 [(gogoproto.nullable) = false]; // System header
+    repeated Header Headers   = 2 [(gogoproto.nullable) = false]; // Extended headers
+    bytes Payload             = 3; // Object's payload
 }
 
 message StorageGroup {
-    uint64 ValidationDataSize = 1;
-    bytes ValidationHash = 2 [(gogoproto.customtype) = "Hash", (gogoproto.nullable) = false];
+    uint64 ValidationDataSize = 1; // Size of the all object's payloads included into storage group
+    bytes ValidationHash = 2 [(gogoproto.customtype) = "Hash", (gogoproto.nullable) = false]; // Homomorphic hash of all object's payloads included into storage group
 
     message Lifetime {
         enum Unit {
-            Unlimited = 0;
-            NeoFSEpoch = 1;
-            UnixTime = 2;
+            Unlimited = 0;  // Storage group always valid
+            NeoFSEpoch = 1; // Storage group is valid until lifetime NeoFS epoch
+            UnixTime = 2;   // Storage group is valid until lifetime unix timestamp
         }
 
-        Unit unit = 1 [(gogoproto.customname) = "Unit"];
-        int64 Value = 2;
+        Unit unit = 1 [(gogoproto.customname) = "Unit"]; // Lifetime type
+        int64 Value = 2; // Lifetime value
     }
 
-    Lifetime lifetime = 3 [(gogoproto.customname) = "Lifetime"];
+    Lifetime lifetime = 3 [(gogoproto.customname) = "Lifetime"]; // Time until storage group is valid
 }
diff --git a/query/types.pb.go b/query/types.pb.go
index 51f682e..8fa3dbe 100644
--- a/query/types.pb.go
+++ b/query/types.pb.go
@@ -23,6 +23,7 @@ var _ = math.Inf
 // proto package needs to be updated.
 const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
 
+// Type can be Exact or Regex
 type Filter_Type int32
 
 const (
@@ -49,12 +50,15 @@ func (Filter_Type) EnumDescriptor() ([]byte, []int) {
 }
 
 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:"-"`
+	// Type of filter
+	Type Filter_Type `protobuf:"varint,1,opt,name=type,proto3,enum=query.Filter_Type" json:"type,omitempty"`
+	// Name of field that should be filtered
+	Name string `protobuf:"bytes,2,opt,name=Name,proto3" json:"Name,omitempty"`
+	// Value that should be used for filter
+	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{} }
@@ -107,6 +111,7 @@ func (m *Filter) GetValue() string {
 }
 
 type Query struct {
+	// Filters is set of filters, should not be empty
 	Filters              []Filter `protobuf:"bytes,1,rep,name=Filters,proto3" json:"Filters"`
 	XXX_NoUnkeyedLiteral struct{} `json:"-"`
 	XXX_unrecognized     []byte   `json:"-"`
diff --git a/query/types.proto b/query/types.proto
index 5f46072..884a6bd 100644
--- a/query/types.proto
+++ b/query/types.proto
@@ -9,17 +9,23 @@ option (gogoproto.stable_marshaler_all) = true;
 message Filter {
     option (gogoproto.goproto_stringer) = false;
 
+    // Type can be Exact or Regex
     enum Type {
         Exact = 0;
         Regex = 1;
     }
+
+    // Type of filter
     Type type = 1 [(gogoproto.customname) = "Type"];
+    // Name of field that should be filtered
     string Name = 2;
+    // Value that should be used for filter
     string Value = 3;
 }
 
 message Query {
     option (gogoproto.goproto_stringer) = false;
 
+    // Filters is set of filters, should not be empty
     repeated Filter Filters = 1 [(gogoproto.nullable) = false];
 }
diff --git a/refs/types.pb.go b/refs/types.pb.go
index 33f7578..87f3fce 100644
--- a/refs/types.pb.go
+++ b/refs/types.pb.go
@@ -23,8 +23,11 @@ var _ = math.Inf
 // proto package needs to be updated.
 const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
 
+// Address of object (container id + object id)
 type Address struct {
-	ObjectID             ObjectID `protobuf:"bytes,1,opt,name=ObjectID,proto3,customtype=ObjectID" json:"ObjectID"`
+	// ObjectID is an object identifier
+	ObjectID ObjectID `protobuf:"bytes,1,opt,name=ObjectID,proto3,customtype=ObjectID" json:"ObjectID"`
+	// CID is container identifier
 	CID                  CID      `protobuf:"bytes,2,opt,name=CID,proto3,customtype=CID" json:"CID"`
 	XXX_NoUnkeyedLiteral struct{} `json:"-"`
 	XXX_unrecognized     []byte   `json:"-"`
diff --git a/refs/types.proto b/refs/types.proto
index e607f34..15355ae 100644
--- a/refs/types.proto
+++ b/refs/types.proto
@@ -9,7 +9,10 @@ option (gogoproto.stable_marshaler_all) = true;
 option (gogoproto.stringer_all) =  false;
 option (gogoproto.goproto_stringer_all) = false;
 
+// Address of object (container id + object id)
 message Address {
-    bytes ObjectID = 1[(gogoproto.customtype) = "ObjectID", (gogoproto.nullable) = false]; // UUID
-    bytes CID      = 2[(gogoproto.customtype) = "CID",      (gogoproto.nullable) = false]; // sha256
+    // ObjectID is an object identifier
+    bytes ObjectID = 1[(gogoproto.customtype) = "ObjectID", (gogoproto.nullable) = false];
+    // CID is container identifier
+    bytes CID      = 2[(gogoproto.customtype) = "CID",      (gogoproto.nullable) = false];
 }
diff --git a/session/service.pb.go b/session/service.pb.go
index da85708..4961b0d 100644
--- a/session/service.pb.go
+++ b/session/service.pb.go
@@ -28,6 +28,8 @@ var _ = math.Inf
 const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
 
 type CreateRequest struct {
+	// Message should be one of
+	//
 	// Types that are valid to be assigned to Message:
 	//	*CreateRequest_Init
 	//	*CreateRequest_Signed
diff --git a/session/service.proto b/session/service.proto
index ee56a22..484425b 100644
--- a/session/service.proto
+++ b/session/service.proto
@@ -7,21 +7,41 @@ import "github.com/gogo/protobuf/gogoproto/gogo.proto";
 
 option (gogoproto.stable_marshaler_all) = true;
 
+
 service Session {
+    // Open a trusted session to manipulate an object. In order to put or
+    // delete object client have to obtain session token with trusted node.
+    // Trusted node will modify client's object (add missing headers, checksums,
+    // homomorphic hash) and sign id with session key. Session is established
+    // during 4-step handshake in one gRPC stream
+
+    // - First client stream message SHOULD BE type of `CreateRequest_Init`.
+    // - First server stream message SHOULD BE type of `CreateResponse_Unsigned`.
+    // - Second client stream message SHOULD BE type of `CreateRequest_Signed`.
+    // - Second server stream message SHOULD BE type of `CreateResponse_Result`.
+
     rpc Create (stream CreateRequest) returns (stream CreateResponse);
 }
 
 
 message CreateRequest {
+    // Message should be one of
     oneof Message {
+        // Message to init session opening. Carry:
+        // owner of manipulation object;
+        // ID of manipulation object;
+        // token lifetime bounds.
         session.Token Init = 1;
+        // Signed Init message response (Unsigned) from server with user private key
         session.Token Signed = 2;
     }
 }
 
 message CreateResponse {
     oneof Message {
+        // Unsigned token with token ID and session public key generated on server side
         session.Token Unsigned = 1;
+        // Resulting token which can be used for object placing through an trusted intermediary
         session.Token Result = 2;
     }
 }
diff --git a/session/types.pb.go b/session/types.pb.go
index ce0e0a4..d39961e 100644
--- a/session/types.pb.go
+++ b/session/types.pb.go
@@ -24,7 +24,9 @@ var _ = math.Inf
 const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
 
 type VerificationHeader struct {
-	PublicKey            []byte   `protobuf:"bytes,1,opt,name=PublicKey,proto3" json:"PublicKey,omitempty"`
+	// Session public key
+	PublicKey []byte `protobuf:"bytes,1,opt,name=PublicKey,proto3" json:"PublicKey,omitempty"`
+	// Session public key signature. Signed by trusted side
 	KeySignature         []byte   `protobuf:"bytes,2,opt,name=KeySignature,proto3" json:"KeySignature,omitempty"`
 	XXX_NoUnkeyedLiteral struct{} `json:"-"`
 	XXX_unrecognized     []byte   `json:"-"`
@@ -74,17 +76,25 @@ func (m *VerificationHeader) GetKeySignature() []byte {
 	return nil
 }
 
+// User token granting rights for object manipulation
 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:"-"`
+	// Header carries verification data of session key
+	Header VerificationHeader `protobuf:"bytes,1,opt,name=Header,proto3" json:"Header"`
+	// Owner of manipulation object
+	OwnerID OwnerID `protobuf:"bytes,2,opt,name=OwnerID,proto3,customtype=OwnerID" json:"OwnerID"`
+	// Initial epoch of token lifetime
+	FirstEpoch uint64 `protobuf:"varint,3,opt,name=FirstEpoch,proto3" json:"FirstEpoch,omitempty"`
+	// Last epoch of token lifetime
+	LastEpoch uint64 `protobuf:"varint,4,opt,name=LastEpoch,proto3" json:"LastEpoch,omitempty"`
+	// ID of manipulation object
+	ObjectID []ObjectID `protobuf:"bytes,5,rep,name=ObjectID,proto3,customtype=ObjectID" json:"ObjectID"`
+	// Token signature. Signed by owner of manipulation object
+	Signature []byte `protobuf:"bytes,6,opt,name=Signature,proto3" json:"Signature,omitempty"`
+	// Token ID (UUID)
+	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{} }
diff --git a/session/types.proto b/session/types.proto
index 8989040..bf804bf 100644
--- a/session/types.proto
+++ b/session/types.proto
@@ -7,16 +7,26 @@ import "github.com/gogo/protobuf/gogoproto/gogo.proto";
 option (gogoproto.stable_marshaler_all) = true;
 
 message VerificationHeader {
+    // Session public key
     bytes PublicKey = 1;
+    // Session public key signature. Signed by trusted side
     bytes KeySignature = 2;
 }
 
+// User token granting rights for object manipulation
 message Token {
+    // Header carries verification data of session key
     VerificationHeader Header = 1 [(gogoproto.nullable) = false];
+    // Owner of manipulation object
     bytes OwnerID = 2 [(gogoproto.customtype) = "OwnerID", (gogoproto.nullable) = false];
+    // Initial epoch of token lifetime
     uint64 FirstEpoch = 3;
+    // Last epoch of token lifetime
     uint64 LastEpoch = 4;
+    // ID of manipulation object
     repeated bytes ObjectID = 5 [(gogoproto.customtype) = "ObjectID", (gogoproto.nullable) = false];
+    // Token signature. Signed by owner of manipulation object
     bytes Signature = 6;
+    // Token ID (UUID)
     bytes ID = 7 [(gogoproto.customtype) = "TokenID", (gogoproto.nullable) = false];
 }
diff --git a/state/service.pb.go b/state/service.pb.go
index f71dad6..a368410 100644
--- a/state/service.pb.go
+++ b/state/service.pb.go
@@ -184,7 +184,9 @@ 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"`
+	// Healthy is true when node alive and healthy
+	Healthy bool `protobuf:"varint,1,opt,name=Healthy,proto3" json:"Healthy,omitempty"`
+	// Status contains detailed information about health status
 	Status               string   `protobuf:"bytes,2,opt,name=Status,proto3" json:"Status,omitempty"`
 	XXX_NoUnkeyedLiteral struct{} `json:"-"`
 	XXX_unrecognized     []byte   `json:"-"`
@@ -280,8 +282,12 @@ const _ = grpc.SupportPackageIsVersion4
 //
 // 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 request allows to receive current [bootstrap.SpreadMap](bootstrap.md#bootstrap.SpreadMap)
 	Netmap(ctx context.Context, in *NetmapRequest, opts ...grpc.CallOption) (*bootstrap.SpreadMap, error)
+	// Metrics request allows to receive metrics in prometheus format
 	Metrics(ctx context.Context, in *MetricsRequest, opts ...grpc.CallOption) (*MetricsResponse, error)
+	// HealthCheck request allows to check health status of the node.
+	// If node unhealthy field Status would contains detailed info.
 	HealthCheck(ctx context.Context, in *HealthRequest, opts ...grpc.CallOption) (*HealthResponse, error)
 }
 
@@ -322,8 +328,12 @@ func (c *statusClient) HealthCheck(ctx context.Context, in *HealthRequest, opts
 
 // StatusServer is the server API for Status service.
 type StatusServer interface {
+	// Netmap request allows to receive current [bootstrap.SpreadMap](bootstrap.md#bootstrap.SpreadMap)
 	Netmap(context.Context, *NetmapRequest) (*bootstrap.SpreadMap, error)
+	// Metrics request allows to receive metrics in prometheus format
 	Metrics(context.Context, *MetricsRequest) (*MetricsResponse, error)
+	// HealthCheck request allows to check health status of the node.
+	// If node unhealthy field Status would contains detailed info.
 	HealthCheck(context.Context, *HealthRequest) (*HealthResponse, error)
 }
 
diff --git a/state/service.proto b/state/service.proto
index d0e59b4..3c85d86 100644
--- a/state/service.proto
+++ b/state/service.proto
@@ -7,10 +7,14 @@ import "github.com/gogo/protobuf/gogoproto/gogo.proto";
 
 option (gogoproto.stable_marshaler_all) = true;
 
-// The Status service definition.
+// Status service provides node's healthcheck and status info
 service Status {
+    // Netmap request allows to receive current [bootstrap.SpreadMap](bootstrap.md#bootstrap.SpreadMap)
     rpc Netmap(NetmapRequest) returns (bootstrap.SpreadMap);
+    // Metrics request allows to receive metrics in prometheus format
     rpc Metrics(MetricsRequest) returns (MetricsResponse);
+    // HealthCheck request allows to check health status of the node.
+    // If node unhealthy field Status would contains detailed info.
     rpc HealthCheck(HealthRequest) returns (HealthResponse);
 }
 
@@ -32,6 +36,8 @@ message HealthRequest {}
 
 // HealthResponse message with current state
 message HealthResponse {
+    // Healthy is true when node alive and healthy
     bool Healthy  = 1;
+    // Status contains detailed information about health status
     string Status = 2;
 }