diff --git a/.golangci.yml b/.golangci.yml index d209693aa..36c1b2b89 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -35,7 +35,7 @@ linters-settings: no-unaliased: true no-extra-aliases: false alias: - pkg: git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object + pkg: git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object alias: objectSDK custom: truecloudlab-linters: diff --git a/Makefile b/Makefile index 4d3c121bf..7a5403228 100755 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ LINT_VERSION ?= 1.56.1 TRUECLOUDLAB_LINT_VERSION ?= 0.0.5 PROTOC_VERSION ?= 25.0 PROTOC_GEN_GO_VERSION ?= $(shell go list -f '{{.Version}}' -m google.golang.org/protobuf) -PROTOGEN_FROSTFS_VERSION ?= $(shell go list -f '{{.Version}}' -m git.frostfs.info/TrueCloudLab/frostfs-api-go/v2) +PROTOGEN_FROSTFS_VERSION ?= $(shell go list -f '{{.Version}}' -m git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api) PROTOC_OS_VERSION=osx-x86_64 ifeq ($(shell uname), Linux) PROTOC_OS_VERSION=linux-x86_64 @@ -126,7 +126,7 @@ protoc-install: @echo "⇒ Installing protoc-gen-go..." @GOBIN=$(PROTOC_GEN_GO_DIR) go install -v google.golang.org/protobuf/...@$(PROTOC_GEN_GO_VERSION) @echo "⇒ Instaling protogen FrostFS plugin..." - @GOBIN=$(PROTOGEN_FROSTFS_DIR) go install -mod=mod -v git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/protogen@$(PROTOGEN_FROSTFS_VERSION) + @GOBIN=$(PROTOGEN_FROSTFS_DIR) go install -mod=mod -v git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/util/protogen@$(PROTOGEN_FROSTFS_VERSION) # Build FrostFS component's docker image image-%: diff --git a/cmd/frostfs-adm/internal/modules/morph/balance/balance.go b/cmd/frostfs-adm/internal/modules/morph/balance/balance.go index 428fb98b9..e5307fa21 100644 --- a/cmd/frostfs-adm/internal/modules/morph/balance/balance.go +++ b/cmd/frostfs-adm/internal/modules/morph/balance/balance.go @@ -9,7 +9,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-contract/nns" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" "github.com/nspcc-dev/neo-go/pkg/core/native/noderoles" "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" diff --git a/cmd/frostfs-adm/internal/modules/morph/container/container.go b/cmd/frostfs-adm/internal/modules/morph/container/container.go index 690db2f4f..c9fd3ed78 100644 --- a/cmd/frostfs-adm/internal/modules/morph/container/container.go +++ b/cmd/frostfs-adm/internal/modules/morph/container/container.go @@ -9,7 +9,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" "github.com/nspcc-dev/neo-go/pkg/crypto/hash" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" diff --git a/cmd/frostfs-cli/internal/client/client.go b/cmd/frostfs-cli/internal/client/client.go index a6d9968c5..2430092cc 100644 --- a/cmd/frostfs-cli/internal/client/client.go +++ b/cmd/frostfs-cli/internal/client/client.go @@ -9,16 +9,16 @@ import ( "sort" "strings" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/accounting" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/checksum" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - containerSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/version" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/accounting" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/checksum" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + containerSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/eacl" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/version" ) var errMissingHeaderInResponse = errors.New("missing header in response") diff --git a/cmd/frostfs-cli/internal/client/prm.go b/cmd/frostfs-cli/internal/client/prm.go index e5c1b41c9..eb7684834 100644 --- a/cmd/frostfs-cli/internal/client/prm.go +++ b/cmd/frostfs-cli/internal/client/prm.go @@ -3,11 +3,11 @@ package internal import ( "io" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/bearer" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/session" ) // here are small structures with public setters to share between parameter structures diff --git a/cmd/frostfs-cli/internal/client/sdk.go b/cmd/frostfs-cli/internal/client/sdk.go index f7c48b871..d28b3e41b 100644 --- a/cmd/frostfs-cli/internal/client/sdk.go +++ b/cmd/frostfs-cli/internal/client/sdk.go @@ -12,8 +12,8 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" tracing "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing/grpc" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" "github.com/spf13/cobra" "github.com/spf13/viper" "google.golang.org/grpc" diff --git a/cmd/frostfs-cli/internal/common/eacl.go b/cmd/frostfs-cli/internal/common/eacl.go index 0a623b0e8..9e3f4686e 100644 --- a/cmd/frostfs-cli/internal/common/eacl.go +++ b/cmd/frostfs-cli/internal/common/eacl.go @@ -6,8 +6,8 @@ import ( commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/version" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" - versionSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/version" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/eacl" + versionSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/version" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/internal/common/token.go b/cmd/frostfs-cli/internal/common/token.go index 102a2d59e..75f58e199 100644 --- a/cmd/frostfs-cli/internal/common/token.go +++ b/cmd/frostfs-cli/internal/common/token.go @@ -7,7 +7,7 @@ import ( "os" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/bearer" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/internal/common/verbose.go b/cmd/frostfs-cli/internal/common/verbose.go index 2f95626ff..f78e53ccd 100644 --- a/cmd/frostfs-cli/internal/common/verbose.go +++ b/cmd/frostfs-cli/internal/common/verbose.go @@ -6,7 +6,7 @@ import ( "time" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/checksum" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/checksum" "github.com/spf13/cobra" "github.com/spf13/viper" ) diff --git a/cmd/frostfs-cli/modules/accounting/balance.go b/cmd/frostfs-cli/modules/accounting/balance.go index 1364b5e8e..7a95eee91 100644 --- a/cmd/frostfs-cli/modules/accounting/balance.go +++ b/cmd/frostfs-cli/modules/accounting/balance.go @@ -7,9 +7,9 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/accounting" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/precision" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/accounting" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn" "github.com/spf13/cobra" "github.com/spf13/viper" diff --git a/cmd/frostfs-cli/modules/acl/basic/print.go b/cmd/frostfs-cli/modules/acl/basic/print.go index cb037bbbd..209211c62 100644 --- a/cmd/frostfs-cli/modules/acl/basic/print.go +++ b/cmd/frostfs-cli/modules/acl/basic/print.go @@ -3,7 +3,7 @@ package basic import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/acl" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/acl/extended/create.go b/cmd/frostfs-cli/modules/acl/extended/create.go index 59dfabba2..df348fbc9 100644 --- a/cmd/frostfs-cli/modules/acl/extended/create.go +++ b/cmd/frostfs-cli/modules/acl/extended/create.go @@ -9,8 +9,8 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/eacl" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/acl/extended/create_test.go b/cmd/frostfs-cli/modules/acl/extended/create_test.go index 71f41e589..927b489e0 100644 --- a/cmd/frostfs-cli/modules/acl/extended/create_test.go +++ b/cmd/frostfs-cli/modules/acl/extended/create_test.go @@ -4,7 +4,7 @@ import ( "testing" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/eacl" "github.com/stretchr/testify/require" ) diff --git a/cmd/frostfs-cli/modules/acl/extended/print.go b/cmd/frostfs-cli/modules/acl/extended/print.go index 3e46a70ba..45bb9edf1 100644 --- a/cmd/frostfs-cli/modules/acl/extended/print.go +++ b/cmd/frostfs-cli/modules/acl/extended/print.go @@ -6,7 +6,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/eacl" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/bearer/create.go b/cmd/frostfs-cli/modules/bearer/create.go index 8a7500db3..c2d2fa64e 100644 --- a/cmd/frostfs-cli/modules/bearer/create.go +++ b/cmd/frostfs-cli/modules/bearer/create.go @@ -11,9 +11,9 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" - eaclSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/bearer" + eaclSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/eacl" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/container/create.go b/cmd/frostfs-cli/modules/container/create.go index 728332b35..142f0ba73 100644 --- a/cmd/frostfs-cli/modules/container/create.go +++ b/cmd/frostfs-cli/modules/container/create.go @@ -7,17 +7,17 @@ import ( "strings" "time" - containerApi "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container" internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" + containerApi "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/container" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/acl" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/container/delete.go b/cmd/frostfs-cli/modules/container/delete.go index e5425bf25..3cae58115 100644 --- a/cmd/frostfs-cli/modules/container/delete.go +++ b/cmd/frostfs-cli/modules/container/delete.go @@ -9,9 +9,9 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/container/get.go b/cmd/frostfs-cli/modules/container/get.go index 8c4ab14f8..ef5cbbbb9 100644 --- a/cmd/frostfs-cli/modules/container/get.go +++ b/cmd/frostfs-cli/modules/container/get.go @@ -10,10 +10,10 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/acl" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/container/get_eacl.go b/cmd/frostfs-cli/modules/container/get_eacl.go index 4ed1c82e1..7c6d91ead 100644 --- a/cmd/frostfs-cli/modules/container/get_eacl.go +++ b/cmd/frostfs-cli/modules/container/get_eacl.go @@ -8,7 +8,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/container/list.go b/cmd/frostfs-cli/modules/container/list.go index 8f5db49df..448afc453 100644 --- a/cmd/frostfs-cli/modules/container/list.go +++ b/cmd/frostfs-cli/modules/container/list.go @@ -3,13 +3,13 @@ package container import ( "strings" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container" internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" - containerSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/container" + containerSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" "github.com/spf13/cobra" ) @@ -80,7 +80,7 @@ var listContainersCmd = &cobra.Command{ if flagVarListPrintAttr { cnr.IterateAttributes(func(key, val string) { if !strings.HasPrefix(key, container.SysAttributePrefix) && !strings.HasPrefix(key, container.SysAttributePrefixNeoFS) { - // FIXME(@cthulhu-rider): https://git.frostfs.info/TrueCloudLab/frostfs-sdk-go/issues/97 + // FIXME(@cthulhu-rider): https://git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/issues/97 // Use dedicated method to skip system attributes. cmd.Printf(" %s: %s\n", key, val) } diff --git a/cmd/frostfs-cli/modules/container/list_objects.go b/cmd/frostfs-cli/modules/container/list_objects.go index ff2f8cf45..5faadea45 100644 --- a/cmd/frostfs-cli/modules/container/list_objects.go +++ b/cmd/frostfs-cli/modules/container/list_objects.go @@ -3,14 +3,14 @@ package container import ( "strings" - v2object "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" objectCli "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/object" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + v2object "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "github.com/spf13/cobra" ) @@ -71,7 +71,7 @@ var listContainerObjectsCmd = &cobra.Command{ for i := range attrs { attrKey := attrs[i].Key() if !strings.HasPrefix(attrKey, v2object.SysAttributePrefix) && !strings.HasPrefix(attrKey, v2object.SysAttributePrefixNeoFS) { - // FIXME(@cthulhu-rider): https://git.frostfs.info/TrueCloudLab/frostfs-sdk-go/issues/97 + // FIXME(@cthulhu-rider): https://git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/issues/97 // Use dedicated method to skip system attributes. cmd.Printf(" %s: %s\n", attrKey, attrs[i].Value()) } diff --git a/cmd/frostfs-cli/modules/container/nodes.go b/cmd/frostfs-cli/modules/container/nodes.go index d785fa23d..1e658a40a 100644 --- a/cmd/frostfs-cli/modules/container/nodes.go +++ b/cmd/frostfs-cli/modules/container/nodes.go @@ -7,9 +7,9 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" - containerAPI "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" + containerAPI "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/container/policy_playground.go b/cmd/frostfs-cli/modules/container/policy_playground.go index 1ac41f08c..880fe70fa 100644 --- a/cmd/frostfs-cli/modules/container/policy_playground.go +++ b/cmd/frostfs-cli/modules/container/policy_playground.go @@ -13,7 +13,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" "github.com/spf13/cobra" "github.com/spf13/viper" ) diff --git a/cmd/frostfs-cli/modules/container/set_eacl.go b/cmd/frostfs-cli/modules/container/set_eacl.go index 86aa50a57..7899facbb 100644 --- a/cmd/frostfs-cli/modules/container/set_eacl.go +++ b/cmd/frostfs-cli/modules/container/set_eacl.go @@ -10,7 +10,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/container/util.go b/cmd/frostfs-cli/modules/container/util.go index 48265f785..e8afb2be7 100644 --- a/cmd/frostfs-cli/modules/container/util.go +++ b/cmd/frostfs-cli/modules/container/util.go @@ -6,8 +6,8 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/session" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/control/add_rule.go b/cmd/frostfs-cli/modules/control/add_rule.go index 45b36bfb1..b0c8c8964 100644 --- a/cmd/frostfs-cli/modules/control/add_rule.go +++ b/cmd/frostfs-cli/modules/control/add_rule.go @@ -4,10 +4,10 @@ import ( "encoding/hex" "errors" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" "github.com/spf13/cobra" diff --git a/cmd/frostfs-cli/modules/control/detach_shards.go b/cmd/frostfs-cli/modules/control/detach_shards.go index 5e5b60c3d..ee4a6e965 100644 --- a/cmd/frostfs-cli/modules/control/detach_shards.go +++ b/cmd/frostfs-cli/modules/control/detach_shards.go @@ -1,9 +1,9 @@ package control import ( - rawclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + rawclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/control/doctor.go b/cmd/frostfs-cli/modules/control/doctor.go index 13bb81a0a..38a9d0a0d 100644 --- a/cmd/frostfs-cli/modules/control/doctor.go +++ b/cmd/frostfs-cli/modules/control/doctor.go @@ -1,9 +1,9 @@ package control import ( - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/control/drop_objects.go b/cmd/frostfs-cli/modules/control/drop_objects.go index 8c0bb2332..797c255ac 100644 --- a/cmd/frostfs-cli/modules/control/drop_objects.go +++ b/cmd/frostfs-cli/modules/control/drop_objects.go @@ -1,9 +1,9 @@ package control import ( - rawclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + rawclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/control/evacuate_shard.go b/cmd/frostfs-cli/modules/control/evacuate_shard.go index 458e4cc0b..033ded07a 100644 --- a/cmd/frostfs-cli/modules/control/evacuate_shard.go +++ b/cmd/frostfs-cli/modules/control/evacuate_shard.go @@ -1,9 +1,9 @@ package control import ( - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/control/evacuation.go b/cmd/frostfs-cli/modules/control/evacuation.go index 6fa5ed75c..47bd254a7 100644 --- a/cmd/frostfs-cli/modules/control/evacuation.go +++ b/cmd/frostfs-cli/modules/control/evacuation.go @@ -7,12 +7,12 @@ import ( "sync/atomic" "time" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" + clientSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" - clientSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/control/flush_cache.go b/cmd/frostfs-cli/modules/control/flush_cache.go index 541961903..7d4a2d795 100644 --- a/cmd/frostfs-cli/modules/control/flush_cache.go +++ b/cmd/frostfs-cli/modules/control/flush_cache.go @@ -1,9 +1,9 @@ package control import ( - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/control/get_rule.go b/cmd/frostfs-cli/modules/control/get_rule.go index 050cf165c..808cd2838 100644 --- a/cmd/frostfs-cli/modules/control/get_rule.go +++ b/cmd/frostfs-cli/modules/control/get_rule.go @@ -3,10 +3,10 @@ package control import ( "encoding/hex" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" "github.com/spf13/cobra" diff --git a/cmd/frostfs-cli/modules/control/healthcheck.go b/cmd/frostfs-cli/modules/control/healthcheck.go index 097fba540..5a03388fd 100644 --- a/cmd/frostfs-cli/modules/control/healthcheck.go +++ b/cmd/frostfs-cli/modules/control/healthcheck.go @@ -1,9 +1,9 @@ package control import ( - rawclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + rawclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/control/ir_healthcheck.go b/cmd/frostfs-cli/modules/control/ir_healthcheck.go index e70538ce2..ad4ddc4e4 100644 --- a/cmd/frostfs-cli/modules/control/ir_healthcheck.go +++ b/cmd/frostfs-cli/modules/control/ir_healthcheck.go @@ -1,9 +1,9 @@ package control import ( - rawclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + rawclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client" ircontrol "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/ir" ircontrolsrv "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/ir/server" "github.com/spf13/cobra" diff --git a/cmd/frostfs-cli/modules/control/ir_remove_container.go b/cmd/frostfs-cli/modules/control/ir_remove_container.go index a66d7e06d..f7d518ff7 100644 --- a/cmd/frostfs-cli/modules/control/ir_remove_container.go +++ b/cmd/frostfs-cli/modules/control/ir_remove_container.go @@ -1,15 +1,15 @@ package control import ( - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" - rawclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + rawclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" ircontrol "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/ir" ircontrolsrv "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/ir/server" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/control/ir_remove_node.go b/cmd/frostfs-cli/modules/control/ir_remove_node.go index 412dc7934..fd111bc92 100644 --- a/cmd/frostfs-cli/modules/control/ir_remove_node.go +++ b/cmd/frostfs-cli/modules/control/ir_remove_node.go @@ -4,9 +4,9 @@ import ( "encoding/hex" "errors" - rawclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + rawclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client" ircontrol "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/ir" ircontrolsrv "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/ir/server" "github.com/spf13/cobra" diff --git a/cmd/frostfs-cli/modules/control/ir_tick_epoch.go b/cmd/frostfs-cli/modules/control/ir_tick_epoch.go index 6965b5dca..5309e5d59 100644 --- a/cmd/frostfs-cli/modules/control/ir_tick_epoch.go +++ b/cmd/frostfs-cli/modules/control/ir_tick_epoch.go @@ -1,9 +1,9 @@ package control import ( - rawclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + rawclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client" ircontrol "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/ir" ircontrolsrv "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/ir/server" "github.com/spf13/cobra" diff --git a/cmd/frostfs-cli/modules/control/list_rules.go b/cmd/frostfs-cli/modules/control/list_rules.go index b345ecbfb..21c6e6a21 100644 --- a/cmd/frostfs-cli/modules/control/list_rules.go +++ b/cmd/frostfs-cli/modules/control/list_rules.go @@ -5,12 +5,12 @@ import ( "fmt" "strings" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" "github.com/nspcc-dev/neo-go/cli/input" "github.com/spf13/cobra" diff --git a/cmd/frostfs-cli/modules/control/list_targets.go b/cmd/frostfs-cli/modules/control/list_targets.go index ddd80b31b..6f6dba6d0 100644 --- a/cmd/frostfs-cli/modules/control/list_targets.go +++ b/cmd/frostfs-cli/modules/control/list_targets.go @@ -7,11 +7,11 @@ import ( "strconv" "text/tabwriter" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/control/remove_rule.go b/cmd/frostfs-cli/modules/control/remove_rule.go index 4189ea76b..f0aa37f1a 100644 --- a/cmd/frostfs-cli/modules/control/remove_rule.go +++ b/cmd/frostfs-cli/modules/control/remove_rule.go @@ -4,9 +4,9 @@ import ( "encoding/hex" "errors" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/control/set_netmap_status.go b/cmd/frostfs-cli/modules/control/set_netmap_status.go index 3aa741689..c2e69b9cd 100644 --- a/cmd/frostfs-cli/modules/control/set_netmap_status.go +++ b/cmd/frostfs-cli/modules/control/set_netmap_status.go @@ -3,11 +3,11 @@ package control import ( "fmt" - rawclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + rawclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/control/shards_list.go b/cmd/frostfs-cli/modules/control/shards_list.go index 3eb74ec82..7d2d6beee 100644 --- a/cmd/frostfs-cli/modules/control/shards_list.go +++ b/cmd/frostfs-cli/modules/control/shards_list.go @@ -7,10 +7,10 @@ import ( "sort" "strings" - rawclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + rawclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" "github.com/mr-tron/base58" "github.com/spf13/cobra" diff --git a/cmd/frostfs-cli/modules/control/shards_set_mode.go b/cmd/frostfs-cli/modules/control/shards_set_mode.go index 1c87b405b..d50a35c80 100644 --- a/cmd/frostfs-cli/modules/control/shards_set_mode.go +++ b/cmd/frostfs-cli/modules/control/shards_set_mode.go @@ -6,9 +6,9 @@ import ( "sort" "strings" - rawclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + rawclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" "github.com/mr-tron/base58" "github.com/spf13/cobra" diff --git a/cmd/frostfs-cli/modules/control/synchronize_tree.go b/cmd/frostfs-cli/modules/control/synchronize_tree.go index 2287344d6..d684f709c 100644 --- a/cmd/frostfs-cli/modules/control/synchronize_tree.go +++ b/cmd/frostfs-cli/modules/control/synchronize_tree.go @@ -4,13 +4,13 @@ import ( "crypto/sha256" "errors" - rawclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + rawclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" controlSvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/server" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/control/util.go b/cmd/frostfs-cli/modules/control/util.go index ffaceff13..988de9d0f 100644 --- a/cmd/frostfs-cli/modules/control/util.go +++ b/cmd/frostfs-cli/modules/control/util.go @@ -4,13 +4,13 @@ import ( "crypto/ecdsa" "errors" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/crypto" controlSvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/server" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/control/writecache.go b/cmd/frostfs-cli/modules/control/writecache.go index abc4ed2e6..abe909e56 100644 --- a/cmd/frostfs-cli/modules/control/writecache.go +++ b/cmd/frostfs-cli/modules/control/writecache.go @@ -1,9 +1,9 @@ package control import ( - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" "github.com/mr-tron/base58" "github.com/spf13/cobra" diff --git a/cmd/frostfs-cli/modules/netmap/nodeinfo.go b/cmd/frostfs-cli/modules/netmap/nodeinfo.go index b6ec48f35..74ec31c99 100644 --- a/cmd/frostfs-cli/modules/netmap/nodeinfo.go +++ b/cmd/frostfs-cli/modules/netmap/nodeinfo.go @@ -8,7 +8,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/object/delete.go b/cmd/frostfs-cli/modules/object/delete.go index e4e9cddb8..61043c24f 100644 --- a/cmd/frostfs-cli/modules/object/delete.go +++ b/cmd/frostfs-cli/modules/object/delete.go @@ -7,8 +7,8 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/object/get.go b/cmd/frostfs-cli/modules/object/get.go index 9a888ccd3..0e5b0d597 100644 --- a/cmd/frostfs-cli/modules/object/get.go +++ b/cmd/frostfs-cli/modules/object/get.go @@ -10,9 +10,9 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "github.com/cheggaaa/pb" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/object/hash.go b/cmd/frostfs-cli/modules/object/hash.go index 26243e7e7..20cb0818b 100644 --- a/cmd/frostfs-cli/modules/object/hash.go +++ b/cmd/frostfs-cli/modules/object/hash.go @@ -9,9 +9,9 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/checksum" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/checksum" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/object/head.go b/cmd/frostfs-cli/modules/object/head.go index db466e588..225f77b1a 100644 --- a/cmd/frostfs-cli/modules/object/head.go +++ b/cmd/frostfs-cli/modules/object/head.go @@ -6,15 +6,15 @@ import ( "fmt" "os" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/object/lock.go b/cmd/frostfs-cli/modules/object/lock.go index d2e9af24c..a2853a2b7 100644 --- a/cmd/frostfs-cli/modules/object/lock.go +++ b/cmd/frostfs-cli/modules/object/lock.go @@ -7,16 +7,16 @@ import ( "strconv" "time" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/object/nodes.go b/cmd/frostfs-cli/modules/object/nodes.go index 50c47e822..ef0dc3b76 100644 --- a/cmd/frostfs-cli/modules/object/nodes.go +++ b/cmd/frostfs-cli/modules/object/nodes.go @@ -15,13 +15,13 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "github.com/spf13/cobra" "golang.org/x/sync/errgroup" ) diff --git a/cmd/frostfs-cli/modules/object/put.go b/cmd/frostfs-cli/modules/object/put.go index 45e02edb3..58e32b131 100644 --- a/cmd/frostfs-cli/modules/object/put.go +++ b/cmd/frostfs-cli/modules/object/put.go @@ -10,14 +10,14 @@ import ( "strings" "time" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" "github.com/cheggaaa/pb" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/object/range.go b/cmd/frostfs-cli/modules/object/range.go index 0eee7bdba..5e594ed71 100644 --- a/cmd/frostfs-cli/modules/object/range.go +++ b/cmd/frostfs-cli/modules/object/range.go @@ -13,9 +13,9 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/object/search.go b/cmd/frostfs-cli/modules/object/search.go index ca5d78bc9..c67794c8e 100644 --- a/cmd/frostfs-cli/modules/object/search.go +++ b/cmd/frostfs-cli/modules/object/search.go @@ -9,9 +9,9 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oidSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oidSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/object/util.go b/cmd/frostfs-cli/modules/object/util.go index 37e9f74e0..4343aba9c 100644 --- a/cmd/frostfs-cli/modules/object/util.go +++ b/cmd/frostfs-cli/modules/object/util.go @@ -12,13 +12,13 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" sessionCli "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/session" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto/ecdsa" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/bearer" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/crypto/ecdsa" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/session" "github.com/spf13/cobra" "github.com/spf13/viper" ) diff --git a/cmd/frostfs-cli/modules/session/create.go b/cmd/frostfs-cli/modules/session/create.go index e13200a5d..676317109 100644 --- a/cmd/frostfs-cli/modules/session/create.go +++ b/cmd/frostfs-cli/modules/session/create.go @@ -10,9 +10,9 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto/ecdsa" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/crypto/ecdsa" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/session" "github.com/google/uuid" "github.com/spf13/cobra" "github.com/spf13/viper" diff --git a/cmd/frostfs-cli/modules/tree/add.go b/cmd/frostfs-cli/modules/tree/add.go index 8ceea4173..24e36216e 100644 --- a/cmd/frostfs-cli/modules/tree/add.go +++ b/cmd/frostfs-cli/modules/tree/add.go @@ -9,8 +9,8 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/tree" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/tree/add_by_path.go b/cmd/frostfs-cli/modules/tree/add_by_path.go index ea815dbfe..1d5f10c89 100644 --- a/cmd/frostfs-cli/modules/tree/add_by_path.go +++ b/cmd/frostfs-cli/modules/tree/add_by_path.go @@ -8,9 +8,9 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/tree" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/tree/get_by_path.go b/cmd/frostfs-cli/modules/tree/get_by_path.go index f239066cd..a469e48b3 100644 --- a/cmd/frostfs-cli/modules/tree/get_by_path.go +++ b/cmd/frostfs-cli/modules/tree/get_by_path.go @@ -8,9 +8,9 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/tree" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/tree/get_op_log.go b/cmd/frostfs-cli/modules/tree/get_op_log.go index b1b307f62..5d52e63a3 100644 --- a/cmd/frostfs-cli/modules/tree/get_op_log.go +++ b/cmd/frostfs-cli/modules/tree/get_op_log.go @@ -9,8 +9,8 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/tree" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/tree/list.go b/cmd/frostfs-cli/modules/tree/list.go index a25d066d5..96676d7cb 100644 --- a/cmd/frostfs-cli/modules/tree/list.go +++ b/cmd/frostfs-cli/modules/tree/list.go @@ -6,8 +6,8 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/tree" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/tree/move.go b/cmd/frostfs-cli/modules/tree/move.go index 84b2fb80e..45c1b9e75 100644 --- a/cmd/frostfs-cli/modules/tree/move.go +++ b/cmd/frostfs-cli/modules/tree/move.go @@ -9,8 +9,8 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/tree" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/tree/remove.go b/cmd/frostfs-cli/modules/tree/remove.go index 74e9d9749..ff194b5e4 100644 --- a/cmd/frostfs-cli/modules/tree/remove.go +++ b/cmd/frostfs-cli/modules/tree/remove.go @@ -7,8 +7,8 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/tree" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/tree/subtree.go b/cmd/frostfs-cli/modules/tree/subtree.go index 64cb351ec..b084a883f 100644 --- a/cmd/frostfs-cli/modules/tree/subtree.go +++ b/cmd/frostfs-cli/modules/tree/subtree.go @@ -9,8 +9,8 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/tree" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/util/acl.go b/cmd/frostfs-cli/modules/util/acl.go index 4c2e324b3..c8857c102 100644 --- a/cmd/frostfs-cli/modules/util/acl.go +++ b/cmd/frostfs-cli/modules/util/acl.go @@ -9,8 +9,8 @@ import ( "strings" "text/tabwriter" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/acl" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/eacl" "github.com/flynn-archive/go-shlex" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/olekukonko/tablewriter" diff --git a/cmd/frostfs-cli/modules/util/sign_session.go b/cmd/frostfs-cli/modules/util/sign_session.go index ba76678dc..e5bfdce37 100644 --- a/cmd/frostfs-cli/modules/util/sign_session.go +++ b/cmd/frostfs-cli/modules/util/sign_session.go @@ -11,7 +11,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/session" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-lens/internal/blobovnicza/inspect.go b/cmd/frostfs-lens/internal/blobovnicza/inspect.go index b1a6e3fd2..b3330fad2 100644 --- a/cmd/frostfs-lens/internal/blobovnicza/inspect.go +++ b/cmd/frostfs-lens/internal/blobovnicza/inspect.go @@ -3,8 +3,8 @@ package blobovnicza import ( common "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/internal" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobovnicza" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-lens/internal/blobovnicza/list.go b/cmd/frostfs-lens/internal/blobovnicza/list.go index d327dbc41..56e302277 100644 --- a/cmd/frostfs-lens/internal/blobovnicza/list.go +++ b/cmd/frostfs-lens/internal/blobovnicza/list.go @@ -7,7 +7,7 @@ import ( common "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/internal" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobovnicza" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-lens/internal/meta/inspect.go b/cmd/frostfs-lens/internal/meta/inspect.go index 9eb60f966..e603f966a 100644 --- a/cmd/frostfs-lens/internal/meta/inspect.go +++ b/cmd/frostfs-lens/internal/meta/inspect.go @@ -7,8 +7,8 @@ import ( common "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/internal" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/blobovniczatree" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-lens/internal/printers.go b/cmd/frostfs-lens/internal/printers.go index ea0cbc8e0..ee75e716c 100644 --- a/cmd/frostfs-lens/internal/printers.go +++ b/cmd/frostfs-lens/internal/printers.go @@ -3,9 +3,9 @@ package common import ( "os" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-lens/internal/writecache/inspect.go b/cmd/frostfs-lens/internal/writecache/inspect.go index afc986c8b..fb6ec71c6 100644 --- a/cmd/frostfs-lens/internal/writecache/inspect.go +++ b/cmd/frostfs-lens/internal/writecache/inspect.go @@ -5,7 +5,7 @@ import ( common "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/internal" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-lens/internal/writecache/list.go b/cmd/frostfs-lens/internal/writecache/list.go index bcbae0ec9..2340c7139 100644 --- a/cmd/frostfs-lens/internal/writecache/list.go +++ b/cmd/frostfs-lens/internal/writecache/list.go @@ -7,7 +7,7 @@ import ( common "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/internal" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-node/accounting.go b/cmd/frostfs-node/accounting.go index ec737f8a0..848875242 100644 --- a/cmd/frostfs-node/accounting.go +++ b/cmd/frostfs-node/accounting.go @@ -4,7 +4,7 @@ import ( "context" "net" - accountingGRPC "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/accounting/grpc" + accountingGRPC "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/accounting/grpc" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/balance" accountingTransportGRPC "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network/transport/accounting/grpc" accountingService "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/accounting" diff --git a/cmd/frostfs-node/cache.go b/cmd/frostfs-node/cache.go index bf68d245f..c8eeeda89 100644 --- a/cmd/frostfs-node/cache.go +++ b/cmd/frostfs-node/cache.go @@ -6,11 +6,11 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" putsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/put" utilSync "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/sync" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" lru "github.com/hashicorp/golang-lru/v2" "github.com/hashicorp/golang-lru/v2/expirable" ) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index a1f7bba40..714d581ff 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -15,7 +15,6 @@ import ( "syscall" "time" - netmapV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config" apiclientconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/apiclient" contractsconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/contracts" @@ -31,6 +30,7 @@ import ( tracingconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/tracing" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/chainbase" + netmapV2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" netmapCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor" @@ -51,6 +51,10 @@ import ( netmap2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network/cache" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/version" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" objectService "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object" getsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/get" @@ -65,10 +69,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/state" "git.frostfs.info/TrueCloudLab/frostfs-observability/logging/lokicore" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/version" policy_engine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" policy_client "git.frostfs.info/TrueCloudLab/policy-engine/pkg/morph/policy" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" diff --git a/cmd/frostfs-node/container.go b/cmd/frostfs-node/container.go index d566c0af3..97876fb22 100644 --- a/cmd/frostfs-node/container.go +++ b/cmd/frostfs-node/container.go @@ -5,18 +5,18 @@ import ( "context" "net" - containerGRPC "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container/grpc" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + containerGRPC "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/container/grpc" containerCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" cntClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/frostfsid" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" containerEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/container" containerTransportGRPC "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network/transport/container/grpc" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" containerService "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/container" containerMorph "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/container/morph" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" "go.uber.org/zap" "google.golang.org/grpc" ) diff --git a/cmd/frostfs-node/netmap.go b/cmd/frostfs-node/netmap.go index b1d854da4..1ac9e2e2e 100644 --- a/cmd/frostfs-node/netmap.go +++ b/cmd/frostfs-node/netmap.go @@ -8,8 +8,8 @@ import ( "net" "sync/atomic" - netmapGRPC "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap/grpc" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + netmapGRPC "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/netmap/grpc" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/metrics" nmClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" @@ -17,10 +17,10 @@ import ( netmapEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" netmapTransportGRPC "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network/transport/netmap/grpc" + netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/version" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" netmapService "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/netmap" - netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/version" "go.uber.org/zap" "google.golang.org/grpc" ) diff --git a/cmd/frostfs-node/notificator.go b/cmd/frostfs-node/notificator.go index f9bb31fed..56f3f831f 100644 --- a/cmd/frostfs-node/notificator.go +++ b/cmd/frostfs-node/notificator.go @@ -10,11 +10,11 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/netmap" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/notificator" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/notificator/nats" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.uber.org/zap" ) diff --git a/cmd/frostfs-node/object.go b/cmd/frostfs-node/object.go index 7f1d094fd..1499b31fc 100644 --- a/cmd/frostfs-node/object.go +++ b/cmd/frostfs-node/object.go @@ -6,12 +6,12 @@ import ( "fmt" "net" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - objectGRPC "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object/grpc" metricsconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/metrics" policerconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/policer" replicatorconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/replicator" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" + objectGRPC "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object/grpc" containercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" objectCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" @@ -21,6 +21,12 @@ import ( nmClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network/cache" objectTransportGRPC "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network/transport/object/grpc" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + eaclSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/eacl" + netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" objectService "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/acl" v2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/acl/v2" @@ -38,12 +44,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/policer" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/replicator" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - eaclSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" - netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" "go.uber.org/zap" "google.golang.org/grpc" ) diff --git a/cmd/frostfs-node/session.go b/cmd/frostfs-node/session.go index ee21ec230..62bd0a898 100644 --- a/cmd/frostfs-node/session.go +++ b/cmd/frostfs-node/session.go @@ -6,17 +6,17 @@ import ( "net" "time" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - sessionGRPC "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session/grpc" nodeconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/node" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" + sessionGRPC "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session/grpc" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/netmap" sessionTransportGRPC "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network/transport/session/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" sessionSvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/session" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/session/storage" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/session/storage/persistent" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/session/storage/temporary" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" "google.golang.org/grpc" ) diff --git a/cmd/frostfs-node/tree.go b/cmd/frostfs-node/tree.go index dced05bc2..c169a1b5c 100644 --- a/cmd/frostfs-node/tree.go +++ b/cmd/frostfs-node/tree.go @@ -13,8 +13,8 @@ import ( containerClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" containerEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/container" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/tree" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "go.uber.org/zap" "google.golang.org/grpc" ) diff --git a/cmd/internal/common/exit.go b/cmd/internal/common/exit.go index 9e4fa3098..d49abcef8 100644 --- a/cmd/internal/common/exit.go +++ b/cmd/internal/common/exit.go @@ -5,7 +5,7 @@ import ( "fmt" "os" - sdkstatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" + sdkstatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" "github.com/spf13/cobra" ) diff --git a/cmd/internal/common/netmap.go b/cmd/internal/common/netmap.go index 79b03a726..bb55a4866 100644 --- a/cmd/internal/common/netmap.go +++ b/cmd/internal/common/netmap.go @@ -3,7 +3,7 @@ package common import ( "encoding/hex" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" "github.com/spf13/cobra" ) diff --git a/go.mod b/go.mod index 2c2eac68f..0bb60615e 100644 --- a/go.mod +++ b/go.mod @@ -4,10 +4,10 @@ go 1.20 require ( code.gitea.io/sdk/gitea v0.17.1 - git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240215124401-634e24aba715 git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.0 + git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api v0.0.0-00010101000000-000000000000 + git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk v0.0.0-00010101000000-000000000000 git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 - git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240301150205-6fe4e2541d0b git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240307151106-2ec958cbfdfd git.frostfs.info/TrueCloudLab/tzhash v1.8.0 @@ -130,3 +130,7 @@ require ( lukechampine.com/blake3 v1.2.1 // indirect rsc.io/tmplfunc v0.0.3 // indirect ) + +replace git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk => ./pkg/sdk + +replace git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api => ./pkg/api diff --git a/go.sum b/go.sum index d90bf0f6a..a306dc8dc 100644 --- a/go.sum +++ b/go.sum @@ -1,15 +1,11 @@ code.gitea.io/sdk/gitea v0.17.1 h1:3jCPOG2ojbl8AcfaUCRYLT5MUcBMFwS0OSK2mA5Zok8= code.gitea.io/sdk/gitea v0.17.1/go.mod h1:aCnBqhHpoEWA180gMbaCtdX9Pl6BWBAuuP2miadoTNM= -git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240215124401-634e24aba715 h1:EDtL9OJcdeevV/jmNMtHugulAQprdOnknNPvLB3LRgE= -git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240215124401-634e24aba715/go.mod h1:uY0AYmCznjZdghDnAk7THFIe1Vlg531IxUcus7ZfUJI= git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.0 h1:FzurjElUwC7InY9v5rzXReKbfBL5yRJKSWJPq6BKhH0= git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.0/go.mod h1:F/fe1OoIDKr5Bz99q4sriuHDuf3aZefZy9ZsCqEtgxc= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSVCB8JNSfPG7Uk4r2oSk= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0/go.mod h1:RUIKZATQLJ+TaYQa60X2fTDwfuhMfm8Ar60bQ5fr+vU= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 h1:PaZ8GpnUoXxUoNsc1qp36bT2u7FU+neU4Jn9cl8AWqI= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65/go.mod h1:6aAX80dvJ3r5fjN9CzzPglRptoiPgIC9KFGGsUA+1Hw= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240301150205-6fe4e2541d0b h1:nLIWYXe4e1fWgpKeMfVke/CNBn388egh4fArFdvhfHw= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240301150205-6fe4e2541d0b/go.mod h1:XcgrbZ88XfvhAMxmZCQJ0dv6FyRSq6Mg2J7nN8uuO0k= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240307151106-2ec958cbfdfd h1:pyIl9f4nIr7ekJ73W9keLIQ5dpoKb8o6xNmodsXY5+o= diff --git a/internal/ape/converter.go b/internal/ape/converter.go index 2adc7645a..f8f800308 100644 --- a/internal/ape/converter.go +++ b/internal/ape/converter.go @@ -4,8 +4,8 @@ import ( "encoding/hex" "fmt" - v2acl "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" + v2acl "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/acl" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/eacl" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" ) @@ -41,8 +41,8 @@ func ConvertEACLToAPE(eaclTable *eacl.Table) (*apechain.Chain, error) { for _, eaclRecord := range eaclTable.Records() { if len(eaclRecord.Targets()) == 0 { - // see https://git.frostfs.info/TrueCloudLab/frostfs-sdk-go/src/commit/ab75edd70939564421936d207ef80d6c1398b51b/eacl/validator.go#L101 - // and https://git.frostfs.info/TrueCloudLab/frostfs-sdk-go/src/commit/ab75edd70939564421936d207ef80d6c1398b51b/eacl/validator.go#L36 + // see https://git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/src/commit/ab75edd70939564421936d207ef80d6c1398b51b/eacl/validator.go#L101 + // and https://git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/src/commit/ab75edd70939564421936d207ef80d6c1398b51b/eacl/validator.go#L36 // such record doesn't have any effect continue } @@ -70,7 +70,7 @@ func ConvertEACLToAPE(eaclTable *eacl.Table) (*apechain.Chain, error) { } func appendTargetsOnly(source []apechain.Rule, st apechain.Status, act apechain.Actions, res apechain.Resources, targets []eacl.Target) []apechain.Rule { - // see https://git.frostfs.info/TrueCloudLab/frostfs-sdk-go/src/commit/ab75edd70939564421936d207ef80d6c1398b51b/eacl/validator.go#L101 + // see https://git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/src/commit/ab75edd70939564421936d207ef80d6c1398b51b/eacl/validator.go#L101 // role OR public key must be equal rule := apechain.Rule{ Status: st, @@ -101,7 +101,7 @@ func appendTargetsOnly(source []apechain.Rule, st apechain.Status, act apechain. func appendTargetsAndFilters(source []apechain.Rule, st apechain.Status, act apechain.Actions, res apechain.Resources, targets []eacl.Target, filters []eacl.Filter, ) ([]apechain.Rule, error) { - // see https://git.frostfs.info/TrueCloudLab/frostfs-sdk-go/src/commit/ab75edd70939564421936d207ef80d6c1398b51b/eacl/validator.go#L101 + // see https://git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/src/commit/ab75edd70939564421936d207ef80d6c1398b51b/eacl/validator.go#L101 // role OR public key must be equal // so filters are repeated for each role and public key var err error diff --git a/internal/ape/converter_test.go b/internal/ape/converter_test.go index b5f8939c4..0bceabf1e 100644 --- a/internal/ape/converter_test.go +++ b/internal/ape/converter_test.go @@ -5,8 +5,8 @@ import ( "fmt" "testing" - cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/eacl" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" "git.frostfs.info/TrueCloudLab/policy-engine/pkg/resource" nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" diff --git a/pkg/api/CHANGELOG.md b/pkg/api/CHANGELOG.md new file mode 100644 index 000000000..77bf5a258 --- /dev/null +++ b/pkg/api/CHANGELOG.md @@ -0,0 +1,50 @@ +# Changelog + +## [Unreleased] + +### Added +### Fixed +### Changed +### Removed +### Updated + +## [2.16.0] - 2023-09-14 - Academy of Sciences Glacier + +### Added +- Add impersonate flag to bearer token (#17) +- `NOT` and `UNIQUE` keywords to the placement policy (#26) +- `PutSingle` RPC (#45) + +### Fixed +### Changed +- `StableSize()` is optimized and no does no allocations (#49) +- Marshaling code now uses `protowire` package (#50) +### Removed +- Reputation system (#21) + +### Updated +- `github.com/stretchr/testify` to `v1.8.3` +- `go.opentelemetry.io/otel` to `v1.15.1` +- `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc` to `v1.15.1` +- `go.opentelemetry.io/otel/exporters/stdout/stdouttrace` to `v1.15.1` +- `go.opentelemetry.io/otel/sdk` to `v1.15.1` +- `go.opentelemetry.io/otel/trace` to `v1.15.1` +- `golang.org/x/sync` to `v0.2.0` +- `google.golang.org/grpc` to `v1.55.0` +- `google.golang.org/protobuf` to `v1.30.0` + + +## 2.15.0 - 2023-04-11 + +### Added +- Basic tracing support (#12) +- Optimize signature checking (#3) + +Initial public release. + +## Older versions + +This project is a fork of [NeoFS](https://github.com/nspcc-dev/neofs-api-go) from version v2.14.0. +To see CHANGELOG for older versions, refer to https://github.com/nspcc-dev/neofs-api-go/blob/master/CHANGELOG.md. + +[Unreleased]: https://github.com/TrueCloudLab/compare/v2.15.0...master diff --git a/pkg/api/CONTRIBUTING.md b/pkg/api/CONTRIBUTING.md new file mode 100644 index 000000000..baa772533 --- /dev/null +++ b/pkg/api/CONTRIBUTING.md @@ -0,0 +1,152 @@ +# Contribution guide + +First, thank you for contributing! We love and encourage pull requests from +everyone. Please follow the guidelines: + +- Check the open [issues](https://github.com/TrueCloudLab/frostfs-api-go/issues) and + [pull requests](https://github.com/TrueCloudLab/frostfs-api-go/pulls) for existing + discussions. + +- Open an issue first, to discuss a new feature or enhancement. + +- Open a pull request, and reference the relevant issue(s). + +- Make sure your commits are logically separated and have good comments + explaining the details of your change. + +- After receiving feedback, amend your commits or add new ones as + appropriate. + +- **Have fun!** + +## Development Workflow + +Start by forking the `frostfs-api-go` repository, make changes in a branch and then +send a pull request. We encourage pull requests to discuss code changes. Here +are the steps in details: + +### Set up your GitHub Repository +Fork [FrostFS node upstream](https://github.com/TrueCloudLab/frostfs-api-go/fork) source +repository to your own personal repository. Copy the URL of your fork (you will +need it for the `git clone` command below). + +```sh +$ git clone https://github.com/TrueCloudLab/frostfs-api-go +``` + +### Set up git remote as ``upstream`` +```sh +$ cd frostfs-api-go +$ git remote add upstream https://github.com/TrueCloudLab/frostfs-api-go +$ git fetch upstream +$ git merge upstream/master +... +``` + +### Create your feature branch +Before making code changes, make sure you create a separate branch for these +changes. Maybe you will find it convenient to name branch in +`/-` format. + +``` +$ git checkout -b feature/123-something_awesome +``` + +### Test your changes +After your code changes, make sure + +- To add test cases for the new code. +- To run `make lint` +- To squash your commits into a single commit or a series of logically separated + commits run `git rebase -i`. It's okay to force update your pull request. + +### Commit changes +After verification, commit your changes. This is a [great +post](https://chris.beams.io/posts/git-commit/) on how to write useful commit +messages. Try following this template: + +``` +[#Issue] Summary + +Description + + + + +``` + +``` +$ git commit -am '[#123] Add some feature' +``` + +### Push to the branch +Push your locally committed changes to the remote origin (your fork) +``` +$ git push origin feature/123-something_awesome +``` + +### Create a Pull Request +Pull requests can be created via GitHub. Refer to [this +document](https://help.github.com/articles/creating-a-pull-request/) for +detailed steps on how to create a pull request. After a Pull Request gets peer +reviewed and approved, it will be merged. + +## DCO Sign off + +All authors to the project retain copyright to their work. However, to ensure +that they are only submitting work that they have rights to, we are requiring +everyone to acknowledge this by signing their work. + +Any copyright notices in this repository should specify the authors as "the +contributors". + +To sign your work, just add a line like this at the end of your commit message: + +``` +Signed-off-by: Samii Sakisaka +``` + +This can easily be done with the `--signoff` option to `git commit`. + +By doing this you state that you can certify the following (from [The Developer +Certificate of Origin](https://developercertificate.org/)): + +``` +Developer Certificate of Origin +Version 1.1 + +Copyright (C) 2004, 2006 The Linux Foundation and its contributors. +1 Letterman Drive +Suite D4700 +San Francisco, CA, 94129 + +Everyone is permitted to copy and distribute verbatim copies of this +license document, but changing it is not allowed. + + +Developer's Certificate of Origin 1.1 + +By making a contribution to this project, I certify that: + +(a) The contribution was created in whole or in part by me and I + have the right to submit it under the open source license + indicated in the file; or + +(b) The contribution is based upon previous work that, to the best + of my knowledge, is covered under an appropriate open source + license and I have the right under that license to submit that + work with modifications, whether created in whole or in part + by me, under the same open source license (unless I am + permitted to submit under a different license), as indicated + in the file; or + +(c) The contribution was provided directly to me by some other + person who certified (a), (b) or (c) and I have not modified + it. + +(d) I understand and agree that this project and the contribution + are public and that a record of the contribution (including all + personal information I submit with it, including my sign-off) is + maintained indefinitely and may be redistributed consistent with + this project or the open source license(s) involved. +``` diff --git a/pkg/api/CREDITS.md b/pkg/api/CREDITS.md new file mode 100644 index 000000000..a868b21ba --- /dev/null +++ b/pkg/api/CREDITS.md @@ -0,0 +1,31 @@ +# Credits + +FrostFS continues the development of NeoFS. + +Initial NeoFS research and development (2018-2020) was done by +[NeoSPCC](https://nspcc.ru) team. + +In alphabetical order: + +- Alexey Vanin +- Anastasia Prasolova +- Anatoly Bogatyrev +- Evgeny Kulikov +- Evgeny Stratonikov +- Leonard Liubich +- Sergei Liubich +- Stanislav Bogatyrev + +# Contributors + +In chronological order: +- Pavel Korotkov +- Pavel Karpy +- Angira Kekteeva + +# Special Thanks + +For product development support: + +- Fabian Wahle +- Neo Global Development diff --git a/pkg/api/LICENSE b/pkg/api/LICENSE new file mode 100644 index 000000000..261eeb9e9 --- /dev/null +++ b/pkg/api/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/pkg/api/Makefile b/pkg/api/Makefile new file mode 100755 index 000000000..239565bee --- /dev/null +++ b/pkg/api/Makefile @@ -0,0 +1,73 @@ +#!/usr/bin/make -f +SHELL = bash + +VERSION ?= $(shell git describe --tags --match "v*" --abbrev=8 --dirty --always) + +.PHONY: dep fmts fumpt imports protoc test lint version help + +# Pull go dependencies +dep: + @printf "⇒ Tidy requirements : " + CGO_ENABLED=0 \ + go mod tidy -v && echo OK + @printf "⇒ Download requirements: " + CGO_ENABLED=0 \ + go mod download && echo OK + @printf "⇒ Install test requirements: " + CGO_ENABLED=0 \ + go test ./... && echo OK + +# Run all code formatters +fmts: fumpt imports + +# Reformat imports +imports: + @echo "⇒ Processing goimports check" + @for f in `find . -type f -name '*.go' -not -path './vendor/*' -not -name '*.pb.go' -prune`; do \ + goimports -w $$f; \ + done + +# Run gofumpt +fumpt: + @echo "⇒ Processing gofumpt check" + @gofumpt -l -w . + +# Regenerate code for proto files +protoc: + @GOPRIVATE=github.com/TrueCloudLab go mod vendor + # Install specific version for protobuf lib + @go list -f '{{.Path}}/...@{{.Version}}' -m google.golang.org/protobuf | xargs go install -v + # Protoc generate + @for f in `find . -type f -name '*.proto' -not -path './vendor/*'`; do \ + echo "⇒ Processing $$f "; \ + protoc \ + --proto_path=.:./vendor:/usr/local/include \ + --go_out=. --go_opt=paths=source_relative \ + --go-grpc_opt=require_unimplemented_servers=false \ + --go-grpc_out=. --go-grpc_opt=paths=source_relative $$f; \ + done + rm -rf vendor + +# Run Unit Test with go test +test: GOFLAGS ?= "-count=1" +test: + @echo "⇒ Running go test" + @GOFLAGS="$(GOFLAGS)" go test ./... + +# Run linters +lint: + @golangci-lint run + +# Print version +version: + @echo $(VERSION) + +# Show this help prompt +help: + @echo ' Usage:' + @echo '' + @echo ' make ' + @echo '' + @echo ' Targets:' + @echo '' + @awk '/^#/{ comment = substr($$0,3) } comment && /^[a-zA-Z][a-zA-Z0-9_-]+ ?:/{ print " ", $$1, comment }' $(MAKEFILE_LIST) | column -t -s ':' | grep -v 'IGNORE' | sort -u diff --git a/pkg/api/README.md b/pkg/api/README.md new file mode 100644 index 000000000..73f06e379 --- /dev/null +++ b/pkg/api/README.md @@ -0,0 +1,37 @@ +

+FrostFS +

+

+ Low-level Golang API for FrostFS +

+ +--- +![Tests](https://github.com/TrueCloudLab/frostfs-api-go/workflows/frostfs-api-go%20tests/badge.svg) +[![codecov](https://codecov.io/gh/TrueCloudLab/frostfs-api-go/branch/master/graph/badge.svg)](https://codecov.io/gh/TrueCloudLab/frostfs-api-go) +[![Report](https://goreportcard.com/badge/github.com/TrueCloudLab/frostfs-api-go)](https://goreportcard.com/report/github.com/TrueCloudLab/frostfs-api-go) +[![GitHub release](https://img.shields.io/github/release/TrueCloudLab/frostfs-api-go.svg)](https://github.com/TrueCloudLab/frostfs-api-go) +![GitHub license](https://img.shields.io/github/license/TrueCloudLab/frostfs-api-go.svg?style=popout) + +# Overview + +Go implementation of recent [FrostFS API](https://github.com/TrueCloudLab/frostfs-api) +versions. For a more high-level SDK see [FrostFS SDK](https://github.com/TrueCloudLab/frostfs-sdk-go). + +## Frostfs-Api compatibility + +|frostfs-api-go version|supported frostfs-api versions| +|:------------------:|:--------------------------:| +|v2.14.x|[v2.14.0](https://github.com/TrueCloudLab/frostfs-api/releases/tag/v2.14.0)| + +## Contributing + +Feel free to contribute to this project after reading the [contributing +guidelines](CONTRIBUTING.md). + +Before starting to work on a certain topic, create a new issue first, describing +the feature/topic you are going to implement. + +## License + +This project is licensed under the Apache 2.0 License - +see the [LICENSE](LICENSE) file for details diff --git a/pkg/api/accounting/accounting.go b/pkg/api/accounting/accounting.go new file mode 100644 index 000000000..20c4d2a46 --- /dev/null +++ b/pkg/api/accounting/accounting.go @@ -0,0 +1,104 @@ +package accounting + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" +) + +type BalanceRequestBody struct { + ownerID *refs.OwnerID +} + +type BalanceResponseBody struct { + bal *Decimal +} + +type Decimal struct { + val int64 + + prec uint32 +} + +type BalanceRequest struct { + body *BalanceRequestBody + + session.RequestHeaders +} + +type BalanceResponse struct { + body *BalanceResponseBody + + session.ResponseHeaders +} + +func (b *BalanceRequestBody) GetOwnerID() *refs.OwnerID { + if b != nil { + return b.ownerID + } + + return nil +} + +func (b *BalanceRequestBody) SetOwnerID(v *refs.OwnerID) { + b.ownerID = v +} + +func (b *BalanceRequest) GetBody() *BalanceRequestBody { + if b != nil { + return b.body + } + + return nil +} + +func (b *BalanceRequest) SetBody(v *BalanceRequestBody) { + b.body = v +} + +func (d *Decimal) GetValue() int64 { + if d != nil { + return d.val + } + + return 0 +} + +func (d *Decimal) SetValue(v int64) { + d.val = v +} + +func (d *Decimal) GetPrecision() uint32 { + if d != nil { + return d.prec + } + + return 0 +} + +func (d *Decimal) SetPrecision(v uint32) { + d.prec = v +} + +func (br *BalanceResponseBody) GetBalance() *Decimal { + if br != nil { + return br.bal + } + + return nil +} + +func (br *BalanceResponseBody) SetBalance(v *Decimal) { + br.bal = v +} + +func (br *BalanceResponse) GetBody() *BalanceResponseBody { + if br != nil { + return br.body + } + + return nil +} + +func (br *BalanceResponse) SetBody(v *BalanceResponseBody) { + br.body = v +} diff --git a/pkg/api/accounting/convert.go b/pkg/api/accounting/convert.go new file mode 100644 index 000000000..024710080 --- /dev/null +++ b/pkg/api/accounting/convert.go @@ -0,0 +1,178 @@ +package accounting + +import ( + accounting "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/accounting/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + refsGRPC "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/message" +) + +func (b *BalanceRequestBody) ToGRPCMessage() grpc.Message { + var m *accounting.BalanceRequest_Body + + if b != nil { + m = new(accounting.BalanceRequest_Body) + + m.SetOwnerId(b.ownerID.ToGRPCMessage().(*refsGRPC.OwnerID)) + } + + return m +} + +func (b *BalanceRequestBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*accounting.BalanceRequest_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + ownerID := v.GetOwnerId() + if ownerID == nil { + b.ownerID = nil + } else { + if b.ownerID == nil { + b.ownerID = new(refs.OwnerID) + } + + err = b.ownerID.FromGRPCMessage(ownerID) + } + + return err +} + +func (b *BalanceRequest) ToGRPCMessage() grpc.Message { + var m *accounting.BalanceRequest + + if b != nil { + m = new(accounting.BalanceRequest) + + m.SetBody(b.body.ToGRPCMessage().(*accounting.BalanceRequest_Body)) + b.RequestHeaders.ToMessage(m) + } + + return m +} + +func (b *BalanceRequest) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*accounting.BalanceRequest) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + b.body = nil + } else { + if b.body == nil { + b.body = new(BalanceRequestBody) + } + + err = b.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return b.RequestHeaders.FromMessage(v) +} + +func (d *Decimal) ToGRPCMessage() grpc.Message { + var m *accounting.Decimal + + if d != nil { + m = new(accounting.Decimal) + + m.SetValue(d.val) + m.SetPrecision(d.prec) + } + + return m +} + +func (d *Decimal) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*accounting.Decimal) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + d.val = v.GetValue() + d.prec = v.GetPrecision() + + return nil +} + +func (br *BalanceResponseBody) ToGRPCMessage() grpc.Message { + var m *accounting.BalanceResponse_Body + + if br != nil { + m = new(accounting.BalanceResponse_Body) + + m.SetBalance(br.bal.ToGRPCMessage().(*accounting.Decimal)) + } + + return m +} + +func (br *BalanceResponseBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*accounting.BalanceResponse_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + bal := v.GetBalance() + if bal == nil { + br.bal = nil + } else { + if br.bal == nil { + br.bal = new(Decimal) + } + + err = br.bal.FromGRPCMessage(bal) + } + + return err +} + +func (br *BalanceResponse) ToGRPCMessage() grpc.Message { + var m *accounting.BalanceResponse + + if br != nil { + m = new(accounting.BalanceResponse) + + m.SetBody(br.body.ToGRPCMessage().(*accounting.BalanceResponse_Body)) + br.ResponseHeaders.ToMessage(m) + } + + return m +} + +func (br *BalanceResponse) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*accounting.BalanceResponse) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + br.body = nil + } else { + if br.body == nil { + br.body = new(BalanceResponseBody) + } + + err = br.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return br.ResponseHeaders.FromMessage(v) +} diff --git a/pkg/api/accounting/grpc/service.go b/pkg/api/accounting/grpc/service.go new file mode 100644 index 000000000..ad9d5558c --- /dev/null +++ b/pkg/api/accounting/grpc/service.go @@ -0,0 +1,46 @@ +package accounting + +import ( + refs "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs/grpc" + session "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session/grpc" +) + +// SetOwnerId sets identifier of the account owner. +func (m *BalanceRequest_Body) SetOwnerId(v *refs.OwnerID) { + m.OwnerId = v +} + +// SetBody sets body of the request. +func (m *BalanceRequest) SetBody(v *BalanceRequest_Body) { + m.Body = v +} + +// SetMetaHeader sets meta header of the request. +func (m *BalanceRequest) SetMetaHeader(v *session.RequestMetaHeader) { + m.MetaHeader = v +} + +// SetVerifyHeader sets verification header of the request. +func (m *BalanceRequest) SetVerifyHeader(v *session.RequestVerificationHeader) { + m.VerifyHeader = v +} + +// SetBalance sets balance value of the response. +func (m *BalanceResponse_Body) SetBalance(v *Decimal) { + m.Balance = v +} + +// SetBody sets body of the response. +func (m *BalanceResponse) SetBody(v *BalanceResponse_Body) { + m.Body = v +} + +// SetMetaHeader sets meta header of the response. +func (m *BalanceResponse) SetMetaHeader(v *session.ResponseMetaHeader) { + m.MetaHeader = v +} + +// SetVerifyHeader sets verification header of the response. +func (m *BalanceResponse) SetVerifyHeader(v *session.ResponseVerificationHeader) { + m.VerifyHeader = v +} diff --git a/pkg/api/accounting/grpc/service.pb.go b/pkg/api/accounting/grpc/service.pb.go new file mode 100644 index 000000000..3ab9b4ef9 --- /dev/null +++ b/pkg/api/accounting/grpc/service.pb.go @@ -0,0 +1,451 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.33.0 +// protoc v4.25.3 +// source: accounting/grpc/service.proto + +package accounting + +import ( + grpc1 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs/grpc" + grpc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session/grpc" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// BalanceRequest message +type BalanceRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Body of the balance request message. + Body *BalanceRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Carries request meta information. Header data is used only to regulate + // message transport and does not affect request execution. + MetaHeader *grpc.RequestMetaHeader `protobuf:"bytes,2,opt,name=meta_header,json=metaHeader,proto3" json:"meta_header,omitempty"` + // Carries request verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + VerifyHeader *grpc.RequestVerificationHeader `protobuf:"bytes,3,opt,name=verify_header,json=verifyHeader,proto3" json:"verify_header,omitempty"` +} + +func (x *BalanceRequest) Reset() { + *x = BalanceRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_accounting_grpc_service_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *BalanceRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BalanceRequest) ProtoMessage() {} + +func (x *BalanceRequest) ProtoReflect() protoreflect.Message { + mi := &file_accounting_grpc_service_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BalanceRequest.ProtoReflect.Descriptor instead. +func (*BalanceRequest) Descriptor() ([]byte, []int) { + return file_accounting_grpc_service_proto_rawDescGZIP(), []int{0} +} + +func (x *BalanceRequest) GetBody() *BalanceRequest_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *BalanceRequest) GetMetaHeader() *grpc.RequestMetaHeader { + if x != nil { + return x.MetaHeader + } + return nil +} + +func (x *BalanceRequest) GetVerifyHeader() *grpc.RequestVerificationHeader { + if x != nil { + return x.VerifyHeader + } + return nil +} + +// BalanceResponse message +type BalanceResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Body of the balance response message. + Body *BalanceResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Carries response meta information. Header data is used only to regulate + // message transport and does not affect request execution. + MetaHeader *grpc.ResponseMetaHeader `protobuf:"bytes,2,opt,name=meta_header,json=metaHeader,proto3" json:"meta_header,omitempty"` + // Carries response verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + VerifyHeader *grpc.ResponseVerificationHeader `protobuf:"bytes,3,opt,name=verify_header,json=verifyHeader,proto3" json:"verify_header,omitempty"` +} + +func (x *BalanceResponse) Reset() { + *x = BalanceResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_accounting_grpc_service_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *BalanceResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BalanceResponse) ProtoMessage() {} + +func (x *BalanceResponse) ProtoReflect() protoreflect.Message { + mi := &file_accounting_grpc_service_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BalanceResponse.ProtoReflect.Descriptor instead. +func (*BalanceResponse) Descriptor() ([]byte, []int) { + return file_accounting_grpc_service_proto_rawDescGZIP(), []int{1} +} + +func (x *BalanceResponse) GetBody() *BalanceResponse_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *BalanceResponse) GetMetaHeader() *grpc.ResponseMetaHeader { + if x != nil { + return x.MetaHeader + } + return nil +} + +func (x *BalanceResponse) GetVerifyHeader() *grpc.ResponseVerificationHeader { + if x != nil { + return x.VerifyHeader + } + return nil +} + +// To indicate the account for which the balance is requested, its identifier +// is used. It can be any existing account in NeoFS sidechain `Balance` smart +// contract. If omitted, client implementation MUST set it to the request's +// signer `OwnerID`. +type BalanceRequest_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Valid user identifier in `OwnerID` format for which the balance is + // requested. Required field. + OwnerId *grpc1.OwnerID `protobuf:"bytes,1,opt,name=owner_id,json=ownerId,proto3" json:"owner_id,omitempty"` +} + +func (x *BalanceRequest_Body) Reset() { + *x = BalanceRequest_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_accounting_grpc_service_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *BalanceRequest_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BalanceRequest_Body) ProtoMessage() {} + +func (x *BalanceRequest_Body) ProtoReflect() protoreflect.Message { + mi := &file_accounting_grpc_service_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BalanceRequest_Body.ProtoReflect.Descriptor instead. +func (*BalanceRequest_Body) Descriptor() ([]byte, []int) { + return file_accounting_grpc_service_proto_rawDescGZIP(), []int{0, 0} +} + +func (x *BalanceRequest_Body) GetOwnerId() *grpc1.OwnerID { + if x != nil { + return x.OwnerId + } + return nil +} + +// The amount of funds in GAS token for the `OwnerID`'s account requested. +// Balance is given in the `Decimal` format to avoid precision issues with +// rounding. +type BalanceResponse_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Amount of funds in GAS token for the requested account. + Balance *Decimal `protobuf:"bytes,1,opt,name=balance,proto3" json:"balance,omitempty"` +} + +func (x *BalanceResponse_Body) Reset() { + *x = BalanceResponse_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_accounting_grpc_service_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *BalanceResponse_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BalanceResponse_Body) ProtoMessage() {} + +func (x *BalanceResponse_Body) ProtoReflect() protoreflect.Message { + mi := &file_accounting_grpc_service_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BalanceResponse_Body.ProtoReflect.Descriptor instead. +func (*BalanceResponse_Body) Descriptor() ([]byte, []int) { + return file_accounting_grpc_service_proto_rawDescGZIP(), []int{1, 0} +} + +func (x *BalanceResponse_Body) GetBalance() *Decimal { + if x != nil { + return x.Balance + } + return nil +} + +var File_accounting_grpc_service_proto protoreflect.FileDescriptor + +var file_accounting_grpc_service_proto_rawDesc = []byte{ + 0x0a, 0x1d, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x69, 0x6e, 0x67, 0x2f, 0x67, 0x72, 0x70, + 0x63, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, + 0x14, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x61, 0x63, 0x63, 0x6f, 0x75, + 0x6e, 0x74, 0x69, 0x6e, 0x67, 0x1a, 0x1b, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x69, 0x6e, + 0x67, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x1a, 0x15, 0x72, 0x65, 0x66, 0x73, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x74, 0x79, + 0x70, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x18, 0x73, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x22, 0xa5, 0x02, 0x0a, 0x0e, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3d, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, + 0x2e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x42, 0x61, 0x6c, 0x61, + 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, + 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x45, 0x0a, 0x0b, 0x6d, 0x65, 0x74, 0x61, 0x5f, 0x68, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6e, 0x65, 0x6f, + 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x52, 0x0a, 0x6d, 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x51, 0x0a, 0x0d, + 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, + 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, + 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x52, 0x0c, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x1a, + 0x3a, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x32, 0x0a, 0x08, 0x6f, 0x77, 0x6e, 0x65, 0x72, + 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, + 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x65, 0x66, 0x73, 0x2e, 0x4f, 0x77, 0x6e, 0x65, 0x72, + 0x49, 0x44, 0x52, 0x07, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x22, 0xae, 0x02, 0x0a, 0x0f, + 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x3e, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, + 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, + 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, + 0x46, 0x0a, 0x0b, 0x6d, 0x65, 0x74, 0x61, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, + 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x4d, 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0a, 0x6d, 0x65, 0x74, + 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x52, 0x0a, 0x0d, 0x76, 0x65, 0x72, 0x69, 0x66, + 0x79, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, + 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x56, 0x65, 0x72, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0c, 0x76, + 0x65, 0x72, 0x69, 0x66, 0x79, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x1a, 0x3f, 0x0a, 0x04, 0x42, + 0x6f, 0x64, 0x79, 0x12, 0x37, 0x0a, 0x07, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, + 0x2e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x44, 0x65, 0x63, 0x69, + 0x6d, 0x61, 0x6c, 0x52, 0x07, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x32, 0x6b, 0x0a, 0x11, + 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x12, 0x56, 0x0a, 0x07, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x24, 0x2e, 0x6e, + 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, + 0x69, 0x6e, 0x67, 0x2e, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x61, + 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x6d, 0x5a, 0x4a, 0x67, 0x69, 0x74, + 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, + 0x75, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x4c, 0x61, 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, + 0x66, 0x73, 0x2d, 0x61, 0x70, 0x69, 0x2d, 0x67, 0x6f, 0x2f, 0x76, 0x32, 0x2f, 0x61, 0x63, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x69, 0x6e, 0x67, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x3b, 0x61, 0x63, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x69, 0x6e, 0x67, 0xaa, 0x02, 0x1e, 0x4e, 0x65, 0x6f, 0x2e, 0x46, 0x69, + 0x6c, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x41, 0x50, 0x49, 0x2e, 0x41, 0x63, + 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x69, 0x6e, 0x67, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_accounting_grpc_service_proto_rawDescOnce sync.Once + file_accounting_grpc_service_proto_rawDescData = file_accounting_grpc_service_proto_rawDesc +) + +func file_accounting_grpc_service_proto_rawDescGZIP() []byte { + file_accounting_grpc_service_proto_rawDescOnce.Do(func() { + file_accounting_grpc_service_proto_rawDescData = protoimpl.X.CompressGZIP(file_accounting_grpc_service_proto_rawDescData) + }) + return file_accounting_grpc_service_proto_rawDescData +} + +var file_accounting_grpc_service_proto_msgTypes = make([]protoimpl.MessageInfo, 4) +var file_accounting_grpc_service_proto_goTypes = []interface{}{ + (*BalanceRequest)(nil), // 0: neo.fs.v2.accounting.BalanceRequest + (*BalanceResponse)(nil), // 1: neo.fs.v2.accounting.BalanceResponse + (*BalanceRequest_Body)(nil), // 2: neo.fs.v2.accounting.BalanceRequest.Body + (*BalanceResponse_Body)(nil), // 3: neo.fs.v2.accounting.BalanceResponse.Body + (*grpc.RequestMetaHeader)(nil), // 4: neo.fs.v2.session.RequestMetaHeader + (*grpc.RequestVerificationHeader)(nil), // 5: neo.fs.v2.session.RequestVerificationHeader + (*grpc.ResponseMetaHeader)(nil), // 6: neo.fs.v2.session.ResponseMetaHeader + (*grpc.ResponseVerificationHeader)(nil), // 7: neo.fs.v2.session.ResponseVerificationHeader + (*grpc1.OwnerID)(nil), // 8: neo.fs.v2.refs.OwnerID + (*Decimal)(nil), // 9: neo.fs.v2.accounting.Decimal +} +var file_accounting_grpc_service_proto_depIdxs = []int32{ + 2, // 0: neo.fs.v2.accounting.BalanceRequest.body:type_name -> neo.fs.v2.accounting.BalanceRequest.Body + 4, // 1: neo.fs.v2.accounting.BalanceRequest.meta_header:type_name -> neo.fs.v2.session.RequestMetaHeader + 5, // 2: neo.fs.v2.accounting.BalanceRequest.verify_header:type_name -> neo.fs.v2.session.RequestVerificationHeader + 3, // 3: neo.fs.v2.accounting.BalanceResponse.body:type_name -> neo.fs.v2.accounting.BalanceResponse.Body + 6, // 4: neo.fs.v2.accounting.BalanceResponse.meta_header:type_name -> neo.fs.v2.session.ResponseMetaHeader + 7, // 5: neo.fs.v2.accounting.BalanceResponse.verify_header:type_name -> neo.fs.v2.session.ResponseVerificationHeader + 8, // 6: neo.fs.v2.accounting.BalanceRequest.Body.owner_id:type_name -> neo.fs.v2.refs.OwnerID + 9, // 7: neo.fs.v2.accounting.BalanceResponse.Body.balance:type_name -> neo.fs.v2.accounting.Decimal + 0, // 8: neo.fs.v2.accounting.AccountingService.Balance:input_type -> neo.fs.v2.accounting.BalanceRequest + 1, // 9: neo.fs.v2.accounting.AccountingService.Balance:output_type -> neo.fs.v2.accounting.BalanceResponse + 9, // [9:10] is the sub-list for method output_type + 8, // [8:9] is the sub-list for method input_type + 8, // [8:8] is the sub-list for extension type_name + 8, // [8:8] is the sub-list for extension extendee + 0, // [0:8] is the sub-list for field type_name +} + +func init() { file_accounting_grpc_service_proto_init() } +func file_accounting_grpc_service_proto_init() { + if File_accounting_grpc_service_proto != nil { + return + } + file_accounting_grpc_types_proto_init() + if !protoimpl.UnsafeEnabled { + file_accounting_grpc_service_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*BalanceRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_accounting_grpc_service_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*BalanceResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_accounting_grpc_service_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*BalanceRequest_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_accounting_grpc_service_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*BalanceResponse_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_accounting_grpc_service_proto_rawDesc, + NumEnums: 0, + NumMessages: 4, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_accounting_grpc_service_proto_goTypes, + DependencyIndexes: file_accounting_grpc_service_proto_depIdxs, + MessageInfos: file_accounting_grpc_service_proto_msgTypes, + }.Build() + File_accounting_grpc_service_proto = out.File + file_accounting_grpc_service_proto_rawDesc = nil + file_accounting_grpc_service_proto_goTypes = nil + file_accounting_grpc_service_proto_depIdxs = nil +} diff --git a/pkg/api/accounting/grpc/service_grpc.pb.go b/pkg/api/accounting/grpc/service_grpc.pb.go new file mode 100644 index 000000000..cd1b2e917 --- /dev/null +++ b/pkg/api/accounting/grpc/service_grpc.pb.go @@ -0,0 +1,119 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.3.0 +// - protoc v4.25.3 +// source: accounting/grpc/service.proto + +package accounting + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +const ( + AccountingService_Balance_FullMethodName = "/neo.fs.v2.accounting.AccountingService/Balance" +) + +// AccountingServiceClient is the client API for AccountingService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type AccountingServiceClient interface { + // Returns the amount of funds in GAS token for the requested NeoFS account. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): + // balance has been successfully read; + // - Common failures (SECTION_FAILURE_COMMON). + Balance(ctx context.Context, in *BalanceRequest, opts ...grpc.CallOption) (*BalanceResponse, error) +} + +type accountingServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewAccountingServiceClient(cc grpc.ClientConnInterface) AccountingServiceClient { + return &accountingServiceClient{cc} +} + +func (c *accountingServiceClient) Balance(ctx context.Context, in *BalanceRequest, opts ...grpc.CallOption) (*BalanceResponse, error) { + out := new(BalanceResponse) + err := c.cc.Invoke(ctx, AccountingService_Balance_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// AccountingServiceServer is the server API for AccountingService service. +// All implementations should embed UnimplementedAccountingServiceServer +// for forward compatibility +type AccountingServiceServer interface { + // Returns the amount of funds in GAS token for the requested NeoFS account. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): + // balance has been successfully read; + // - Common failures (SECTION_FAILURE_COMMON). + Balance(context.Context, *BalanceRequest) (*BalanceResponse, error) +} + +// UnimplementedAccountingServiceServer should be embedded to have forward compatible implementations. +type UnimplementedAccountingServiceServer struct { +} + +func (UnimplementedAccountingServiceServer) Balance(context.Context, *BalanceRequest) (*BalanceResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Balance not implemented") +} + +// UnsafeAccountingServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to AccountingServiceServer will +// result in compilation errors. +type UnsafeAccountingServiceServer interface { + mustEmbedUnimplementedAccountingServiceServer() +} + +func RegisterAccountingServiceServer(s grpc.ServiceRegistrar, srv AccountingServiceServer) { + s.RegisterService(&AccountingService_ServiceDesc, srv) +} + +func _AccountingService_Balance_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(BalanceRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AccountingServiceServer).Balance(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: AccountingService_Balance_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AccountingServiceServer).Balance(ctx, req.(*BalanceRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// AccountingService_ServiceDesc is the grpc.ServiceDesc for AccountingService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var AccountingService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "neo.fs.v2.accounting.AccountingService", + HandlerType: (*AccountingServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Balance", + Handler: _AccountingService_Balance_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "accounting/grpc/service.proto", +} diff --git a/pkg/api/accounting/grpc/types.go b/pkg/api/accounting/grpc/types.go new file mode 100644 index 000000000..1c1bac957 --- /dev/null +++ b/pkg/api/accounting/grpc/types.go @@ -0,0 +1,11 @@ +package accounting + +// SetValue sets value of the decimal number. +func (m *Decimal) SetValue(v int64) { + m.Value = v +} + +// SetPrecision sets precision of the decimal number. +func (m *Decimal) SetPrecision(v uint32) { + m.Precision = v +} diff --git a/pkg/api/accounting/grpc/types.pb.go b/pkg/api/accounting/grpc/types.pb.go new file mode 100644 index 000000000..592aa8b38 --- /dev/null +++ b/pkg/api/accounting/grpc/types.pb.go @@ -0,0 +1,169 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.33.0 +// protoc v4.25.3 +// source: accounting/grpc/types.proto + +package accounting + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// Standard floating point data type can't be used in NeoFS due to inexactness +// of the result when doing lots of small number operations. To solve the lost +// precision issue, special `Decimal` format is used for monetary computations. +// +// Please see [The General Decimal Arithmetic +// Specification](http://speleotrove.com/decimal/) for detailed problem +// description. +type Decimal struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Number in the smallest Token fractions. + Value int64 `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"` + // Precision value indicating how many smallest fractions can be in one + // integer. + Precision uint32 `protobuf:"varint,2,opt,name=precision,proto3" json:"precision,omitempty"` +} + +func (x *Decimal) Reset() { + *x = Decimal{} + if protoimpl.UnsafeEnabled { + mi := &file_accounting_grpc_types_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Decimal) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Decimal) ProtoMessage() {} + +func (x *Decimal) ProtoReflect() protoreflect.Message { + mi := &file_accounting_grpc_types_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Decimal.ProtoReflect.Descriptor instead. +func (*Decimal) Descriptor() ([]byte, []int) { + return file_accounting_grpc_types_proto_rawDescGZIP(), []int{0} +} + +func (x *Decimal) GetValue() int64 { + if x != nil { + return x.Value + } + return 0 +} + +func (x *Decimal) GetPrecision() uint32 { + if x != nil { + return x.Precision + } + return 0 +} + +var File_accounting_grpc_types_proto protoreflect.FileDescriptor + +var file_accounting_grpc_types_proto_rawDesc = []byte{ + 0x0a, 0x1b, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x69, 0x6e, 0x67, 0x2f, 0x67, 0x72, 0x70, + 0x63, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x14, 0x6e, + 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, + 0x69, 0x6e, 0x67, 0x22, 0x3d, 0x0a, 0x07, 0x44, 0x65, 0x63, 0x69, 0x6d, 0x61, 0x6c, 0x12, 0x14, + 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, + 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x69, + 0x6f, 0x6e, 0x42, 0x6d, 0x5a, 0x4a, 0x67, 0x69, 0x74, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, + 0x73, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, 0x75, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, + 0x4c, 0x61, 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2d, 0x61, 0x70, 0x69, 0x2d, + 0x67, 0x6f, 0x2f, 0x76, 0x32, 0x2f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x69, 0x6e, 0x67, + 0x2f, 0x67, 0x72, 0x70, 0x63, 0x3b, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x69, 0x6e, 0x67, + 0xaa, 0x02, 0x1e, 0x4e, 0x65, 0x6f, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x61, + 0x67, 0x65, 0x2e, 0x41, 0x50, 0x49, 0x2e, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x69, 0x6e, + 0x67, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_accounting_grpc_types_proto_rawDescOnce sync.Once + file_accounting_grpc_types_proto_rawDescData = file_accounting_grpc_types_proto_rawDesc +) + +func file_accounting_grpc_types_proto_rawDescGZIP() []byte { + file_accounting_grpc_types_proto_rawDescOnce.Do(func() { + file_accounting_grpc_types_proto_rawDescData = protoimpl.X.CompressGZIP(file_accounting_grpc_types_proto_rawDescData) + }) + return file_accounting_grpc_types_proto_rawDescData +} + +var file_accounting_grpc_types_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_accounting_grpc_types_proto_goTypes = []interface{}{ + (*Decimal)(nil), // 0: neo.fs.v2.accounting.Decimal +} +var file_accounting_grpc_types_proto_depIdxs = []int32{ + 0, // [0:0] is the sub-list for method output_type + 0, // [0:0] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_accounting_grpc_types_proto_init() } +func file_accounting_grpc_types_proto_init() { + if File_accounting_grpc_types_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_accounting_grpc_types_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Decimal); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_accounting_grpc_types_proto_rawDesc, + NumEnums: 0, + NumMessages: 1, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_accounting_grpc_types_proto_goTypes, + DependencyIndexes: file_accounting_grpc_types_proto_depIdxs, + MessageInfos: file_accounting_grpc_types_proto_msgTypes, + }.Build() + File_accounting_grpc_types_proto = out.File + file_accounting_grpc_types_proto_rawDesc = nil + file_accounting_grpc_types_proto_goTypes = nil + file_accounting_grpc_types_proto_depIdxs = nil +} diff --git a/pkg/api/accounting/json.go b/pkg/api/accounting/json.go new file mode 100644 index 000000000..417e633b7 --- /dev/null +++ b/pkg/api/accounting/json.go @@ -0,0 +1,14 @@ +package accounting + +import ( + accounting "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/accounting/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/message" +) + +func (d *Decimal) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(d) +} + +func (d *Decimal) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(d, data, new(accounting.Decimal)) +} diff --git a/pkg/api/accounting/marshal.go b/pkg/api/accounting/marshal.go new file mode 100644 index 000000000..a5651a936 --- /dev/null +++ b/pkg/api/accounting/marshal.go @@ -0,0 +1,104 @@ +package accounting + +import ( + accounting "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/accounting/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/message" + protoutil "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/util/proto" +) + +const ( + decimalValueField = 1 + decimalPrecisionField = 2 + + balanceReqBodyOwnerField = 1 + + balanceRespBodyDecimalField = 1 +) + +func (d *Decimal) StableMarshal(buf []byte) []byte { + if d == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, d.StableSize()) + } + + var offset int + + offset += protoutil.Int64Marshal(decimalValueField, buf[offset:], d.val) + protoutil.UInt32Marshal(decimalPrecisionField, buf[offset:], d.prec) + + return buf +} + +func (d *Decimal) StableSize() (size int) { + if d == nil { + return 0 + } + + size += protoutil.Int64Size(decimalValueField, d.val) + size += protoutil.UInt32Size(decimalPrecisionField, d.prec) + + return size +} + +func (d *Decimal) Unmarshal(data []byte) error { + return message.Unmarshal(d, data, new(accounting.Decimal)) +} + +func (b *BalanceRequestBody) StableMarshal(buf []byte) []byte { + if b == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, b.StableSize()) + } + + protoutil.NestedStructureMarshal(balanceReqBodyOwnerField, buf, b.ownerID) + + return buf +} + +func (b *BalanceRequestBody) StableSize() (size int) { + if b == nil { + return 0 + } + + size = protoutil.NestedStructureSize(balanceReqBodyOwnerField, b.ownerID) + + return size +} + +func (b *BalanceRequestBody) Unmarshal(data []byte) error { + return message.Unmarshal(b, data, new(accounting.BalanceRequest_Body)) +} + +func (br *BalanceResponseBody) StableMarshal(buf []byte) []byte { + if br == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, br.StableSize()) + } + + protoutil.NestedStructureMarshal(balanceRespBodyDecimalField, buf, br.bal) + + return buf +} + +func (br *BalanceResponseBody) StableSize() (size int) { + if br == nil { + return 0 + } + + size = protoutil.NestedStructureSize(balanceRespBodyDecimalField, br.bal) + + return size +} + +func (br *BalanceResponseBody) Unmarshal(data []byte) error { + return message.Unmarshal(br, data, new(accounting.BalanceResponse_Body)) +} diff --git a/pkg/api/accounting/message_test.go b/pkg/api/accounting/message_test.go new file mode 100644 index 000000000..732625024 --- /dev/null +++ b/pkg/api/accounting/message_test.go @@ -0,0 +1,19 @@ +package accounting_test + +import ( + "testing" + + accountingtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/accounting/test" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/message" + messagetest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/message/test" +) + +func TestMessage(t *testing.T) { + messagetest.TestRPCMessage(t, + func(empty bool) message.Message { return accountingtest.GenerateDecimal(empty) }, + func(empty bool) message.Message { return accountingtest.GenerateBalanceRequestBody(empty) }, + func(empty bool) message.Message { return accountingtest.GenerateBalanceRequest(empty) }, + func(empty bool) message.Message { return accountingtest.GenerateBalanceResponseBody(empty) }, + func(empty bool) message.Message { return accountingtest.GenerateBalanceResponse(empty) }, + ) +} diff --git a/pkg/api/accounting/test/generate.go b/pkg/api/accounting/test/generate.go new file mode 100644 index 000000000..b17a0b65e --- /dev/null +++ b/pkg/api/accounting/test/generate.go @@ -0,0 +1,64 @@ +package accountingtest + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/accounting" + accountingtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs/test" + sessiontest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session/test" +) + +func GenerateBalanceRequest(empty bool) *accounting.BalanceRequest { + m := new(accounting.BalanceRequest) + + if !empty { + m.SetBody(GenerateBalanceRequestBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateRequestMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateRequestVerificationHeader(empty)) + + return m +} + +func GenerateBalanceRequestBody(empty bool) *accounting.BalanceRequestBody { + m := new(accounting.BalanceRequestBody) + + if !empty { + m.SetOwnerID(accountingtest.GenerateOwnerID(false)) + } + + return m +} + +func GenerateBalanceResponse(empty bool) *accounting.BalanceResponse { + m := new(accounting.BalanceResponse) + + if !empty { + m.SetBody(GenerateBalanceResponseBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateResponseMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateResponseVerificationHeader(empty)) + + return m +} + +func GenerateBalanceResponseBody(empty bool) *accounting.BalanceResponseBody { + m := new(accounting.BalanceResponseBody) + + if !empty { + m.SetBalance(GenerateDecimal(false)) + } + + return m +} + +func GenerateDecimal(empty bool) *accounting.Decimal { + m := new(accounting.Decimal) + + if !empty { + m.SetValue(1) + m.SetPrecision(2) + } + + return m +} diff --git a/pkg/api/acl/bench_test.go b/pkg/api/acl/bench_test.go new file mode 100644 index 000000000..9113f546e --- /dev/null +++ b/pkg/api/acl/bench_test.go @@ -0,0 +1,51 @@ +package acl_test + +import ( + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/acl" + aclGrpc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/acl/grpc" + acltest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/acl/test" +) + +func BenchmarkTable_ToGRPCMessage(b *testing.B) { + const size = 4 + + tb := new(acl.Table) + rs := make([]acl.Record, size) + for i := range rs { + fs := make([]acl.HeaderFilter, size) + for j := range fs { + fs[j] = *acltest.GenerateFilter(false) + } + ts := make([]acl.Target, size) + for j := range ts { + ts[j] = *acltest.GenerateTarget(false) + } + + rs[i].SetFilters(fs) + rs[i].SetTargets(ts) + } + tb.SetRecords(rs) + + raw := tb.ToGRPCMessage() + + b.Run("to grpc message", func(b *testing.B) { + b.ReportAllocs() + for i := 0; i < b.N; i++ { + raw := tb.ToGRPCMessage() + if len(tb.GetRecords()) != len(raw.(*aclGrpc.EACLTable).Records) { + b.FailNow() + } + } + }) + b.Run("from grpc message", func(b *testing.B) { + b.ReportAllocs() + for i := 0; i < b.N; i++ { + tb := new(acl.Table) + if tb.FromGRPCMessage(raw) != nil { + b.FailNow() + } + } + }) +} diff --git a/pkg/api/acl/convert.go b/pkg/api/acl/convert.go new file mode 100644 index 000000000..eacdfe378 --- /dev/null +++ b/pkg/api/acl/convert.go @@ -0,0 +1,535 @@ +package acl + +import ( + acl "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/acl/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + refsGRPC "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/message" +) + +// RoleToGRPCField converts unified role enum into grpc enum. +func RoleToGRPCField(t Role) acl.Role { + switch t { + case RoleUser: + return acl.Role_USER + case RoleSystem: + return acl.Role_SYSTEM + case RoleOthers: + return acl.Role_OTHERS + default: + return acl.Role_ROLE_UNSPECIFIED + } +} + +// RoleFromGRPCField converts grpc enum into unified role enum. +func RoleFromGRPCField(t acl.Role) Role { + switch t { + case acl.Role_USER: + return RoleUser + case acl.Role_SYSTEM: + return RoleSystem + case acl.Role_OTHERS: + return RoleOthers + default: + return RoleUnknown + } +} + +// OperationToGRPCField converts unified operation enum into grpc enum. +func OperationToGRPCField(t Operation) acl.Operation { + switch t { + case OperationPut: + return acl.Operation_PUT + case OperationDelete: + return acl.Operation_DELETE + case OperationGet: + return acl.Operation_GET + case OperationHead: + return acl.Operation_HEAD + case OperationSearch: + return acl.Operation_SEARCH + case OperationRange: + return acl.Operation_GETRANGE + case OperationRangeHash: + return acl.Operation_GETRANGEHASH + default: + return acl.Operation_OPERATION_UNSPECIFIED + } +} + +// OperationFromGRPCField converts grpc enum into unified operation enum. +func OperationFromGRPCField(t acl.Operation) Operation { + switch t { + case acl.Operation_PUT: + return OperationPut + case acl.Operation_DELETE: + return OperationDelete + case acl.Operation_GET: + return OperationGet + case acl.Operation_HEAD: + return OperationHead + case acl.Operation_SEARCH: + return OperationSearch + case acl.Operation_GETRANGE: + return OperationRange + case acl.Operation_GETRANGEHASH: + return OperationRangeHash + default: + return OperationUnknown + } +} + +// ActionToGRPCField converts unified action enum into grpc enum. +func ActionToGRPCField(t Action) acl.Action { + switch t { + case ActionDeny: + return acl.Action_DENY + case ActionAllow: + return acl.Action_ALLOW + default: + return acl.Action_ACTION_UNSPECIFIED + } +} + +// ActionFromGRPCField converts grpc enum into unified action enum. +func ActionFromGRPCField(t acl.Action) Action { + switch t { + case acl.Action_DENY: + return ActionDeny + case acl.Action_ALLOW: + return ActionAllow + default: + return ActionUnknown + } +} + +// HeaderTypeToGRPCField converts unified header type enum into grpc enum. +func HeaderTypeToGRPCField(t HeaderType) acl.HeaderType { + switch t { + case HeaderTypeRequest: + return acl.HeaderType_REQUEST + case HeaderTypeObject: + return acl.HeaderType_OBJECT + case HeaderTypeService: + return acl.HeaderType_SERVICE + default: + return acl.HeaderType_HEADER_UNSPECIFIED + } +} + +// HeaderTypeFromGRPCField converts grpc enum into unified header type enum. +func HeaderTypeFromGRPCField(t acl.HeaderType) HeaderType { + switch t { + case acl.HeaderType_REQUEST: + return HeaderTypeRequest + case acl.HeaderType_OBJECT: + return HeaderTypeObject + case acl.HeaderType_SERVICE: + return HeaderTypeService + default: + return HeaderTypeUnknown + } +} + +// MatchTypeToGRPCField converts unified match type enum into grpc enum. +func MatchTypeToGRPCField(t MatchType) acl.MatchType { + switch t { + case MatchTypeStringEqual: + return acl.MatchType_STRING_EQUAL + case MatchTypeStringNotEqual: + return acl.MatchType_STRING_NOT_EQUAL + default: + return acl.MatchType_MATCH_TYPE_UNSPECIFIED + } +} + +// MatchTypeFromGRPCField converts grpc enum into unified match type enum. +func MatchTypeFromGRPCField(t acl.MatchType) MatchType { + switch t { + case acl.MatchType_STRING_EQUAL: + return MatchTypeStringEqual + case acl.MatchType_STRING_NOT_EQUAL: + return MatchTypeStringNotEqual + default: + return MatchTypeUnknown + } +} + +func (f *HeaderFilter) ToGRPCMessage() grpc.Message { + var m *acl.EACLRecord_Filter + + if f != nil { + m = new(acl.EACLRecord_Filter) + + m.SetKey(f.key) + m.SetValue(f.value) + m.SetHeader(HeaderTypeToGRPCField(f.hdrType)) + m.SetMatchType(MatchTypeToGRPCField(f.matchType)) + } + + return m +} + +func (f *HeaderFilter) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*acl.EACLRecord_Filter) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + f.key = v.GetKey() + f.value = v.GetValue() + f.hdrType = HeaderTypeFromGRPCField(v.GetHeaderType()) + f.matchType = MatchTypeFromGRPCField(v.GetMatchType()) + + return nil +} + +func HeaderFiltersToGRPC(fs []HeaderFilter) (res []*acl.EACLRecord_Filter) { + if fs != nil { + res = make([]*acl.EACLRecord_Filter, 0, len(fs)) + + for i := range fs { + res = append(res, fs[i].ToGRPCMessage().(*acl.EACLRecord_Filter)) + } + } + + return +} + +func HeaderFiltersFromGRPC(fs []*acl.EACLRecord_Filter) (res []HeaderFilter, err error) { + if fs != nil { + res = make([]HeaderFilter, len(fs)) + + for i := range fs { + if fs[i] != nil { + err = res[i].FromGRPCMessage(fs[i]) + if err != nil { + return + } + } + } + } + + return +} + +func (t *Target) ToGRPCMessage() grpc.Message { + var m *acl.EACLRecord_Target + + if t != nil { + m = new(acl.EACLRecord_Target) + + m.SetRole(RoleToGRPCField(t.role)) + m.SetKeys(t.keys) + } + + return m +} + +func (t *Target) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*acl.EACLRecord_Target) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + t.role = RoleFromGRPCField(v.GetRole()) + t.keys = v.GetKeys() + + return nil +} + +func TargetsToGRPC(ts []Target) (res []*acl.EACLRecord_Target) { + if ts != nil { + res = make([]*acl.EACLRecord_Target, 0, len(ts)) + + for i := range ts { + res = append(res, ts[i].ToGRPCMessage().(*acl.EACLRecord_Target)) + } + } + + return +} + +func TargetsFromGRPC(fs []*acl.EACLRecord_Target) (res []Target, err error) { + if fs != nil { + res = make([]Target, len(fs)) + + for i := range fs { + if fs[i] != nil { + err = res[i].FromGRPCMessage(fs[i]) + if err != nil { + return + } + } + } + } + + return +} + +func (r *Record) ToGRPCMessage() grpc.Message { + var m *acl.EACLRecord + + if r != nil { + m = new(acl.EACLRecord) + + m.SetOperation(OperationToGRPCField(r.op)) + m.SetAction(ActionToGRPCField(r.action)) + m.SetFilters(HeaderFiltersToGRPC(r.filters)) + m.SetTargets(TargetsToGRPC(r.targets)) + } + + return m +} + +func (r *Record) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*acl.EACLRecord) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + r.filters, err = HeaderFiltersFromGRPC(v.GetFilters()) + if err != nil { + return err + } + + r.targets, err = TargetsFromGRPC(v.GetTargets()) + if err != nil { + return err + } + + r.op = OperationFromGRPCField(v.GetOperation()) + r.action = ActionFromGRPCField(v.GetAction()) + + return nil +} + +func RecordsToGRPC(ts []Record) (res []*acl.EACLRecord) { + if ts != nil { + res = make([]*acl.EACLRecord, 0, len(ts)) + + for i := range ts { + res = append(res, ts[i].ToGRPCMessage().(*acl.EACLRecord)) + } + } + + return +} + +func RecordsFromGRPC(fs []*acl.EACLRecord) (res []Record, err error) { + if fs != nil { + res = make([]Record, len(fs)) + + for i := range fs { + if fs[i] != nil { + err = res[i].FromGRPCMessage(fs[i]) + if err != nil { + return + } + } + } + } + + return +} + +func (t *Table) ToGRPCMessage() grpc.Message { + var m *acl.EACLTable + + if t != nil { + m = new(acl.EACLTable) + + m.SetVersion(t.version.ToGRPCMessage().(*refsGRPC.Version)) + m.SetContainerId(t.cid.ToGRPCMessage().(*refsGRPC.ContainerID)) + m.SetRecords(RecordsToGRPC(t.records)) + } + + return m +} + +func (t *Table) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*acl.EACLTable) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + cid := v.GetContainerId() + if cid == nil { + t.cid = nil + } else { + if t.cid == nil { + t.cid = new(refs.ContainerID) + } + + err = t.cid.FromGRPCMessage(cid) + if err != nil { + return err + } + } + + version := v.GetVersion() + if version == nil { + t.version = nil + } else { + if t.version == nil { + t.version = new(refs.Version) + } + + err = t.version.FromGRPCMessage(version) + if err != nil { + return err + } + } + + t.records, err = RecordsFromGRPC(v.GetRecords()) + + return err +} + +func (l *TokenLifetime) ToGRPCMessage() grpc.Message { + var m *acl.BearerToken_Body_TokenLifetime + + if l != nil { + m = new(acl.BearerToken_Body_TokenLifetime) + + m.SetExp(l.exp) + m.SetIat(l.iat) + m.SetNbf(l.nbf) + } + + return m +} + +func (l *TokenLifetime) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*acl.BearerToken_Body_TokenLifetime) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + l.exp = v.GetExp() + l.iat = v.GetIat() + l.nbf = v.GetNbf() + + return nil +} + +func (bt *BearerTokenBody) ToGRPCMessage() grpc.Message { + var m *acl.BearerToken_Body + + if bt != nil { + m = new(acl.BearerToken_Body) + + m.SetOwnerId(bt.ownerID.ToGRPCMessage().(*refsGRPC.OwnerID)) + m.SetLifetime(bt.lifetime.ToGRPCMessage().(*acl.BearerToken_Body_TokenLifetime)) + m.SetEaclTable(bt.eacl.ToGRPCMessage().(*acl.EACLTable)) + m.SetImpersonate(bt.impersonate) + } + + return m +} + +func (bt *BearerTokenBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*acl.BearerToken_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + ownerID := v.GetOwnerId() + if ownerID == nil { + bt.ownerID = nil + } else { + if bt.ownerID == nil { + bt.ownerID = new(refs.OwnerID) + } + + err = bt.ownerID.FromGRPCMessage(ownerID) + if err != nil { + return err + } + } + + lifetime := v.GetLifetime() + if lifetime == nil { + bt.lifetime = nil + } else { + if bt.lifetime == nil { + bt.lifetime = new(TokenLifetime) + } + + err = bt.lifetime.FromGRPCMessage(lifetime) + if err != nil { + return err + } + } + + eacl := v.GetEaclTable() + if eacl == nil { + bt.eacl = nil + } else { + if bt.eacl == nil { + bt.eacl = new(Table) + } + + err = bt.eacl.FromGRPCMessage(eacl) + } + + bt.impersonate = v.GetAllowImpersonate() + + return err +} + +func (bt *BearerToken) ToGRPCMessage() grpc.Message { + var m *acl.BearerToken + + if bt != nil { + m = new(acl.BearerToken) + + m.SetBody(bt.body.ToGRPCMessage().(*acl.BearerToken_Body)) + m.SetSignature(bt.sig.ToGRPCMessage().(*refsGRPC.Signature)) + } + + return m +} + +func (bt *BearerToken) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*acl.BearerToken) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + bt.body = nil + } else { + if bt.body == nil { + bt.body = new(BearerTokenBody) + } + + err = bt.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + sig := v.GetSignature() + if sig == nil { + bt.sig = nil + } else { + if bt.sig == nil { + bt.sig = new(refs.Signature) + } + + err = bt.sig.FromGRPCMessage(sig) + } + + return err +} diff --git a/pkg/api/acl/filters.go b/pkg/api/acl/filters.go new file mode 100644 index 000000000..c1d8afec7 --- /dev/null +++ b/pkg/api/acl/filters.go @@ -0,0 +1,33 @@ +package acl + +// ObjectFilterPrefix is a prefix of key to object header value or property. +const ObjectFilterPrefix = "$Object:" + +const ( + // FilterObjectVersion is a filter key to "version" field of the object header. + FilterObjectVersion = ObjectFilterPrefix + "version" + + // FilterObjectID is a filter key to "object_id" field of the object. + FilterObjectID = ObjectFilterPrefix + "objectID" + + // FilterObjectContainerID is a filter key to "container_id" field of the object header. + FilterObjectContainerID = ObjectFilterPrefix + "containerID" + + // FilterObjectOwnerID is a filter key to "owner_id" field of the object header. + FilterObjectOwnerID = ObjectFilterPrefix + "ownerID" + + // FilterObjectCreationEpoch is a filter key to "creation_epoch" field of the object header. + FilterObjectCreationEpoch = ObjectFilterPrefix + "creationEpoch" + + // FilterObjectPayloadLength is a filter key to "payload_length" field of the object header. + FilterObjectPayloadLength = ObjectFilterPrefix + "payloadLength" + + // FilterObjectPayloadHash is a filter key to "payload_hash" field of the object header. + FilterObjectPayloadHash = ObjectFilterPrefix + "payloadHash" + + // FilterObjectType is a filter key to "object_type" field of the object header. + FilterObjectType = ObjectFilterPrefix + "objectType" + + // FilterObjectHomomorphicHash is a filter key to "homomorphic_hash" field of the object header. + FilterObjectHomomorphicHash = ObjectFilterPrefix + "homomorphicHash" +) diff --git a/pkg/api/acl/grpc/types.go b/pkg/api/acl/grpc/types.go new file mode 100644 index 000000000..4dc0c83ef --- /dev/null +++ b/pkg/api/acl/grpc/types.go @@ -0,0 +1,180 @@ +package acl + +import ( + refs "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs/grpc" +) + +// SetVersion sets version of EACL rules in table. +func (m *EACLTable) SetVersion(v *refs.Version) { + m.Version = v +} + +// SetContainerId sets container identifier of the eACL table. +func (m *EACLTable) SetContainerId(v *refs.ContainerID) { + m.ContainerId = v +} + +// SetRecords sets record list of the eACL table. +func (m *EACLTable) SetRecords(v []*EACLRecord) { + m.Records = v +} + +// SetOperation sets operation of the eACL record. +func (m *EACLRecord) SetOperation(v Operation) { + m.Operation = v +} + +// SetAction sets action of the eACL record. +func (m *EACLRecord) SetAction(v Action) { + m.Action = v +} + +// SetFilters sets filter list of the eACL record. +func (m *EACLRecord) SetFilters(v []*EACLRecord_Filter) { + m.Filters = v +} + +// SetTargets sets target list of the eACL record. +func (m *EACLRecord) SetTargets(v []*EACLRecord_Target) { + m.Targets = v +} + +// SetHeader sets header type of the eACL filter. +func (m *EACLRecord_Filter) SetHeader(v HeaderType) { + m.HeaderType = v +} + +// SetMatchType sets match type of the eACL filter. +func (m *EACLRecord_Filter) SetMatchType(v MatchType) { + m.MatchType = v +} + +// SetKey sets key of the eACL filter. +func (m *EACLRecord_Filter) SetKey(v string) { + m.Key = v +} + +// SetValue sets value of the eACL filter. +func (m *EACLRecord_Filter) SetValue(v string) { + m.Value = v +} + +// SetRole sets target group of the eACL target. +func (m *EACLRecord_Target) SetRole(v Role) { + m.Role = v +} + +// SetKeys of the eACL target. +func (m *EACLRecord_Target) SetKeys(v [][]byte) { + m.Keys = v +} + +// SetEaclTable sets eACL table of the bearer token. +func (m *BearerToken_Body) SetEaclTable(v *EACLTable) { + m.EaclTable = v +} + +// SetOwnerId sets identifier of the bearer token owner. +func (m *BearerToken_Body) SetOwnerId(v *refs.OwnerID) { + m.OwnerId = v +} + +// SetLifetime sets lifetime of the bearer token. +func (m *BearerToken_Body) SetLifetime(v *BearerToken_Body_TokenLifetime) { + m.Lifetime = v +} + +// SetImpersonate allows impersonate. +func (m *BearerToken_Body) SetImpersonate(v bool) { + m.AllowImpersonate = v +} + +// SetBody sets bearer token body. +func (m *BearerToken) SetBody(v *BearerToken_Body) { + m.Body = v +} + +// SetSignature sets bearer token signature. +func (m *BearerToken) SetSignature(v *refs.Signature) { + m.Signature = v +} + +// SetExp sets epoch number of the token expiration. +func (m *BearerToken_Body_TokenLifetime) SetExp(v uint64) { + m.Exp = v +} + +// SetNbf sets starting epoch number of the token. +func (m *BearerToken_Body_TokenLifetime) SetNbf(v uint64) { + m.Nbf = v +} + +// SetIat sets the number of the epoch in which the token was issued. +func (m *BearerToken_Body_TokenLifetime) SetIat(v uint64) { + m.Iat = v +} + +// FromString parses Action from a string representation, +// It is a reverse action to String(). +// +// Returns true if s was parsed successfully. +func (x *Action) FromString(s string) bool { + i, ok := Action_value[s] + if ok { + *x = Action(i) + } + + return ok +} + +// FromString parses Role from a string representation, +// It is a reverse action to String(). +// +// Returns true if s was parsed successfully. +func (x *Role) FromString(s string) bool { + i, ok := Role_value[s] + if ok { + *x = Role(i) + } + + return ok +} + +// FromString parses Operation from a string representation, +// It is a reverse action to String(). +// +// Returns true if s was parsed successfully. +func (x *Operation) FromString(s string) bool { + i, ok := Operation_value[s] + if ok { + *x = Operation(i) + } + + return ok +} + +// FromString parses MatchType from a string representation, +// It is a reverse action to String(). +// +// Returns true if s was parsed successfully. +func (x *MatchType) FromString(s string) bool { + i, ok := MatchType_value[s] + if ok { + *x = MatchType(i) + } + + return ok +} + +// FromString parses HeaderType from a string representation, +// It is a reverse action to String(). +// +// Returns true if s was parsed successfully. +func (x *HeaderType) FromString(s string) bool { + i, ok := HeaderType_value[s] + if ok { + *x = HeaderType(i) + } + + return ok +} diff --git a/pkg/api/acl/grpc/types.pb.go b/pkg/api/acl/grpc/types.pb.go new file mode 100644 index 000000000..a10e92f7e --- /dev/null +++ b/pkg/api/acl/grpc/types.pb.go @@ -0,0 +1,1123 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.33.0 +// protoc v4.25.3 +// source: acl/grpc/types.proto + +package acl + +import ( + grpc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs/grpc" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// Target role of the access control rule in access control list. +type Role int32 + +const ( + // Unspecified role, default value + Role_ROLE_UNSPECIFIED Role = 0 + // User target rule is applied if sender is the owner of the container + Role_USER Role = 1 + // System target rule is applied if sender is a storage node within the + // container or an inner ring node + Role_SYSTEM Role = 2 + // Others target rule is applied if sender is neither a user nor a system + // target + Role_OTHERS Role = 3 +) + +// Enum value maps for Role. +var ( + Role_name = map[int32]string{ + 0: "ROLE_UNSPECIFIED", + 1: "USER", + 2: "SYSTEM", + 3: "OTHERS", + } + Role_value = map[string]int32{ + "ROLE_UNSPECIFIED": 0, + "USER": 1, + "SYSTEM": 2, + "OTHERS": 3, + } +) + +func (x Role) Enum() *Role { + p := new(Role) + *p = x + return p +} + +func (x Role) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (Role) Descriptor() protoreflect.EnumDescriptor { + return file_acl_grpc_types_proto_enumTypes[0].Descriptor() +} + +func (Role) Type() protoreflect.EnumType { + return &file_acl_grpc_types_proto_enumTypes[0] +} + +func (x Role) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use Role.Descriptor instead. +func (Role) EnumDescriptor() ([]byte, []int) { + return file_acl_grpc_types_proto_rawDescGZIP(), []int{0} +} + +// MatchType is an enumeration of match types. +type MatchType int32 + +const ( + // Unspecified match type, default value. + MatchType_MATCH_TYPE_UNSPECIFIED MatchType = 0 + // Return true if strings are equal + MatchType_STRING_EQUAL MatchType = 1 + // Return true if strings are different + MatchType_STRING_NOT_EQUAL MatchType = 2 +) + +// Enum value maps for MatchType. +var ( + MatchType_name = map[int32]string{ + 0: "MATCH_TYPE_UNSPECIFIED", + 1: "STRING_EQUAL", + 2: "STRING_NOT_EQUAL", + } + MatchType_value = map[string]int32{ + "MATCH_TYPE_UNSPECIFIED": 0, + "STRING_EQUAL": 1, + "STRING_NOT_EQUAL": 2, + } +) + +func (x MatchType) Enum() *MatchType { + p := new(MatchType) + *p = x + return p +} + +func (x MatchType) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (MatchType) Descriptor() protoreflect.EnumDescriptor { + return file_acl_grpc_types_proto_enumTypes[1].Descriptor() +} + +func (MatchType) Type() protoreflect.EnumType { + return &file_acl_grpc_types_proto_enumTypes[1] +} + +func (x MatchType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use MatchType.Descriptor instead. +func (MatchType) EnumDescriptor() ([]byte, []int) { + return file_acl_grpc_types_proto_rawDescGZIP(), []int{1} +} + +// Request's operation type to match if the rule is applicable to a particular +// request. +type Operation int32 + +const ( + // Unspecified operation, default value + Operation_OPERATION_UNSPECIFIED Operation = 0 + // Get + Operation_GET Operation = 1 + // Head + Operation_HEAD Operation = 2 + // Put + Operation_PUT Operation = 3 + // Delete + Operation_DELETE Operation = 4 + // Search + Operation_SEARCH Operation = 5 + // GetRange + Operation_GETRANGE Operation = 6 + // GetRangeHash + Operation_GETRANGEHASH Operation = 7 +) + +// Enum value maps for Operation. +var ( + Operation_name = map[int32]string{ + 0: "OPERATION_UNSPECIFIED", + 1: "GET", + 2: "HEAD", + 3: "PUT", + 4: "DELETE", + 5: "SEARCH", + 6: "GETRANGE", + 7: "GETRANGEHASH", + } + Operation_value = map[string]int32{ + "OPERATION_UNSPECIFIED": 0, + "GET": 1, + "HEAD": 2, + "PUT": 3, + "DELETE": 4, + "SEARCH": 5, + "GETRANGE": 6, + "GETRANGEHASH": 7, + } +) + +func (x Operation) Enum() *Operation { + p := new(Operation) + *p = x + return p +} + +func (x Operation) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (Operation) Descriptor() protoreflect.EnumDescriptor { + return file_acl_grpc_types_proto_enumTypes[2].Descriptor() +} + +func (Operation) Type() protoreflect.EnumType { + return &file_acl_grpc_types_proto_enumTypes[2] +} + +func (x Operation) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use Operation.Descriptor instead. +func (Operation) EnumDescriptor() ([]byte, []int) { + return file_acl_grpc_types_proto_rawDescGZIP(), []int{2} +} + +// Rule execution result action. Either allows or denies access if the rule's +// filters match. +type Action int32 + +const ( + // Unspecified action, default value + Action_ACTION_UNSPECIFIED Action = 0 + // Allow action + Action_ALLOW Action = 1 + // Deny action + Action_DENY Action = 2 +) + +// Enum value maps for Action. +var ( + Action_name = map[int32]string{ + 0: "ACTION_UNSPECIFIED", + 1: "ALLOW", + 2: "DENY", + } + Action_value = map[string]int32{ + "ACTION_UNSPECIFIED": 0, + "ALLOW": 1, + "DENY": 2, + } +) + +func (x Action) Enum() *Action { + p := new(Action) + *p = x + return p +} + +func (x Action) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (Action) Descriptor() protoreflect.EnumDescriptor { + return file_acl_grpc_types_proto_enumTypes[3].Descriptor() +} + +func (Action) Type() protoreflect.EnumType { + return &file_acl_grpc_types_proto_enumTypes[3] +} + +func (x Action) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use Action.Descriptor instead. +func (Action) EnumDescriptor() ([]byte, []int) { + return file_acl_grpc_types_proto_rawDescGZIP(), []int{3} +} + +// Enumeration of possible sources of Headers to apply filters. +type HeaderType int32 + +const ( + // Unspecified header, default value. + HeaderType_HEADER_UNSPECIFIED HeaderType = 0 + // Filter request headers + HeaderType_REQUEST HeaderType = 1 + // Filter object headers + HeaderType_OBJECT HeaderType = 2 + // Filter service headers. These are not processed by NeoFS nodes and + // exist for service use only. + HeaderType_SERVICE HeaderType = 3 +) + +// Enum value maps for HeaderType. +var ( + HeaderType_name = map[int32]string{ + 0: "HEADER_UNSPECIFIED", + 1: "REQUEST", + 2: "OBJECT", + 3: "SERVICE", + } + HeaderType_value = map[string]int32{ + "HEADER_UNSPECIFIED": 0, + "REQUEST": 1, + "OBJECT": 2, + "SERVICE": 3, + } +) + +func (x HeaderType) Enum() *HeaderType { + p := new(HeaderType) + *p = x + return p +} + +func (x HeaderType) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (HeaderType) Descriptor() protoreflect.EnumDescriptor { + return file_acl_grpc_types_proto_enumTypes[4].Descriptor() +} + +func (HeaderType) Type() protoreflect.EnumType { + return &file_acl_grpc_types_proto_enumTypes[4] +} + +func (x HeaderType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use HeaderType.Descriptor instead. +func (HeaderType) EnumDescriptor() ([]byte, []int) { + return file_acl_grpc_types_proto_rawDescGZIP(), []int{4} +} + +// Describes a single eACL rule. +type EACLRecord struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // NeoFS request Verb to match + Operation Operation `protobuf:"varint,1,opt,name=operation,proto3,enum=neo.fs.v2.acl.Operation" json:"operation,omitempty"` + // Rule execution result. Either allows or denies access if filters match. + Action Action `protobuf:"varint,2,opt,name=action,proto3,enum=neo.fs.v2.acl.Action" json:"action,omitempty"` + // List of filters to match and see if rule is applicable + Filters []*EACLRecord_Filter `protobuf:"bytes,3,rep,name=filters,proto3" json:"filters,omitempty"` + // List of target subjects to apply ACL rule to + Targets []*EACLRecord_Target `protobuf:"bytes,4,rep,name=targets,proto3" json:"targets,omitempty"` +} + +func (x *EACLRecord) Reset() { + *x = EACLRecord{} + if protoimpl.UnsafeEnabled { + mi := &file_acl_grpc_types_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *EACLRecord) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EACLRecord) ProtoMessage() {} + +func (x *EACLRecord) ProtoReflect() protoreflect.Message { + mi := &file_acl_grpc_types_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use EACLRecord.ProtoReflect.Descriptor instead. +func (*EACLRecord) Descriptor() ([]byte, []int) { + return file_acl_grpc_types_proto_rawDescGZIP(), []int{0} +} + +func (x *EACLRecord) GetOperation() Operation { + if x != nil { + return x.Operation + } + return Operation_OPERATION_UNSPECIFIED +} + +func (x *EACLRecord) GetAction() Action { + if x != nil { + return x.Action + } + return Action_ACTION_UNSPECIFIED +} + +func (x *EACLRecord) GetFilters() []*EACLRecord_Filter { + if x != nil { + return x.Filters + } + return nil +} + +func (x *EACLRecord) GetTargets() []*EACLRecord_Target { + if x != nil { + return x.Targets + } + return nil +} + +// Extended ACL rules table. A list of ACL rules defined additionally to Basic +// ACL. Extended ACL rules can be attached to a container and can be updated +// or may be defined in `BearerToken` structure. Please see the corresponding +// NeoFS Technical Specification section for detailed description. +type EACLTable struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // eACL format version. Effectively, the version of API library used to create + // eACL Table. + Version *grpc.Version `protobuf:"bytes,1,opt,name=version,proto3" json:"version,omitempty"` + // Identifier of the container that should use given access control rules + ContainerId *grpc.ContainerID `protobuf:"bytes,2,opt,name=container_id,json=containerID,proto3" json:"container_id,omitempty"` + // List of Extended ACL rules + Records []*EACLRecord `protobuf:"bytes,3,rep,name=records,proto3" json:"records,omitempty"` +} + +func (x *EACLTable) Reset() { + *x = EACLTable{} + if protoimpl.UnsafeEnabled { + mi := &file_acl_grpc_types_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *EACLTable) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EACLTable) ProtoMessage() {} + +func (x *EACLTable) ProtoReflect() protoreflect.Message { + mi := &file_acl_grpc_types_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use EACLTable.ProtoReflect.Descriptor instead. +func (*EACLTable) Descriptor() ([]byte, []int) { + return file_acl_grpc_types_proto_rawDescGZIP(), []int{1} +} + +func (x *EACLTable) GetVersion() *grpc.Version { + if x != nil { + return x.Version + } + return nil +} + +func (x *EACLTable) GetContainerId() *grpc.ContainerID { + if x != nil { + return x.ContainerId + } + return nil +} + +func (x *EACLTable) GetRecords() []*EACLRecord { + if x != nil { + return x.Records + } + return nil +} + +// BearerToken allows to attach signed Extended ACL rules to the request in +// `RequestMetaHeader`. If container's Basic ACL rules allow, the attached rule +// set will be checked instead of one attached to the container itself. Just +// like [JWT](https://jwt.io), it has a limited lifetime and scope, hence can be +// used in the similar use cases, like providing authorisation to externally +// authenticated party. +// +// BearerToken can be issued only by the container's owner and must be signed +// using the key associated with the container's `OwnerID`. +type BearerToken struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Bearer Token body + Body *BearerToken_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Signature of BearerToken body + Signature *grpc.Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` +} + +func (x *BearerToken) Reset() { + *x = BearerToken{} + if protoimpl.UnsafeEnabled { + mi := &file_acl_grpc_types_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *BearerToken) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BearerToken) ProtoMessage() {} + +func (x *BearerToken) ProtoReflect() protoreflect.Message { + mi := &file_acl_grpc_types_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BearerToken.ProtoReflect.Descriptor instead. +func (*BearerToken) Descriptor() ([]byte, []int) { + return file_acl_grpc_types_proto_rawDescGZIP(), []int{2} +} + +func (x *BearerToken) GetBody() *BearerToken_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *BearerToken) GetSignature() *grpc.Signature { + if x != nil { + return x.Signature + } + return nil +} + +// Filter to check particular properties of the request or the object. +// +// By default `key` field refers to the corresponding object's `Attribute`. +// Some Object's header fields can also be accessed by adding `$Object:` +// prefix to the name. Here is the list of fields available via this prefix: +// +// - $Object:version \ +// version +// - $Object:objectID \ +// object_id +// - $Object:containerID \ +// container_id +// - $Object:ownerID \ +// owner_id +// - $Object:creationEpoch \ +// creation_epoch +// - $Object:payloadLength \ +// payload_length +// - $Object:payloadHash \ +// payload_hash +// - $Object:objectType \ +// object_type +// - $Object:homomorphicHash \ +// homomorphic_hash +// +// Please note, that if request or response does not have object's headers of +// full object (Range, RangeHash, Search, Delete), it will not be possible to +// filter by object header fields or user attributes. From the well-known list +// only `$Object:objectID` and `$Object:containerID` will be available, as +// it's possible to take that information from the requested address. +type EACLRecord_Filter struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Define if Object or Request header will be used + HeaderType HeaderType `protobuf:"varint,1,opt,name=header_type,json=headerType,proto3,enum=neo.fs.v2.acl.HeaderType" json:"header_type,omitempty"` + // Match operation type + MatchType MatchType `protobuf:"varint,2,opt,name=match_type,json=matchType,proto3,enum=neo.fs.v2.acl.MatchType" json:"match_type,omitempty"` + // Name of the Header to use + Key string `protobuf:"bytes,3,opt,name=key,proto3" json:"key,omitempty"` + // Expected Header Value or pattern to match + Value string `protobuf:"bytes,4,opt,name=value,proto3" json:"value,omitempty"` +} + +func (x *EACLRecord_Filter) Reset() { + *x = EACLRecord_Filter{} + if protoimpl.UnsafeEnabled { + mi := &file_acl_grpc_types_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *EACLRecord_Filter) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EACLRecord_Filter) ProtoMessage() {} + +func (x *EACLRecord_Filter) ProtoReflect() protoreflect.Message { + mi := &file_acl_grpc_types_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use EACLRecord_Filter.ProtoReflect.Descriptor instead. +func (*EACLRecord_Filter) Descriptor() ([]byte, []int) { + return file_acl_grpc_types_proto_rawDescGZIP(), []int{0, 0} +} + +func (x *EACLRecord_Filter) GetHeaderType() HeaderType { + if x != nil { + return x.HeaderType + } + return HeaderType_HEADER_UNSPECIFIED +} + +func (x *EACLRecord_Filter) GetMatchType() MatchType { + if x != nil { + return x.MatchType + } + return MatchType_MATCH_TYPE_UNSPECIFIED +} + +func (x *EACLRecord_Filter) GetKey() string { + if x != nil { + return x.Key + } + return "" +} + +func (x *EACLRecord_Filter) GetValue() string { + if x != nil { + return x.Value + } + return "" +} + +// Target to apply ACL rule. Can be a subject's role class or a list of public +// keys to match. +type EACLRecord_Target struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Target subject's role class + Role Role `protobuf:"varint,1,opt,name=role,proto3,enum=neo.fs.v2.acl.Role" json:"role,omitempty"` + // List of public keys to identify target subject + Keys [][]byte `protobuf:"bytes,2,rep,name=keys,proto3" json:"keys,omitempty"` +} + +func (x *EACLRecord_Target) Reset() { + *x = EACLRecord_Target{} + if protoimpl.UnsafeEnabled { + mi := &file_acl_grpc_types_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *EACLRecord_Target) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EACLRecord_Target) ProtoMessage() {} + +func (x *EACLRecord_Target) ProtoReflect() protoreflect.Message { + mi := &file_acl_grpc_types_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use EACLRecord_Target.ProtoReflect.Descriptor instead. +func (*EACLRecord_Target) Descriptor() ([]byte, []int) { + return file_acl_grpc_types_proto_rawDescGZIP(), []int{0, 1} +} + +func (x *EACLRecord_Target) GetRole() Role { + if x != nil { + return x.Role + } + return Role_ROLE_UNSPECIFIED +} + +func (x *EACLRecord_Target) GetKeys() [][]byte { + if x != nil { + return x.Keys + } + return nil +} + +// Bearer Token body structure contains Extended ACL table issued by the +// container owner with additional information preventing token abuse. +type BearerToken_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Table of Extended ACL rules to use instead of the ones attached to the + // container. If it contains `container_id` field, bearer token is only + // valid for this specific container. Otherwise, any container of the same + // owner is allowed. + EaclTable *EACLTable `protobuf:"bytes,1,opt,name=eacl_table,json=eaclTable,proto3" json:"eacl_table,omitempty"` + // `OwnerID` defines to whom the token was issued. It must match the request + // originator's `OwnerID`. If empty, any token bearer will be accepted. + OwnerId *grpc.OwnerID `protobuf:"bytes,2,opt,name=owner_id,json=ownerID,proto3" json:"owner_id,omitempty"` + // Token expiration and valid time period parameters + Lifetime *BearerToken_Body_TokenLifetime `protobuf:"bytes,3,opt,name=lifetime,proto3" json:"lifetime,omitempty"` + // AllowImpersonate flag to consider token signer as request owner. + // If this field is true extended ACL table in token body isn't processed. + AllowImpersonate bool `protobuf:"varint,4,opt,name=allow_impersonate,json=allowImpersonate,proto3" json:"allow_impersonate,omitempty"` +} + +func (x *BearerToken_Body) Reset() { + *x = BearerToken_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_acl_grpc_types_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *BearerToken_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BearerToken_Body) ProtoMessage() {} + +func (x *BearerToken_Body) ProtoReflect() protoreflect.Message { + mi := &file_acl_grpc_types_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BearerToken_Body.ProtoReflect.Descriptor instead. +func (*BearerToken_Body) Descriptor() ([]byte, []int) { + return file_acl_grpc_types_proto_rawDescGZIP(), []int{2, 0} +} + +func (x *BearerToken_Body) GetEaclTable() *EACLTable { + if x != nil { + return x.EaclTable + } + return nil +} + +func (x *BearerToken_Body) GetOwnerId() *grpc.OwnerID { + if x != nil { + return x.OwnerId + } + return nil +} + +func (x *BearerToken_Body) GetLifetime() *BearerToken_Body_TokenLifetime { + if x != nil { + return x.Lifetime + } + return nil +} + +func (x *BearerToken_Body) GetAllowImpersonate() bool { + if x != nil { + return x.AllowImpersonate + } + return false +} + +// Lifetime parameters of the token. Field names taken from +// [rfc7519](https://tools.ietf.org/html/rfc7519). +type BearerToken_Body_TokenLifetime struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Expiration Epoch + Exp uint64 `protobuf:"varint,1,opt,name=exp,proto3" json:"exp,omitempty"` + // Not valid before Epoch + Nbf uint64 `protobuf:"varint,2,opt,name=nbf,proto3" json:"nbf,omitempty"` + // Issued at Epoch + Iat uint64 `protobuf:"varint,3,opt,name=iat,proto3" json:"iat,omitempty"` +} + +func (x *BearerToken_Body_TokenLifetime) Reset() { + *x = BearerToken_Body_TokenLifetime{} + if protoimpl.UnsafeEnabled { + mi := &file_acl_grpc_types_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *BearerToken_Body_TokenLifetime) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BearerToken_Body_TokenLifetime) ProtoMessage() {} + +func (x *BearerToken_Body_TokenLifetime) ProtoReflect() protoreflect.Message { + mi := &file_acl_grpc_types_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BearerToken_Body_TokenLifetime.ProtoReflect.Descriptor instead. +func (*BearerToken_Body_TokenLifetime) Descriptor() ([]byte, []int) { + return file_acl_grpc_types_proto_rawDescGZIP(), []int{2, 0, 0} +} + +func (x *BearerToken_Body_TokenLifetime) GetExp() uint64 { + if x != nil { + return x.Exp + } + return 0 +} + +func (x *BearerToken_Body_TokenLifetime) GetNbf() uint64 { + if x != nil { + return x.Nbf + } + return 0 +} + +func (x *BearerToken_Body_TokenLifetime) GetIat() uint64 { + if x != nil { + return x.Iat + } + return 0 +} + +var File_acl_grpc_types_proto protoreflect.FileDescriptor + +var file_acl_grpc_types_proto_rawDesc = []byte{ + 0x0a, 0x14, 0x61, 0x63, 0x6c, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0d, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, + 0x32, 0x2e, 0x61, 0x63, 0x6c, 0x1a, 0x15, 0x72, 0x65, 0x66, 0x73, 0x2f, 0x67, 0x72, 0x70, 0x63, + 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xda, 0x03, 0x0a, + 0x0a, 0x45, 0x41, 0x43, 0x4c, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x12, 0x36, 0x0a, 0x09, 0x6f, + 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, + 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x61, 0x63, 0x6c, 0x2e, 0x4f, + 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x2d, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, + 0x61, 0x63, 0x6c, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x3a, 0x0a, 0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, + 0x61, 0x63, 0x6c, 0x2e, 0x45, 0x41, 0x43, 0x4c, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x2e, 0x46, + 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x12, 0x3a, + 0x0a, 0x07, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x20, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x61, 0x63, 0x6c, 0x2e, + 0x45, 0x41, 0x43, 0x4c, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x2e, 0x54, 0x61, 0x72, 0x67, 0x65, + 0x74, 0x52, 0x07, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x1a, 0xa5, 0x01, 0x0a, 0x06, 0x46, + 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x3a, 0x0a, 0x0b, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, + 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x6e, 0x65, 0x6f, + 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x61, 0x63, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0a, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x54, 0x79, 0x70, + 0x65, 0x12, 0x37, 0x0a, 0x0a, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, + 0x32, 0x2e, 0x61, 0x63, 0x6c, 0x2e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x54, 0x79, 0x70, 0x65, 0x52, + 0x09, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x54, 0x79, 0x70, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, + 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x1a, 0x45, 0x0a, 0x06, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x27, 0x0a, 0x04, + 0x72, 0x6f, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x13, 0x2e, 0x6e, 0x65, 0x6f, + 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x61, 0x63, 0x6c, 0x2e, 0x52, 0x6f, 0x6c, 0x65, 0x52, + 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x02, 0x20, + 0x03, 0x28, 0x0c, 0x52, 0x04, 0x6b, 0x65, 0x79, 0x73, 0x22, 0xb3, 0x01, 0x0a, 0x09, 0x45, 0x41, + 0x43, 0x4c, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x31, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, + 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, + 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x65, 0x66, 0x73, 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x3e, 0x0a, 0x0c, 0x63, 0x6f, + 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1b, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x65, 0x66, + 0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x44, 0x52, 0x0b, 0x63, + 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x44, 0x12, 0x33, 0x0a, 0x07, 0x72, 0x65, + 0x63, 0x6f, 0x72, 0x64, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x6e, 0x65, + 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x61, 0x63, 0x6c, 0x2e, 0x45, 0x41, 0x43, 0x4c, + 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x52, 0x07, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x22, + 0xb0, 0x03, 0x0a, 0x0b, 0x42, 0x65, 0x61, 0x72, 0x65, 0x72, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, + 0x33, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, + 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x61, 0x63, 0x6c, 0x2e, 0x42, 0x65, + 0x61, 0x72, 0x65, 0x72, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, + 0x62, 0x6f, 0x64, 0x79, 0x12, 0x37, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, + 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x65, 0x66, 0x73, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0xb2, 0x02, + 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x37, 0x0a, 0x0a, 0x65, 0x61, 0x63, 0x6c, 0x5f, 0x74, + 0x61, 0x62, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6e, 0x65, 0x6f, + 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x61, 0x63, 0x6c, 0x2e, 0x45, 0x41, 0x43, 0x4c, 0x54, + 0x61, 0x62, 0x6c, 0x65, 0x52, 0x09, 0x65, 0x61, 0x63, 0x6c, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x12, + 0x32, 0x0a, 0x08, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x17, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x65, + 0x66, 0x73, 0x2e, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x49, 0x44, 0x52, 0x07, 0x6f, 0x77, 0x6e, 0x65, + 0x72, 0x49, 0x44, 0x12, 0x49, 0x0a, 0x08, 0x6c, 0x69, 0x66, 0x65, 0x74, 0x69, 0x6d, 0x65, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, + 0x32, 0x2e, 0x61, 0x63, 0x6c, 0x2e, 0x42, 0x65, 0x61, 0x72, 0x65, 0x72, 0x54, 0x6f, 0x6b, 0x65, + 0x6e, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x2e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x4c, 0x69, 0x66, 0x65, + 0x74, 0x69, 0x6d, 0x65, 0x52, 0x08, 0x6c, 0x69, 0x66, 0x65, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x2b, + 0x0a, 0x11, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x69, 0x6d, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, + 0x61, 0x74, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x61, 0x6c, 0x6c, 0x6f, 0x77, + 0x49, 0x6d, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x61, 0x74, 0x65, 0x1a, 0x45, 0x0a, 0x0d, 0x54, + 0x6f, 0x6b, 0x65, 0x6e, 0x4c, 0x69, 0x66, 0x65, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, + 0x65, 0x78, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x65, 0x78, 0x70, 0x12, 0x10, + 0x0a, 0x03, 0x6e, 0x62, 0x66, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x6e, 0x62, 0x66, + 0x12, 0x10, 0x0a, 0x03, 0x69, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x69, + 0x61, 0x74, 0x2a, 0x3e, 0x0a, 0x04, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0x14, 0x0a, 0x10, 0x52, 0x4f, + 0x4c, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, + 0x12, 0x08, 0x0a, 0x04, 0x55, 0x53, 0x45, 0x52, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x59, + 0x53, 0x54, 0x45, 0x4d, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x4f, 0x54, 0x48, 0x45, 0x52, 0x53, + 0x10, 0x03, 0x2a, 0x4f, 0x0a, 0x09, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x54, 0x79, 0x70, 0x65, 0x12, + 0x1a, 0x0a, 0x16, 0x4d, 0x41, 0x54, 0x43, 0x48, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, + 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x10, 0x0a, 0x0c, 0x53, + 0x54, 0x52, 0x49, 0x4e, 0x47, 0x5f, 0x45, 0x51, 0x55, 0x41, 0x4c, 0x10, 0x01, 0x12, 0x14, 0x0a, + 0x10, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x45, 0x51, 0x55, 0x41, + 0x4c, 0x10, 0x02, 0x2a, 0x7a, 0x0a, 0x09, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x19, 0x0a, 0x15, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, + 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x47, + 0x45, 0x54, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x48, 0x45, 0x41, 0x44, 0x10, 0x02, 0x12, 0x07, + 0x0a, 0x03, 0x50, 0x55, 0x54, 0x10, 0x03, 0x12, 0x0a, 0x0a, 0x06, 0x44, 0x45, 0x4c, 0x45, 0x54, + 0x45, 0x10, 0x04, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x45, 0x41, 0x52, 0x43, 0x48, 0x10, 0x05, 0x12, + 0x0c, 0x0a, 0x08, 0x47, 0x45, 0x54, 0x52, 0x41, 0x4e, 0x47, 0x45, 0x10, 0x06, 0x12, 0x10, 0x0a, + 0x0c, 0x47, 0x45, 0x54, 0x52, 0x41, 0x4e, 0x47, 0x45, 0x48, 0x41, 0x53, 0x48, 0x10, 0x07, 0x2a, + 0x35, 0x0a, 0x06, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x12, 0x41, 0x43, 0x54, + 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, + 0x00, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, + 0x44, 0x45, 0x4e, 0x59, 0x10, 0x02, 0x2a, 0x4a, 0x0a, 0x0a, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x54, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x12, 0x48, 0x45, 0x41, 0x44, 0x45, 0x52, 0x5f, 0x55, + 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, + 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x4f, 0x42, 0x4a, + 0x45, 0x43, 0x54, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x45, 0x52, 0x56, 0x49, 0x43, 0x45, + 0x10, 0x03, 0x42, 0x58, 0x5a, 0x3c, 0x67, 0x69, 0x74, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, + 0x73, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, 0x75, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, + 0x4c, 0x61, 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2d, 0x61, 0x70, 0x69, 0x2d, + 0x67, 0x6f, 0x2f, 0x76, 0x32, 0x2f, 0x61, 0x63, 0x6c, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x3b, 0x61, + 0x63, 0x6c, 0xaa, 0x02, 0x17, 0x4e, 0x65, 0x6f, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x53, 0x74, 0x6f, + 0x72, 0x61, 0x67, 0x65, 0x2e, 0x41, 0x50, 0x49, 0x2e, 0x41, 0x63, 0x6c, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_acl_grpc_types_proto_rawDescOnce sync.Once + file_acl_grpc_types_proto_rawDescData = file_acl_grpc_types_proto_rawDesc +) + +func file_acl_grpc_types_proto_rawDescGZIP() []byte { + file_acl_grpc_types_proto_rawDescOnce.Do(func() { + file_acl_grpc_types_proto_rawDescData = protoimpl.X.CompressGZIP(file_acl_grpc_types_proto_rawDescData) + }) + return file_acl_grpc_types_proto_rawDescData +} + +var file_acl_grpc_types_proto_enumTypes = make([]protoimpl.EnumInfo, 5) +var file_acl_grpc_types_proto_msgTypes = make([]protoimpl.MessageInfo, 7) +var file_acl_grpc_types_proto_goTypes = []interface{}{ + (Role)(0), // 0: neo.fs.v2.acl.Role + (MatchType)(0), // 1: neo.fs.v2.acl.MatchType + (Operation)(0), // 2: neo.fs.v2.acl.Operation + (Action)(0), // 3: neo.fs.v2.acl.Action + (HeaderType)(0), // 4: neo.fs.v2.acl.HeaderType + (*EACLRecord)(nil), // 5: neo.fs.v2.acl.EACLRecord + (*EACLTable)(nil), // 6: neo.fs.v2.acl.EACLTable + (*BearerToken)(nil), // 7: neo.fs.v2.acl.BearerToken + (*EACLRecord_Filter)(nil), // 8: neo.fs.v2.acl.EACLRecord.Filter + (*EACLRecord_Target)(nil), // 9: neo.fs.v2.acl.EACLRecord.Target + (*BearerToken_Body)(nil), // 10: neo.fs.v2.acl.BearerToken.Body + (*BearerToken_Body_TokenLifetime)(nil), // 11: neo.fs.v2.acl.BearerToken.Body.TokenLifetime + (*grpc.Version)(nil), // 12: neo.fs.v2.refs.Version + (*grpc.ContainerID)(nil), // 13: neo.fs.v2.refs.ContainerID + (*grpc.Signature)(nil), // 14: neo.fs.v2.refs.Signature + (*grpc.OwnerID)(nil), // 15: neo.fs.v2.refs.OwnerID +} +var file_acl_grpc_types_proto_depIdxs = []int32{ + 2, // 0: neo.fs.v2.acl.EACLRecord.operation:type_name -> neo.fs.v2.acl.Operation + 3, // 1: neo.fs.v2.acl.EACLRecord.action:type_name -> neo.fs.v2.acl.Action + 8, // 2: neo.fs.v2.acl.EACLRecord.filters:type_name -> neo.fs.v2.acl.EACLRecord.Filter + 9, // 3: neo.fs.v2.acl.EACLRecord.targets:type_name -> neo.fs.v2.acl.EACLRecord.Target + 12, // 4: neo.fs.v2.acl.EACLTable.version:type_name -> neo.fs.v2.refs.Version + 13, // 5: neo.fs.v2.acl.EACLTable.container_id:type_name -> neo.fs.v2.refs.ContainerID + 5, // 6: neo.fs.v2.acl.EACLTable.records:type_name -> neo.fs.v2.acl.EACLRecord + 10, // 7: neo.fs.v2.acl.BearerToken.body:type_name -> neo.fs.v2.acl.BearerToken.Body + 14, // 8: neo.fs.v2.acl.BearerToken.signature:type_name -> neo.fs.v2.refs.Signature + 4, // 9: neo.fs.v2.acl.EACLRecord.Filter.header_type:type_name -> neo.fs.v2.acl.HeaderType + 1, // 10: neo.fs.v2.acl.EACLRecord.Filter.match_type:type_name -> neo.fs.v2.acl.MatchType + 0, // 11: neo.fs.v2.acl.EACLRecord.Target.role:type_name -> neo.fs.v2.acl.Role + 6, // 12: neo.fs.v2.acl.BearerToken.Body.eacl_table:type_name -> neo.fs.v2.acl.EACLTable + 15, // 13: neo.fs.v2.acl.BearerToken.Body.owner_id:type_name -> neo.fs.v2.refs.OwnerID + 11, // 14: neo.fs.v2.acl.BearerToken.Body.lifetime:type_name -> neo.fs.v2.acl.BearerToken.Body.TokenLifetime + 15, // [15:15] is the sub-list for method output_type + 15, // [15:15] is the sub-list for method input_type + 15, // [15:15] is the sub-list for extension type_name + 15, // [15:15] is the sub-list for extension extendee + 0, // [0:15] is the sub-list for field type_name +} + +func init() { file_acl_grpc_types_proto_init() } +func file_acl_grpc_types_proto_init() { + if File_acl_grpc_types_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_acl_grpc_types_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*EACLRecord); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_acl_grpc_types_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*EACLTable); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_acl_grpc_types_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*BearerToken); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_acl_grpc_types_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*EACLRecord_Filter); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_acl_grpc_types_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*EACLRecord_Target); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_acl_grpc_types_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*BearerToken_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_acl_grpc_types_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*BearerToken_Body_TokenLifetime); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_acl_grpc_types_proto_rawDesc, + NumEnums: 5, + NumMessages: 7, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_acl_grpc_types_proto_goTypes, + DependencyIndexes: file_acl_grpc_types_proto_depIdxs, + EnumInfos: file_acl_grpc_types_proto_enumTypes, + MessageInfos: file_acl_grpc_types_proto_msgTypes, + }.Build() + File_acl_grpc_types_proto = out.File + file_acl_grpc_types_proto_rawDesc = nil + file_acl_grpc_types_proto_goTypes = nil + file_acl_grpc_types_proto_depIdxs = nil +} diff --git a/pkg/api/acl/json.go b/pkg/api/acl/json.go new file mode 100644 index 000000000..6ebd0bcd6 --- /dev/null +++ b/pkg/api/acl/json.go @@ -0,0 +1,62 @@ +package acl + +import ( + acl "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/acl/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/message" +) + +func (f *HeaderFilter) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(f) +} + +func (f *HeaderFilter) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(f, data, new(acl.EACLRecord_Filter)) +} + +func (t *Target) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(t) +} + +func (t *Target) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(t, data, new(acl.EACLRecord_Target)) +} + +func (r *Record) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(r) +} + +func (r *Record) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(r, data, new(acl.EACLRecord)) +} + +func (t *Table) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(t) +} + +func (t *Table) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(t, data, new(acl.EACLTable)) +} + +func (l *TokenLifetime) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(l) +} + +func (l *TokenLifetime) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(l, data, new(acl.BearerToken_Body_TokenLifetime)) +} + +func (bt *BearerTokenBody) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(bt) +} + +func (bt *BearerTokenBody) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(bt, data, new(acl.BearerToken_Body)) +} + +func (bt *BearerToken) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(bt) +} + +func (bt *BearerToken) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(bt, data, new(acl.BearerToken)) +} diff --git a/pkg/api/acl/marshal.go b/pkg/api/acl/marshal.go new file mode 100644 index 000000000..9cb8fc28e --- /dev/null +++ b/pkg/api/acl/marshal.go @@ -0,0 +1,308 @@ +package acl + +import ( + acl "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/acl/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/message" + protoutil "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/util/proto" +) + +const ( + filterHeaderTypeField = 1 + filterMatchTypeField = 2 + filterNameField = 3 + filterValueField = 4 + + targetTypeField = 1 + targetKeysField = 2 + + recordOperationField = 1 + recordActionField = 2 + recordFiltersField = 3 + recordTargetsField = 4 + + tableVersionField = 1 + tableContainerIDField = 2 + tableRecordsField = 3 + + lifetimeExpirationField = 1 + lifetimeNotValidBeforeField = 2 + lifetimeIssuedAtField = 3 + + bearerTokenBodyACLField = 1 + bearerTokenBodyOwnerField = 2 + bearerTokenBodyLifetimeField = 3 + bearerTokenBodyImpersonate = 4 + + bearerTokenBodyField = 1 + bearerTokenSignatureField = 2 +) + +// StableMarshal marshals unified acl table structure in a protobuf +// compatible way without field order shuffle. +func (t *Table) StableMarshal(buf []byte) []byte { + if t == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, t.StableSize()) + } + + var offset int + + offset += protoutil.NestedStructureMarshal(tableVersionField, buf[offset:], t.version) + offset += protoutil.NestedStructureMarshal(tableContainerIDField, buf[offset:], t.cid) + + for i := range t.records { + offset += protoutil.NestedStructureMarshal(tableRecordsField, buf[offset:], &t.records[i]) + } + + return buf +} + +// StableSize of acl table structure marshalled by StableMarshal function. +func (t *Table) StableSize() (size int) { + if t == nil { + return 0 + } + + size += protoutil.NestedStructureSize(tableVersionField, t.version) + size += protoutil.NestedStructureSize(tableContainerIDField, t.cid) + + for i := range t.records { + size += protoutil.NestedStructureSize(tableRecordsField, &t.records[i]) + } + + return size +} + +func (t *Table) Unmarshal(data []byte) error { + return message.Unmarshal(t, data, new(acl.EACLTable)) +} + +// StableMarshal marshals unified acl record structure in a protobuf +// compatible way without field order shuffle. +func (r *Record) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + var offset int + + offset += protoutil.EnumMarshal(recordOperationField, buf[offset:], int32(r.op)) + offset += protoutil.EnumMarshal(recordActionField, buf[offset:], int32(r.action)) + + for i := range r.filters { + offset += protoutil.NestedStructureMarshal(recordFiltersField, buf[offset:], &r.filters[i]) + } + + for i := range r.targets { + offset += protoutil.NestedStructureMarshal(recordTargetsField, buf[offset:], &r.targets[i]) + } + + return buf +} + +// StableSize of acl record structure marshalled by StableMarshal function. +func (r *Record) StableSize() (size int) { + if r == nil { + return 0 + } + + size += protoutil.EnumSize(recordOperationField, int32(r.op)) + size += protoutil.EnumSize(recordActionField, int32(r.action)) + + for i := range r.filters { + size += protoutil.NestedStructureSize(recordFiltersField, &r.filters[i]) + } + + for i := range r.targets { + size += protoutil.NestedStructureSize(recordTargetsField, &r.targets[i]) + } + + return size +} + +func (r *Record) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(acl.EACLRecord)) +} + +// StableMarshal marshals unified header filter structure in a protobuf +// compatible way without field order shuffle. +func (f *HeaderFilter) StableMarshal(buf []byte) []byte { + if f == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, f.StableSize()) + } + + var offset int + + offset += protoutil.EnumMarshal(filterHeaderTypeField, buf[offset:], int32(f.hdrType)) + offset += protoutil.EnumMarshal(filterMatchTypeField, buf[offset:], int32(f.matchType)) + offset += protoutil.StringMarshal(filterNameField, buf[offset:], f.key) + protoutil.StringMarshal(filterValueField, buf[offset:], f.value) + + return buf +} + +// StableSize of header filter structure marshalled by StableMarshal function. +func (f *HeaderFilter) StableSize() (size int) { + if f == nil { + return 0 + } + + size += protoutil.EnumSize(filterHeaderTypeField, int32(f.hdrType)) + size += protoutil.EnumSize(filterMatchTypeField, int32(f.matchType)) + size += protoutil.StringSize(filterNameField, f.key) + size += protoutil.StringSize(filterValueField, f.value) + + return size +} + +func (f *HeaderFilter) Unmarshal(data []byte) error { + return message.Unmarshal(f, data, new(acl.EACLRecord_Filter)) +} + +// StableMarshal marshals unified role info structure in a protobuf +// compatible way without field order shuffle. +func (t *Target) StableMarshal(buf []byte) []byte { + if t == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, t.StableSize()) + } + + var offset int + + offset += protoutil.EnumMarshal(targetTypeField, buf[offset:], int32(t.role)) + protoutil.RepeatedBytesMarshal(targetKeysField, buf[offset:], t.keys) + + return buf +} + +// StableSize of role info structure marshalled by StableMarshal function. +func (t *Target) StableSize() (size int) { + if t == nil { + return 0 + } + + size += protoutil.EnumSize(targetTypeField, int32(t.role)) + size += protoutil.RepeatedBytesSize(targetKeysField, t.keys) + + return size +} + +func (t *Target) Unmarshal(data []byte) error { + return message.Unmarshal(t, data, new(acl.EACLRecord_Target)) +} + +func (l *TokenLifetime) StableMarshal(buf []byte) []byte { + if l == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, l.StableSize()) + } + + var offset int + + offset += protoutil.UInt64Marshal(lifetimeExpirationField, buf[offset:], l.exp) + offset += protoutil.UInt64Marshal(lifetimeNotValidBeforeField, buf[offset:], l.nbf) + protoutil.UInt64Marshal(lifetimeIssuedAtField, buf[offset:], l.iat) + + return buf +} + +func (l *TokenLifetime) StableSize() (size int) { + if l == nil { + return 0 + } + + size += protoutil.UInt64Size(lifetimeExpirationField, l.exp) + size += protoutil.UInt64Size(lifetimeNotValidBeforeField, l.nbf) + size += protoutil.UInt64Size(lifetimeIssuedAtField, l.iat) + + return size +} + +func (l *TokenLifetime) Unmarshal(data []byte) error { + return message.Unmarshal(l, data, new(acl.BearerToken_Body_TokenLifetime)) +} + +func (bt *BearerTokenBody) StableMarshal(buf []byte) []byte { + if bt == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, bt.StableSize()) + } + + var offset int + + offset += protoutil.NestedStructureMarshal(bearerTokenBodyACLField, buf[offset:], bt.eacl) + offset += protoutil.NestedStructureMarshal(bearerTokenBodyOwnerField, buf[offset:], bt.ownerID) + offset += protoutil.NestedStructureMarshal(bearerTokenBodyLifetimeField, buf[offset:], bt.lifetime) + protoutil.BoolMarshal(bearerTokenBodyImpersonate, buf[offset:], bt.impersonate) + + return buf +} + +func (bt *BearerTokenBody) StableSize() (size int) { + if bt == nil { + return 0 + } + + size += protoutil.NestedStructureSize(bearerTokenBodyACLField, bt.eacl) + size += protoutil.NestedStructureSize(bearerTokenBodyOwnerField, bt.ownerID) + size += protoutil.NestedStructureSize(bearerTokenBodyLifetimeField, bt.lifetime) + size += protoutil.BoolSize(bearerTokenBodyImpersonate, bt.impersonate) + + return size +} + +func (bt *BearerTokenBody) Unmarshal(data []byte) error { + return message.Unmarshal(bt, data, new(acl.BearerToken_Body)) +} + +func (bt *BearerToken) StableMarshal(buf []byte) []byte { + if bt == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, bt.StableSize()) + } + + var offset int + + offset += protoutil.NestedStructureMarshal(bearerTokenBodyField, buf[offset:], bt.body) + protoutil.NestedStructureMarshal(bearerTokenSignatureField, buf[offset:], bt.sig) + + return buf +} + +func (bt *BearerToken) StableSize() (size int) { + if bt == nil { + return 0 + } + + size += protoutil.NestedStructureSize(bearerTokenBodyField, bt.body) + size += protoutil.NestedStructureSize(bearerTokenSignatureField, bt.sig) + + return size +} + +func (bt *BearerToken) Unmarshal(data []byte) error { + return message.Unmarshal(bt, data, new(acl.BearerToken)) +} diff --git a/pkg/api/acl/message_test.go b/pkg/api/acl/message_test.go new file mode 100644 index 000000000..40f25e2e0 --- /dev/null +++ b/pkg/api/acl/message_test.go @@ -0,0 +1,21 @@ +package acl_test + +import ( + "testing" + + acltest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/acl/test" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/message" + messagetest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/message/test" +) + +func TestMessageConvert(t *testing.T) { + messagetest.TestRPCMessage(t, + func(empty bool) message.Message { return acltest.GenerateFilter(empty) }, + func(empty bool) message.Message { return acltest.GenerateTarget(empty) }, + func(empty bool) message.Message { return acltest.GenerateRecord(empty) }, + func(empty bool) message.Message { return acltest.GenerateTable(empty) }, + func(empty bool) message.Message { return acltest.GenerateTokenLifetime(empty) }, + func(empty bool) message.Message { return acltest.GenerateBearerTokenBody(empty) }, + func(empty bool) message.Message { return acltest.GenerateBearerToken(empty) }, + ) +} diff --git a/pkg/api/acl/string.go b/pkg/api/acl/string.go new file mode 100644 index 000000000..8f8a69ea3 --- /dev/null +++ b/pkg/api/acl/string.go @@ -0,0 +1,110 @@ +package acl + +import ( + acl "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/acl/grpc" +) + +// String returns string representation of Action. +func (x Action) String() string { + return ActionToGRPCField(x).String() +} + +// FromString parses Action from a string representation. +// It is a reverse action to String(). +// +// Returns true if s was parsed successfully. +func (x *Action) FromString(s string) bool { + var g acl.Action + + ok := g.FromString(s) + + if ok { + *x = ActionFromGRPCField(g) + } + + return ok +} + +// String returns string representation of Role. +func (x Role) String() string { + return RoleToGRPCField(x).String() +} + +// FromString parses Role from a string representation. +// It is a reverse action to String(). +// +// Returns true if s was parsed successfully. +func (x *Role) FromString(s string) bool { + var g acl.Role + + ok := g.FromString(s) + + if ok { + *x = RoleFromGRPCField(g) + } + + return ok +} + +// String returns string representation of Operation. +func (x Operation) String() string { + return OperationToGRPCField(x).String() +} + +// FromString parses Operation from a string representation. +// It is a reverse action to String(). +// +// Returns true if s was parsed successfully. +func (x *Operation) FromString(s string) bool { + var g acl.Operation + + ok := g.FromString(s) + + if ok { + *x = OperationFromGRPCField(g) + } + + return ok +} + +// String returns string representation of MatchType. +func (x MatchType) String() string { + return MatchTypeToGRPCField(x).String() +} + +// FromString parses MatchType from a string representation. +// It is a reverse action to String(). +// +// Returns true if s was parsed successfully. +func (x *MatchType) FromString(s string) bool { + var g acl.MatchType + + ok := g.FromString(s) + + if ok { + *x = MatchTypeFromGRPCField(g) + } + + return ok +} + +// String returns string representation of HeaderType. +func (x HeaderType) String() string { + return HeaderTypeToGRPCField(x).String() +} + +// FromString parses HeaderType from a string representation. +// It is a reverse action to String(). +// +// Returns true if s was parsed successfully. +func (x *HeaderType) FromString(s string) bool { + var g acl.HeaderType + + ok := g.FromString(s) + + if ok { + *x = HeaderTypeFromGRPCField(g) + } + + return ok +} diff --git a/pkg/api/acl/test/generate.go b/pkg/api/acl/test/generate.go new file mode 100644 index 000000000..fce4a78e5 --- /dev/null +++ b/pkg/api/acl/test/generate.go @@ -0,0 +1,131 @@ +package acltest + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/acl" + accountingtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs/test" +) + +func GenerateBearerToken(empty bool) *acl.BearerToken { + m := new(acl.BearerToken) + + if !empty { + m.SetBody(GenerateBearerTokenBody(false)) + } + + m.SetSignature(accountingtest.GenerateSignature(empty)) + + return m +} + +func GenerateBearerTokenBody(empty bool) *acl.BearerTokenBody { + m := new(acl.BearerTokenBody) + + if !empty { + m.SetOwnerID(accountingtest.GenerateOwnerID(false)) + m.SetEACL(GenerateTable(false)) + m.SetLifetime(GenerateTokenLifetime(false)) + } + + return m +} + +func GenerateTable(empty bool) *acl.Table { + m := new(acl.Table) + + if !empty { + m.SetRecords(GenerateRecords(false)) + m.SetContainerID(accountingtest.GenerateContainerID(false)) + } + + m.SetVersion(accountingtest.GenerateVersion(empty)) + + return m +} + +func GenerateRecords(empty bool) []acl.Record { + var rs []acl.Record + + if !empty { + rs = append(rs, + *GenerateRecord(false), + *GenerateRecord(false), + ) + } + + return rs +} + +func GenerateRecord(empty bool) *acl.Record { + m := new(acl.Record) + + if !empty { + m.SetAction(acl.ActionAllow) + m.SetOperation(acl.OperationGet) + m.SetFilters(GenerateFilters(false)) + m.SetTargets(GenerateTargets(false)) + } + + return m +} + +func GenerateFilters(empty bool) []acl.HeaderFilter { + var fs []acl.HeaderFilter + + if !empty { + fs = append(fs, + *GenerateFilter(false), + *GenerateFilter(false), + ) + } + + return fs +} + +func GenerateFilter(empty bool) *acl.HeaderFilter { + m := new(acl.HeaderFilter) + + if !empty { + m.SetKey("key") + m.SetValue("val") + m.SetHeaderType(acl.HeaderTypeRequest) + m.SetMatchType(acl.MatchTypeStringEqual) + } + + return m +} + +func GenerateTargets(empty bool) []acl.Target { + var ts []acl.Target + + if !empty { + ts = append(ts, + *GenerateTarget(false), + *GenerateTarget(false), + ) + } + + return ts +} + +func GenerateTarget(empty bool) *acl.Target { + m := new(acl.Target) + + if !empty { + m.SetRole(acl.RoleSystem) + m.SetKeys([][]byte{{1}, {2}}) + } + + return m +} + +func GenerateTokenLifetime(empty bool) *acl.TokenLifetime { + m := new(acl.TokenLifetime) + + if !empty { + m.SetExp(1) + m.SetIat(2) + m.SetExp(3) + } + + return m +} diff --git a/pkg/api/acl/types.go b/pkg/api/acl/types.go new file mode 100644 index 000000000..138c6590c --- /dev/null +++ b/pkg/api/acl/types.go @@ -0,0 +1,379 @@ +package acl + +import "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + +// HeaderFilter is a unified structure of FilterInfo +// message from proto definition. +type HeaderFilter struct { + hdrType HeaderType + + matchType MatchType + + key, value string +} + +// Target is a unified structure of Target +// message from proto definition. +type Target struct { + role Role + + keys [][]byte +} + +// Record is a unified structure of EACLRecord +// message from proto definition. +type Record struct { + op Operation + + action Action + + filters []HeaderFilter + + targets []Target +} + +// Table is a unified structure of EACLTable +// message from proto definition. +type Table struct { + version *refs.Version + + cid *refs.ContainerID + + records []Record +} + +type TokenLifetime struct { + exp, nbf, iat uint64 +} + +type BearerTokenBody struct { + eacl *Table + + ownerID *refs.OwnerID + + lifetime *TokenLifetime + + impersonate bool +} + +type BearerToken struct { + body *BearerTokenBody + + sig *refs.Signature +} + +// Target is a unified enum of MatchType enum from proto definition. +type MatchType uint32 + +// HeaderType is a unified enum of HeaderType enum from proto definition. +type HeaderType uint32 + +// Action is a unified enum of Action enum from proto definition. +type Action uint32 + +// Operation is a unified enum of Operation enum from proto definition. +type Operation uint32 + +// Role is a unified enum of Role enum from proto definition. +type Role uint32 + +const ( + MatchTypeUnknown MatchType = iota + MatchTypeStringEqual + MatchTypeStringNotEqual +) + +const ( + HeaderTypeUnknown HeaderType = iota + HeaderTypeRequest + HeaderTypeObject + HeaderTypeService +) + +const ( + ActionUnknown Action = iota + ActionAllow + ActionDeny +) + +const ( + OperationUnknown Operation = iota + OperationGet + OperationHead + OperationPut + OperationDelete + OperationSearch + OperationRange + OperationRangeHash +) + +const ( + RoleUnknown Role = iota + RoleUser + RoleSystem + RoleOthers +) + +func (f *HeaderFilter) GetHeaderType() HeaderType { + if f != nil { + return f.hdrType + } + + return HeaderTypeUnknown +} + +func (f *HeaderFilter) SetHeaderType(v HeaderType) { + f.hdrType = v +} + +func (f *HeaderFilter) GetMatchType() MatchType { + if f != nil { + return f.matchType + } + + return MatchTypeUnknown +} + +func (f *HeaderFilter) SetMatchType(v MatchType) { + f.matchType = v +} + +func (f *HeaderFilter) GetKey() string { + if f != nil { + return f.key + } + + return "" +} + +func (f *HeaderFilter) SetKey(v string) { + f.key = v +} + +func (f *HeaderFilter) GetValue() string { + if f != nil { + return f.value + } + + return "" +} + +func (f *HeaderFilter) SetValue(v string) { + f.value = v +} + +func (t *Target) GetRole() Role { + if t != nil { + return t.role + } + + return RoleUnknown +} + +func (t *Target) SetRole(v Role) { + t.role = v +} + +func (t *Target) GetKeys() [][]byte { + if t != nil { + return t.keys + } + + return nil +} + +func (t *Target) SetKeys(v [][]byte) { + t.keys = v +} + +func (r *Record) GetOperation() Operation { + if r != nil { + return r.op + } + + return OperationUnknown +} + +func (r *Record) SetOperation(v Operation) { + r.op = v +} + +func (r *Record) GetAction() Action { + if r != nil { + return r.action + } + + return ActionUnknown +} + +func (r *Record) SetAction(v Action) { + r.action = v +} + +func (r *Record) GetFilters() []HeaderFilter { + if r != nil { + return r.filters + } + + return nil +} + +func (r *Record) SetFilters(v []HeaderFilter) { + r.filters = v +} + +func (r *Record) GetTargets() []Target { + if r != nil { + return r.targets + } + + return nil +} + +func (r *Record) SetTargets(v []Target) { + r.targets = v +} + +func (t *Table) GetVersion() *refs.Version { + if t != nil { + return t.version + } + + return nil +} + +func (t *Table) SetVersion(v *refs.Version) { + t.version = v +} + +func (t *Table) GetContainerID() *refs.ContainerID { + if t != nil { + return t.cid + } + + return nil +} + +func (t *Table) SetContainerID(v *refs.ContainerID) { + t.cid = v +} + +func (t *Table) GetRecords() []Record { + if t != nil { + return t.records + } + + return nil +} + +func (t *Table) SetRecords(v []Record) { + t.records = v +} + +func (l *TokenLifetime) GetExp() uint64 { + if l != nil { + return l.exp + } + + return 0 +} + +func (l *TokenLifetime) SetExp(v uint64) { + l.exp = v +} + +func (l *TokenLifetime) GetNbf() uint64 { + if l != nil { + return l.nbf + } + + return 0 +} + +func (l *TokenLifetime) SetNbf(v uint64) { + l.nbf = v +} + +func (l *TokenLifetime) GetIat() uint64 { + if l != nil { + return l.iat + } + + return 0 +} + +func (l *TokenLifetime) SetIat(v uint64) { + l.iat = v +} + +func (bt *BearerTokenBody) GetEACL() *Table { + if bt != nil { + return bt.eacl + } + + return nil +} + +func (bt *BearerTokenBody) SetEACL(v *Table) { + bt.eacl = v +} + +func (bt *BearerTokenBody) GetOwnerID() *refs.OwnerID { + if bt != nil { + return bt.ownerID + } + + return nil +} + +func (bt *BearerTokenBody) SetOwnerID(v *refs.OwnerID) { + bt.ownerID = v +} + +func (bt *BearerTokenBody) GetLifetime() *TokenLifetime { + if bt != nil { + return bt.lifetime + } + + return nil +} + +func (bt *BearerTokenBody) SetLifetime(v *TokenLifetime) { + bt.lifetime = v +} + +func (bt *BearerTokenBody) GetImpersonate() bool { + if bt != nil { + return bt.impersonate + } + + return false +} + +func (bt *BearerTokenBody) SetImpersonate(v bool) { + bt.impersonate = v +} + +func (bt *BearerToken) GetBody() *BearerTokenBody { + if bt != nil { + return bt.body + } + + return nil +} + +func (bt *BearerToken) SetBody(v *BearerTokenBody) { + bt.body = v +} + +func (bt *BearerToken) GetSignature() *refs.Signature { + if bt != nil { + return bt.sig + } + + return nil +} + +func (bt *BearerToken) SetSignature(v *refs.Signature) { + bt.sig = v +} diff --git a/pkg/api/audit/convert.go b/pkg/api/audit/convert.go new file mode 100644 index 000000000..67b0f27cf --- /dev/null +++ b/pkg/api/audit/convert.go @@ -0,0 +1,94 @@ +package audit + +import ( + audit "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/audit/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + refsGRPC "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/message" +) + +func (a *DataAuditResult) ToGRPCMessage() grpc.Message { + var m *audit.DataAuditResult + + if a != nil { + m = new(audit.DataAuditResult) + + m.SetAuditEpoch(a.auditEpoch) + m.SetPublicKey(a.pubKey) + m.SetContainerId(a.cid.ToGRPCMessage().(*refsGRPC.ContainerID)) + m.SetComplete(a.complete) + m.SetVersion(a.version.ToGRPCMessage().(*refsGRPC.Version)) + m.SetPassNodes(a.passNodes) + m.SetFailNodes(a.failNodes) + m.SetRetries(a.retries) + m.SetRequests(a.requests) + m.SetHit(a.hit) + m.SetMiss(a.miss) + m.SetFail(a.fail) + m.SetPassSg(refs.ObjectIDListToGRPCMessage(a.passSG)) + m.SetFailSg(refs.ObjectIDListToGRPCMessage(a.failSG)) + } + + return m +} + +func (a *DataAuditResult) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*audit.DataAuditResult) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + cid := v.GetContainerId() + if cid == nil { + a.cid = nil + } else { + if a.cid == nil { + a.cid = new(refs.ContainerID) + } + + err = a.cid.FromGRPCMessage(cid) + if err != nil { + return err + } + } + + version := v.GetVersion() + if version == nil { + a.version = nil + } else { + if a.version == nil { + a.version = new(refs.Version) + } + + err = a.version.FromGRPCMessage(version) + if err != nil { + return err + } + } + + a.passSG, err = refs.ObjectIDListFromGRPCMessage(v.GetPassSg()) + if err != nil { + return err + } + + a.failSG, err = refs.ObjectIDListFromGRPCMessage(v.GetFailSg()) + if err != nil { + return err + } + + a.auditEpoch = v.GetAuditEpoch() + a.pubKey = v.GetPublicKey() + a.complete = v.GetComplete() + a.passNodes = v.GetPassNodes() + a.failNodes = v.GetFailNodes() + a.retries = v.GetRetries() + a.requests = v.GetRequests() + a.hit = v.GetHit() + a.miss = v.GetMiss() + a.fail = v.GetFail() + + return err +} diff --git a/pkg/api/audit/grpc/types.go b/pkg/api/audit/grpc/types.go new file mode 100644 index 000000000..cfb901afa --- /dev/null +++ b/pkg/api/audit/grpc/types.go @@ -0,0 +1,75 @@ +package audit + +import ( + refs "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs/grpc" +) + +// SetVersion is a Version field setter. +func (x *DataAuditResult) SetVersion(v *refs.Version) { + x.Version = v +} + +// SetAuditEpoch is an AuditEpoch field setter. +func (x *DataAuditResult) SetAuditEpoch(v uint64) { + x.AuditEpoch = v +} + +// SetContainerId is a ContainerId field setter. +func (x *DataAuditResult) SetContainerId(v *refs.ContainerID) { + x.ContainerId = v +} + +// SetPublicKey is a PublicKey field setter. +func (x *DataAuditResult) SetPublicKey(v []byte) { + x.PublicKey = v +} + +// SetComplete is a Complete field setter. +func (x *DataAuditResult) SetComplete(v bool) { + x.Complete = v +} + +// SetRequests is a Requests field setter. +func (x *DataAuditResult) SetRequests(v uint32) { + x.Requests = v +} + +// SetRetries is a Retries field setter. +func (x *DataAuditResult) SetRetries(v uint32) { + x.Retries = v +} + +// SetPassSg is a PassSg field setter. +func (x *DataAuditResult) SetPassSg(v []*refs.ObjectID) { + x.PassSg = v +} + +// SetFailSg is a FailSg field setter. +func (x *DataAuditResult) SetFailSg(v []*refs.ObjectID) { + x.FailSg = v +} + +// SetHit is a Hit field setter. +func (x *DataAuditResult) SetHit(v uint32) { + x.Hit = v +} + +// SetMiss is a Miss field setter. +func (x *DataAuditResult) SetMiss(v uint32) { + x.Miss = v +} + +// SetFail is a Fail field setter. +func (x *DataAuditResult) SetFail(v uint32) { + x.Fail = v +} + +// SetPassNodes is a PassNodes field setter. +func (x *DataAuditResult) SetPassNodes(v [][]byte) { + x.PassNodes = v +} + +// SetFailNodes is a FailNodes field setter. +func (x *DataAuditResult) SetFailNodes(v [][]byte) { + x.FailNodes = v +} diff --git a/pkg/api/audit/grpc/types.pb.go b/pkg/api/audit/grpc/types.pb.go new file mode 100644 index 000000000..c68d1ecb5 --- /dev/null +++ b/pkg/api/audit/grpc/types.pb.go @@ -0,0 +1,311 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.33.0 +// protoc v4.25.3 +// source: audit/grpc/types.proto + +package audit + +import ( + grpc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs/grpc" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// DataAuditResult keeps record of conducted Data Audits. The detailed report is +// generated separately. +type DataAuditResult struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Data Audit Result format version. Effectively, the version of API library + // used to report DataAuditResult structure. + Version *grpc.Version `protobuf:"bytes,1,opt,name=version,proto3" json:"version,omitempty"` + // Epoch number when the Data Audit was conducted + AuditEpoch uint64 `protobuf:"fixed64,2,opt,name=audit_epoch,json=auditEpoch,proto3" json:"audit_epoch,omitempty"` + // Container under audit + ContainerId *grpc.ContainerID `protobuf:"bytes,3,opt,name=container_id,json=containerID,proto3" json:"container_id,omitempty"` + // Public key of the auditing InnerRing node in a binary format + PublicKey []byte `protobuf:"bytes,4,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"` + // Shows if Data Audit process was complete in time or if it was cancelled + Complete bool `protobuf:"varint,5,opt,name=complete,proto3" json:"complete,omitempty"` + // Number of request done at PoR stage + Requests uint32 `protobuf:"varint,6,opt,name=requests,proto3" json:"requests,omitempty"` + // Number of retries done at PoR stage + Retries uint32 `protobuf:"varint,7,opt,name=retries,proto3" json:"retries,omitempty"` + // List of Storage Groups that passed audit PoR stage + PassSg []*grpc.ObjectID `protobuf:"bytes,8,rep,name=pass_sg,json=passSG,proto3" json:"pass_sg,omitempty"` + // List of Storage Groups that failed audit PoR stage + FailSg []*grpc.ObjectID `protobuf:"bytes,9,rep,name=fail_sg,json=failSG,proto3" json:"fail_sg,omitempty"` + // Number of sampled objects under the audit placed in an optimal way + // according to the containers placement policy when checking PoP + Hit uint32 `protobuf:"varint,10,opt,name=hit,proto3" json:"hit,omitempty"` + // Number of sampled objects under the audit placed in suboptimal way + // according to the containers placement policy, but still at a satisfactory + // level when checking PoP + Miss uint32 `protobuf:"varint,11,opt,name=miss,proto3" json:"miss,omitempty"` + // Number of sampled objects under the audit stored inconsistently with the + // placement policy or not found at all when checking PoP + Fail uint32 `protobuf:"varint,12,opt,name=fail,proto3" json:"fail,omitempty"` + // List of storage node public keys that passed at least one PDP + PassNodes [][]byte `protobuf:"bytes,13,rep,name=pass_nodes,json=passNodes,proto3" json:"pass_nodes,omitempty"` + // List of storage node public keys that failed at least one PDP + FailNodes [][]byte `protobuf:"bytes,14,rep,name=fail_nodes,json=failNodes,proto3" json:"fail_nodes,omitempty"` +} + +func (x *DataAuditResult) Reset() { + *x = DataAuditResult{} + if protoimpl.UnsafeEnabled { + mi := &file_audit_grpc_types_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DataAuditResult) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DataAuditResult) ProtoMessage() {} + +func (x *DataAuditResult) ProtoReflect() protoreflect.Message { + mi := &file_audit_grpc_types_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DataAuditResult.ProtoReflect.Descriptor instead. +func (*DataAuditResult) Descriptor() ([]byte, []int) { + return file_audit_grpc_types_proto_rawDescGZIP(), []int{0} +} + +func (x *DataAuditResult) GetVersion() *grpc.Version { + if x != nil { + return x.Version + } + return nil +} + +func (x *DataAuditResult) GetAuditEpoch() uint64 { + if x != nil { + return x.AuditEpoch + } + return 0 +} + +func (x *DataAuditResult) GetContainerId() *grpc.ContainerID { + if x != nil { + return x.ContainerId + } + return nil +} + +func (x *DataAuditResult) GetPublicKey() []byte { + if x != nil { + return x.PublicKey + } + return nil +} + +func (x *DataAuditResult) GetComplete() bool { + if x != nil { + return x.Complete + } + return false +} + +func (x *DataAuditResult) GetRequests() uint32 { + if x != nil { + return x.Requests + } + return 0 +} + +func (x *DataAuditResult) GetRetries() uint32 { + if x != nil { + return x.Retries + } + return 0 +} + +func (x *DataAuditResult) GetPassSg() []*grpc.ObjectID { + if x != nil { + return x.PassSg + } + return nil +} + +func (x *DataAuditResult) GetFailSg() []*grpc.ObjectID { + if x != nil { + return x.FailSg + } + return nil +} + +func (x *DataAuditResult) GetHit() uint32 { + if x != nil { + return x.Hit + } + return 0 +} + +func (x *DataAuditResult) GetMiss() uint32 { + if x != nil { + return x.Miss + } + return 0 +} + +func (x *DataAuditResult) GetFail() uint32 { + if x != nil { + return x.Fail + } + return 0 +} + +func (x *DataAuditResult) GetPassNodes() [][]byte { + if x != nil { + return x.PassNodes + } + return nil +} + +func (x *DataAuditResult) GetFailNodes() [][]byte { + if x != nil { + return x.FailNodes + } + return nil +} + +var File_audit_grpc_types_proto protoreflect.FileDescriptor + +var file_audit_grpc_types_proto_rawDesc = []byte{ + 0x0a, 0x16, 0x61, 0x75, 0x64, 0x69, 0x74, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x74, 0x79, 0x70, + 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, + 0x2e, 0x76, 0x32, 0x2e, 0x61, 0x75, 0x64, 0x69, 0x74, 0x1a, 0x15, 0x72, 0x65, 0x66, 0x73, 0x2f, + 0x67, 0x72, 0x70, 0x63, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x22, 0xf4, 0x03, 0x0a, 0x0f, 0x44, 0x61, 0x74, 0x61, 0x41, 0x75, 0x64, 0x69, 0x74, 0x52, 0x65, + 0x73, 0x75, 0x6c, 0x74, 0x12, 0x31, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, + 0x32, 0x2e, 0x72, 0x65, 0x66, 0x73, 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x07, + 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x75, 0x64, 0x69, 0x74, + 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x06, 0x52, 0x0a, 0x61, 0x75, + 0x64, 0x69, 0x74, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x3e, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, + 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, + 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x65, 0x66, 0x73, 0x2e, + 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x44, 0x52, 0x0b, 0x63, 0x6f, 0x6e, + 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x44, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, + 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x70, 0x75, + 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x6f, 0x6d, 0x70, 0x6c, + 0x65, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x63, 0x6f, 0x6d, 0x70, 0x6c, + 0x65, 0x74, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x12, + 0x18, 0x0a, 0x07, 0x72, 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0d, + 0x52, 0x07, 0x72, 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x12, 0x31, 0x0a, 0x07, 0x70, 0x61, 0x73, + 0x73, 0x5f, 0x73, 0x67, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6e, 0x65, 0x6f, + 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x65, 0x66, 0x73, 0x2e, 0x4f, 0x62, 0x6a, 0x65, + 0x63, 0x74, 0x49, 0x44, 0x52, 0x06, 0x70, 0x61, 0x73, 0x73, 0x53, 0x47, 0x12, 0x31, 0x0a, 0x07, + 0x66, 0x61, 0x69, 0x6c, 0x5f, 0x73, 0x67, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, + 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x65, 0x66, 0x73, 0x2e, 0x4f, + 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x44, 0x52, 0x06, 0x66, 0x61, 0x69, 0x6c, 0x53, 0x47, 0x12, + 0x10, 0x0a, 0x03, 0x68, 0x69, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x68, 0x69, + 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x69, 0x73, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0d, 0x52, + 0x04, 0x6d, 0x69, 0x73, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x61, 0x69, 0x6c, 0x18, 0x0c, 0x20, + 0x01, 0x28, 0x0d, 0x52, 0x04, 0x66, 0x61, 0x69, 0x6c, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x73, + 0x73, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x09, 0x70, + 0x61, 0x73, 0x73, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x66, 0x61, 0x69, 0x6c, + 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x0e, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x09, 0x66, 0x61, + 0x69, 0x6c, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x42, 0x5e, 0x5a, 0x40, 0x67, 0x69, 0x74, 0x2e, 0x66, + 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, 0x75, 0x65, + 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x4c, 0x61, 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, + 0x2d, 0x61, 0x70, 0x69, 0x2d, 0x67, 0x6f, 0x2f, 0x76, 0x32, 0x2f, 0x61, 0x75, 0x64, 0x69, 0x74, + 0x2f, 0x67, 0x72, 0x70, 0x63, 0x3b, 0x61, 0x75, 0x64, 0x69, 0x74, 0xaa, 0x02, 0x19, 0x4e, 0x65, + 0x6f, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x41, 0x50, + 0x49, 0x2e, 0x41, 0x75, 0x64, 0x69, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_audit_grpc_types_proto_rawDescOnce sync.Once + file_audit_grpc_types_proto_rawDescData = file_audit_grpc_types_proto_rawDesc +) + +func file_audit_grpc_types_proto_rawDescGZIP() []byte { + file_audit_grpc_types_proto_rawDescOnce.Do(func() { + file_audit_grpc_types_proto_rawDescData = protoimpl.X.CompressGZIP(file_audit_grpc_types_proto_rawDescData) + }) + return file_audit_grpc_types_proto_rawDescData +} + +var file_audit_grpc_types_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_audit_grpc_types_proto_goTypes = []interface{}{ + (*DataAuditResult)(nil), // 0: neo.fs.v2.audit.DataAuditResult + (*grpc.Version)(nil), // 1: neo.fs.v2.refs.Version + (*grpc.ContainerID)(nil), // 2: neo.fs.v2.refs.ContainerID + (*grpc.ObjectID)(nil), // 3: neo.fs.v2.refs.ObjectID +} +var file_audit_grpc_types_proto_depIdxs = []int32{ + 1, // 0: neo.fs.v2.audit.DataAuditResult.version:type_name -> neo.fs.v2.refs.Version + 2, // 1: neo.fs.v2.audit.DataAuditResult.container_id:type_name -> neo.fs.v2.refs.ContainerID + 3, // 2: neo.fs.v2.audit.DataAuditResult.pass_sg:type_name -> neo.fs.v2.refs.ObjectID + 3, // 3: neo.fs.v2.audit.DataAuditResult.fail_sg:type_name -> neo.fs.v2.refs.ObjectID + 4, // [4:4] is the sub-list for method output_type + 4, // [4:4] is the sub-list for method input_type + 4, // [4:4] is the sub-list for extension type_name + 4, // [4:4] is the sub-list for extension extendee + 0, // [0:4] is the sub-list for field type_name +} + +func init() { file_audit_grpc_types_proto_init() } +func file_audit_grpc_types_proto_init() { + if File_audit_grpc_types_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_audit_grpc_types_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DataAuditResult); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_audit_grpc_types_proto_rawDesc, + NumEnums: 0, + NumMessages: 1, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_audit_grpc_types_proto_goTypes, + DependencyIndexes: file_audit_grpc_types_proto_depIdxs, + MessageInfos: file_audit_grpc_types_proto_msgTypes, + }.Build() + File_audit_grpc_types_proto = out.File + file_audit_grpc_types_proto_rawDesc = nil + file_audit_grpc_types_proto_goTypes = nil + file_audit_grpc_types_proto_depIdxs = nil +} diff --git a/pkg/api/audit/json.go b/pkg/api/audit/json.go new file mode 100644 index 000000000..de3b789b7 --- /dev/null +++ b/pkg/api/audit/json.go @@ -0,0 +1,14 @@ +package audit + +import ( + audit "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/audit/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/message" +) + +func (a *DataAuditResult) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(a) +} + +func (a *DataAuditResult) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(a, data, new(audit.DataAuditResult)) +} diff --git a/pkg/api/audit/marshal.go b/pkg/api/audit/marshal.go new file mode 100644 index 000000000..8e29a614c --- /dev/null +++ b/pkg/api/audit/marshal.go @@ -0,0 +1,88 @@ +package audit + +import ( + audit "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/audit/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/message" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/util/proto" +) + +const ( + _ = iota + versionFNum + auditEpochFNum + cidFNum + pubKeyFNum + completeFNum + requestsFNum + retriesFNum + passSGFNum + failSGFNum + hitFNum + missFNum + failFNum + passNodesFNum + failNodesFNum +) + +// StableMarshal marshals unified DataAuditResult structure into a protobuf +// binary format without field order shuffle. +func (a *DataAuditResult) StableMarshal(buf []byte) []byte { + if a == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, a.StableSize()) + } + + var offset int + + offset += proto.NestedStructureMarshal(versionFNum, buf[offset:], a.version) + offset += proto.Fixed64Marshal(auditEpochFNum, buf[offset:], a.auditEpoch) + offset += proto.NestedStructureMarshal(cidFNum, buf[offset:], a.cid) + offset += proto.BytesMarshal(pubKeyFNum, buf[offset:], a.pubKey) + offset += proto.BoolMarshal(completeFNum, buf[offset:], a.complete) + offset += proto.UInt32Marshal(requestsFNum, buf[offset:], a.requests) + offset += proto.UInt32Marshal(retriesFNum, buf[offset:], a.retries) + offset += refs.ObjectIDNestedListMarshal(passSGFNum, buf[offset:], a.passSG) + offset += refs.ObjectIDNestedListMarshal(failSGFNum, buf[offset:], a.failSG) + offset += proto.UInt32Marshal(hitFNum, buf[offset:], a.hit) + offset += proto.UInt32Marshal(missFNum, buf[offset:], a.miss) + offset += proto.UInt32Marshal(failFNum, buf[offset:], a.fail) + offset += proto.RepeatedBytesMarshal(passNodesFNum, buf[offset:], a.passNodes) + proto.RepeatedBytesMarshal(failNodesFNum, buf[offset:], a.failNodes) + + return buf +} + +// StableSize returns byte length of DataAuditResult structure +// marshaled by StableMarshal function. +func (a *DataAuditResult) StableSize() (size int) { + if a == nil { + return 0 + } + + size += proto.NestedStructureSize(versionFNum, a.version) + size += proto.Fixed64Size(auditEpochFNum, a.auditEpoch) + size += proto.NestedStructureSize(cidFNum, a.cid) + size += proto.BytesSize(pubKeyFNum, a.pubKey) + size += proto.BoolSize(completeFNum, a.complete) + size += proto.UInt32Size(requestsFNum, a.requests) + size += proto.UInt32Size(retriesFNum, a.retries) + size += refs.ObjectIDNestedListSize(passSGFNum, a.passSG) + size += refs.ObjectIDNestedListSize(failSGFNum, a.failSG) + size += proto.UInt32Size(hitFNum, a.hit) + size += proto.UInt32Size(missFNum, a.miss) + size += proto.UInt32Size(failFNum, a.fail) + size += proto.RepeatedBytesSize(passNodesFNum, a.passNodes) + size += proto.RepeatedBytesSize(failNodesFNum, a.failNodes) + + return size +} + +// Unmarshal unmarshals DataAuditResult structure from its protobuf +// binary representation. +func (a *DataAuditResult) Unmarshal(data []byte) error { + return message.Unmarshal(a, data, new(audit.DataAuditResult)) +} diff --git a/pkg/api/audit/message_test.go b/pkg/api/audit/message_test.go new file mode 100644 index 000000000..b0b6b6205 --- /dev/null +++ b/pkg/api/audit/message_test.go @@ -0,0 +1,15 @@ +package audit_test + +import ( + "testing" + + audittest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/audit/test" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/message" + messagetest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/message/test" +) + +func TestMessageConvert(t *testing.T) { + messagetest.TestRPCMessage(t, + func(empty bool) message.Message { return audittest.GenerateDataAuditResult(empty) }, + ) +} diff --git a/pkg/api/audit/test/generate.go b/pkg/api/audit/test/generate.go new file mode 100644 index 000000000..b4424e7d3 --- /dev/null +++ b/pkg/api/audit/test/generate.go @@ -0,0 +1,29 @@ +package audittest + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/audit" + refstest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs/test" +) + +func GenerateDataAuditResult(empty bool) *audit.DataAuditResult { + m := new(audit.DataAuditResult) + + if !empty { + m.SetPublicKey([]byte{1, 2, 3}) + m.SetAuditEpoch(13) + m.SetHit(100) + m.SetMiss(200) + m.SetFail(300) + m.SetComplete(true) + m.SetPassNodes([][]byte{{1}, {2}}) + m.SetFailNodes([][]byte{{3}, {4}}) + m.SetRequests(666) + m.SetRetries(777) + m.SetVersion(refstest.GenerateVersion(false)) + m.SetContainerID(refstest.GenerateContainerID(false)) + m.SetPassSG(refstest.GenerateObjectIDs(false)) + m.SetFailSG(refstest.GenerateObjectIDs(false)) + } + + return m +} diff --git a/pkg/api/audit/types.go b/pkg/api/audit/types.go new file mode 100644 index 000000000..88f6cc050 --- /dev/null +++ b/pkg/api/audit/types.go @@ -0,0 +1,243 @@ +package audit + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" +) + +// DataAuditResult is a unified structure of +// DataAuditResult message from proto definition. +type DataAuditResult struct { + version *refs.Version + + auditEpoch uint64 + + requests, retries uint32 + + hit, miss, fail uint32 + + cid *refs.ContainerID + + pubKey []byte + + passSG, failSG []refs.ObjectID + + failNodes, passNodes [][]byte + + complete bool +} + +// GetVersion returns version of Data Audit structure. +func (a *DataAuditResult) GetVersion() *refs.Version { + if a != nil { + return a.version + } + + return nil +} + +// SetVersion sets version of Data Audit structure. +func (a *DataAuditResult) SetVersion(v *refs.Version) { + a.version = v +} + +// GetAuditEpoch returns epoch number when the Data Audit was conducted. +func (a *DataAuditResult) GetAuditEpoch() uint64 { + if a != nil { + return a.auditEpoch + } + + return 0 +} + +// SetAuditEpoch sets epoch number when the Data Audit was conducted. +func (a *DataAuditResult) SetAuditEpoch(v uint64) { + a.auditEpoch = v +} + +// GetContainerID returns container under audit. +func (a *DataAuditResult) GetContainerID() *refs.ContainerID { + if a != nil { + return a.cid + } + + return nil +} + +// SetContainerID sets container under audit. +func (a *DataAuditResult) SetContainerID(v *refs.ContainerID) { + a.cid = v +} + +// GetPublicKey returns public key of the auditing InnerRing node in a binary format. +func (a *DataAuditResult) GetPublicKey() []byte { + if a != nil { + return a.pubKey + } + + return nil +} + +// SetPublicKey sets public key of the auditing InnerRing node in a binary format. +func (a *DataAuditResult) SetPublicKey(v []byte) { + a.pubKey = v +} + +// GetPassSG returns list of Storage Groups that passed audit PoR stage. +func (a *DataAuditResult) GetPassSG() []refs.ObjectID { + if a != nil { + return a.passSG + } + + return nil +} + +// SetPassSG sets list of Storage Groups that passed audit PoR stage. +func (a *DataAuditResult) SetPassSG(v []refs.ObjectID) { + a.passSG = v +} + +// GetFailSG returns list of Storage Groups that failed audit PoR stage. +func (a *DataAuditResult) GetFailSG() []refs.ObjectID { + if a != nil { + return a.failSG + } + + return nil +} + +// SetFailSG sets list of Storage Groups that failed audit PoR stage. +func (a *DataAuditResult) SetFailSG(v []refs.ObjectID) { + a.failSG = v +} + +// GetRequests returns number of requests made by PoR audit check to get +// all headers of the objects inside storage groups. +func (a *DataAuditResult) GetRequests() uint32 { + if a != nil { + return a.requests + } + + return 0 +} + +// SetRequests sets number of requests made by PoR audit check to get +// all headers of the objects inside storage groups. +func (a *DataAuditResult) SetRequests(v uint32) { + a.requests = v +} + +// GetRetries returns number of retries made by PoR audit check to get +// all headers of the objects inside storage groups. +func (a *DataAuditResult) GetRetries() uint32 { + if a != nil { + return a.retries + } + + return 0 +} + +// SetRetries sets number of retries made by PoR audit check to get +// all headers of the objects inside storage groups. +func (a *DataAuditResult) SetRetries(v uint32) { + a.retries = v +} + +// GetHit returns number of sampled objects under audit placed +// in an optimal way according to the containers placement policy +// when checking PoP. +func (a *DataAuditResult) GetHit() uint32 { + if a != nil { + return a.hit + } + + return 0 +} + +// SetHit sets number of sampled objects under audit placed +// in an optimal way according to the containers placement policy +// when checking PoP. +func (a *DataAuditResult) SetHit(v uint32) { + a.hit = v +} + +// GetMiss returns number of sampled objects under audit placed +// in suboptimal way according to the containers placement policy, +// but still at a satisfactory level when checking PoP. +func (a *DataAuditResult) GetMiss() uint32 { + if a != nil { + return a.miss + } + + return 0 +} + +// SetMiss sets number of sampled objects under audit placed +// in suboptimal way according to the containers placement policy, +// but still at a satisfactory level when checking PoP. +func (a *DataAuditResult) SetMiss(v uint32) { + a.miss = v +} + +// GetFail returns number of sampled objects under audit stored +// in a way not confirming placement policy or not found at all +// when checking PoP. +func (a *DataAuditResult) GetFail() uint32 { + if a != nil { + return a.fail + } + + return 0 +} + +// SetFail sets number of sampled objects under audit stored +// in a way not confirming placement policy or not found at all +// when checking PoP. +func (a *DataAuditResult) SetFail(v uint32) { + a.fail = v +} + +// GetPassNodes returns list of storage node public keys that +// passed at least one PDP. +func (a *DataAuditResult) GetPassNodes() [][]byte { + if a != nil { + return a.passNodes + } + + return nil +} + +// SetPassNodes sets list of storage node public keys that +// passed at least one PDP. +func (a *DataAuditResult) SetPassNodes(v [][]byte) { + a.passNodes = v +} + +// GetFailNodes returns list of storage node public keys that +// failed at least one PDP. +func (a *DataAuditResult) GetFailNodes() [][]byte { + if a != nil { + return a.failNodes + } + + return nil +} + +// SetFailNodes sets list of storage node public keys that +// failed at least one PDP. +func (a *DataAuditResult) SetFailNodes(v [][]byte) { + a.failNodes = v +} + +// GetComplete returns boolean completion statement of audit result. +func (a *DataAuditResult) GetComplete() bool { + if a != nil { + return a.complete + } + + return false // bool default +} + +// SetComplete sets boolean completion statement of audit result. +func (a *DataAuditResult) SetComplete(v bool) { + a.complete = v +} diff --git a/pkg/api/container/attributes.go b/pkg/api/container/attributes.go new file mode 100644 index 000000000..288d0484b --- /dev/null +++ b/pkg/api/container/attributes.go @@ -0,0 +1,90 @@ +package container + +// SysAttributePrefix is a prefix of key to system attribute. +const SysAttributePrefix = "__SYSTEM__" + +const ( + // SysAttributeName is a string of human-friendly container name registered as the domain in NNS contract. + SysAttributeName = SysAttributePrefix + "NAME" + + // SysAttributeZone is a string of zone for container name. + SysAttributeZone = SysAttributePrefix + "ZONE" + + // SysAttributeHomomorphicHashing is a container's homomorphic hashing state. + SysAttributeHomomorphicHashing = SysAttributePrefix + "DISABLE_HOMOMORPHIC_HASHING" +) + +// SysAttributePrefixNeoFS is a prefix of key to system attribute. +// Deprecated: use SysAttributePrefix. +const SysAttributePrefixNeoFS = "__NEOFS__" + +const ( + // SysAttributeNameNeoFS is a string of human-friendly container name registered as the domain in NNS contract. + // Deprecated: use SysAttributeName. + SysAttributeNameNeoFS = SysAttributePrefixNeoFS + "NAME" + + // SysAttributeZoneNeoFS is a string of zone for container name. + // Deprecated: use SysAttributeZone. + SysAttributeZoneNeoFS = SysAttributePrefixNeoFS + "ZONE" + + // SysAttributeHomomorphicHashingNeoFS is a container's homomorphic hashing state. + // Deprecated: use SysAttributeHomomorphicHashing. + SysAttributeHomomorphicHashingNeoFS = SysAttributePrefixNeoFS + "DISABLE_HOMOMORPHIC_HASHING" +) + +// SysAttributeZoneDefault is a default value for SysAttributeZone attribute. +const SysAttributeZoneDefault = "container" + +const disabledHomomorphicHashingValue = "true" + +// HomomorphicHashingState returns container's homomorphic +// hashing state: +// - true if hashing is enabled; +// - false if hashing is disabled. +// +// All container's attributes must be unique, otherwise behavior +// is undefined. +// +// See also SetHomomorphicHashingState. +func (c Container) HomomorphicHashingState() bool { + for i := range c.attr { + if c.attr[i].GetKey() == SysAttributeHomomorphicHashing || c.attr[i].GetKey() == SysAttributeHomomorphicHashingNeoFS { + return c.attr[i].GetValue() != disabledHomomorphicHashingValue + } + } + + return true +} + +// SetHomomorphicHashingState sets homomorphic hashing state for +// container. +// +// All container's attributes must be unique, otherwise behavior +// is undefined. +// +// See also HomomorphicHashingState. +func (c *Container) SetHomomorphicHashingState(enable bool) { + for i := range c.attr { + if c.attr[i].GetKey() == SysAttributeHomomorphicHashing || c.attr[i].GetKey() == SysAttributeHomomorphicHashingNeoFS { + if enable { + // approach without allocation/waste + // coping works since the attributes + // order is not important + c.attr[i] = c.attr[len(c.attr)-1] + c.attr = c.attr[:len(c.attr)-1] + } else { + c.attr[i].SetValue(disabledHomomorphicHashingValue) + } + + return + } + } + + if !enable { + attr := Attribute{} + attr.SetKey(SysAttributeHomomorphicHashing) + attr.SetValue(disabledHomomorphicHashingValue) + + c.attr = append(c.attr, attr) + } +} diff --git a/pkg/api/container/attributes_test.go b/pkg/api/container/attributes_test.go new file mode 100644 index 000000000..0ef8f7fe5 --- /dev/null +++ b/pkg/api/container/attributes_test.go @@ -0,0 +1,59 @@ +package container_test + +import ( + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/container" + containertest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/container/test" + "github.com/stretchr/testify/require" +) + +func TestContainer_HomomorphicHashingDisabled(t *testing.T) { + cnr := containertest.GenerateContainer(false) + + t.Run("defaults", func(t *testing.T) { + require.True(t, cnr.HomomorphicHashingState()) + }) + + t.Run("disabled", func(t *testing.T) { + attr := container.Attribute{} + attr.SetKey(container.SysAttributeHomomorphicHashing) + attr.SetValue("NOT_true") + + cnr.SetAttributes(append(cnr.GetAttributes(), attr)) + require.True(t, cnr.HomomorphicHashingState()) + + attr.SetValue("true") + + cnr.SetAttributes([]container.Attribute{attr}) + require.False(t, cnr.HomomorphicHashingState()) + }) +} + +func TestContainer_SetHomomorphicHashingState(t *testing.T) { + cnr := containertest.GenerateContainer(false) + attrs := cnr.GetAttributes() + attrLen := len(attrs) + + cnr.SetHomomorphicHashingState(true) + + // enabling hashing should not add any new attributes + require.Equal(t, attrLen, len(cnr.GetAttributes())) + require.True(t, cnr.HomomorphicHashingState()) + + cnr.SetHomomorphicHashingState(false) + + // disabling hashing should add exactly one attribute + require.Equal(t, attrLen+1, len(cnr.GetAttributes())) + require.False(t, cnr.HomomorphicHashingState()) + + cnr.SetHomomorphicHashingState(true) + + // enabling hashing should remove 1 attribute if + // hashing was disabled before + require.Equal(t, attrLen, len(cnr.GetAttributes())) + require.True(t, cnr.HomomorphicHashingState()) + + // hashing operations should not change any other attributes + require.ElementsMatch(t, attrs, cnr.GetAttributes()) +} diff --git a/pkg/api/container/convert.go b/pkg/api/container/convert.go new file mode 100644 index 000000000..ccd0f45a0 --- /dev/null +++ b/pkg/api/container/convert.go @@ -0,0 +1,1280 @@ +package container + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/acl" + aclGRPC "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/acl/grpc" + container "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/container/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/netmap" + netmapGRPC "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/netmap/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + refsGRPC "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/message" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" + sessionGRPC "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session/grpc" +) + +func (a *Attribute) ToGRPCMessage() grpc.Message { + var m *container.Container_Attribute + + if a != nil { + m = new(container.Container_Attribute) + + m.SetKey(a.key) + m.SetValue(a.val) + } + + return m +} + +func (a *Attribute) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*container.Container_Attribute) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + a.key = v.GetKey() + a.val = v.GetValue() + + return nil +} + +func AttributesToGRPC(xs []Attribute) (res []*container.Container_Attribute) { + if xs != nil { + res = make([]*container.Container_Attribute, 0, len(xs)) + + for i := range xs { + res = append(res, xs[i].ToGRPCMessage().(*container.Container_Attribute)) + } + } + + return +} + +func AttributesFromGRPC(xs []*container.Container_Attribute) (res []Attribute, err error) { + if xs != nil { + res = make([]Attribute, len(xs)) + + for i := range xs { + if xs[i] != nil { + err = res[i].FromGRPCMessage(xs[i]) + if err != nil { + return + } + } + } + } + + return +} + +func (c *Container) ToGRPCMessage() grpc.Message { + var m *container.Container + + if c != nil { + m = new(container.Container) + + m.SetVersion(c.version.ToGRPCMessage().(*refsGRPC.Version)) + m.SetOwnerId(c.ownerID.ToGRPCMessage().(*refsGRPC.OwnerID)) + m.SetPlacementPolicy(c.policy.ToGRPCMessage().(*netmapGRPC.PlacementPolicy)) + m.SetAttributes(AttributesToGRPC(c.attr)) + m.SetBasicAcl(c.basicACL) + m.SetNonce(c.nonce) + } + + return m +} + +func (c *Container) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*container.Container) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + version := v.GetVersion() + if version == nil { + c.version = nil + } else { + if c.version == nil { + c.version = new(refs.Version) + } + + err = c.version.FromGRPCMessage(version) + if err != nil { + return err + } + } + + ownerID := v.GetOwnerId() + if ownerID == nil { + c.ownerID = nil + } else { + if c.ownerID == nil { + c.ownerID = new(refs.OwnerID) + } + + err = c.ownerID.FromGRPCMessage(ownerID) + if err != nil { + return err + } + } + + policy := v.GetPlacementPolicy() + if policy == nil { + c.policy = nil + } else { + if c.policy == nil { + c.policy = new(netmap.PlacementPolicy) + } + + err = c.policy.FromGRPCMessage(policy) + if err != nil { + return err + } + } + + c.attr, err = AttributesFromGRPC(v.GetAttributes()) + if err != nil { + return err + } + + c.basicACL = v.GetBasicAcl() + c.nonce = v.GetNonce() + + return nil +} + +func toSignatureRFC6979(s *refs.Signature) *refsGRPC.SignatureRFC6979 { + var res *refsGRPC.SignatureRFC6979 + + if s != nil { + res = new(refsGRPC.SignatureRFC6979) + res.SetKey(s.GetKey()) + res.SetSign(s.GetSign()) + } + + return res +} + +func (r *PutRequestBody) ToGRPCMessage() grpc.Message { + var m *container.PutRequest_Body + + if r != nil { + m = new(container.PutRequest_Body) + + m.SetContainer(r.cnr.ToGRPCMessage().(*container.Container)) + m.SetSignature(toSignatureRFC6979(r.sig)) + } + + return m +} + +func (r *PutRequestBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*container.PutRequest_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + cnr := v.GetContainer() + if cnr == nil { + r.cnr = nil + } else { + if r.cnr == nil { + r.cnr = new(Container) + } + + err = r.cnr.FromGRPCMessage(cnr) + if err != nil { + return err + } + } + + sig := v.GetSignature() + if sig == nil { + r.sig = nil + } else { + if r.sig == nil { + r.sig = new(refs.Signature) + } + + r.sig.SetKey(sig.GetKey()) + r.sig.SetSign(sig.GetSign()) + } + + return err +} + +func (r *PutRequest) ToGRPCMessage() grpc.Message { + var m *container.PutRequest + + if r != nil { + m = new(container.PutRequest) + + m.SetBody(r.body.ToGRPCMessage().(*container.PutRequest_Body)) + r.RequestHeaders.ToMessage(m) + } + + return m +} + +func (r *PutRequest) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*container.PutRequest) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + r.body = nil + } else { + if r.body == nil { + r.body = new(PutRequestBody) + } + + err = r.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return r.RequestHeaders.FromMessage(v) +} + +func (r *PutResponseBody) ToGRPCMessage() grpc.Message { + var m *container.PutResponse_Body + + if r != nil { + m = new(container.PutResponse_Body) + + m.SetContainerId(r.cid.ToGRPCMessage().(*refsGRPC.ContainerID)) + } + + return m +} + +func (r *PutResponseBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*container.PutResponse_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + cid := v.GetContainerId() + if cid == nil { + r.cid = nil + } else { + if r.cid == nil { + r.cid = new(refs.ContainerID) + } + + err = r.cid.FromGRPCMessage(cid) + } + + return err +} + +func (r *PutResponse) ToGRPCMessage() grpc.Message { + var m *container.PutResponse + + if r != nil { + m = new(container.PutResponse) + + m.SetBody(r.body.ToGRPCMessage().(*container.PutResponse_Body)) + r.ResponseHeaders.ToMessage(m) + } + + return m +} + +func (r *PutResponse) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*container.PutResponse) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + r.body = nil + } else { + if r.body == nil { + r.body = new(PutResponseBody) + } + + err = r.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return r.ResponseHeaders.FromMessage(v) +} + +func (r *GetRequestBody) ToGRPCMessage() grpc.Message { + var m *container.GetRequest_Body + + if r != nil { + m = new(container.GetRequest_Body) + + m.SetContainerId(r.cid.ToGRPCMessage().(*refsGRPC.ContainerID)) + } + + return m +} + +func (r *GetRequestBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*container.GetRequest_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + cid := v.GetContainerId() + if cid == nil { + r.cid = nil + } else { + if r.cid == nil { + r.cid = new(refs.ContainerID) + } + + err = r.cid.FromGRPCMessage(cid) + } + + return err +} + +func (r *GetRequest) ToGRPCMessage() grpc.Message { + var m *container.GetRequest + + if r != nil { + m = new(container.GetRequest) + + m.SetBody(r.body.ToGRPCMessage().(*container.GetRequest_Body)) + r.RequestHeaders.ToMessage(m) + } + + return m +} + +func (r *GetRequest) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*container.GetRequest) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + r.body = nil + } else { + if r.body == nil { + r.body = new(GetRequestBody) + } + + err = r.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return r.RequestHeaders.FromMessage(v) +} + +func (r *GetResponseBody) ToGRPCMessage() grpc.Message { + var m *container.GetResponse_Body + + if r != nil { + m = new(container.GetResponse_Body) + + m.SetContainer(r.cnr.ToGRPCMessage().(*container.Container)) + m.SetSessionToken(r.token.ToGRPCMessage().(*sessionGRPC.SessionToken)) + m.SetSignature(toSignatureRFC6979(r.sig)) + } + + return m +} + +func (r *GetResponseBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*container.GetResponse_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + cnr := v.GetContainer() + if cnr == nil { + r.cnr = nil + } else { + if r.cnr == nil { + r.cnr = new(Container) + } + + err = r.cnr.FromGRPCMessage(cnr) + } + + sig := v.GetSignature() + if sig == nil { + r.sig = nil + } else { + if r.sig == nil { + r.sig = new(refs.Signature) + } + + r.sig.SetKey(sig.GetKey()) + r.sig.SetSign(sig.GetSign()) + } + + token := v.GetSessionToken() + if token == nil { + r.token = nil + } else { + if r.token == nil { + r.token = new(session.Token) + } + + err = r.token.FromGRPCMessage(token) + } + + return err +} + +func (r *GetResponse) ToGRPCMessage() grpc.Message { + var m *container.GetResponse + + if r != nil { + m = new(container.GetResponse) + + m.SetBody(r.body.ToGRPCMessage().(*container.GetResponse_Body)) + r.ResponseHeaders.ToMessage(m) + } + + return m +} + +func (r *GetResponse) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*container.GetResponse) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + r.body = nil + } else { + if r.body == nil { + r.body = new(GetResponseBody) + } + + err = r.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return r.ResponseHeaders.FromMessage(v) +} + +func (r *DeleteRequestBody) ToGRPCMessage() grpc.Message { + var m *container.DeleteRequest_Body + + if r != nil { + m = new(container.DeleteRequest_Body) + + m.SetContainerId(r.cid.ToGRPCMessage().(*refsGRPC.ContainerID)) + m.SetSignature(toSignatureRFC6979(r.sig)) + } + + return m +} + +func (r *DeleteRequestBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*container.DeleteRequest_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + cid := v.GetContainerId() + if cid == nil { + r.cid = nil + } else { + if r.cid == nil { + r.cid = new(refs.ContainerID) + } + + err = r.cid.FromGRPCMessage(cid) + if err != nil { + return err + } + } + + sig := v.GetSignature() + if sig == nil { + r.sig = nil + } else { + if r.sig == nil { + r.sig = new(refs.Signature) + } + + r.sig.SetKey(sig.GetKey()) + r.sig.SetSign(sig.GetSign()) + } + + return err +} + +func (r *DeleteRequest) ToGRPCMessage() grpc.Message { + var m *container.DeleteRequest + + if r != nil { + m = new(container.DeleteRequest) + + m.SetBody(r.body.ToGRPCMessage().(*container.DeleteRequest_Body)) + r.RequestHeaders.ToMessage(m) + } + + return m +} + +func (r *DeleteRequest) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*container.DeleteRequest) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + r.body = nil + } else { + if r.body == nil { + r.body = new(DeleteRequestBody) + } + + err = r.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return r.RequestHeaders.FromMessage(v) +} + +func (r *DeleteResponseBody) ToGRPCMessage() grpc.Message { + var m *container.DeleteResponse_Body + + if r != nil { + m = new(container.DeleteResponse_Body) + } + + return m +} + +func (r *DeleteResponseBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*container.DeleteResponse_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + return nil +} + +func (r *DeleteResponse) ToGRPCMessage() grpc.Message { + var m *container.DeleteResponse + + if r != nil { + m = new(container.DeleteResponse) + + m.SetBody(r.body.ToGRPCMessage().(*container.DeleteResponse_Body)) + r.ResponseHeaders.ToMessage(m) + } + + return m +} + +func (r *DeleteResponse) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*container.DeleteResponse) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + r.body = nil + } else { + if r.body == nil { + r.body = new(DeleteResponseBody) + } + + err = r.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return r.ResponseHeaders.FromMessage(v) +} + +func (r *ListRequestBody) ToGRPCMessage() grpc.Message { + var m *container.ListRequest_Body + + if r != nil { + m = new(container.ListRequest_Body) + + m.SetOwnerId(r.ownerID.ToGRPCMessage().(*refsGRPC.OwnerID)) + } + + return m +} + +func (r *ListRequestBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*container.ListRequest_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + ownerID := v.GetOwnerId() + if ownerID == nil { + r.ownerID = nil + } else { + if r.ownerID == nil { + r.ownerID = new(refs.OwnerID) + } + + err = r.ownerID.FromGRPCMessage(ownerID) + } + + return err +} + +func (r *ListRequest) ToGRPCMessage() grpc.Message { + var m *container.ListRequest + + if r != nil { + m = new(container.ListRequest) + + m.SetBody(r.body.ToGRPCMessage().(*container.ListRequest_Body)) + r.RequestHeaders.ToMessage(m) + } + + return m +} + +func (r *ListRequest) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*container.ListRequest) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + r.body = nil + } else { + if r.body == nil { + r.body = new(ListRequestBody) + } + + err = r.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return r.RequestHeaders.FromMessage(v) +} + +func (r *ListResponseBody) ToGRPCMessage() grpc.Message { + var m *container.ListResponse_Body + + if r != nil { + m = new(container.ListResponse_Body) + + m.SetContainerIds(refs.ContainerIDsToGRPCMessage(r.cidList)) + } + + return m +} + +func (r *ListResponseBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*container.ListResponse_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + r.cidList, err = refs.ContainerIDsFromGRPCMessage(v.GetContainerIds()) + + return err +} + +func (r *ListResponse) ToGRPCMessage() grpc.Message { + var m *container.ListResponse + + if r != nil { + m = new(container.ListResponse) + + m.SetBody(r.body.ToGRPCMessage().(*container.ListResponse_Body)) + r.ResponseHeaders.ToMessage(m) + } + + return m +} + +func (r *ListResponse) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*container.ListResponse) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + r.body = nil + } else { + if r.body == nil { + r.body = new(ListResponseBody) + } + + err = r.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return r.ResponseHeaders.FromMessage(v) +} + +func (r *SetExtendedACLRequestBody) ToGRPCMessage() grpc.Message { + var m *container.SetExtendedACLRequest_Body + + if r != nil { + m = new(container.SetExtendedACLRequest_Body) + + m.SetEacl(r.eacl.ToGRPCMessage().(*aclGRPC.EACLTable)) + m.SetSignature(toSignatureRFC6979(r.sig)) + } + + return m +} + +func (r *SetExtendedACLRequestBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*container.SetExtendedACLRequest_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + eacl := v.GetEacl() + if eacl == nil { + r.eacl = nil + } else { + if r.eacl == nil { + r.eacl = new(acl.Table) + } + + err = r.eacl.FromGRPCMessage(eacl) + if err != nil { + return err + } + } + + sig := v.GetSignature() + if sig == nil { + r.sig = nil + } else { + if r.sig == nil { + r.sig = new(refs.Signature) + } + + r.sig.SetKey(sig.GetKey()) + r.sig.SetSign(sig.GetSign()) + } + + return err +} + +func (r *SetExtendedACLRequest) ToGRPCMessage() grpc.Message { + var m *container.SetExtendedACLRequest + + if r != nil { + m = new(container.SetExtendedACLRequest) + + m.SetBody(r.body.ToGRPCMessage().(*container.SetExtendedACLRequest_Body)) + r.RequestHeaders.ToMessage(m) + } + + return m +} + +func (r *SetExtendedACLRequest) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*container.SetExtendedACLRequest) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + r.body = nil + } else { + if r.body == nil { + r.body = new(SetExtendedACLRequestBody) + } + + err = r.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return r.RequestHeaders.FromMessage(v) +} + +func (r *SetExtendedACLResponseBody) ToGRPCMessage() grpc.Message { + var m *container.SetExtendedACLResponse_Body + + if r != nil { + m = new(container.SetExtendedACLResponse_Body) + } + + return m +} + +func (r *SetExtendedACLResponseBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*container.SetExtendedACLResponse_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + return nil +} + +func (r *SetExtendedACLResponse) ToGRPCMessage() grpc.Message { + var m *container.SetExtendedACLResponse + + if r != nil { + m = new(container.SetExtendedACLResponse) + + m.SetBody(r.body.ToGRPCMessage().(*container.SetExtendedACLResponse_Body)) + r.ResponseHeaders.ToMessage(m) + } + + return m +} + +func (r *SetExtendedACLResponse) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*container.SetExtendedACLResponse) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + r.body = nil + } else { + if r.body == nil { + r.body = new(SetExtendedACLResponseBody) + } + + err = r.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return r.ResponseHeaders.FromMessage(v) +} + +func (r *GetExtendedACLRequestBody) ToGRPCMessage() grpc.Message { + var m *container.GetExtendedACLRequest_Body + + if r != nil { + m = new(container.GetExtendedACLRequest_Body) + + m.SetContainerId(r.cid.ToGRPCMessage().(*refsGRPC.ContainerID)) + } + + return m +} + +func (r *GetExtendedACLRequestBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*container.GetExtendedACLRequest_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + cid := v.GetContainerId() + if cid == nil { + r.cid = nil + } else { + if r.cid == nil { + r.cid = new(refs.ContainerID) + } + + err = r.cid.FromGRPCMessage(cid) + } + + return err +} + +func (r *GetExtendedACLRequest) ToGRPCMessage() grpc.Message { + var m *container.GetExtendedACLRequest + + if r != nil { + m = new(container.GetExtendedACLRequest) + + m.SetBody(r.body.ToGRPCMessage().(*container.GetExtendedACLRequest_Body)) + r.RequestHeaders.ToMessage(m) + } + + return m +} + +func (r *GetExtendedACLRequest) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*container.GetExtendedACLRequest) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + r.body = nil + } else { + if r.body == nil { + r.body = new(GetExtendedACLRequestBody) + } + + err = r.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return r.RequestHeaders.FromMessage(v) +} + +func (r *GetExtendedACLResponseBody) ToGRPCMessage() grpc.Message { + var m *container.GetExtendedACLResponse_Body + + if r != nil { + m = new(container.GetExtendedACLResponse_Body) + + m.SetEacl(r.eacl.ToGRPCMessage().(*aclGRPC.EACLTable)) + m.SetSignature(toSignatureRFC6979(r.sig)) + m.SetSessionToken(r.token.ToGRPCMessage().(*sessionGRPC.SessionToken)) + } + + return m +} + +func (r *GetExtendedACLResponseBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*container.GetExtendedACLResponse_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + eacl := v.GetEacl() + if eacl == nil { + r.eacl = nil + } else { + if r.eacl == nil { + r.eacl = new(acl.Table) + } + + err = r.eacl.FromGRPCMessage(eacl) + if err != nil { + return err + } + } + + sig := v.GetSignature() + if sig == nil { + r.sig = nil + } else { + if r.sig == nil { + r.sig = new(refs.Signature) + } + + r.sig.SetKey(sig.GetKey()) + r.sig.SetSign(sig.GetSign()) + } + + token := v.GetSessionToken() + if token == nil { + r.token = nil + } else { + if r.token == nil { + r.token = new(session.Token) + } + + err = r.token.FromGRPCMessage(token) + } + + return err +} + +func (r *GetExtendedACLResponse) ToGRPCMessage() grpc.Message { + var m *container.GetExtendedACLResponse + + if r != nil { + m = new(container.GetExtendedACLResponse) + + m.SetBody(r.body.ToGRPCMessage().(*container.GetExtendedACLResponse_Body)) + r.ResponseHeaders.ToMessage(m) + } + + return m +} + +func (r *GetExtendedACLResponse) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*container.GetExtendedACLResponse) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + r.body = nil + } else { + if r.body == nil { + r.body = new(GetExtendedACLResponseBody) + } + + err = r.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return r.ResponseHeaders.FromMessage(v) +} + +func (a *UsedSpaceAnnouncement) ToGRPCMessage() grpc.Message { + var m *container.AnnounceUsedSpaceRequest_Body_Announcement + + if a != nil { + m = new(container.AnnounceUsedSpaceRequest_Body_Announcement) + + m.SetContainerId(a.cid.ToGRPCMessage().(*refsGRPC.ContainerID)) + m.SetEpoch(a.epoch) + m.SetUsedSpace(a.usedSpace) + } + + return m +} + +func (a *UsedSpaceAnnouncement) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*container.AnnounceUsedSpaceRequest_Body_Announcement) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + cid := v.GetContainerId() + if cid == nil { + a.cid = nil + } else { + if a.cid == nil { + a.cid = new(refs.ContainerID) + } + + err = a.cid.FromGRPCMessage(cid) + if err != nil { + return err + } + } + + a.epoch = v.GetEpoch() + a.usedSpace = v.GetUsedSpace() + + return nil +} + +func UsedSpaceAnnouncementsToGRPCMessage( + ids []UsedSpaceAnnouncement, +) (res []*container.AnnounceUsedSpaceRequest_Body_Announcement) { + if ids != nil { + res = make([]*container.AnnounceUsedSpaceRequest_Body_Announcement, 0, len(ids)) + + for i := range ids { + res = append(res, ids[i].ToGRPCMessage().(*container.AnnounceUsedSpaceRequest_Body_Announcement)) + } + } + + return +} + +func UsedSpaceAnnouncementssFromGRPCMessage( + asV2 []*container.AnnounceUsedSpaceRequest_Body_Announcement, +) (res []UsedSpaceAnnouncement, err error) { + if asV2 != nil { + res = make([]UsedSpaceAnnouncement, len(asV2)) + + for i := range asV2 { + if asV2[i] != nil { + err = res[i].FromGRPCMessage(asV2[i]) + if err != nil { + return + } + } + } + } + + return +} + +func (r *AnnounceUsedSpaceRequestBody) ToGRPCMessage() grpc.Message { + var m *container.AnnounceUsedSpaceRequest_Body + + if r != nil { + m = new(container.AnnounceUsedSpaceRequest_Body) + + m.SetAnnouncements(UsedSpaceAnnouncementsToGRPCMessage(r.announcements)) + } + + return m +} + +func (r *AnnounceUsedSpaceRequestBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*container.AnnounceUsedSpaceRequest_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + r.announcements, err = UsedSpaceAnnouncementssFromGRPCMessage(v.GetAnnouncements()) + + return err +} + +func (r *AnnounceUsedSpaceRequest) ToGRPCMessage() grpc.Message { + var m *container.AnnounceUsedSpaceRequest + + if r != nil { + m = new(container.AnnounceUsedSpaceRequest) + + m.SetBody(r.body.ToGRPCMessage().(*container.AnnounceUsedSpaceRequest_Body)) + r.RequestHeaders.ToMessage(m) + } + + return m +} + +func (r *AnnounceUsedSpaceRequest) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*container.AnnounceUsedSpaceRequest) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + r.body = nil + } else { + if r.body == nil { + r.body = new(AnnounceUsedSpaceRequestBody) + } + + err = r.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return r.RequestHeaders.FromMessage(v) +} + +func (r *AnnounceUsedSpaceResponseBody) ToGRPCMessage() grpc.Message { + var m *container.AnnounceUsedSpaceResponse_Body + + if r != nil { + m = new(container.AnnounceUsedSpaceResponse_Body) + } + + return m +} + +func (r *AnnounceUsedSpaceResponseBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*container.AnnounceUsedSpaceResponse_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + return nil +} + +func (r *AnnounceUsedSpaceResponse) ToGRPCMessage() grpc.Message { + var m *container.AnnounceUsedSpaceResponse + + if r != nil { + m = new(container.AnnounceUsedSpaceResponse) + + m.SetBody(r.body.ToGRPCMessage().(*container.AnnounceUsedSpaceResponse_Body)) + r.ResponseHeaders.ToMessage(m) + } + + return m +} + +func (r *AnnounceUsedSpaceResponse) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*container.AnnounceUsedSpaceResponse) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + r.body = nil + } else { + if r.body == nil { + r.body = new(AnnounceUsedSpaceResponseBody) + } + + err = r.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return r.ResponseHeaders.FromMessage(v) +} diff --git a/pkg/api/container/grpc/service.go b/pkg/api/container/grpc/service.go new file mode 100644 index 000000000..9f50dd035 --- /dev/null +++ b/pkg/api/container/grpc/service.go @@ -0,0 +1,324 @@ +package container + +import ( + acl "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/acl/grpc" + refs "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs/grpc" + session "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session/grpc" +) + +// SetContainer sets container of the request. +func (m *PutRequest_Body) SetContainer(v *Container) { + m.Container = v +} + +// SetSignature sets signature of the container structure. +func (m *PutRequest_Body) SetSignature(v *refs.SignatureRFC6979) { + m.Signature = v +} + +// SetBody sets body of the request. +func (m *PutRequest) SetBody(v *PutRequest_Body) { + m.Body = v +} + +// SetMetaHeader sets meta header of the request. +func (m *PutRequest) SetMetaHeader(v *session.RequestMetaHeader) { + m.MetaHeader = v +} + +// SetVerifyHeader sets verification header of the request. +func (m *PutRequest) SetVerifyHeader(v *session.RequestVerificationHeader) { + m.VerifyHeader = v +} + +// SetContainerId sets identifier of the container. +func (m *PutResponse_Body) SetContainerId(v *refs.ContainerID) { + m.ContainerId = v +} + +// SetBody sets body of the response. +func (m *PutResponse) SetBody(v *PutResponse_Body) { + m.Body = v +} + +// SetMetaHeader sets meta header of the response. +func (m *PutResponse) SetMetaHeader(v *session.ResponseMetaHeader) { + m.MetaHeader = v +} + +// SetVerifyHeader sets verification header of the response. +func (m *PutResponse) SetVerifyHeader(v *session.ResponseVerificationHeader) { + m.VerifyHeader = v +} + +// SetContainerId sets identifier of the container. +func (m *DeleteRequest_Body) SetContainerId(v *refs.ContainerID) { + m.ContainerId = v +} + +// SetSignature sets signature of the container identifier. +func (m *DeleteRequest_Body) SetSignature(v *refs.SignatureRFC6979) { + m.Signature = v +} + +// SetBody sets body of the request. +func (m *DeleteRequest) SetBody(v *DeleteRequest_Body) { + m.Body = v +} + +// SetMetaHeader sets meta header of the request. +func (m *DeleteRequest) SetMetaHeader(v *session.RequestMetaHeader) { + m.MetaHeader = v +} + +// SetVerifyHeader sets verification header of the request. +func (m *DeleteRequest) SetVerifyHeader(v *session.RequestVerificationHeader) { + m.VerifyHeader = v +} + +// SetBody sets body of the response. +func (m *DeleteResponse) SetBody(v *DeleteResponse_Body) { + m.Body = v +} + +// SetMetaHeader sets meta header of the response. +func (m *DeleteResponse) SetMetaHeader(v *session.ResponseMetaHeader) { + m.MetaHeader = v +} + +// SetVerifyHeader sets verification header of the response. +func (m *DeleteResponse) SetVerifyHeader(v *session.ResponseVerificationHeader) { + m.VerifyHeader = v +} + +// SetContainerId sets identifier of the container. +func (m *GetRequest_Body) SetContainerId(v *refs.ContainerID) { + m.ContainerId = v +} + +// SetBody sets body of the request. +func (m *GetRequest) SetBody(v *GetRequest_Body) { + m.Body = v +} + +// SetMetaHeader sets meta header of the request. +func (m *GetRequest) SetMetaHeader(v *session.RequestMetaHeader) { + m.MetaHeader = v +} + +// SetVerifyHeader sets verification header of the request. +func (m *GetRequest) SetVerifyHeader(v *session.RequestVerificationHeader) { + m.VerifyHeader = v +} + +// SetContainer sets the container structure. +func (m *GetResponse_Body) SetContainer(v *Container) { + m.Container = v +} + +// SetSessionToken sets token of the session within which requested +// container was created. +func (m *GetResponse_Body) SetSessionToken(v *session.SessionToken) { + m.SessionToken = v +} + +// SetSignature sets signature of the container structure. +func (m *GetResponse_Body) SetSignature(v *refs.SignatureRFC6979) { + m.Signature = v +} + +// SetBody sets body of the response. +func (m *GetResponse) SetBody(v *GetResponse_Body) { + m.Body = v +} + +// SetMetaHeader sets meta header of the response. +func (m *GetResponse) SetMetaHeader(v *session.ResponseMetaHeader) { + m.MetaHeader = v +} + +// SetVerifyHeader sets verification header of the response. +func (m *GetResponse) SetVerifyHeader(v *session.ResponseVerificationHeader) { + m.VerifyHeader = v +} + +// SetOwnerId sets identifier of the container owner. +func (m *ListRequest_Body) SetOwnerId(v *refs.OwnerID) { + m.OwnerId = v +} + +// SetBody sets body of the request. +func (m *ListRequest) SetBody(v *ListRequest_Body) { + m.Body = v +} + +// SetMetaHeader sets meta header of the request. +func (m *ListRequest) SetMetaHeader(v *session.RequestMetaHeader) { + m.MetaHeader = v +} + +// SetVerifyHeader sets verification header of the request. +func (m *ListRequest) SetVerifyHeader(v *session.RequestVerificationHeader) { + m.VerifyHeader = v +} + +// SetContainerIds sets list of the container identifiers. +func (m *ListResponse_Body) SetContainerIds(v []*refs.ContainerID) { + m.ContainerIds = v +} + +// SetBody sets body of the response. +func (m *ListResponse) SetBody(v *ListResponse_Body) { + m.Body = v +} + +// SetMetaHeader sets meta header of the response. +func (m *ListResponse) SetMetaHeader(v *session.ResponseMetaHeader) { + m.MetaHeader = v +} + +// SetVerifyHeader sets verification header of the response. +func (m *ListResponse) SetVerifyHeader(v *session.ResponseVerificationHeader) { + m.VerifyHeader = v +} + +// SetEacl sets eACL table structure. +func (m *SetExtendedACLRequest_Body) SetEacl(v *acl.EACLTable) { + m.Eacl = v +} + +// SetSignature sets signature of the eACL table structure. +func (m *SetExtendedACLRequest_Body) SetSignature(v *refs.SignatureRFC6979) { + m.Signature = v +} + +// SetBody sets body of the request. +func (m *SetExtendedACLRequest) SetBody(v *SetExtendedACLRequest_Body) { + m.Body = v +} + +// SetMetaHeader sets meta header of the request. +func (m *SetExtendedACLRequest) SetMetaHeader(v *session.RequestMetaHeader) { + m.MetaHeader = v +} + +// SetVerifyHeader sets verification header of the request. +func (m *SetExtendedACLRequest) SetVerifyHeader(v *session.RequestVerificationHeader) { + m.VerifyHeader = v +} + +// SetBody sets body of the response. +func (m *SetExtendedACLResponse) SetBody(v *SetExtendedACLResponse_Body) { + m.Body = v +} + +// SetMetaHeader sets meta header of the response. +func (m *SetExtendedACLResponse) SetMetaHeader(v *session.ResponseMetaHeader) { + m.MetaHeader = v +} + +// SetVerifyHeader sets verification header of the response. +func (m *SetExtendedACLResponse) SetVerifyHeader(v *session.ResponseVerificationHeader) { + m.VerifyHeader = v +} + +// SetContainerId sets identifier of the container. +func (m *GetExtendedACLRequest_Body) SetContainerId(v *refs.ContainerID) { + m.ContainerId = v +} + +// SetBody sets body of the request. +func (m *GetExtendedACLRequest) SetBody(v *GetExtendedACLRequest_Body) { + m.Body = v +} + +// SetMetaHeader sets meta header of the request. +func (m *GetExtendedACLRequest) SetMetaHeader(v *session.RequestMetaHeader) { + m.MetaHeader = v +} + +// SetVerifyHeader sets verification header of the request. +func (m *GetExtendedACLRequest) SetVerifyHeader(v *session.RequestVerificationHeader) { + m.VerifyHeader = v +} + +// SetEacl sets eACL table structure. +func (m *GetExtendedACLResponse_Body) SetEacl(v *acl.EACLTable) { + m.Eacl = v +} + +// SetSignature sets signature of the eACL table structure. +func (m *GetExtendedACLResponse_Body) SetSignature(v *refs.SignatureRFC6979) { + m.Signature = v +} + +// SetSessionToken sets token of the session within which requested +// eACl table was set. +func (m *GetExtendedACLResponse_Body) SetSessionToken(v *session.SessionToken) { + m.SessionToken = v +} + +// SetBody sets body of the response. +func (m *GetExtendedACLResponse) SetBody(v *GetExtendedACLResponse_Body) { + m.Body = v +} + +// SetMetaHeader sets meta header of the response. +func (m *GetExtendedACLResponse) SetMetaHeader(v *session.ResponseMetaHeader) { + m.MetaHeader = v +} + +// SetVerifyHeader sets verification header of the response. +func (m *GetExtendedACLResponse) SetVerifyHeader(v *session.ResponseVerificationHeader) { + m.VerifyHeader = v +} + +// SetEpoch sets epoch of the size estimation. +func (m *AnnounceUsedSpaceRequest_Body_Announcement) SetEpoch(v uint64) { + m.Epoch = v +} + +// SetContainerId sets identifier of the container. +func (m *AnnounceUsedSpaceRequest_Body_Announcement) SetContainerId(v *refs.ContainerID) { + m.ContainerId = v +} + +// SetUsedSpace sets used space value of the container. +func (m *AnnounceUsedSpaceRequest_Body_Announcement) SetUsedSpace(v uint64) { + m.UsedSpace = v +} + +// SetAnnouncements sets list of announcement for shared containers between nodes. +func (m *AnnounceUsedSpaceRequest_Body) SetAnnouncements(v []*AnnounceUsedSpaceRequest_Body_Announcement) { + m.Announcements = v +} + +// SetBody sets body of the request. +func (m *AnnounceUsedSpaceRequest) SetBody(v *AnnounceUsedSpaceRequest_Body) { + m.Body = v +} + +// SetMetaHeader sets meta header of the request. +func (m *AnnounceUsedSpaceRequest) SetMetaHeader(v *session.RequestMetaHeader) { + m.MetaHeader = v +} + +// SetVerifyHeader sets verification header of the request. +func (m *AnnounceUsedSpaceRequest) SetVerifyHeader(v *session.RequestVerificationHeader) { + m.VerifyHeader = v +} + +// SetBody sets body of the response. +func (m *AnnounceUsedSpaceResponse) SetBody(v *AnnounceUsedSpaceResponse_Body) { + m.Body = v +} + +// SetMetaHeader sets meta header of the response. +func (m *AnnounceUsedSpaceResponse) SetMetaHeader(v *session.ResponseMetaHeader) { + m.MetaHeader = v +} + +// SetVerifyHeader sets verification header of the response. +func (m *AnnounceUsedSpaceResponse) SetVerifyHeader(v *session.ResponseVerificationHeader) { + m.VerifyHeader = v +} diff --git a/pkg/api/container/grpc/service.pb.go b/pkg/api/container/grpc/service.pb.go new file mode 100644 index 000000000..e1414d8f5 --- /dev/null +++ b/pkg/api/container/grpc/service.pb.go @@ -0,0 +1,2685 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.33.0 +// protoc v4.25.3 +// source: container/grpc/service.proto + +package container + +import ( + grpc2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/acl/grpc" + grpc1 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs/grpc" + grpc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session/grpc" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// New NeoFS Container creation request +type PutRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Body of container put request message. + Body *PutRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Carries request meta information. Header data is used only to regulate + // message transport and does not affect request execution. + MetaHeader *grpc.RequestMetaHeader `protobuf:"bytes,2,opt,name=meta_header,json=metaHeader,proto3" json:"meta_header,omitempty"` + // Carries request verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + VerifyHeader *grpc.RequestVerificationHeader `protobuf:"bytes,3,opt,name=verify_header,json=verifyHeader,proto3" json:"verify_header,omitempty"` +} + +func (x *PutRequest) Reset() { + *x = PutRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_container_grpc_service_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PutRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PutRequest) ProtoMessage() {} + +func (x *PutRequest) ProtoReflect() protoreflect.Message { + mi := &file_container_grpc_service_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PutRequest.ProtoReflect.Descriptor instead. +func (*PutRequest) Descriptor() ([]byte, []int) { + return file_container_grpc_service_proto_rawDescGZIP(), []int{0} +} + +func (x *PutRequest) GetBody() *PutRequest_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *PutRequest) GetMetaHeader() *grpc.RequestMetaHeader { + if x != nil { + return x.MetaHeader + } + return nil +} + +func (x *PutRequest) GetVerifyHeader() *grpc.RequestVerificationHeader { + if x != nil { + return x.VerifyHeader + } + return nil +} + +// New NeoFS Container creation response +type PutResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Body of container put response message. + Body *PutResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Carries response meta information. Header data is used only to regulate + // message transport and does not affect request execution. + MetaHeader *grpc.ResponseMetaHeader `protobuf:"bytes,2,opt,name=meta_header,json=metaHeader,proto3" json:"meta_header,omitempty"` + // Carries response verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + VerifyHeader *grpc.ResponseVerificationHeader `protobuf:"bytes,3,opt,name=verify_header,json=verifyHeader,proto3" json:"verify_header,omitempty"` +} + +func (x *PutResponse) Reset() { + *x = PutResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_container_grpc_service_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PutResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PutResponse) ProtoMessage() {} + +func (x *PutResponse) ProtoReflect() protoreflect.Message { + mi := &file_container_grpc_service_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PutResponse.ProtoReflect.Descriptor instead. +func (*PutResponse) Descriptor() ([]byte, []int) { + return file_container_grpc_service_proto_rawDescGZIP(), []int{1} +} + +func (x *PutResponse) GetBody() *PutResponse_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *PutResponse) GetMetaHeader() *grpc.ResponseMetaHeader { + if x != nil { + return x.MetaHeader + } + return nil +} + +func (x *PutResponse) GetVerifyHeader() *grpc.ResponseVerificationHeader { + if x != nil { + return x.VerifyHeader + } + return nil +} + +// Container removal request +type DeleteRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Body of container delete request message. + Body *DeleteRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Carries request meta information. Header data is used only to regulate + // message transport and does not affect request execution. + MetaHeader *grpc.RequestMetaHeader `protobuf:"bytes,2,opt,name=meta_header,json=metaHeader,proto3" json:"meta_header,omitempty"` + // Carries request verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + VerifyHeader *grpc.RequestVerificationHeader `protobuf:"bytes,3,opt,name=verify_header,json=verifyHeader,proto3" json:"verify_header,omitempty"` +} + +func (x *DeleteRequest) Reset() { + *x = DeleteRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_container_grpc_service_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DeleteRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteRequest) ProtoMessage() {} + +func (x *DeleteRequest) ProtoReflect() protoreflect.Message { + mi := &file_container_grpc_service_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DeleteRequest.ProtoReflect.Descriptor instead. +func (*DeleteRequest) Descriptor() ([]byte, []int) { + return file_container_grpc_service_proto_rawDescGZIP(), []int{2} +} + +func (x *DeleteRequest) GetBody() *DeleteRequest_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *DeleteRequest) GetMetaHeader() *grpc.RequestMetaHeader { + if x != nil { + return x.MetaHeader + } + return nil +} + +func (x *DeleteRequest) GetVerifyHeader() *grpc.RequestVerificationHeader { + if x != nil { + return x.VerifyHeader + } + return nil +} + +// `DeleteResponse` has an empty body because delete operation is asynchronous +// and done via consensus in Inner Ring nodes. +type DeleteResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Body of container delete response message. + Body *DeleteResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Carries response meta information. Header data is used only to regulate + // message transport and does not affect request execution. + MetaHeader *grpc.ResponseMetaHeader `protobuf:"bytes,2,opt,name=meta_header,json=metaHeader,proto3" json:"meta_header,omitempty"` + // Carries response verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + VerifyHeader *grpc.ResponseVerificationHeader `protobuf:"bytes,3,opt,name=verify_header,json=verifyHeader,proto3" json:"verify_header,omitempty"` +} + +func (x *DeleteResponse) Reset() { + *x = DeleteResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_container_grpc_service_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DeleteResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteResponse) ProtoMessage() {} + +func (x *DeleteResponse) ProtoReflect() protoreflect.Message { + mi := &file_container_grpc_service_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DeleteResponse.ProtoReflect.Descriptor instead. +func (*DeleteResponse) Descriptor() ([]byte, []int) { + return file_container_grpc_service_proto_rawDescGZIP(), []int{3} +} + +func (x *DeleteResponse) GetBody() *DeleteResponse_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *DeleteResponse) GetMetaHeader() *grpc.ResponseMetaHeader { + if x != nil { + return x.MetaHeader + } + return nil +} + +func (x *DeleteResponse) GetVerifyHeader() *grpc.ResponseVerificationHeader { + if x != nil { + return x.VerifyHeader + } + return nil +} + +// Get container structure +type GetRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Body of container get request message. + Body *GetRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Carries request meta information. Header data is used only to regulate + // message transport and does not affect request execution. + MetaHeader *grpc.RequestMetaHeader `protobuf:"bytes,2,opt,name=meta_header,json=metaHeader,proto3" json:"meta_header,omitempty"` + // Carries request verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + VerifyHeader *grpc.RequestVerificationHeader `protobuf:"bytes,3,opt,name=verify_header,json=verifyHeader,proto3" json:"verify_header,omitempty"` +} + +func (x *GetRequest) Reset() { + *x = GetRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_container_grpc_service_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetRequest) ProtoMessage() {} + +func (x *GetRequest) ProtoReflect() protoreflect.Message { + mi := &file_container_grpc_service_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetRequest.ProtoReflect.Descriptor instead. +func (*GetRequest) Descriptor() ([]byte, []int) { + return file_container_grpc_service_proto_rawDescGZIP(), []int{4} +} + +func (x *GetRequest) GetBody() *GetRequest_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *GetRequest) GetMetaHeader() *grpc.RequestMetaHeader { + if x != nil { + return x.MetaHeader + } + return nil +} + +func (x *GetRequest) GetVerifyHeader() *grpc.RequestVerificationHeader { + if x != nil { + return x.VerifyHeader + } + return nil +} + +// Get container structure +type GetResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Body of container get response message. + Body *GetResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Carries response meta information. Header data is used only to regulate + // message transport and does not affect request execution. + MetaHeader *grpc.ResponseMetaHeader `protobuf:"bytes,2,opt,name=meta_header,json=metaHeader,proto3" json:"meta_header,omitempty"` + // Carries response verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + VerifyHeader *grpc.ResponseVerificationHeader `protobuf:"bytes,3,opt,name=verify_header,json=verifyHeader,proto3" json:"verify_header,omitempty"` +} + +func (x *GetResponse) Reset() { + *x = GetResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_container_grpc_service_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetResponse) ProtoMessage() {} + +func (x *GetResponse) ProtoReflect() protoreflect.Message { + mi := &file_container_grpc_service_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetResponse.ProtoReflect.Descriptor instead. +func (*GetResponse) Descriptor() ([]byte, []int) { + return file_container_grpc_service_proto_rawDescGZIP(), []int{5} +} + +func (x *GetResponse) GetBody() *GetResponse_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *GetResponse) GetMetaHeader() *grpc.ResponseMetaHeader { + if x != nil { + return x.MetaHeader + } + return nil +} + +func (x *GetResponse) GetVerifyHeader() *grpc.ResponseVerificationHeader { + if x != nil { + return x.VerifyHeader + } + return nil +} + +// List containers +type ListRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Body of list containers request message + Body *ListRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Carries request meta information. Header data is used only to regulate + // message transport and does not affect request execution. + MetaHeader *grpc.RequestMetaHeader `protobuf:"bytes,2,opt,name=meta_header,json=metaHeader,proto3" json:"meta_header,omitempty"` + // Carries request verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + VerifyHeader *grpc.RequestVerificationHeader `protobuf:"bytes,3,opt,name=verify_header,json=verifyHeader,proto3" json:"verify_header,omitempty"` +} + +func (x *ListRequest) Reset() { + *x = ListRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_container_grpc_service_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListRequest) ProtoMessage() {} + +func (x *ListRequest) ProtoReflect() protoreflect.Message { + mi := &file_container_grpc_service_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListRequest.ProtoReflect.Descriptor instead. +func (*ListRequest) Descriptor() ([]byte, []int) { + return file_container_grpc_service_proto_rawDescGZIP(), []int{6} +} + +func (x *ListRequest) GetBody() *ListRequest_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *ListRequest) GetMetaHeader() *grpc.RequestMetaHeader { + if x != nil { + return x.MetaHeader + } + return nil +} + +func (x *ListRequest) GetVerifyHeader() *grpc.RequestVerificationHeader { + if x != nil { + return x.VerifyHeader + } + return nil +} + +// List containers +type ListResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Body of list containers response message. + Body *ListResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Carries response meta information. Header data is used only to regulate + // message transport and does not affect request execution. + MetaHeader *grpc.ResponseMetaHeader `protobuf:"bytes,2,opt,name=meta_header,json=metaHeader,proto3" json:"meta_header,omitempty"` + // Carries response verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + VerifyHeader *grpc.ResponseVerificationHeader `protobuf:"bytes,3,opt,name=verify_header,json=verifyHeader,proto3" json:"verify_header,omitempty"` +} + +func (x *ListResponse) Reset() { + *x = ListResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_container_grpc_service_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListResponse) ProtoMessage() {} + +func (x *ListResponse) ProtoReflect() protoreflect.Message { + mi := &file_container_grpc_service_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListResponse.ProtoReflect.Descriptor instead. +func (*ListResponse) Descriptor() ([]byte, []int) { + return file_container_grpc_service_proto_rawDescGZIP(), []int{7} +} + +func (x *ListResponse) GetBody() *ListResponse_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *ListResponse) GetMetaHeader() *grpc.ResponseMetaHeader { + if x != nil { + return x.MetaHeader + } + return nil +} + +func (x *ListResponse) GetVerifyHeader() *grpc.ResponseVerificationHeader { + if x != nil { + return x.VerifyHeader + } + return nil +} + +// Set Extended ACL +type SetExtendedACLRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Body of set extended acl request message. + Body *SetExtendedACLRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Carries request meta information. Header data is used only to regulate + // message transport and does not affect request execution. + MetaHeader *grpc.RequestMetaHeader `protobuf:"bytes,2,opt,name=meta_header,json=metaHeader,proto3" json:"meta_header,omitempty"` + // Carries request verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + VerifyHeader *grpc.RequestVerificationHeader `protobuf:"bytes,3,opt,name=verify_header,json=verifyHeader,proto3" json:"verify_header,omitempty"` +} + +func (x *SetExtendedACLRequest) Reset() { + *x = SetExtendedACLRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_container_grpc_service_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SetExtendedACLRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SetExtendedACLRequest) ProtoMessage() {} + +func (x *SetExtendedACLRequest) ProtoReflect() protoreflect.Message { + mi := &file_container_grpc_service_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SetExtendedACLRequest.ProtoReflect.Descriptor instead. +func (*SetExtendedACLRequest) Descriptor() ([]byte, []int) { + return file_container_grpc_service_proto_rawDescGZIP(), []int{8} +} + +func (x *SetExtendedACLRequest) GetBody() *SetExtendedACLRequest_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *SetExtendedACLRequest) GetMetaHeader() *grpc.RequestMetaHeader { + if x != nil { + return x.MetaHeader + } + return nil +} + +func (x *SetExtendedACLRequest) GetVerifyHeader() *grpc.RequestVerificationHeader { + if x != nil { + return x.VerifyHeader + } + return nil +} + +// Set Extended ACL +type SetExtendedACLResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Body of set extended acl response message. + Body *SetExtendedACLResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Carries response meta information. Header data is used only to regulate + // message transport and does not affect request execution. + MetaHeader *grpc.ResponseMetaHeader `protobuf:"bytes,2,opt,name=meta_header,json=metaHeader,proto3" json:"meta_header,omitempty"` + // Carries response verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + VerifyHeader *grpc.ResponseVerificationHeader `protobuf:"bytes,3,opt,name=verify_header,json=verifyHeader,proto3" json:"verify_header,omitempty"` +} + +func (x *SetExtendedACLResponse) Reset() { + *x = SetExtendedACLResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_container_grpc_service_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SetExtendedACLResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SetExtendedACLResponse) ProtoMessage() {} + +func (x *SetExtendedACLResponse) ProtoReflect() protoreflect.Message { + mi := &file_container_grpc_service_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SetExtendedACLResponse.ProtoReflect.Descriptor instead. +func (*SetExtendedACLResponse) Descriptor() ([]byte, []int) { + return file_container_grpc_service_proto_rawDescGZIP(), []int{9} +} + +func (x *SetExtendedACLResponse) GetBody() *SetExtendedACLResponse_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *SetExtendedACLResponse) GetMetaHeader() *grpc.ResponseMetaHeader { + if x != nil { + return x.MetaHeader + } + return nil +} + +func (x *SetExtendedACLResponse) GetVerifyHeader() *grpc.ResponseVerificationHeader { + if x != nil { + return x.VerifyHeader + } + return nil +} + +// Get Extended ACL +type GetExtendedACLRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Body of get extended acl request message. + Body *GetExtendedACLRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Carries request meta information. Header data is used only to regulate + // message transport and does not affect request execution. + MetaHeader *grpc.RequestMetaHeader `protobuf:"bytes,2,opt,name=meta_header,json=metaHeader,proto3" json:"meta_header,omitempty"` + // Carries request verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + VerifyHeader *grpc.RequestVerificationHeader `protobuf:"bytes,3,opt,name=verify_header,json=verifyHeader,proto3" json:"verify_header,omitempty"` +} + +func (x *GetExtendedACLRequest) Reset() { + *x = GetExtendedACLRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_container_grpc_service_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetExtendedACLRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetExtendedACLRequest) ProtoMessage() {} + +func (x *GetExtendedACLRequest) ProtoReflect() protoreflect.Message { + mi := &file_container_grpc_service_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetExtendedACLRequest.ProtoReflect.Descriptor instead. +func (*GetExtendedACLRequest) Descriptor() ([]byte, []int) { + return file_container_grpc_service_proto_rawDescGZIP(), []int{10} +} + +func (x *GetExtendedACLRequest) GetBody() *GetExtendedACLRequest_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *GetExtendedACLRequest) GetMetaHeader() *grpc.RequestMetaHeader { + if x != nil { + return x.MetaHeader + } + return nil +} + +func (x *GetExtendedACLRequest) GetVerifyHeader() *grpc.RequestVerificationHeader { + if x != nil { + return x.VerifyHeader + } + return nil +} + +// Get Extended ACL +type GetExtendedACLResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Body of get extended acl response message. + Body *GetExtendedACLResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Carries response meta information. Header data is used only to regulate + // message transport and does not affect request execution. + MetaHeader *grpc.ResponseMetaHeader `protobuf:"bytes,2,opt,name=meta_header,json=metaHeader,proto3" json:"meta_header,omitempty"` + // Carries response verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + VerifyHeader *grpc.ResponseVerificationHeader `protobuf:"bytes,3,opt,name=verify_header,json=verifyHeader,proto3" json:"verify_header,omitempty"` +} + +func (x *GetExtendedACLResponse) Reset() { + *x = GetExtendedACLResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_container_grpc_service_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetExtendedACLResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetExtendedACLResponse) ProtoMessage() {} + +func (x *GetExtendedACLResponse) ProtoReflect() protoreflect.Message { + mi := &file_container_grpc_service_proto_msgTypes[11] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetExtendedACLResponse.ProtoReflect.Descriptor instead. +func (*GetExtendedACLResponse) Descriptor() ([]byte, []int) { + return file_container_grpc_service_proto_rawDescGZIP(), []int{11} +} + +func (x *GetExtendedACLResponse) GetBody() *GetExtendedACLResponse_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *GetExtendedACLResponse) GetMetaHeader() *grpc.ResponseMetaHeader { + if x != nil { + return x.MetaHeader + } + return nil +} + +func (x *GetExtendedACLResponse) GetVerifyHeader() *grpc.ResponseVerificationHeader { + if x != nil { + return x.VerifyHeader + } + return nil +} + +// Announce container used space +type AnnounceUsedSpaceRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Body of announce used space request message. + Body *AnnounceUsedSpaceRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Carries request meta information. Header data is used only to regulate + // message transport and does not affect request execution. + MetaHeader *grpc.RequestMetaHeader `protobuf:"bytes,2,opt,name=meta_header,json=metaHeader,proto3" json:"meta_header,omitempty"` + // Carries request verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + VerifyHeader *grpc.RequestVerificationHeader `protobuf:"bytes,3,opt,name=verify_header,json=verifyHeader,proto3" json:"verify_header,omitempty"` +} + +func (x *AnnounceUsedSpaceRequest) Reset() { + *x = AnnounceUsedSpaceRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_container_grpc_service_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AnnounceUsedSpaceRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AnnounceUsedSpaceRequest) ProtoMessage() {} + +func (x *AnnounceUsedSpaceRequest) ProtoReflect() protoreflect.Message { + mi := &file_container_grpc_service_proto_msgTypes[12] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AnnounceUsedSpaceRequest.ProtoReflect.Descriptor instead. +func (*AnnounceUsedSpaceRequest) Descriptor() ([]byte, []int) { + return file_container_grpc_service_proto_rawDescGZIP(), []int{12} +} + +func (x *AnnounceUsedSpaceRequest) GetBody() *AnnounceUsedSpaceRequest_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *AnnounceUsedSpaceRequest) GetMetaHeader() *grpc.RequestMetaHeader { + if x != nil { + return x.MetaHeader + } + return nil +} + +func (x *AnnounceUsedSpaceRequest) GetVerifyHeader() *grpc.RequestVerificationHeader { + if x != nil { + return x.VerifyHeader + } + return nil +} + +// Announce container used space +type AnnounceUsedSpaceResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Body of announce used space response message. + Body *AnnounceUsedSpaceResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Carries response meta information. Header data is used only to regulate + // message transport and does not affect request execution. + MetaHeader *grpc.ResponseMetaHeader `protobuf:"bytes,2,opt,name=meta_header,json=metaHeader,proto3" json:"meta_header,omitempty"` + // Carries response verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + VerifyHeader *grpc.ResponseVerificationHeader `protobuf:"bytes,3,opt,name=verify_header,json=verifyHeader,proto3" json:"verify_header,omitempty"` +} + +func (x *AnnounceUsedSpaceResponse) Reset() { + *x = AnnounceUsedSpaceResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_container_grpc_service_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AnnounceUsedSpaceResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AnnounceUsedSpaceResponse) ProtoMessage() {} + +func (x *AnnounceUsedSpaceResponse) ProtoReflect() protoreflect.Message { + mi := &file_container_grpc_service_proto_msgTypes[13] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AnnounceUsedSpaceResponse.ProtoReflect.Descriptor instead. +func (*AnnounceUsedSpaceResponse) Descriptor() ([]byte, []int) { + return file_container_grpc_service_proto_rawDescGZIP(), []int{13} +} + +func (x *AnnounceUsedSpaceResponse) GetBody() *AnnounceUsedSpaceResponse_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *AnnounceUsedSpaceResponse) GetMetaHeader() *grpc.ResponseMetaHeader { + if x != nil { + return x.MetaHeader + } + return nil +} + +func (x *AnnounceUsedSpaceResponse) GetVerifyHeader() *grpc.ResponseVerificationHeader { + if x != nil { + return x.VerifyHeader + } + return nil +} + +// Container creation request has container structure's signature as a +// separate field. It's not stored in sidechain, just verified on container +// creation by `Container` smart contract. `ContainerID` is a SHA256 hash of +// the stable-marshalled container strucutre, hence there is no need for +// additional signature checks. +type PutRequest_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Container structure to register in NeoFS + Container *Container `protobuf:"bytes,1,opt,name=container,proto3" json:"container,omitempty"` + // Signature of a stable-marshalled container according to RFC-6979. + Signature *grpc1.SignatureRFC6979 `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` +} + +func (x *PutRequest_Body) Reset() { + *x = PutRequest_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_container_grpc_service_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PutRequest_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PutRequest_Body) ProtoMessage() {} + +func (x *PutRequest_Body) ProtoReflect() protoreflect.Message { + mi := &file_container_grpc_service_proto_msgTypes[14] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PutRequest_Body.ProtoReflect.Descriptor instead. +func (*PutRequest_Body) Descriptor() ([]byte, []int) { + return file_container_grpc_service_proto_rawDescGZIP(), []int{0, 0} +} + +func (x *PutRequest_Body) GetContainer() *Container { + if x != nil { + return x.Container + } + return nil +} + +func (x *PutRequest_Body) GetSignature() *grpc1.SignatureRFC6979 { + if x != nil { + return x.Signature + } + return nil +} + +// Container put response body contains information about the newly registered +// container as seen by `Container` smart contract. `ContainerID` can be +// calculated beforehand from the container structure and compared to the one +// returned here to make sure everything has been done as expected. +type PutResponse_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Unique identifier of the newly created container + ContainerId *grpc1.ContainerID `protobuf:"bytes,1,opt,name=container_id,json=containerId,proto3" json:"container_id,omitempty"` +} + +func (x *PutResponse_Body) Reset() { + *x = PutResponse_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_container_grpc_service_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PutResponse_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PutResponse_Body) ProtoMessage() {} + +func (x *PutResponse_Body) ProtoReflect() protoreflect.Message { + mi := &file_container_grpc_service_proto_msgTypes[15] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PutResponse_Body.ProtoReflect.Descriptor instead. +func (*PutResponse_Body) Descriptor() ([]byte, []int) { + return file_container_grpc_service_proto_rawDescGZIP(), []int{1, 0} +} + +func (x *PutResponse_Body) GetContainerId() *grpc1.ContainerID { + if x != nil { + return x.ContainerId + } + return nil +} + +// Container removal request body has signed `ContainerID` as a proof of +// the container owner's intent. The signature will be verified by `Container` +// smart contract, so signing algorithm must be supported by NeoVM. +type DeleteRequest_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Identifier of the container to delete from NeoFS + ContainerId *grpc1.ContainerID `protobuf:"bytes,1,opt,name=container_id,json=containerId,proto3" json:"container_id,omitempty"` + // `ContainerID` signed with the container owner's key according to + // RFC-6979. + Signature *grpc1.SignatureRFC6979 `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` +} + +func (x *DeleteRequest_Body) Reset() { + *x = DeleteRequest_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_container_grpc_service_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DeleteRequest_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteRequest_Body) ProtoMessage() {} + +func (x *DeleteRequest_Body) ProtoReflect() protoreflect.Message { + mi := &file_container_grpc_service_proto_msgTypes[16] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DeleteRequest_Body.ProtoReflect.Descriptor instead. +func (*DeleteRequest_Body) Descriptor() ([]byte, []int) { + return file_container_grpc_service_proto_rawDescGZIP(), []int{2, 0} +} + +func (x *DeleteRequest_Body) GetContainerId() *grpc1.ContainerID { + if x != nil { + return x.ContainerId + } + return nil +} + +func (x *DeleteRequest_Body) GetSignature() *grpc1.SignatureRFC6979 { + if x != nil { + return x.Signature + } + return nil +} + +// `DeleteResponse` has an empty body because delete operation is asynchronous +// and done via consensus in Inner Ring nodes. +type DeleteResponse_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *DeleteResponse_Body) Reset() { + *x = DeleteResponse_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_container_grpc_service_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DeleteResponse_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteResponse_Body) ProtoMessage() {} + +func (x *DeleteResponse_Body) ProtoReflect() protoreflect.Message { + mi := &file_container_grpc_service_proto_msgTypes[17] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DeleteResponse_Body.ProtoReflect.Descriptor instead. +func (*DeleteResponse_Body) Descriptor() ([]byte, []int) { + return file_container_grpc_service_proto_rawDescGZIP(), []int{3, 0} +} + +// Get container structure request body. +type GetRequest_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Identifier of the container to get + ContainerId *grpc1.ContainerID `protobuf:"bytes,1,opt,name=container_id,json=containerId,proto3" json:"container_id,omitempty"` +} + +func (x *GetRequest_Body) Reset() { + *x = GetRequest_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_container_grpc_service_proto_msgTypes[18] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetRequest_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetRequest_Body) ProtoMessage() {} + +func (x *GetRequest_Body) ProtoReflect() protoreflect.Message { + mi := &file_container_grpc_service_proto_msgTypes[18] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetRequest_Body.ProtoReflect.Descriptor instead. +func (*GetRequest_Body) Descriptor() ([]byte, []int) { + return file_container_grpc_service_proto_rawDescGZIP(), []int{4, 0} +} + +func (x *GetRequest_Body) GetContainerId() *grpc1.ContainerID { + if x != nil { + return x.ContainerId + } + return nil +} + +// Get container response body does not have container structure signature. It +// has been already verified upon container creation. +type GetResponse_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Requested container structure + Container *Container `protobuf:"bytes,1,opt,name=container,proto3" json:"container,omitempty"` + // Signature of a stable-marshalled container according to RFC-6979. + Signature *grpc1.SignatureRFC6979 `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` + // Session token if the container has been created within the session + SessionToken *grpc.SessionToken `protobuf:"bytes,3,opt,name=session_token,json=sessionToken,proto3" json:"session_token,omitempty"` +} + +func (x *GetResponse_Body) Reset() { + *x = GetResponse_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_container_grpc_service_proto_msgTypes[19] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetResponse_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetResponse_Body) ProtoMessage() {} + +func (x *GetResponse_Body) ProtoReflect() protoreflect.Message { + mi := &file_container_grpc_service_proto_msgTypes[19] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetResponse_Body.ProtoReflect.Descriptor instead. +func (*GetResponse_Body) Descriptor() ([]byte, []int) { + return file_container_grpc_service_proto_rawDescGZIP(), []int{5, 0} +} + +func (x *GetResponse_Body) GetContainer() *Container { + if x != nil { + return x.Container + } + return nil +} + +func (x *GetResponse_Body) GetSignature() *grpc1.SignatureRFC6979 { + if x != nil { + return x.Signature + } + return nil +} + +func (x *GetResponse_Body) GetSessionToken() *grpc.SessionToken { + if x != nil { + return x.SessionToken + } + return nil +} + +// List containers request body. +type ListRequest_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Identifier of the container owner + OwnerId *grpc1.OwnerID `protobuf:"bytes,1,opt,name=owner_id,json=ownerId,proto3" json:"owner_id,omitempty"` +} + +func (x *ListRequest_Body) Reset() { + *x = ListRequest_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_container_grpc_service_proto_msgTypes[20] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListRequest_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListRequest_Body) ProtoMessage() {} + +func (x *ListRequest_Body) ProtoReflect() protoreflect.Message { + mi := &file_container_grpc_service_proto_msgTypes[20] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListRequest_Body.ProtoReflect.Descriptor instead. +func (*ListRequest_Body) Descriptor() ([]byte, []int) { + return file_container_grpc_service_proto_rawDescGZIP(), []int{6, 0} +} + +func (x *ListRequest_Body) GetOwnerId() *grpc1.OwnerID { + if x != nil { + return x.OwnerId + } + return nil +} + +// List containers response body. +type ListResponse_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // List of `ContainerID`s belonging to the requested `OwnerID` + ContainerIds []*grpc1.ContainerID `protobuf:"bytes,1,rep,name=container_ids,json=containerIds,proto3" json:"container_ids,omitempty"` +} + +func (x *ListResponse_Body) Reset() { + *x = ListResponse_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_container_grpc_service_proto_msgTypes[21] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListResponse_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListResponse_Body) ProtoMessage() {} + +func (x *ListResponse_Body) ProtoReflect() protoreflect.Message { + mi := &file_container_grpc_service_proto_msgTypes[21] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListResponse_Body.ProtoReflect.Descriptor instead. +func (*ListResponse_Body) Descriptor() ([]byte, []int) { + return file_container_grpc_service_proto_rawDescGZIP(), []int{7, 0} +} + +func (x *ListResponse_Body) GetContainerIds() []*grpc1.ContainerID { + if x != nil { + return x.ContainerIds + } + return nil +} + +// Set Extended ACL request body does not have separate `ContainerID` +// reference. It will be taken from `EACLTable.container_id` field. +type SetExtendedACLRequest_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Extended ACL table to set for the container + Eacl *grpc2.EACLTable `protobuf:"bytes,1,opt,name=eacl,proto3" json:"eacl,omitempty"` + // Signature of stable-marshalled Extended ACL table according to RFC-6979. + Signature *grpc1.SignatureRFC6979 `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` +} + +func (x *SetExtendedACLRequest_Body) Reset() { + *x = SetExtendedACLRequest_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_container_grpc_service_proto_msgTypes[22] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SetExtendedACLRequest_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SetExtendedACLRequest_Body) ProtoMessage() {} + +func (x *SetExtendedACLRequest_Body) ProtoReflect() protoreflect.Message { + mi := &file_container_grpc_service_proto_msgTypes[22] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SetExtendedACLRequest_Body.ProtoReflect.Descriptor instead. +func (*SetExtendedACLRequest_Body) Descriptor() ([]byte, []int) { + return file_container_grpc_service_proto_rawDescGZIP(), []int{8, 0} +} + +func (x *SetExtendedACLRequest_Body) GetEacl() *grpc2.EACLTable { + if x != nil { + return x.Eacl + } + return nil +} + +func (x *SetExtendedACLRequest_Body) GetSignature() *grpc1.SignatureRFC6979 { + if x != nil { + return x.Signature + } + return nil +} + +// `SetExtendedACLResponse` has an empty body because the operation is +// asynchronous and the update should be reflected in `Container` smart +// contract's storage after next block is issued in sidechain. +type SetExtendedACLResponse_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *SetExtendedACLResponse_Body) Reset() { + *x = SetExtendedACLResponse_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_container_grpc_service_proto_msgTypes[23] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SetExtendedACLResponse_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SetExtendedACLResponse_Body) ProtoMessage() {} + +func (x *SetExtendedACLResponse_Body) ProtoReflect() protoreflect.Message { + mi := &file_container_grpc_service_proto_msgTypes[23] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SetExtendedACLResponse_Body.ProtoReflect.Descriptor instead. +func (*SetExtendedACLResponse_Body) Descriptor() ([]byte, []int) { + return file_container_grpc_service_proto_rawDescGZIP(), []int{9, 0} +} + +// Get Extended ACL request body +type GetExtendedACLRequest_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Identifier of the container having Extended ACL + ContainerId *grpc1.ContainerID `protobuf:"bytes,1,opt,name=container_id,json=containerId,proto3" json:"container_id,omitempty"` +} + +func (x *GetExtendedACLRequest_Body) Reset() { + *x = GetExtendedACLRequest_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_container_grpc_service_proto_msgTypes[24] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetExtendedACLRequest_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetExtendedACLRequest_Body) ProtoMessage() {} + +func (x *GetExtendedACLRequest_Body) ProtoReflect() protoreflect.Message { + mi := &file_container_grpc_service_proto_msgTypes[24] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetExtendedACLRequest_Body.ProtoReflect.Descriptor instead. +func (*GetExtendedACLRequest_Body) Descriptor() ([]byte, []int) { + return file_container_grpc_service_proto_rawDescGZIP(), []int{10, 0} +} + +func (x *GetExtendedACLRequest_Body) GetContainerId() *grpc1.ContainerID { + if x != nil { + return x.ContainerId + } + return nil +} + +// Get Extended ACL Response body can be empty if the requested container does +// not have Extended ACL Table attached or Extended ACL has not been allowed +// at the time of container creation. +type GetExtendedACLResponse_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Extended ACL requested, if available + Eacl *grpc2.EACLTable `protobuf:"bytes,1,opt,name=eacl,proto3" json:"eacl,omitempty"` + // Signature of stable-marshalled Extended ACL according to RFC-6979. + Signature *grpc1.SignatureRFC6979 `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` + // Session token if Extended ACL was set within a session + SessionToken *grpc.SessionToken `protobuf:"bytes,3,opt,name=session_token,json=sessionToken,proto3" json:"session_token,omitempty"` +} + +func (x *GetExtendedACLResponse_Body) Reset() { + *x = GetExtendedACLResponse_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_container_grpc_service_proto_msgTypes[25] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetExtendedACLResponse_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetExtendedACLResponse_Body) ProtoMessage() {} + +func (x *GetExtendedACLResponse_Body) ProtoReflect() protoreflect.Message { + mi := &file_container_grpc_service_proto_msgTypes[25] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetExtendedACLResponse_Body.ProtoReflect.Descriptor instead. +func (*GetExtendedACLResponse_Body) Descriptor() ([]byte, []int) { + return file_container_grpc_service_proto_rawDescGZIP(), []int{11, 0} +} + +func (x *GetExtendedACLResponse_Body) GetEacl() *grpc2.EACLTable { + if x != nil { + return x.Eacl + } + return nil +} + +func (x *GetExtendedACLResponse_Body) GetSignature() *grpc1.SignatureRFC6979 { + if x != nil { + return x.Signature + } + return nil +} + +func (x *GetExtendedACLResponse_Body) GetSessionToken() *grpc.SessionToken { + if x != nil { + return x.SessionToken + } + return nil +} + +// Container used space announcement body. +type AnnounceUsedSpaceRequest_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // List of announcements. If nodes share several containers, + // announcements are transferred in a batch. + Announcements []*AnnounceUsedSpaceRequest_Body_Announcement `protobuf:"bytes,1,rep,name=announcements,proto3" json:"announcements,omitempty"` +} + +func (x *AnnounceUsedSpaceRequest_Body) Reset() { + *x = AnnounceUsedSpaceRequest_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_container_grpc_service_proto_msgTypes[26] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AnnounceUsedSpaceRequest_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AnnounceUsedSpaceRequest_Body) ProtoMessage() {} + +func (x *AnnounceUsedSpaceRequest_Body) ProtoReflect() protoreflect.Message { + mi := &file_container_grpc_service_proto_msgTypes[26] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AnnounceUsedSpaceRequest_Body.ProtoReflect.Descriptor instead. +func (*AnnounceUsedSpaceRequest_Body) Descriptor() ([]byte, []int) { + return file_container_grpc_service_proto_rawDescGZIP(), []int{12, 0} +} + +func (x *AnnounceUsedSpaceRequest_Body) GetAnnouncements() []*AnnounceUsedSpaceRequest_Body_Announcement { + if x != nil { + return x.Announcements + } + return nil +} + +// Announcement contains used space information for a single container. +type AnnounceUsedSpaceRequest_Body_Announcement struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Epoch number for which the container size estimation was produced. + Epoch uint64 `protobuf:"varint,1,opt,name=epoch,proto3" json:"epoch,omitempty"` + // Identifier of the container. + ContainerId *grpc1.ContainerID `protobuf:"bytes,2,opt,name=container_id,json=containerId,proto3" json:"container_id,omitempty"` + // Used space is a sum of object payload sizes of a specified + // container, stored in the node. It must not include inhumed objects. + UsedSpace uint64 `protobuf:"varint,3,opt,name=used_space,json=usedSpace,proto3" json:"used_space,omitempty"` +} + +func (x *AnnounceUsedSpaceRequest_Body_Announcement) Reset() { + *x = AnnounceUsedSpaceRequest_Body_Announcement{} + if protoimpl.UnsafeEnabled { + mi := &file_container_grpc_service_proto_msgTypes[27] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AnnounceUsedSpaceRequest_Body_Announcement) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AnnounceUsedSpaceRequest_Body_Announcement) ProtoMessage() {} + +func (x *AnnounceUsedSpaceRequest_Body_Announcement) ProtoReflect() protoreflect.Message { + mi := &file_container_grpc_service_proto_msgTypes[27] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AnnounceUsedSpaceRequest_Body_Announcement.ProtoReflect.Descriptor instead. +func (*AnnounceUsedSpaceRequest_Body_Announcement) Descriptor() ([]byte, []int) { + return file_container_grpc_service_proto_rawDescGZIP(), []int{12, 0, 0} +} + +func (x *AnnounceUsedSpaceRequest_Body_Announcement) GetEpoch() uint64 { + if x != nil { + return x.Epoch + } + return 0 +} + +func (x *AnnounceUsedSpaceRequest_Body_Announcement) GetContainerId() *grpc1.ContainerID { + if x != nil { + return x.ContainerId + } + return nil +} + +func (x *AnnounceUsedSpaceRequest_Body_Announcement) GetUsedSpace() uint64 { + if x != nil { + return x.UsedSpace + } + return 0 +} + +// `AnnounceUsedSpaceResponse` has an empty body because announcements are +// one way communication. +type AnnounceUsedSpaceResponse_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *AnnounceUsedSpaceResponse_Body) Reset() { + *x = AnnounceUsedSpaceResponse_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_container_grpc_service_proto_msgTypes[28] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AnnounceUsedSpaceResponse_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AnnounceUsedSpaceResponse_Body) ProtoMessage() {} + +func (x *AnnounceUsedSpaceResponse_Body) ProtoReflect() protoreflect.Message { + mi := &file_container_grpc_service_proto_msgTypes[28] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AnnounceUsedSpaceResponse_Body.ProtoReflect.Descriptor instead. +func (*AnnounceUsedSpaceResponse_Body) Descriptor() ([]byte, []int) { + return file_container_grpc_service_proto_rawDescGZIP(), []int{13, 0} +} + +var File_container_grpc_service_proto protoreflect.FileDescriptor + +var file_container_grpc_service_proto_rawDesc = []byte{ + 0x0a, 0x1c, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2f, 0x67, 0x72, 0x70, 0x63, + 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x13, + 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, + 0x6e, 0x65, 0x72, 0x1a, 0x14, 0x61, 0x63, 0x6c, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x74, 0x79, + 0x70, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1a, 0x63, 0x6f, 0x6e, 0x74, 0x61, + 0x69, 0x6e, 0x65, 0x72, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x15, 0x72, 0x65, 0x66, 0x73, 0x2f, 0x67, 0x72, 0x70, 0x63, + 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x18, 0x73, 0x65, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xe7, 0x02, 0x0a, 0x0a, 0x50, 0x75, 0x74, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x38, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x75, 0x74, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, + 0x45, 0x0a, 0x0b, 0x6d, 0x65, 0x74, 0x61, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, + 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x4d, 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0a, 0x6d, 0x65, 0x74, 0x61, + 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x51, 0x0a, 0x0d, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, + 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, + 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0c, 0x76, 0x65, 0x72, + 0x69, 0x66, 0x79, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x1a, 0x84, 0x01, 0x0a, 0x04, 0x42, 0x6f, + 0x64, 0x79, 0x12, 0x3c, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, + 0x32, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6e, 0x74, + 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, + 0x12, 0x3e, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, + 0x72, 0x65, 0x66, 0x73, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x46, + 0x43, 0x36, 0x39, 0x37, 0x39, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x22, 0xac, 0x02, 0x0a, 0x0b, 0x50, 0x75, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x39, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, + 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, + 0x69, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x75, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x46, 0x0a, 0x0b, 0x6d, + 0x65, 0x74, 0x61, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x25, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x74, + 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0a, 0x6d, 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x12, 0x52, 0x0a, 0x0d, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x5f, 0x68, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x6e, 0x65, 0x6f, + 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0c, 0x76, 0x65, 0x72, 0x69, 0x66, + 0x79, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x1a, 0x46, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, + 0x3e, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, + 0x32, 0x2e, 0x72, 0x65, 0x66, 0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, + 0x49, 0x44, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x22, + 0xef, 0x02, 0x0a, 0x0d, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x3b, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x27, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x45, + 0x0a, 0x0b, 0x6d, 0x65, 0x74, 0x61, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, + 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, + 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0a, 0x6d, 0x65, 0x74, 0x61, 0x48, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x51, 0x0a, 0x0d, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x5f, + 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x6e, + 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0c, 0x76, 0x65, 0x72, 0x69, + 0x66, 0x79, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x1a, 0x86, 0x01, 0x0a, 0x04, 0x42, 0x6f, 0x64, + 0x79, 0x12, 0x3e, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, + 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x65, 0x66, 0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, + 0x65, 0x72, 0x49, 0x44, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, + 0x64, 0x12, 0x3e, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, + 0x2e, 0x72, 0x65, 0x66, 0x73, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, + 0x46, 0x43, 0x36, 0x39, 0x37, 0x39, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x22, 0xf2, 0x01, 0x0a, 0x0e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3c, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, + 0x64, 0x79, 0x12, 0x46, 0x0a, 0x0b, 0x6d, 0x65, 0x74, 0x61, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, + 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0a, + 0x6d, 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x52, 0x0a, 0x0d, 0x76, 0x65, + 0x72, 0x69, 0x66, 0x79, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x2d, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x56, 0x65, + 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x52, 0x0c, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x1a, 0x06, + 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0xa8, 0x02, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x38, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, + 0x45, 0x0a, 0x0b, 0x6d, 0x65, 0x74, 0x61, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, + 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x4d, 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0a, 0x6d, 0x65, 0x74, 0x61, + 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x51, 0x0a, 0x0d, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, + 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, + 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0c, 0x76, 0x65, 0x72, + 0x69, 0x66, 0x79, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x1a, 0x46, 0x0a, 0x04, 0x42, 0x6f, 0x64, + 0x79, 0x12, 0x3e, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, + 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x65, 0x66, 0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, + 0x65, 0x72, 0x49, 0x44, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, + 0x64, 0x22, 0xb1, 0x03, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x39, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x25, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x46, 0x0a, 0x0b, + 0x6d, 0x65, 0x74, 0x61, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x25, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, + 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0a, 0x6d, 0x65, 0x74, 0x61, 0x48, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x12, 0x52, 0x0a, 0x0d, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x5f, 0x68, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x6e, 0x65, + 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0c, 0x76, 0x65, 0x72, 0x69, + 0x66, 0x79, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x1a, 0xca, 0x01, 0x0a, 0x04, 0x42, 0x6f, 0x64, + 0x79, 0x12, 0x3c, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, + 0x69, 0x6e, 0x65, 0x72, 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, + 0x3e, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x72, + 0x65, 0x66, 0x73, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x46, 0x43, + 0x36, 0x39, 0x37, 0x39, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, + 0x44, 0x0a, 0x0d, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, + 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x0c, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x9e, 0x02, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x39, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, + 0x12, 0x45, 0x0a, 0x0b, 0x6d, 0x65, 0x74, 0x61, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, + 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x4d, 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0a, 0x6d, 0x65, 0x74, + 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x51, 0x0a, 0x0d, 0x76, 0x65, 0x72, 0x69, 0x66, + 0x79, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, + 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0c, 0x76, 0x65, + 0x72, 0x69, 0x66, 0x79, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x1a, 0x3a, 0x0a, 0x04, 0x42, 0x6f, + 0x64, 0x79, 0x12, 0x32, 0x0a, 0x08, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, + 0x2e, 0x72, 0x65, 0x66, 0x73, 0x2e, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x49, 0x44, 0x52, 0x07, 0x6f, + 0x77, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x22, 0xb0, 0x02, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, + 0x32, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, + 0x6f, 0x64, 0x79, 0x12, 0x46, 0x0a, 0x0b, 0x6d, 0x65, 0x74, 0x61, 0x5f, 0x68, 0x65, 0x61, 0x64, + 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, + 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, + 0x0a, 0x6d, 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x52, 0x0a, 0x0d, 0x76, + 0x65, 0x72, 0x69, 0x66, 0x79, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, + 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x56, + 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x52, 0x0c, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x1a, + 0x48, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x40, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x61, + 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, + 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x65, 0x66, 0x73, 0x2e, + 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x44, 0x52, 0x0c, 0x63, 0x6f, 0x6e, + 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x73, 0x22, 0xec, 0x02, 0x0a, 0x15, 0x53, 0x65, + 0x74, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x41, 0x43, 0x4c, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x43, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x2f, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2e, 0x53, 0x65, 0x74, 0x45, 0x78, 0x74, 0x65, 0x6e, + 0x64, 0x65, 0x64, 0x41, 0x43, 0x4c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, + 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x45, 0x0a, 0x0b, 0x6d, 0x65, 0x74, 0x61, + 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, + 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x52, 0x0a, 0x6d, 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, + 0x51, 0x0a, 0x0d, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, + 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x52, 0x0c, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x48, 0x65, 0x61, 0x64, + 0x65, 0x72, 0x1a, 0x74, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2c, 0x0a, 0x04, 0x65, 0x61, + 0x63, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, + 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x61, 0x63, 0x6c, 0x2e, 0x45, 0x41, 0x43, 0x4c, 0x54, 0x61, 0x62, + 0x6c, 0x65, 0x52, 0x04, 0x65, 0x61, 0x63, 0x6c, 0x12, 0x3e, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x6e, 0x65, + 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x65, 0x66, 0x73, 0x2e, 0x53, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x46, 0x43, 0x36, 0x39, 0x37, 0x39, 0x52, 0x09, 0x73, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x82, 0x02, 0x0a, 0x16, 0x53, 0x65, 0x74, + 0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x41, 0x43, 0x4c, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x30, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2e, 0x53, 0x65, 0x74, 0x45, 0x78, 0x74, 0x65, 0x6e, + 0x64, 0x65, 0x64, 0x41, 0x43, 0x4c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, + 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x46, 0x0a, 0x0b, 0x6d, 0x65, 0x74, + 0x61, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, + 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x48, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0a, 0x6d, 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x12, 0x52, 0x0a, 0x0d, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x5f, 0x68, 0x65, 0x61, 0x64, + 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, + 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0c, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x48, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0xbe, 0x02, + 0x0a, 0x15, 0x47, 0x65, 0x74, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x41, 0x43, 0x4c, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x43, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, + 0x32, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x74, 0x45, + 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x41, 0x43, 0x4c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x45, 0x0a, 0x0b, + 0x6d, 0x65, 0x74, 0x61, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x24, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, + 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0a, 0x6d, 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x12, 0x51, 0x0a, 0x0d, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x5f, 0x68, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x6e, 0x65, 0x6f, + 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0c, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, + 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x1a, 0x46, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x3e, + 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, + 0x2e, 0x72, 0x65, 0x66, 0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, + 0x44, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x22, 0xb7, + 0x03, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x41, 0x43, + 0x4c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x04, 0x62, 0x6f, 0x64, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, + 0x2e, 0x76, 0x32, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2e, 0x47, 0x65, + 0x74, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x41, 0x43, 0x4c, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, + 0x46, 0x0a, 0x0b, 0x6d, 0x65, 0x74, 0x61, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, + 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x4d, 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0a, 0x6d, 0x65, 0x74, + 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x52, 0x0a, 0x0d, 0x76, 0x65, 0x72, 0x69, 0x66, + 0x79, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, + 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x56, 0x65, 0x72, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0c, 0x76, + 0x65, 0x72, 0x69, 0x66, 0x79, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x1a, 0xba, 0x01, 0x0a, 0x04, + 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2c, 0x0a, 0x04, 0x65, 0x61, 0x63, 0x6c, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x61, + 0x63, 0x6c, 0x2e, 0x45, 0x41, 0x43, 0x4c, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x04, 0x65, 0x61, + 0x63, 0x6c, 0x12, 0x3e, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, + 0x32, 0x2e, 0x72, 0x65, 0x66, 0x73, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x52, 0x46, 0x43, 0x36, 0x39, 0x37, 0x39, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x12, 0x44, 0x0a, 0x0d, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x6f, + 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, + 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x53, 0x65, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x0c, 0x73, 0x65, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0xf2, 0x03, 0x0a, 0x18, 0x41, 0x6e, 0x6e, + 0x6f, 0x75, 0x6e, 0x63, 0x65, 0x55, 0x73, 0x65, 0x64, 0x53, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x46, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2e, 0x41, 0x6e, 0x6e, 0x6f, 0x75, 0x6e, + 0x63, 0x65, 0x55, 0x73, 0x65, 0x64, 0x53, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x45, 0x0a, + 0x0b, 0x6d, 0x65, 0x74, 0x61, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, + 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, + 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0a, 0x6d, 0x65, 0x74, 0x61, 0x48, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x12, 0x51, 0x0a, 0x0d, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x5f, 0x68, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x6e, 0x65, + 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0c, 0x76, 0x65, 0x72, 0x69, 0x66, + 0x79, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x1a, 0xf3, 0x01, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, + 0x12, 0x65, 0x0a, 0x0d, 0x61, 0x6e, 0x6e, 0x6f, 0x75, 0x6e, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, + 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, + 0x2e, 0x76, 0x32, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2e, 0x41, 0x6e, + 0x6e, 0x6f, 0x75, 0x6e, 0x63, 0x65, 0x55, 0x73, 0x65, 0x64, 0x53, 0x70, 0x61, 0x63, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x2e, 0x41, 0x6e, 0x6e, 0x6f, + 0x75, 0x6e, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x0d, 0x61, 0x6e, 0x6e, 0x6f, 0x75, 0x6e, + 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x1a, 0x83, 0x01, 0x0a, 0x0c, 0x41, 0x6e, 0x6e, 0x6f, + 0x75, 0x6e, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, + 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x3e, + 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, + 0x2e, 0x72, 0x65, 0x66, 0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, + 0x44, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1d, + 0x0a, 0x0a, 0x75, 0x73, 0x65, 0x64, 0x5f, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x04, 0x52, 0x09, 0x75, 0x73, 0x65, 0x64, 0x53, 0x70, 0x61, 0x63, 0x65, 0x22, 0x88, 0x02, + 0x0a, 0x19, 0x41, 0x6e, 0x6e, 0x6f, 0x75, 0x6e, 0x63, 0x65, 0x55, 0x73, 0x65, 0x64, 0x53, 0x70, + 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x47, 0x0a, 0x04, 0x62, + 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, + 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2e, + 0x41, 0x6e, 0x6e, 0x6f, 0x75, 0x6e, 0x63, 0x65, 0x55, 0x73, 0x65, 0x64, 0x53, 0x70, 0x61, 0x63, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, + 0x62, 0x6f, 0x64, 0x79, 0x12, 0x46, 0x0a, 0x0b, 0x6d, 0x65, 0x74, 0x61, 0x5f, 0x68, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, + 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x52, 0x0a, 0x6d, 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x52, 0x0a, 0x0d, + 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, + 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x64, + 0x65, 0x72, 0x52, 0x0c, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x32, 0x90, 0x05, 0x0a, 0x10, 0x43, 0x6f, 0x6e, + 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x48, 0x0a, + 0x03, 0x50, 0x75, 0x74, 0x12, 0x1f, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x75, 0x74, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, + 0x32, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x75, 0x74, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x51, 0x0a, 0x06, 0x44, 0x65, 0x6c, 0x65, 0x74, + 0x65, 0x12, 0x22, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, + 0x32, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2e, 0x44, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x48, 0x0a, 0x03, 0x47, 0x65, + 0x74, 0x12, 0x1f, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x20, 0x2e, 0x6e, + 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, + 0x65, 0x72, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, + 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, + 0x69, 0x6e, 0x65, 0x72, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x69, 0x0a, 0x0e, 0x53, 0x65, 0x74, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, + 0x41, 0x43, 0x4c, 0x12, 0x2a, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2e, 0x53, 0x65, 0x74, 0x45, 0x78, 0x74, + 0x65, 0x6e, 0x64, 0x65, 0x64, 0x41, 0x43, 0x4c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x2b, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2e, 0x53, 0x65, 0x74, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, + 0x64, 0x41, 0x43, 0x4c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x69, 0x0a, 0x0e, + 0x47, 0x65, 0x74, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x41, 0x43, 0x4c, 0x12, 0x2a, + 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, + 0x69, 0x6e, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, + 0x41, 0x43, 0x4c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x6e, 0x65, 0x6f, + 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, + 0x2e, 0x47, 0x65, 0x74, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x41, 0x43, 0x4c, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x72, 0x0a, 0x11, 0x41, 0x6e, 0x6e, 0x6f, 0x75, + 0x6e, 0x63, 0x65, 0x55, 0x73, 0x65, 0x64, 0x53, 0x70, 0x61, 0x63, 0x65, 0x12, 0x2d, 0x2e, 0x6e, + 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, + 0x65, 0x72, 0x2e, 0x41, 0x6e, 0x6e, 0x6f, 0x75, 0x6e, 0x63, 0x65, 0x55, 0x73, 0x65, 0x64, 0x53, + 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x6e, 0x65, + 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, + 0x72, 0x2e, 0x41, 0x6e, 0x6e, 0x6f, 0x75, 0x6e, 0x63, 0x65, 0x55, 0x73, 0x65, 0x64, 0x53, 0x70, + 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x6a, 0x5a, 0x48, 0x67, + 0x69, 0x74, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x2f, + 0x54, 0x72, 0x75, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x4c, 0x61, 0x62, 0x2f, 0x66, 0x72, 0x6f, + 0x73, 0x74, 0x66, 0x73, 0x2d, 0x61, 0x70, 0x69, 0x2d, 0x67, 0x6f, 0x2f, 0x76, 0x32, 0x2f, 0x63, + 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x3b, 0x63, 0x6f, + 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0xaa, 0x02, 0x1d, 0x4e, 0x65, 0x6f, 0x2e, 0x46, 0x69, + 0x6c, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x41, 0x50, 0x49, 0x2e, 0x43, 0x6f, + 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_container_grpc_service_proto_rawDescOnce sync.Once + file_container_grpc_service_proto_rawDescData = file_container_grpc_service_proto_rawDesc +) + +func file_container_grpc_service_proto_rawDescGZIP() []byte { + file_container_grpc_service_proto_rawDescOnce.Do(func() { + file_container_grpc_service_proto_rawDescData = protoimpl.X.CompressGZIP(file_container_grpc_service_proto_rawDescData) + }) + return file_container_grpc_service_proto_rawDescData +} + +var file_container_grpc_service_proto_msgTypes = make([]protoimpl.MessageInfo, 29) +var file_container_grpc_service_proto_goTypes = []interface{}{ + (*PutRequest)(nil), // 0: neo.fs.v2.container.PutRequest + (*PutResponse)(nil), // 1: neo.fs.v2.container.PutResponse + (*DeleteRequest)(nil), // 2: neo.fs.v2.container.DeleteRequest + (*DeleteResponse)(nil), // 3: neo.fs.v2.container.DeleteResponse + (*GetRequest)(nil), // 4: neo.fs.v2.container.GetRequest + (*GetResponse)(nil), // 5: neo.fs.v2.container.GetResponse + (*ListRequest)(nil), // 6: neo.fs.v2.container.ListRequest + (*ListResponse)(nil), // 7: neo.fs.v2.container.ListResponse + (*SetExtendedACLRequest)(nil), // 8: neo.fs.v2.container.SetExtendedACLRequest + (*SetExtendedACLResponse)(nil), // 9: neo.fs.v2.container.SetExtendedACLResponse + (*GetExtendedACLRequest)(nil), // 10: neo.fs.v2.container.GetExtendedACLRequest + (*GetExtendedACLResponse)(nil), // 11: neo.fs.v2.container.GetExtendedACLResponse + (*AnnounceUsedSpaceRequest)(nil), // 12: neo.fs.v2.container.AnnounceUsedSpaceRequest + (*AnnounceUsedSpaceResponse)(nil), // 13: neo.fs.v2.container.AnnounceUsedSpaceResponse + (*PutRequest_Body)(nil), // 14: neo.fs.v2.container.PutRequest.Body + (*PutResponse_Body)(nil), // 15: neo.fs.v2.container.PutResponse.Body + (*DeleteRequest_Body)(nil), // 16: neo.fs.v2.container.DeleteRequest.Body + (*DeleteResponse_Body)(nil), // 17: neo.fs.v2.container.DeleteResponse.Body + (*GetRequest_Body)(nil), // 18: neo.fs.v2.container.GetRequest.Body + (*GetResponse_Body)(nil), // 19: neo.fs.v2.container.GetResponse.Body + (*ListRequest_Body)(nil), // 20: neo.fs.v2.container.ListRequest.Body + (*ListResponse_Body)(nil), // 21: neo.fs.v2.container.ListResponse.Body + (*SetExtendedACLRequest_Body)(nil), // 22: neo.fs.v2.container.SetExtendedACLRequest.Body + (*SetExtendedACLResponse_Body)(nil), // 23: neo.fs.v2.container.SetExtendedACLResponse.Body + (*GetExtendedACLRequest_Body)(nil), // 24: neo.fs.v2.container.GetExtendedACLRequest.Body + (*GetExtendedACLResponse_Body)(nil), // 25: neo.fs.v2.container.GetExtendedACLResponse.Body + (*AnnounceUsedSpaceRequest_Body)(nil), // 26: neo.fs.v2.container.AnnounceUsedSpaceRequest.Body + (*AnnounceUsedSpaceRequest_Body_Announcement)(nil), // 27: neo.fs.v2.container.AnnounceUsedSpaceRequest.Body.Announcement + (*AnnounceUsedSpaceResponse_Body)(nil), // 28: neo.fs.v2.container.AnnounceUsedSpaceResponse.Body + (*grpc.RequestMetaHeader)(nil), // 29: neo.fs.v2.session.RequestMetaHeader + (*grpc.RequestVerificationHeader)(nil), // 30: neo.fs.v2.session.RequestVerificationHeader + (*grpc.ResponseMetaHeader)(nil), // 31: neo.fs.v2.session.ResponseMetaHeader + (*grpc.ResponseVerificationHeader)(nil), // 32: neo.fs.v2.session.ResponseVerificationHeader + (*Container)(nil), // 33: neo.fs.v2.container.Container + (*grpc1.SignatureRFC6979)(nil), // 34: neo.fs.v2.refs.SignatureRFC6979 + (*grpc1.ContainerID)(nil), // 35: neo.fs.v2.refs.ContainerID + (*grpc.SessionToken)(nil), // 36: neo.fs.v2.session.SessionToken + (*grpc1.OwnerID)(nil), // 37: neo.fs.v2.refs.OwnerID + (*grpc2.EACLTable)(nil), // 38: neo.fs.v2.acl.EACLTable +} +var file_container_grpc_service_proto_depIdxs = []int32{ + 14, // 0: neo.fs.v2.container.PutRequest.body:type_name -> neo.fs.v2.container.PutRequest.Body + 29, // 1: neo.fs.v2.container.PutRequest.meta_header:type_name -> neo.fs.v2.session.RequestMetaHeader + 30, // 2: neo.fs.v2.container.PutRequest.verify_header:type_name -> neo.fs.v2.session.RequestVerificationHeader + 15, // 3: neo.fs.v2.container.PutResponse.body:type_name -> neo.fs.v2.container.PutResponse.Body + 31, // 4: neo.fs.v2.container.PutResponse.meta_header:type_name -> neo.fs.v2.session.ResponseMetaHeader + 32, // 5: neo.fs.v2.container.PutResponse.verify_header:type_name -> neo.fs.v2.session.ResponseVerificationHeader + 16, // 6: neo.fs.v2.container.DeleteRequest.body:type_name -> neo.fs.v2.container.DeleteRequest.Body + 29, // 7: neo.fs.v2.container.DeleteRequest.meta_header:type_name -> neo.fs.v2.session.RequestMetaHeader + 30, // 8: neo.fs.v2.container.DeleteRequest.verify_header:type_name -> neo.fs.v2.session.RequestVerificationHeader + 17, // 9: neo.fs.v2.container.DeleteResponse.body:type_name -> neo.fs.v2.container.DeleteResponse.Body + 31, // 10: neo.fs.v2.container.DeleteResponse.meta_header:type_name -> neo.fs.v2.session.ResponseMetaHeader + 32, // 11: neo.fs.v2.container.DeleteResponse.verify_header:type_name -> neo.fs.v2.session.ResponseVerificationHeader + 18, // 12: neo.fs.v2.container.GetRequest.body:type_name -> neo.fs.v2.container.GetRequest.Body + 29, // 13: neo.fs.v2.container.GetRequest.meta_header:type_name -> neo.fs.v2.session.RequestMetaHeader + 30, // 14: neo.fs.v2.container.GetRequest.verify_header:type_name -> neo.fs.v2.session.RequestVerificationHeader + 19, // 15: neo.fs.v2.container.GetResponse.body:type_name -> neo.fs.v2.container.GetResponse.Body + 31, // 16: neo.fs.v2.container.GetResponse.meta_header:type_name -> neo.fs.v2.session.ResponseMetaHeader + 32, // 17: neo.fs.v2.container.GetResponse.verify_header:type_name -> neo.fs.v2.session.ResponseVerificationHeader + 20, // 18: neo.fs.v2.container.ListRequest.body:type_name -> neo.fs.v2.container.ListRequest.Body + 29, // 19: neo.fs.v2.container.ListRequest.meta_header:type_name -> neo.fs.v2.session.RequestMetaHeader + 30, // 20: neo.fs.v2.container.ListRequest.verify_header:type_name -> neo.fs.v2.session.RequestVerificationHeader + 21, // 21: neo.fs.v2.container.ListResponse.body:type_name -> neo.fs.v2.container.ListResponse.Body + 31, // 22: neo.fs.v2.container.ListResponse.meta_header:type_name -> neo.fs.v2.session.ResponseMetaHeader + 32, // 23: neo.fs.v2.container.ListResponse.verify_header:type_name -> neo.fs.v2.session.ResponseVerificationHeader + 22, // 24: neo.fs.v2.container.SetExtendedACLRequest.body:type_name -> neo.fs.v2.container.SetExtendedACLRequest.Body + 29, // 25: neo.fs.v2.container.SetExtendedACLRequest.meta_header:type_name -> neo.fs.v2.session.RequestMetaHeader + 30, // 26: neo.fs.v2.container.SetExtendedACLRequest.verify_header:type_name -> neo.fs.v2.session.RequestVerificationHeader + 23, // 27: neo.fs.v2.container.SetExtendedACLResponse.body:type_name -> neo.fs.v2.container.SetExtendedACLResponse.Body + 31, // 28: neo.fs.v2.container.SetExtendedACLResponse.meta_header:type_name -> neo.fs.v2.session.ResponseMetaHeader + 32, // 29: neo.fs.v2.container.SetExtendedACLResponse.verify_header:type_name -> neo.fs.v2.session.ResponseVerificationHeader + 24, // 30: neo.fs.v2.container.GetExtendedACLRequest.body:type_name -> neo.fs.v2.container.GetExtendedACLRequest.Body + 29, // 31: neo.fs.v2.container.GetExtendedACLRequest.meta_header:type_name -> neo.fs.v2.session.RequestMetaHeader + 30, // 32: neo.fs.v2.container.GetExtendedACLRequest.verify_header:type_name -> neo.fs.v2.session.RequestVerificationHeader + 25, // 33: neo.fs.v2.container.GetExtendedACLResponse.body:type_name -> neo.fs.v2.container.GetExtendedACLResponse.Body + 31, // 34: neo.fs.v2.container.GetExtendedACLResponse.meta_header:type_name -> neo.fs.v2.session.ResponseMetaHeader + 32, // 35: neo.fs.v2.container.GetExtendedACLResponse.verify_header:type_name -> neo.fs.v2.session.ResponseVerificationHeader + 26, // 36: neo.fs.v2.container.AnnounceUsedSpaceRequest.body:type_name -> neo.fs.v2.container.AnnounceUsedSpaceRequest.Body + 29, // 37: neo.fs.v2.container.AnnounceUsedSpaceRequest.meta_header:type_name -> neo.fs.v2.session.RequestMetaHeader + 30, // 38: neo.fs.v2.container.AnnounceUsedSpaceRequest.verify_header:type_name -> neo.fs.v2.session.RequestVerificationHeader + 28, // 39: neo.fs.v2.container.AnnounceUsedSpaceResponse.body:type_name -> neo.fs.v2.container.AnnounceUsedSpaceResponse.Body + 31, // 40: neo.fs.v2.container.AnnounceUsedSpaceResponse.meta_header:type_name -> neo.fs.v2.session.ResponseMetaHeader + 32, // 41: neo.fs.v2.container.AnnounceUsedSpaceResponse.verify_header:type_name -> neo.fs.v2.session.ResponseVerificationHeader + 33, // 42: neo.fs.v2.container.PutRequest.Body.container:type_name -> neo.fs.v2.container.Container + 34, // 43: neo.fs.v2.container.PutRequest.Body.signature:type_name -> neo.fs.v2.refs.SignatureRFC6979 + 35, // 44: neo.fs.v2.container.PutResponse.Body.container_id:type_name -> neo.fs.v2.refs.ContainerID + 35, // 45: neo.fs.v2.container.DeleteRequest.Body.container_id:type_name -> neo.fs.v2.refs.ContainerID + 34, // 46: neo.fs.v2.container.DeleteRequest.Body.signature:type_name -> neo.fs.v2.refs.SignatureRFC6979 + 35, // 47: neo.fs.v2.container.GetRequest.Body.container_id:type_name -> neo.fs.v2.refs.ContainerID + 33, // 48: neo.fs.v2.container.GetResponse.Body.container:type_name -> neo.fs.v2.container.Container + 34, // 49: neo.fs.v2.container.GetResponse.Body.signature:type_name -> neo.fs.v2.refs.SignatureRFC6979 + 36, // 50: neo.fs.v2.container.GetResponse.Body.session_token:type_name -> neo.fs.v2.session.SessionToken + 37, // 51: neo.fs.v2.container.ListRequest.Body.owner_id:type_name -> neo.fs.v2.refs.OwnerID + 35, // 52: neo.fs.v2.container.ListResponse.Body.container_ids:type_name -> neo.fs.v2.refs.ContainerID + 38, // 53: neo.fs.v2.container.SetExtendedACLRequest.Body.eacl:type_name -> neo.fs.v2.acl.EACLTable + 34, // 54: neo.fs.v2.container.SetExtendedACLRequest.Body.signature:type_name -> neo.fs.v2.refs.SignatureRFC6979 + 35, // 55: neo.fs.v2.container.GetExtendedACLRequest.Body.container_id:type_name -> neo.fs.v2.refs.ContainerID + 38, // 56: neo.fs.v2.container.GetExtendedACLResponse.Body.eacl:type_name -> neo.fs.v2.acl.EACLTable + 34, // 57: neo.fs.v2.container.GetExtendedACLResponse.Body.signature:type_name -> neo.fs.v2.refs.SignatureRFC6979 + 36, // 58: neo.fs.v2.container.GetExtendedACLResponse.Body.session_token:type_name -> neo.fs.v2.session.SessionToken + 27, // 59: neo.fs.v2.container.AnnounceUsedSpaceRequest.Body.announcements:type_name -> neo.fs.v2.container.AnnounceUsedSpaceRequest.Body.Announcement + 35, // 60: neo.fs.v2.container.AnnounceUsedSpaceRequest.Body.Announcement.container_id:type_name -> neo.fs.v2.refs.ContainerID + 0, // 61: neo.fs.v2.container.ContainerService.Put:input_type -> neo.fs.v2.container.PutRequest + 2, // 62: neo.fs.v2.container.ContainerService.Delete:input_type -> neo.fs.v2.container.DeleteRequest + 4, // 63: neo.fs.v2.container.ContainerService.Get:input_type -> neo.fs.v2.container.GetRequest + 6, // 64: neo.fs.v2.container.ContainerService.List:input_type -> neo.fs.v2.container.ListRequest + 8, // 65: neo.fs.v2.container.ContainerService.SetExtendedACL:input_type -> neo.fs.v2.container.SetExtendedACLRequest + 10, // 66: neo.fs.v2.container.ContainerService.GetExtendedACL:input_type -> neo.fs.v2.container.GetExtendedACLRequest + 12, // 67: neo.fs.v2.container.ContainerService.AnnounceUsedSpace:input_type -> neo.fs.v2.container.AnnounceUsedSpaceRequest + 1, // 68: neo.fs.v2.container.ContainerService.Put:output_type -> neo.fs.v2.container.PutResponse + 3, // 69: neo.fs.v2.container.ContainerService.Delete:output_type -> neo.fs.v2.container.DeleteResponse + 5, // 70: neo.fs.v2.container.ContainerService.Get:output_type -> neo.fs.v2.container.GetResponse + 7, // 71: neo.fs.v2.container.ContainerService.List:output_type -> neo.fs.v2.container.ListResponse + 9, // 72: neo.fs.v2.container.ContainerService.SetExtendedACL:output_type -> neo.fs.v2.container.SetExtendedACLResponse + 11, // 73: neo.fs.v2.container.ContainerService.GetExtendedACL:output_type -> neo.fs.v2.container.GetExtendedACLResponse + 13, // 74: neo.fs.v2.container.ContainerService.AnnounceUsedSpace:output_type -> neo.fs.v2.container.AnnounceUsedSpaceResponse + 68, // [68:75] is the sub-list for method output_type + 61, // [61:68] is the sub-list for method input_type + 61, // [61:61] is the sub-list for extension type_name + 61, // [61:61] is the sub-list for extension extendee + 0, // [0:61] is the sub-list for field type_name +} + +func init() { file_container_grpc_service_proto_init() } +func file_container_grpc_service_proto_init() { + if File_container_grpc_service_proto != nil { + return + } + file_container_grpc_types_proto_init() + if !protoimpl.UnsafeEnabled { + file_container_grpc_service_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PutRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_container_grpc_service_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PutResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_container_grpc_service_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DeleteRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_container_grpc_service_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DeleteResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_container_grpc_service_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_container_grpc_service_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_container_grpc_service_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_container_grpc_service_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_container_grpc_service_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SetExtendedACLRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_container_grpc_service_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SetExtendedACLResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_container_grpc_service_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetExtendedACLRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_container_grpc_service_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetExtendedACLResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_container_grpc_service_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AnnounceUsedSpaceRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_container_grpc_service_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AnnounceUsedSpaceResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_container_grpc_service_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PutRequest_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_container_grpc_service_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PutResponse_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_container_grpc_service_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DeleteRequest_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_container_grpc_service_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DeleteResponse_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_container_grpc_service_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetRequest_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_container_grpc_service_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetResponse_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_container_grpc_service_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListRequest_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_container_grpc_service_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListResponse_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_container_grpc_service_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SetExtendedACLRequest_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_container_grpc_service_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SetExtendedACLResponse_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_container_grpc_service_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetExtendedACLRequest_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_container_grpc_service_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetExtendedACLResponse_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_container_grpc_service_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AnnounceUsedSpaceRequest_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_container_grpc_service_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AnnounceUsedSpaceRequest_Body_Announcement); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_container_grpc_service_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AnnounceUsedSpaceResponse_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_container_grpc_service_proto_rawDesc, + NumEnums: 0, + NumMessages: 29, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_container_grpc_service_proto_goTypes, + DependencyIndexes: file_container_grpc_service_proto_depIdxs, + MessageInfos: file_container_grpc_service_proto_msgTypes, + }.Build() + File_container_grpc_service_proto = out.File + file_container_grpc_service_proto_rawDesc = nil + file_container_grpc_service_proto_goTypes = nil + file_container_grpc_service_proto_depIdxs = nil +} diff --git a/pkg/api/container/grpc/service_grpc.pb.go b/pkg/api/container/grpc/service_grpc.pb.go new file mode 100644 index 000000000..79b0533fd --- /dev/null +++ b/pkg/api/container/grpc/service_grpc.pb.go @@ -0,0 +1,443 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.3.0 +// - protoc v4.25.3 +// source: container/grpc/service.proto + +package container + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +const ( + ContainerService_Put_FullMethodName = "/neo.fs.v2.container.ContainerService/Put" + ContainerService_Delete_FullMethodName = "/neo.fs.v2.container.ContainerService/Delete" + ContainerService_Get_FullMethodName = "/neo.fs.v2.container.ContainerService/Get" + ContainerService_List_FullMethodName = "/neo.fs.v2.container.ContainerService/List" + ContainerService_SetExtendedACL_FullMethodName = "/neo.fs.v2.container.ContainerService/SetExtendedACL" + ContainerService_GetExtendedACL_FullMethodName = "/neo.fs.v2.container.ContainerService/GetExtendedACL" + ContainerService_AnnounceUsedSpace_FullMethodName = "/neo.fs.v2.container.ContainerService/AnnounceUsedSpace" +) + +// ContainerServiceClient is the client API for ContainerService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type ContainerServiceClient interface { + // `Put` invokes `Container` smart contract's `Put` method and returns + // response immediately. After a new block is issued in sidechain, request is + // verified by Inner Ring nodes. After one more block in sidechain, the + // container is added into smart contract storage. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): \ + // request to save the container has been sent to the sidechain; + // - Common failures (SECTION_FAILURE_COMMON). + Put(ctx context.Context, in *PutRequest, opts ...grpc.CallOption) (*PutResponse, error) + // `Delete` invokes `Container` smart contract's `Delete` method and returns + // response immediately. After a new block is issued in sidechain, request is + // verified by Inner Ring nodes. After one more block in sidechain, the + // container is added into smart contract storage. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): \ + // request to remove the container has been sent to the sidechain; + // - Common failures (SECTION_FAILURE_COMMON). + Delete(ctx context.Context, in *DeleteRequest, opts ...grpc.CallOption) (*DeleteResponse, error) + // Returns container structure from `Container` smart contract storage. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): \ + // container has been successfully read; + // - Common failures (SECTION_FAILURE_COMMON); + // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ + // requested container not found. + Get(ctx context.Context, in *GetRequest, opts ...grpc.CallOption) (*GetResponse, error) + // Returns all owner's containers from 'Container` smart contract' storage. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): \ + // container list has been successfully read; + // - Common failures (SECTION_FAILURE_COMMON). + List(ctx context.Context, in *ListRequest, opts ...grpc.CallOption) (*ListResponse, error) + // Invokes 'SetEACL' method of 'Container` smart contract and returns response + // immediately. After one more block in sidechain, changes in an Extended ACL + // are added into smart contract storage. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): \ + // request to save container eACL has been sent to the sidechain; + // - Common failures (SECTION_FAILURE_COMMON). + SetExtendedACL(ctx context.Context, in *SetExtendedACLRequest, opts ...grpc.CallOption) (*SetExtendedACLResponse, error) + // Returns Extended ACL table and signature from `Container` smart contract + // storage. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): \ + // container eACL has been successfully read; + // - Common failures (SECTION_FAILURE_COMMON); + // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ + // container not found; + // - **EACL_NOT_FOUND** (3073, SECTION_CONTAINER): \ + // eACL table not found. + GetExtendedACL(ctx context.Context, in *GetExtendedACLRequest, opts ...grpc.CallOption) (*GetExtendedACLResponse, error) + // Announces the space values used by the container for P2P synchronization. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): \ + // estimation of used space has been successfully announced; + // - Common failures (SECTION_FAILURE_COMMON). + AnnounceUsedSpace(ctx context.Context, in *AnnounceUsedSpaceRequest, opts ...grpc.CallOption) (*AnnounceUsedSpaceResponse, error) +} + +type containerServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewContainerServiceClient(cc grpc.ClientConnInterface) ContainerServiceClient { + return &containerServiceClient{cc} +} + +func (c *containerServiceClient) Put(ctx context.Context, in *PutRequest, opts ...grpc.CallOption) (*PutResponse, error) { + out := new(PutResponse) + err := c.cc.Invoke(ctx, ContainerService_Put_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *containerServiceClient) Delete(ctx context.Context, in *DeleteRequest, opts ...grpc.CallOption) (*DeleteResponse, error) { + out := new(DeleteResponse) + err := c.cc.Invoke(ctx, ContainerService_Delete_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *containerServiceClient) Get(ctx context.Context, in *GetRequest, opts ...grpc.CallOption) (*GetResponse, error) { + out := new(GetResponse) + err := c.cc.Invoke(ctx, ContainerService_Get_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *containerServiceClient) List(ctx context.Context, in *ListRequest, opts ...grpc.CallOption) (*ListResponse, error) { + out := new(ListResponse) + err := c.cc.Invoke(ctx, ContainerService_List_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *containerServiceClient) SetExtendedACL(ctx context.Context, in *SetExtendedACLRequest, opts ...grpc.CallOption) (*SetExtendedACLResponse, error) { + out := new(SetExtendedACLResponse) + err := c.cc.Invoke(ctx, ContainerService_SetExtendedACL_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *containerServiceClient) GetExtendedACL(ctx context.Context, in *GetExtendedACLRequest, opts ...grpc.CallOption) (*GetExtendedACLResponse, error) { + out := new(GetExtendedACLResponse) + err := c.cc.Invoke(ctx, ContainerService_GetExtendedACL_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *containerServiceClient) AnnounceUsedSpace(ctx context.Context, in *AnnounceUsedSpaceRequest, opts ...grpc.CallOption) (*AnnounceUsedSpaceResponse, error) { + out := new(AnnounceUsedSpaceResponse) + err := c.cc.Invoke(ctx, ContainerService_AnnounceUsedSpace_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// ContainerServiceServer is the server API for ContainerService service. +// All implementations should embed UnimplementedContainerServiceServer +// for forward compatibility +type ContainerServiceServer interface { + // `Put` invokes `Container` smart contract's `Put` method and returns + // response immediately. After a new block is issued in sidechain, request is + // verified by Inner Ring nodes. After one more block in sidechain, the + // container is added into smart contract storage. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): \ + // request to save the container has been sent to the sidechain; + // - Common failures (SECTION_FAILURE_COMMON). + Put(context.Context, *PutRequest) (*PutResponse, error) + // `Delete` invokes `Container` smart contract's `Delete` method and returns + // response immediately. After a new block is issued in sidechain, request is + // verified by Inner Ring nodes. After one more block in sidechain, the + // container is added into smart contract storage. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): \ + // request to remove the container has been sent to the sidechain; + // - Common failures (SECTION_FAILURE_COMMON). + Delete(context.Context, *DeleteRequest) (*DeleteResponse, error) + // Returns container structure from `Container` smart contract storage. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): \ + // container has been successfully read; + // - Common failures (SECTION_FAILURE_COMMON); + // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ + // requested container not found. + Get(context.Context, *GetRequest) (*GetResponse, error) + // Returns all owner's containers from 'Container` smart contract' storage. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): \ + // container list has been successfully read; + // - Common failures (SECTION_FAILURE_COMMON). + List(context.Context, *ListRequest) (*ListResponse, error) + // Invokes 'SetEACL' method of 'Container` smart contract and returns response + // immediately. After one more block in sidechain, changes in an Extended ACL + // are added into smart contract storage. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): \ + // request to save container eACL has been sent to the sidechain; + // - Common failures (SECTION_FAILURE_COMMON). + SetExtendedACL(context.Context, *SetExtendedACLRequest) (*SetExtendedACLResponse, error) + // Returns Extended ACL table and signature from `Container` smart contract + // storage. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): \ + // container eACL has been successfully read; + // - Common failures (SECTION_FAILURE_COMMON); + // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ + // container not found; + // - **EACL_NOT_FOUND** (3073, SECTION_CONTAINER): \ + // eACL table not found. + GetExtendedACL(context.Context, *GetExtendedACLRequest) (*GetExtendedACLResponse, error) + // Announces the space values used by the container for P2P synchronization. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): \ + // estimation of used space has been successfully announced; + // - Common failures (SECTION_FAILURE_COMMON). + AnnounceUsedSpace(context.Context, *AnnounceUsedSpaceRequest) (*AnnounceUsedSpaceResponse, error) +} + +// UnimplementedContainerServiceServer should be embedded to have forward compatible implementations. +type UnimplementedContainerServiceServer struct { +} + +func (UnimplementedContainerServiceServer) Put(context.Context, *PutRequest) (*PutResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Put not implemented") +} +func (UnimplementedContainerServiceServer) Delete(context.Context, *DeleteRequest) (*DeleteResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Delete not implemented") +} +func (UnimplementedContainerServiceServer) Get(context.Context, *GetRequest) (*GetResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Get not implemented") +} +func (UnimplementedContainerServiceServer) List(context.Context, *ListRequest) (*ListResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method List not implemented") +} +func (UnimplementedContainerServiceServer) SetExtendedACL(context.Context, *SetExtendedACLRequest) (*SetExtendedACLResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method SetExtendedACL not implemented") +} +func (UnimplementedContainerServiceServer) GetExtendedACL(context.Context, *GetExtendedACLRequest) (*GetExtendedACLResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetExtendedACL not implemented") +} +func (UnimplementedContainerServiceServer) AnnounceUsedSpace(context.Context, *AnnounceUsedSpaceRequest) (*AnnounceUsedSpaceResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method AnnounceUsedSpace not implemented") +} + +// UnsafeContainerServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to ContainerServiceServer will +// result in compilation errors. +type UnsafeContainerServiceServer interface { + mustEmbedUnimplementedContainerServiceServer() +} + +func RegisterContainerServiceServer(s grpc.ServiceRegistrar, srv ContainerServiceServer) { + s.RegisterService(&ContainerService_ServiceDesc, srv) +} + +func _ContainerService_Put_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(PutRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ContainerServiceServer).Put(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ContainerService_Put_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ContainerServiceServer).Put(ctx, req.(*PutRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ContainerService_Delete_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeleteRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ContainerServiceServer).Delete(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ContainerService_Delete_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ContainerServiceServer).Delete(ctx, req.(*DeleteRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ContainerService_Get_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ContainerServiceServer).Get(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ContainerService_Get_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ContainerServiceServer).Get(ctx, req.(*GetRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ContainerService_List_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ContainerServiceServer).List(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ContainerService_List_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ContainerServiceServer).List(ctx, req.(*ListRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ContainerService_SetExtendedACL_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(SetExtendedACLRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ContainerServiceServer).SetExtendedACL(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ContainerService_SetExtendedACL_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ContainerServiceServer).SetExtendedACL(ctx, req.(*SetExtendedACLRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ContainerService_GetExtendedACL_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetExtendedACLRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ContainerServiceServer).GetExtendedACL(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ContainerService_GetExtendedACL_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ContainerServiceServer).GetExtendedACL(ctx, req.(*GetExtendedACLRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ContainerService_AnnounceUsedSpace_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(AnnounceUsedSpaceRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ContainerServiceServer).AnnounceUsedSpace(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ContainerService_AnnounceUsedSpace_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ContainerServiceServer).AnnounceUsedSpace(ctx, req.(*AnnounceUsedSpaceRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// ContainerService_ServiceDesc is the grpc.ServiceDesc for ContainerService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var ContainerService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "neo.fs.v2.container.ContainerService", + HandlerType: (*ContainerServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Put", + Handler: _ContainerService_Put_Handler, + }, + { + MethodName: "Delete", + Handler: _ContainerService_Delete_Handler, + }, + { + MethodName: "Get", + Handler: _ContainerService_Get_Handler, + }, + { + MethodName: "List", + Handler: _ContainerService_List_Handler, + }, + { + MethodName: "SetExtendedACL", + Handler: _ContainerService_SetExtendedACL_Handler, + }, + { + MethodName: "GetExtendedACL", + Handler: _ContainerService_GetExtendedACL_Handler, + }, + { + MethodName: "AnnounceUsedSpace", + Handler: _ContainerService_AnnounceUsedSpace_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "container/grpc/service.proto", +} diff --git a/pkg/api/container/grpc/types.go b/pkg/api/container/grpc/types.go new file mode 100644 index 000000000..94fd72514 --- /dev/null +++ b/pkg/api/container/grpc/types.go @@ -0,0 +1,46 @@ +package container + +import ( + netmap "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/netmap/grpc" + refs "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs/grpc" +) + +// SetKey sets key to the container attribute. +func (m *Container_Attribute) SetKey(v string) { + m.Key = v +} + +// SetValue sets value of the container attribute. +func (m *Container_Attribute) SetValue(v string) { + m.Value = v +} + +// SetOwnerId sets identifier of the container owner, +func (m *Container) SetOwnerId(v *refs.OwnerID) { + m.OwnerId = v +} + +// SetNonce sets nonce of the container structure. +func (m *Container) SetNonce(v []byte) { + m.Nonce = v +} + +// SetBasicAcl sets basic ACL of the container. +func (m *Container) SetBasicAcl(v uint32) { + m.BasicAcl = v +} + +// SetAttributes sets list of the container attributes. +func (m *Container) SetAttributes(v []*Container_Attribute) { + m.Attributes = v +} + +// SetPlacementPolicy sets placement policy of the container. +func (m *Container) SetPlacementPolicy(v *netmap.PlacementPolicy) { + m.PlacementPolicy = v +} + +// SetVersion sets version of the container. +func (m *Container) SetVersion(v *refs.Version) { + m.Version = v +} diff --git a/pkg/api/container/grpc/types.pb.go b/pkg/api/container/grpc/types.pb.go new file mode 100644 index 000000000..0c647c116 --- /dev/null +++ b/pkg/api/container/grpc/types.pb.go @@ -0,0 +1,337 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.33.0 +// protoc v4.25.3 +// source: container/grpc/types.proto + +package container + +import ( + grpc1 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/netmap/grpc" + grpc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs/grpc" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// Container is a structure that defines object placement behaviour. Objects can +// be stored only within containers. They define placement rule, attributes and +// access control information. An ID of a container is a 32 byte long SHA256 +// hash of stable-marshalled container message. +type Container struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Container format version. Effectively, the version of API library used to + // create the container. + Version *grpc.Version `protobuf:"bytes,1,opt,name=version,proto3" json:"version,omitempty"` + // Identifier of the container owner + OwnerId *grpc.OwnerID `protobuf:"bytes,2,opt,name=owner_id,json=ownerID,proto3" json:"owner_id,omitempty"` + // Nonce is a 16 byte UUIDv4, used to avoid collisions of `ContainerID`s + Nonce []byte `protobuf:"bytes,3,opt,name=nonce,proto3" json:"nonce,omitempty"` + // `BasicACL` contains access control rules for the owner, system and others + // groups, as well as permission bits for `BearerToken` and `Extended ACL` + BasicAcl uint32 `protobuf:"varint,4,opt,name=basic_acl,json=basicACL,proto3" json:"basic_acl,omitempty"` + // Attributes represent immutable container's meta data + Attributes []*Container_Attribute `protobuf:"bytes,5,rep,name=attributes,proto3" json:"attributes,omitempty"` + // Placement policy for the object inside the container + PlacementPolicy *grpc1.PlacementPolicy `protobuf:"bytes,6,opt,name=placement_policy,json=placementPolicy,proto3" json:"placement_policy,omitempty"` +} + +func (x *Container) Reset() { + *x = Container{} + if protoimpl.UnsafeEnabled { + mi := &file_container_grpc_types_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Container) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Container) ProtoMessage() {} + +func (x *Container) ProtoReflect() protoreflect.Message { + mi := &file_container_grpc_types_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Container.ProtoReflect.Descriptor instead. +func (*Container) Descriptor() ([]byte, []int) { + return file_container_grpc_types_proto_rawDescGZIP(), []int{0} +} + +func (x *Container) GetVersion() *grpc.Version { + if x != nil { + return x.Version + } + return nil +} + +func (x *Container) GetOwnerId() *grpc.OwnerID { + if x != nil { + return x.OwnerId + } + return nil +} + +func (x *Container) GetNonce() []byte { + if x != nil { + return x.Nonce + } + return nil +} + +func (x *Container) GetBasicAcl() uint32 { + if x != nil { + return x.BasicAcl + } + return 0 +} + +func (x *Container) GetAttributes() []*Container_Attribute { + if x != nil { + return x.Attributes + } + return nil +} + +func (x *Container) GetPlacementPolicy() *grpc1.PlacementPolicy { + if x != nil { + return x.PlacementPolicy + } + return nil +} + +// `Attribute` is a user-defined Key-Value metadata pair attached to the +// container. Container attributes are immutable. They are set at the moment +// of container creation and can never be added or updated. +// +// Key name must be a container-unique valid UTF-8 string. Value can't be +// empty. Containers with duplicated attribute names or attributes with empty +// values will be considered invalid. +// +// There are some "well-known" attributes affecting system behaviour: +// +// - [ __SYSTEM__NAME ] \ +// (`__NEOFS__NAME` is deprecated) \ +// String of a human-friendly container name registered as a domain in +// NNS contract. +// - [ __SYSTEM__ZONE ] \ +// (`__NEOFS__ZONE` is deprecated) \ +// String of a zone for `__SYSTEM__NAME` (`__NEOFS__NAME` is deprecated). +// Used as a TLD of a domain name in NNS contract. If no zone is specified, +// use default zone: `container`. +// - [ __SYSTEM__DISABLE_HOMOMORPHIC_HASHING ] \ +// (`__NEOFS__DISABLE_HOMOMORPHIC_HASHING` is deprecated) \ +// Disables homomorphic hashing for the container if the value equals "true" +// string. Any other values are interpreted as missing attribute. Container +// could be accepted in a NeoFS network only if the global network hashing +// configuration value corresponds with that attribute's value. After +// container inclusion, network setting is ignored. +// +// And some well-known attributes used by applications only: +// +// - Name \ +// Human-friendly name +// - Timestamp \ +// User-defined local time of container creation in Unix Timestamp format +type Container_Attribute struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Attribute name key + Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` + // Attribute value + Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` +} + +func (x *Container_Attribute) Reset() { + *x = Container_Attribute{} + if protoimpl.UnsafeEnabled { + mi := &file_container_grpc_types_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Container_Attribute) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Container_Attribute) ProtoMessage() {} + +func (x *Container_Attribute) ProtoReflect() protoreflect.Message { + mi := &file_container_grpc_types_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Container_Attribute.ProtoReflect.Descriptor instead. +func (*Container_Attribute) Descriptor() ([]byte, []int) { + return file_container_grpc_types_proto_rawDescGZIP(), []int{0, 0} +} + +func (x *Container_Attribute) GetKey() string { + if x != nil { + return x.Key + } + return "" +} + +func (x *Container_Attribute) GetValue() string { + if x != nil { + return x.Value + } + return "" +} + +var File_container_grpc_types_proto protoreflect.FileDescriptor + +var file_container_grpc_types_proto_rawDesc = []byte{ + 0x0a, 0x1a, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2f, 0x67, 0x72, 0x70, 0x63, + 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x13, 0x6e, 0x65, + 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, + 0x72, 0x1a, 0x17, 0x6e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x74, + 0x79, 0x70, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x15, 0x72, 0x65, 0x66, 0x73, + 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x22, 0xf2, 0x02, 0x0a, 0x09, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, + 0x31, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x17, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x65, 0x66, + 0x73, 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, + 0x6f, 0x6e, 0x12, 0x32, 0x0a, 0x08, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, + 0x2e, 0x72, 0x65, 0x66, 0x73, 0x2e, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x49, 0x44, 0x52, 0x07, 0x6f, + 0x77, 0x6e, 0x65, 0x72, 0x49, 0x44, 0x12, 0x14, 0x0a, 0x05, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x12, 0x1b, 0x0a, 0x09, + 0x62, 0x61, 0x73, 0x69, 0x63, 0x5f, 0x61, 0x63, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, + 0x08, 0x62, 0x61, 0x73, 0x69, 0x63, 0x41, 0x43, 0x4c, 0x12, 0x48, 0x0a, 0x0a, 0x61, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, + 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, + 0x6e, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2e, 0x41, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x73, 0x12, 0x4c, 0x0a, 0x10, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, + 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, + 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6e, 0x65, 0x74, 0x6d, 0x61, 0x70, + 0x2e, 0x50, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x52, 0x0f, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, + 0x79, 0x1a, 0x33, 0x0a, 0x09, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x10, + 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, + 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x6a, 0x5a, 0x48, 0x67, 0x69, 0x74, 0x2e, 0x66, 0x72, + 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, 0x75, 0x65, 0x43, + 0x6c, 0x6f, 0x75, 0x64, 0x4c, 0x61, 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2d, + 0x61, 0x70, 0x69, 0x2d, 0x67, 0x6f, 0x2f, 0x76, 0x32, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, + 0x6e, 0x65, 0x72, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x3b, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, + 0x65, 0x72, 0xaa, 0x02, 0x1d, 0x4e, 0x65, 0x6f, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x53, 0x74, 0x6f, + 0x72, 0x61, 0x67, 0x65, 0x2e, 0x41, 0x50, 0x49, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, + 0x65, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_container_grpc_types_proto_rawDescOnce sync.Once + file_container_grpc_types_proto_rawDescData = file_container_grpc_types_proto_rawDesc +) + +func file_container_grpc_types_proto_rawDescGZIP() []byte { + file_container_grpc_types_proto_rawDescOnce.Do(func() { + file_container_grpc_types_proto_rawDescData = protoimpl.X.CompressGZIP(file_container_grpc_types_proto_rawDescData) + }) + return file_container_grpc_types_proto_rawDescData +} + +var file_container_grpc_types_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_container_grpc_types_proto_goTypes = []interface{}{ + (*Container)(nil), // 0: neo.fs.v2.container.Container + (*Container_Attribute)(nil), // 1: neo.fs.v2.container.Container.Attribute + (*grpc.Version)(nil), // 2: neo.fs.v2.refs.Version + (*grpc.OwnerID)(nil), // 3: neo.fs.v2.refs.OwnerID + (*grpc1.PlacementPolicy)(nil), // 4: neo.fs.v2.netmap.PlacementPolicy +} +var file_container_grpc_types_proto_depIdxs = []int32{ + 2, // 0: neo.fs.v2.container.Container.version:type_name -> neo.fs.v2.refs.Version + 3, // 1: neo.fs.v2.container.Container.owner_id:type_name -> neo.fs.v2.refs.OwnerID + 1, // 2: neo.fs.v2.container.Container.attributes:type_name -> neo.fs.v2.container.Container.Attribute + 4, // 3: neo.fs.v2.container.Container.placement_policy:type_name -> neo.fs.v2.netmap.PlacementPolicy + 4, // [4:4] is the sub-list for method output_type + 4, // [4:4] is the sub-list for method input_type + 4, // [4:4] is the sub-list for extension type_name + 4, // [4:4] is the sub-list for extension extendee + 0, // [0:4] is the sub-list for field type_name +} + +func init() { file_container_grpc_types_proto_init() } +func file_container_grpc_types_proto_init() { + if File_container_grpc_types_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_container_grpc_types_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Container); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_container_grpc_types_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Container_Attribute); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_container_grpc_types_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_container_grpc_types_proto_goTypes, + DependencyIndexes: file_container_grpc_types_proto_depIdxs, + MessageInfos: file_container_grpc_types_proto_msgTypes, + }.Build() + File_container_grpc_types_proto = out.File + file_container_grpc_types_proto_rawDesc = nil + file_container_grpc_types_proto_goTypes = nil + file_container_grpc_types_proto_depIdxs = nil +} diff --git a/pkg/api/container/json.go b/pkg/api/container/json.go new file mode 100644 index 000000000..a6e411593 --- /dev/null +++ b/pkg/api/container/json.go @@ -0,0 +1,22 @@ +package container + +import ( + container "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/container/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/message" +) + +func (a *Attribute) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(a) +} + +func (a *Attribute) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(a, data, new(container.Container_Attribute)) +} + +func (c *Container) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(c) +} + +func (c *Container) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(c, data, new(container.Container)) +} diff --git a/pkg/api/container/marshal.go b/pkg/api/container/marshal.go new file mode 100644 index 000000000..111c1e02f --- /dev/null +++ b/pkg/api/container/marshal.go @@ -0,0 +1,546 @@ +package container + +import ( + container "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/container/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/message" + protoutil "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/util/proto" +) + +const ( + attributeKeyField = 1 + attributeValueField = 2 + + containerVersionField = 1 + containerOwnerField = 2 + containerNonceField = 3 + containerBasicACLField = 4 + containerAttributesField = 5 + containerPlacementField = 6 + + putReqBodyContainerField = 1 + putReqBodySignatureField = 2 + + putRespBodyIDField = 1 + + deleteReqBodyIDField = 1 + deleteReqBodySignatureField = 2 + + getReqBodyIDField = 1 + + getRespBodyContainerField = 1 + getRespBodySignatureField = 2 + getRespBodyTokenField = 3 + + listReqBodyOwnerField = 1 + + listRespBodyIDsField = 1 + + setEACLReqBodyTableField = 1 + setEACLReqBodySignatureField = 2 + + getEACLReqBodyIDField = 1 + + getEACLRespBodyTableField = 1 + getEACLRespBodySignatureField = 2 + getEACLRespBodyTokenField = 3 + + usedSpaceAnnounceEpochField = 1 + usedSpaceAnnounceCIDField = 2 + usedSpaceAnnounceUsedSpaceField = 3 + + usedSpaceReqBodyAnnouncementsField = 1 +) + +func (a *Attribute) StableMarshal(buf []byte) []byte { + if a == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, a.StableSize()) + } + + var offset int + + offset += protoutil.StringMarshal(attributeKeyField, buf[offset:], a.key) + protoutil.StringMarshal(attributeValueField, buf[offset:], a.val) + + return buf +} + +func (a *Attribute) StableSize() (size int) { + if a == nil { + return 0 + } + + size += protoutil.StringSize(attributeKeyField, a.key) + size += protoutil.StringSize(attributeValueField, a.val) + + return size +} + +func (a *Attribute) Unmarshal(data []byte) error { + return message.Unmarshal(a, data, new(container.Container_Attribute)) +} + +func (c *Container) StableMarshal(buf []byte) []byte { + if c == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, c.StableSize()) + } + + var offset int + + offset += protoutil.NestedStructureMarshal(containerVersionField, buf[offset:], c.version) + offset += protoutil.NestedStructureMarshal(containerOwnerField, buf[offset:], c.ownerID) + offset += protoutil.BytesMarshal(containerNonceField, buf[offset:], c.nonce) + offset += protoutil.UInt32Marshal(containerBasicACLField, buf[offset:], c.basicACL) + + for i := range c.attr { + offset += protoutil.NestedStructureMarshal(containerAttributesField, buf[offset:], &c.attr[i]) + } + + protoutil.NestedStructureMarshal(containerPlacementField, buf[offset:], c.policy) + + return buf +} + +func (c *Container) StableSize() (size int) { + if c == nil { + return 0 + } + + size += protoutil.NestedStructureSize(containerVersionField, c.version) + size += protoutil.NestedStructureSize(containerOwnerField, c.ownerID) + size += protoutil.BytesSize(containerNonceField, c.nonce) + size += protoutil.UInt32Size(containerBasicACLField, c.basicACL) + + for i := range c.attr { + size += protoutil.NestedStructureSize(containerAttributesField, &c.attr[i]) + } + + size += protoutil.NestedStructureSize(containerPlacementField, c.policy) + + return size +} + +func (c *Container) Unmarshal(data []byte) error { + return message.Unmarshal(c, data, new(container.Container)) +} + +func (r *PutRequestBody) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + var offset int + + offset += protoutil.NestedStructureMarshal(putReqBodyContainerField, buf[offset:], r.cnr) + protoutil.NestedStructureMarshal(putReqBodySignatureField, buf[offset:], r.sig) + + return buf +} + +func (r *PutRequestBody) StableSize() (size int) { + if r == nil { + return 0 + } + + size += protoutil.NestedStructureSize(putReqBodyContainerField, r.cnr) + size += protoutil.NestedStructureSize(putReqBodySignatureField, r.sig) + + return size +} + +func (r *PutRequestBody) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(container.PutRequest_Body)) +} + +func (r *PutResponseBody) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + protoutil.NestedStructureMarshal(putRespBodyIDField, buf, r.cid) + + return buf +} + +func (r *PutResponseBody) StableSize() (size int) { + if r == nil { + return 0 + } + + size += protoutil.NestedStructureSize(putRespBodyIDField, r.cid) + + return size +} + +func (r *PutResponseBody) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(container.PutResponse_Body)) +} + +func (r *DeleteRequestBody) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + var offset int + + offset += protoutil.NestedStructureMarshal(deleteReqBodyIDField, buf[offset:], r.cid) + protoutil.NestedStructureMarshal(deleteReqBodySignatureField, buf[offset:], r.sig) + + return buf +} + +func (r *DeleteRequestBody) StableSize() (size int) { + if r == nil { + return 0 + } + + size += protoutil.NestedStructureSize(deleteReqBodyIDField, r.cid) + size += protoutil.NestedStructureSize(deleteReqBodySignatureField, r.sig) + + return size +} + +func (r *DeleteRequestBody) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(container.DeleteRequest_Body)) +} + +func (r *DeleteResponseBody) StableMarshal(_ []byte) []byte { + return nil +} + +func (r *DeleteResponseBody) StableSize() (size int) { + return 0 +} + +func (r *DeleteResponseBody) Unmarshal([]byte) error { + return nil +} + +func (r *GetRequestBody) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + protoutil.NestedStructureMarshal(getReqBodyIDField, buf, r.cid) + + return buf +} + +func (r *GetRequestBody) StableSize() (size int) { + if r == nil { + return 0 + } + + size += protoutil.NestedStructureSize(getReqBodyIDField, r.cid) + + return size +} + +func (r *GetRequestBody) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(container.GetRequest_Body)) +} + +func (r *GetResponseBody) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + var offset int + + offset += protoutil.NestedStructureMarshal(getRespBodyContainerField, buf, r.cnr) + offset += protoutil.NestedStructureMarshal(getRespBodySignatureField, buf[offset:], r.sig) + protoutil.NestedStructureMarshal(getRespBodyTokenField, buf[offset:], r.token) + + return buf +} + +func (r *GetResponseBody) StableSize() (size int) { + if r == nil { + return 0 + } + + size += protoutil.NestedStructureSize(getRespBodyContainerField, r.cnr) + size += protoutil.NestedStructureSize(getRespBodySignatureField, r.sig) + size += protoutil.NestedStructureSize(getRespBodyTokenField, r.token) + + return size +} + +func (r *GetResponseBody) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(container.GetResponse_Body)) +} + +func (r *ListRequestBody) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + protoutil.NestedStructureMarshal(listReqBodyOwnerField, buf, r.ownerID) + + return buf +} + +func (r *ListRequestBody) StableSize() (size int) { + if r == nil { + return 0 + } + + size += protoutil.NestedStructureSize(listReqBodyOwnerField, r.ownerID) + + return size +} + +func (r *ListRequestBody) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(container.ListRequest_Body)) +} + +func (r *ListResponseBody) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + var offset int + + for i := range r.cidList { + offset += protoutil.NestedStructureMarshal(listRespBodyIDsField, buf[offset:], &r.cidList[i]) + } + + return buf +} + +func (r *ListResponseBody) StableSize() (size int) { + if r == nil { + return 0 + } + + for i := range r.cidList { + size += protoutil.NestedStructureSize(listRespBodyIDsField, &r.cidList[i]) + } + + return size +} + +func (r *ListResponseBody) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(container.ListResponse_Body)) +} + +func (r *SetExtendedACLRequestBody) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + var offset int + + offset += protoutil.NestedStructureMarshal(setEACLReqBodyTableField, buf[offset:], r.eacl) + protoutil.NestedStructureMarshal(setEACLReqBodySignatureField, buf[offset:], r.sig) + + return buf +} + +func (r *SetExtendedACLRequestBody) StableSize() (size int) { + if r == nil { + return 0 + } + + size += protoutil.NestedStructureSize(setEACLReqBodyTableField, r.eacl) + size += protoutil.NestedStructureSize(setEACLReqBodySignatureField, r.sig) + + return size +} + +func (r *SetExtendedACLRequestBody) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(container.SetExtendedACLRequest_Body)) +} + +func (r *SetExtendedACLResponseBody) StableMarshal(_ []byte) []byte { + return nil +} + +func (r *SetExtendedACLResponseBody) StableSize() (size int) { + return 0 +} + +func (r *SetExtendedACLResponseBody) Unmarshal([]byte) error { + return nil +} + +func (r *GetExtendedACLRequestBody) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + protoutil.NestedStructureMarshal(getEACLReqBodyIDField, buf, r.cid) + + return buf +} + +func (r *GetExtendedACLRequestBody) StableSize() (size int) { + if r == nil { + return 0 + } + + size += protoutil.NestedStructureSize(getEACLReqBodyIDField, r.cid) + + return size +} + +func (r *GetExtendedACLRequestBody) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(container.GetExtendedACLRequest_Body)) +} + +func (r *GetExtendedACLResponseBody) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + var offset int + + offset += protoutil.NestedStructureMarshal(getEACLRespBodyTableField, buf[offset:], r.eacl) + offset += protoutil.NestedStructureMarshal(getEACLRespBodySignatureField, buf[offset:], r.sig) + protoutil.NestedStructureMarshal(getEACLRespBodyTokenField, buf[offset:], r.token) + + return buf +} + +func (r *GetExtendedACLResponseBody) StableSize() (size int) { + if r == nil { + return 0 + } + + size += protoutil.NestedStructureSize(getEACLRespBodyTableField, r.eacl) + size += protoutil.NestedStructureSize(getEACLRespBodySignatureField, r.sig) + size += protoutil.NestedStructureSize(getEACLRespBodyTokenField, r.token) + + return size +} + +func (r *GetExtendedACLResponseBody) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(container.GetExtendedACLResponse_Body)) +} + +func (a *UsedSpaceAnnouncement) StableMarshal(buf []byte) []byte { + if a == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, a.StableSize()) + } + + var offset int + + offset += protoutil.UInt64Marshal(usedSpaceAnnounceEpochField, buf[offset:], a.epoch) + offset += protoutil.NestedStructureMarshal(usedSpaceAnnounceCIDField, buf[offset:], a.cid) + protoutil.UInt64Marshal(usedSpaceAnnounceUsedSpaceField, buf[offset:], a.usedSpace) + + return buf +} + +func (a *UsedSpaceAnnouncement) StableSize() (size int) { + if a == nil { + return 0 + } + + size += protoutil.UInt64Size(usedSpaceAnnounceEpochField, a.epoch) + size += protoutil.NestedStructureSize(usedSpaceAnnounceCIDField, a.cid) + size += protoutil.UInt64Size(usedSpaceAnnounceUsedSpaceField, a.usedSpace) + + return size +} + +func (a *UsedSpaceAnnouncement) Unmarshal(data []byte) error { + return message.Unmarshal(a, data, new(container.AnnounceUsedSpaceRequest_Body_Announcement)) +} + +func (r *AnnounceUsedSpaceRequestBody) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + var offset int + + for i := range r.announcements { + offset += protoutil.NestedStructureMarshal(usedSpaceReqBodyAnnouncementsField, buf[offset:], &r.announcements[i]) + } + + return buf +} + +func (r *AnnounceUsedSpaceRequestBody) StableSize() (size int) { + if r == nil { + return 0 + } + + for i := range r.announcements { + size += protoutil.NestedStructureSize(usedSpaceReqBodyAnnouncementsField, &r.announcements[i]) + } + + return size +} + +func (r *AnnounceUsedSpaceRequestBody) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(container.AnnounceUsedSpaceRequest_Body)) +} + +func (r *AnnounceUsedSpaceResponseBody) StableMarshal(_ []byte) []byte { + return nil +} + +func (r *AnnounceUsedSpaceResponseBody) StableSize() (size int) { + return 0 +} + +func (r *AnnounceUsedSpaceResponseBody) Unmarshal([]byte) error { + return nil +} diff --git a/pkg/api/container/message_test.go b/pkg/api/container/message_test.go new file mode 100644 index 000000000..c028cdabc --- /dev/null +++ b/pkg/api/container/message_test.go @@ -0,0 +1,47 @@ +package container_test + +import ( + "testing" + + containertest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/container/test" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/message" + messagetest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/message/test" +) + +func TestMessageConvert(t *testing.T) { + messagetest.TestRPCMessage(t, + func(empty bool) message.Message { return containertest.GenerateAttribute(empty) }, + func(empty bool) message.Message { return containertest.GenerateContainer(empty) }, + func(empty bool) message.Message { return containertest.GeneratePutRequestBody(empty) }, + func(empty bool) message.Message { return containertest.GeneratePutRequest(empty) }, + func(empty bool) message.Message { return containertest.GeneratePutResponseBody(empty) }, + func(empty bool) message.Message { return containertest.GeneratePutResponse(empty) }, + func(empty bool) message.Message { return containertest.GenerateGetRequestBody(empty) }, + func(empty bool) message.Message { return containertest.GenerateGetRequest(empty) }, + func(empty bool) message.Message { return containertest.GenerateGetResponseBody(empty) }, + func(empty bool) message.Message { return containertest.GenerateGetResponse(empty) }, + func(empty bool) message.Message { return containertest.GenerateDeleteRequestBody(empty) }, + func(empty bool) message.Message { return containertest.GenerateDeleteRequest(empty) }, + func(empty bool) message.Message { return containertest.GenerateDeleteResponseBody(empty) }, + func(empty bool) message.Message { return containertest.GenerateDeleteResponse(empty) }, + func(empty bool) message.Message { return containertest.GenerateListRequestBody(empty) }, + func(empty bool) message.Message { return containertest.GenerateListRequest(empty) }, + func(empty bool) message.Message { return containertest.GenerateListResponseBody(empty) }, + func(empty bool) message.Message { return containertest.GenerateListResponse(empty) }, + func(empty bool) message.Message { return containertest.GenerateSetExtendedACLRequestBody(empty) }, + func(empty bool) message.Message { return containertest.GenerateSetExtendedACLRequest(empty) }, + func(empty bool) message.Message { return containertest.GenerateGetRequestBody(empty) }, + func(empty bool) message.Message { return containertest.GenerateGetRequest(empty) }, + func(empty bool) message.Message { return containertest.GenerateGetResponseBody(empty) }, + func(empty bool) message.Message { return containertest.GenerateGetResponse(empty) }, + func(empty bool) message.Message { return containertest.GenerateGetExtendedACLRequestBody(empty) }, + func(empty bool) message.Message { return containertest.GenerateGetExtendedACLRequest(empty) }, + func(empty bool) message.Message { return containertest.GenerateGetExtendedACLResponseBody(empty) }, + func(empty bool) message.Message { return containertest.GenerateGetExtendedACLResponse(empty) }, + func(empty bool) message.Message { return containertest.GenerateUsedSpaceAnnouncement(empty) }, + func(empty bool) message.Message { return containertest.GenerateAnnounceUsedSpaceRequestBody(empty) }, + func(empty bool) message.Message { return containertest.GenerateAnnounceUsedSpaceRequest(empty) }, + func(empty bool) message.Message { return containertest.GenerateAnnounceUsedSpaceResponseBody(empty) }, + func(empty bool) message.Message { return containertest.GenerateAnnounceUsedSpaceResponse(empty) }, + ) +} diff --git a/pkg/api/container/status.go b/pkg/api/container/status.go new file mode 100644 index 000000000..bfb655e0a --- /dev/null +++ b/pkg/api/container/status.go @@ -0,0 +1,33 @@ +package container + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/status" + statusgrpc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/status/grpc" +) + +// LocalizeFailStatus checks if passed global status.Code is related to container failure and: +// +// then localizes the code and returns true, +// else leaves the code unchanged and returns false. +// +// Arg must not be nil. +func LocalizeFailStatus(c *status.Code) bool { + return status.LocalizeIfInSection(c, uint32(statusgrpc.Section_SECTION_CONTAINER)) +} + +// GlobalizeFail globalizes local code of container failure. +// +// Arg must not be nil. +func GlobalizeFail(c *status.Code) { + c.GlobalizeSection(uint32(statusgrpc.Section_SECTION_CONTAINER)) +} + +const ( + // StatusNotFound is a local status.Code value for + // CONTAINER_NOT_FOUND container failure. + StatusNotFound status.Code = iota + + // StatusEACLNotFound is a local status.Code value for + // EACL_NOT_FOUND failure. + StatusEACLNotFound +) diff --git a/pkg/api/container/status_test.go b/pkg/api/container/status_test.go new file mode 100644 index 000000000..974b7655c --- /dev/null +++ b/pkg/api/container/status_test.go @@ -0,0 +1,15 @@ +package container_test + +import ( + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/container" + statustest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/status/test" +) + +func TestStatusCodes(t *testing.T) { + statustest.TestCodes(t, container.LocalizeFailStatus, container.GlobalizeFail, + container.StatusNotFound, 3072, + container.StatusEACLNotFound, 3073, + ) +} diff --git a/pkg/api/container/test/generate.go b/pkg/api/container/test/generate.go new file mode 100644 index 000000000..c205b4ec1 --- /dev/null +++ b/pkg/api/container/test/generate.go @@ -0,0 +1,396 @@ +package containertest + +import ( + acltest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/acl/test" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/container" + netmaptest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/netmap/test" + refstest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs/test" + sessiontest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session/test" +) + +func GenerateAttribute(empty bool) *container.Attribute { + m := new(container.Attribute) + + if !empty { + m.SetKey("key") + m.SetValue("val") + } + + return m +} + +func GenerateAttributes(empty bool) []container.Attribute { + var res []container.Attribute + + if !empty { + res = append(res, + *GenerateAttribute(false), + *GenerateAttribute(false), + ) + } + + return res +} + +func GenerateContainer(empty bool) *container.Container { + m := new(container.Container) + + if !empty { + m.SetBasicACL(12) + m.SetNonce([]byte{1, 2, 3}) + m.SetOwnerID(refstest.GenerateOwnerID(false)) + m.SetAttributes(GenerateAttributes(false)) + m.SetPlacementPolicy(netmaptest.GeneratePlacementPolicy(false)) + } + + m.SetVersion(refstest.GenerateVersion(empty)) + + return m +} + +func GeneratePutRequestBody(empty bool) *container.PutRequestBody { + m := new(container.PutRequestBody) + + if !empty { + m.SetContainer(GenerateContainer(false)) + } + + m.SetSignature(refstest.GenerateSignature(empty)) + + return m +} + +func GeneratePutRequest(empty bool) *container.PutRequest { + m := new(container.PutRequest) + + if !empty { + m.SetBody(GeneratePutRequestBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateRequestMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateRequestVerificationHeader(empty)) + + return m +} + +func GeneratePutResponseBody(empty bool) *container.PutResponseBody { + m := new(container.PutResponseBody) + + if !empty { + m.SetContainerID(refstest.GenerateContainerID(false)) + } + + return m +} + +func GeneratePutResponse(empty bool) *container.PutResponse { + m := new(container.PutResponse) + + if !empty { + m.SetBody(GeneratePutResponseBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateResponseMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateResponseVerificationHeader(empty)) + + return m +} + +func GenerateGetRequestBody(empty bool) *container.GetRequestBody { + m := new(container.GetRequestBody) + + if !empty { + m.SetContainerID(refstest.GenerateContainerID(false)) + } + + return m +} + +func GenerateGetRequest(empty bool) *container.GetRequest { + m := new(container.GetRequest) + + if !empty { + m.SetBody(GenerateGetRequestBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateRequestMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateRequestVerificationHeader(empty)) + + return m +} + +func GenerateGetResponseBody(empty bool) *container.GetResponseBody { + m := new(container.GetResponseBody) + + if !empty { + m.SetContainer(GenerateContainer(false)) + } + + m.SetSignature(refstest.GenerateSignature(empty)) + m.SetSessionToken(sessiontest.GenerateSessionToken(empty)) + + return m +} + +func GenerateGetResponse(empty bool) *container.GetResponse { + m := new(container.GetResponse) + + if !empty { + m.SetBody(GenerateGetResponseBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateResponseMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateResponseVerificationHeader(empty)) + + return m +} + +func GenerateDeleteRequestBody(empty bool) *container.DeleteRequestBody { + m := new(container.DeleteRequestBody) + + if !empty { + m.SetContainerID(refstest.GenerateContainerID(false)) + } + + m.SetSignature(refstest.GenerateSignature(empty)) + + return m +} + +func GenerateDeleteRequest(empty bool) *container.DeleteRequest { + m := new(container.DeleteRequest) + + if !empty { + m.SetBody(GenerateDeleteRequestBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateRequestMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateRequestVerificationHeader(empty)) + + return m +} + +func GenerateDeleteResponseBody(_ bool) *container.DeleteResponseBody { + m := new(container.DeleteResponseBody) + + return m +} + +func GenerateDeleteResponse(empty bool) *container.DeleteResponse { + m := new(container.DeleteResponse) + + if !empty { + m.SetBody(GenerateDeleteResponseBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateResponseMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateResponseVerificationHeader(empty)) + + return m +} + +func GenerateListRequestBody(empty bool) *container.ListRequestBody { + m := new(container.ListRequestBody) + + if !empty { + m.SetOwnerID(refstest.GenerateOwnerID(false)) + } + + return m +} + +func GenerateListRequest(empty bool) *container.ListRequest { + m := new(container.ListRequest) + + if !empty { + m.SetBody(GenerateListRequestBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateRequestMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateRequestVerificationHeader(empty)) + + return m +} + +func GenerateListResponseBody(empty bool) *container.ListResponseBody { + m := new(container.ListResponseBody) + + if !empty { + m.SetContainerIDs(refstest.GenerateContainerIDs(false)) + } + + return m +} + +func GenerateListResponse(empty bool) *container.ListResponse { + m := new(container.ListResponse) + + if !empty { + m.SetBody(GenerateListResponseBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateResponseMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateResponseVerificationHeader(empty)) + + return m +} + +func GenerateSetExtendedACLRequestBody(empty bool) *container.SetExtendedACLRequestBody { + m := new(container.SetExtendedACLRequestBody) + + if !empty { + m.SetEACL(acltest.GenerateTable(false)) + } + + m.SetSignature(refstest.GenerateSignature(empty)) + + return m +} + +func GenerateSetExtendedACLRequest(empty bool) *container.SetExtendedACLRequest { + m := new(container.SetExtendedACLRequest) + + if !empty { + m.SetBody(GenerateSetExtendedACLRequestBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateRequestMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateRequestVerificationHeader(empty)) + + return m +} + +func GenerateSetExtendedACLResponseBody(_ bool) *container.SetExtendedACLResponseBody { + m := new(container.SetExtendedACLResponseBody) + + return m +} + +func GenerateSetExtendedACLResponse(empty bool) *container.SetExtendedACLResponse { + m := new(container.SetExtendedACLResponse) + + if !empty { + m.SetBody(GenerateSetExtendedACLResponseBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateResponseMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateResponseVerificationHeader(empty)) + + return m +} + +func GenerateGetExtendedACLRequestBody(empty bool) *container.GetExtendedACLRequestBody { + m := new(container.GetExtendedACLRequestBody) + + if !empty { + m.SetContainerID(refstest.GenerateContainerID(false)) + } + + return m +} + +func GenerateGetExtendedACLRequest(empty bool) *container.GetExtendedACLRequest { + m := new(container.GetExtendedACLRequest) + + if !empty { + m.SetBody(GenerateGetExtendedACLRequestBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateRequestMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateRequestVerificationHeader(empty)) + + return m +} + +func GenerateGetExtendedACLResponseBody(empty bool) *container.GetExtendedACLResponseBody { + m := new(container.GetExtendedACLResponseBody) + + if !empty { + m.SetEACL(acltest.GenerateTable(false)) + } + + m.SetSignature(refstest.GenerateSignature(empty)) + m.SetSessionToken(sessiontest.GenerateSessionToken(empty)) + + return m +} + +func GenerateGetExtendedACLResponse(empty bool) *container.GetExtendedACLResponse { + m := new(container.GetExtendedACLResponse) + + if !empty { + m.SetBody(GenerateGetExtendedACLResponseBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateResponseMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateResponseVerificationHeader(empty)) + + return m +} + +func GenerateUsedSpaceAnnouncement(empty bool) *container.UsedSpaceAnnouncement { + m := new(container.UsedSpaceAnnouncement) + + if !empty { + m.SetContainerID(refstest.GenerateContainerID(false)) + m.SetEpoch(1) + m.SetUsedSpace(2) + } + + return m +} + +func GenerateUsedSpaceAnnouncements(empty bool) []container.UsedSpaceAnnouncement { + var res []container.UsedSpaceAnnouncement + + if !empty { + res = append(res, + *GenerateUsedSpaceAnnouncement(false), + *GenerateUsedSpaceAnnouncement(false), + ) + } + + return res +} + +func GenerateAnnounceUsedSpaceRequestBody(empty bool) *container.AnnounceUsedSpaceRequestBody { + m := new(container.AnnounceUsedSpaceRequestBody) + + if !empty { + m.SetAnnouncements(GenerateUsedSpaceAnnouncements(false)) + } + + return m +} + +func GenerateAnnounceUsedSpaceRequest(empty bool) *container.AnnounceUsedSpaceRequest { + m := new(container.AnnounceUsedSpaceRequest) + + if !empty { + m.SetBody(GenerateAnnounceUsedSpaceRequestBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateRequestMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateRequestVerificationHeader(empty)) + + return m +} + +func GenerateAnnounceUsedSpaceResponseBody(_ bool) *container.AnnounceUsedSpaceResponseBody { + m := new(container.AnnounceUsedSpaceResponseBody) + + return m +} + +func GenerateAnnounceUsedSpaceResponse(empty bool) *container.AnnounceUsedSpaceResponse { + m := new(container.AnnounceUsedSpaceResponse) + + if !empty { + m.SetBody(GenerateAnnounceUsedSpaceResponseBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateResponseMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateResponseVerificationHeader(empty)) + + return m +} diff --git a/pkg/api/container/types.go b/pkg/api/container/types.go new file mode 100644 index 000000000..863c7d1d1 --- /dev/null +++ b/pkg/api/container/types.go @@ -0,0 +1,717 @@ +package container + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/acl" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" +) + +type Attribute struct { + key, val string +} + +type Container struct { + version *refs.Version + + ownerID *refs.OwnerID + + nonce []byte + + basicACL uint32 + + attr []Attribute + + policy *netmap.PlacementPolicy +} + +type PutRequestBody struct { + cnr *Container + + sig *refs.Signature +} +type PutRequest struct { + body *PutRequestBody + + session.RequestHeaders +} + +type PutResponseBody struct { + cid *refs.ContainerID +} + +type PutResponse struct { + body *PutResponseBody + + session.ResponseHeaders +} + +type GetRequestBody struct { + cid *refs.ContainerID +} + +type GetRequest struct { + body *GetRequestBody + + session.RequestHeaders +} + +type GetResponseBody struct { + cnr *Container + + token *session.Token + + sig *refs.Signature +} + +type GetResponse struct { + body *GetResponseBody + + session.ResponseHeaders +} + +type DeleteRequestBody struct { + cid *refs.ContainerID + + sig *refs.Signature +} + +type DeleteRequest struct { + body *DeleteRequestBody + + session.RequestHeaders +} + +type DeleteResponseBody struct{} + +type DeleteResponse struct { + body *DeleteResponseBody + + session.ResponseHeaders +} + +type ListRequestBody struct { + ownerID *refs.OwnerID +} + +type ListRequest struct { + body *ListRequestBody + + session.RequestHeaders +} + +type ListResponseBody struct { + cidList []refs.ContainerID +} + +type ListResponse struct { + body *ListResponseBody + + session.ResponseHeaders +} + +type SetExtendedACLRequestBody struct { + eacl *acl.Table + + sig *refs.Signature +} + +type SetExtendedACLRequest struct { + body *SetExtendedACLRequestBody + + session.RequestHeaders +} + +type SetExtendedACLResponseBody struct{} + +type SetExtendedACLResponse struct { + body *SetExtendedACLResponseBody + + session.ResponseHeaders +} + +type GetExtendedACLRequestBody struct { + cid *refs.ContainerID +} + +type GetExtendedACLRequest struct { + body *GetExtendedACLRequestBody + + session.RequestHeaders +} + +type GetExtendedACLResponseBody struct { + eacl *acl.Table + + sig *refs.Signature + + token *session.Token +} + +type GetExtendedACLResponse struct { + body *GetExtendedACLResponseBody + + session.ResponseHeaders +} + +type UsedSpaceAnnouncement struct { + epoch uint64 + + cid *refs.ContainerID + + usedSpace uint64 +} + +type AnnounceUsedSpaceRequestBody struct { + announcements []UsedSpaceAnnouncement +} + +type AnnounceUsedSpaceRequest struct { + body *AnnounceUsedSpaceRequestBody + + session.RequestHeaders +} + +type AnnounceUsedSpaceResponseBody struct{} + +type AnnounceUsedSpaceResponse struct { + body *AnnounceUsedSpaceResponseBody + + session.ResponseHeaders +} + +func (a *Attribute) GetKey() string { + if a != nil { + return a.key + } + + return "" +} + +func (a *Attribute) SetKey(v string) { + a.key = v +} + +func (a *Attribute) GetValue() string { + if a != nil { + return a.val + } + + return "" +} + +func (a *Attribute) SetValue(v string) { + a.val = v +} + +func (c *Container) GetVersion() *refs.Version { + if c != nil { + return c.version + } + + return nil +} + +func (c *Container) SetVersion(v *refs.Version) { + c.version = v +} + +func (c *Container) GetOwnerID() *refs.OwnerID { + if c != nil { + return c.ownerID + } + + return nil +} + +func (c *Container) SetOwnerID(v *refs.OwnerID) { + c.ownerID = v +} + +func (c *Container) GetNonce() []byte { + if c != nil { + return c.nonce + } + + return nil +} + +func (c *Container) SetNonce(v []byte) { + c.nonce = v +} + +func (c *Container) GetBasicACL() uint32 { + if c != nil { + return c.basicACL + } + + return 0 +} + +func (c *Container) SetBasicACL(v uint32) { + c.basicACL = v +} + +func (c *Container) GetAttributes() []Attribute { + if c != nil { + return c.attr + } + + return nil +} + +func (c *Container) SetAttributes(v []Attribute) { + c.attr = v +} + +func (c *Container) GetPlacementPolicy() *netmap.PlacementPolicy { + if c != nil { + return c.policy + } + + return nil +} + +func (c *Container) SetPlacementPolicy(v *netmap.PlacementPolicy) { + c.policy = v +} + +func (r *PutRequestBody) GetContainer() *Container { + if r != nil { + return r.cnr + } + + return nil +} + +func (r *PutRequestBody) SetContainer(v *Container) { + r.cnr = v +} + +func (r *PutRequestBody) GetSignature() *refs.Signature { + if r != nil { + return r.sig + } + + return nil +} + +func (r *PutRequestBody) SetSignature(v *refs.Signature) { + // TODO: (neofs-api-go#381) avoid this hack (e.g. create refs.SignatureRFC6979 type) + v.SetScheme(0) + r.sig = v +} + +func (r *PutRequest) GetBody() *PutRequestBody { + if r != nil { + return r.body + } + + return nil +} + +func (r *PutRequest) SetBody(v *PutRequestBody) { + r.body = v +} + +func (r *PutResponseBody) GetContainerID() *refs.ContainerID { + if r != nil { + return r.cid + } + + return nil +} + +func (r *PutResponseBody) SetContainerID(v *refs.ContainerID) { + r.cid = v +} + +func (r *PutResponse) GetBody() *PutResponseBody { + if r != nil { + return r.body + } + + return nil +} + +func (r *PutResponse) SetBody(v *PutResponseBody) { + r.body = v +} + +func (r *GetRequestBody) GetContainerID() *refs.ContainerID { + if r != nil { + return r.cid + } + + return nil +} + +func (r *GetRequestBody) SetContainerID(v *refs.ContainerID) { + r.cid = v +} + +func (r *GetRequest) GetBody() *GetRequestBody { + if r != nil { + return r.body + } + + return nil +} + +func (r *GetRequest) SetBody(v *GetRequestBody) { + r.body = v +} + +func (r *GetResponseBody) GetContainer() *Container { + if r != nil { + return r.cnr + } + + return nil +} + +func (r *GetResponseBody) SetContainer(v *Container) { + r.cnr = v +} + +// GetSessionToken returns token of the session within which requested +// container was created. +func (r *GetResponseBody) GetSessionToken() *session.Token { + if r != nil { + return r.token + } + + return nil +} + +// SetSessionToken sets token of the session within which requested +// container was created. +func (r *GetResponseBody) SetSessionToken(v *session.Token) { + r.token = v +} + +// GetSignature returns signature of the requested container. +func (r *GetResponseBody) GetSignature() *refs.Signature { + if r != nil { + return r.sig + } + + return nil +} + +// SetSignature sets signature of the requested container. +func (r *GetResponseBody) SetSignature(v *refs.Signature) { + // TODO: (neofs-api-go#381) avoid this hack (e.g. create refs.SignatureRFC6979 type) + v.SetScheme(0) + r.sig = v +} + +func (r *GetResponse) GetBody() *GetResponseBody { + if r != nil { + return r.body + } + + return nil +} + +func (r *GetResponse) SetBody(v *GetResponseBody) { + r.body = v +} + +func (r *DeleteRequestBody) GetContainerID() *refs.ContainerID { + if r != nil { + return r.cid + } + + return nil +} + +func (r *DeleteRequestBody) SetContainerID(v *refs.ContainerID) { + r.cid = v +} + +func (r *DeleteRequestBody) GetSignature() *refs.Signature { + if r != nil { + return r.sig + } + + return nil +} + +func (r *DeleteRequestBody) SetSignature(v *refs.Signature) { + // TODO: (neofs-api-go#381) avoid this hack (e.g. create refs.SignatureRFC6979 type) + v.SetScheme(0) + r.sig = v +} + +func (r *DeleteRequest) GetBody() *DeleteRequestBody { + if r != nil { + return r.body + } + + return nil +} + +func (r *DeleteRequest) SetBody(v *DeleteRequestBody) { + r.body = v +} + +func (r *DeleteResponse) GetBody() *DeleteResponseBody { + if r != nil { + return r.body + } + + return nil +} + +func (r *DeleteResponse) SetBody(v *DeleteResponseBody) { + r.body = v +} + +func (r *ListRequestBody) GetOwnerID() *refs.OwnerID { + if r != nil { + return r.ownerID + } + + return nil +} + +func (r *ListRequestBody) SetOwnerID(v *refs.OwnerID) { + r.ownerID = v +} + +func (r *ListRequest) GetBody() *ListRequestBody { + if r != nil { + return r.body + } + + return nil +} + +func (r *ListRequest) SetBody(v *ListRequestBody) { + r.body = v +} + +func (r *ListResponseBody) GetContainerIDs() []refs.ContainerID { + if r != nil { + return r.cidList + } + + return nil +} + +func (r *ListResponseBody) SetContainerIDs(v []refs.ContainerID) { + r.cidList = v +} + +func (r *ListResponse) GetBody() *ListResponseBody { + if r != nil { + return r.body + } + + return nil +} + +func (r *ListResponse) SetBody(v *ListResponseBody) { + r.body = v +} + +func (r *SetExtendedACLRequestBody) GetEACL() *acl.Table { + if r != nil { + return r.eacl + } + + return nil +} + +func (r *SetExtendedACLRequestBody) SetEACL(v *acl.Table) { + r.eacl = v +} + +func (r *SetExtendedACLRequestBody) GetSignature() *refs.Signature { + if r != nil { + return r.sig + } + + return nil +} + +func (r *SetExtendedACLRequestBody) SetSignature(v *refs.Signature) { + // TODO: (neofs-api-go#381) avoid this hack (e.g. create refs.SignatureRFC6979 type) + v.SetScheme(0) + r.sig = v +} + +func (r *SetExtendedACLRequest) GetBody() *SetExtendedACLRequestBody { + if r != nil { + return r.body + } + + return nil +} + +func (r *SetExtendedACLRequest) SetBody(v *SetExtendedACLRequestBody) { + r.body = v +} + +func (r *SetExtendedACLResponse) GetBody() *SetExtendedACLResponseBody { + if r != nil { + return r.body + } + + return nil +} + +func (r *SetExtendedACLResponse) SetBody(v *SetExtendedACLResponseBody) { + r.body = v +} + +func (r *GetExtendedACLRequestBody) GetContainerID() *refs.ContainerID { + if r != nil { + return r.cid + } + + return nil +} + +func (r *GetExtendedACLRequestBody) SetContainerID(v *refs.ContainerID) { + r.cid = v +} + +func (r *GetExtendedACLRequest) GetBody() *GetExtendedACLRequestBody { + if r != nil { + return r.body + } + + return nil +} + +func (r *GetExtendedACLRequest) SetBody(v *GetExtendedACLRequestBody) { + r.body = v +} + +func (r *GetExtendedACLResponseBody) GetEACL() *acl.Table { + if r != nil { + return r.eacl + } + + return nil +} + +func (r *GetExtendedACLResponseBody) SetEACL(v *acl.Table) { + r.eacl = v +} + +func (r *GetExtendedACLResponseBody) GetSignature() *refs.Signature { + if r != nil { + return r.sig + } + + return nil +} + +func (r *GetExtendedACLResponseBody) SetSignature(v *refs.Signature) { + // TODO: (neofs-api-go#381) avoid this hack (e.g. create refs.SignatureRFC6979 type) + v.SetScheme(0) + r.sig = v +} + +// GetSessionToken returns token of the session within which requested +// eACL table was set. +func (r *GetExtendedACLResponseBody) GetSessionToken() *session.Token { + if r != nil { + return r.token + } + + return nil +} + +// SetSessionToken sets token of the session within which requested +// eACL table was set. +func (r *GetExtendedACLResponseBody) SetSessionToken(v *session.Token) { + r.token = v +} + +func (r *GetExtendedACLResponse) GetBody() *GetExtendedACLResponseBody { + if r != nil { + return r.body + } + + return nil +} + +func (r *GetExtendedACLResponse) SetBody(v *GetExtendedACLResponseBody) { + r.body = v +} + +func (a *UsedSpaceAnnouncement) GetEpoch() uint64 { + if a != nil { + return a.epoch + } + + return 0 +} + +func (a *UsedSpaceAnnouncement) SetEpoch(v uint64) { + a.epoch = v +} + +func (a *UsedSpaceAnnouncement) GetUsedSpace() uint64 { + if a != nil { + return a.usedSpace + } + + return 0 +} + +func (a *UsedSpaceAnnouncement) SetUsedSpace(v uint64) { + a.usedSpace = v +} + +func (a *UsedSpaceAnnouncement) GetContainerID() *refs.ContainerID { + if a != nil { + return a.cid + } + + return nil +} + +func (a *UsedSpaceAnnouncement) SetContainerID(v *refs.ContainerID) { + a.cid = v +} + +func (r *AnnounceUsedSpaceRequestBody) GetAnnouncements() []UsedSpaceAnnouncement { + if r != nil { + return r.announcements + } + + return nil +} + +func (r *AnnounceUsedSpaceRequestBody) SetAnnouncements(v []UsedSpaceAnnouncement) { + r.announcements = v +} + +func (r *AnnounceUsedSpaceRequest) GetBody() *AnnounceUsedSpaceRequestBody { + if r != nil { + return r.body + } + + return nil +} + +func (r *AnnounceUsedSpaceRequest) SetBody(v *AnnounceUsedSpaceRequestBody) { + r.body = v +} + +func (r *AnnounceUsedSpaceResponse) GetBody() *AnnounceUsedSpaceResponseBody { + if r != nil { + return r.body + } + + return nil +} + +func (r *AnnounceUsedSpaceResponse) SetBody(v *AnnounceUsedSpaceResponseBody) { + r.body = v +} diff --git a/pkg/api/docs/.gitkeep b/pkg/api/docs/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/pkg/api/docs/release-instruction.md b/pkg/api/docs/release-instruction.md new file mode 100644 index 000000000..4134f1cc3 --- /dev/null +++ b/pkg/api/docs/release-instruction.md @@ -0,0 +1,45 @@ +# Release instructions + +## Pre-release checks + +These should run successfully: +* `go test ./...`; +* `golangci-lint run ./...`; +* `go fmt ./...` (should not change any files); +* `go mog tidy` (should not change any files); +* `./prepare.sh /path/to/frostfs-api/on/your/machine` (should not change any files). + +## Writing changelog + +Add an entry to the `CHANGELOG.md` following the style established there. Add an +optional codename(for not patch releases), version and release date in the heading. +Write a paragraph describing the most significant changes done in this release. Add +`Fixed`, `Added`, `Removed` and `Updated` sections with fixed bug, new features and +other changes. + +Open Pull Request (must receive at least one approval) and merge this changes. + +## Update README + +Actualize compatibility table in `README.md` with relevant information. + +## Tag a release + +Use `vX.Y.Z` tag for releases and `vX.Y.Z-rc.N` for release candidates +following the [semantic versioning](https://semver.org/) standard. + +Update your local `master` branch after approved and merged `CHANGELOG.md` changes. +Tag a release (must be signed) and push it: + +``` +$ git tag -s vX.Y.Z[-rc.N] && git push origin vX.Y.Z[-rc.N] +``` + +## Make a Github release + +Using Github's web interface create a new release based on just created tag +with the same changes from changelog and publish it. + +## Close github milestone + +Close corresponding vX.Y.Z github milestone. diff --git a/pkg/api/go.mod b/pkg/api/go.mod new file mode 100644 index 000000000..b0829110a --- /dev/null +++ b/pkg/api/go.mod @@ -0,0 +1,26 @@ +module git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api + +go 1.20 + +require ( + git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 + github.com/stretchr/testify v1.8.3 + golang.org/x/sync v0.2.0 + google.golang.org/grpc v1.55.0 + google.golang.org/protobuf v1.33.0 +) + +require ( + git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/golang/protobuf v1.5.3 // indirect + github.com/kr/pretty v0.1.0 // indirect + github.com/mr-tron/base58 v1.2.0 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + golang.org/x/net v0.10.0 // indirect + golang.org/x/sys v0.8.0 // indirect + golang.org/x/text v0.9.0 // indirect + google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect + gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/pkg/api/go.sum b/pkg/api/go.sum new file mode 100644 index 000000000..56fc5d087 --- /dev/null +++ b/pkg/api/go.sum @@ -0,0 +1,48 @@ +git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSVCB8JNSfPG7Uk4r2oSk= +git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0/go.mod h1:RUIKZATQLJ+TaYQa60X2fTDwfuhMfm8Ar60bQ5fr+vU= +git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 h1:M2KR3iBj7WpY3hP10IevfIB9MURr4O9mwVfJ+SjT3HA= +git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0/go.mod h1:okpbKfVYf/BpejtfFTfhZqFP+sZ8rsHrP8Rr/jYPNRc= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= +github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI= +golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A= +google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= +google.golang.org/grpc v1.55.0 h1:3Oj82/tFSCeUrRTg/5E/7d/W5A1tj6Ky1ABAuZuv5ag= +google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/pkg/api/lock/grpc/types.go b/pkg/api/lock/grpc/types.go new file mode 100644 index 000000000..a01819c2b --- /dev/null +++ b/pkg/api/lock/grpc/types.go @@ -0,0 +1,8 @@ +package lock + +import refs "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs/grpc" + +// SetMembers sets `members` field. +func (x *Lock) SetMembers(ids []*refs.ObjectID) { + x.Members = ids +} diff --git a/pkg/api/lock/grpc/types.pb.go b/pkg/api/lock/grpc/types.pb.go new file mode 100644 index 000000000..20d00ed13 --- /dev/null +++ b/pkg/api/lock/grpc/types.pb.go @@ -0,0 +1,160 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.33.0 +// protoc v4.25.3 +// source: lock/grpc/types.proto + +package lock + +import ( + grpc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs/grpc" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// Lock objects protects a list of objects from being deleted. The lifetime of a +// lock object is limited similar to regular objects in +// `__SYSTEM__EXPIRATION_EPOCH` (`__NEOFS__EXPIRATION_EPOCH` is deprecated) +// attribute. Lock object MUST have expiration epoch. It is impossible to delete +// a lock object via ObjectService.Delete RPC call. +type Lock struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // List of objects to lock. Must not be empty or carry empty IDs. + // All members must be of the `REGULAR` type. + Members []*grpc.ObjectID `protobuf:"bytes,1,rep,name=members,proto3" json:"members,omitempty"` +} + +func (x *Lock) Reset() { + *x = Lock{} + if protoimpl.UnsafeEnabled { + mi := &file_lock_grpc_types_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Lock) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Lock) ProtoMessage() {} + +func (x *Lock) ProtoReflect() protoreflect.Message { + mi := &file_lock_grpc_types_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Lock.ProtoReflect.Descriptor instead. +func (*Lock) Descriptor() ([]byte, []int) { + return file_lock_grpc_types_proto_rawDescGZIP(), []int{0} +} + +func (x *Lock) GetMembers() []*grpc.ObjectID { + if x != nil { + return x.Members + } + return nil +} + +var File_lock_grpc_types_proto protoreflect.FileDescriptor + +var file_lock_grpc_types_proto_rawDesc = []byte{ + 0x0a, 0x15, 0x6c, 0x6f, 0x63, 0x6b, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x74, 0x79, 0x70, 0x65, + 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, + 0x76, 0x32, 0x2e, 0x6c, 0x6f, 0x63, 0x6b, 0x1a, 0x15, 0x72, 0x65, 0x66, 0x73, 0x2f, 0x67, 0x72, + 0x70, 0x63, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x3a, + 0x0a, 0x04, 0x4c, 0x6f, 0x63, 0x6b, 0x12, 0x32, 0x0a, 0x07, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, + 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, + 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x65, 0x66, 0x73, 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, + 0x44, 0x52, 0x07, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x42, 0x5b, 0x5a, 0x3e, 0x67, 0x69, + 0x74, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, + 0x72, 0x75, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x4c, 0x61, 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, + 0x74, 0x66, 0x73, 0x2d, 0x61, 0x70, 0x69, 0x2d, 0x67, 0x6f, 0x2f, 0x76, 0x32, 0x2f, 0x6c, 0x6f, + 0x63, 0x6b, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x3b, 0x6c, 0x6f, 0x63, 0x6b, 0xaa, 0x02, 0x18, 0x4e, + 0x65, 0x6f, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x41, + 0x50, 0x49, 0x2e, 0x4c, 0x6f, 0x63, 0x6b, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_lock_grpc_types_proto_rawDescOnce sync.Once + file_lock_grpc_types_proto_rawDescData = file_lock_grpc_types_proto_rawDesc +) + +func file_lock_grpc_types_proto_rawDescGZIP() []byte { + file_lock_grpc_types_proto_rawDescOnce.Do(func() { + file_lock_grpc_types_proto_rawDescData = protoimpl.X.CompressGZIP(file_lock_grpc_types_proto_rawDescData) + }) + return file_lock_grpc_types_proto_rawDescData +} + +var file_lock_grpc_types_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_lock_grpc_types_proto_goTypes = []interface{}{ + (*Lock)(nil), // 0: neo.fs.v2.lock.Lock + (*grpc.ObjectID)(nil), // 1: neo.fs.v2.refs.ObjectID +} +var file_lock_grpc_types_proto_depIdxs = []int32{ + 1, // 0: neo.fs.v2.lock.Lock.members:type_name -> neo.fs.v2.refs.ObjectID + 1, // [1:1] is the sub-list for method output_type + 1, // [1:1] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_lock_grpc_types_proto_init() } +func file_lock_grpc_types_proto_init() { + if File_lock_grpc_types_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_lock_grpc_types_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Lock); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_lock_grpc_types_proto_rawDesc, + NumEnums: 0, + NumMessages: 1, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_lock_grpc_types_proto_goTypes, + DependencyIndexes: file_lock_grpc_types_proto_depIdxs, + MessageInfos: file_lock_grpc_types_proto_msgTypes, + }.Build() + File_lock_grpc_types_proto = out.File + file_lock_grpc_types_proto_rawDesc = nil + file_lock_grpc_types_proto_goTypes = nil + file_lock_grpc_types_proto_depIdxs = nil +} diff --git a/pkg/api/netmap/convert.go b/pkg/api/netmap/convert.go new file mode 100644 index 000000000..df8368baf --- /dev/null +++ b/pkg/api/netmap/convert.go @@ -0,0 +1,926 @@ +package netmap + +import ( + netmap "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/netmap/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + refsGRPC "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/message" +) + +func (f *Filter) ToGRPCMessage() grpc.Message { + var m *netmap.Filter + + if f != nil { + m = new(netmap.Filter) + + m.SetKey(f.key) + m.SetValue(f.value) + m.SetName(f.name) + m.SetOp(OperationToGRPCMessage(f.op)) + m.SetFilters(FiltersToGRPC(f.filters)) + } + + return m +} + +func (f *Filter) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*netmap.Filter) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + f.filters, err = FiltersFromGRPC(v.GetFilters()) + if err != nil { + return err + } + + f.key = v.GetKey() + f.value = v.GetValue() + f.name = v.GetName() + f.op = OperationFromGRPCMessage(v.GetOp()) + + return nil +} + +func FiltersToGRPC(fs []Filter) (res []*netmap.Filter) { + if fs != nil { + res = make([]*netmap.Filter, 0, len(fs)) + + for i := range fs { + res = append(res, fs[i].ToGRPCMessage().(*netmap.Filter)) + } + } + + return +} + +func FiltersFromGRPC(fs []*netmap.Filter) (res []Filter, err error) { + if fs != nil { + res = make([]Filter, len(fs)) + + for i := range fs { + if fs[i] != nil { + err = res[i].FromGRPCMessage(fs[i]) + if err != nil { + return + } + } + } + } + + return +} + +func (s *Selector) ToGRPCMessage() grpc.Message { + var m *netmap.Selector + + if s != nil { + m = new(netmap.Selector) + + m.SetName(s.name) + m.SetAttribute(s.attribute) + m.SetFilter(s.filter) + m.SetCount(s.count) + m.SetClause(ClauseToGRPCMessage(s.clause)) + } + + return m +} + +func (s *Selector) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*netmap.Selector) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + s.name = v.GetName() + s.attribute = v.GetAttribute() + s.filter = v.GetFilter() + s.count = v.GetCount() + s.clause = ClauseFromGRPCMessage(v.GetClause()) + + return nil +} + +func SelectorsToGRPC(ss []Selector) (res []*netmap.Selector) { + if ss != nil { + res = make([]*netmap.Selector, 0, len(ss)) + + for i := range ss { + res = append(res, ss[i].ToGRPCMessage().(*netmap.Selector)) + } + } + + return +} + +func SelectorsFromGRPC(ss []*netmap.Selector) (res []Selector, err error) { + if ss != nil { + res = make([]Selector, len(ss)) + + for i := range ss { + if ss[i] != nil { + err = res[i].FromGRPCMessage(ss[i]) + if err != nil { + return + } + } + } + } + + return +} + +func (r *Replica) ToGRPCMessage() grpc.Message { + var m *netmap.Replica + + if r != nil { + m = new(netmap.Replica) + + m.SetSelector(r.selector) + m.SetCount(r.count) + m.EcDataCount = r.ecDataCount + m.EcParityCount = r.ecParityCount + } + + return m +} + +func (r *Replica) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*netmap.Replica) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + r.selector = v.GetSelector() + r.count = v.GetCount() + r.ecDataCount = v.GetEcDataCount() + r.ecParityCount = v.GetEcParityCount() + + return nil +} + +func ReplicasToGRPC(rs []Replica) (res []*netmap.Replica) { + if rs != nil { + res = make([]*netmap.Replica, 0, len(rs)) + + for i := range rs { + res = append(res, rs[i].ToGRPCMessage().(*netmap.Replica)) + } + } + + return +} + +func ReplicasFromGRPC(rs []*netmap.Replica) (res []Replica, err error) { + if rs != nil { + res = make([]Replica, len(rs)) + + for i := range rs { + if rs[i] != nil { + err = res[i].FromGRPCMessage(rs[i]) + if err != nil { + return + } + } + } + } + + return +} + +func (p *PlacementPolicy) ToGRPCMessage() grpc.Message { + var m *netmap.PlacementPolicy + + if p != nil { + m = new(netmap.PlacementPolicy) + + m.SetFilters(FiltersToGRPC(p.filters)) + m.SetSelectors(SelectorsToGRPC(p.selectors)) + m.SetReplicas(ReplicasToGRPC(p.replicas)) + m.SetContainerBackupFactor(p.backupFactor) + m.SetUnique(p.unique) + } + + return m +} + +func (p *PlacementPolicy) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*netmap.PlacementPolicy) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + p.filters, err = FiltersFromGRPC(v.GetFilters()) + if err != nil { + return err + } + + p.selectors, err = SelectorsFromGRPC(v.GetSelectors()) + if err != nil { + return err + } + + p.replicas, err = ReplicasFromGRPC(v.GetReplicas()) + if err != nil { + return err + } + + p.backupFactor = v.GetContainerBackupFactor() + + p.unique = v.GetUnique() + + return nil +} + +func ClauseToGRPCMessage(n Clause) netmap.Clause { + return netmap.Clause(n) +} + +func ClauseFromGRPCMessage(n netmap.Clause) Clause { + return Clause(n) +} + +func OperationToGRPCMessage(n Operation) netmap.Operation { + return netmap.Operation(n) +} + +func OperationFromGRPCMessage(n netmap.Operation) Operation { + return Operation(n) +} + +func NodeStateToGRPCMessage(n NodeState) netmap.NodeInfo_State { + return netmap.NodeInfo_State(n) +} + +func NodeStateFromRPCMessage(n netmap.NodeInfo_State) NodeState { + return NodeState(n) +} + +func (a *Attribute) ToGRPCMessage() grpc.Message { + var m *netmap.NodeInfo_Attribute + + if a != nil { + m = new(netmap.NodeInfo_Attribute) + + m.SetKey(a.key) + m.SetValue(a.value) + m.SetParents(a.parents) + } + + return m +} + +func (a *Attribute) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*netmap.NodeInfo_Attribute) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + a.key = v.GetKey() + a.value = v.GetValue() + a.parents = v.GetParents() + + return nil +} + +func AttributesToGRPC(as []Attribute) (res []*netmap.NodeInfo_Attribute) { + if as != nil { + res = make([]*netmap.NodeInfo_Attribute, 0, len(as)) + + for i := range as { + res = append(res, as[i].ToGRPCMessage().(*netmap.NodeInfo_Attribute)) + } + } + + return +} + +func AttributesFromGRPC(as []*netmap.NodeInfo_Attribute) (res []Attribute, err error) { + if as != nil { + res = make([]Attribute, len(as)) + + for i := range as { + if as[i] != nil { + err = res[i].FromGRPCMessage(as[i]) + if err != nil { + return + } + } + } + } + + return +} + +func (ni *NodeInfo) ToGRPCMessage() grpc.Message { + var m *netmap.NodeInfo + + if ni != nil { + m = new(netmap.NodeInfo) + + m.SetPublicKey(ni.publicKey) + m.SetAddresses(ni.addresses) + m.SetState(NodeStateToGRPCMessage(ni.state)) + m.SetAttributes(AttributesToGRPC(ni.attributes)) + } + + return m +} + +func (ni *NodeInfo) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*netmap.NodeInfo) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + ni.attributes, err = AttributesFromGRPC(v.GetAttributes()) + if err != nil { + return err + } + + ni.publicKey = v.GetPublicKey() + ni.addresses = v.GetAddresses() + ni.state = NodeStateFromRPCMessage(v.GetState()) + + return nil +} + +func (l *LocalNodeInfoRequestBody) ToGRPCMessage() grpc.Message { + var m *netmap.LocalNodeInfoRequest_Body + + if l != nil { + m = new(netmap.LocalNodeInfoRequest_Body) + } + + return m +} + +func (l *LocalNodeInfoRequestBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*netmap.LocalNodeInfoRequest_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + return nil +} + +func (l *LocalNodeInfoRequest) ToGRPCMessage() grpc.Message { + var m *netmap.LocalNodeInfoRequest + + if l != nil { + m = new(netmap.LocalNodeInfoRequest) + + m.SetBody(l.body.ToGRPCMessage().(*netmap.LocalNodeInfoRequest_Body)) + l.RequestHeaders.ToMessage(m) + } + + return m +} + +func (l *LocalNodeInfoRequest) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*netmap.LocalNodeInfoRequest) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + l.body = nil + } else { + if l.body == nil { + l.body = new(LocalNodeInfoRequestBody) + } + + err = l.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return l.RequestHeaders.FromMessage(v) +} + +func (l *LocalNodeInfoResponseBody) ToGRPCMessage() grpc.Message { + var m *netmap.LocalNodeInfoResponse_Body + + if l != nil { + m = new(netmap.LocalNodeInfoResponse_Body) + + m.SetVersion(l.version.ToGRPCMessage().(*refsGRPC.Version)) + m.SetNodeInfo(l.nodeInfo.ToGRPCMessage().(*netmap.NodeInfo)) + } + + return m +} + +func (l *LocalNodeInfoResponseBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*netmap.LocalNodeInfoResponse_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + version := v.GetVersion() + if version == nil { + l.version = nil + } else { + if l.version == nil { + l.version = new(refs.Version) + } + + err = l.version.FromGRPCMessage(version) + if err != nil { + return err + } + } + + nodeInfo := v.GetNodeInfo() + if nodeInfo == nil { + l.nodeInfo = nil + } else { + if l.nodeInfo == nil { + l.nodeInfo = new(NodeInfo) + } + + err = l.nodeInfo.FromGRPCMessage(nodeInfo) + } + + return err +} + +func (l *LocalNodeInfoResponse) ToGRPCMessage() grpc.Message { + var m *netmap.LocalNodeInfoResponse + + if l != nil { + m = new(netmap.LocalNodeInfoResponse) + + m.SetBody(l.body.ToGRPCMessage().(*netmap.LocalNodeInfoResponse_Body)) + l.ResponseHeaders.ToMessage(m) + } + + return m +} + +func (l *LocalNodeInfoResponse) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*netmap.LocalNodeInfoResponse) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + l.body = nil + } else { + if l.body == nil { + l.body = new(LocalNodeInfoResponseBody) + } + + err = l.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return l.ResponseHeaders.FromMessage(v) +} + +func (x *NetworkParameter) ToGRPCMessage() grpc.Message { + var m *netmap.NetworkConfig_Parameter + + if x != nil { + m = new(netmap.NetworkConfig_Parameter) + + m.SetKey(x.k) + m.SetValue(x.v) + } + + return m +} + +func (x *NetworkParameter) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*netmap.NetworkConfig_Parameter) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + x.k = v.GetKey() + x.v = v.GetValue() + + return nil +} + +func (x *NetworkConfig) ToGRPCMessage() grpc.Message { + var m *netmap.NetworkConfig + + if x != nil { + m = new(netmap.NetworkConfig) + + var ps []*netmap.NetworkConfig_Parameter + + if ln := len(x.ps); ln > 0 { + ps = make([]*netmap.NetworkConfig_Parameter, 0, ln) + + for i := 0; i < ln; i++ { + ps = append(ps, x.ps[i].ToGRPCMessage().(*netmap.NetworkConfig_Parameter)) + } + } + + m.SetParameters(ps) + } + + return m +} + +func (x *NetworkConfig) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*netmap.NetworkConfig) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var ( + ps []NetworkParameter + psV2 = v.GetParameters() + ) + + if psV2 != nil { + ln := len(psV2) + + ps = make([]NetworkParameter, ln) + + for i := 0; i < ln; i++ { + if psV2[i] != nil { + if err := ps[i].FromGRPCMessage(psV2[i]); err != nil { + return err + } + } + } + } + + x.ps = ps + + return nil +} + +func (i *NetworkInfo) ToGRPCMessage() grpc.Message { + var m *netmap.NetworkInfo + + if i != nil { + m = new(netmap.NetworkInfo) + + m.SetMagicNumber(i.magicNum) + m.SetCurrentEpoch(i.curEpoch) + m.SetMsPerBlock(i.msPerBlock) + m.SetNetworkConfig(i.netCfg.ToGRPCMessage().(*netmap.NetworkConfig)) + } + + return m +} + +func (i *NetworkInfo) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*netmap.NetworkInfo) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + netCfg := v.GetNetworkConfig() + if netCfg == nil { + i.netCfg = nil + } else { + if i.netCfg == nil { + i.netCfg = new(NetworkConfig) + } + + err = i.netCfg.FromGRPCMessage(netCfg) + if err != nil { + return err + } + } + + i.magicNum = v.GetMagicNumber() + i.curEpoch = v.GetCurrentEpoch() + i.msPerBlock = v.GetMsPerBlock() + + return nil +} + +func (l *NetworkInfoRequestBody) ToGRPCMessage() grpc.Message { + var m *netmap.NetworkInfoRequest_Body + + if l != nil { + m = new(netmap.NetworkInfoRequest_Body) + } + + return m +} + +func (l *NetworkInfoRequestBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*netmap.NetworkInfoRequest_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + return nil +} + +func (l *NetworkInfoRequest) ToGRPCMessage() grpc.Message { + var m *netmap.NetworkInfoRequest + + if l != nil { + m = new(netmap.NetworkInfoRequest) + + m.SetBody(l.body.ToGRPCMessage().(*netmap.NetworkInfoRequest_Body)) + l.RequestHeaders.ToMessage(m) + } + + return m +} + +func (l *NetworkInfoRequest) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*netmap.NetworkInfoRequest) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + l.body = nil + } else { + if l.body == nil { + l.body = new(NetworkInfoRequestBody) + } + + err = l.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return l.RequestHeaders.FromMessage(v) +} + +func (i *NetworkInfoResponseBody) ToGRPCMessage() grpc.Message { + var m *netmap.NetworkInfoResponse_Body + + if i != nil { + m = new(netmap.NetworkInfoResponse_Body) + + m.SetNetworkInfo(i.netInfo.ToGRPCMessage().(*netmap.NetworkInfo)) + } + + return m +} + +func (i *NetworkInfoResponseBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*netmap.NetworkInfoResponse_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + netInfo := v.GetNetworkInfo() + if netInfo == nil { + i.netInfo = nil + } else { + if i.netInfo == nil { + i.netInfo = new(NetworkInfo) + } + + err = i.netInfo.FromGRPCMessage(netInfo) + } + + return err +} + +func (l *NetworkInfoResponse) ToGRPCMessage() grpc.Message { + var m *netmap.NetworkInfoResponse + + if l != nil { + m = new(netmap.NetworkInfoResponse) + + m.SetBody(l.body.ToGRPCMessage().(*netmap.NetworkInfoResponse_Body)) + l.ResponseHeaders.ToMessage(m) + } + + return m +} + +func (l *NetworkInfoResponse) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*netmap.NetworkInfoResponse) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + l.body = nil + } else { + if l.body == nil { + l.body = new(NetworkInfoResponseBody) + } + + err = l.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return l.ResponseHeaders.FromMessage(v) +} + +func (x *NetMap) ToGRPCMessage() grpc.Message { + var m *netmap.Netmap + + if x != nil { + m = new(netmap.Netmap) + + m.SetEpoch(x.epoch) + + if x.nodes != nil { + nodes := make([]*netmap.NodeInfo, len(x.nodes)) + + for i := range x.nodes { + nodes[i] = x.nodes[i].ToGRPCMessage().(*netmap.NodeInfo) + } + + m.SetNodes(nodes) + } + } + + return m +} + +func (x *NetMap) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*netmap.Netmap) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + nodes := v.GetNodes() + if nodes == nil { + x.nodes = nil + } else { + x.nodes = make([]NodeInfo, len(nodes)) + + for i := range nodes { + err = x.nodes[i].FromGRPCMessage(nodes[i]) + if err != nil { + return err + } + } + } + + x.epoch = v.GetEpoch() + + return nil +} + +func (x *SnapshotRequestBody) ToGRPCMessage() grpc.Message { + var m *netmap.NetmapSnapshotRequest_Body + + if x != nil { + m = new(netmap.NetmapSnapshotRequest_Body) + } + + return m +} + +func (x *SnapshotRequestBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*netmap.NetmapSnapshotRequest_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + return nil +} + +func (x *SnapshotRequest) ToGRPCMessage() grpc.Message { + var m *netmap.NetmapSnapshotRequest + + if x != nil { + m = new(netmap.NetmapSnapshotRequest) + + m.SetBody(x.body.ToGRPCMessage().(*netmap.NetmapSnapshotRequest_Body)) + x.RequestHeaders.ToMessage(m) + } + + return m +} + +func (x *SnapshotRequest) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*netmap.NetmapSnapshotRequest) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + x.body = nil + } else { + if x.body == nil { + x.body = new(SnapshotRequestBody) + } + + err = x.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return x.RequestHeaders.FromMessage(v) +} + +func (x *SnapshotResponseBody) ToGRPCMessage() grpc.Message { + var m *netmap.NetmapSnapshotResponse_Body + + if x != nil { + m = new(netmap.NetmapSnapshotResponse_Body) + + m.SetNetmap(x.netMap.ToGRPCMessage().(*netmap.Netmap)) + } + + return m +} + +func (x *SnapshotResponseBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*netmap.NetmapSnapshotResponse_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + netMap := v.GetNetmap() + if netMap == nil { + x.netMap = nil + } else { + if x.netMap == nil { + x.netMap = new(NetMap) + } + + err = x.netMap.FromGRPCMessage(netMap) + } + + return err +} + +func (x *SnapshotResponse) ToGRPCMessage() grpc.Message { + var m *netmap.NetmapSnapshotResponse + + if x != nil { + m = new(netmap.NetmapSnapshotResponse) + + m.SetBody(x.body.ToGRPCMessage().(*netmap.NetmapSnapshotResponse_Body)) + x.ResponseHeaders.ToMessage(m) + } + + return m +} + +func (x *SnapshotResponse) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*netmap.NetmapSnapshotResponse) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + x.body = nil + } else { + if x.body == nil { + x.body = new(SnapshotResponseBody) + } + + err = x.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return x.ResponseHeaders.FromMessage(v) +} diff --git a/pkg/api/netmap/grpc/service.go b/pkg/api/netmap/grpc/service.go new file mode 100644 index 000000000..efdbb5f5a --- /dev/null +++ b/pkg/api/netmap/grpc/service.go @@ -0,0 +1,116 @@ +package netmap + +import ( + refs "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs/grpc" + session "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session/grpc" +) + +// SetBody sets body of the request. +func (m *LocalNodeInfoRequest) SetBody(v *LocalNodeInfoRequest_Body) { + m.Body = v +} + +// SetMetaHeader sets meta header of the request. +func (m *LocalNodeInfoRequest) SetMetaHeader(v *session.RequestMetaHeader) { + m.MetaHeader = v +} + +// SetVerifyHeader sets verification header of the request. +func (m *LocalNodeInfoRequest) SetVerifyHeader(v *session.RequestVerificationHeader) { + m.VerifyHeader = v +} + +// SetVersion sets version of response body. +func (m *LocalNodeInfoResponse_Body) SetVersion(v *refs.Version) { + m.Version = v +} + +// SetNodeInfo sets node info of response body. +func (m *LocalNodeInfoResponse_Body) SetNodeInfo(v *NodeInfo) { + m.NodeInfo = v +} + +// SetBody sets body of the response. +func (m *LocalNodeInfoResponse) SetBody(v *LocalNodeInfoResponse_Body) { + m.Body = v +} + +// SetMetaHeader sets meta header of the response. +func (m *LocalNodeInfoResponse) SetMetaHeader(v *session.ResponseMetaHeader) { + m.MetaHeader = v +} + +// SetVerifyHeader sets verification header of the response. +func (m *LocalNodeInfoResponse) SetVerifyHeader(v *session.ResponseVerificationHeader) { + m.VerifyHeader = v +} + +// SetBody sets body of the request. +func (x *NetworkInfoRequest) SetBody(v *NetworkInfoRequest_Body) { + x.Body = v +} + +// SetMetaHeader sets meta header of the request. +func (x *NetworkInfoRequest) SetMetaHeader(v *session.RequestMetaHeader) { + x.MetaHeader = v +} + +// SetVerifyHeader sets verification header of the request. +func (x *NetworkInfoRequest) SetVerifyHeader(v *session.RequestVerificationHeader) { + x.VerifyHeader = v +} + +// SetNetworkInfo sets information about the network. +func (x *NetworkInfoResponse_Body) SetNetworkInfo(v *NetworkInfo) { + x.NetworkInfo = v +} + +// SetBody sets body of the response. +func (x *NetworkInfoResponse) SetBody(v *NetworkInfoResponse_Body) { + x.Body = v +} + +// SetMetaHeader sets meta header of the response. +func (x *NetworkInfoResponse) SetMetaHeader(v *session.ResponseMetaHeader) { + x.MetaHeader = v +} + +// SetVerifyHeader sets verification header of the response. +func (x *NetworkInfoResponse) SetVerifyHeader(v *session.ResponseVerificationHeader) { + x.VerifyHeader = v +} + +// SetBody sets body of the request. +func (x *NetmapSnapshotRequest) SetBody(v *NetmapSnapshotRequest_Body) { + x.Body = v +} + +// SetMetaHeader sets meta header of the request. +func (x *NetmapSnapshotRequest) SetMetaHeader(v *session.RequestMetaHeader) { + x.MetaHeader = v +} + +// SetVerifyHeader sets verification header of the request. +func (x *NetmapSnapshotRequest) SetVerifyHeader(v *session.RequestVerificationHeader) { + x.VerifyHeader = v +} + +// SetNetmap sets current Netmap. +func (x *NetmapSnapshotResponse_Body) SetNetmap(v *Netmap) { + x.Netmap = v +} + +// SetBody sets body of the response. +func (x *NetmapSnapshotResponse) SetBody(v *NetmapSnapshotResponse_Body) { + x.Body = v +} + +// SetMetaHeader sets meta header of the response. +func (x *NetmapSnapshotResponse) SetMetaHeader(v *session.ResponseMetaHeader) { + x.MetaHeader = v +} + +// SetVerifyHeader sets verification header of the response. +func (x *NetmapSnapshotResponse) SetVerifyHeader(v *session.ResponseVerificationHeader) { + x.VerifyHeader = v +} diff --git a/pkg/api/netmap/grpc/service.pb.go b/pkg/api/netmap/grpc/service.pb.go new file mode 100644 index 000000000..589a6b345 --- /dev/null +++ b/pkg/api/netmap/grpc/service.pb.go @@ -0,0 +1,1108 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.33.0 +// protoc v4.25.3 +// source: netmap/grpc/service.proto + +package netmap + +import ( + grpc1 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs/grpc" + grpc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session/grpc" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// Get NodeInfo structure directly from a particular node +type LocalNodeInfoRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Body of the LocalNodeInfo request message + Body *LocalNodeInfoRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Carries request meta information. Header data is used only to regulate + // message transport and does not affect request execution. + MetaHeader *grpc.RequestMetaHeader `protobuf:"bytes,2,opt,name=meta_header,json=metaHeader,proto3" json:"meta_header,omitempty"` + // Carries request verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + VerifyHeader *grpc.RequestVerificationHeader `protobuf:"bytes,3,opt,name=verify_header,json=verifyHeader,proto3" json:"verify_header,omitempty"` +} + +func (x *LocalNodeInfoRequest) Reset() { + *x = LocalNodeInfoRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_netmap_grpc_service_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LocalNodeInfoRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LocalNodeInfoRequest) ProtoMessage() {} + +func (x *LocalNodeInfoRequest) ProtoReflect() protoreflect.Message { + mi := &file_netmap_grpc_service_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LocalNodeInfoRequest.ProtoReflect.Descriptor instead. +func (*LocalNodeInfoRequest) Descriptor() ([]byte, []int) { + return file_netmap_grpc_service_proto_rawDescGZIP(), []int{0} +} + +func (x *LocalNodeInfoRequest) GetBody() *LocalNodeInfoRequest_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *LocalNodeInfoRequest) GetMetaHeader() *grpc.RequestMetaHeader { + if x != nil { + return x.MetaHeader + } + return nil +} + +func (x *LocalNodeInfoRequest) GetVerifyHeader() *grpc.RequestVerificationHeader { + if x != nil { + return x.VerifyHeader + } + return nil +} + +// Local Node Info, including API Version in use +type LocalNodeInfoResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Body of the balance response message. + Body *LocalNodeInfoResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Carries response meta information. Header data is used only to regulate + // message transport and does not affect response execution. + MetaHeader *grpc.ResponseMetaHeader `protobuf:"bytes,2,opt,name=meta_header,json=metaHeader,proto3" json:"meta_header,omitempty"` + // Carries response verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + VerifyHeader *grpc.ResponseVerificationHeader `protobuf:"bytes,3,opt,name=verify_header,json=verifyHeader,proto3" json:"verify_header,omitempty"` +} + +func (x *LocalNodeInfoResponse) Reset() { + *x = LocalNodeInfoResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_netmap_grpc_service_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LocalNodeInfoResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LocalNodeInfoResponse) ProtoMessage() {} + +func (x *LocalNodeInfoResponse) ProtoReflect() protoreflect.Message { + mi := &file_netmap_grpc_service_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LocalNodeInfoResponse.ProtoReflect.Descriptor instead. +func (*LocalNodeInfoResponse) Descriptor() ([]byte, []int) { + return file_netmap_grpc_service_proto_rawDescGZIP(), []int{1} +} + +func (x *LocalNodeInfoResponse) GetBody() *LocalNodeInfoResponse_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *LocalNodeInfoResponse) GetMetaHeader() *grpc.ResponseMetaHeader { + if x != nil { + return x.MetaHeader + } + return nil +} + +func (x *LocalNodeInfoResponse) GetVerifyHeader() *grpc.ResponseVerificationHeader { + if x != nil { + return x.VerifyHeader + } + return nil +} + +// Get NetworkInfo structure with the network view from a particular node. +type NetworkInfoRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Body of the NetworkInfo request message + Body *NetworkInfoRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Carries request meta information. Header data is used only to regulate + // message transport and does not affect request execution. + MetaHeader *grpc.RequestMetaHeader `protobuf:"bytes,2,opt,name=meta_header,json=metaHeader,proto3" json:"meta_header,omitempty"` + // Carries request verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + VerifyHeader *grpc.RequestVerificationHeader `protobuf:"bytes,3,opt,name=verify_header,json=verifyHeader,proto3" json:"verify_header,omitempty"` +} + +func (x *NetworkInfoRequest) Reset() { + *x = NetworkInfoRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_netmap_grpc_service_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NetworkInfoRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NetworkInfoRequest) ProtoMessage() {} + +func (x *NetworkInfoRequest) ProtoReflect() protoreflect.Message { + mi := &file_netmap_grpc_service_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NetworkInfoRequest.ProtoReflect.Descriptor instead. +func (*NetworkInfoRequest) Descriptor() ([]byte, []int) { + return file_netmap_grpc_service_proto_rawDescGZIP(), []int{2} +} + +func (x *NetworkInfoRequest) GetBody() *NetworkInfoRequest_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *NetworkInfoRequest) GetMetaHeader() *grpc.RequestMetaHeader { + if x != nil { + return x.MetaHeader + } + return nil +} + +func (x *NetworkInfoRequest) GetVerifyHeader() *grpc.RequestVerificationHeader { + if x != nil { + return x.VerifyHeader + } + return nil +} + +// Response with NetworkInfo structure including current epoch and +// sidechain magic number. +type NetworkInfoResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Body of the NetworkInfo response message. + Body *NetworkInfoResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Carries response meta information. Header data is used only to regulate + // message transport and does not affect response execution. + MetaHeader *grpc.ResponseMetaHeader `protobuf:"bytes,2,opt,name=meta_header,json=metaHeader,proto3" json:"meta_header,omitempty"` + // Carries response verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + VerifyHeader *grpc.ResponseVerificationHeader `protobuf:"bytes,3,opt,name=verify_header,json=verifyHeader,proto3" json:"verify_header,omitempty"` +} + +func (x *NetworkInfoResponse) Reset() { + *x = NetworkInfoResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_netmap_grpc_service_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NetworkInfoResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NetworkInfoResponse) ProtoMessage() {} + +func (x *NetworkInfoResponse) ProtoReflect() protoreflect.Message { + mi := &file_netmap_grpc_service_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NetworkInfoResponse.ProtoReflect.Descriptor instead. +func (*NetworkInfoResponse) Descriptor() ([]byte, []int) { + return file_netmap_grpc_service_proto_rawDescGZIP(), []int{3} +} + +func (x *NetworkInfoResponse) GetBody() *NetworkInfoResponse_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *NetworkInfoResponse) GetMetaHeader() *grpc.ResponseMetaHeader { + if x != nil { + return x.MetaHeader + } + return nil +} + +func (x *NetworkInfoResponse) GetVerifyHeader() *grpc.ResponseVerificationHeader { + if x != nil { + return x.VerifyHeader + } + return nil +} + +// Get netmap snapshot request +type NetmapSnapshotRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Body of get netmap snapshot request message. + Body *NetmapSnapshotRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Carries request meta information. Header data is used only to regulate + // message transport and does not affect request execution. + MetaHeader *grpc.RequestMetaHeader `protobuf:"bytes,2,opt,name=meta_header,json=metaHeader,proto3" json:"meta_header,omitempty"` + // Carries request verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + VerifyHeader *grpc.RequestVerificationHeader `protobuf:"bytes,3,opt,name=verify_header,json=verifyHeader,proto3" json:"verify_header,omitempty"` +} + +func (x *NetmapSnapshotRequest) Reset() { + *x = NetmapSnapshotRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_netmap_grpc_service_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NetmapSnapshotRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NetmapSnapshotRequest) ProtoMessage() {} + +func (x *NetmapSnapshotRequest) ProtoReflect() protoreflect.Message { + mi := &file_netmap_grpc_service_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NetmapSnapshotRequest.ProtoReflect.Descriptor instead. +func (*NetmapSnapshotRequest) Descriptor() ([]byte, []int) { + return file_netmap_grpc_service_proto_rawDescGZIP(), []int{4} +} + +func (x *NetmapSnapshotRequest) GetBody() *NetmapSnapshotRequest_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *NetmapSnapshotRequest) GetMetaHeader() *grpc.RequestMetaHeader { + if x != nil { + return x.MetaHeader + } + return nil +} + +func (x *NetmapSnapshotRequest) GetVerifyHeader() *grpc.RequestVerificationHeader { + if x != nil { + return x.VerifyHeader + } + return nil +} + +// Response with current netmap snapshot +type NetmapSnapshotResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Body of get netmap snapshot response message. + Body *NetmapSnapshotResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Carries response meta information. Header data is used only to regulate + // message transport and does not affect response execution. + MetaHeader *grpc.ResponseMetaHeader `protobuf:"bytes,2,opt,name=meta_header,json=metaHeader,proto3" json:"meta_header,omitempty"` + // Carries response verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + VerifyHeader *grpc.ResponseVerificationHeader `protobuf:"bytes,3,opt,name=verify_header,json=verifyHeader,proto3" json:"verify_header,omitempty"` +} + +func (x *NetmapSnapshotResponse) Reset() { + *x = NetmapSnapshotResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_netmap_grpc_service_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NetmapSnapshotResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NetmapSnapshotResponse) ProtoMessage() {} + +func (x *NetmapSnapshotResponse) ProtoReflect() protoreflect.Message { + mi := &file_netmap_grpc_service_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NetmapSnapshotResponse.ProtoReflect.Descriptor instead. +func (*NetmapSnapshotResponse) Descriptor() ([]byte, []int) { + return file_netmap_grpc_service_proto_rawDescGZIP(), []int{5} +} + +func (x *NetmapSnapshotResponse) GetBody() *NetmapSnapshotResponse_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *NetmapSnapshotResponse) GetMetaHeader() *grpc.ResponseMetaHeader { + if x != nil { + return x.MetaHeader + } + return nil +} + +func (x *NetmapSnapshotResponse) GetVerifyHeader() *grpc.ResponseVerificationHeader { + if x != nil { + return x.VerifyHeader + } + return nil +} + +// LocalNodeInfo request body is empty. +type LocalNodeInfoRequest_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *LocalNodeInfoRequest_Body) Reset() { + *x = LocalNodeInfoRequest_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_netmap_grpc_service_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LocalNodeInfoRequest_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LocalNodeInfoRequest_Body) ProtoMessage() {} + +func (x *LocalNodeInfoRequest_Body) ProtoReflect() protoreflect.Message { + mi := &file_netmap_grpc_service_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LocalNodeInfoRequest_Body.ProtoReflect.Descriptor instead. +func (*LocalNodeInfoRequest_Body) Descriptor() ([]byte, []int) { + return file_netmap_grpc_service_proto_rawDescGZIP(), []int{0, 0} +} + +// Local Node Info, including API Version in use. +type LocalNodeInfoResponse_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Latest NeoFS API version in use + Version *grpc1.Version `protobuf:"bytes,1,opt,name=version,proto3" json:"version,omitempty"` + // NodeInfo structure with recent information from node itself + NodeInfo *NodeInfo `protobuf:"bytes,2,opt,name=node_info,json=nodeInfo,proto3" json:"node_info,omitempty"` +} + +func (x *LocalNodeInfoResponse_Body) Reset() { + *x = LocalNodeInfoResponse_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_netmap_grpc_service_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LocalNodeInfoResponse_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LocalNodeInfoResponse_Body) ProtoMessage() {} + +func (x *LocalNodeInfoResponse_Body) ProtoReflect() protoreflect.Message { + mi := &file_netmap_grpc_service_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LocalNodeInfoResponse_Body.ProtoReflect.Descriptor instead. +func (*LocalNodeInfoResponse_Body) Descriptor() ([]byte, []int) { + return file_netmap_grpc_service_proto_rawDescGZIP(), []int{1, 0} +} + +func (x *LocalNodeInfoResponse_Body) GetVersion() *grpc1.Version { + if x != nil { + return x.Version + } + return nil +} + +func (x *LocalNodeInfoResponse_Body) GetNodeInfo() *NodeInfo { + if x != nil { + return x.NodeInfo + } + return nil +} + +// NetworkInfo request body is empty. +type NetworkInfoRequest_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *NetworkInfoRequest_Body) Reset() { + *x = NetworkInfoRequest_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_netmap_grpc_service_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NetworkInfoRequest_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NetworkInfoRequest_Body) ProtoMessage() {} + +func (x *NetworkInfoRequest_Body) ProtoReflect() protoreflect.Message { + mi := &file_netmap_grpc_service_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NetworkInfoRequest_Body.ProtoReflect.Descriptor instead. +func (*NetworkInfoRequest_Body) Descriptor() ([]byte, []int) { + return file_netmap_grpc_service_proto_rawDescGZIP(), []int{2, 0} +} + +// Information about the network. +type NetworkInfoResponse_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // NetworkInfo structure with recent information. + NetworkInfo *NetworkInfo `protobuf:"bytes,1,opt,name=network_info,json=networkInfo,proto3" json:"network_info,omitempty"` +} + +func (x *NetworkInfoResponse_Body) Reset() { + *x = NetworkInfoResponse_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_netmap_grpc_service_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NetworkInfoResponse_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NetworkInfoResponse_Body) ProtoMessage() {} + +func (x *NetworkInfoResponse_Body) ProtoReflect() protoreflect.Message { + mi := &file_netmap_grpc_service_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NetworkInfoResponse_Body.ProtoReflect.Descriptor instead. +func (*NetworkInfoResponse_Body) Descriptor() ([]byte, []int) { + return file_netmap_grpc_service_proto_rawDescGZIP(), []int{3, 0} +} + +func (x *NetworkInfoResponse_Body) GetNetworkInfo() *NetworkInfo { + if x != nil { + return x.NetworkInfo + } + return nil +} + +// Get netmap snapshot request body. +type NetmapSnapshotRequest_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *NetmapSnapshotRequest_Body) Reset() { + *x = NetmapSnapshotRequest_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_netmap_grpc_service_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NetmapSnapshotRequest_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NetmapSnapshotRequest_Body) ProtoMessage() {} + +func (x *NetmapSnapshotRequest_Body) ProtoReflect() protoreflect.Message { + mi := &file_netmap_grpc_service_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NetmapSnapshotRequest_Body.ProtoReflect.Descriptor instead. +func (*NetmapSnapshotRequest_Body) Descriptor() ([]byte, []int) { + return file_netmap_grpc_service_proto_rawDescGZIP(), []int{4, 0} +} + +// Get netmap snapshot response body +type NetmapSnapshotResponse_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Structure of the requested network map. + Netmap *Netmap `protobuf:"bytes,1,opt,name=netmap,proto3" json:"netmap,omitempty"` +} + +func (x *NetmapSnapshotResponse_Body) Reset() { + *x = NetmapSnapshotResponse_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_netmap_grpc_service_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NetmapSnapshotResponse_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NetmapSnapshotResponse_Body) ProtoMessage() {} + +func (x *NetmapSnapshotResponse_Body) ProtoReflect() protoreflect.Message { + mi := &file_netmap_grpc_service_proto_msgTypes[11] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NetmapSnapshotResponse_Body.ProtoReflect.Descriptor instead. +func (*NetmapSnapshotResponse_Body) Descriptor() ([]byte, []int) { + return file_netmap_grpc_service_proto_rawDescGZIP(), []int{5, 0} +} + +func (x *NetmapSnapshotResponse_Body) GetNetmap() *Netmap { + if x != nil { + return x.Netmap + } + return nil +} + +var File_netmap_grpc_service_proto protoreflect.FileDescriptor + +var file_netmap_grpc_service_proto_rawDesc = []byte{ + 0x0a, 0x19, 0x6e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x73, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x10, 0x6e, 0x65, 0x6f, + 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x1a, 0x17, 0x6e, + 0x65, 0x74, 0x6d, 0x61, 0x70, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x15, 0x72, 0x65, 0x66, 0x73, 0x2f, 0x67, 0x72, 0x70, + 0x63, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x18, 0x73, + 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x74, 0x79, 0x70, 0x65, + 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xf9, 0x01, 0x0a, 0x14, 0x4c, 0x6f, 0x63, 0x61, + 0x6c, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x3f, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, + 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6e, 0x65, 0x74, 0x6d, 0x61, + 0x70, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, + 0x79, 0x12, 0x45, 0x0a, 0x0b, 0x6d, 0x65, 0x74, 0x61, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, + 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0a, 0x6d, 0x65, + 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x51, 0x0a, 0x0d, 0x76, 0x65, 0x72, 0x69, + 0x66, 0x79, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x2c, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x65, 0x72, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0c, 0x76, + 0x65, 0x72, 0x69, 0x66, 0x79, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x1a, 0x06, 0x0a, 0x04, 0x42, + 0x6f, 0x64, 0x79, 0x22, 0xe9, 0x02, 0x0a, 0x15, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4e, 0x6f, 0x64, + 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, + 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x6e, 0x65, + 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x2e, 0x4c, + 0x6f, 0x63, 0x61, 0x6c, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, + 0x46, 0x0a, 0x0b, 0x6d, 0x65, 0x74, 0x61, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, + 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x4d, 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0a, 0x6d, 0x65, 0x74, + 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x52, 0x0a, 0x0d, 0x76, 0x65, 0x72, 0x69, 0x66, + 0x79, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, + 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x56, 0x65, 0x72, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0c, 0x76, + 0x65, 0x72, 0x69, 0x66, 0x79, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x1a, 0x72, 0x0a, 0x04, 0x42, + 0x6f, 0x64, 0x79, 0x12, 0x31, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, + 0x2e, 0x72, 0x65, 0x66, 0x73, 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x76, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x37, 0x0a, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, + 0x6e, 0x66, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, + 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x2e, 0x4e, 0x6f, 0x64, + 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x08, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x22, + 0xf5, 0x01, 0x0a, 0x12, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3d, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, + 0x2e, 0x6e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x2e, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, + 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, + 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x45, 0x0a, 0x0b, 0x6d, 0x65, 0x74, 0x61, 0x5f, 0x68, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6e, 0x65, 0x6f, + 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x52, 0x0a, 0x6d, 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x51, 0x0a, 0x0d, + 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, + 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, + 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x52, 0x0c, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x1a, + 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0xbb, 0x02, 0x0a, 0x13, 0x4e, 0x65, 0x74, 0x77, + 0x6f, 0x72, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x3e, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, + 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6e, 0x65, 0x74, 0x6d, 0x61, 0x70, + 0x2e, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, + 0x46, 0x0a, 0x0b, 0x6d, 0x65, 0x74, 0x61, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, + 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x4d, 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0a, 0x6d, 0x65, 0x74, + 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x52, 0x0a, 0x0d, 0x76, 0x65, 0x72, 0x69, 0x66, + 0x79, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, + 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x56, 0x65, 0x72, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0c, 0x76, + 0x65, 0x72, 0x69, 0x66, 0x79, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x1a, 0x48, 0x0a, 0x04, 0x42, + 0x6f, 0x64, 0x79, 0x12, 0x40, 0x0a, 0x0c, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x5f, 0x69, + 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, + 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x2e, 0x4e, 0x65, 0x74, + 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0b, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, + 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0xfb, 0x01, 0x0a, 0x15, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, + 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x40, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, + 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6e, 0x65, 0x74, 0x6d, 0x61, 0x70, + 0x2e, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, + 0x79, 0x12, 0x45, 0x0a, 0x0b, 0x6d, 0x65, 0x74, 0x61, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, + 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0a, 0x6d, 0x65, + 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x51, 0x0a, 0x0d, 0x76, 0x65, 0x72, 0x69, + 0x66, 0x79, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x2c, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x65, 0x72, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0c, 0x76, + 0x65, 0x72, 0x69, 0x66, 0x79, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x1a, 0x06, 0x0a, 0x04, 0x42, + 0x6f, 0x64, 0x79, 0x22, 0xb1, 0x02, 0x0a, 0x16, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x6e, + 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, + 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x6e, + 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x2e, + 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, + 0x79, 0x12, 0x46, 0x0a, 0x0b, 0x6d, 0x65, 0x74, 0x61, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, + 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0a, 0x6d, + 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x52, 0x0a, 0x0d, 0x76, 0x65, 0x72, + 0x69, 0x66, 0x79, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x2d, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x56, 0x65, 0x72, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, + 0x0c, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x1a, 0x38, 0x0a, + 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x06, 0x6e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, + 0x32, 0x2e, 0x6e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x2e, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x52, + 0x06, 0x6e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x32, 0xb2, 0x02, 0x0a, 0x0d, 0x4e, 0x65, 0x74, 0x6d, + 0x61, 0x70, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x60, 0x0a, 0x0d, 0x4c, 0x6f, 0x63, + 0x61, 0x6c, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x26, 0x2e, 0x6e, 0x65, 0x6f, + 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x2e, 0x4c, 0x6f, + 0x63, 0x61, 0x6c, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6e, + 0x65, 0x74, 0x6d, 0x61, 0x70, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4e, 0x6f, 0x64, 0x65, 0x49, + 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5a, 0x0a, 0x0b, 0x4e, + 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x24, 0x2e, 0x6e, 0x65, 0x6f, + 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x2e, 0x4e, 0x65, + 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x25, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6e, 0x65, 0x74, + 0x6d, 0x61, 0x70, 0x2e, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x63, 0x0a, 0x0e, 0x4e, 0x65, 0x74, 0x6d, 0x61, + 0x70, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x12, 0x27, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, + 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x2e, 0x4e, 0x65, 0x74, + 0x6d, 0x61, 0x70, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6e, + 0x65, 0x74, 0x6d, 0x61, 0x70, 0x2e, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x6e, 0x61, 0x70, + 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x61, 0x5a, 0x42, + 0x67, 0x69, 0x74, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2e, 0x69, 0x6e, 0x66, 0x6f, + 0x2f, 0x54, 0x72, 0x75, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x4c, 0x61, 0x62, 0x2f, 0x66, 0x72, + 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2d, 0x61, 0x70, 0x69, 0x2d, 0x67, 0x6f, 0x2f, 0x76, 0x32, 0x2f, + 0x6e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x3b, 0x6e, 0x65, 0x74, 0x6d, + 0x61, 0x70, 0xaa, 0x02, 0x1a, 0x4e, 0x65, 0x6f, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x53, 0x74, 0x6f, + 0x72, 0x61, 0x67, 0x65, 0x2e, 0x41, 0x50, 0x49, 0x2e, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x62, + 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_netmap_grpc_service_proto_rawDescOnce sync.Once + file_netmap_grpc_service_proto_rawDescData = file_netmap_grpc_service_proto_rawDesc +) + +func file_netmap_grpc_service_proto_rawDescGZIP() []byte { + file_netmap_grpc_service_proto_rawDescOnce.Do(func() { + file_netmap_grpc_service_proto_rawDescData = protoimpl.X.CompressGZIP(file_netmap_grpc_service_proto_rawDescData) + }) + return file_netmap_grpc_service_proto_rawDescData +} + +var file_netmap_grpc_service_proto_msgTypes = make([]protoimpl.MessageInfo, 12) +var file_netmap_grpc_service_proto_goTypes = []interface{}{ + (*LocalNodeInfoRequest)(nil), // 0: neo.fs.v2.netmap.LocalNodeInfoRequest + (*LocalNodeInfoResponse)(nil), // 1: neo.fs.v2.netmap.LocalNodeInfoResponse + (*NetworkInfoRequest)(nil), // 2: neo.fs.v2.netmap.NetworkInfoRequest + (*NetworkInfoResponse)(nil), // 3: neo.fs.v2.netmap.NetworkInfoResponse + (*NetmapSnapshotRequest)(nil), // 4: neo.fs.v2.netmap.NetmapSnapshotRequest + (*NetmapSnapshotResponse)(nil), // 5: neo.fs.v2.netmap.NetmapSnapshotResponse + (*LocalNodeInfoRequest_Body)(nil), // 6: neo.fs.v2.netmap.LocalNodeInfoRequest.Body + (*LocalNodeInfoResponse_Body)(nil), // 7: neo.fs.v2.netmap.LocalNodeInfoResponse.Body + (*NetworkInfoRequest_Body)(nil), // 8: neo.fs.v2.netmap.NetworkInfoRequest.Body + (*NetworkInfoResponse_Body)(nil), // 9: neo.fs.v2.netmap.NetworkInfoResponse.Body + (*NetmapSnapshotRequest_Body)(nil), // 10: neo.fs.v2.netmap.NetmapSnapshotRequest.Body + (*NetmapSnapshotResponse_Body)(nil), // 11: neo.fs.v2.netmap.NetmapSnapshotResponse.Body + (*grpc.RequestMetaHeader)(nil), // 12: neo.fs.v2.session.RequestMetaHeader + (*grpc.RequestVerificationHeader)(nil), // 13: neo.fs.v2.session.RequestVerificationHeader + (*grpc.ResponseMetaHeader)(nil), // 14: neo.fs.v2.session.ResponseMetaHeader + (*grpc.ResponseVerificationHeader)(nil), // 15: neo.fs.v2.session.ResponseVerificationHeader + (*grpc1.Version)(nil), // 16: neo.fs.v2.refs.Version + (*NodeInfo)(nil), // 17: neo.fs.v2.netmap.NodeInfo + (*NetworkInfo)(nil), // 18: neo.fs.v2.netmap.NetworkInfo + (*Netmap)(nil), // 19: neo.fs.v2.netmap.Netmap +} +var file_netmap_grpc_service_proto_depIdxs = []int32{ + 6, // 0: neo.fs.v2.netmap.LocalNodeInfoRequest.body:type_name -> neo.fs.v2.netmap.LocalNodeInfoRequest.Body + 12, // 1: neo.fs.v2.netmap.LocalNodeInfoRequest.meta_header:type_name -> neo.fs.v2.session.RequestMetaHeader + 13, // 2: neo.fs.v2.netmap.LocalNodeInfoRequest.verify_header:type_name -> neo.fs.v2.session.RequestVerificationHeader + 7, // 3: neo.fs.v2.netmap.LocalNodeInfoResponse.body:type_name -> neo.fs.v2.netmap.LocalNodeInfoResponse.Body + 14, // 4: neo.fs.v2.netmap.LocalNodeInfoResponse.meta_header:type_name -> neo.fs.v2.session.ResponseMetaHeader + 15, // 5: neo.fs.v2.netmap.LocalNodeInfoResponse.verify_header:type_name -> neo.fs.v2.session.ResponseVerificationHeader + 8, // 6: neo.fs.v2.netmap.NetworkInfoRequest.body:type_name -> neo.fs.v2.netmap.NetworkInfoRequest.Body + 12, // 7: neo.fs.v2.netmap.NetworkInfoRequest.meta_header:type_name -> neo.fs.v2.session.RequestMetaHeader + 13, // 8: neo.fs.v2.netmap.NetworkInfoRequest.verify_header:type_name -> neo.fs.v2.session.RequestVerificationHeader + 9, // 9: neo.fs.v2.netmap.NetworkInfoResponse.body:type_name -> neo.fs.v2.netmap.NetworkInfoResponse.Body + 14, // 10: neo.fs.v2.netmap.NetworkInfoResponse.meta_header:type_name -> neo.fs.v2.session.ResponseMetaHeader + 15, // 11: neo.fs.v2.netmap.NetworkInfoResponse.verify_header:type_name -> neo.fs.v2.session.ResponseVerificationHeader + 10, // 12: neo.fs.v2.netmap.NetmapSnapshotRequest.body:type_name -> neo.fs.v2.netmap.NetmapSnapshotRequest.Body + 12, // 13: neo.fs.v2.netmap.NetmapSnapshotRequest.meta_header:type_name -> neo.fs.v2.session.RequestMetaHeader + 13, // 14: neo.fs.v2.netmap.NetmapSnapshotRequest.verify_header:type_name -> neo.fs.v2.session.RequestVerificationHeader + 11, // 15: neo.fs.v2.netmap.NetmapSnapshotResponse.body:type_name -> neo.fs.v2.netmap.NetmapSnapshotResponse.Body + 14, // 16: neo.fs.v2.netmap.NetmapSnapshotResponse.meta_header:type_name -> neo.fs.v2.session.ResponseMetaHeader + 15, // 17: neo.fs.v2.netmap.NetmapSnapshotResponse.verify_header:type_name -> neo.fs.v2.session.ResponseVerificationHeader + 16, // 18: neo.fs.v2.netmap.LocalNodeInfoResponse.Body.version:type_name -> neo.fs.v2.refs.Version + 17, // 19: neo.fs.v2.netmap.LocalNodeInfoResponse.Body.node_info:type_name -> neo.fs.v2.netmap.NodeInfo + 18, // 20: neo.fs.v2.netmap.NetworkInfoResponse.Body.network_info:type_name -> neo.fs.v2.netmap.NetworkInfo + 19, // 21: neo.fs.v2.netmap.NetmapSnapshotResponse.Body.netmap:type_name -> neo.fs.v2.netmap.Netmap + 0, // 22: neo.fs.v2.netmap.NetmapService.LocalNodeInfo:input_type -> neo.fs.v2.netmap.LocalNodeInfoRequest + 2, // 23: neo.fs.v2.netmap.NetmapService.NetworkInfo:input_type -> neo.fs.v2.netmap.NetworkInfoRequest + 4, // 24: neo.fs.v2.netmap.NetmapService.NetmapSnapshot:input_type -> neo.fs.v2.netmap.NetmapSnapshotRequest + 1, // 25: neo.fs.v2.netmap.NetmapService.LocalNodeInfo:output_type -> neo.fs.v2.netmap.LocalNodeInfoResponse + 3, // 26: neo.fs.v2.netmap.NetmapService.NetworkInfo:output_type -> neo.fs.v2.netmap.NetworkInfoResponse + 5, // 27: neo.fs.v2.netmap.NetmapService.NetmapSnapshot:output_type -> neo.fs.v2.netmap.NetmapSnapshotResponse + 25, // [25:28] is the sub-list for method output_type + 22, // [22:25] is the sub-list for method input_type + 22, // [22:22] is the sub-list for extension type_name + 22, // [22:22] is the sub-list for extension extendee + 0, // [0:22] is the sub-list for field type_name +} + +func init() { file_netmap_grpc_service_proto_init() } +func file_netmap_grpc_service_proto_init() { + if File_netmap_grpc_service_proto != nil { + return + } + file_netmap_grpc_types_proto_init() + if !protoimpl.UnsafeEnabled { + file_netmap_grpc_service_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LocalNodeInfoRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_netmap_grpc_service_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LocalNodeInfoResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_netmap_grpc_service_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NetworkInfoRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_netmap_grpc_service_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NetworkInfoResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_netmap_grpc_service_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NetmapSnapshotRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_netmap_grpc_service_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NetmapSnapshotResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_netmap_grpc_service_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LocalNodeInfoRequest_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_netmap_grpc_service_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LocalNodeInfoResponse_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_netmap_grpc_service_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NetworkInfoRequest_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_netmap_grpc_service_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NetworkInfoResponse_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_netmap_grpc_service_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NetmapSnapshotRequest_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_netmap_grpc_service_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NetmapSnapshotResponse_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_netmap_grpc_service_proto_rawDesc, + NumEnums: 0, + NumMessages: 12, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_netmap_grpc_service_proto_goTypes, + DependencyIndexes: file_netmap_grpc_service_proto_depIdxs, + MessageInfos: file_netmap_grpc_service_proto_msgTypes, + }.Build() + File_netmap_grpc_service_proto = out.File + file_netmap_grpc_service_proto_rawDesc = nil + file_netmap_grpc_service_proto_goTypes = nil + file_netmap_grpc_service_proto_depIdxs = nil +} diff --git a/pkg/api/netmap/grpc/service_grpc.pb.go b/pkg/api/netmap/grpc/service_grpc.pb.go new file mode 100644 index 000000000..00cb8de72 --- /dev/null +++ b/pkg/api/netmap/grpc/service_grpc.pb.go @@ -0,0 +1,227 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.3.0 +// - protoc v4.25.3 +// source: netmap/grpc/service.proto + +package netmap + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +const ( + NetmapService_LocalNodeInfo_FullMethodName = "/neo.fs.v2.netmap.NetmapService/LocalNodeInfo" + NetmapService_NetworkInfo_FullMethodName = "/neo.fs.v2.netmap.NetmapService/NetworkInfo" + NetmapService_NetmapSnapshot_FullMethodName = "/neo.fs.v2.netmap.NetmapService/NetmapSnapshot" +) + +// NetmapServiceClient is the client API for NetmapService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type NetmapServiceClient interface { + // Get NodeInfo structure from the particular node directly. + // Node information can be taken from `Netmap` smart contract. In some cases, + // though, one may want to get recent information directly or to talk to the + // node not yet present in the `Network Map` to find out what API version can + // be used for further communication. This can be also used to check if a node + // is up and running. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): + // information about the server has been successfully read; + // - Common failures (SECTION_FAILURE_COMMON). + LocalNodeInfo(ctx context.Context, in *LocalNodeInfoRequest, opts ...grpc.CallOption) (*LocalNodeInfoResponse, error) + // Read recent information about the NeoFS network. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): + // information about the current network state has been successfully read; + // - Common failures (SECTION_FAILURE_COMMON). + NetworkInfo(ctx context.Context, in *NetworkInfoRequest, opts ...grpc.CallOption) (*NetworkInfoResponse, error) + // Returns network map snapshot of the current NeoFS epoch. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): + // information about the current network map has been successfully read; + // - Common failures (SECTION_FAILURE_COMMON). + NetmapSnapshot(ctx context.Context, in *NetmapSnapshotRequest, opts ...grpc.CallOption) (*NetmapSnapshotResponse, error) +} + +type netmapServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewNetmapServiceClient(cc grpc.ClientConnInterface) NetmapServiceClient { + return &netmapServiceClient{cc} +} + +func (c *netmapServiceClient) LocalNodeInfo(ctx context.Context, in *LocalNodeInfoRequest, opts ...grpc.CallOption) (*LocalNodeInfoResponse, error) { + out := new(LocalNodeInfoResponse) + err := c.cc.Invoke(ctx, NetmapService_LocalNodeInfo_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *netmapServiceClient) NetworkInfo(ctx context.Context, in *NetworkInfoRequest, opts ...grpc.CallOption) (*NetworkInfoResponse, error) { + out := new(NetworkInfoResponse) + err := c.cc.Invoke(ctx, NetmapService_NetworkInfo_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *netmapServiceClient) NetmapSnapshot(ctx context.Context, in *NetmapSnapshotRequest, opts ...grpc.CallOption) (*NetmapSnapshotResponse, error) { + out := new(NetmapSnapshotResponse) + err := c.cc.Invoke(ctx, NetmapService_NetmapSnapshot_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// NetmapServiceServer is the server API for NetmapService service. +// All implementations should embed UnimplementedNetmapServiceServer +// for forward compatibility +type NetmapServiceServer interface { + // Get NodeInfo structure from the particular node directly. + // Node information can be taken from `Netmap` smart contract. In some cases, + // though, one may want to get recent information directly or to talk to the + // node not yet present in the `Network Map` to find out what API version can + // be used for further communication. This can be also used to check if a node + // is up and running. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): + // information about the server has been successfully read; + // - Common failures (SECTION_FAILURE_COMMON). + LocalNodeInfo(context.Context, *LocalNodeInfoRequest) (*LocalNodeInfoResponse, error) + // Read recent information about the NeoFS network. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): + // information about the current network state has been successfully read; + // - Common failures (SECTION_FAILURE_COMMON). + NetworkInfo(context.Context, *NetworkInfoRequest) (*NetworkInfoResponse, error) + // Returns network map snapshot of the current NeoFS epoch. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): + // information about the current network map has been successfully read; + // - Common failures (SECTION_FAILURE_COMMON). + NetmapSnapshot(context.Context, *NetmapSnapshotRequest) (*NetmapSnapshotResponse, error) +} + +// UnimplementedNetmapServiceServer should be embedded to have forward compatible implementations. +type UnimplementedNetmapServiceServer struct { +} + +func (UnimplementedNetmapServiceServer) LocalNodeInfo(context.Context, *LocalNodeInfoRequest) (*LocalNodeInfoResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method LocalNodeInfo not implemented") +} +func (UnimplementedNetmapServiceServer) NetworkInfo(context.Context, *NetworkInfoRequest) (*NetworkInfoResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method NetworkInfo not implemented") +} +func (UnimplementedNetmapServiceServer) NetmapSnapshot(context.Context, *NetmapSnapshotRequest) (*NetmapSnapshotResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method NetmapSnapshot not implemented") +} + +// UnsafeNetmapServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to NetmapServiceServer will +// result in compilation errors. +type UnsafeNetmapServiceServer interface { + mustEmbedUnimplementedNetmapServiceServer() +} + +func RegisterNetmapServiceServer(s grpc.ServiceRegistrar, srv NetmapServiceServer) { + s.RegisterService(&NetmapService_ServiceDesc, srv) +} + +func _NetmapService_LocalNodeInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(LocalNodeInfoRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NetmapServiceServer).LocalNodeInfo(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: NetmapService_LocalNodeInfo_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NetmapServiceServer).LocalNodeInfo(ctx, req.(*LocalNodeInfoRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _NetmapService_NetworkInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(NetworkInfoRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NetmapServiceServer).NetworkInfo(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: NetmapService_NetworkInfo_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NetmapServiceServer).NetworkInfo(ctx, req.(*NetworkInfoRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _NetmapService_NetmapSnapshot_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(NetmapSnapshotRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NetmapServiceServer).NetmapSnapshot(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: NetmapService_NetmapSnapshot_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NetmapServiceServer).NetmapSnapshot(ctx, req.(*NetmapSnapshotRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// NetmapService_ServiceDesc is the grpc.ServiceDesc for NetmapService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var NetmapService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "neo.fs.v2.netmap.NetmapService", + HandlerType: (*NetmapServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "LocalNodeInfo", + Handler: _NetmapService_LocalNodeInfo_Handler, + }, + { + MethodName: "NetworkInfo", + Handler: _NetmapService_NetworkInfo_Handler, + }, + { + MethodName: "NetmapSnapshot", + Handler: _NetmapService_NetmapSnapshot_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "netmap/grpc/service.proto", +} diff --git a/pkg/api/netmap/grpc/types.go b/pkg/api/netmap/grpc/types.go new file mode 100644 index 000000000..f4e90f88d --- /dev/null +++ b/pkg/api/netmap/grpc/types.go @@ -0,0 +1,212 @@ +package netmap + +// SetReplicas of placement policy. +func (m *PlacementPolicy) SetReplicas(v []*Replica) { + m.Replicas = v +} + +// SetContainerBackupFactor of placement policy. +func (m *PlacementPolicy) SetContainerBackupFactor(v uint32) { + m.ContainerBackupFactor = v +} + +// SetSelectors of placement policy. +func (m *PlacementPolicy) SetSelectors(v []*Selector) { + m.Selectors = v +} + +// SetFilters of placement policy. +func (m *PlacementPolicy) SetFilters(v []*Filter) { + m.Filters = v +} + +// SetUnique of placement policy. +func (m *PlacementPolicy) SetUnique(unique bool) { + m.Unique = unique +} + +// SetName of placement filter. +func (m *Filter) SetName(v string) { + m.Name = v +} + +// SetKey of placement filter. +func (m *Filter) SetKey(v string) { + m.Key = v +} + +// SetOperation of placement filter. +func (m *Filter) SetOp(v Operation) { + m.Op = v +} + +// SetValue of placement filter. +func (m *Filter) SetValue(v string) { + m.Value = v +} + +// SetFilters sets sub-filters of placement filter. +func (m *Filter) SetFilters(v []*Filter) { + m.Filters = v +} + +// SetName of placement selector. +func (m *Selector) SetName(v string) { + m.Name = v +} + +// SetCount of nodes of placement selector. +func (m *Selector) SetCount(v uint32) { + m.Count = v +} + +// SetAttribute of nodes of placement selector. +func (m *Selector) SetAttribute(v string) { + m.Attribute = v +} + +// SetFilter of placement selector. +func (m *Selector) SetFilter(v string) { + m.Filter = v +} + +// SetClause of placement selector. +func (m *Selector) SetClause(v Clause) { + m.Clause = v +} + +// SetCount of object replica. +func (m *Replica) SetCount(v uint32) { + m.Count = v +} + +// SetSelector of object replica. +func (m *Replica) SetSelector(v string) { + m.Selector = v +} + +// SetKey sets key to the node attribute. +func (m *NodeInfo_Attribute) SetKey(v string) { + m.Key = v +} + +// SetValue sets value of the node attribute. +func (m *NodeInfo_Attribute) SetValue(v string) { + m.Value = v +} + +// SetParent sets value of the node parents. +func (m *NodeInfo_Attribute) SetParents(v []string) { + m.Parents = v +} + +// SetAddress sets node network address. +// +// Deprecated: use SetAddresses. +func (m *NodeInfo) SetAddress(v string) { + m.SetAddresses([]string{v}) +} + +// SetAddresses sets list of network addresses of the node. +func (m *NodeInfo) SetAddresses(v []string) { + m.Addresses = v +} + +// SetPublicKey sets node public key in a binary format. +func (m *NodeInfo) SetPublicKey(v []byte) { + m.PublicKey = v +} + +// SetAttributes sets list of the node attributes. +func (m *NodeInfo) SetAttributes(v []*NodeInfo_Attribute) { + m.Attributes = v +} + +// SetState sets node state. +func (m *NodeInfo) SetState(v NodeInfo_State) { + m.State = v +} + +// SetCurrentEpoch sets number of the current epoch. +func (x *NetworkInfo) SetCurrentEpoch(v uint64) { + x.CurrentEpoch = v +} + +// SetMagicNumber sets magic number of the sidechain. +func (x *NetworkInfo) SetMagicNumber(v uint64) { + x.MagicNumber = v +} + +// SetMsPerBlock sets MillisecondsPerBlock network parameter. +func (x *NetworkInfo) SetMsPerBlock(v int64) { + x.MsPerBlock = v +} + +// SetNetworkConfig sets NeoFS network configuration. +func (x *NetworkInfo) SetNetworkConfig(v *NetworkConfig) { + x.NetworkConfig = v +} + +// FromString parses Clause from a string representation, +// It is a reverse action to String(). +// +// Returns true if s was parsed successfully. +func (x *Clause) FromString(s string) bool { + i, ok := Clause_value[s] + if ok { + *x = Clause(i) + } + + return ok +} + +// FromString parses Operation from a string representation, +// It is a reverse action to String(). +// +// Returns true if s was parsed successfully. +func (x *Operation) FromString(s string) bool { + i, ok := Operation_value[s] + if ok { + *x = Operation(i) + } + + return ok +} + +// FromString parses NodeInfo_State from a string representation, +// It is a reverse action to String(). +// +// Returns true if s was parsed successfully. +func (x *NodeInfo_State) FromString(s string) bool { + i, ok := NodeInfo_State_value[s] + if ok { + *x = NodeInfo_State(i) + } + + return ok +} + +// SetKey sets parameter key. +func (x *NetworkConfig_Parameter) SetKey(v []byte) { + x.Key = v +} + +// SetValue sets parameter value. +func (x *NetworkConfig_Parameter) SetValue(v []byte) { + x.Value = v +} + +// SetParameters sets NeoFS network parameters. +func (x *NetworkConfig) SetParameters(v []*NetworkConfig_Parameter) { + x.Parameters = v +} + +// SetEpoch sets revision number of the Netmap. +func (x *Netmap) SetEpoch(v uint64) { + x.Epoch = v +} + +// SetNodes sets nodes presented in the Netmap. +func (x *Netmap) SetNodes(v []*NodeInfo) { + x.Nodes = v +} diff --git a/pkg/api/netmap/grpc/types.pb.go b/pkg/api/netmap/grpc/types.pb.go new file mode 100644 index 000000000..385713d48 --- /dev/null +++ b/pkg/api/netmap/grpc/types.pb.go @@ -0,0 +1,1366 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.33.0 +// protoc v4.25.3 +// source: netmap/grpc/types.proto + +package netmap + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// Operations on filters +type Operation int32 + +const ( + // No Operation defined + Operation_OPERATION_UNSPECIFIED Operation = 0 + // Equal + Operation_EQ Operation = 1 + // Not Equal + Operation_NE Operation = 2 + // Greater then + Operation_GT Operation = 3 + // Greater or equal + Operation_GE Operation = 4 + // Less then + Operation_LT Operation = 5 + // Less or equal + Operation_LE Operation = 6 + // Logical OR + Operation_OR Operation = 7 + // Logical AND + Operation_AND Operation = 8 + // Logical negation + Operation_NOT Operation = 9 +) + +// Enum value maps for Operation. +var ( + Operation_name = map[int32]string{ + 0: "OPERATION_UNSPECIFIED", + 1: "EQ", + 2: "NE", + 3: "GT", + 4: "GE", + 5: "LT", + 6: "LE", + 7: "OR", + 8: "AND", + 9: "NOT", + } + Operation_value = map[string]int32{ + "OPERATION_UNSPECIFIED": 0, + "EQ": 1, + "NE": 2, + "GT": 3, + "GE": 4, + "LT": 5, + "LE": 6, + "OR": 7, + "AND": 8, + "NOT": 9, + } +) + +func (x Operation) Enum() *Operation { + p := new(Operation) + *p = x + return p +} + +func (x Operation) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (Operation) Descriptor() protoreflect.EnumDescriptor { + return file_netmap_grpc_types_proto_enumTypes[0].Descriptor() +} + +func (Operation) Type() protoreflect.EnumType { + return &file_netmap_grpc_types_proto_enumTypes[0] +} + +func (x Operation) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use Operation.Descriptor instead. +func (Operation) EnumDescriptor() ([]byte, []int) { + return file_netmap_grpc_types_proto_rawDescGZIP(), []int{0} +} + +// Selector modifier shows how the node set will be formed. By default selector +// just groups nodes into a bucket by attribute, selecting nodes only by their +// hash distance. +type Clause int32 + +const ( + // No modifier defined. Nodes will be selected from the bucket randomly + Clause_CLAUSE_UNSPECIFIED Clause = 0 + // SAME will select only nodes having the same value of bucket attribute + Clause_SAME Clause = 1 + // DISTINCT will select nodes having different values of bucket attribute + Clause_DISTINCT Clause = 2 +) + +// Enum value maps for Clause. +var ( + Clause_name = map[int32]string{ + 0: "CLAUSE_UNSPECIFIED", + 1: "SAME", + 2: "DISTINCT", + } + Clause_value = map[string]int32{ + "CLAUSE_UNSPECIFIED": 0, + "SAME": 1, + "DISTINCT": 2, + } +) + +func (x Clause) Enum() *Clause { + p := new(Clause) + *p = x + return p +} + +func (x Clause) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (Clause) Descriptor() protoreflect.EnumDescriptor { + return file_netmap_grpc_types_proto_enumTypes[1].Descriptor() +} + +func (Clause) Type() protoreflect.EnumType { + return &file_netmap_grpc_types_proto_enumTypes[1] +} + +func (x Clause) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use Clause.Descriptor instead. +func (Clause) EnumDescriptor() ([]byte, []int) { + return file_netmap_grpc_types_proto_rawDescGZIP(), []int{1} +} + +// Represents the enumeration of various states of the NeoFS node. +type NodeInfo_State int32 + +const ( + // Unknown state + NodeInfo_UNSPECIFIED NodeInfo_State = 0 + // Active state in the network + NodeInfo_ONLINE NodeInfo_State = 1 + // Network unavailable state + NodeInfo_OFFLINE NodeInfo_State = 2 + // Maintenance state + NodeInfo_MAINTENANCE NodeInfo_State = 3 +) + +// Enum value maps for NodeInfo_State. +var ( + NodeInfo_State_name = map[int32]string{ + 0: "UNSPECIFIED", + 1: "ONLINE", + 2: "OFFLINE", + 3: "MAINTENANCE", + } + NodeInfo_State_value = map[string]int32{ + "UNSPECIFIED": 0, + "ONLINE": 1, + "OFFLINE": 2, + "MAINTENANCE": 3, + } +) + +func (x NodeInfo_State) Enum() *NodeInfo_State { + p := new(NodeInfo_State) + *p = x + return p +} + +func (x NodeInfo_State) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (NodeInfo_State) Descriptor() protoreflect.EnumDescriptor { + return file_netmap_grpc_types_proto_enumTypes[2].Descriptor() +} + +func (NodeInfo_State) Type() protoreflect.EnumType { + return &file_netmap_grpc_types_proto_enumTypes[2] +} + +func (x NodeInfo_State) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use NodeInfo_State.Descriptor instead. +func (NodeInfo_State) EnumDescriptor() ([]byte, []int) { + return file_netmap_grpc_types_proto_rawDescGZIP(), []int{4, 0} +} + +// This filter will return the subset of nodes from `NetworkMap` or another +// filter's results that will satisfy filter's conditions. +type Filter struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Name of the filter or a reference to a named filter. '*' means + // application to the whole unfiltered NetworkMap. At top level it's used as a + // filter name. At lower levels it's considered to be a reference to another + // named filter + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + // Key to filter + Key string `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"` + // Filtering operation + Op Operation `protobuf:"varint,3,opt,name=op,proto3,enum=neo.fs.v2.netmap.Operation" json:"op,omitempty"` + // Value to match + Value string `protobuf:"bytes,4,opt,name=value,proto3" json:"value,omitempty"` + // List of inner filters. Top level operation will be applied to the whole + // list. + Filters []*Filter `protobuf:"bytes,5,rep,name=filters,proto3" json:"filters,omitempty"` +} + +func (x *Filter) Reset() { + *x = Filter{} + if protoimpl.UnsafeEnabled { + mi := &file_netmap_grpc_types_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Filter) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Filter) ProtoMessage() {} + +func (x *Filter) ProtoReflect() protoreflect.Message { + mi := &file_netmap_grpc_types_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Filter.ProtoReflect.Descriptor instead. +func (*Filter) Descriptor() ([]byte, []int) { + return file_netmap_grpc_types_proto_rawDescGZIP(), []int{0} +} + +func (x *Filter) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Filter) GetKey() string { + if x != nil { + return x.Key + } + return "" +} + +func (x *Filter) GetOp() Operation { + if x != nil { + return x.Op + } + return Operation_OPERATION_UNSPECIFIED +} + +func (x *Filter) GetValue() string { + if x != nil { + return x.Value + } + return "" +} + +func (x *Filter) GetFilters() []*Filter { + if x != nil { + return x.Filters + } + return nil +} + +// Selector chooses a number of nodes from the bucket taking the nearest nodes +// to the provided `ContainerID` by hash distance. +type Selector struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Selector name to reference in object placement section + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + // How many nodes to select from the bucket + Count uint32 `protobuf:"varint,2,opt,name=count,proto3" json:"count,omitempty"` + // Selector modifier showing how to form a bucket + Clause Clause `protobuf:"varint,3,opt,name=clause,proto3,enum=neo.fs.v2.netmap.Clause" json:"clause,omitempty"` + // Bucket attribute to select from + Attribute string `protobuf:"bytes,4,opt,name=attribute,proto3" json:"attribute,omitempty"` + // Filter reference to select from + Filter string `protobuf:"bytes,5,opt,name=filter,proto3" json:"filter,omitempty"` +} + +func (x *Selector) Reset() { + *x = Selector{} + if protoimpl.UnsafeEnabled { + mi := &file_netmap_grpc_types_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Selector) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Selector) ProtoMessage() {} + +func (x *Selector) ProtoReflect() protoreflect.Message { + mi := &file_netmap_grpc_types_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Selector.ProtoReflect.Descriptor instead. +func (*Selector) Descriptor() ([]byte, []int) { + return file_netmap_grpc_types_proto_rawDescGZIP(), []int{1} +} + +func (x *Selector) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Selector) GetCount() uint32 { + if x != nil { + return x.Count + } + return 0 +} + +func (x *Selector) GetClause() Clause { + if x != nil { + return x.Clause + } + return Clause_CLAUSE_UNSPECIFIED +} + +func (x *Selector) GetAttribute() string { + if x != nil { + return x.Attribute + } + return "" +} + +func (x *Selector) GetFilter() string { + if x != nil { + return x.Filter + } + return "" +} + +// Number of object replicas in a set of nodes from the defined selector. If no +// selector set, the root bucket containing all possible nodes will be used by +// default. +type Replica struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // How many object replicas to put + Count uint32 `protobuf:"varint,1,opt,name=count,proto3" json:"count,omitempty"` + // Named selector bucket to put replicas + Selector string `protobuf:"bytes,2,opt,name=selector,proto3" json:"selector,omitempty"` + // Data shards count + EcDataCount uint32 `protobuf:"varint,6,opt,name=ec_data_count,json=ecDataCount,proto3" json:"ec_data_count,omitempty"` + // Parity shards count + EcParityCount uint32 `protobuf:"varint,7,opt,name=ec_parity_count,json=ecParityCount,proto3" json:"ec_parity_count,omitempty"` +} + +func (x *Replica) Reset() { + *x = Replica{} + if protoimpl.UnsafeEnabled { + mi := &file_netmap_grpc_types_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Replica) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Replica) ProtoMessage() {} + +func (x *Replica) ProtoReflect() protoreflect.Message { + mi := &file_netmap_grpc_types_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Replica.ProtoReflect.Descriptor instead. +func (*Replica) Descriptor() ([]byte, []int) { + return file_netmap_grpc_types_proto_rawDescGZIP(), []int{2} +} + +func (x *Replica) GetCount() uint32 { + if x != nil { + return x.Count + } + return 0 +} + +func (x *Replica) GetSelector() string { + if x != nil { + return x.Selector + } + return "" +} + +func (x *Replica) GetEcDataCount() uint32 { + if x != nil { + return x.EcDataCount + } + return 0 +} + +func (x *Replica) GetEcParityCount() uint32 { + if x != nil { + return x.EcParityCount + } + return 0 +} + +// Set of rules to select a subset of nodes from `NetworkMap` able to store +// container's objects. The format is simple enough to transpile from different +// storage policy definition languages. +type PlacementPolicy struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Rules to set number of object replicas and place each one into a named + // bucket + Replicas []*Replica `protobuf:"bytes,1,rep,name=replicas,proto3" json:"replicas,omitempty"` + // Container backup factor controls how deep NeoFS will search for nodes + // alternatives to include into container's nodes subset + ContainerBackupFactor uint32 `protobuf:"varint,2,opt,name=container_backup_factor,json=containerBackupFactor,proto3" json:"container_backup_factor,omitempty"` + // Set of Selectors to form the container's nodes subset + Selectors []*Selector `protobuf:"bytes,3,rep,name=selectors,proto3" json:"selectors,omitempty"` + // List of named filters to reference in selectors + Filters []*Filter `protobuf:"bytes,4,rep,name=filters,proto3" json:"filters,omitempty"` + // Unique flag defines non-overlapping application for replicas + Unique bool `protobuf:"varint,5,opt,name=unique,proto3" json:"unique,omitempty"` +} + +func (x *PlacementPolicy) Reset() { + *x = PlacementPolicy{} + if protoimpl.UnsafeEnabled { + mi := &file_netmap_grpc_types_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PlacementPolicy) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PlacementPolicy) ProtoMessage() {} + +func (x *PlacementPolicy) ProtoReflect() protoreflect.Message { + mi := &file_netmap_grpc_types_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PlacementPolicy.ProtoReflect.Descriptor instead. +func (*PlacementPolicy) Descriptor() ([]byte, []int) { + return file_netmap_grpc_types_proto_rawDescGZIP(), []int{3} +} + +func (x *PlacementPolicy) GetReplicas() []*Replica { + if x != nil { + return x.Replicas + } + return nil +} + +func (x *PlacementPolicy) GetContainerBackupFactor() uint32 { + if x != nil { + return x.ContainerBackupFactor + } + return 0 +} + +func (x *PlacementPolicy) GetSelectors() []*Selector { + if x != nil { + return x.Selectors + } + return nil +} + +func (x *PlacementPolicy) GetFilters() []*Filter { + if x != nil { + return x.Filters + } + return nil +} + +func (x *PlacementPolicy) GetUnique() bool { + if x != nil { + return x.Unique + } + return false +} + +// NeoFS node description +type NodeInfo struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Public key of the NeoFS node in a binary format + PublicKey []byte `protobuf:"bytes,1,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"` + // Ways to connect to a node + Addresses []string `protobuf:"bytes,2,rep,name=addresses,proto3" json:"addresses,omitempty"` + // Carries list of the NeoFS node attributes in a key-value form. Key name + // must be a node-unique valid UTF-8 string. Value can't be empty. NodeInfo + // structures with duplicated attribute names or attributes with empty values + // will be considered invalid. + Attributes []*NodeInfo_Attribute `protobuf:"bytes,3,rep,name=attributes,proto3" json:"attributes,omitempty"` + // Carries state of the NeoFS node + State NodeInfo_State `protobuf:"varint,4,opt,name=state,proto3,enum=neo.fs.v2.netmap.NodeInfo_State" json:"state,omitempty"` +} + +func (x *NodeInfo) Reset() { + *x = NodeInfo{} + if protoimpl.UnsafeEnabled { + mi := &file_netmap_grpc_types_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NodeInfo) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NodeInfo) ProtoMessage() {} + +func (x *NodeInfo) ProtoReflect() protoreflect.Message { + mi := &file_netmap_grpc_types_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NodeInfo.ProtoReflect.Descriptor instead. +func (*NodeInfo) Descriptor() ([]byte, []int) { + return file_netmap_grpc_types_proto_rawDescGZIP(), []int{4} +} + +func (x *NodeInfo) GetPublicKey() []byte { + if x != nil { + return x.PublicKey + } + return nil +} + +func (x *NodeInfo) GetAddresses() []string { + if x != nil { + return x.Addresses + } + return nil +} + +func (x *NodeInfo) GetAttributes() []*NodeInfo_Attribute { + if x != nil { + return x.Attributes + } + return nil +} + +func (x *NodeInfo) GetState() NodeInfo_State { + if x != nil { + return x.State + } + return NodeInfo_UNSPECIFIED +} + +// Network map structure +type Netmap struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Network map revision number. + Epoch uint64 `protobuf:"varint,1,opt,name=epoch,proto3" json:"epoch,omitempty"` + // Nodes presented in network. + Nodes []*NodeInfo `protobuf:"bytes,2,rep,name=nodes,proto3" json:"nodes,omitempty"` +} + +func (x *Netmap) Reset() { + *x = Netmap{} + if protoimpl.UnsafeEnabled { + mi := &file_netmap_grpc_types_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Netmap) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Netmap) ProtoMessage() {} + +func (x *Netmap) ProtoReflect() protoreflect.Message { + mi := &file_netmap_grpc_types_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Netmap.ProtoReflect.Descriptor instead. +func (*Netmap) Descriptor() ([]byte, []int) { + return file_netmap_grpc_types_proto_rawDescGZIP(), []int{5} +} + +func (x *Netmap) GetEpoch() uint64 { + if x != nil { + return x.Epoch + } + return 0 +} + +func (x *Netmap) GetNodes() []*NodeInfo { + if x != nil { + return x.Nodes + } + return nil +} + +// NeoFS network configuration +type NetworkConfig struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // List of parameter values + Parameters []*NetworkConfig_Parameter `protobuf:"bytes,1,rep,name=parameters,proto3" json:"parameters,omitempty"` +} + +func (x *NetworkConfig) Reset() { + *x = NetworkConfig{} + if protoimpl.UnsafeEnabled { + mi := &file_netmap_grpc_types_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NetworkConfig) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NetworkConfig) ProtoMessage() {} + +func (x *NetworkConfig) ProtoReflect() protoreflect.Message { + mi := &file_netmap_grpc_types_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NetworkConfig.ProtoReflect.Descriptor instead. +func (*NetworkConfig) Descriptor() ([]byte, []int) { + return file_netmap_grpc_types_proto_rawDescGZIP(), []int{6} +} + +func (x *NetworkConfig) GetParameters() []*NetworkConfig_Parameter { + if x != nil { + return x.Parameters + } + return nil +} + +// Information about NeoFS network +type NetworkInfo struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Number of the current epoch in the NeoFS network + CurrentEpoch uint64 `protobuf:"varint,1,opt,name=current_epoch,json=currentEpoch,proto3" json:"current_epoch,omitempty"` + // Magic number of the sidechain of the NeoFS network + MagicNumber uint64 `protobuf:"varint,2,opt,name=magic_number,json=magicNumber,proto3" json:"magic_number,omitempty"` + // MillisecondsPerBlock network parameter of the sidechain of the NeoFS + // network + MsPerBlock int64 `protobuf:"varint,3,opt,name=ms_per_block,json=msPerBlock,proto3" json:"ms_per_block,omitempty"` + // NeoFS network configuration + NetworkConfig *NetworkConfig `protobuf:"bytes,4,opt,name=network_config,json=networkConfig,proto3" json:"network_config,omitempty"` +} + +func (x *NetworkInfo) Reset() { + *x = NetworkInfo{} + if protoimpl.UnsafeEnabled { + mi := &file_netmap_grpc_types_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NetworkInfo) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NetworkInfo) ProtoMessage() {} + +func (x *NetworkInfo) ProtoReflect() protoreflect.Message { + mi := &file_netmap_grpc_types_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NetworkInfo.ProtoReflect.Descriptor instead. +func (*NetworkInfo) Descriptor() ([]byte, []int) { + return file_netmap_grpc_types_proto_rawDescGZIP(), []int{7} +} + +func (x *NetworkInfo) GetCurrentEpoch() uint64 { + if x != nil { + return x.CurrentEpoch + } + return 0 +} + +func (x *NetworkInfo) GetMagicNumber() uint64 { + if x != nil { + return x.MagicNumber + } + return 0 +} + +func (x *NetworkInfo) GetMsPerBlock() int64 { + if x != nil { + return x.MsPerBlock + } + return 0 +} + +func (x *NetworkInfo) GetNetworkConfig() *NetworkConfig { + if x != nil { + return x.NetworkConfig + } + return nil +} + +// Administrator-defined Attributes of the NeoFS Storage Node. +// +// `Attribute` is a Key-Value metadata pair. Key name must be a valid UTF-8 +// string. Value can't be empty. +// +// Attributes can be constructed into a chain of attributes: any attribute can +// have a parent attribute and a child attribute (except the first and the +// last one). A string representation of the chain of attributes in NeoFS +// Storage Node configuration uses ":" and "/" symbols, e.g.: +// +// `NEOFS_NODE_ATTRIBUTE_1=key1:val1/key2:val2` +// +// Therefore the string attribute representation in the Node configuration +// must use "\:", "\/" and "\\" escaped symbols if any of them appears in an +// attribute's key or value. +// +// Node's attributes are mostly used during Storage Policy evaluation to +// calculate object's placement and find a set of nodes satisfying policy +// requirements. There are some "well-known" node attributes common to all the +// Storage Nodes in the network and used implicitly with default values if not +// explicitly set: +// +// - Capacity \ +// Total available disk space in Gigabytes. +// - Price \ +// Price in GAS tokens for storing one GB of data during one Epoch. In node +// attributes it's a string presenting floating point number with comma or +// point delimiter for decimal part. In the Network Map it will be saved as +// 64-bit unsigned integer representing number of minimal token fractions. +// - UN-LOCODE \ +// Node's geographic location in +// [UN/LOCODE](https://www.unece.org/cefact/codesfortrade/codes_index.html) +// format approximated to the nearest point defined in the standard. +// - CountryCode \ +// Country code in +// [ISO 3166-1_alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) +// format. Calculated automatically from `UN-LOCODE` attribute. +// - Country \ +// Country short name in English, as defined in +// [ISO-3166](https://www.iso.org/obp/ui/#search). Calculated automatically +// from `UN-LOCODE` attribute. +// - Location \ +// Place names are given, whenever possible, in their national language +// versions as expressed in the Roman alphabet using the 26 characters of +// the character set adopted for international trade data interchange, +// written without diacritics . Calculated automatically from `UN-LOCODE` +// attribute. +// - SubDivCode \ +// Country's administrative subdivision where node is located. Calculated +// automatically from `UN-LOCODE` attribute based on `SubDiv` field. +// Presented in [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) +// format. +// - SubDiv \ +// Country's administrative subdivision name, as defined in +// [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2). Calculated +// automatically from `UN-LOCODE` attribute. +// - Continent \ +// Node's continent name according to the [Seven-Continent model] +// (https://en.wikipedia.org/wiki/Continent#Number). Calculated +// automatically from `UN-LOCODE` attribute. +// - ExternalAddr +// Node's preferred way for communications with external clients. +// Clients SHOULD use these addresses if possible. +// Must contain a comma-separated list of multi-addresses. +// +// For detailed description of each well-known attribute please see the +// corresponding section in NeoFS Technical Specification. +type NodeInfo_Attribute struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Key of the node attribute + Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` + // Value of the node attribute + Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` + // Parent keys, if any. For example for `City` it could be `Region` and + // `Country`. + Parents []string `protobuf:"bytes,3,rep,name=parents,proto3" json:"parents,omitempty"` +} + +func (x *NodeInfo_Attribute) Reset() { + *x = NodeInfo_Attribute{} + if protoimpl.UnsafeEnabled { + mi := &file_netmap_grpc_types_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NodeInfo_Attribute) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NodeInfo_Attribute) ProtoMessage() {} + +func (x *NodeInfo_Attribute) ProtoReflect() protoreflect.Message { + mi := &file_netmap_grpc_types_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NodeInfo_Attribute.ProtoReflect.Descriptor instead. +func (*NodeInfo_Attribute) Descriptor() ([]byte, []int) { + return file_netmap_grpc_types_proto_rawDescGZIP(), []int{4, 0} +} + +func (x *NodeInfo_Attribute) GetKey() string { + if x != nil { + return x.Key + } + return "" +} + +func (x *NodeInfo_Attribute) GetValue() string { + if x != nil { + return x.Value + } + return "" +} + +func (x *NodeInfo_Attribute) GetParents() []string { + if x != nil { + return x.Parents + } + return nil +} + +// Single configuration parameter. Key MUST be network-unique. +// +// System parameters: +// - **AuditFee** \ +// Fee paid by the storage group owner to the Inner Ring member. +// Value: little-endian integer. Default: 0. +// - **BasicIncomeRate** \ +// Cost of storing one gigabyte of data for a period of one epoch. Paid by +// container owner to container nodes. +// Value: little-endian integer. Default: 0. +// - **ContainerAliasFee** \ +// Fee paid for named container's creation by the container owner. +// Value: little-endian integer. Default: 0. +// - **ContainerFee** \ +// Fee paid for container creation by the container owner. +// Value: little-endian integer. Default: 0. +// - **EpochDuration** \ +// NeoFS epoch duration measured in Sidechain blocks. +// Value: little-endian integer. Default: 0. +// - **HomomorphicHashingDisabled** \ +// Flag of disabling the homomorphic hashing of objects' payload. +// Value: true if any byte != 0. Default: false. +// - **InnerRingCandidateFee** \ +// Fee for entrance to the Inner Ring paid by the candidate. +// Value: little-endian integer. Default: 0. +// - **MaintenanceModeAllowed** \ +// Flag allowing setting the MAINTENANCE state to storage nodes. +// Value: true if any byte != 0. Default: false. +// - **MaxObjectSize** \ +// Maximum size of physically stored NeoFS object measured in bytes. +// Value: little-endian integer. Default: 0. +// - **WithdrawFee** \ +// Fee paid for withdrawal of funds paid by the account owner. +// Value: little-endian integer. Default: 0. +// - **MaxECDataCount** \ +// Maximum number of data shards for EC placement policy. +// Value: little-endian integer. Default: 0. +// - **MaxECParityCount** \ +// Maximum number of parity shards for EC placement policy. +// Value: little-endian integer. Default: 0. +type NetworkConfig_Parameter struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Parameter key. UTF-8 encoded string + Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` + // Parameter value + Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` +} + +func (x *NetworkConfig_Parameter) Reset() { + *x = NetworkConfig_Parameter{} + if protoimpl.UnsafeEnabled { + mi := &file_netmap_grpc_types_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NetworkConfig_Parameter) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NetworkConfig_Parameter) ProtoMessage() {} + +func (x *NetworkConfig_Parameter) ProtoReflect() protoreflect.Message { + mi := &file_netmap_grpc_types_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NetworkConfig_Parameter.ProtoReflect.Descriptor instead. +func (*NetworkConfig_Parameter) Descriptor() ([]byte, []int) { + return file_netmap_grpc_types_proto_rawDescGZIP(), []int{6, 0} +} + +func (x *NetworkConfig_Parameter) GetKey() []byte { + if x != nil { + return x.Key + } + return nil +} + +func (x *NetworkConfig_Parameter) GetValue() []byte { + if x != nil { + return x.Value + } + return nil +} + +var File_netmap_grpc_types_proto protoreflect.FileDescriptor + +var file_netmap_grpc_types_proto_rawDesc = []byte{ + 0x0a, 0x17, 0x6e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x74, 0x79, + 0x70, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x10, 0x6e, 0x65, 0x6f, 0x2e, 0x66, + 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x22, 0xa5, 0x01, 0x0a, 0x06, + 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, + 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2b, 0x0a, 0x02, + 0x6f, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, + 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x2e, 0x4f, 0x70, 0x65, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x02, 0x6f, 0x70, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, + 0x32, 0x0a, 0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x18, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6e, 0x65, 0x74, + 0x6d, 0x61, 0x70, 0x2e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x07, 0x66, 0x69, 0x6c, 0x74, + 0x65, 0x72, 0x73, 0x22, 0x9c, 0x01, 0x0a, 0x08, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, + 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0d, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x30, 0x0a, 0x06, 0x63, 0x6c, + 0x61, 0x75, 0x73, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x6e, 0x65, 0x6f, + 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x2e, 0x43, 0x6c, + 0x61, 0x75, 0x73, 0x65, 0x52, 0x06, 0x63, 0x6c, 0x61, 0x75, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, + 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x69, + 0x6c, 0x74, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x66, 0x69, 0x6c, 0x74, + 0x65, 0x72, 0x22, 0x87, 0x01, 0x0a, 0x07, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x12, 0x14, + 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, + 0x12, 0x22, 0x0a, 0x0d, 0x65, 0x63, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x63, 0x6f, 0x75, 0x6e, + 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x65, 0x63, 0x44, 0x61, 0x74, 0x61, 0x43, + 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x26, 0x0a, 0x0f, 0x65, 0x63, 0x5f, 0x70, 0x61, 0x72, 0x69, 0x74, + 0x79, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x65, + 0x63, 0x50, 0x61, 0x72, 0x69, 0x74, 0x79, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x86, 0x02, 0x0a, + 0x0f, 0x50, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x12, 0x35, 0x0a, 0x08, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x73, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6e, + 0x65, 0x74, 0x6d, 0x61, 0x70, 0x2e, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x52, 0x08, 0x72, + 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x73, 0x12, 0x36, 0x0a, 0x17, 0x63, 0x6f, 0x6e, 0x74, 0x61, + 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x5f, 0x66, 0x61, 0x63, 0x74, + 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x15, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, + 0x6e, 0x65, 0x72, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x46, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x12, + 0x38, 0x0a, 0x09, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6e, + 0x65, 0x74, 0x6d, 0x61, 0x70, 0x2e, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x09, + 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x32, 0x0a, 0x07, 0x66, 0x69, 0x6c, + 0x74, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6e, 0x65, 0x6f, + 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x2e, 0x46, 0x69, + 0x6c, 0x74, 0x65, 0x72, 0x52, 0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x12, 0x16, 0x0a, + 0x06, 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x75, + 0x6e, 0x69, 0x71, 0x75, 0x65, 0x22, 0xd8, 0x02, 0x0a, 0x08, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, + 0x66, 0x6f, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, + 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x02, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x12, + 0x44, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, + 0x6e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x2e, + 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x36, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, + 0x2e, 0x6e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, + 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x1a, 0x4d, 0x0a, + 0x09, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x03, 0x20, + 0x03, 0x28, 0x09, 0x52, 0x07, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x42, 0x0a, 0x05, + 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x0f, 0x0a, 0x0b, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, + 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x4f, 0x4e, 0x4c, 0x49, 0x4e, 0x45, + 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x4f, 0x46, 0x46, 0x4c, 0x49, 0x4e, 0x45, 0x10, 0x02, 0x12, + 0x0f, 0x0a, 0x0b, 0x4d, 0x41, 0x49, 0x4e, 0x54, 0x45, 0x4e, 0x41, 0x4e, 0x43, 0x45, 0x10, 0x03, + 0x22, 0x50, 0x0a, 0x06, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x70, + 0x6f, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, + 0x12, 0x30, 0x0a, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x1a, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6e, 0x65, 0x74, 0x6d, + 0x61, 0x70, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x05, 0x6e, 0x6f, 0x64, + 0x65, 0x73, 0x22, 0x8f, 0x01, 0x0a, 0x0d, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x12, 0x49, 0x0a, 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, + 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, + 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x2e, 0x4e, 0x65, 0x74, 0x77, + 0x6f, 0x72, 0x6b, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, + 0x74, 0x65, 0x72, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x1a, + 0x33, 0x0a, 0x09, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x12, 0x10, 0x0a, 0x03, + 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, + 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x22, 0xbf, 0x01, 0x0a, 0x0b, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, + 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, + 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x63, 0x75, 0x72, + 0x72, 0x65, 0x6e, 0x74, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x21, 0x0a, 0x0c, 0x6d, 0x61, 0x67, + 0x69, 0x63, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x0b, 0x6d, 0x61, 0x67, 0x69, 0x63, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x20, 0x0a, 0x0c, + 0x6d, 0x73, 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x0a, 0x6d, 0x73, 0x50, 0x65, 0x72, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x46, + 0x0a, 0x0e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, + 0x76, 0x32, 0x2e, 0x6e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x2e, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, + 0x6b, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0d, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2a, 0x70, 0x0a, 0x09, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x0a, 0x15, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, + 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x06, + 0x0a, 0x02, 0x45, 0x51, 0x10, 0x01, 0x12, 0x06, 0x0a, 0x02, 0x4e, 0x45, 0x10, 0x02, 0x12, 0x06, + 0x0a, 0x02, 0x47, 0x54, 0x10, 0x03, 0x12, 0x06, 0x0a, 0x02, 0x47, 0x45, 0x10, 0x04, 0x12, 0x06, + 0x0a, 0x02, 0x4c, 0x54, 0x10, 0x05, 0x12, 0x06, 0x0a, 0x02, 0x4c, 0x45, 0x10, 0x06, 0x12, 0x06, + 0x0a, 0x02, 0x4f, 0x52, 0x10, 0x07, 0x12, 0x07, 0x0a, 0x03, 0x41, 0x4e, 0x44, 0x10, 0x08, 0x12, + 0x07, 0x0a, 0x03, 0x4e, 0x4f, 0x54, 0x10, 0x09, 0x2a, 0x38, 0x0a, 0x06, 0x43, 0x6c, 0x61, 0x75, + 0x73, 0x65, 0x12, 0x16, 0x0a, 0x12, 0x43, 0x4c, 0x41, 0x55, 0x53, 0x45, 0x5f, 0x55, 0x4e, 0x53, + 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x53, 0x41, + 0x4d, 0x45, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x44, 0x49, 0x53, 0x54, 0x49, 0x4e, 0x43, 0x54, + 0x10, 0x02, 0x42, 0x61, 0x5a, 0x42, 0x67, 0x69, 0x74, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, + 0x73, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, 0x75, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, + 0x4c, 0x61, 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2d, 0x61, 0x70, 0x69, 0x2d, + 0x67, 0x6f, 0x2f, 0x76, 0x32, 0x2f, 0x6e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x2f, 0x67, 0x72, 0x70, + 0x63, 0x3b, 0x6e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0xaa, 0x02, 0x1a, 0x4e, 0x65, 0x6f, 0x2e, 0x46, + 0x69, 0x6c, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x41, 0x50, 0x49, 0x2e, 0x4e, + 0x65, 0x74, 0x6d, 0x61, 0x70, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_netmap_grpc_types_proto_rawDescOnce sync.Once + file_netmap_grpc_types_proto_rawDescData = file_netmap_grpc_types_proto_rawDesc +) + +func file_netmap_grpc_types_proto_rawDescGZIP() []byte { + file_netmap_grpc_types_proto_rawDescOnce.Do(func() { + file_netmap_grpc_types_proto_rawDescData = protoimpl.X.CompressGZIP(file_netmap_grpc_types_proto_rawDescData) + }) + return file_netmap_grpc_types_proto_rawDescData +} + +var file_netmap_grpc_types_proto_enumTypes = make([]protoimpl.EnumInfo, 3) +var file_netmap_grpc_types_proto_msgTypes = make([]protoimpl.MessageInfo, 10) +var file_netmap_grpc_types_proto_goTypes = []interface{}{ + (Operation)(0), // 0: neo.fs.v2.netmap.Operation + (Clause)(0), // 1: neo.fs.v2.netmap.Clause + (NodeInfo_State)(0), // 2: neo.fs.v2.netmap.NodeInfo.State + (*Filter)(nil), // 3: neo.fs.v2.netmap.Filter + (*Selector)(nil), // 4: neo.fs.v2.netmap.Selector + (*Replica)(nil), // 5: neo.fs.v2.netmap.Replica + (*PlacementPolicy)(nil), // 6: neo.fs.v2.netmap.PlacementPolicy + (*NodeInfo)(nil), // 7: neo.fs.v2.netmap.NodeInfo + (*Netmap)(nil), // 8: neo.fs.v2.netmap.Netmap + (*NetworkConfig)(nil), // 9: neo.fs.v2.netmap.NetworkConfig + (*NetworkInfo)(nil), // 10: neo.fs.v2.netmap.NetworkInfo + (*NodeInfo_Attribute)(nil), // 11: neo.fs.v2.netmap.NodeInfo.Attribute + (*NetworkConfig_Parameter)(nil), // 12: neo.fs.v2.netmap.NetworkConfig.Parameter +} +var file_netmap_grpc_types_proto_depIdxs = []int32{ + 0, // 0: neo.fs.v2.netmap.Filter.op:type_name -> neo.fs.v2.netmap.Operation + 3, // 1: neo.fs.v2.netmap.Filter.filters:type_name -> neo.fs.v2.netmap.Filter + 1, // 2: neo.fs.v2.netmap.Selector.clause:type_name -> neo.fs.v2.netmap.Clause + 5, // 3: neo.fs.v2.netmap.PlacementPolicy.replicas:type_name -> neo.fs.v2.netmap.Replica + 4, // 4: neo.fs.v2.netmap.PlacementPolicy.selectors:type_name -> neo.fs.v2.netmap.Selector + 3, // 5: neo.fs.v2.netmap.PlacementPolicy.filters:type_name -> neo.fs.v2.netmap.Filter + 11, // 6: neo.fs.v2.netmap.NodeInfo.attributes:type_name -> neo.fs.v2.netmap.NodeInfo.Attribute + 2, // 7: neo.fs.v2.netmap.NodeInfo.state:type_name -> neo.fs.v2.netmap.NodeInfo.State + 7, // 8: neo.fs.v2.netmap.Netmap.nodes:type_name -> neo.fs.v2.netmap.NodeInfo + 12, // 9: neo.fs.v2.netmap.NetworkConfig.parameters:type_name -> neo.fs.v2.netmap.NetworkConfig.Parameter + 9, // 10: neo.fs.v2.netmap.NetworkInfo.network_config:type_name -> neo.fs.v2.netmap.NetworkConfig + 11, // [11:11] is the sub-list for method output_type + 11, // [11:11] is the sub-list for method input_type + 11, // [11:11] is the sub-list for extension type_name + 11, // [11:11] is the sub-list for extension extendee + 0, // [0:11] is the sub-list for field type_name +} + +func init() { file_netmap_grpc_types_proto_init() } +func file_netmap_grpc_types_proto_init() { + if File_netmap_grpc_types_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_netmap_grpc_types_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Filter); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_netmap_grpc_types_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Selector); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_netmap_grpc_types_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Replica); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_netmap_grpc_types_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PlacementPolicy); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_netmap_grpc_types_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NodeInfo); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_netmap_grpc_types_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Netmap); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_netmap_grpc_types_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NetworkConfig); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_netmap_grpc_types_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NetworkInfo); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_netmap_grpc_types_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NodeInfo_Attribute); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_netmap_grpc_types_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NetworkConfig_Parameter); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_netmap_grpc_types_proto_rawDesc, + NumEnums: 3, + NumMessages: 10, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_netmap_grpc_types_proto_goTypes, + DependencyIndexes: file_netmap_grpc_types_proto_depIdxs, + EnumInfos: file_netmap_grpc_types_proto_enumTypes, + MessageInfos: file_netmap_grpc_types_proto_msgTypes, + }.Build() + File_netmap_grpc_types_proto = out.File + file_netmap_grpc_types_proto_rawDesc = nil + file_netmap_grpc_types_proto_goTypes = nil + file_netmap_grpc_types_proto_depIdxs = nil +} diff --git a/pkg/api/netmap/json.go b/pkg/api/netmap/json.go new file mode 100644 index 000000000..c4bcd0db8 --- /dev/null +++ b/pkg/api/netmap/json.go @@ -0,0 +1,62 @@ +package netmap + +import ( + netmap "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/netmap/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/message" +) + +func (p *PlacementPolicy) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(p) +} + +func (p *PlacementPolicy) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(p, data, new(netmap.PlacementPolicy)) +} + +func (f *Filter) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(f) +} + +func (f *Filter) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(f, data, new(netmap.Filter)) +} + +func (s *Selector) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(s) +} + +func (s *Selector) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(s, data, new(netmap.Selector)) +} + +func (r *Replica) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(r) +} + +func (r *Replica) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(r, data, new(netmap.Replica)) +} + +func (a *Attribute) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(a) +} + +func (a *Attribute) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(a, data, new(netmap.NodeInfo_Attribute)) +} + +func (ni *NodeInfo) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(ni) +} + +func (ni *NodeInfo) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(ni, data, new(netmap.NodeInfo)) +} + +func (i *NetworkInfo) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(i) +} + +func (i *NetworkInfo) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(i, data, new(netmap.NetworkInfo)) +} diff --git a/pkg/api/netmap/marshal.go b/pkg/api/netmap/marshal.go new file mode 100644 index 000000000..ea62f365b --- /dev/null +++ b/pkg/api/netmap/marshal.go @@ -0,0 +1,576 @@ +package netmap + +import ( + netmap "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/netmap/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/message" + protoutil "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/util/proto" +) + +const ( + nameFilterField = 1 + keyFilterField = 2 + opFilterField = 3 + valueFilterField = 4 + filtersFilterField = 5 + + nameSelectorField = 1 + countSelectorField = 2 + clauseSelectorField = 3 + attributeSelectorField = 4 + filterSelectorField = 5 + + countReplicaField = 1 + selectorReplicaField = 2 + ecDataCountReplicaField = 3 + ecParityCountReplicaField = 4 + + replicasPolicyField = 1 + backupPolicyField = 2 + selectorsPolicyField = 3 + filtersPolicyField = 4 + uniquePolicyField = 5 + + keyAttributeField = 1 + valueAttributeField = 2 + parentsAttributeField = 3 + + keyNodeInfoField = 1 + addressNodeInfoField = 2 + attributesNodeInfoField = 3 + stateNodeInfoField = 4 + + versionInfoResponseBodyField = 1 + nodeInfoResponseBodyField = 2 +) + +func (f *Filter) StableMarshal(buf []byte) []byte { + if f == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, f.StableSize()) + } + + var offset int + + offset += protoutil.StringMarshal(nameFilterField, buf[offset:], f.name) + offset += protoutil.StringMarshal(keyFilterField, buf[offset:], f.key) + offset += protoutil.EnumMarshal(opFilterField, buf[offset:], int32(f.op)) + offset += protoutil.StringMarshal(valueFilterField, buf[offset:], f.value) + + for i := range f.filters { + offset += protoutil.NestedStructureMarshal(filtersFilterField, buf[offset:], &f.filters[i]) + } + + return buf +} + +func (f *Filter) StableSize() (size int) { + if f == nil { + return 0 + } + + size += protoutil.StringSize(nameFilterField, f.name) + size += protoutil.StringSize(keyFilterField, f.key) + size += protoutil.EnumSize(opFilterField, int32(f.op)) + size += protoutil.StringSize(valueFilterField, f.value) + for i := range f.filters { + size += protoutil.NestedStructureSize(filtersFilterField, &f.filters[i]) + } + + return size +} + +func (f *Filter) Unmarshal(data []byte) error { + return message.Unmarshal(f, data, new(netmap.Filter)) +} + +func (s *Selector) StableMarshal(buf []byte) []byte { + if s == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, s.StableSize()) + } + + var offset int + + offset += protoutil.StringMarshal(nameSelectorField, buf[offset:], s.name) + offset += protoutil.UInt32Marshal(countSelectorField, buf[offset:], s.count) + offset += protoutil.EnumMarshal(clauseSelectorField, buf[offset:], int32(s.clause)) + offset += protoutil.StringMarshal(attributeSelectorField, buf[offset:], s.attribute) + protoutil.StringMarshal(filterSelectorField, buf[offset:], s.filter) + + return buf +} + +func (s *Selector) StableSize() (size int) { + if s == nil { + return 0 + } + + size += protoutil.StringSize(nameSelectorField, s.name) + size += protoutil.UInt32Size(countSelectorField, s.count) + size += protoutil.EnumSize(countSelectorField, int32(s.clause)) + size += protoutil.StringSize(attributeSelectorField, s.attribute) + size += protoutil.StringSize(filterSelectorField, s.filter) + + return size +} + +func (s *Selector) Unmarshal(data []byte) error { + return message.Unmarshal(s, data, new(netmap.Selector)) +} + +func (r *Replica) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + var offset int + + offset += protoutil.UInt32Marshal(countReplicaField, buf[offset:], r.count) + offset += protoutil.StringMarshal(selectorReplicaField, buf[offset:], r.selector) + offset += protoutil.UInt32Marshal(ecDataCountReplicaField, buf[offset:], r.ecDataCount) + protoutil.UInt32Marshal(ecParityCountReplicaField, buf[offset:], r.ecParityCount) + + return buf +} + +func (r *Replica) StableSize() (size int) { + if r == nil { + return 0 + } + + size += protoutil.UInt32Size(countReplicaField, r.count) + size += protoutil.StringSize(selectorReplicaField, r.selector) + size += protoutil.UInt32Size(ecDataCountReplicaField, r.ecDataCount) + size += protoutil.UInt32Size(ecParityCountReplicaField, r.ecParityCount) + + return size +} + +func (r *Replica) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(netmap.Replica)) +} + +func (p *PlacementPolicy) StableMarshal(buf []byte) []byte { + if p == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, p.StableSize()) + } + + var offset int + + for i := range p.replicas { + offset += protoutil.NestedStructureMarshal(replicasPolicyField, buf[offset:], &p.replicas[i]) + } + + offset += protoutil.UInt32Marshal(backupPolicyField, buf[offset:], p.backupFactor) + + for i := range p.selectors { + offset += protoutil.NestedStructureMarshal(selectorsPolicyField, buf[offset:], &p.selectors[i]) + } + + for i := range p.filters { + offset += protoutil.NestedStructureMarshal(filtersPolicyField, buf[offset:], &p.filters[i]) + } + + protoutil.BoolMarshal(uniquePolicyField, buf[offset:], p.unique) + + return buf +} + +func (p *PlacementPolicy) StableSize() (size int) { + if p == nil { + return 0 + } + + for i := range p.replicas { + size += protoutil.NestedStructureSize(replicasPolicyField, &p.replicas[i]) + } + + size += protoutil.UInt32Size(backupPolicyField, p.backupFactor) + + for i := range p.selectors { + size += protoutil.NestedStructureSize(selectorsPolicyField, &p.selectors[i]) + } + + for i := range p.filters { + size += protoutil.NestedStructureSize(filtersPolicyField, &p.filters[i]) + } + + size += protoutil.BoolSize(uniquePolicyField, p.unique) + + return size +} + +func (p *PlacementPolicy) Unmarshal(data []byte) error { + return message.Unmarshal(p, data, new(netmap.PlacementPolicy)) +} + +func (a *Attribute) StableMarshal(buf []byte) []byte { + if a == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, a.StableSize()) + } + + var offset int + + offset += protoutil.StringMarshal(keyAttributeField, buf[offset:], a.key) + offset += protoutil.StringMarshal(valueAttributeField, buf[offset:], a.value) + + for i := range a.parents { + offset += protoutil.StringMarshal(parentsAttributeField, buf[offset:], a.parents[i]) + } + + return buf +} + +func (a *Attribute) StableSize() (size int) { + if a == nil { + return 0 + } + + size += protoutil.StringSize(keyAttributeField, a.key) + size += protoutil.StringSize(valueAttributeField, a.value) + + for i := range a.parents { + size += protoutil.StringSize(parentsAttributeField, a.parents[i]) + } + + return size +} + +func (a *Attribute) Unmarshal(data []byte) error { + return message.Unmarshal(a, data, new(netmap.NodeInfo_Attribute)) +} + +func (ni *NodeInfo) StableMarshal(buf []byte) []byte { + if ni == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, ni.StableSize()) + } + + var offset int + + offset += protoutil.BytesMarshal(keyNodeInfoField, buf[offset:], ni.publicKey) + offset += protoutil.RepeatedStringMarshal(addressNodeInfoField, buf[offset:], ni.addresses) + + for i := range ni.attributes { + offset += protoutil.NestedStructureMarshal(attributesNodeInfoField, buf[offset:], &ni.attributes[i]) + } + + protoutil.EnumMarshal(stateNodeInfoField, buf[offset:], int32(ni.state)) + + return buf +} + +func (ni *NodeInfo) StableSize() (size int) { + if ni == nil { + return 0 + } + + size += protoutil.BytesSize(keyNodeInfoField, ni.publicKey) + size += protoutil.RepeatedStringSize(addressNodeInfoField, ni.addresses) + + for i := range ni.attributes { + size += protoutil.NestedStructureSize(attributesNodeInfoField, &ni.attributes[i]) + } + + size += protoutil.EnumSize(stateNodeInfoField, int32(ni.state)) + + return size +} + +func (ni *NodeInfo) Unmarshal(data []byte) error { + return message.Unmarshal(ni, data, new(netmap.NodeInfo)) +} + +func (l *LocalNodeInfoRequestBody) StableMarshal(_ []byte) []byte { + return nil +} + +func (l *LocalNodeInfoRequestBody) StableSize() (size int) { + return 0 +} + +func (l *LocalNodeInfoRequestBody) Unmarshal([]byte) error { + return nil +} + +func (l *LocalNodeInfoResponseBody) StableMarshal(buf []byte) []byte { + if l == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, l.StableSize()) + } + + var offset int + + offset += protoutil.NestedStructureMarshal(versionInfoResponseBodyField, buf[offset:], l.version) + protoutil.NestedStructureMarshal(nodeInfoResponseBodyField, buf[offset:], l.nodeInfo) + + return buf +} + +func (l *LocalNodeInfoResponseBody) StableSize() (size int) { + if l == nil { + return 0 + } + + size += protoutil.NestedStructureSize(versionInfoResponseBodyField, l.version) + size += protoutil.NestedStructureSize(nodeInfoResponseBodyField, l.nodeInfo) + + return size +} + +func (l *LocalNodeInfoResponseBody) Unmarshal(data []byte) error { + return message.Unmarshal(l, data, new(netmap.LocalNodeInfoResponse_Body)) +} + +const ( + _ = iota + netPrmKeyFNum + netPrmValFNum +) + +func (x *NetworkParameter) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, x.StableSize()) + } + + var offset int + + offset += protoutil.BytesMarshal(netPrmKeyFNum, buf[offset:], x.k) + protoutil.BytesMarshal(netPrmValFNum, buf[offset:], x.v) + + return buf +} + +func (x *NetworkParameter) StableSize() (size int) { + if x == nil { + return 0 + } + + size += protoutil.BytesSize(netPrmKeyFNum, x.k) + size += protoutil.BytesSize(netPrmValFNum, x.v) + + return size +} + +const ( + _ = iota + netCfgPrmsFNum +) + +func (x *NetworkConfig) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, x.StableSize()) + } + + var offset int + + for i := range x.ps { + offset += protoutil.NestedStructureMarshal(netCfgPrmsFNum, buf[offset:], &x.ps[i]) + } + + return buf +} + +func (x *NetworkConfig) StableSize() (size int) { + if x == nil { + return 0 + } + + for i := range x.ps { + size += protoutil.NestedStructureSize(netCfgPrmsFNum, &x.ps[i]) + } + + return size +} + +const ( + _ = iota + netInfoCurEpochFNum + netInfoMagicNumFNum + netInfoMSPerBlockFNum + netInfoCfgFNum +) + +func (i *NetworkInfo) StableMarshal(buf []byte) []byte { + if i == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, i.StableSize()) + } + + var offset int + + offset += protoutil.UInt64Marshal(netInfoCurEpochFNum, buf[offset:], i.curEpoch) + offset += protoutil.UInt64Marshal(netInfoMagicNumFNum, buf[offset:], i.magicNum) + offset += protoutil.Int64Marshal(netInfoMSPerBlockFNum, buf[offset:], i.msPerBlock) + protoutil.NestedStructureMarshal(netInfoCfgFNum, buf[offset:], i.netCfg) + + return buf +} + +func (i *NetworkInfo) StableSize() (size int) { + if i == nil { + return 0 + } + + size += protoutil.UInt64Size(netInfoCurEpochFNum, i.curEpoch) + size += protoutil.UInt64Size(netInfoMagicNumFNum, i.magicNum) + size += protoutil.Int64Size(netInfoMSPerBlockFNum, i.msPerBlock) + size += protoutil.NestedStructureSize(netInfoCfgFNum, i.netCfg) + + return size +} + +func (i *NetworkInfo) Unmarshal(data []byte) error { + return message.Unmarshal(i, data, new(netmap.NetworkInfo)) +} + +func (l *NetworkInfoRequestBody) StableMarshal(_ []byte) []byte { + return nil +} + +func (l *NetworkInfoRequestBody) StableSize() (size int) { + return 0 +} + +func (l *NetworkInfoRequestBody) Unmarshal(data []byte) error { + return message.Unmarshal(l, data, new(netmap.NetworkInfoRequest_Body)) +} + +const ( + _ = iota + netInfoRespBodyNetInfoFNum +) + +func (i *NetworkInfoResponseBody) StableMarshal(buf []byte) []byte { + if i == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, i.StableSize()) + } + + protoutil.NestedStructureMarshal(netInfoRespBodyNetInfoFNum, buf, i.netInfo) + + return buf +} + +func (i *NetworkInfoResponseBody) StableSize() (size int) { + if i == nil { + return 0 + } + + size += protoutil.NestedStructureSize(netInfoRespBodyNetInfoFNum, i.netInfo) + + return size +} + +func (i *NetworkInfoResponseBody) Unmarshal(data []byte) error { + return message.Unmarshal(i, data, new(netmap.NetworkInfoResponse_Body)) +} + +const ( + _ = iota + fNumNetMapEpoch + fNumNetMapNodes +) + +func (x *NetMap) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, x.StableSize()) + } + + offset := protoutil.UInt64Marshal(fNumNetMapEpoch, buf, x.epoch) + + for i := range x.nodes { + offset += protoutil.NestedStructureMarshal(fNumNetMapNodes, buf[offset:], &x.nodes[i]) + } + + return buf +} + +func (x *NetMap) StableSize() (size int) { + if x != nil { + size = protoutil.UInt64Size(fNumNetMapEpoch, x.epoch) + + for i := range x.nodes { + size += protoutil.NestedStructureSize(fNumNetMapNodes, &x.nodes[i]) + } + } + + return +} + +func (x *SnapshotRequestBody) StableMarshal([]byte) []byte { + return nil +} + +func (x *SnapshotRequestBody) StableSize() int { + return 0 +} + +const ( + _ = iota + fNumSnapshotResponseBodyNetMap +) + +func (x *SnapshotResponseBody) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, x.StableSize()) + } + + protoutil.NestedStructureMarshal(fNumSnapshotResponseBodyNetMap, buf, x.netMap) + + return buf +} + +func (x *SnapshotResponseBody) StableSize() (size int) { + if x != nil { + size = protoutil.NestedStructureSize(fNumSnapshotResponseBodyNetMap, x.netMap) + } + + return +} diff --git a/pkg/api/netmap/message_test.go b/pkg/api/netmap/message_test.go new file mode 100644 index 000000000..bbbf76be4 --- /dev/null +++ b/pkg/api/netmap/message_test.go @@ -0,0 +1,32 @@ +package netmap_test + +import ( + "testing" + + netmaptest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/netmap/test" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/message" + messagetest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/message/test" +) + +func TestMessageConvert(t *testing.T) { + messagetest.TestRPCMessage(t, + func(empty bool) message.Message { return netmaptest.GenerateFilter(empty) }, + func(empty bool) message.Message { return netmaptest.GenerateSelector(empty) }, + func(empty bool) message.Message { return netmaptest.GenerateReplica(empty) }, + func(empty bool) message.Message { return netmaptest.GeneratePlacementPolicy(empty) }, + func(empty bool) message.Message { return netmaptest.GenerateAttribute(empty) }, + func(empty bool) message.Message { return netmaptest.GenerateNodeInfo(empty) }, + func(empty bool) message.Message { return netmaptest.GenerateLocalNodeInfoRequest(empty) }, + func(empty bool) message.Message { return netmaptest.GenerateLocalNodeInfoResponseBody(empty) }, + func(empty bool) message.Message { return netmaptest.GenerateNetworkParameter(empty) }, + func(empty bool) message.Message { return netmaptest.GenerateNetworkConfig(empty) }, + func(empty bool) message.Message { return netmaptest.GenerateNetworkInfo(empty) }, + func(empty bool) message.Message { return netmaptest.GenerateNetworkInfoRequest(empty) }, + func(empty bool) message.Message { return netmaptest.GenerateNetworkInfoResponseBody(empty) }, + func(empty bool) message.Message { return netmaptest.GenerateNetMap(empty) }, + func(empty bool) message.Message { return netmaptest.GenerateSnapshotRequestBody(empty) }, + func(empty bool) message.Message { return netmaptest.GenerateSnapshotRequest(empty) }, + func(empty bool) message.Message { return netmaptest.GenerateSnapshotResponseBody(empty) }, + func(empty bool) message.Message { return netmaptest.GenerateSnapshotResponse(empty) }, + ) +} diff --git a/pkg/api/netmap/string.go b/pkg/api/netmap/string.go new file mode 100644 index 000000000..3dd7abf47 --- /dev/null +++ b/pkg/api/netmap/string.go @@ -0,0 +1,68 @@ +package netmap + +import ( + netmap "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/netmap/grpc" +) + +// String returns string representation of Clause. +func (x Clause) String() string { + return ClauseToGRPCMessage(x).String() +} + +// FromString parses Clause from a string representation. +// It is a reverse action to String(). +// +// Returns true if s was parsed successfully. +func (x *Clause) FromString(s string) bool { + var g netmap.Clause + + ok := g.FromString(s) + + if ok { + *x = ClauseFromGRPCMessage(g) + } + + return ok +} + +// String returns string representation of Operation. +func (x Operation) String() string { + return OperationToGRPCMessage(x).String() +} + +// FromString parses Operation from a string representation. +// It is a reverse action to String(). +// +// Returns true if s was parsed successfully. +func (x *Operation) FromString(s string) bool { + var g netmap.Operation + + ok := g.FromString(s) + + if ok { + *x = OperationFromGRPCMessage(g) + } + + return ok +} + +// String returns string representation of NodeState. +func (x NodeState) String() string { + return NodeStateToGRPCMessage(x).String() +} + +// FromString parses NodeState from a string representation. +// It is a reverse action to String(). +// +// Returns true if s was parsed successfully. +func (x *NodeState) FromString(s string) bool { + var g netmap.NodeInfo_State + + ok := g.FromString(s) + + if ok { + *x = NodeStateFromRPCMessage(g) + } + + return ok +} diff --git a/pkg/api/netmap/test/generate.go b/pkg/api/netmap/test/generate.go new file mode 100644 index 000000000..42a6a3eed --- /dev/null +++ b/pkg/api/netmap/test/generate.go @@ -0,0 +1,323 @@ +package netmaptest + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/netmap" + refstest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs/test" + sessiontest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session/test" +) + +func GenerateFilter(empty bool) *netmap.Filter { + return generateFilter(empty, true) +} + +func generateFilter(empty, withSub bool) *netmap.Filter { + m := new(netmap.Filter) + + if !empty { + m.SetKey("filter key") + m.SetValue("filter value") + m.SetName("filter name") + m.SetOp(1) + + if withSub { + m.SetFilters([]netmap.Filter{ + *generateFilter(empty, false), + *generateFilter(empty, false), + }) + } + } + + return m +} + +func GenerateFilters(empty bool) []netmap.Filter { + var res []netmap.Filter + + if !empty { + res = append(res, + *GenerateFilter(false), + *GenerateFilter(false), + ) + } + + return res +} + +func GenerateSelector(empty bool) *netmap.Selector { + m := new(netmap.Selector) + + if !empty { + m.SetCount(66) + m.SetAttribute("selector attribute") + m.SetFilter("select filter") + m.SetName("select name") + m.SetClause(1) + } + + return m +} + +func GenerateSelectors(empty bool) []netmap.Selector { + var res []netmap.Selector + + if !empty { + res = append(res, + *GenerateSelector(false), + *GenerateSelector(false), + ) + } + + return res +} + +func GenerateReplica(empty bool) *netmap.Replica { + m := new(netmap.Replica) + + if !empty { + m.SetCount(42) + m.SetSelector("replica selector") + } + + return m +} + +func GenerateReplicas(empty bool) []netmap.Replica { + var res []netmap.Replica + + if !empty { + res = append(res, + *GenerateReplica(false), + *GenerateReplica(false), + ) + } + + return res +} + +func GeneratePlacementPolicy(empty bool) *netmap.PlacementPolicy { + m := new(netmap.PlacementPolicy) + + if !empty { + m.SetContainerBackupFactor(322) + m.SetFilters(GenerateFilters(false)) + m.SetSelectors(GenerateSelectors(false)) + m.SetReplicas(GenerateReplicas(false)) + m.SetUnique(true) + } + + return m +} + +func GenerateAttribute(empty bool) *netmap.Attribute { + m := new(netmap.Attribute) + + if !empty { + m.SetKey("attribute key") + m.SetValue("attribute val") + } + + return m +} + +func GenerateAttributes(empty bool) []netmap.Attribute { + var res []netmap.Attribute + + if !empty { + res = append(res, + *GenerateAttribute(false), + *GenerateAttribute(false), + ) + } + + return res +} + +func GenerateNodeInfo(empty bool) *netmap.NodeInfo { + m := new(netmap.NodeInfo) + + if !empty { + m.SetAddresses("node address", "node address 2") + m.SetPublicKey([]byte{1, 2, 3}) + m.SetState(33) + m.SetAttributes(GenerateAttributes(empty)) + } + + return m +} + +func GenerateLocalNodeInfoRequestBody(_ bool) *netmap.LocalNodeInfoRequestBody { + m := new(netmap.LocalNodeInfoRequestBody) + + return m +} + +func GenerateLocalNodeInfoRequest(empty bool) *netmap.LocalNodeInfoRequest { + m := new(netmap.LocalNodeInfoRequest) + + if !empty { + m.SetBody(GenerateLocalNodeInfoRequestBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateRequestMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateRequestVerificationHeader(empty)) + + return m +} + +func GenerateLocalNodeInfoResponseBody(empty bool) *netmap.LocalNodeInfoResponseBody { + m := new(netmap.LocalNodeInfoResponseBody) + + if !empty { + m.SetNodeInfo(GenerateNodeInfo(false)) + } + + m.SetVersion(refstest.GenerateVersion(empty)) + + return m +} + +func GenerateLocalNodeInfoResponse(empty bool) *netmap.LocalNodeInfoResponse { + m := new(netmap.LocalNodeInfoResponse) + + if !empty { + m.SetBody(GenerateLocalNodeInfoResponseBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateResponseMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateResponseVerificationHeader(empty)) + + return m +} + +func GenerateNetworkParameter(empty bool) *netmap.NetworkParameter { + m := new(netmap.NetworkParameter) + + if !empty { + m.SetKey([]byte("key")) + m.SetValue([]byte("value")) + } + + return m +} + +func GenerateNetworkConfig(empty bool) *netmap.NetworkConfig { + m := new(netmap.NetworkConfig) + + if !empty { + m.SetParameters( + *GenerateNetworkParameter(empty), + *GenerateNetworkParameter(empty), + ) + } + + return m +} + +func GenerateNetworkInfo(empty bool) *netmap.NetworkInfo { + m := new(netmap.NetworkInfo) + + if !empty { + m.SetMagicNumber(228) + m.SetCurrentEpoch(666) + m.SetMsPerBlock(5678) + m.SetNetworkConfig(GenerateNetworkConfig(empty)) + } + + return m +} + +func GenerateNetworkInfoRequestBody(_ bool) *netmap.NetworkInfoRequestBody { + m := new(netmap.NetworkInfoRequestBody) + + return m +} + +func GenerateNetworkInfoRequest(empty bool) *netmap.NetworkInfoRequest { + m := new(netmap.NetworkInfoRequest) + + if !empty { + m.SetBody(GenerateNetworkInfoRequestBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateRequestMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateRequestVerificationHeader(empty)) + + return m +} + +func GenerateNetworkInfoResponseBody(empty bool) *netmap.NetworkInfoResponseBody { + m := new(netmap.NetworkInfoResponseBody) + + if !empty { + m.SetNetworkInfo(GenerateNetworkInfo(false)) + } + + return m +} + +func GenerateNetworkInfoResponse(empty bool) *netmap.NetworkInfoResponse { + m := new(netmap.NetworkInfoResponse) + + if !empty { + m.SetBody(GenerateNetworkInfoResponseBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateResponseMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateResponseVerificationHeader(empty)) + + return m +} + +func GenerateNetMap(empty bool) *netmap.NetMap { + m := new(netmap.NetMap) + + if !empty { + m.SetEpoch(987) + m.SetNodes([]netmap.NodeInfo{ + *GenerateNodeInfo(false), + *GenerateNodeInfo(false), + }) + } + + return m +} + +func GenerateSnapshotRequestBody(_ bool) *netmap.SnapshotRequestBody { + return new(netmap.SnapshotRequestBody) +} + +func GenerateSnapshotRequest(empty bool) *netmap.SnapshotRequest { + m := new(netmap.SnapshotRequest) + + if !empty { + m.SetBody(GenerateSnapshotRequestBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateRequestMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateRequestVerificationHeader(empty)) + + return m +} + +func GenerateSnapshotResponseBody(empty bool) *netmap.SnapshotResponseBody { + m := new(netmap.SnapshotResponseBody) + + if !empty { + m.SetNetMap(GenerateNetMap(false)) + } + + return m +} + +func GenerateSnapshotResponse(empty bool) *netmap.SnapshotResponse { + m := new(netmap.SnapshotResponse) + + if !empty { + m.SetBody(GenerateSnapshotResponseBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateResponseMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateResponseVerificationHeader(empty)) + + return m +} diff --git a/pkg/api/netmap/types.go b/pkg/api/netmap/types.go new file mode 100644 index 000000000..f3027122f --- /dev/null +++ b/pkg/api/netmap/types.go @@ -0,0 +1,778 @@ +package netmap + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" +) + +type LocalNodeInfoRequest struct { + body *LocalNodeInfoRequestBody + + session.RequestHeaders +} + +type LocalNodeInfoResponse struct { + body *LocalNodeInfoResponseBody + + session.ResponseHeaders +} + +// NetworkInfoRequest is a structure of NetworkInfo request. +type NetworkInfoRequest struct { + body *NetworkInfoRequestBody + + session.RequestHeaders +} + +// NetworkInfoResponse is a structure of NetworkInfo response. +type NetworkInfoResponse struct { + body *NetworkInfoResponseBody + + session.ResponseHeaders +} + +type Filter struct { + name string + key string + op Operation + value string + filters []Filter +} + +type Selector struct { + name string + count uint32 + clause Clause + attribute string + filter string +} + +type Replica struct { + count uint32 + selector string + + ecDataCount uint32 + ecParityCount uint32 +} + +type Operation uint32 + +type PlacementPolicy struct { + replicas []Replica + backupFactor uint32 + selectors []Selector + filters []Filter + unique bool +} + +// Attribute of storage node. +type Attribute struct { + key string + value string + parents []string +} + +// NodeInfo of storage node. +type NodeInfo struct { + publicKey []byte + addresses []string + attributes []Attribute + state NodeState +} + +// NodeState of storage node. +type NodeState uint32 + +// Clause of placement selector. +type Clause uint32 + +type LocalNodeInfoRequestBody struct{} + +type LocalNodeInfoResponseBody struct { + version *refs.Version + nodeInfo *NodeInfo +} + +const ( + UnspecifiedState NodeState = iota + Online + Offline + Maintenance +) + +const ( + UnspecifiedOperation Operation = iota + EQ + NE + GT + GE + LT + LE + OR + AND + NOT +) + +const ( + UnspecifiedClause Clause = iota + Same + Distinct +) + +func (f *Filter) GetFilters() []Filter { + if f != nil { + return f.filters + } + + return nil +} + +func (f *Filter) SetFilters(filters []Filter) { + f.filters = filters +} + +func (f *Filter) GetValue() string { + if f != nil { + return f.value + } + + return "" +} + +func (f *Filter) SetValue(value string) { + f.value = value +} + +func (f *Filter) GetOp() Operation { + if f != nil { + return f.op + } + return UnspecifiedOperation +} + +func (f *Filter) SetOp(op Operation) { + f.op = op +} + +func (f *Filter) GetKey() string { + if f != nil { + return f.key + } + + return "" +} + +func (f *Filter) SetKey(key string) { + f.key = key +} + +func (f *Filter) GetName() string { + if f != nil { + return f.name + } + + return "" +} + +func (f *Filter) SetName(name string) { + f.name = name +} + +func (s *Selector) GetFilter() string { + if s != nil { + return s.filter + } + + return "" +} + +func (s *Selector) SetFilter(filter string) { + s.filter = filter +} + +func (s *Selector) GetAttribute() string { + if s != nil { + return s.attribute + } + + return "" +} + +func (s *Selector) SetAttribute(attribute string) { + s.attribute = attribute +} + +func (s *Selector) GetClause() Clause { + if s != nil { + return s.clause + } + + return UnspecifiedClause +} + +func (s *Selector) SetClause(clause Clause) { + s.clause = clause +} + +func (s *Selector) GetCount() uint32 { + if s != nil { + return s.count + } + + return 0 +} + +func (s *Selector) SetCount(count uint32) { + s.count = count +} + +func (s *Selector) GetName() string { + if s != nil { + return s.name + } + + return "" +} + +func (s *Selector) SetName(name string) { + s.name = name +} + +func (r *Replica) GetSelector() string { + if r != nil { + return r.selector + } + + return "" +} + +func (r *Replica) SetSelector(selector string) { + r.selector = selector +} + +func (r *Replica) GetCount() uint32 { + if r != nil { + return r.count + } + + return 0 +} + +func (r *Replica) SetCount(count uint32) { + r.count = count +} + +func (r *Replica) GetECDataCount() uint32 { + if r != nil { + return r.ecDataCount + } + + return 0 +} + +func (r *Replica) SetECDataCount(count uint32) { + r.ecDataCount = count +} + +func (r *Replica) GetECParityCount() uint32 { + if r != nil { + return r.ecParityCount + } + + return 0 +} + +func (r *Replica) SetECParityCount(count uint32) { + r.ecParityCount = count +} + +func (p *PlacementPolicy) GetUnique() bool { + if p != nil { + return p.unique + } + return false +} + +func (p *PlacementPolicy) SetUnique(unique bool) { + p.unique = unique +} + +func (p *PlacementPolicy) GetFilters() []Filter { + if p != nil { + return p.filters + } + + return nil +} + +func (p *PlacementPolicy) SetFilters(filters []Filter) { + p.filters = filters +} + +func (p *PlacementPolicy) GetSelectors() []Selector { + if p != nil { + return p.selectors + } + + return nil +} + +func (p *PlacementPolicy) SetSelectors(selectors []Selector) { + p.selectors = selectors +} + +func (p *PlacementPolicy) GetContainerBackupFactor() uint32 { + if p != nil { + return p.backupFactor + } + + return 0 +} + +func (p *PlacementPolicy) SetContainerBackupFactor(backupFactor uint32) { + p.backupFactor = backupFactor +} + +func (p *PlacementPolicy) GetReplicas() []Replica { + return p.replicas +} + +func (p *PlacementPolicy) SetReplicas(replicas []Replica) { + p.replicas = replicas +} + +func (a *Attribute) GetKey() string { + if a != nil { + return a.key + } + + return "" +} + +func (a *Attribute) SetKey(v string) { + a.key = v +} + +func (a *Attribute) GetValue() string { + if a != nil { + return a.value + } + + return "" +} + +func (a *Attribute) SetValue(v string) { + a.value = v +} + +func (a *Attribute) GetParents() []string { + if a != nil { + return a.parents + } + + return nil +} + +func (a *Attribute) SetParents(parent []string) { + a.parents = parent +} + +func (ni *NodeInfo) GetPublicKey() []byte { + if ni != nil { + return ni.publicKey + } + + return nil +} + +func (ni *NodeInfo) SetPublicKey(v []byte) { + ni.publicKey = v +} + +// GetAddress returns node's network address. +// +// Deprecated: use IterateAddresses. +func (ni *NodeInfo) GetAddress() (addr string) { + ni.IterateAddresses(func(s string) bool { + addr = s + return true + }) + + return +} + +// SetAddress sets node's network address. +// +// Deprecated: use SetAddresses. +func (ni *NodeInfo) SetAddress(v string) { + ni.SetAddresses(v) +} + +// SetAddresses sets list of network addresses of the node. +func (ni *NodeInfo) SetAddresses(v ...string) { + ni.addresses = v +} + +// NumberOfAddresses returns number of network addresses of the node. +func (ni *NodeInfo) NumberOfAddresses() int { + if ni != nil { + return len(ni.addresses) + } + + return 0 +} + +// IterateAddresses iterates over network addresses of the node. +// Breaks iteration on f's true return. +// +// Handler should not be nil. +func (ni *NodeInfo) IterateAddresses(f func(string) bool) { + if ni != nil { + for i := range ni.addresses { + if f(ni.addresses[i]) { + break + } + } + } +} + +func (ni *NodeInfo) GetAttributes() []Attribute { + if ni != nil { + return ni.attributes + } + + return nil +} + +func (ni *NodeInfo) SetAttributes(v []Attribute) { + ni.attributes = v +} + +func (ni *NodeInfo) GetState() NodeState { + if ni != nil { + return ni.state + } + + return UnspecifiedState +} + +func (ni *NodeInfo) SetState(state NodeState) { + ni.state = state +} + +func (l *LocalNodeInfoResponseBody) GetVersion() *refs.Version { + if l != nil { + return l.version + } + + return nil +} + +func (l *LocalNodeInfoResponseBody) SetVersion(version *refs.Version) { + l.version = version +} + +func (l *LocalNodeInfoResponseBody) GetNodeInfo() *NodeInfo { + if l != nil { + return l.nodeInfo + } + + return nil +} + +func (l *LocalNodeInfoResponseBody) SetNodeInfo(nodeInfo *NodeInfo) { + l.nodeInfo = nodeInfo +} + +func (l *LocalNodeInfoRequest) GetBody() *LocalNodeInfoRequestBody { + if l != nil { + return l.body + } + return nil +} + +func (l *LocalNodeInfoRequest) SetBody(body *LocalNodeInfoRequestBody) { + l.body = body +} + +func (l *LocalNodeInfoResponse) GetBody() *LocalNodeInfoResponseBody { + if l != nil { + return l.body + } + return nil +} + +func (l *LocalNodeInfoResponse) SetBody(body *LocalNodeInfoResponseBody) { + l.body = body +} + +// NetworkParameter represents NeoFS network parameter. +type NetworkParameter struct { + k, v []byte +} + +// GetKey returns parameter key. +func (x *NetworkParameter) GetKey() []byte { + if x != nil { + return x.k + } + + return nil +} + +// SetKey sets parameter key. +func (x *NetworkParameter) SetKey(k []byte) { + x.k = k +} + +// GetValue returns parameter value. +func (x *NetworkParameter) GetValue() []byte { + if x != nil { + return x.v + } + + return nil +} + +// SetValue sets parameter value. +func (x *NetworkParameter) SetValue(v []byte) { + x.v = v +} + +// NetworkConfig represents NeoFS network configuration. +type NetworkConfig struct { + ps []NetworkParameter +} + +// NumberOfParameters returns number of network parameters. +func (x *NetworkConfig) NumberOfParameters() int { + if x != nil { + return len(x.ps) + } + + return 0 +} + +// IterateParameters iterates over network parameters. +// Breaks iteration on f's true return. +// +// Handler must not be nil. +func (x *NetworkConfig) IterateParameters(f func(*NetworkParameter) bool) { + if x != nil { + for i := range x.ps { + if f(&x.ps[i]) { + break + } + } + } +} + +// SetParameters sets list of network parameters. +func (x *NetworkConfig) SetParameters(v ...NetworkParameter) { + x.ps = v +} + +// NetworkInfo groups information about +// NeoFS network. +type NetworkInfo struct { + curEpoch, magicNum uint64 + + msPerBlock int64 + + netCfg *NetworkConfig +} + +// GetCurrentEpoch returns number of the current epoch. +func (i *NetworkInfo) GetCurrentEpoch() uint64 { + if i != nil { + return i.curEpoch + } + + return 0 +} + +// SetCurrentEpoch sets number of the current epoch. +func (i *NetworkInfo) SetCurrentEpoch(epoch uint64) { + i.curEpoch = epoch +} + +// GetMagicNumber returns magic number of the sidechain. +func (i *NetworkInfo) GetMagicNumber() uint64 { + if i != nil { + return i.magicNum + } + + return 0 +} + +// SetMagicNumber sets magic number of the sidechain. +func (i *NetworkInfo) SetMagicNumber(magic uint64) { + i.magicNum = magic +} + +// GetMsPerBlock returns MillisecondsPerBlock network parameter. +func (i *NetworkInfo) GetMsPerBlock() int64 { + if i != nil { + return i.msPerBlock + } + + return 0 +} + +// SetMsPerBlock sets MillisecondsPerBlock network parameter. +func (i *NetworkInfo) SetMsPerBlock(v int64) { + i.msPerBlock = v +} + +// GetNetworkConfig returns NeoFS network configuration. +func (i *NetworkInfo) GetNetworkConfig() *NetworkConfig { + if i != nil { + return i.netCfg + } + + return nil +} + +// SetNetworkConfig sets NeoFS network configuration. +func (i *NetworkInfo) SetNetworkConfig(v *NetworkConfig) { + i.netCfg = v +} + +// NetworkInfoRequestBody is a structure of NetworkInfo request body. +type NetworkInfoRequestBody struct{} + +// NetworkInfoResponseBody is a structure of NetworkInfo response body. +type NetworkInfoResponseBody struct { + netInfo *NetworkInfo +} + +// GetNetworkInfo returns information about the NeoFS network. +func (i *NetworkInfoResponseBody) GetNetworkInfo() *NetworkInfo { + if i != nil { + return i.netInfo + } + + return nil +} + +// SetNetworkInfo sets information about the NeoFS network. +func (i *NetworkInfoResponseBody) SetNetworkInfo(netInfo *NetworkInfo) { + i.netInfo = netInfo +} + +func (l *NetworkInfoRequest) GetBody() *NetworkInfoRequestBody { + if l != nil { + return l.body + } + return nil +} + +func (l *NetworkInfoRequest) SetBody(body *NetworkInfoRequestBody) { + l.body = body +} + +func (l *NetworkInfoResponse) GetBody() *NetworkInfoResponseBody { + if l != nil { + return l.body + } + return nil +} + +func (l *NetworkInfoResponse) SetBody(body *NetworkInfoResponseBody) { + l.body = body +} + +// NetMap represents structure of NeoFS network map. +type NetMap struct { + epoch uint64 + + nodes []NodeInfo +} + +// Epoch returns revision number of the NetMap. +func (x *NetMap) Epoch() uint64 { + if x != nil { + return x.epoch + } + + return 0 +} + +// SetEpoch sets revision number of the NetMap. +func (x *NetMap) SetEpoch(v uint64) { + x.epoch = v +} + +// Nodes returns nodes presented in the NetMap. +func (x *NetMap) Nodes() []NodeInfo { + if x != nil { + return x.nodes + } + + return nil +} + +// SetNodes sets nodes presented in the NetMap. +func (x *NetMap) SetNodes(v []NodeInfo) { + x.nodes = v +} + +// SnapshotRequestBody represents structure of Snapshot request body. +type SnapshotRequestBody struct{} + +// SnapshotRequest represents structure of Snapshot request. +type SnapshotRequest struct { + body *SnapshotRequestBody + + session.RequestHeaders +} + +func (x *SnapshotRequest) GetBody() *SnapshotRequestBody { + if x != nil { + return x.body + } + + return nil +} + +func (x *SnapshotRequest) SetBody(body *SnapshotRequestBody) { + x.body = body +} + +// SnapshotResponseBody represents structure of Snapshot response body. +type SnapshotResponseBody struct { + netMap *NetMap +} + +// NetMap returns current NetMap. +func (x *SnapshotResponseBody) NetMap() *NetMap { + if x != nil { + return x.netMap + } + + return nil +} + +// SetNetMap sets current NetMap. +func (x *SnapshotResponseBody) SetNetMap(netMap *NetMap) { + x.netMap = netMap +} + +// SnapshotResponse represents structure of Snapshot response. +type SnapshotResponse struct { + body *SnapshotResponseBody + + session.ResponseHeaders +} + +func (x *SnapshotResponse) GetBody() *SnapshotResponseBody { + if x != nil { + return x.body + } + + return nil +} + +func (x *SnapshotResponse) SetBody(body *SnapshotResponseBody) { + x.body = body +} diff --git a/pkg/api/object/attributes.go b/pkg/api/object/attributes.go new file mode 100644 index 000000000..7f4fca02c --- /dev/null +++ b/pkg/api/object/attributes.go @@ -0,0 +1,187 @@ +package object + +import ( + "errors" + "fmt" + "strconv" +) + +// SysAttributePrefix is a prefix of key to system attribute. +const SysAttributePrefix = "__SYSTEM__" + +const ( + // SysAttributeUploadID marks smaller parts of a split bigger object. + SysAttributeUploadID = SysAttributePrefix + "UPLOAD_ID" + + // SysAttributeExpEpoch tells GC to delete object after that epoch. + SysAttributeExpEpoch = SysAttributePrefix + "EXPIRATION_EPOCH" + + // SysAttributeTickEpoch defines what epoch must produce object + // notification. + SysAttributeTickEpoch = SysAttributePrefix + "TICK_EPOCH" + + // SysAttributeTickTopic defines what topic object notification + // must be sent to. + SysAttributeTickTopic = SysAttributePrefix + "TICK_TOPIC" +) + +// SysAttributePrefixNeoFS is a prefix of key to system attribute. +// Deprecated: use SysAttributePrefix. +const SysAttributePrefixNeoFS = "__NEOFS__" + +const ( + // SysAttributeUploadIDNeoFS marks smaller parts of a split bigger object. + // Deprecated: use SysAttributeUploadID. + SysAttributeUploadIDNeoFS = SysAttributePrefixNeoFS + "UPLOAD_ID" + + // SysAttributeExpEpochNeoFS tells GC to delete object after that epoch. + // Deprecated: use SysAttributeExpEpoch. + SysAttributeExpEpochNeoFS = SysAttributePrefixNeoFS + "EXPIRATION_EPOCH" + + // SysAttributeTickEpochNeoFS defines what epoch must produce object + // notification. + // Deprecated: use SysAttributeTickEpoch. + SysAttributeTickEpochNeoFS = SysAttributePrefixNeoFS + "TICK_EPOCH" + + // SysAttributeTickTopicNeoFS defines what topic object notification + // must be sent to. + // Deprecated: use SysAttributeTickTopic. + SysAttributeTickTopicNeoFS = SysAttributePrefixNeoFS + "TICK_TOPIC" +) + +// NotificationInfo groups information about object notification +// that can be written to object. +// +// Topic is an optional field. +type NotificationInfo struct { + epoch uint64 + topic string +} + +// Epoch returns object notification tick +// epoch. +func (n NotificationInfo) Epoch() uint64 { + return n.epoch +} + +// SetEpoch sets object notification tick +// epoch. +func (n *NotificationInfo) SetEpoch(epoch uint64) { + n.epoch = epoch +} + +// Topic return optional object notification +// topic. +func (n NotificationInfo) Topic() string { + return n.topic +} + +// SetTopic sets optional object notification +// topic. +func (n *NotificationInfo) SetTopic(topic string) { + n.topic = topic +} + +// WriteNotificationInfo writes NotificationInfo to the Object via attributes. Object must not be nil. +// +// Existing notification attributes are expected to be key-unique, otherwise undefined behavior. +func WriteNotificationInfo(o *Object, ni NotificationInfo) { + h := o.GetHeader() + if h == nil { + h = new(Header) + o.SetHeader(h) + } + + var ( + attrs = h.GetAttributes() + + epoch = strconv.FormatUint(ni.Epoch(), 10) + topic = ni.Topic() + + changedEpoch bool + changedTopic bool + deleteIndex = -1 + ) + + for i := range attrs { + switch attrs[i].GetKey() { + case SysAttributeTickEpoch, SysAttributeTickEpochNeoFS: + attrs[i].SetValue(epoch) + changedEpoch = true + case SysAttributeTickTopic, SysAttributeTickTopicNeoFS: + changedTopic = true + + if topic == "" { + deleteIndex = i + break + } + + attrs[i].SetValue(topic) + } + + if changedEpoch && changedTopic { + break + } + } + + if deleteIndex != -1 { + // approach without allocation/waste + // coping works since the attributes + // order is not important + attrs[deleteIndex] = attrs[len(attrs)-1] + attrs = attrs[:len(attrs)-1] + } + + if !changedEpoch { + index := len(attrs) + attrs = append(attrs, Attribute{}) + attrs[index].SetKey(SysAttributeTickEpoch) + attrs[index].SetValue(epoch) + } + + if !changedTopic && topic != "" { + index := len(attrs) + attrs = append(attrs, Attribute{}) + attrs[index].SetKey(SysAttributeTickTopic) + attrs[index].SetValue(topic) + } + + h.SetAttributes(attrs) +} + +// ErrNotificationNotSet means that object does not have notification. +var ErrNotificationNotSet = errors.New("notification for object is not set") + +// GetNotificationInfo looks for object notification attributes. Object must not be nil. +// Returns ErrNotificationNotSet if no corresponding attributes +// were found. +// +// Existing notification attributes are expected to be key-unique, otherwise undefined behavior. +func GetNotificationInfo(o *Object) (*NotificationInfo, error) { + var ( + foundEpoch bool + ni = new(NotificationInfo) + ) + + for _, attr := range o.GetHeader().GetAttributes() { + switch key := attr.GetKey(); key { + case SysAttributeTickEpoch, SysAttributeTickEpochNeoFS: + epoch, err := strconv.ParseUint(attr.GetValue(), 10, 64) + if err != nil { + return nil, fmt.Errorf("could not parse epoch: %w", err) + } + + ni.SetEpoch(epoch) + + foundEpoch = true + case SysAttributeTickTopic, SysAttributeTickTopicNeoFS: + ni.SetTopic(attr.GetValue()) + } + } + + if !foundEpoch { + return nil, ErrNotificationNotSet + } + + return ni, nil +} diff --git a/pkg/api/object/attributes_test.go b/pkg/api/object/attributes_test.go new file mode 100644 index 000000000..85635da73 --- /dev/null +++ b/pkg/api/object/attributes_test.go @@ -0,0 +1,89 @@ +package object + +import ( + "strconv" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestSetNotification(t *testing.T) { + o := new(Object) + + ni := NotificationInfo{ + epoch: 10, + topic: "test", + } + + WriteNotificationInfo(o, ni) + + var foundEpoch, foundTopic bool + + for _, attr := range o.GetHeader().GetAttributes() { + switch key := attr.GetKey(); key { + case SysAttributeTickEpoch: + require.Equal(t, false, foundEpoch) + + uEpoch, err := strconv.ParseUint(attr.GetValue(), 10, 64) + require.NoError(t, err) + + require.Equal(t, ni.Epoch(), uEpoch) + foundEpoch = true + case SysAttributeTickTopic: + require.Equal(t, false, foundTopic) + require.Equal(t, ni.Topic(), attr.GetValue()) + foundTopic = true + } + } + + require.Equal(t, true, foundEpoch && foundTopic) +} + +func TestGetNotification(t *testing.T) { + o := new(Object) + + attr := []Attribute{ + {SysAttributeTickEpoch, "10"}, + {SysAttributeTickTopic, "test"}, + } + + h := new(Header) + h.SetAttributes(attr) + + o.SetHeader(h) + + t.Run("No error", func(t *testing.T) { + ni, err := GetNotificationInfo(o) + require.NoError(t, err) + + require.Equal(t, uint64(10), ni.Epoch()) + require.Equal(t, "test", ni.Topic()) + }) +} + +func TestIntegration(t *testing.T) { + o := new(Object) + + var ( + ni1 = NotificationInfo{ + epoch: 10, + topic: "", + } + ni2 = NotificationInfo{ + epoch: 11, + topic: "test", + } + ) + + WriteNotificationInfo(o, ni1) + WriteNotificationInfo(o, ni2) + + t.Run("double set", func(t *testing.T) { + ni, err := GetNotificationInfo(o) + require.NoError(t, err) + + require.Equal(t, ni2.epoch, ni.Epoch()) + require.Equal(t, ni2.topic, ni.Topic()) + require.Equal(t, 2, len(o.GetHeader().GetAttributes())) + }) +} diff --git a/pkg/api/object/bench_test.go b/pkg/api/object/bench_test.go new file mode 100644 index 000000000..90fab730c --- /dev/null +++ b/pkg/api/object/bench_test.go @@ -0,0 +1,45 @@ +package object + +import ( + "math/rand" + "testing" + + "github.com/stretchr/testify/require" +) + +func randString(n int) string { + x := make([]byte, n) + for i := range x { + x[i] = byte('a' + rand.Intn('z'-'a')) + } + return string(x) +} + +func BenchmarkAttributesMarshal(b *testing.B) { + attrs := make([]Attribute, 50) + for i := range attrs { + attrs[i].key = SysAttributePrefix + randString(10) + attrs[i].val = randString(10) + } + raw := AttributesToGRPC(attrs) + require.Equal(b, len(raw), len(attrs)) + + b.Run("marshal", func(b *testing.B) { + b.ReportAllocs() + for i := 0; i < b.N; i++ { + res := AttributesToGRPC(attrs) + if len(res) != len(raw) { + b.FailNow() + } + } + }) + b.Run("unmarshal", func(b *testing.B) { + b.ReportAllocs() + for i := 0; i < b.N; i++ { + res, err := AttributesFromGRPC(raw) + if err != nil || len(res) != len(raw) { + b.FailNow() + } + } + }) +} diff --git a/pkg/api/object/convert.go b/pkg/api/object/convert.go new file mode 100644 index 000000000..4b7add73c --- /dev/null +++ b/pkg/api/object/convert.go @@ -0,0 +1,2277 @@ +package object + +import ( + "fmt" + + object "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + refsGRPC "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/message" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" + sessionGRPC "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session/grpc" +) + +func TypeToGRPCField(t Type) object.ObjectType { + return object.ObjectType(t) +} + +func TypeFromGRPCField(t object.ObjectType) Type { + return Type(t) +} + +func MatchTypeToGRPCField(t MatchType) object.MatchType { + return object.MatchType(t) +} + +func MatchTypeFromGRPCField(t object.MatchType) MatchType { + return MatchType(t) +} + +func (h *ShortHeader) ToGRPCMessage() grpc.Message { + var m *object.ShortHeader + + if h != nil { + m = new(object.ShortHeader) + + m.SetVersion(h.version.ToGRPCMessage().(*refsGRPC.Version)) + m.SetOwnerId(h.ownerID.ToGRPCMessage().(*refsGRPC.OwnerID)) + m.SetHomomorphicHash(h.homoHash.ToGRPCMessage().(*refsGRPC.Checksum)) + m.SetPayloadHash(h.payloadHash.ToGRPCMessage().(*refsGRPC.Checksum)) + m.SetObjectType(TypeToGRPCField(h.typ)) + m.SetCreationEpoch(h.creatEpoch) + m.SetPayloadLength(h.payloadLen) + } + + return m +} + +func (h *ShortHeader) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.ShortHeader) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + version := v.GetVersion() + if version == nil { + h.version = nil + } else { + if h.version == nil { + h.version = new(refs.Version) + } + + err = h.version.FromGRPCMessage(version) + if err != nil { + return err + } + } + + ownerID := v.GetOwnerId() + if ownerID == nil { + h.ownerID = nil + } else { + if h.ownerID == nil { + h.ownerID = new(refs.OwnerID) + } + + err = h.ownerID.FromGRPCMessage(ownerID) + if err != nil { + return err + } + } + + homoHash := v.GetHomomorphicHash() + if homoHash == nil { + h.homoHash = nil + } else { + if h.homoHash == nil { + h.homoHash = new(refs.Checksum) + } + + err = h.homoHash.FromGRPCMessage(homoHash) + if err != nil { + return err + } + } + + payloadHash := v.GetPayloadHash() + if payloadHash == nil { + h.payloadHash = nil + } else { + if h.payloadHash == nil { + h.payloadHash = new(refs.Checksum) + } + + err = h.payloadHash.FromGRPCMessage(payloadHash) + if err != nil { + return err + } + } + + h.typ = TypeFromGRPCField(v.GetObjectType()) + h.creatEpoch = v.GetCreationEpoch() + h.payloadLen = v.GetPayloadLength() + + return nil +} + +func (a *Attribute) ToGRPCMessage() grpc.Message { + var m *object.Header_Attribute + + if a != nil { + m = new(object.Header_Attribute) + + m.SetKey(a.key) + m.SetValue(a.val) + } + + return m +} + +func (a *Attribute) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.Header_Attribute) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + a.key = v.GetKey() + a.val = v.GetValue() + + return nil +} + +func AttributesToGRPC(xs []Attribute) (res []*object.Header_Attribute) { + if xs != nil { + res = make([]*object.Header_Attribute, 0, len(xs)) + + for i := range xs { + res = append(res, xs[i].ToGRPCMessage().(*object.Header_Attribute)) + } + } + + return +} + +func AttributesFromGRPC(xs []*object.Header_Attribute) (res []Attribute, err error) { + if xs != nil { + res = make([]Attribute, len(xs)) + + for i := range xs { + if xs[i] != nil { + err = res[i].FromGRPCMessage(xs[i]) + if err != nil { + return + } + } + } + } + + return +} + +func (h *SplitHeader) ToGRPCMessage() grpc.Message { + var m *object.Header_Split + + if h != nil { + m = new(object.Header_Split) + + m.SetParent(h.par.ToGRPCMessage().(*refsGRPC.ObjectID)) + m.SetPrevious(h.prev.ToGRPCMessage().(*refsGRPC.ObjectID)) + m.SetParentHeader(h.parHdr.ToGRPCMessage().(*object.Header)) + m.SetParentSignature(h.parSig.ToGRPCMessage().(*refsGRPC.Signature)) + m.SetChildren(refs.ObjectIDListToGRPCMessage(h.children)) + m.SetSplitId(h.splitID) + } + + return m +} + +func (h *SplitHeader) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.Header_Split) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + par := v.GetParent() + if par == nil { + h.par = nil + } else { + if h.par == nil { + h.par = new(refs.ObjectID) + } + + err = h.par.FromGRPCMessage(par) + if err != nil { + return err + } + } + + prev := v.GetPrevious() + if prev == nil { + h.prev = nil + } else { + if h.prev == nil { + h.prev = new(refs.ObjectID) + } + + err = h.prev.FromGRPCMessage(prev) + if err != nil { + return err + } + } + + parHdr := v.GetParentHeader() + if parHdr == nil { + h.parHdr = nil + } else { + if h.parHdr == nil { + h.parHdr = new(Header) + } + + err = h.parHdr.FromGRPCMessage(parHdr) + if err != nil { + return err + } + } + + parSig := v.GetParentSignature() + if parSig == nil { + h.parSig = nil + } else { + if h.parSig == nil { + h.parSig = new(refs.Signature) + } + + err = h.parSig.FromGRPCMessage(parSig) + if err != nil { + return err + } + } + + h.children, err = refs.ObjectIDListFromGRPCMessage(v.GetChildren()) + if err != nil { + return err + } + + h.splitID = v.GetSplitId() + + return nil +} + +func (h *ECHeader) ToGRPCMessage() grpc.Message { + var m *object.Header_EC + + if h != nil { + m = new(object.Header_EC) + + m.Parent = h.Parent.ToGRPCMessage().(*refsGRPC.ObjectID) + m.Index = h.Index + m.Total = h.Total + m.Header = h.Header + m.HeaderLength = h.HeaderLength + } + + return m +} + +func (h *ECHeader) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.Header_EC) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + par := v.GetParent() + if par == nil { + h.Parent = nil + } else { + if h.Parent == nil { + h.Parent = new(refs.ObjectID) + } + + err = h.Parent.FromGRPCMessage(par) + if err != nil { + return err + } + } + + h.Index = v.GetIndex() + h.Total = v.GetTotal() + h.Header = v.GetHeader() + h.HeaderLength = v.GetHeaderLength() + return nil +} + +func (h *Header) ToGRPCMessage() grpc.Message { + var m *object.Header + + if h != nil { + m = new(object.Header) + + m.SetVersion(h.version.ToGRPCMessage().(*refsGRPC.Version)) + m.SetPayloadHash(h.payloadHash.ToGRPCMessage().(*refsGRPC.Checksum)) + m.SetOwnerId(h.ownerID.ToGRPCMessage().(*refsGRPC.OwnerID)) + m.SetHomomorphicHash(h.homoHash.ToGRPCMessage().(*refsGRPC.Checksum)) + m.SetContainerId(h.cid.ToGRPCMessage().(*refsGRPC.ContainerID)) + m.SetSessionToken(h.sessionToken.ToGRPCMessage().(*sessionGRPC.SessionToken)) + m.SetSplit(h.split.ToGRPCMessage().(*object.Header_Split)) + m.Ec = h.ec.ToGRPCMessage().(*object.Header_EC) + m.SetAttributes(AttributesToGRPC(h.attr)) + m.SetPayloadLength(h.payloadLen) + m.SetCreationEpoch(h.creatEpoch) + m.SetObjectType(TypeToGRPCField(h.typ)) + } + + return m +} + +func (h *Header) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.Header) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + if err := h.fillVersion(v); err != nil { + return err + } + if err := h.fillPayloadHash(v); err != nil { + return err + } + if err := h.fillOwnerID(v); err != nil { + return err + } + if err := h.fillHomomorphicHash(v); err != nil { + return err + } + if err := h.fillContainerID(v); err != nil { + return err + } + if err := h.fillSessionToken(v); err != nil { + return err + } + if err := h.fillSplitHeader(v); err != nil { + return err + } + if err := h.fillECHeader(v); err != nil { + return err + } + + h.attr, err = AttributesFromGRPC(v.GetAttributes()) + if err != nil { + return err + } + + h.payloadLen = v.GetPayloadLength() + h.creatEpoch = v.GetCreationEpoch() + h.typ = TypeFromGRPCField(v.GetObjectType()) + + return nil +} + +func (h *Header) fillVersion(v *object.Header) error { + version := v.GetVersion() + if version == nil { + h.version = nil + return nil + } + + if h.version == nil { + h.version = new(refs.Version) + } + return h.version.FromGRPCMessage(version) +} + +func (h *Header) fillPayloadHash(v *object.Header) error { + payloadHash := v.GetPayloadHash() + if payloadHash == nil { + h.payloadHash = nil + return nil + } + + if h.payloadHash == nil { + h.payloadHash = new(refs.Checksum) + } + return h.payloadHash.FromGRPCMessage(payloadHash) +} + +func (h *Header) fillOwnerID(v *object.Header) error { + ownerID := v.GetOwnerId() + if ownerID == nil { + h.ownerID = nil + return nil + } + + if h.ownerID == nil { + h.ownerID = new(refs.OwnerID) + } + return h.ownerID.FromGRPCMessage(ownerID) +} + +func (h *Header) fillHomomorphicHash(v *object.Header) error { + homoHash := v.GetHomomorphicHash() + if homoHash == nil { + h.homoHash = nil + return nil + } + + if h.homoHash == nil { + h.homoHash = new(refs.Checksum) + } + return h.homoHash.FromGRPCMessage(homoHash) +} + +func (h *Header) fillContainerID(v *object.Header) error { + cid := v.GetContainerId() + if cid == nil { + h.cid = nil + return nil + } + + if h.cid == nil { + h.cid = new(refs.ContainerID) + } + return h.cid.FromGRPCMessage(cid) +} + +func (h *Header) fillSessionToken(v *object.Header) error { + sessionToken := v.GetSessionToken() + if sessionToken == nil { + h.sessionToken = nil + return nil + } + + if h.sessionToken == nil { + h.sessionToken = new(session.Token) + } + return h.sessionToken.FromGRPCMessage(sessionToken) +} + +func (h *Header) fillSplitHeader(v *object.Header) error { + split := v.GetSplit() + if split == nil { + h.split = nil + return nil + } + + if h.split == nil { + h.split = new(SplitHeader) + } + return h.split.FromGRPCMessage(split) +} + +func (h *Header) fillECHeader(v *object.Header) error { + ec := v.GetEc() + if ec == nil { + h.ec = nil + return nil + } + + if h.ec == nil { + h.ec = new(ECHeader) + } + return h.ec.FromGRPCMessage(ec) +} + +func (h *HeaderWithSignature) ToGRPCMessage() grpc.Message { + var m *object.HeaderWithSignature + + if h != nil { + m = new(object.HeaderWithSignature) + + m.SetSignature(h.signature.ToGRPCMessage().(*refsGRPC.Signature)) + m.SetHeader(h.header.ToGRPCMessage().(*object.Header)) + } + + return m +} + +func (h *HeaderWithSignature) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.HeaderWithSignature) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + signature := v.GetSignature() + if signature == nil { + h.signature = nil + } else { + if h.signature == nil { + h.signature = new(refs.Signature) + } + + err = h.signature.FromGRPCMessage(signature) + if err != nil { + return err + } + } + + header := v.GetHeader() + if header == nil { + h.header = nil + } else { + if h.header == nil { + h.header = new(Header) + } + + err = h.header.FromGRPCMessage(header) + } + + return err +} + +func (o *Object) ToGRPCMessage() grpc.Message { + var m *object.Object + + if o != nil { + m = new(object.Object) + + m.SetObjectId(o.objectID.ToGRPCMessage().(*refsGRPC.ObjectID)) + m.SetSignature(o.idSig.ToGRPCMessage().(*refsGRPC.Signature)) + m.SetHeader(o.header.ToGRPCMessage().(*object.Header)) + m.SetPayload(o.payload) + } + + return m +} + +func (o *Object) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.Object) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + objectID := v.GetObjectId() + if objectID == nil { + o.objectID = nil + } else { + if o.objectID == nil { + o.objectID = new(refs.ObjectID) + } + + err = o.objectID.FromGRPCMessage(objectID) + if err != nil { + return err + } + } + + idSig := v.GetSignature() + if idSig == nil { + o.idSig = nil + } else { + if o.idSig == nil { + o.idSig = new(refs.Signature) + } + + err = o.idSig.FromGRPCMessage(idSig) + if err != nil { + return err + } + } + + header := v.GetHeader() + if header == nil { + o.header = nil + } else { + if o.header == nil { + o.header = new(Header) + } + + err = o.header.FromGRPCMessage(header) + if err != nil { + return err + } + } + + o.payload = v.GetPayload() + + return nil +} + +func (s *SplitInfo) ToGRPCMessage() grpc.Message { + var m *object.SplitInfo + + if s != nil { + m = new(object.SplitInfo) + + m.SetLastPart(s.lastPart.ToGRPCMessage().(*refsGRPC.ObjectID)) + m.SetLink(s.link.ToGRPCMessage().(*refsGRPC.ObjectID)) + m.SetSplitId(s.splitID) + } + + return m +} + +func (s *SplitInfo) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.SplitInfo) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + lastPart := v.GetLastPart() + if lastPart == nil { + s.lastPart = nil + } else { + if s.lastPart == nil { + s.lastPart = new(refs.ObjectID) + } + + err = s.lastPart.FromGRPCMessage(lastPart) + if err != nil { + return err + } + } + + link := v.GetLink() + if link == nil { + s.link = nil + } else { + if s.link == nil { + s.link = new(refs.ObjectID) + } + + err = s.link.FromGRPCMessage(link) + if err != nil { + return err + } + } + + s.splitID = v.GetSplitId() + + return nil +} + +func (s *ECInfo) ToGRPCMessage() grpc.Message { + var m *object.ECInfo + + if s != nil { + m = new(object.ECInfo) + + if s.Chunks != nil { + chunks := make([]*object.ECInfo_Chunk, len(s.Chunks)) + for i := range chunks { + chunks[i] = &object.ECInfo_Chunk{ + Id: s.Chunks[i].ID.ToGRPCMessage().(*refsGRPC.ObjectID), + Index: s.Chunks[i].Index, + Total: s.Chunks[i].Total, + } + } + m.Chunks = chunks + } + } + + return m +} + +func (s *ECInfo) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.ECInfo) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + chunks := v.GetChunks() + if chunks == nil { + s.Chunks = nil + } else { + s.Chunks = make([]ECChunk, len(chunks)) + for i := range chunks { + if err := s.Chunks[i].ID.FromGRPCMessage(chunks[i].Id); err != nil { + return err + } + s.Chunks[i].Index = chunks[i].Index + s.Chunks[i].Total = chunks[i].Total + } + } + return nil +} + +func (r *GetRequestBody) ToGRPCMessage() grpc.Message { + var m *object.GetRequest_Body + + if r != nil { + m = new(object.GetRequest_Body) + + m.SetAddress(r.addr.ToGRPCMessage().(*refsGRPC.Address)) + m.SetRaw(r.raw) + } + + return m +} + +func (r *GetRequestBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.GetRequest_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + addr := v.GetAddress() + if addr == nil { + r.addr = nil + } else { + if r.addr == nil { + r.addr = new(refs.Address) + } + + err = r.addr.FromGRPCMessage(addr) + if err != nil { + return err + } + } + + r.raw = v.GetRaw() + + return nil +} + +func (r *GetRequest) ToGRPCMessage() grpc.Message { + var m *object.GetRequest + + if r != nil { + m = new(object.GetRequest) + + m.SetBody(r.body.ToGRPCMessage().(*object.GetRequest_Body)) + r.RequestHeaders.ToMessage(m) + } + + return m +} + +func (r *GetRequest) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.GetRequest) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + r.body = nil + } else { + if r.body == nil { + r.body = new(GetRequestBody) + } + + err = r.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return r.RequestHeaders.FromMessage(v) +} + +func (r *GetObjectPartInit) ToGRPCMessage() grpc.Message { + var m *object.GetResponse_Body_Init + + if r != nil { + m = new(object.GetResponse_Body_Init) + + m.SetObjectId(r.id.ToGRPCMessage().(*refsGRPC.ObjectID)) + m.SetSignature(r.sig.ToGRPCMessage().(*refsGRPC.Signature)) + m.SetHeader(r.hdr.ToGRPCMessage().(*object.Header)) + } + + return m +} + +func (r *GetObjectPartInit) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.GetResponse_Body_Init) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + id := v.GetObjectId() + if id == nil { + r.id = nil + } else { + if r.id == nil { + r.id = new(refs.ObjectID) + } + + err = r.id.FromGRPCMessage(id) + if err != nil { + return err + } + } + + sig := v.GetSignature() + if sig == nil { + r.sig = nil + } else { + if r.sig == nil { + r.sig = new(refs.Signature) + } + + err = r.sig.FromGRPCMessage(sig) + if err != nil { + return err + } + } + + hdr := v.GetHeader() + if hdr == nil { + r.hdr = nil + } else { + if r.hdr == nil { + r.hdr = new(Header) + } + + err = r.hdr.FromGRPCMessage(hdr) + } + + return err +} + +func (r *GetObjectPartChunk) ToGRPCMessage() grpc.Message { + var m *object.GetResponse_Body_Chunk + + if r != nil { + m = new(object.GetResponse_Body_Chunk) + + m.SetChunk(r.chunk) + } + + return m +} + +func (r *GetObjectPartChunk) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.GetResponse_Body_Chunk) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + r.chunk = v.GetChunk() + + return nil +} + +func (r *GetResponseBody) ToGRPCMessage() grpc.Message { + var m *object.GetResponse_Body + + if r != nil { + m = new(object.GetResponse_Body) + + switch v := r.GetObjectPart(); t := v.(type) { + case nil: + m.ObjectPart = nil + case *GetObjectPartInit: + m.SetInit(t.ToGRPCMessage().(*object.GetResponse_Body_Init)) + case *GetObjectPartChunk: + m.SetChunk(t.ToGRPCMessage().(*object.GetResponse_Body_Chunk)) + case *SplitInfo: + m.SetSplitInfo(t.ToGRPCMessage().(*object.SplitInfo)) + default: + panic(fmt.Sprintf("unknown get object part %T", t)) + } + } + + return m +} + +func (r *GetResponseBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.GetResponse_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + r.objPart = nil + + switch pt := v.GetObjectPart().(type) { + case nil: + case *object.GetResponse_Body_Init_: + if pt != nil { + partInit := new(GetObjectPartInit) + r.objPart = partInit + err = partInit.FromGRPCMessage(pt.Init) + } + case *object.GetResponse_Body_Chunk: + if pt != nil { + partChunk := new(GetObjectPartChunk) + r.objPart = partChunk + err = partChunk.FromGRPCMessage(pt) + } + case *object.GetResponse_Body_SplitInfo: + if pt != nil { + partSplit := new(SplitInfo) + r.objPart = partSplit + err = partSplit.FromGRPCMessage(pt.SplitInfo) + } + default: + err = fmt.Errorf("unknown get object part %T", pt) + } + + return err +} + +func (r *GetResponse) ToGRPCMessage() grpc.Message { + var m *object.GetResponse + + if r != nil { + m = new(object.GetResponse) + + m.SetBody(r.body.ToGRPCMessage().(*object.GetResponse_Body)) + r.ResponseHeaders.ToMessage(m) + } + + return m +} + +func (r *GetResponse) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.GetResponse) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + r.body = nil + } else { + if r.body == nil { + r.body = new(GetResponseBody) + } + + err = r.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return r.ResponseHeaders.FromMessage(v) +} + +func (r *PutObjectPartInit) ToGRPCMessage() grpc.Message { + var m *object.PutRequest_Body_Init + + if r != nil { + m = new(object.PutRequest_Body_Init) + + m.SetObjectId(r.id.ToGRPCMessage().(*refsGRPC.ObjectID)) + m.SetSignature(r.sig.ToGRPCMessage().(*refsGRPC.Signature)) + m.SetHeader(r.hdr.ToGRPCMessage().(*object.Header)) + m.SetCopiesNumber(r.copyNum) + } + + return m +} + +func (r *PutObjectPartInit) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.PutRequest_Body_Init) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + id := v.GetObjectId() + if id == nil { + r.id = nil + } else { + if r.id == nil { + r.id = new(refs.ObjectID) + } + + err = r.id.FromGRPCMessage(id) + if err != nil { + return err + } + } + + sig := v.GetSignature() + if sig == nil { + r.sig = nil + } else { + if r.sig == nil { + r.sig = new(refs.Signature) + } + + err = r.sig.FromGRPCMessage(sig) + if err != nil { + return err + } + } + + hdr := v.GetHeader() + if hdr == nil { + r.hdr = nil + } else { + if r.hdr == nil { + r.hdr = new(Header) + } + + err = r.hdr.FromGRPCMessage(hdr) + if err != nil { + return err + } + } + + r.copyNum = v.GetCopiesNumber() + + return nil +} + +func (r *PutObjectPartChunk) ToGRPCMessage() grpc.Message { + var m *object.PutRequest_Body_Chunk + + if r != nil { + m = new(object.PutRequest_Body_Chunk) + + m.SetChunk(r.chunk) + } + + return m +} + +func (r *PutObjectPartChunk) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.PutRequest_Body_Chunk) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + r.chunk = v.GetChunk() + + return nil +} + +func (r *PutRequestBody) ToGRPCMessage() grpc.Message { + var m *object.PutRequest_Body + + if r != nil { + m = new(object.PutRequest_Body) + + switch v := r.GetObjectPart(); t := v.(type) { + case nil: + m.ObjectPart = nil + case *PutObjectPartInit: + m.SetInit(t.ToGRPCMessage().(*object.PutRequest_Body_Init)) + case *PutObjectPartChunk: + m.SetChunk(t.ToGRPCMessage().(*object.PutRequest_Body_Chunk)) + default: + panic(fmt.Sprintf("unknown put object part %T", t)) + } + } + + return m +} + +func (r *PutRequestBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.PutRequest_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + r.objPart = nil + + switch pt := v.GetObjectPart().(type) { + case nil: + case *object.PutRequest_Body_Init_: + if pt != nil { + partInit := new(PutObjectPartInit) + r.objPart = partInit + err = partInit.FromGRPCMessage(pt.Init) + } + case *object.PutRequest_Body_Chunk: + if pt != nil { + partChunk := new(PutObjectPartChunk) + r.objPart = partChunk + err = partChunk.FromGRPCMessage(pt) + } + default: + err = fmt.Errorf("unknown put object part %T", pt) + } + + return err +} + +func (r *PutRequest) ToGRPCMessage() grpc.Message { + var m *object.PutRequest + + if r != nil { + m = new(object.PutRequest) + + m.SetBody(r.body.ToGRPCMessage().(*object.PutRequest_Body)) + r.RequestHeaders.ToMessage(m) + } + + return m +} + +func (r *PutRequest) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.PutRequest) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + r.body = nil + } else { + if r.body == nil { + r.body = new(PutRequestBody) + } + + err = r.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return r.RequestHeaders.FromMessage(v) +} + +func (r *PutResponseBody) ToGRPCMessage() grpc.Message { + var m *object.PutResponse_Body + + if r != nil { + m = new(object.PutResponse_Body) + + m.SetObjectId(r.id.ToGRPCMessage().(*refsGRPC.ObjectID)) + } + + return m +} + +func (r *PutResponseBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.PutResponse_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + id := v.GetObjectId() + if id == nil { + r.id = nil + } else { + if r.id == nil { + r.id = new(refs.ObjectID) + } + + err = r.id.FromGRPCMessage(id) + } + + return err +} + +func (r *PutResponse) ToGRPCMessage() grpc.Message { + var m *object.PutResponse + + if r != nil { + m = new(object.PutResponse) + + m.SetBody(r.body.ToGRPCMessage().(*object.PutResponse_Body)) + r.ResponseHeaders.ToMessage(m) + } + + return m +} + +func (r *PutResponse) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.PutResponse) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + r.body = nil + } else { + if r.body == nil { + r.body = new(PutResponseBody) + } + + err = r.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return r.ResponseHeaders.FromMessage(v) +} + +func (r *DeleteRequestBody) ToGRPCMessage() grpc.Message { + var m *object.DeleteRequest_Body + + if r != nil { + m = new(object.DeleteRequest_Body) + + m.SetAddress(r.addr.ToGRPCMessage().(*refsGRPC.Address)) + } + + return m +} + +func (r *DeleteRequestBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.DeleteRequest_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + addr := v.GetAddress() + if addr == nil { + r.addr = nil + } else { + if r.addr == nil { + r.addr = new(refs.Address) + } + + err = r.addr.FromGRPCMessage(addr) + } + + return err +} + +func (r *DeleteRequest) ToGRPCMessage() grpc.Message { + var m *object.DeleteRequest + + if r != nil { + m = new(object.DeleteRequest) + + m.SetBody(r.body.ToGRPCMessage().(*object.DeleteRequest_Body)) + r.RequestHeaders.ToMessage(m) + } + + return m +} + +func (r *DeleteRequest) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.DeleteRequest) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + r.body = nil + } else { + if r.body == nil { + r.body = new(DeleteRequestBody) + } + + err = r.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return r.RequestHeaders.FromMessage(v) +} + +func (r *DeleteResponseBody) ToGRPCMessage() grpc.Message { + var m *object.DeleteResponse_Body + + if r != nil { + m = new(object.DeleteResponse_Body) + + m.SetTombstone(r.tombstone.ToGRPCMessage().(*refsGRPC.Address)) + } + + return m +} + +func (r *DeleteResponseBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.DeleteResponse_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + tombstone := v.GetTombstone() + if tombstone == nil { + r.tombstone = nil + } else { + if r.tombstone == nil { + r.tombstone = new(refs.Address) + } + + err = r.tombstone.FromGRPCMessage(tombstone) + } + + return err +} + +func (r *DeleteResponse) ToGRPCMessage() grpc.Message { + var m *object.DeleteResponse + + if r != nil { + m = new(object.DeleteResponse) + + m.SetBody(r.body.ToGRPCMessage().(*object.DeleteResponse_Body)) + r.ResponseHeaders.ToMessage(m) + } + + return m +} + +func (r *DeleteResponse) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.DeleteResponse) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + r.body = nil + } else { + if r.body == nil { + r.body = new(DeleteResponseBody) + } + + err = r.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return r.ResponseHeaders.FromMessage(v) +} + +func (r *HeadRequestBody) ToGRPCMessage() grpc.Message { + var m *object.HeadRequest_Body + + if r != nil { + m = new(object.HeadRequest_Body) + + m.SetAddress(r.addr.ToGRPCMessage().(*refsGRPC.Address)) + m.SetRaw(r.raw) + m.SetMainOnly(r.mainOnly) + } + + return m +} + +func (r *HeadRequestBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.HeadRequest_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + addr := v.GetAddress() + if addr == nil { + r.addr = nil + } else { + if r.addr == nil { + r.addr = new(refs.Address) + } + + err = r.addr.FromGRPCMessage(addr) + if err != nil { + return err + } + } + + r.raw = v.GetRaw() + r.mainOnly = v.GetMainOnly() + + return nil +} + +func (r *HeadRequest) ToGRPCMessage() grpc.Message { + var m *object.HeadRequest + + if r != nil { + m = new(object.HeadRequest) + + m.SetBody(r.body.ToGRPCMessage().(*object.HeadRequest_Body)) + r.RequestHeaders.ToMessage(m) + } + + return m +} + +func (r *HeadRequest) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.HeadRequest) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + r.body = nil + } else { + if r.body == nil { + r.body = new(HeadRequestBody) + } + + err = r.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return r.RequestHeaders.FromMessage(v) +} + +func (r *HeadResponseBody) ToGRPCMessage() grpc.Message { + var m *object.HeadResponse_Body + + if r != nil { + m = new(object.HeadResponse_Body) + + switch v := r.hdrPart.(type) { + case nil: + m.Head = nil + case *HeaderWithSignature: + m.SetHeader(v.ToGRPCMessage().(*object.HeaderWithSignature)) + case *ShortHeader: + m.SetShortHeader(v.ToGRPCMessage().(*object.ShortHeader)) + case *SplitInfo: + m.SetSplitInfo(v.ToGRPCMessage().(*object.SplitInfo)) + default: + panic(fmt.Sprintf("unknown head part %T", v)) + } + } + + return m +} + +func (r *HeadResponseBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.HeadResponse_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + r.hdrPart = nil + + switch pt := v.GetHead().(type) { + case nil: + case *object.HeadResponse_Body_Header: + if pt != nil { + partHdr := new(HeaderWithSignature) + r.hdrPart = partHdr + err = partHdr.FromGRPCMessage(pt.Header) + } + case *object.HeadResponse_Body_ShortHeader: + if pt != nil { + partShort := new(ShortHeader) + r.hdrPart = partShort + err = partShort.FromGRPCMessage(pt.ShortHeader) + } + case *object.HeadResponse_Body_SplitInfo: + if pt != nil { + partSplit := new(SplitInfo) + r.hdrPart = partSplit + err = partSplit.FromGRPCMessage(pt.SplitInfo) + } + default: + err = fmt.Errorf("unknown head part %T", pt) + } + + return err +} + +func (r *HeadResponse) ToGRPCMessage() grpc.Message { + var m *object.HeadResponse + + if r != nil { + m = new(object.HeadResponse) + + m.SetBody(r.body.ToGRPCMessage().(*object.HeadResponse_Body)) + r.ResponseHeaders.ToMessage(m) + } + + return m +} + +func (r *HeadResponse) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.HeadResponse) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + r.body = nil + } else { + if r.body == nil { + r.body = new(HeadResponseBody) + } + + err = r.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return r.ResponseHeaders.FromMessage(v) +} + +func (f *SearchFilter) ToGRPCMessage() grpc.Message { + var m *object.SearchRequest_Body_Filter + + if f != nil { + m = new(object.SearchRequest_Body_Filter) + + m.SetKey(f.key) + m.SetValue(f.val) + m.SetMatchType(MatchTypeToGRPCField(f.matchType)) + } + + return m +} + +func (f *SearchFilter) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.SearchRequest_Body_Filter) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + f.key = v.GetKey() + f.val = v.GetValue() + f.matchType = MatchTypeFromGRPCField(v.GetMatchType()) + + return nil +} + +func SearchFiltersToGRPC(fs []SearchFilter) (res []*object.SearchRequest_Body_Filter) { + if fs != nil { + res = make([]*object.SearchRequest_Body_Filter, 0, len(fs)) + + for i := range fs { + res = append(res, fs[i].ToGRPCMessage().(*object.SearchRequest_Body_Filter)) + } + } + + return +} + +func SearchFiltersFromGRPC(fs []*object.SearchRequest_Body_Filter) (res []SearchFilter, err error) { + if fs != nil { + res = make([]SearchFilter, len(fs)) + + for i := range fs { + if fs[i] != nil { + err = res[i].FromGRPCMessage(fs[i]) + if err != nil { + return + } + } + } + } + + return +} + +func (r *SearchRequestBody) ToGRPCMessage() grpc.Message { + var m *object.SearchRequest_Body + + if r != nil { + m = new(object.SearchRequest_Body) + + m.SetContainerId(r.cid.ToGRPCMessage().(*refsGRPC.ContainerID)) + m.SetFilters(SearchFiltersToGRPC(r.filters)) + m.SetVersion(r.version) + } + + return m +} + +func (r *SearchRequestBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.SearchRequest_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + cid := v.GetContainerId() + if cid == nil { + r.cid = nil + } else { + if r.cid == nil { + r.cid = new(refs.ContainerID) + } + + err = r.cid.FromGRPCMessage(cid) + if err != nil { + return err + } + } + + r.filters, err = SearchFiltersFromGRPC(v.GetFilters()) + if err != nil { + return err + } + + r.version = v.GetVersion() + + return nil +} + +func (r *SearchRequest) ToGRPCMessage() grpc.Message { + var m *object.SearchRequest + + if r != nil { + m = new(object.SearchRequest) + + m.SetBody(r.body.ToGRPCMessage().(*object.SearchRequest_Body)) + r.RequestHeaders.ToMessage(m) + } + + return m +} + +func (r *SearchRequest) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.SearchRequest) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + r.body = nil + } else { + if r.body == nil { + r.body = new(SearchRequestBody) + } + + err = r.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return r.RequestHeaders.FromMessage(v) +} + +func (r *SearchResponseBody) ToGRPCMessage() grpc.Message { + var m *object.SearchResponse_Body + + if r != nil { + m = new(object.SearchResponse_Body) + + m.SetIdList(refs.ObjectIDListToGRPCMessage(r.idList)) + } + + return m +} + +func (r *SearchResponseBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.SearchResponse_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + r.idList, err = refs.ObjectIDListFromGRPCMessage(v.GetIdList()) + + return err +} + +func (r *SearchResponse) ToGRPCMessage() grpc.Message { + var m *object.SearchResponse + + if r != nil { + m = new(object.SearchResponse) + + m.SetBody(r.body.ToGRPCMessage().(*object.SearchResponse_Body)) + r.ResponseHeaders.ToMessage(m) + } + + return m +} + +func (r *SearchResponse) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.SearchResponse) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + r.body = nil + } else { + if r.body == nil { + r.body = new(SearchResponseBody) + } + + err = r.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return r.ResponseHeaders.FromMessage(v) +} + +func (r *Range) ToGRPCMessage() grpc.Message { + var m *object.Range + + if r != nil { + m = new(object.Range) + + m.SetLength(r.len) + m.SetOffset(r.off) + } + + return m +} + +func (r *Range) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.Range) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + r.len = v.GetLength() + r.off = v.GetOffset() + + return nil +} + +func RangesToGRPC(rs []Range) (res []*object.Range) { + if rs != nil { + res = make([]*object.Range, 0, len(rs)) + + for i := range rs { + res = append(res, rs[i].ToGRPCMessage().(*object.Range)) + } + } + + return +} + +func RangesFromGRPC(rs []*object.Range) (res []Range, err error) { + if rs != nil { + res = make([]Range, len(rs)) + + for i := range rs { + if rs[i] != nil { + err = res[i].FromGRPCMessage(rs[i]) + if err != nil { + return + } + } + } + } + + return +} + +func (r *GetRangeRequestBody) ToGRPCMessage() grpc.Message { + var m *object.GetRangeRequest_Body + + if r != nil { + m = new(object.GetRangeRequest_Body) + + m.SetAddress(r.addr.ToGRPCMessage().(*refsGRPC.Address)) + m.SetRange(r.rng.ToGRPCMessage().(*object.Range)) + m.SetRaw(r.raw) + } + + return m +} + +func (r *GetRangeRequestBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.GetRangeRequest_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + addr := v.GetAddress() + if addr == nil { + r.addr = nil + } else { + if r.addr == nil { + r.addr = new(refs.Address) + } + + err = r.addr.FromGRPCMessage(addr) + if err != nil { + return err + } + } + + rng := v.GetRange() + if rng == nil { + r.rng = nil + } else { + if r.rng == nil { + r.rng = new(Range) + } + + err = r.rng.FromGRPCMessage(rng) + if err != nil { + return err + } + } + + r.raw = v.GetRaw() + + return nil +} + +func (r *GetRangeRequest) ToGRPCMessage() grpc.Message { + var m *object.GetRangeRequest + + if r != nil { + m = new(object.GetRangeRequest) + + m.SetBody(r.body.ToGRPCMessage().(*object.GetRangeRequest_Body)) + r.RequestHeaders.ToMessage(m) + } + + return m +} + +func (r *GetRangeRequest) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.GetRangeRequest) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + r.body = nil + } else { + if r.body == nil { + r.body = new(GetRangeRequestBody) + } + + err = r.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return r.RequestHeaders.FromMessage(v) +} + +func (r *GetRangePartChunk) ToGRPCMessage() grpc.Message { + var m *object.GetRangeResponse_Body_Chunk + + if r != nil { + m = new(object.GetRangeResponse_Body_Chunk) + + m.SetChunk(r.chunk) + } + + return m +} + +func (r *GetRangePartChunk) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.GetRangeResponse_Body_Chunk) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + r.chunk = v.GetChunk() + + return nil +} + +func (r *GetRangeResponseBody) ToGRPCMessage() grpc.Message { + var m *object.GetRangeResponse_Body + + if r != nil { + m = new(object.GetRangeResponse_Body) + + switch v := r.rngPart.(type) { + case nil: + m.RangePart = nil + case *GetRangePartChunk: + m.SetChunk(v.ToGRPCMessage().(*object.GetRangeResponse_Body_Chunk)) + case *SplitInfo: + m.SetSplitInfo(v.ToGRPCMessage().(*object.SplitInfo)) + default: + panic(fmt.Sprintf("unknown get range part %T", v)) + } + } + + return m +} + +func (r *GetRangeResponseBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.GetRangeResponse_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + r.rngPart = nil + + switch pt := v.GetRangePart().(type) { + case nil: + case *object.GetRangeResponse_Body_Chunk: + if pt != nil { + partChunk := new(GetRangePartChunk) + r.rngPart = partChunk + err = partChunk.FromGRPCMessage(pt) + } + case *object.GetRangeResponse_Body_SplitInfo: + if pt != nil { + partSplit := new(SplitInfo) + r.rngPart = partSplit + err = partSplit.FromGRPCMessage(pt.SplitInfo) + } + default: + err = fmt.Errorf("unknown get range part %T", pt) + } + + return err +} + +func (r *GetRangeResponse) ToGRPCMessage() grpc.Message { + var m *object.GetRangeResponse + + if r != nil { + m = new(object.GetRangeResponse) + + m.SetBody(r.body.ToGRPCMessage().(*object.GetRangeResponse_Body)) + r.ResponseHeaders.ToMessage(m) + } + + return m +} + +func (r *GetRangeResponse) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.GetRangeResponse) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + r.body = nil + } else { + if r.body == nil { + r.body = new(GetRangeResponseBody) + } + + err = r.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return r.ResponseHeaders.FromMessage(v) +} + +func (r *GetRangeHashRequestBody) ToGRPCMessage() grpc.Message { + var m *object.GetRangeHashRequest_Body + + if r != nil { + m = new(object.GetRangeHashRequest_Body) + + m.SetAddress(r.addr.ToGRPCMessage().(*refsGRPC.Address)) + m.SetRanges(RangesToGRPC(r.rngs)) + m.SetType(refs.ChecksumTypeToGRPC(r.typ)) + m.SetSalt(r.salt) + } + + return m +} + +func (r *GetRangeHashRequestBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.GetRangeHashRequest_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + addr := v.GetAddress() + if addr == nil { + r.addr = nil + } else { + if r.addr == nil { + r.addr = new(refs.Address) + } + + err = r.addr.FromGRPCMessage(addr) + if err != nil { + return err + } + } + + r.rngs, err = RangesFromGRPC(v.GetRanges()) + if err != nil { + return err + } + + r.typ = refs.ChecksumTypeFromGRPC(v.GetType()) + r.salt = v.GetSalt() + + return nil +} + +func (r *GetRangeHashRequest) ToGRPCMessage() grpc.Message { + var m *object.GetRangeHashRequest + + if r != nil { + m = new(object.GetRangeHashRequest) + + m.SetBody(r.body.ToGRPCMessage().(*object.GetRangeHashRequest_Body)) + r.RequestHeaders.ToMessage(m) + } + + return m +} + +func (r *GetRangeHashRequest) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.GetRangeHashRequest) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + r.body = nil + } else { + if r.body == nil { + r.body = new(GetRangeHashRequestBody) + } + + err = r.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return r.RequestHeaders.FromMessage(v) +} + +func (r *GetRangeHashResponseBody) ToGRPCMessage() grpc.Message { + var m *object.GetRangeHashResponse_Body + + if r != nil { + m = new(object.GetRangeHashResponse_Body) + + m.SetType(refs.ChecksumTypeToGRPC(r.typ)) + m.SetHashList(r.hashList) + } + + return m +} + +func (r *GetRangeHashResponseBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.GetRangeHashResponse_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + r.typ = refs.ChecksumTypeFromGRPC(v.GetType()) + r.hashList = v.GetHashList() + + return nil +} + +func (r *GetRangeHashResponse) ToGRPCMessage() grpc.Message { + var m *object.GetRangeHashResponse + + if r != nil { + m = new(object.GetRangeHashResponse) + + m.SetBody(r.body.ToGRPCMessage().(*object.GetRangeHashResponse_Body)) + r.ResponseHeaders.ToMessage(m) + } + + return m +} + +func (r *GetRangeHashResponse) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.GetRangeHashResponse) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + r.body = nil + } else { + if r.body == nil { + r.body = new(GetRangeHashResponseBody) + } + + err = r.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return r.ResponseHeaders.FromMessage(v) +} + +func (r *PutSingleRequestBody) ToGRPCMessage() grpc.Message { + var m *object.PutSingleRequest_Body + + if r != nil { + m = new(object.PutSingleRequest_Body) + m.SetObject(r.GetObject().ToGRPCMessage().(*object.Object)) + m.SetCopiesNumber(r.GetCopiesNumber()) + } + + return m +} + +func (r *PutSingleRequestBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.PutSingleRequest_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + if v.GetObject() == nil { + r.object = nil + } else { + if r.object == nil { + r.object = new(Object) + } + + err := r.object.FromGRPCMessage(v.GetObject()) + if err != nil { + return err + } + } + + r.copyNum = v.GetCopiesNumber() + + return nil +} + +func (r *PutSingleRequest) ToGRPCMessage() grpc.Message { + var m *object.PutSingleRequest + + if r != nil { + m = new(object.PutSingleRequest) + + m.SetBody(r.body.ToGRPCMessage().(*object.PutSingleRequest_Body)) + r.RequestHeaders.ToMessage(m) + } + + return m +} + +func (r *PutSingleRequest) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.PutSingleRequest) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + body := v.GetBody() + if body == nil { + r.body = nil + } else { + if r.body == nil { + r.body = new(PutSingleRequestBody) + } + + err := r.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return r.RequestHeaders.FromMessage(v) +} + +func (r *PutSingleResponseBody) ToGRPCMessage() grpc.Message { + var b *object.PutSingleResponse_Body + if r != nil { + b = new(object.PutSingleResponse_Body) + } + return b +} + +func (r *PutSingleResponseBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.PutSingleResponse_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + return nil +} + +func (r *PutSingleResponse) ToGRPCMessage() grpc.Message { + var m *object.PutSingleResponse + + if r != nil { + m = new(object.PutSingleResponse) + + m.SetBody(r.body.ToGRPCMessage().(*object.PutSingleResponse_Body)) + r.ResponseHeaders.ToMessage(m) + } + + return m +} + +func (r *PutSingleResponse) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*object.PutSingleResponse) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + r.body = nil + } else { + if r.body == nil { + r.body = new(PutSingleResponseBody) + } + + err = r.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return r.ResponseHeaders.FromMessage(v) +} diff --git a/pkg/api/object/filters.go b/pkg/api/object/filters.go new file mode 100644 index 000000000..5eee13ba3 --- /dev/null +++ b/pkg/api/object/filters.go @@ -0,0 +1,55 @@ +package object + +// ReservedFilterPrefix is a prefix of key to object header value or property. +const ReservedFilterPrefix = "$Object:" + +const ( + // FilterHeaderVersion is a filter key to "version" field of the object header. + FilterHeaderVersion = ReservedFilterPrefix + "version" + + // FilterHeaderObjectID is a filter key to "object_id" field of the object. + FilterHeaderObjectID = ReservedFilterPrefix + "objectID" + + // FilterHeaderContainerID is a filter key to "container_id" field of the object header. + FilterHeaderContainerID = ReservedFilterPrefix + "containerID" + + // FilterHeaderOwnerID is a filter key to "owner_id" field of the object header. + FilterHeaderOwnerID = ReservedFilterPrefix + "ownerID" + + // FilterHeaderCreationEpoch is a filter key to "creation_epoch" field of the object header. + FilterHeaderCreationEpoch = ReservedFilterPrefix + "creationEpoch" + + // FilterHeaderPayloadLength is a filter key to "payload_length" field of the object header. + FilterHeaderPayloadLength = ReservedFilterPrefix + "payloadLength" + + // FilterHeaderPayloadHash is a filter key to "payload_hash" field of the object header. + FilterHeaderPayloadHash = ReservedFilterPrefix + "payloadHash" + + // FilterHeaderObjectType is a filter key to "object_type" field of the object header. + FilterHeaderObjectType = ReservedFilterPrefix + "objectType" + + // FilterHeaderHomomorphicHash is a filter key to "homomorphic_hash" field of the object header. + FilterHeaderHomomorphicHash = ReservedFilterPrefix + "homomorphicHash" + + // FilterHeaderParent is a filter key to "split.parent" field of the object header. + FilterHeaderParent = ReservedFilterPrefix + "split.parent" + + // FilterHeaderSplitID is a filter key to "split.splitID" field of the object header. + FilterHeaderSplitID = ReservedFilterPrefix + "split.splitID" +) + +const ( + // FilterPropertyRoot is a filter key to check if regular object is on top of split hierarchy. + FilterPropertyRoot = ReservedFilterPrefix + "ROOT" + + // FilterPropertyPhy is a filter key to check if an object physically stored on a node. + FilterPropertyPhy = ReservedFilterPrefix + "PHY" +) + +const ( + // BooleanPropertyValueTrue is a true value for boolean property filters. + BooleanPropertyValueTrue = "true" + + // BooleanPropertyValueFalse is a false value for boolean property filters. + BooleanPropertyValueFalse = "" +) diff --git a/pkg/api/object/grpc/client.go b/pkg/api/object/grpc/client.go new file mode 100644 index 000000000..35028cfe2 --- /dev/null +++ b/pkg/api/object/grpc/client.go @@ -0,0 +1,86 @@ +package object + +import ( + "context" + "errors" + + "google.golang.org/grpc" +) + +// Client wraps ObjectServiceClient +// with pre-defined configurations. +type Client struct { + *cfg + + client ObjectServiceClient +} + +// Option represents Client option. +type Option func(*cfg) + +type cfg struct { + callOpts []grpc.CallOption +} + +// ErrNilObjectServiceClient is returned by functions that expect +// a non-nil ObjectServiceClient, but received nil. +var ErrNilObjectServiceClient = errors.New("object gRPC client is nil") + +func defaultCfg() *cfg { + return new(cfg) +} + +// NewClient creates, initializes and returns a new Client instance. +// +// Options are applied one by one in order. +func NewClient(c ObjectServiceClient, opts ...Option) (*Client, error) { + if c == nil { + return nil, ErrNilObjectServiceClient + } + + cfg := defaultCfg() + for i := range opts { + opts[i](cfg) + } + + return &Client{ + cfg: cfg, + client: c, + }, nil +} + +func (c *Client) Get(ctx context.Context, req *GetRequest) (ObjectService_GetClient, error) { + return c.client.Get(ctx, req, c.callOpts...) +} + +func (c *Client) Put(ctx context.Context) (ObjectService_PutClient, error) { + return c.client.Put(ctx, c.callOpts...) +} + +func (c *Client) Head(ctx context.Context, req *HeadRequest) (*HeadResponse, error) { + return c.client.Head(ctx, req, c.callOpts...) +} + +func (c *Client) Search(ctx context.Context, req *SearchRequest) (ObjectService_SearchClient, error) { + return c.client.Search(ctx, req, c.callOpts...) +} + +func (c *Client) Delete(ctx context.Context, req *DeleteRequest) (*DeleteResponse, error) { + return c.client.Delete(ctx, req, c.callOpts...) +} + +func (c *Client) GetRange(ctx context.Context, req *GetRangeRequest) (ObjectService_GetRangeClient, error) { + return c.client.GetRange(ctx, req, c.callOpts...) +} + +func (c *Client) GetRangeHash(ctx context.Context, req *GetRangeHashRequest) (*GetRangeHashResponse, error) { + return c.client.GetRangeHash(ctx, req, c.callOpts...) +} + +// WithCallOptions returns Option that configures +// Client to attach call options to each rpc call. +func WithCallOptions(opts []grpc.CallOption) Option { + return func(c *cfg) { + c.callOpts = opts + } +} diff --git a/pkg/api/object/grpc/service.go b/pkg/api/object/grpc/service.go new file mode 100644 index 000000000..a3cd6f195 --- /dev/null +++ b/pkg/api/object/grpc/service.go @@ -0,0 +1,537 @@ +package object + +import ( + refs "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs/grpc" + session "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session/grpc" +) + +// SetAddress sets address of the requested object. +func (m *GetRequest_Body) SetAddress(v *refs.Address) { + m.Address = v +} + +// SetRaw sets raw flag of the request. +func (m *GetRequest_Body) SetRaw(v bool) { + m.Raw = v +} + +// SetBody sets body of the request. +func (m *GetRequest) SetBody(v *GetRequest_Body) { + m.Body = v +} + +// SetMetaHeader sets meta header of the request. +func (m *GetRequest) SetMetaHeader(v *session.RequestMetaHeader) { + m.MetaHeader = v +} + +// SetVerifyHeader sets verification header of the request. +func (m *GetRequest) SetVerifyHeader(v *session.RequestVerificationHeader) { + m.VerifyHeader = v +} + +// SetObjectId sets identifier of the object. +func (m *GetResponse_Body_Init) SetObjectId(v *refs.ObjectID) { + m.ObjectId = v +} + +// SetSignature sets signature of the object identifier. +func (m *GetResponse_Body_Init) SetSignature(v *refs.Signature) { + m.Signature = v +} + +// SetHeader sets header of the object. +func (m *GetResponse_Body_Init) SetHeader(v *Header) { + m.Header = v +} + +// GetChunk returns chunk of the object payload bytes. +func (m *GetResponse_Body_Chunk) GetChunk() []byte { + if m != nil { + return m.Chunk + } + + return nil +} + +// SetChunk sets chunk of the object payload bytes. +func (m *GetResponse_Body_Chunk) SetChunk(v []byte) { + m.Chunk = v +} + +// SetInit sets initial part of the object. +func (m *GetResponse_Body) SetInit(v *GetResponse_Body_Init) { + m.ObjectPart = &GetResponse_Body_Init_{ + Init: v, + } +} + +// SetChunk sets part of the object payload. +func (m *GetResponse_Body) SetChunk(v *GetResponse_Body_Chunk) { + m.ObjectPart = v +} + +// SetSplitInfo sets part of the object payload. +func (m *GetResponse_Body) SetSplitInfo(v *SplitInfo) { + m.ObjectPart = &GetResponse_Body_SplitInfo{ + SplitInfo: v, + } +} + +// SetBody sets body of the response. +func (m *GetResponse) SetBody(v *GetResponse_Body) { + m.Body = v +} + +// SetMetaHeader sets meta header of the response. +func (m *GetResponse) SetMetaHeader(v *session.ResponseMetaHeader) { + m.MetaHeader = v +} + +// SetVerifyHeader sets verification header of the response. +func (m *GetResponse) SetVerifyHeader(v *session.ResponseVerificationHeader) { + m.VerifyHeader = v +} + +// SetObjectId sets identifier of the object. +func (m *PutRequest_Body_Init) SetObjectId(v *refs.ObjectID) { + m.ObjectId = v +} + +// SetSignature sets signature of the object identifier. +func (m *PutRequest_Body_Init) SetSignature(v *refs.Signature) { + m.Signature = v +} + +// SetHeader sets header of the object. +func (m *PutRequest_Body_Init) SetHeader(v *Header) { + m.Header = v +} + +// SetCopiesNumber sets number of the copies to save. +func (m *PutRequest_Body_Init) SetCopiesNumber(v []uint32) { + m.CopiesNumber = v +} + +// GetChunk returns chunk of the object payload bytes. +func (m *PutRequest_Body_Chunk) GetChunk() []byte { + if m != nil { + return m.Chunk + } + + return nil +} + +// SetChunk sets chunk of the object payload bytes. +func (m *PutRequest_Body_Chunk) SetChunk(v []byte) { + m.Chunk = v +} + +// SetInit sets initial part of the object. +func (m *PutRequest_Body) SetInit(v *PutRequest_Body_Init) { + m.ObjectPart = &PutRequest_Body_Init_{ + Init: v, + } +} + +// SetChunk sets part of the object payload. +func (m *PutRequest_Body) SetChunk(v *PutRequest_Body_Chunk) { + m.ObjectPart = v +} + +// SetBody sets body of the request. +func (m *PutRequest) SetBody(v *PutRequest_Body) { + m.Body = v +} + +// SetMetaHeader sets meta header of the request. +func (m *PutRequest) SetMetaHeader(v *session.RequestMetaHeader) { + m.MetaHeader = v +} + +// SetVerifyHeader sets verification header of the request. +func (m *PutRequest) SetVerifyHeader(v *session.RequestVerificationHeader) { + m.VerifyHeader = v +} + +// SetObjectId sets identifier of the saved object. +func (m *PutResponse_Body) SetObjectId(v *refs.ObjectID) { + m.ObjectId = v +} + +// SetBody sets body of the response. +func (m *PutResponse) SetBody(v *PutResponse_Body) { + m.Body = v +} + +// SetMetaHeader sets meta header of the response. +func (m *PutResponse) SetMetaHeader(v *session.ResponseMetaHeader) { + m.MetaHeader = v +} + +// SetVerifyHeader sets verification header of the response. +func (m *PutResponse) SetVerifyHeader(v *session.ResponseVerificationHeader) { + m.VerifyHeader = v +} + +// SetAddress sets address of the object to delete. +func (m *DeleteRequest_Body) SetAddress(v *refs.Address) { + m.Address = v +} + +// SetBody sets body of the request. +func (m *DeleteRequest) SetBody(v *DeleteRequest_Body) { + m.Body = v +} + +// SetMetaHeader sets meta header of the request. +func (m *DeleteRequest) SetMetaHeader(v *session.RequestMetaHeader) { + m.MetaHeader = v +} + +// SetVerifyHeader sets verification header of the request. +func (m *DeleteRequest) SetVerifyHeader(v *session.RequestVerificationHeader) { + m.VerifyHeader = v +} + +// SetTombstone sets tombstone address. +func (x *DeleteResponse_Body) SetTombstone(v *refs.Address) { + x.Tombstone = v +} + +// SetBody sets body of the response. +func (m *DeleteResponse) SetBody(v *DeleteResponse_Body) { + m.Body = v +} + +// SetMetaHeader sets meta header of the response. +func (m *DeleteResponse) SetMetaHeader(v *session.ResponseMetaHeader) { + m.MetaHeader = v +} + +// SetVerifyHeader sets verification header of the response. +func (m *DeleteResponse) SetVerifyHeader(v *session.ResponseVerificationHeader) { + m.VerifyHeader = v +} + +// SetAddress sets address of the object with the requested header. +func (m *HeadRequest_Body) SetAddress(v *refs.Address) { + m.Address = v +} + +// SetMainOnly sets flag to return the minimal header subset. +func (m *HeadRequest_Body) SetMainOnly(v bool) { + m.MainOnly = v +} + +// SetRaw sets raw flag of the request. +func (m *HeadRequest_Body) SetRaw(v bool) { + m.Raw = v +} + +// SetBody sets body of the request. +func (m *HeadRequest) SetBody(v *HeadRequest_Body) { + m.Body = v +} + +// SetMetaHeader sets meta header of the request. +func (m *HeadRequest) SetMetaHeader(v *session.RequestMetaHeader) { + m.MetaHeader = v +} + +// SetVerifyHeader sets verification header of the request. +func (m *HeadRequest) SetVerifyHeader(v *session.RequestVerificationHeader) { + m.VerifyHeader = v +} + +// SetHeader sets object header. +func (m *HeaderWithSignature) SetHeader(v *Header) { + m.Header = v +} + +// SetSignature of the header. +func (m *HeaderWithSignature) SetSignature(v *refs.Signature) { + m.Signature = v +} + +// SetHeader sets full header of the object. +func (m *HeadResponse_Body) SetHeader(v *HeaderWithSignature) { + m.Head = &HeadResponse_Body_Header{ + Header: v, + } +} + +// SetShortHeader sets short header of the object. +func (m *HeadResponse_Body) SetShortHeader(v *ShortHeader) { + m.Head = &HeadResponse_Body_ShortHeader{ + ShortHeader: v, + } +} + +// SetSplitInfo sets meta info about split hierarchy of the object. +func (m *HeadResponse_Body) SetSplitInfo(v *SplitInfo) { + m.Head = &HeadResponse_Body_SplitInfo{ + SplitInfo: v, + } +} + +// SetBody sets body of the response. +func (m *HeadResponse) SetBody(v *HeadResponse_Body) { + m.Body = v +} + +// SetMetaHeader sets meta header of the response. +func (m *HeadResponse) SetMetaHeader(v *session.ResponseMetaHeader) { + m.MetaHeader = v +} + +// SetVerifyHeader sets verification header of the response. +func (m *HeadResponse) SetVerifyHeader(v *session.ResponseVerificationHeader) { + m.VerifyHeader = v +} + +// SetMatchType sets match type of the filter. +func (m *SearchRequest_Body_Filter) SetMatchType(v MatchType) { + m.MatchType = v +} + +// SetKey sets key to the filtering header. +func (m *SearchRequest_Body_Filter) SetKey(v string) { + m.Key = v +} + +// SetValue sets value of the filtering header. +func (m *SearchRequest_Body_Filter) SetValue(v string) { + m.Value = v +} + +// SetVersion sets version of the search query. +func (m *SearchRequest_Body) SetVersion(v uint32) { + m.Version = v +} + +// SetFilters sets list of the query filters. +func (m *SearchRequest_Body) SetFilters(v []*SearchRequest_Body_Filter) { + m.Filters = v +} + +// SetContainerId sets container ID of the search requets. +func (m *SearchRequest_Body) SetContainerId(v *refs.ContainerID) { + m.ContainerId = v +} + +// SetBody sets body of the request. +func (m *SearchRequest) SetBody(v *SearchRequest_Body) { + m.Body = v +} + +// SetMetaHeader sets meta header of the request. +func (m *SearchRequest) SetMetaHeader(v *session.RequestMetaHeader) { + m.MetaHeader = v +} + +// SetVerifyHeader sets verification header of the request. +func (m *SearchRequest) SetVerifyHeader(v *session.RequestVerificationHeader) { + m.VerifyHeader = v +} + +// SetIdList sets list of the identifiers of the matched objects. +func (m *SearchResponse_Body) SetIdList(v []*refs.ObjectID) { + m.IdList = v +} + +// SetBody sets body of the response. +func (m *SearchResponse) SetBody(v *SearchResponse_Body) { + m.Body = v +} + +// SetMetaHeader sets meta header of the response. +func (m *SearchResponse) SetMetaHeader(v *session.ResponseMetaHeader) { + m.MetaHeader = v +} + +// SetVerifyHeader sets verification header of the response. +func (m *SearchResponse) SetVerifyHeader(v *session.ResponseVerificationHeader) { + m.VerifyHeader = v +} + +// SetOffset sets offset of the payload range. +func (m *Range) SetOffset(v uint64) { + m.Offset = v +} + +// SetLength sets length of the payload range. +func (m *Range) SetLength(v uint64) { + m.Length = v +} + +// SetAddress sets address of the object with the request payload range. +func (m *GetRangeRequest_Body) SetAddress(v *refs.Address) { + m.Address = v +} + +// SetRange sets range of the object payload. +func (m *GetRangeRequest_Body) SetRange(v *Range) { + m.Range = v +} + +// SetRaw sets raw flag of the request. +func (m *GetRangeRequest_Body) SetRaw(v bool) { + m.Raw = v +} + +// SetBody sets body of the request. +func (m *GetRangeRequest) SetBody(v *GetRangeRequest_Body) { + m.Body = v +} + +// SetMetaHeader sets meta header of the request. +func (m *GetRangeRequest) SetMetaHeader(v *session.RequestMetaHeader) { + m.MetaHeader = v +} + +// SetVerifyHeader sets verification header of the request. +func (m *GetRangeRequest) SetVerifyHeader(v *session.RequestVerificationHeader) { + m.VerifyHeader = v +} + +// GetChunk returns chunk of the object payload range bytes. +func (m *GetRangeResponse_Body_Chunk) GetChunk() []byte { + if m != nil { + return m.Chunk + } + + return nil +} + +// SetChunk sets chunk of the object payload range bytes. +func (m *GetRangeResponse_Body_Chunk) SetChunk(v []byte) { + m.Chunk = v +} + +// SetChunk sets chunk of the object payload. +func (m *GetRangeResponse_Body) SetChunk(v *GetRangeResponse_Body_Chunk) { + m.RangePart = v +} + +// SetSplitInfo sets meta info about split hierarchy of the object. +func (m *GetRangeResponse_Body) SetSplitInfo(v *SplitInfo) { + m.RangePart = &GetRangeResponse_Body_SplitInfo{ + SplitInfo: v, + } +} + +// SetBody sets body of the response. +func (m *GetRangeResponse) SetBody(v *GetRangeResponse_Body) { + m.Body = v +} + +// SetMetaHeader sets meta header of the response. +func (m *GetRangeResponse) SetMetaHeader(v *session.ResponseMetaHeader) { + m.MetaHeader = v +} + +// SetVerifyHeader sets verification header of the response. +func (m *GetRangeResponse) SetVerifyHeader(v *session.ResponseVerificationHeader) { + m.VerifyHeader = v +} + +// SetAddress sets address of the object with the request payload range. +func (m *GetRangeHashRequest_Body) SetAddress(v *refs.Address) { + m.Address = v +} + +// SetRanges sets list of the ranges of the object payload. +func (m *GetRangeHashRequest_Body) SetRanges(v []*Range) { + m.Ranges = v +} + +// SetSalt sets salt for the object payload ranges. +func (m *GetRangeHashRequest_Body) SetSalt(v []byte) { + m.Salt = v +} + +// Set sets salt for the object payload ranges. +func (m *GetRangeHashRequest_Body) SetType(v refs.ChecksumType) { + m.Type = v +} + +// SetBody sets body of the request. +func (m *GetRangeHashRequest) SetBody(v *GetRangeHashRequest_Body) { + m.Body = v +} + +// SetMetaHeader sets meta header of the request. +func (m *GetRangeHashRequest) SetMetaHeader(v *session.RequestMetaHeader) { + m.MetaHeader = v +} + +// SetVerifyHeader sets verification header of the request. +func (m *GetRangeHashRequest) SetVerifyHeader(v *session.RequestVerificationHeader) { + m.VerifyHeader = v +} + +// SetHashList returns list of the range hashes. +func (m *GetRangeHashResponse_Body) SetHashList(v [][]byte) { + m.HashList = v +} + +// SetHashList returns list of the range hashes. +func (m *GetRangeHashResponse_Body) SetType(v refs.ChecksumType) { + m.Type = v +} + +// SetBody sets body of the response. +func (m *GetRangeHashResponse) SetBody(v *GetRangeHashResponse_Body) { + m.Body = v +} + +// SetMetaHeader sets meta header of the response. +func (m *GetRangeHashResponse) SetMetaHeader(v *session.ResponseMetaHeader) { + m.MetaHeader = v +} + +// SetVerifyHeader sets verification header of the response. +func (m *GetRangeHashResponse) SetVerifyHeader(v *session.ResponseVerificationHeader) { + m.VerifyHeader = v +} + +// SetObject set object of the body. +func (m *PutSingleRequest_Body) SetObject(o *Object) { + m.Object = o +} + +// SetCopiesNumber sets copies number of the body. +func (m *PutSingleRequest_Body) SetCopiesNumber(v []uint32) { + m.CopiesNumber = v +} + +// SetBody sets body of the request. +func (m *PutSingleRequest) SetBody(b *PutSingleRequest_Body) { + m.Body = b +} + +// SetMetaHeader sets meta header of the request. +func (m *PutSingleRequest) SetMetaHeader(v *session.RequestMetaHeader) { + m.MetaHeader = v +} + +// SetVerifyHeader sets verification header of the request. +func (m *PutSingleRequest) SetVerifyHeader(v *session.RequestVerificationHeader) { + m.VerifyHeader = v +} + +// SetBody sets body of the response. +func (m *PutSingleResponse) SetBody(b *PutSingleResponse_Body) { + m.Body = b +} + +// SetMetaHeader sets meta header of the response. +func (m *PutSingleResponse) SetMetaHeader(v *session.ResponseMetaHeader) { + m.MetaHeader = v +} + +// SetVerifyHeader sets verification header of the response. +func (m *PutSingleResponse) SetVerifyHeader(v *session.ResponseVerificationHeader) { + m.VerifyHeader = v +} diff --git a/pkg/api/object/grpc/service.pb.go b/pkg/api/object/grpc/service.pb.go new file mode 100644 index 000000000..112e5537b --- /dev/null +++ b/pkg/api/object/grpc/service.pb.go @@ -0,0 +1,3774 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.33.0 +// protoc v4.25.3 +// source: object/grpc/service.proto + +package object + +import ( + grpc1 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs/grpc" + grpc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session/grpc" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// GET object request +type GetRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Body of get object request message. + Body *GetRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Carries request meta information. Header data is used only to regulate + // message transport and does not affect request execution. + MetaHeader *grpc.RequestMetaHeader `protobuf:"bytes,2,opt,name=meta_header,json=metaHeader,proto3" json:"meta_header,omitempty"` + // Carries request verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + VerifyHeader *grpc.RequestVerificationHeader `protobuf:"bytes,3,opt,name=verify_header,json=verifyHeader,proto3" json:"verify_header,omitempty"` +} + +func (x *GetRequest) Reset() { + *x = GetRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_object_grpc_service_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetRequest) ProtoMessage() {} + +func (x *GetRequest) ProtoReflect() protoreflect.Message { + mi := &file_object_grpc_service_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetRequest.ProtoReflect.Descriptor instead. +func (*GetRequest) Descriptor() ([]byte, []int) { + return file_object_grpc_service_proto_rawDescGZIP(), []int{0} +} + +func (x *GetRequest) GetBody() *GetRequest_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *GetRequest) GetMetaHeader() *grpc.RequestMetaHeader { + if x != nil { + return x.MetaHeader + } + return nil +} + +func (x *GetRequest) GetVerifyHeader() *grpc.RequestVerificationHeader { + if x != nil { + return x.VerifyHeader + } + return nil +} + +// GET object response +type GetResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Body of get object response message. + Body *GetResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Carries response meta information. Header data is used only to regulate + // message transport and does not affect request execution. + MetaHeader *grpc.ResponseMetaHeader `protobuf:"bytes,2,opt,name=meta_header,json=metaHeader,proto3" json:"meta_header,omitempty"` + // Carries response verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + VerifyHeader *grpc.ResponseVerificationHeader `protobuf:"bytes,3,opt,name=verify_header,json=verifyHeader,proto3" json:"verify_header,omitempty"` +} + +func (x *GetResponse) Reset() { + *x = GetResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_object_grpc_service_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetResponse) ProtoMessage() {} + +func (x *GetResponse) ProtoReflect() protoreflect.Message { + mi := &file_object_grpc_service_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetResponse.ProtoReflect.Descriptor instead. +func (*GetResponse) Descriptor() ([]byte, []int) { + return file_object_grpc_service_proto_rawDescGZIP(), []int{1} +} + +func (x *GetResponse) GetBody() *GetResponse_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *GetResponse) GetMetaHeader() *grpc.ResponseMetaHeader { + if x != nil { + return x.MetaHeader + } + return nil +} + +func (x *GetResponse) GetVerifyHeader() *grpc.ResponseVerificationHeader { + if x != nil { + return x.VerifyHeader + } + return nil +} + +// PUT object request +type PutRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Body of put object request message. + Body *PutRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Carries request meta information. Header data is used only to regulate + // message transport and does not affect request execution. + MetaHeader *grpc.RequestMetaHeader `protobuf:"bytes,2,opt,name=meta_header,json=metaHeader,proto3" json:"meta_header,omitempty"` + // Carries request verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + VerifyHeader *grpc.RequestVerificationHeader `protobuf:"bytes,3,opt,name=verify_header,json=verifyHeader,proto3" json:"verify_header,omitempty"` +} + +func (x *PutRequest) Reset() { + *x = PutRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_object_grpc_service_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PutRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PutRequest) ProtoMessage() {} + +func (x *PutRequest) ProtoReflect() protoreflect.Message { + mi := &file_object_grpc_service_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PutRequest.ProtoReflect.Descriptor instead. +func (*PutRequest) Descriptor() ([]byte, []int) { + return file_object_grpc_service_proto_rawDescGZIP(), []int{2} +} + +func (x *PutRequest) GetBody() *PutRequest_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *PutRequest) GetMetaHeader() *grpc.RequestMetaHeader { + if x != nil { + return x.MetaHeader + } + return nil +} + +func (x *PutRequest) GetVerifyHeader() *grpc.RequestVerificationHeader { + if x != nil { + return x.VerifyHeader + } + return nil +} + +// PUT Object response +type PutResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Body of put object response message. + Body *PutResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Carries response meta information. Header data is used only to regulate + // message transport and does not affect request execution. + MetaHeader *grpc.ResponseMetaHeader `protobuf:"bytes,2,opt,name=meta_header,json=metaHeader,proto3" json:"meta_header,omitempty"` + // Carries response verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + VerifyHeader *grpc.ResponseVerificationHeader `protobuf:"bytes,3,opt,name=verify_header,json=verifyHeader,proto3" json:"verify_header,omitempty"` +} + +func (x *PutResponse) Reset() { + *x = PutResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_object_grpc_service_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PutResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PutResponse) ProtoMessage() {} + +func (x *PutResponse) ProtoReflect() protoreflect.Message { + mi := &file_object_grpc_service_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PutResponse.ProtoReflect.Descriptor instead. +func (*PutResponse) Descriptor() ([]byte, []int) { + return file_object_grpc_service_proto_rawDescGZIP(), []int{3} +} + +func (x *PutResponse) GetBody() *PutResponse_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *PutResponse) GetMetaHeader() *grpc.ResponseMetaHeader { + if x != nil { + return x.MetaHeader + } + return nil +} + +func (x *PutResponse) GetVerifyHeader() *grpc.ResponseVerificationHeader { + if x != nil { + return x.VerifyHeader + } + return nil +} + +// Object DELETE request +type DeleteRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Body of delete object request message. + Body *DeleteRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Carries request meta information. Header data is used only to regulate + // message transport and does not affect request execution. + MetaHeader *grpc.RequestMetaHeader `protobuf:"bytes,2,opt,name=meta_header,json=metaHeader,proto3" json:"meta_header,omitempty"` + // Carries request verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + VerifyHeader *grpc.RequestVerificationHeader `protobuf:"bytes,3,opt,name=verify_header,json=verifyHeader,proto3" json:"verify_header,omitempty"` +} + +func (x *DeleteRequest) Reset() { + *x = DeleteRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_object_grpc_service_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DeleteRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteRequest) ProtoMessage() {} + +func (x *DeleteRequest) ProtoReflect() protoreflect.Message { + mi := &file_object_grpc_service_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DeleteRequest.ProtoReflect.Descriptor instead. +func (*DeleteRequest) Descriptor() ([]byte, []int) { + return file_object_grpc_service_proto_rawDescGZIP(), []int{4} +} + +func (x *DeleteRequest) GetBody() *DeleteRequest_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *DeleteRequest) GetMetaHeader() *grpc.RequestMetaHeader { + if x != nil { + return x.MetaHeader + } + return nil +} + +func (x *DeleteRequest) GetVerifyHeader() *grpc.RequestVerificationHeader { + if x != nil { + return x.VerifyHeader + } + return nil +} + +// DeleteResponse body is empty because we cannot guarantee permanent object +// removal in distributed system. +type DeleteResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Body of delete object response message. + Body *DeleteResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Carries response meta information. Header data is used only to regulate + // message transport and does not affect request execution. + MetaHeader *grpc.ResponseMetaHeader `protobuf:"bytes,2,opt,name=meta_header,json=metaHeader,proto3" json:"meta_header,omitempty"` + // Carries response verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + VerifyHeader *grpc.ResponseVerificationHeader `protobuf:"bytes,3,opt,name=verify_header,json=verifyHeader,proto3" json:"verify_header,omitempty"` +} + +func (x *DeleteResponse) Reset() { + *x = DeleteResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_object_grpc_service_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DeleteResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteResponse) ProtoMessage() {} + +func (x *DeleteResponse) ProtoReflect() protoreflect.Message { + mi := &file_object_grpc_service_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DeleteResponse.ProtoReflect.Descriptor instead. +func (*DeleteResponse) Descriptor() ([]byte, []int) { + return file_object_grpc_service_proto_rawDescGZIP(), []int{5} +} + +func (x *DeleteResponse) GetBody() *DeleteResponse_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *DeleteResponse) GetMetaHeader() *grpc.ResponseMetaHeader { + if x != nil { + return x.MetaHeader + } + return nil +} + +func (x *DeleteResponse) GetVerifyHeader() *grpc.ResponseVerificationHeader { + if x != nil { + return x.VerifyHeader + } + return nil +} + +// Object HEAD request +type HeadRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Body of head object request message. + Body *HeadRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Carries request meta information. Header data is used only to regulate + // message transport and does not affect request execution. + MetaHeader *grpc.RequestMetaHeader `protobuf:"bytes,2,opt,name=meta_header,json=metaHeader,proto3" json:"meta_header,omitempty"` + // Carries request verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + VerifyHeader *grpc.RequestVerificationHeader `protobuf:"bytes,3,opt,name=verify_header,json=verifyHeader,proto3" json:"verify_header,omitempty"` +} + +func (x *HeadRequest) Reset() { + *x = HeadRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_object_grpc_service_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *HeadRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HeadRequest) ProtoMessage() {} + +func (x *HeadRequest) ProtoReflect() protoreflect.Message { + mi := &file_object_grpc_service_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use HeadRequest.ProtoReflect.Descriptor instead. +func (*HeadRequest) Descriptor() ([]byte, []int) { + return file_object_grpc_service_proto_rawDescGZIP(), []int{6} +} + +func (x *HeadRequest) GetBody() *HeadRequest_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *HeadRequest) GetMetaHeader() *grpc.RequestMetaHeader { + if x != nil { + return x.MetaHeader + } + return nil +} + +func (x *HeadRequest) GetVerifyHeader() *grpc.RequestVerificationHeader { + if x != nil { + return x.VerifyHeader + } + return nil +} + +// Tuple of a full object header and signature of an `ObjectID`. \ +// Signed `ObjectID` is present to verify full header's authenticity through the +// following steps: +// +// 1. Calculate `SHA-256` of the marshalled `Header` structure +// 2. Check if the resulting hash matches `ObjectID` +// 3. Check if `ObjectID` signature in `signature` field is correct +type HeaderWithSignature struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Full object header + Header *Header `protobuf:"bytes,1,opt,name=header,proto3" json:"header,omitempty"` + // Signed `ObjectID` to verify full header's authenticity + Signature *grpc1.Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` +} + +func (x *HeaderWithSignature) Reset() { + *x = HeaderWithSignature{} + if protoimpl.UnsafeEnabled { + mi := &file_object_grpc_service_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *HeaderWithSignature) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HeaderWithSignature) ProtoMessage() {} + +func (x *HeaderWithSignature) ProtoReflect() protoreflect.Message { + mi := &file_object_grpc_service_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use HeaderWithSignature.ProtoReflect.Descriptor instead. +func (*HeaderWithSignature) Descriptor() ([]byte, []int) { + return file_object_grpc_service_proto_rawDescGZIP(), []int{7} +} + +func (x *HeaderWithSignature) GetHeader() *Header { + if x != nil { + return x.Header + } + return nil +} + +func (x *HeaderWithSignature) GetSignature() *grpc1.Signature { + if x != nil { + return x.Signature + } + return nil +} + +// Object HEAD response +type HeadResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Body of head object response message. + Body *HeadResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Carries response meta information. Header data is used only to regulate + // message transport and does not affect request execution. + MetaHeader *grpc.ResponseMetaHeader `protobuf:"bytes,2,opt,name=meta_header,json=metaHeader,proto3" json:"meta_header,omitempty"` + // Carries response verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + VerifyHeader *grpc.ResponseVerificationHeader `protobuf:"bytes,3,opt,name=verify_header,json=verifyHeader,proto3" json:"verify_header,omitempty"` +} + +func (x *HeadResponse) Reset() { + *x = HeadResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_object_grpc_service_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *HeadResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HeadResponse) ProtoMessage() {} + +func (x *HeadResponse) ProtoReflect() protoreflect.Message { + mi := &file_object_grpc_service_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use HeadResponse.ProtoReflect.Descriptor instead. +func (*HeadResponse) Descriptor() ([]byte, []int) { + return file_object_grpc_service_proto_rawDescGZIP(), []int{8} +} + +func (x *HeadResponse) GetBody() *HeadResponse_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *HeadResponse) GetMetaHeader() *grpc.ResponseMetaHeader { + if x != nil { + return x.MetaHeader + } + return nil +} + +func (x *HeadResponse) GetVerifyHeader() *grpc.ResponseVerificationHeader { + if x != nil { + return x.VerifyHeader + } + return nil +} + +// Object Search request +type SearchRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Body of search object request message. + Body *SearchRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Carries request meta information. Header data is used only to regulate + // message transport and does not affect request execution. + MetaHeader *grpc.RequestMetaHeader `protobuf:"bytes,2,opt,name=meta_header,json=metaHeader,proto3" json:"meta_header,omitempty"` + // Carries request verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + VerifyHeader *grpc.RequestVerificationHeader `protobuf:"bytes,3,opt,name=verify_header,json=verifyHeader,proto3" json:"verify_header,omitempty"` +} + +func (x *SearchRequest) Reset() { + *x = SearchRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_object_grpc_service_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SearchRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SearchRequest) ProtoMessage() {} + +func (x *SearchRequest) ProtoReflect() protoreflect.Message { + mi := &file_object_grpc_service_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SearchRequest.ProtoReflect.Descriptor instead. +func (*SearchRequest) Descriptor() ([]byte, []int) { + return file_object_grpc_service_proto_rawDescGZIP(), []int{9} +} + +func (x *SearchRequest) GetBody() *SearchRequest_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *SearchRequest) GetMetaHeader() *grpc.RequestMetaHeader { + if x != nil { + return x.MetaHeader + } + return nil +} + +func (x *SearchRequest) GetVerifyHeader() *grpc.RequestVerificationHeader { + if x != nil { + return x.VerifyHeader + } + return nil +} + +// Search response +type SearchResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Body of search object response message. + Body *SearchResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Carries response meta information. Header data is used only to regulate + // message transport and does not affect request execution. + MetaHeader *grpc.ResponseMetaHeader `protobuf:"bytes,2,opt,name=meta_header,json=metaHeader,proto3" json:"meta_header,omitempty"` + // Carries response verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + VerifyHeader *grpc.ResponseVerificationHeader `protobuf:"bytes,3,opt,name=verify_header,json=verifyHeader,proto3" json:"verify_header,omitempty"` +} + +func (x *SearchResponse) Reset() { + *x = SearchResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_object_grpc_service_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SearchResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SearchResponse) ProtoMessage() {} + +func (x *SearchResponse) ProtoReflect() protoreflect.Message { + mi := &file_object_grpc_service_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SearchResponse.ProtoReflect.Descriptor instead. +func (*SearchResponse) Descriptor() ([]byte, []int) { + return file_object_grpc_service_proto_rawDescGZIP(), []int{10} +} + +func (x *SearchResponse) GetBody() *SearchResponse_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *SearchResponse) GetMetaHeader() *grpc.ResponseMetaHeader { + if x != nil { + return x.MetaHeader + } + return nil +} + +func (x *SearchResponse) GetVerifyHeader() *grpc.ResponseVerificationHeader { + if x != nil { + return x.VerifyHeader + } + return nil +} + +// Object payload range.Ranges of zero length SHOULD be considered as invalid. +type Range struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Offset of the range from the object payload start + Offset uint64 `protobuf:"varint,1,opt,name=offset,proto3" json:"offset,omitempty"` + // Length in bytes of the object payload range + Length uint64 `protobuf:"varint,2,opt,name=length,proto3" json:"length,omitempty"` +} + +func (x *Range) Reset() { + *x = Range{} + if protoimpl.UnsafeEnabled { + mi := &file_object_grpc_service_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Range) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Range) ProtoMessage() {} + +func (x *Range) ProtoReflect() protoreflect.Message { + mi := &file_object_grpc_service_proto_msgTypes[11] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Range.ProtoReflect.Descriptor instead. +func (*Range) Descriptor() ([]byte, []int) { + return file_object_grpc_service_proto_rawDescGZIP(), []int{11} +} + +func (x *Range) GetOffset() uint64 { + if x != nil { + return x.Offset + } + return 0 +} + +func (x *Range) GetLength() uint64 { + if x != nil { + return x.Length + } + return 0 +} + +// Request part of object's payload +type GetRangeRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Body of get range object request message. + Body *GetRangeRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Carries request meta information. Header data is used only to regulate + // message transport and does not affect request execution. + MetaHeader *grpc.RequestMetaHeader `protobuf:"bytes,2,opt,name=meta_header,json=metaHeader,proto3" json:"meta_header,omitempty"` + // Carries request verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + VerifyHeader *grpc.RequestVerificationHeader `protobuf:"bytes,3,opt,name=verify_header,json=verifyHeader,proto3" json:"verify_header,omitempty"` +} + +func (x *GetRangeRequest) Reset() { + *x = GetRangeRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_object_grpc_service_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetRangeRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetRangeRequest) ProtoMessage() {} + +func (x *GetRangeRequest) ProtoReflect() protoreflect.Message { + mi := &file_object_grpc_service_proto_msgTypes[12] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetRangeRequest.ProtoReflect.Descriptor instead. +func (*GetRangeRequest) Descriptor() ([]byte, []int) { + return file_object_grpc_service_proto_rawDescGZIP(), []int{12} +} + +func (x *GetRangeRequest) GetBody() *GetRangeRequest_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *GetRangeRequest) GetMetaHeader() *grpc.RequestMetaHeader { + if x != nil { + return x.MetaHeader + } + return nil +} + +func (x *GetRangeRequest) GetVerifyHeader() *grpc.RequestVerificationHeader { + if x != nil { + return x.VerifyHeader + } + return nil +} + +// Get part of object's payload +type GetRangeResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Body of get range object response message. + Body *GetRangeResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Carries response meta information. Header data is used only to regulate + // message transport and does not affect request execution. + MetaHeader *grpc.ResponseMetaHeader `protobuf:"bytes,2,opt,name=meta_header,json=metaHeader,proto3" json:"meta_header,omitempty"` + // Carries response verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + VerifyHeader *grpc.ResponseVerificationHeader `protobuf:"bytes,3,opt,name=verify_header,json=verifyHeader,proto3" json:"verify_header,omitempty"` +} + +func (x *GetRangeResponse) Reset() { + *x = GetRangeResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_object_grpc_service_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetRangeResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetRangeResponse) ProtoMessage() {} + +func (x *GetRangeResponse) ProtoReflect() protoreflect.Message { + mi := &file_object_grpc_service_proto_msgTypes[13] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetRangeResponse.ProtoReflect.Descriptor instead. +func (*GetRangeResponse) Descriptor() ([]byte, []int) { + return file_object_grpc_service_proto_rawDescGZIP(), []int{13} +} + +func (x *GetRangeResponse) GetBody() *GetRangeResponse_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *GetRangeResponse) GetMetaHeader() *grpc.ResponseMetaHeader { + if x != nil { + return x.MetaHeader + } + return nil +} + +func (x *GetRangeResponse) GetVerifyHeader() *grpc.ResponseVerificationHeader { + if x != nil { + return x.VerifyHeader + } + return nil +} + +// Get hash of object's payload part +type GetRangeHashRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Body of get range hash object request message. + Body *GetRangeHashRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Carries request meta information. Header data is used only to regulate + // message transport and does not affect request execution. + MetaHeader *grpc.RequestMetaHeader `protobuf:"bytes,2,opt,name=meta_header,json=metaHeader,proto3" json:"meta_header,omitempty"` + // Carries request verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + VerifyHeader *grpc.RequestVerificationHeader `protobuf:"bytes,3,opt,name=verify_header,json=verifyHeader,proto3" json:"verify_header,omitempty"` +} + +func (x *GetRangeHashRequest) Reset() { + *x = GetRangeHashRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_object_grpc_service_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetRangeHashRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetRangeHashRequest) ProtoMessage() {} + +func (x *GetRangeHashRequest) ProtoReflect() protoreflect.Message { + mi := &file_object_grpc_service_proto_msgTypes[14] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetRangeHashRequest.ProtoReflect.Descriptor instead. +func (*GetRangeHashRequest) Descriptor() ([]byte, []int) { + return file_object_grpc_service_proto_rawDescGZIP(), []int{14} +} + +func (x *GetRangeHashRequest) GetBody() *GetRangeHashRequest_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *GetRangeHashRequest) GetMetaHeader() *grpc.RequestMetaHeader { + if x != nil { + return x.MetaHeader + } + return nil +} + +func (x *GetRangeHashRequest) GetVerifyHeader() *grpc.RequestVerificationHeader { + if x != nil { + return x.VerifyHeader + } + return nil +} + +// Get hash of object's payload part +type GetRangeHashResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Body of get range hash object response message. + Body *GetRangeHashResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Carries response meta information. Header data is used only to regulate + // message transport and does not affect request execution. + MetaHeader *grpc.ResponseMetaHeader `protobuf:"bytes,2,opt,name=meta_header,json=metaHeader,proto3" json:"meta_header,omitempty"` + // Carries response verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + VerifyHeader *grpc.ResponseVerificationHeader `protobuf:"bytes,3,opt,name=verify_header,json=verifyHeader,proto3" json:"verify_header,omitempty"` +} + +func (x *GetRangeHashResponse) Reset() { + *x = GetRangeHashResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_object_grpc_service_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetRangeHashResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetRangeHashResponse) ProtoMessage() {} + +func (x *GetRangeHashResponse) ProtoReflect() protoreflect.Message { + mi := &file_object_grpc_service_proto_msgTypes[15] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetRangeHashResponse.ProtoReflect.Descriptor instead. +func (*GetRangeHashResponse) Descriptor() ([]byte, []int) { + return file_object_grpc_service_proto_rawDescGZIP(), []int{15} +} + +func (x *GetRangeHashResponse) GetBody() *GetRangeHashResponse_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *GetRangeHashResponse) GetMetaHeader() *grpc.ResponseMetaHeader { + if x != nil { + return x.MetaHeader + } + return nil +} + +func (x *GetRangeHashResponse) GetVerifyHeader() *grpc.ResponseVerificationHeader { + if x != nil { + return x.VerifyHeader + } + return nil +} + +// Object PUT Single request +type PutSingleRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Body of put single object request message. + Body *PutSingleRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Carries request meta information. Header data is used only to regulate + // message transport and does not affect request execution. + MetaHeader *grpc.RequestMetaHeader `protobuf:"bytes,2,opt,name=meta_header,json=metaHeader,proto3" json:"meta_header,omitempty"` + // Carries request verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + VerifyHeader *grpc.RequestVerificationHeader `protobuf:"bytes,3,opt,name=verify_header,json=verifyHeader,proto3" json:"verify_header,omitempty"` +} + +func (x *PutSingleRequest) Reset() { + *x = PutSingleRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_object_grpc_service_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PutSingleRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PutSingleRequest) ProtoMessage() {} + +func (x *PutSingleRequest) ProtoReflect() protoreflect.Message { + mi := &file_object_grpc_service_proto_msgTypes[16] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PutSingleRequest.ProtoReflect.Descriptor instead. +func (*PutSingleRequest) Descriptor() ([]byte, []int) { + return file_object_grpc_service_proto_rawDescGZIP(), []int{16} +} + +func (x *PutSingleRequest) GetBody() *PutSingleRequest_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *PutSingleRequest) GetMetaHeader() *grpc.RequestMetaHeader { + if x != nil { + return x.MetaHeader + } + return nil +} + +func (x *PutSingleRequest) GetVerifyHeader() *grpc.RequestVerificationHeader { + if x != nil { + return x.VerifyHeader + } + return nil +} + +// Object PUT Single response +type PutSingleResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Body of put single object response message. + Body *PutSingleResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Carries response meta information. Header data is used only to regulate + // message transport and does not affect request execution. + MetaHeader *grpc.ResponseMetaHeader `protobuf:"bytes,2,opt,name=meta_header,json=metaHeader,proto3" json:"meta_header,omitempty"` + // Carries response verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + VerifyHeader *grpc.ResponseVerificationHeader `protobuf:"bytes,3,opt,name=verify_header,json=verifyHeader,proto3" json:"verify_header,omitempty"` +} + +func (x *PutSingleResponse) Reset() { + *x = PutSingleResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_object_grpc_service_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PutSingleResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PutSingleResponse) ProtoMessage() {} + +func (x *PutSingleResponse) ProtoReflect() protoreflect.Message { + mi := &file_object_grpc_service_proto_msgTypes[17] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PutSingleResponse.ProtoReflect.Descriptor instead. +func (*PutSingleResponse) Descriptor() ([]byte, []int) { + return file_object_grpc_service_proto_rawDescGZIP(), []int{17} +} + +func (x *PutSingleResponse) GetBody() *PutSingleResponse_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *PutSingleResponse) GetMetaHeader() *grpc.ResponseMetaHeader { + if x != nil { + return x.MetaHeader + } + return nil +} + +func (x *PutSingleResponse) GetVerifyHeader() *grpc.ResponseVerificationHeader { + if x != nil { + return x.VerifyHeader + } + return nil +} + +// GET Object request body +type GetRequest_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Address of the requested object + Address *grpc1.Address `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + // If `raw` flag is set, request will work only with objects that are + // physically stored on the peer node + Raw bool `protobuf:"varint,2,opt,name=raw,proto3" json:"raw,omitempty"` +} + +func (x *GetRequest_Body) Reset() { + *x = GetRequest_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_object_grpc_service_proto_msgTypes[18] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetRequest_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetRequest_Body) ProtoMessage() {} + +func (x *GetRequest_Body) ProtoReflect() protoreflect.Message { + mi := &file_object_grpc_service_proto_msgTypes[18] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetRequest_Body.ProtoReflect.Descriptor instead. +func (*GetRequest_Body) Descriptor() ([]byte, []int) { + return file_object_grpc_service_proto_rawDescGZIP(), []int{0, 0} +} + +func (x *GetRequest_Body) GetAddress() *grpc1.Address { + if x != nil { + return x.Address + } + return nil +} + +func (x *GetRequest_Body) GetRaw() bool { + if x != nil { + return x.Raw + } + return false +} + +// GET Object Response body +type GetResponse_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Single message in the response stream. + // + // Types that are assignable to ObjectPart: + // + // *GetResponse_Body_Init_ + // *GetResponse_Body_Chunk + // *GetResponse_Body_SplitInfo + // *GetResponse_Body_EcInfo + ObjectPart isGetResponse_Body_ObjectPart `protobuf_oneof:"object_part"` +} + +func (x *GetResponse_Body) Reset() { + *x = GetResponse_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_object_grpc_service_proto_msgTypes[19] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetResponse_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetResponse_Body) ProtoMessage() {} + +func (x *GetResponse_Body) ProtoReflect() protoreflect.Message { + mi := &file_object_grpc_service_proto_msgTypes[19] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetResponse_Body.ProtoReflect.Descriptor instead. +func (*GetResponse_Body) Descriptor() ([]byte, []int) { + return file_object_grpc_service_proto_rawDescGZIP(), []int{1, 0} +} + +func (m *GetResponse_Body) GetObjectPart() isGetResponse_Body_ObjectPart { + if m != nil { + return m.ObjectPart + } + return nil +} + +func (x *GetResponse_Body) GetInit() *GetResponse_Body_Init { + if x, ok := x.GetObjectPart().(*GetResponse_Body_Init_); ok { + return x.Init + } + return nil +} + +func (x *GetResponse_Body) GetChunk() []byte { + if x, ok := x.GetObjectPart().(*GetResponse_Body_Chunk); ok { + return x.Chunk + } + return nil +} + +func (x *GetResponse_Body) GetSplitInfo() *SplitInfo { + if x, ok := x.GetObjectPart().(*GetResponse_Body_SplitInfo); ok { + return x.SplitInfo + } + return nil +} + +func (x *GetResponse_Body) GetEcInfo() *ECInfo { + if x, ok := x.GetObjectPart().(*GetResponse_Body_EcInfo); ok { + return x.EcInfo + } + return nil +} + +type isGetResponse_Body_ObjectPart interface { + isGetResponse_Body_ObjectPart() +} + +type GetResponse_Body_Init_ struct { + // Initial part of the object stream + Init *GetResponse_Body_Init `protobuf:"bytes,1,opt,name=init,proto3,oneof"` +} + +type GetResponse_Body_Chunk struct { + // Chunked object payload + Chunk []byte `protobuf:"bytes,2,opt,name=chunk,proto3,oneof"` +} + +type GetResponse_Body_SplitInfo struct { + // Meta information of split hierarchy for object assembly. + SplitInfo *SplitInfo `protobuf:"bytes,3,opt,name=split_info,json=splitInfo,proto3,oneof"` +} + +type GetResponse_Body_EcInfo struct { + // Meta information for EC object assembly. + EcInfo *ECInfo `protobuf:"bytes,4,opt,name=ec_info,json=ecInfo,proto3,oneof"` +} + +func (*GetResponse_Body_Init_) isGetResponse_Body_ObjectPart() {} + +func (*GetResponse_Body_Chunk) isGetResponse_Body_ObjectPart() {} + +func (*GetResponse_Body_SplitInfo) isGetResponse_Body_ObjectPart() {} + +func (*GetResponse_Body_EcInfo) isGetResponse_Body_ObjectPart() {} + +// Initial part of the `Object` structure stream. Technically it's a +// set of all `Object` structure's fields except `payload`. +type GetResponse_Body_Init struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Object's unique identifier. + ObjectId *grpc1.ObjectID `protobuf:"bytes,1,opt,name=object_id,json=objectId,proto3" json:"object_id,omitempty"` + // Signed `ObjectID` + Signature *grpc1.Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` + // Object metadata headers + Header *Header `protobuf:"bytes,3,opt,name=header,proto3" json:"header,omitempty"` +} + +func (x *GetResponse_Body_Init) Reset() { + *x = GetResponse_Body_Init{} + if protoimpl.UnsafeEnabled { + mi := &file_object_grpc_service_proto_msgTypes[20] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetResponse_Body_Init) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetResponse_Body_Init) ProtoMessage() {} + +func (x *GetResponse_Body_Init) ProtoReflect() protoreflect.Message { + mi := &file_object_grpc_service_proto_msgTypes[20] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetResponse_Body_Init.ProtoReflect.Descriptor instead. +func (*GetResponse_Body_Init) Descriptor() ([]byte, []int) { + return file_object_grpc_service_proto_rawDescGZIP(), []int{1, 0, 0} +} + +func (x *GetResponse_Body_Init) GetObjectId() *grpc1.ObjectID { + if x != nil { + return x.ObjectId + } + return nil +} + +func (x *GetResponse_Body_Init) GetSignature() *grpc1.Signature { + if x != nil { + return x.Signature + } + return nil +} + +func (x *GetResponse_Body_Init) GetHeader() *Header { + if x != nil { + return x.Header + } + return nil +} + +// PUT request body +type PutRequest_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Single message in the request stream. + // + // Types that are assignable to ObjectPart: + // + // *PutRequest_Body_Init_ + // *PutRequest_Body_Chunk + ObjectPart isPutRequest_Body_ObjectPart `protobuf_oneof:"object_part"` +} + +func (x *PutRequest_Body) Reset() { + *x = PutRequest_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_object_grpc_service_proto_msgTypes[21] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PutRequest_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PutRequest_Body) ProtoMessage() {} + +func (x *PutRequest_Body) ProtoReflect() protoreflect.Message { + mi := &file_object_grpc_service_proto_msgTypes[21] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PutRequest_Body.ProtoReflect.Descriptor instead. +func (*PutRequest_Body) Descriptor() ([]byte, []int) { + return file_object_grpc_service_proto_rawDescGZIP(), []int{2, 0} +} + +func (m *PutRequest_Body) GetObjectPart() isPutRequest_Body_ObjectPart { + if m != nil { + return m.ObjectPart + } + return nil +} + +func (x *PutRequest_Body) GetInit() *PutRequest_Body_Init { + if x, ok := x.GetObjectPart().(*PutRequest_Body_Init_); ok { + return x.Init + } + return nil +} + +func (x *PutRequest_Body) GetChunk() []byte { + if x, ok := x.GetObjectPart().(*PutRequest_Body_Chunk); ok { + return x.Chunk + } + return nil +} + +type isPutRequest_Body_ObjectPart interface { + isPutRequest_Body_ObjectPart() +} + +type PutRequest_Body_Init_ struct { + // Initial part of the object stream + Init *PutRequest_Body_Init `protobuf:"bytes,1,opt,name=init,proto3,oneof"` +} + +type PutRequest_Body_Chunk struct { + // Chunked object payload + Chunk []byte `protobuf:"bytes,2,opt,name=chunk,proto3,oneof"` +} + +func (*PutRequest_Body_Init_) isPutRequest_Body_ObjectPart() {} + +func (*PutRequest_Body_Chunk) isPutRequest_Body_ObjectPart() {} + +// Newly created object structure parameters. If some optional parameters +// are not set, they will be calculated by a peer node. +type PutRequest_Body_Init struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // ObjectID if available. + ObjectId *grpc1.ObjectID `protobuf:"bytes,1,opt,name=object_id,json=objectId,proto3" json:"object_id,omitempty"` + // Object signature if available + Signature *grpc1.Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` + // Object's Header + Header *Header `protobuf:"bytes,3,opt,name=header,proto3" json:"header,omitempty"` + // Number of copies of the object to store within the RPC call. By + // default, object is processed according to the container's placement + // policy. Can be one of: + // 1. A single number; applied to the whole request and is treated as + // a minimal number of nodes that must store an object to complete the + // request successfully. + // 2. An ordered array; every number is treated as a minimal number of + // nodes in a corresponding placement vector that must store an object + // to complete the request successfully. The length MUST equal the + // placement vectors number, otherwise request is considered malformed. + CopiesNumber []uint32 `protobuf:"varint,4,rep,packed,name=copies_number,json=copiesNumber,proto3" json:"copies_number,omitempty"` +} + +func (x *PutRequest_Body_Init) Reset() { + *x = PutRequest_Body_Init{} + if protoimpl.UnsafeEnabled { + mi := &file_object_grpc_service_proto_msgTypes[22] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PutRequest_Body_Init) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PutRequest_Body_Init) ProtoMessage() {} + +func (x *PutRequest_Body_Init) ProtoReflect() protoreflect.Message { + mi := &file_object_grpc_service_proto_msgTypes[22] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PutRequest_Body_Init.ProtoReflect.Descriptor instead. +func (*PutRequest_Body_Init) Descriptor() ([]byte, []int) { + return file_object_grpc_service_proto_rawDescGZIP(), []int{2, 0, 0} +} + +func (x *PutRequest_Body_Init) GetObjectId() *grpc1.ObjectID { + if x != nil { + return x.ObjectId + } + return nil +} + +func (x *PutRequest_Body_Init) GetSignature() *grpc1.Signature { + if x != nil { + return x.Signature + } + return nil +} + +func (x *PutRequest_Body_Init) GetHeader() *Header { + if x != nil { + return x.Header + } + return nil +} + +func (x *PutRequest_Body_Init) GetCopiesNumber() []uint32 { + if x != nil { + return x.CopiesNumber + } + return nil +} + +// PUT Object response body +type PutResponse_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Identifier of the saved object + ObjectId *grpc1.ObjectID `protobuf:"bytes,1,opt,name=object_id,json=objectId,proto3" json:"object_id,omitempty"` +} + +func (x *PutResponse_Body) Reset() { + *x = PutResponse_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_object_grpc_service_proto_msgTypes[23] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PutResponse_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PutResponse_Body) ProtoMessage() {} + +func (x *PutResponse_Body) ProtoReflect() protoreflect.Message { + mi := &file_object_grpc_service_proto_msgTypes[23] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PutResponse_Body.ProtoReflect.Descriptor instead. +func (*PutResponse_Body) Descriptor() ([]byte, []int) { + return file_object_grpc_service_proto_rawDescGZIP(), []int{3, 0} +} + +func (x *PutResponse_Body) GetObjectId() *grpc1.ObjectID { + if x != nil { + return x.ObjectId + } + return nil +} + +// Object DELETE request body +type DeleteRequest_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Address of the object to be deleted + Address *grpc1.Address `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` +} + +func (x *DeleteRequest_Body) Reset() { + *x = DeleteRequest_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_object_grpc_service_proto_msgTypes[24] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DeleteRequest_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteRequest_Body) ProtoMessage() {} + +func (x *DeleteRequest_Body) ProtoReflect() protoreflect.Message { + mi := &file_object_grpc_service_proto_msgTypes[24] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DeleteRequest_Body.ProtoReflect.Descriptor instead. +func (*DeleteRequest_Body) Descriptor() ([]byte, []int) { + return file_object_grpc_service_proto_rawDescGZIP(), []int{4, 0} +} + +func (x *DeleteRequest_Body) GetAddress() *grpc1.Address { + if x != nil { + return x.Address + } + return nil +} + +// Object DELETE Response has an empty body. +type DeleteResponse_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Address of the tombstone created for the deleted object + Tombstone *grpc1.Address `protobuf:"bytes,1,opt,name=tombstone,proto3" json:"tombstone,omitempty"` +} + +func (x *DeleteResponse_Body) Reset() { + *x = DeleteResponse_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_object_grpc_service_proto_msgTypes[25] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DeleteResponse_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteResponse_Body) ProtoMessage() {} + +func (x *DeleteResponse_Body) ProtoReflect() protoreflect.Message { + mi := &file_object_grpc_service_proto_msgTypes[25] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DeleteResponse_Body.ProtoReflect.Descriptor instead. +func (*DeleteResponse_Body) Descriptor() ([]byte, []int) { + return file_object_grpc_service_proto_rawDescGZIP(), []int{5, 0} +} + +func (x *DeleteResponse_Body) GetTombstone() *grpc1.Address { + if x != nil { + return x.Tombstone + } + return nil +} + +// Object HEAD request body +type HeadRequest_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Address of the object with the requested Header + Address *grpc1.Address `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + // Return only minimal header subset + MainOnly bool `protobuf:"varint,2,opt,name=main_only,json=mainOnly,proto3" json:"main_only,omitempty"` + // If `raw` flag is set, request will work only with objects that are + // physically stored on the peer node + Raw bool `protobuf:"varint,3,opt,name=raw,proto3" json:"raw,omitempty"` +} + +func (x *HeadRequest_Body) Reset() { + *x = HeadRequest_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_object_grpc_service_proto_msgTypes[26] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *HeadRequest_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HeadRequest_Body) ProtoMessage() {} + +func (x *HeadRequest_Body) ProtoReflect() protoreflect.Message { + mi := &file_object_grpc_service_proto_msgTypes[26] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use HeadRequest_Body.ProtoReflect.Descriptor instead. +func (*HeadRequest_Body) Descriptor() ([]byte, []int) { + return file_object_grpc_service_proto_rawDescGZIP(), []int{6, 0} +} + +func (x *HeadRequest_Body) GetAddress() *grpc1.Address { + if x != nil { + return x.Address + } + return nil +} + +func (x *HeadRequest_Body) GetMainOnly() bool { + if x != nil { + return x.MainOnly + } + return false +} + +func (x *HeadRequest_Body) GetRaw() bool { + if x != nil { + return x.Raw + } + return false +} + +// Object HEAD response body +type HeadResponse_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Requested object header, it's part or meta information about split + // object. + // + // Types that are assignable to Head: + // + // *HeadResponse_Body_Header + // *HeadResponse_Body_ShortHeader + // *HeadResponse_Body_SplitInfo + // *HeadResponse_Body_EcInfo + Head isHeadResponse_Body_Head `protobuf_oneof:"head"` +} + +func (x *HeadResponse_Body) Reset() { + *x = HeadResponse_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_object_grpc_service_proto_msgTypes[27] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *HeadResponse_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HeadResponse_Body) ProtoMessage() {} + +func (x *HeadResponse_Body) ProtoReflect() protoreflect.Message { + mi := &file_object_grpc_service_proto_msgTypes[27] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use HeadResponse_Body.ProtoReflect.Descriptor instead. +func (*HeadResponse_Body) Descriptor() ([]byte, []int) { + return file_object_grpc_service_proto_rawDescGZIP(), []int{8, 0} +} + +func (m *HeadResponse_Body) GetHead() isHeadResponse_Body_Head { + if m != nil { + return m.Head + } + return nil +} + +func (x *HeadResponse_Body) GetHeader() *HeaderWithSignature { + if x, ok := x.GetHead().(*HeadResponse_Body_Header); ok { + return x.Header + } + return nil +} + +func (x *HeadResponse_Body) GetShortHeader() *ShortHeader { + if x, ok := x.GetHead().(*HeadResponse_Body_ShortHeader); ok { + return x.ShortHeader + } + return nil +} + +func (x *HeadResponse_Body) GetSplitInfo() *SplitInfo { + if x, ok := x.GetHead().(*HeadResponse_Body_SplitInfo); ok { + return x.SplitInfo + } + return nil +} + +func (x *HeadResponse_Body) GetEcInfo() *ECInfo { + if x, ok := x.GetHead().(*HeadResponse_Body_EcInfo); ok { + return x.EcInfo + } + return nil +} + +type isHeadResponse_Body_Head interface { + isHeadResponse_Body_Head() +} + +type HeadResponse_Body_Header struct { + // Full object's `Header` with `ObjectID` signature + Header *HeaderWithSignature `protobuf:"bytes,1,opt,name=header,proto3,oneof"` +} + +type HeadResponse_Body_ShortHeader struct { + // Short object header + ShortHeader *ShortHeader `protobuf:"bytes,2,opt,name=short_header,json=shortHeader,proto3,oneof"` +} + +type HeadResponse_Body_SplitInfo struct { + // Meta information of split hierarchy. + SplitInfo *SplitInfo `protobuf:"bytes,3,opt,name=split_info,json=splitInfo,proto3,oneof"` +} + +type HeadResponse_Body_EcInfo struct { + // Meta information for EC object assembly. + EcInfo *ECInfo `protobuf:"bytes,4,opt,name=ec_info,json=ecInfo,proto3,oneof"` +} + +func (*HeadResponse_Body_Header) isHeadResponse_Body_Head() {} + +func (*HeadResponse_Body_ShortHeader) isHeadResponse_Body_Head() {} + +func (*HeadResponse_Body_SplitInfo) isHeadResponse_Body_Head() {} + +func (*HeadResponse_Body_EcInfo) isHeadResponse_Body_Head() {} + +// Object Search request body +type SearchRequest_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Container identifier were to search + ContainerId *grpc1.ContainerID `protobuf:"bytes,1,opt,name=container_id,json=containerId,proto3" json:"container_id,omitempty"` + // Version of the Query Language used + Version uint32 `protobuf:"varint,2,opt,name=version,proto3" json:"version,omitempty"` + // List of search expressions + Filters []*SearchRequest_Body_Filter `protobuf:"bytes,3,rep,name=filters,proto3" json:"filters,omitempty"` +} + +func (x *SearchRequest_Body) Reset() { + *x = SearchRequest_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_object_grpc_service_proto_msgTypes[28] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SearchRequest_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SearchRequest_Body) ProtoMessage() {} + +func (x *SearchRequest_Body) ProtoReflect() protoreflect.Message { + mi := &file_object_grpc_service_proto_msgTypes[28] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SearchRequest_Body.ProtoReflect.Descriptor instead. +func (*SearchRequest_Body) Descriptor() ([]byte, []int) { + return file_object_grpc_service_proto_rawDescGZIP(), []int{9, 0} +} + +func (x *SearchRequest_Body) GetContainerId() *grpc1.ContainerID { + if x != nil { + return x.ContainerId + } + return nil +} + +func (x *SearchRequest_Body) GetVersion() uint32 { + if x != nil { + return x.Version + } + return 0 +} + +func (x *SearchRequest_Body) GetFilters() []*SearchRequest_Body_Filter { + if x != nil { + return x.Filters + } + return nil +} + +// Filter structure checks if the object header field or the attribute +// content matches a value. +// +// If no filters are set, search request will return all objects of the +// container, including Regular object and Tombstone +// objects. Most human users expect to get only object they can directly +// work with. In that case, `$Object:ROOT` filter should be used. +// +// By default `key` field refers to the corresponding object's `Attribute`. +// Some Object's header fields can also be accessed by adding `$Object:` +// prefix to the name. Here is the list of fields available via this prefix: +// +// - $Object:version \ +// version +// - $Object:objectID \ +// object_id +// - $Object:containerID \ +// container_id +// - $Object:ownerID \ +// owner_id +// - $Object:creationEpoch \ +// creation_epoch +// - $Object:payloadLength \ +// payload_length +// - $Object:payloadHash \ +// payload_hash +// - $Object:objectType \ +// object_type +// - $Object:homomorphicHash \ +// homomorphic_hash +// - $Object:split.parent \ +// object_id of parent +// - $Object:split.splitID \ +// 16 byte UUIDv4 used to identify the split object hierarchy parts +// +// There are some well-known filter aliases to match objects by certain +// properties: +// +// - $Object:ROOT \ +// Returns only `REGULAR` type objects that are not split or that are the +// top level root objects in a split hierarchy. This includes objects not +// present physically, like large objects split into smaller objects +// without a separate top-level root object. Objects of other types like +// Locks and Tombstones will not be shown. This filter may be +// useful for listing objects like `ls` command of some virtual file +// system. This filter is activated if the `key` exists, disregarding the +// value and matcher type. +// - $Object:PHY \ +// Returns only objects physically stored in the system. This filter is +// activated if the `key` exists, disregarding the value and matcher type. +// +// Note: using filters with a key with prefix `$Object:` and match type +// `NOT_PRESENT `is not recommended since this is not a cross-version +// approach. Behavior when processing this kind of filters is undefined. +type SearchRequest_Body_Filter struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Match type to use + MatchType MatchType `protobuf:"varint,1,opt,name=match_type,json=matchType,proto3,enum=neo.fs.v2.object.MatchType" json:"match_type,omitempty"` + // Attribute or Header fields to match + Key string `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"` + // Value to match + Value string `protobuf:"bytes,3,opt,name=value,proto3" json:"value,omitempty"` +} + +func (x *SearchRequest_Body_Filter) Reset() { + *x = SearchRequest_Body_Filter{} + if protoimpl.UnsafeEnabled { + mi := &file_object_grpc_service_proto_msgTypes[29] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SearchRequest_Body_Filter) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SearchRequest_Body_Filter) ProtoMessage() {} + +func (x *SearchRequest_Body_Filter) ProtoReflect() protoreflect.Message { + mi := &file_object_grpc_service_proto_msgTypes[29] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SearchRequest_Body_Filter.ProtoReflect.Descriptor instead. +func (*SearchRequest_Body_Filter) Descriptor() ([]byte, []int) { + return file_object_grpc_service_proto_rawDescGZIP(), []int{9, 0, 0} +} + +func (x *SearchRequest_Body_Filter) GetMatchType() MatchType { + if x != nil { + return x.MatchType + } + return MatchType_MATCH_TYPE_UNSPECIFIED +} + +func (x *SearchRequest_Body_Filter) GetKey() string { + if x != nil { + return x.Key + } + return "" +} + +func (x *SearchRequest_Body_Filter) GetValue() string { + if x != nil { + return x.Value + } + return "" +} + +// Object Search response body +type SearchResponse_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // List of `ObjectID`s that match the search query + IdList []*grpc1.ObjectID `protobuf:"bytes,1,rep,name=id_list,json=idList,proto3" json:"id_list,omitempty"` +} + +func (x *SearchResponse_Body) Reset() { + *x = SearchResponse_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_object_grpc_service_proto_msgTypes[30] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SearchResponse_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SearchResponse_Body) ProtoMessage() {} + +func (x *SearchResponse_Body) ProtoReflect() protoreflect.Message { + mi := &file_object_grpc_service_proto_msgTypes[30] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SearchResponse_Body.ProtoReflect.Descriptor instead. +func (*SearchResponse_Body) Descriptor() ([]byte, []int) { + return file_object_grpc_service_proto_rawDescGZIP(), []int{10, 0} +} + +func (x *SearchResponse_Body) GetIdList() []*grpc1.ObjectID { + if x != nil { + return x.IdList + } + return nil +} + +// Byte range of object's payload request body +type GetRangeRequest_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Address of the object containing the requested payload range + Address *grpc1.Address `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + // Requested payload range + Range *Range `protobuf:"bytes,2,opt,name=range,proto3" json:"range,omitempty"` + // If `raw` flag is set, request will work only with objects that are + // physically stored on the peer node. + Raw bool `protobuf:"varint,3,opt,name=raw,proto3" json:"raw,omitempty"` +} + +func (x *GetRangeRequest_Body) Reset() { + *x = GetRangeRequest_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_object_grpc_service_proto_msgTypes[31] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetRangeRequest_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetRangeRequest_Body) ProtoMessage() {} + +func (x *GetRangeRequest_Body) ProtoReflect() protoreflect.Message { + mi := &file_object_grpc_service_proto_msgTypes[31] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetRangeRequest_Body.ProtoReflect.Descriptor instead. +func (*GetRangeRequest_Body) Descriptor() ([]byte, []int) { + return file_object_grpc_service_proto_rawDescGZIP(), []int{12, 0} +} + +func (x *GetRangeRequest_Body) GetAddress() *grpc1.Address { + if x != nil { + return x.Address + } + return nil +} + +func (x *GetRangeRequest_Body) GetRange() *Range { + if x != nil { + return x.Range + } + return nil +} + +func (x *GetRangeRequest_Body) GetRaw() bool { + if x != nil { + return x.Raw + } + return false +} + +// Get Range response body uses streams to transfer the response. Because +// object payload considered a byte sequence, there is no need to have some +// initial preamble message. The requested byte range is sent as a series +// chunks. +type GetRangeResponse_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Requested object range or meta information about split object. + // + // Types that are assignable to RangePart: + // + // *GetRangeResponse_Body_Chunk + // *GetRangeResponse_Body_SplitInfo + // *GetRangeResponse_Body_EcInfo + RangePart isGetRangeResponse_Body_RangePart `protobuf_oneof:"range_part"` +} + +func (x *GetRangeResponse_Body) Reset() { + *x = GetRangeResponse_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_object_grpc_service_proto_msgTypes[32] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetRangeResponse_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetRangeResponse_Body) ProtoMessage() {} + +func (x *GetRangeResponse_Body) ProtoReflect() protoreflect.Message { + mi := &file_object_grpc_service_proto_msgTypes[32] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetRangeResponse_Body.ProtoReflect.Descriptor instead. +func (*GetRangeResponse_Body) Descriptor() ([]byte, []int) { + return file_object_grpc_service_proto_rawDescGZIP(), []int{13, 0} +} + +func (m *GetRangeResponse_Body) GetRangePart() isGetRangeResponse_Body_RangePart { + if m != nil { + return m.RangePart + } + return nil +} + +func (x *GetRangeResponse_Body) GetChunk() []byte { + if x, ok := x.GetRangePart().(*GetRangeResponse_Body_Chunk); ok { + return x.Chunk + } + return nil +} + +func (x *GetRangeResponse_Body) GetSplitInfo() *SplitInfo { + if x, ok := x.GetRangePart().(*GetRangeResponse_Body_SplitInfo); ok { + return x.SplitInfo + } + return nil +} + +func (x *GetRangeResponse_Body) GetEcInfo() *ECInfo { + if x, ok := x.GetRangePart().(*GetRangeResponse_Body_EcInfo); ok { + return x.EcInfo + } + return nil +} + +type isGetRangeResponse_Body_RangePart interface { + isGetRangeResponse_Body_RangePart() +} + +type GetRangeResponse_Body_Chunk struct { + // Chunked object payload's range. + Chunk []byte `protobuf:"bytes,1,opt,name=chunk,proto3,oneof"` +} + +type GetRangeResponse_Body_SplitInfo struct { + // Meta information of split hierarchy. + SplitInfo *SplitInfo `protobuf:"bytes,2,opt,name=split_info,json=splitInfo,proto3,oneof"` +} + +type GetRangeResponse_Body_EcInfo struct { + // Meta information for EC object assembly. + EcInfo *ECInfo `protobuf:"bytes,3,opt,name=ec_info,json=ecInfo,proto3,oneof"` +} + +func (*GetRangeResponse_Body_Chunk) isGetRangeResponse_Body_RangePart() {} + +func (*GetRangeResponse_Body_SplitInfo) isGetRangeResponse_Body_RangePart() {} + +func (*GetRangeResponse_Body_EcInfo) isGetRangeResponse_Body_RangePart() {} + +// Get hash of object's payload part request body. +type GetRangeHashRequest_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Address of the object that containing the requested payload range + Address *grpc1.Address `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + // List of object's payload ranges to calculate homomorphic hash + Ranges []*Range `protobuf:"bytes,2,rep,name=ranges,proto3" json:"ranges,omitempty"` + // Binary salt to XOR object's payload ranges before hash calculation + Salt []byte `protobuf:"bytes,3,opt,name=salt,proto3" json:"salt,omitempty"` + // Checksum algorithm type + Type grpc1.ChecksumType `protobuf:"varint,4,opt,name=type,proto3,enum=neo.fs.v2.refs.ChecksumType" json:"type,omitempty"` +} + +func (x *GetRangeHashRequest_Body) Reset() { + *x = GetRangeHashRequest_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_object_grpc_service_proto_msgTypes[33] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetRangeHashRequest_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetRangeHashRequest_Body) ProtoMessage() {} + +func (x *GetRangeHashRequest_Body) ProtoReflect() protoreflect.Message { + mi := &file_object_grpc_service_proto_msgTypes[33] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetRangeHashRequest_Body.ProtoReflect.Descriptor instead. +func (*GetRangeHashRequest_Body) Descriptor() ([]byte, []int) { + return file_object_grpc_service_proto_rawDescGZIP(), []int{14, 0} +} + +func (x *GetRangeHashRequest_Body) GetAddress() *grpc1.Address { + if x != nil { + return x.Address + } + return nil +} + +func (x *GetRangeHashRequest_Body) GetRanges() []*Range { + if x != nil { + return x.Ranges + } + return nil +} + +func (x *GetRangeHashRequest_Body) GetSalt() []byte { + if x != nil { + return x.Salt + } + return nil +} + +func (x *GetRangeHashRequest_Body) GetType() grpc1.ChecksumType { + if x != nil { + return x.Type + } + return grpc1.ChecksumType(0) +} + +// Get hash of object's payload part response body. +type GetRangeHashResponse_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Checksum algorithm type + Type grpc1.ChecksumType `protobuf:"varint,1,opt,name=type,proto3,enum=neo.fs.v2.refs.ChecksumType" json:"type,omitempty"` + // List of range hashes in a binary format + HashList [][]byte `protobuf:"bytes,2,rep,name=hash_list,json=hashList,proto3" json:"hash_list,omitempty"` +} + +func (x *GetRangeHashResponse_Body) Reset() { + *x = GetRangeHashResponse_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_object_grpc_service_proto_msgTypes[34] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetRangeHashResponse_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetRangeHashResponse_Body) ProtoMessage() {} + +func (x *GetRangeHashResponse_Body) ProtoReflect() protoreflect.Message { + mi := &file_object_grpc_service_proto_msgTypes[34] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetRangeHashResponse_Body.ProtoReflect.Descriptor instead. +func (*GetRangeHashResponse_Body) Descriptor() ([]byte, []int) { + return file_object_grpc_service_proto_rawDescGZIP(), []int{15, 0} +} + +func (x *GetRangeHashResponse_Body) GetType() grpc1.ChecksumType { + if x != nil { + return x.Type + } + return grpc1.ChecksumType(0) +} + +func (x *GetRangeHashResponse_Body) GetHashList() [][]byte { + if x != nil { + return x.HashList + } + return nil +} + +// PUT Single request body +type PutSingleRequest_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Prepared object with payload. + Object *Object `protobuf:"bytes,1,opt,name=object,proto3" json:"object,omitempty"` + // Number of copies of the object to store within the RPC call. By default, + // object is processed according to the container's placement policy. + // Every number is treated as a minimal number of + // nodes in a corresponding placement vector that must store an object + // to complete the request successfully. The length MUST equal the placement + // vectors number, otherwise request is considered malformed. + CopiesNumber []uint32 `protobuf:"varint,2,rep,packed,name=copies_number,json=copiesNumber,proto3" json:"copies_number,omitempty"` +} + +func (x *PutSingleRequest_Body) Reset() { + *x = PutSingleRequest_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_object_grpc_service_proto_msgTypes[35] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PutSingleRequest_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PutSingleRequest_Body) ProtoMessage() {} + +func (x *PutSingleRequest_Body) ProtoReflect() protoreflect.Message { + mi := &file_object_grpc_service_proto_msgTypes[35] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PutSingleRequest_Body.ProtoReflect.Descriptor instead. +func (*PutSingleRequest_Body) Descriptor() ([]byte, []int) { + return file_object_grpc_service_proto_rawDescGZIP(), []int{16, 0} +} + +func (x *PutSingleRequest_Body) GetObject() *Object { + if x != nil { + return x.Object + } + return nil +} + +func (x *PutSingleRequest_Body) GetCopiesNumber() []uint32 { + if x != nil { + return x.CopiesNumber + } + return nil +} + +// PUT Single Object response body +type PutSingleResponse_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *PutSingleResponse_Body) Reset() { + *x = PutSingleResponse_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_object_grpc_service_proto_msgTypes[36] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PutSingleResponse_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PutSingleResponse_Body) ProtoMessage() {} + +func (x *PutSingleResponse_Body) ProtoReflect() protoreflect.Message { + mi := &file_object_grpc_service_proto_msgTypes[36] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PutSingleResponse_Body.ProtoReflect.Descriptor instead. +func (*PutSingleResponse_Body) Descriptor() ([]byte, []int) { + return file_object_grpc_service_proto_rawDescGZIP(), []int{17, 0} +} + +var File_object_grpc_service_proto protoreflect.FileDescriptor + +var file_object_grpc_service_proto_rawDesc = []byte{ + 0x0a, 0x19, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x73, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x10, 0x6e, 0x65, 0x6f, + 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x1a, 0x17, 0x6f, + 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x15, 0x72, 0x65, 0x66, 0x73, 0x2f, 0x67, 0x72, 0x70, + 0x63, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x18, 0x73, + 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x74, 0x79, 0x70, 0x65, + 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xaa, 0x02, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, + 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x45, 0x0a, + 0x0b, 0x6d, 0x65, 0x74, 0x61, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, + 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, + 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0a, 0x6d, 0x65, 0x74, 0x61, 0x48, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x12, 0x51, 0x0a, 0x0d, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x5f, 0x68, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x6e, 0x65, + 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0c, 0x76, 0x65, 0x72, 0x69, 0x66, + 0x79, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x1a, 0x4b, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, + 0x31, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x17, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x65, 0x66, + 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x72, 0x61, 0x77, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x03, 0x72, 0x61, 0x77, 0x22, 0xee, 0x04, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, + 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x46, 0x0a, 0x0b, + 0x6d, 0x65, 0x74, 0x61, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x25, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, + 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0a, 0x6d, 0x65, 0x74, 0x61, 0x48, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x12, 0x52, 0x0a, 0x0d, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x5f, 0x68, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x6e, 0x65, + 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0c, 0x76, 0x65, 0x72, 0x69, + 0x66, 0x79, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x1a, 0x8a, 0x03, 0x0a, 0x04, 0x42, 0x6f, 0x64, + 0x79, 0x12, 0x3d, 0x0a, 0x04, 0x69, 0x6e, 0x69, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x27, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, + 0x63, 0x74, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, + 0x6f, 0x64, 0x79, 0x2e, 0x49, 0x6e, 0x69, 0x74, 0x48, 0x00, 0x52, 0x04, 0x69, 0x6e, 0x69, 0x74, + 0x12, 0x16, 0x0a, 0x05, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x48, + 0x00, 0x52, 0x05, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x12, 0x3c, 0x0a, 0x0a, 0x73, 0x70, 0x6c, 0x69, + 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x6e, + 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, + 0x53, 0x70, 0x6c, 0x69, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x48, 0x00, 0x52, 0x09, 0x73, 0x70, 0x6c, + 0x69, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x33, 0x0a, 0x07, 0x65, 0x63, 0x5f, 0x69, 0x6e, 0x66, + 0x6f, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, + 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x45, 0x43, 0x49, 0x6e, 0x66, + 0x6f, 0x48, 0x00, 0x52, 0x06, 0x65, 0x63, 0x49, 0x6e, 0x66, 0x6f, 0x1a, 0xa8, 0x01, 0x0a, 0x04, + 0x49, 0x6e, 0x69, 0x74, 0x12, 0x35, 0x0a, 0x09, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, + 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x65, 0x66, 0x73, 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, + 0x44, 0x52, 0x08, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x64, 0x12, 0x37, 0x0a, 0x09, 0x73, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, + 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x65, 0x66, 0x73, 0x2e, + 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x12, 0x30, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, + 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x06, + 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x42, 0x0d, 0x0a, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, + 0x5f, 0x70, 0x61, 0x72, 0x74, 0x22, 0x9b, 0x04, 0x0a, 0x0a, 0x50, 0x75, 0x74, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, + 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x50, 0x75, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x45, 0x0a, 0x0b, 0x6d, + 0x65, 0x74, 0x61, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x24, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, + 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0a, 0x6d, 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, + 0x65, 0x72, 0x12, 0x51, 0x0a, 0x0d, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x5f, 0x68, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, + 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0c, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x48, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x1a, 0xbb, 0x02, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x3c, + 0x0a, 0x04, 0x69, 0x6e, 0x69, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x6e, + 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, + 0x50, 0x75, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x2e, + 0x49, 0x6e, 0x69, 0x74, 0x48, 0x00, 0x52, 0x04, 0x69, 0x6e, 0x69, 0x74, 0x12, 0x16, 0x0a, 0x05, + 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x05, 0x63, + 0x68, 0x75, 0x6e, 0x6b, 0x1a, 0xcd, 0x01, 0x0a, 0x04, 0x49, 0x6e, 0x69, 0x74, 0x12, 0x35, 0x0a, + 0x09, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x18, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x65, 0x66, + 0x73, 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x44, 0x52, 0x08, 0x6f, 0x62, 0x6a, 0x65, + 0x63, 0x74, 0x49, 0x64, 0x12, 0x37, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, + 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x65, 0x66, 0x73, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x30, 0x0a, + 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, + 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, + 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, + 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x70, 0x69, 0x65, 0x73, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, + 0x18, 0x04, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x0c, 0x63, 0x6f, 0x70, 0x69, 0x65, 0x73, 0x4e, 0x75, + 0x6d, 0x62, 0x65, 0x72, 0x42, 0x0d, 0x0a, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x70, + 0x61, 0x72, 0x74, 0x22, 0xa0, 0x02, 0x0a, 0x0b, 0x50, 0x75, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x22, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, + 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x50, 0x75, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x46, 0x0a, 0x0b, 0x6d, + 0x65, 0x74, 0x61, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x25, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x74, + 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0a, 0x6d, 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x12, 0x52, 0x0a, 0x0d, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x5f, 0x68, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x6e, 0x65, 0x6f, + 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0c, 0x76, 0x65, 0x72, 0x69, 0x66, + 0x79, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x1a, 0x3d, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, + 0x35, 0x0a, 0x09, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x72, + 0x65, 0x66, 0x73, 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x44, 0x52, 0x08, 0x6f, 0x62, + 0x6a, 0x65, 0x63, 0x74, 0x49, 0x64, 0x22, 0x9e, 0x02, 0x0a, 0x0d, 0x44, 0x65, 0x6c, 0x65, 0x74, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x38, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, + 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, + 0x64, 0x79, 0x12, 0x45, 0x0a, 0x0b, 0x6d, 0x65, 0x74, 0x61, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, + 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0a, 0x6d, + 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x51, 0x0a, 0x0d, 0x76, 0x65, 0x72, + 0x69, 0x66, 0x79, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x2c, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x65, 0x72, 0x69, + 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0c, + 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x1a, 0x39, 0x0a, 0x04, + 0x42, 0x6f, 0x64, 0x79, 0x12, 0x31, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, + 0x32, 0x2e, 0x72, 0x65, 0x66, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x07, + 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0xa6, 0x02, 0x0a, 0x0e, 0x44, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x04, 0x62, 0x6f, + 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, + 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x44, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, + 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x46, 0x0a, 0x0b, 0x6d, 0x65, 0x74, 0x61, 0x5f, 0x68, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x6e, 0x65, 0x6f, + 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x52, 0x0a, 0x6d, 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x52, 0x0a, + 0x0d, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, + 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x52, 0x0c, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x48, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x1a, 0x3d, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x35, 0x0a, 0x09, 0x74, 0x6f, 0x6d, + 0x62, 0x73, 0x74, 0x6f, 0x6e, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6e, + 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x65, 0x66, 0x73, 0x2e, 0x41, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x09, 0x74, 0x6f, 0x6d, 0x62, 0x73, 0x74, 0x6f, 0x6e, 0x65, + 0x22, 0xc9, 0x02, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x36, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, + 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, + 0x74, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, + 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x45, 0x0a, 0x0b, 0x6d, 0x65, 0x74, 0x61, + 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, + 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x52, 0x0a, 0x6d, 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, + 0x51, 0x0a, 0x0d, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, + 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x52, 0x0c, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x48, 0x65, 0x61, 0x64, + 0x65, 0x72, 0x1a, 0x68, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x31, 0x0a, 0x07, 0x61, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6e, 0x65, + 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x65, 0x66, 0x73, 0x2e, 0x41, 0x64, 0x64, + 0x72, 0x65, 0x73, 0x73, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1b, 0x0a, + 0x09, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x08, 0x6d, 0x61, 0x69, 0x6e, 0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x72, 0x61, + 0x77, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x72, 0x61, 0x77, 0x22, 0x80, 0x01, 0x0a, + 0x13, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x57, 0x69, 0x74, 0x68, 0x53, 0x69, 0x67, 0x6e, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x12, 0x30, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, + 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x06, + 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x37, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, + 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x65, 0x66, 0x73, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, + 0xec, 0x03, 0x0a, 0x0c, 0x48, 0x65, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x37, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, + 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, + 0x74, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, + 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x46, 0x0a, 0x0b, 0x6d, 0x65, 0x74, + 0x61, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, + 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x48, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0a, 0x6d, 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x12, 0x52, 0x0a, 0x0d, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x5f, 0x68, 0x65, 0x61, 0x64, + 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, + 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0c, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x48, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x1a, 0x86, 0x02, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x3f, + 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, + 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, + 0x74, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x57, 0x69, 0x74, 0x68, 0x53, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x48, 0x00, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, + 0x42, 0x0a, 0x0c, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, + 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x53, 0x68, 0x6f, 0x72, 0x74, 0x48, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x48, 0x00, 0x52, 0x0b, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x48, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x12, 0x3c, 0x0a, 0x0a, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x5f, 0x69, 0x6e, 0x66, + 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, + 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x53, 0x70, 0x6c, 0x69, 0x74, + 0x49, 0x6e, 0x66, 0x6f, 0x48, 0x00, 0x52, 0x09, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x49, 0x6e, 0x66, + 0x6f, 0x12, 0x33, 0x0a, 0x07, 0x65, 0x63, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, + 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x45, 0x43, 0x49, 0x6e, 0x66, 0x6f, 0x48, 0x00, 0x52, 0x06, + 0x65, 0x63, 0x49, 0x6e, 0x66, 0x6f, 0x42, 0x06, 0x0a, 0x04, 0x68, 0x65, 0x61, 0x64, 0x22, 0xfb, + 0x03, 0x0a, 0x0d, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x38, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, + 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, + 0x74, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, + 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x45, 0x0a, 0x0b, 0x6d, 0x65, + 0x74, 0x61, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x24, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x48, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0a, 0x6d, 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x12, 0x51, 0x0a, 0x0d, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x5f, 0x68, 0x65, 0x61, 0x64, + 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, + 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0c, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x48, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x1a, 0x95, 0x02, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x3e, 0x0a, + 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, + 0x72, 0x65, 0x66, 0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x44, + 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x18, 0x0a, + 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, + 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x45, 0x0a, 0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, + 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, + 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x53, 0x65, 0x61, 0x72, + 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x2e, 0x46, + 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x1a, 0x6c, + 0x0a, 0x06, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x3a, 0x0a, 0x0a, 0x6d, 0x61, 0x74, 0x63, + 0x68, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x6e, + 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, + 0x4d, 0x61, 0x74, 0x63, 0x68, 0x54, 0x79, 0x70, 0x65, 0x52, 0x09, 0x6d, 0x61, 0x74, 0x63, 0x68, + 0x54, 0x79, 0x70, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xa2, 0x02, 0x0a, + 0x0e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x39, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, + 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, + 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, + 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x46, 0x0a, 0x0b, 0x6d, 0x65, + 0x74, 0x61, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x25, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, + 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0a, 0x6d, 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, + 0x65, 0x72, 0x12, 0x52, 0x0a, 0x0d, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x5f, 0x68, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, + 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0c, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, + 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x1a, 0x39, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x31, + 0x0a, 0x07, 0x69, 0x64, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x18, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x65, 0x66, 0x73, + 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x44, 0x52, 0x06, 0x69, 0x64, 0x4c, 0x69, 0x73, + 0x74, 0x22, 0x37, 0x0a, 0x05, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x66, + 0x66, 0x73, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x6f, 0x66, 0x66, 0x73, + 0x65, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x04, 0x52, 0x06, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0xe3, 0x02, 0x0a, 0x0f, 0x47, + 0x65, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3a, + 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x6e, + 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, + 0x47, 0x65, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, + 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x45, 0x0a, 0x0b, 0x6d, 0x65, + 0x74, 0x61, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x24, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x48, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0a, 0x6d, 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x12, 0x51, 0x0a, 0x0d, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x5f, 0x68, 0x65, 0x61, 0x64, + 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, + 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0c, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x48, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x1a, 0x7a, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x31, 0x0a, 0x07, + 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, + 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x65, 0x66, 0x73, 0x2e, 0x41, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, + 0x2d, 0x0a, 0x05, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, + 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, + 0x74, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x05, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x10, + 0x0a, 0x03, 0x72, 0x61, 0x77, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x72, 0x61, 0x77, + 0x22, 0x8d, 0x03, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, + 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, + 0x64, 0x79, 0x12, 0x46, 0x0a, 0x0b, 0x6d, 0x65, 0x74, 0x61, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, + 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0a, + 0x6d, 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x52, 0x0a, 0x0d, 0x76, 0x65, + 0x72, 0x69, 0x66, 0x79, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x2d, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x56, 0x65, + 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x52, 0x0c, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x1a, 0x9f, + 0x01, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x16, 0x0a, 0x05, 0x63, 0x68, 0x75, 0x6e, 0x6b, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x05, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x12, + 0x3c, 0x0a, 0x0a, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, + 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x53, 0x70, 0x6c, 0x69, 0x74, 0x49, 0x6e, 0x66, 0x6f, + 0x48, 0x00, 0x52, 0x09, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x33, 0x0a, + 0x07, 0x65, 0x63, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, + 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, + 0x74, 0x2e, 0x45, 0x43, 0x49, 0x6e, 0x66, 0x6f, 0x48, 0x00, 0x52, 0x06, 0x65, 0x63, 0x49, 0x6e, + 0x66, 0x6f, 0x42, 0x0c, 0x0a, 0x0a, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x5f, 0x70, 0x61, 0x72, 0x74, + 0x22, 0xa2, 0x03, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x48, 0x61, 0x73, + 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3e, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, + 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x61, 0x6e, + 0x67, 0x65, 0x48, 0x61, 0x73, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, + 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x45, 0x0a, 0x0b, 0x6d, 0x65, 0x74, 0x61, + 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, + 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x52, 0x0a, 0x6d, 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, + 0x51, 0x0a, 0x0d, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, + 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x52, 0x0c, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x48, 0x65, 0x61, 0x64, + 0x65, 0x72, 0x1a, 0xb0, 0x01, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x31, 0x0a, 0x07, 0x61, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6e, + 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x65, 0x66, 0x73, 0x2e, 0x41, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x2f, + 0x0a, 0x06, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, + 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, + 0x74, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x06, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, + 0x12, 0x0a, 0x04, 0x73, 0x61, 0x6c, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x73, + 0x61, 0x6c, 0x74, 0x12, 0x30, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x0e, 0x32, 0x1c, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x65, + 0x66, 0x73, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0x54, 0x79, 0x70, 0x65, 0x52, + 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0xca, 0x02, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x52, 0x61, 0x6e, + 0x67, 0x65, 0x48, 0x61, 0x73, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, + 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x6e, + 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, + 0x47, 0x65, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x48, 0x61, 0x73, 0x68, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, + 0x46, 0x0a, 0x0b, 0x6d, 0x65, 0x74, 0x61, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, + 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x4d, 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0a, 0x6d, 0x65, 0x74, + 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x52, 0x0a, 0x0d, 0x76, 0x65, 0x72, 0x69, 0x66, + 0x79, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, + 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x56, 0x65, 0x72, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0c, 0x76, + 0x65, 0x72, 0x69, 0x66, 0x79, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x1a, 0x55, 0x0a, 0x04, 0x42, + 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0e, 0x32, 0x1c, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x65, + 0x66, 0x73, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0x54, 0x79, 0x70, 0x65, 0x52, + 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x68, 0x61, 0x73, 0x68, 0x5f, 0x6c, 0x69, + 0x73, 0x74, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x08, 0x68, 0x61, 0x73, 0x68, 0x4c, 0x69, + 0x73, 0x74, 0x22, 0xc8, 0x02, 0x0a, 0x10, 0x50, 0x75, 0x74, 0x53, 0x69, 0x6e, 0x67, 0x6c, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3b, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, + 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x50, 0x75, 0x74, 0x53, 0x69, 0x6e, 0x67, + 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, + 0x62, 0x6f, 0x64, 0x79, 0x12, 0x45, 0x0a, 0x0b, 0x6d, 0x65, 0x74, 0x61, 0x5f, 0x68, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, + 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, + 0x0a, 0x6d, 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x51, 0x0a, 0x0d, 0x76, + 0x65, 0x72, 0x69, 0x66, 0x79, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, + 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x65, + 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x52, 0x0c, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x1a, 0x5d, + 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x06, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, + 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, + 0x52, 0x06, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x70, 0x69, + 0x65, 0x73, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0d, 0x52, + 0x0c, 0x63, 0x6f, 0x70, 0x69, 0x65, 0x73, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0xf5, 0x01, + 0x0a, 0x11, 0x50, 0x75, 0x74, 0x53, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x3c, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x28, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, + 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x50, 0x75, 0x74, 0x53, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, + 0x79, 0x12, 0x46, 0x0a, 0x0b, 0x6d, 0x65, 0x74, 0x61, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, + 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0a, 0x6d, + 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x52, 0x0a, 0x0d, 0x76, 0x65, 0x72, + 0x69, 0x66, 0x79, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x2d, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x56, 0x65, 0x72, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, + 0x0c, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x1a, 0x06, 0x0a, + 0x04, 0x42, 0x6f, 0x64, 0x79, 0x32, 0x88, 0x05, 0x0a, 0x0d, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x44, 0x0a, 0x03, 0x47, 0x65, 0x74, 0x12, 0x1c, + 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, + 0x74, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x6e, + 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, + 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x44, 0x0a, + 0x03, 0x50, 0x75, 0x74, 0x12, 0x1c, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, + 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x50, 0x75, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, + 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x50, 0x75, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x28, 0x01, 0x12, 0x4b, 0x0a, 0x06, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x1f, 0x2e, + 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, + 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, + 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, + 0x74, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x45, 0x0a, 0x04, 0x48, 0x65, 0x61, 0x64, 0x12, 0x1d, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, + 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x48, 0x65, 0x61, 0x64, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, + 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4d, 0x0a, 0x06, 0x53, 0x65, 0x61, 0x72, 0x63, + 0x68, 0x12, 0x1f, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, + 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, + 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x53, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x52, 0x61, 0x6e, + 0x67, 0x65, 0x12, 0x21, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, + 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, + 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x61, 0x6e, 0x67, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x5d, 0x0a, 0x0c, 0x47, + 0x65, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x48, 0x61, 0x73, 0x68, 0x12, 0x25, 0x2e, 0x6e, 0x65, + 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x47, + 0x65, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x48, 0x61, 0x73, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, + 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x48, 0x61, + 0x73, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x09, 0x50, 0x75, + 0x74, 0x53, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x12, 0x22, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, + 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x50, 0x75, 0x74, 0x53, 0x69, + 0x6e, 0x67, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x6e, 0x65, + 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x50, + 0x75, 0x74, 0x53, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x42, 0x61, 0x5a, 0x42, 0x67, 0x69, 0x74, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2e, + 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, 0x75, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x4c, 0x61, + 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2d, 0x61, 0x70, 0x69, 0x2d, 0x67, 0x6f, + 0x2f, 0x76, 0x32, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x3b, + 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0xaa, 0x02, 0x1a, 0x4e, 0x65, 0x6f, 0x2e, 0x46, 0x69, 0x6c, + 0x65, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x41, 0x50, 0x49, 0x2e, 0x4f, 0x62, 0x6a, + 0x65, 0x63, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_object_grpc_service_proto_rawDescOnce sync.Once + file_object_grpc_service_proto_rawDescData = file_object_grpc_service_proto_rawDesc +) + +func file_object_grpc_service_proto_rawDescGZIP() []byte { + file_object_grpc_service_proto_rawDescOnce.Do(func() { + file_object_grpc_service_proto_rawDescData = protoimpl.X.CompressGZIP(file_object_grpc_service_proto_rawDescData) + }) + return file_object_grpc_service_proto_rawDescData +} + +var file_object_grpc_service_proto_msgTypes = make([]protoimpl.MessageInfo, 37) +var file_object_grpc_service_proto_goTypes = []interface{}{ + (*GetRequest)(nil), // 0: neo.fs.v2.object.GetRequest + (*GetResponse)(nil), // 1: neo.fs.v2.object.GetResponse + (*PutRequest)(nil), // 2: neo.fs.v2.object.PutRequest + (*PutResponse)(nil), // 3: neo.fs.v2.object.PutResponse + (*DeleteRequest)(nil), // 4: neo.fs.v2.object.DeleteRequest + (*DeleteResponse)(nil), // 5: neo.fs.v2.object.DeleteResponse + (*HeadRequest)(nil), // 6: neo.fs.v2.object.HeadRequest + (*HeaderWithSignature)(nil), // 7: neo.fs.v2.object.HeaderWithSignature + (*HeadResponse)(nil), // 8: neo.fs.v2.object.HeadResponse + (*SearchRequest)(nil), // 9: neo.fs.v2.object.SearchRequest + (*SearchResponse)(nil), // 10: neo.fs.v2.object.SearchResponse + (*Range)(nil), // 11: neo.fs.v2.object.Range + (*GetRangeRequest)(nil), // 12: neo.fs.v2.object.GetRangeRequest + (*GetRangeResponse)(nil), // 13: neo.fs.v2.object.GetRangeResponse + (*GetRangeHashRequest)(nil), // 14: neo.fs.v2.object.GetRangeHashRequest + (*GetRangeHashResponse)(nil), // 15: neo.fs.v2.object.GetRangeHashResponse + (*PutSingleRequest)(nil), // 16: neo.fs.v2.object.PutSingleRequest + (*PutSingleResponse)(nil), // 17: neo.fs.v2.object.PutSingleResponse + (*GetRequest_Body)(nil), // 18: neo.fs.v2.object.GetRequest.Body + (*GetResponse_Body)(nil), // 19: neo.fs.v2.object.GetResponse.Body + (*GetResponse_Body_Init)(nil), // 20: neo.fs.v2.object.GetResponse.Body.Init + (*PutRequest_Body)(nil), // 21: neo.fs.v2.object.PutRequest.Body + (*PutRequest_Body_Init)(nil), // 22: neo.fs.v2.object.PutRequest.Body.Init + (*PutResponse_Body)(nil), // 23: neo.fs.v2.object.PutResponse.Body + (*DeleteRequest_Body)(nil), // 24: neo.fs.v2.object.DeleteRequest.Body + (*DeleteResponse_Body)(nil), // 25: neo.fs.v2.object.DeleteResponse.Body + (*HeadRequest_Body)(nil), // 26: neo.fs.v2.object.HeadRequest.Body + (*HeadResponse_Body)(nil), // 27: neo.fs.v2.object.HeadResponse.Body + (*SearchRequest_Body)(nil), // 28: neo.fs.v2.object.SearchRequest.Body + (*SearchRequest_Body_Filter)(nil), // 29: neo.fs.v2.object.SearchRequest.Body.Filter + (*SearchResponse_Body)(nil), // 30: neo.fs.v2.object.SearchResponse.Body + (*GetRangeRequest_Body)(nil), // 31: neo.fs.v2.object.GetRangeRequest.Body + (*GetRangeResponse_Body)(nil), // 32: neo.fs.v2.object.GetRangeResponse.Body + (*GetRangeHashRequest_Body)(nil), // 33: neo.fs.v2.object.GetRangeHashRequest.Body + (*GetRangeHashResponse_Body)(nil), // 34: neo.fs.v2.object.GetRangeHashResponse.Body + (*PutSingleRequest_Body)(nil), // 35: neo.fs.v2.object.PutSingleRequest.Body + (*PutSingleResponse_Body)(nil), // 36: neo.fs.v2.object.PutSingleResponse.Body + (*grpc.RequestMetaHeader)(nil), // 37: neo.fs.v2.session.RequestMetaHeader + (*grpc.RequestVerificationHeader)(nil), // 38: neo.fs.v2.session.RequestVerificationHeader + (*grpc.ResponseMetaHeader)(nil), // 39: neo.fs.v2.session.ResponseMetaHeader + (*grpc.ResponseVerificationHeader)(nil), // 40: neo.fs.v2.session.ResponseVerificationHeader + (*Header)(nil), // 41: neo.fs.v2.object.Header + (*grpc1.Signature)(nil), // 42: neo.fs.v2.refs.Signature + (*grpc1.Address)(nil), // 43: neo.fs.v2.refs.Address + (*SplitInfo)(nil), // 44: neo.fs.v2.object.SplitInfo + (*ECInfo)(nil), // 45: neo.fs.v2.object.ECInfo + (*grpc1.ObjectID)(nil), // 46: neo.fs.v2.refs.ObjectID + (*ShortHeader)(nil), // 47: neo.fs.v2.object.ShortHeader + (*grpc1.ContainerID)(nil), // 48: neo.fs.v2.refs.ContainerID + (MatchType)(0), // 49: neo.fs.v2.object.MatchType + (grpc1.ChecksumType)(0), // 50: neo.fs.v2.refs.ChecksumType + (*Object)(nil), // 51: neo.fs.v2.object.Object +} +var file_object_grpc_service_proto_depIdxs = []int32{ + 18, // 0: neo.fs.v2.object.GetRequest.body:type_name -> neo.fs.v2.object.GetRequest.Body + 37, // 1: neo.fs.v2.object.GetRequest.meta_header:type_name -> neo.fs.v2.session.RequestMetaHeader + 38, // 2: neo.fs.v2.object.GetRequest.verify_header:type_name -> neo.fs.v2.session.RequestVerificationHeader + 19, // 3: neo.fs.v2.object.GetResponse.body:type_name -> neo.fs.v2.object.GetResponse.Body + 39, // 4: neo.fs.v2.object.GetResponse.meta_header:type_name -> neo.fs.v2.session.ResponseMetaHeader + 40, // 5: neo.fs.v2.object.GetResponse.verify_header:type_name -> neo.fs.v2.session.ResponseVerificationHeader + 21, // 6: neo.fs.v2.object.PutRequest.body:type_name -> neo.fs.v2.object.PutRequest.Body + 37, // 7: neo.fs.v2.object.PutRequest.meta_header:type_name -> neo.fs.v2.session.RequestMetaHeader + 38, // 8: neo.fs.v2.object.PutRequest.verify_header:type_name -> neo.fs.v2.session.RequestVerificationHeader + 23, // 9: neo.fs.v2.object.PutResponse.body:type_name -> neo.fs.v2.object.PutResponse.Body + 39, // 10: neo.fs.v2.object.PutResponse.meta_header:type_name -> neo.fs.v2.session.ResponseMetaHeader + 40, // 11: neo.fs.v2.object.PutResponse.verify_header:type_name -> neo.fs.v2.session.ResponseVerificationHeader + 24, // 12: neo.fs.v2.object.DeleteRequest.body:type_name -> neo.fs.v2.object.DeleteRequest.Body + 37, // 13: neo.fs.v2.object.DeleteRequest.meta_header:type_name -> neo.fs.v2.session.RequestMetaHeader + 38, // 14: neo.fs.v2.object.DeleteRequest.verify_header:type_name -> neo.fs.v2.session.RequestVerificationHeader + 25, // 15: neo.fs.v2.object.DeleteResponse.body:type_name -> neo.fs.v2.object.DeleteResponse.Body + 39, // 16: neo.fs.v2.object.DeleteResponse.meta_header:type_name -> neo.fs.v2.session.ResponseMetaHeader + 40, // 17: neo.fs.v2.object.DeleteResponse.verify_header:type_name -> neo.fs.v2.session.ResponseVerificationHeader + 26, // 18: neo.fs.v2.object.HeadRequest.body:type_name -> neo.fs.v2.object.HeadRequest.Body + 37, // 19: neo.fs.v2.object.HeadRequest.meta_header:type_name -> neo.fs.v2.session.RequestMetaHeader + 38, // 20: neo.fs.v2.object.HeadRequest.verify_header:type_name -> neo.fs.v2.session.RequestVerificationHeader + 41, // 21: neo.fs.v2.object.HeaderWithSignature.header:type_name -> neo.fs.v2.object.Header + 42, // 22: neo.fs.v2.object.HeaderWithSignature.signature:type_name -> neo.fs.v2.refs.Signature + 27, // 23: neo.fs.v2.object.HeadResponse.body:type_name -> neo.fs.v2.object.HeadResponse.Body + 39, // 24: neo.fs.v2.object.HeadResponse.meta_header:type_name -> neo.fs.v2.session.ResponseMetaHeader + 40, // 25: neo.fs.v2.object.HeadResponse.verify_header:type_name -> neo.fs.v2.session.ResponseVerificationHeader + 28, // 26: neo.fs.v2.object.SearchRequest.body:type_name -> neo.fs.v2.object.SearchRequest.Body + 37, // 27: neo.fs.v2.object.SearchRequest.meta_header:type_name -> neo.fs.v2.session.RequestMetaHeader + 38, // 28: neo.fs.v2.object.SearchRequest.verify_header:type_name -> neo.fs.v2.session.RequestVerificationHeader + 30, // 29: neo.fs.v2.object.SearchResponse.body:type_name -> neo.fs.v2.object.SearchResponse.Body + 39, // 30: neo.fs.v2.object.SearchResponse.meta_header:type_name -> neo.fs.v2.session.ResponseMetaHeader + 40, // 31: neo.fs.v2.object.SearchResponse.verify_header:type_name -> neo.fs.v2.session.ResponseVerificationHeader + 31, // 32: neo.fs.v2.object.GetRangeRequest.body:type_name -> neo.fs.v2.object.GetRangeRequest.Body + 37, // 33: neo.fs.v2.object.GetRangeRequest.meta_header:type_name -> neo.fs.v2.session.RequestMetaHeader + 38, // 34: neo.fs.v2.object.GetRangeRequest.verify_header:type_name -> neo.fs.v2.session.RequestVerificationHeader + 32, // 35: neo.fs.v2.object.GetRangeResponse.body:type_name -> neo.fs.v2.object.GetRangeResponse.Body + 39, // 36: neo.fs.v2.object.GetRangeResponse.meta_header:type_name -> neo.fs.v2.session.ResponseMetaHeader + 40, // 37: neo.fs.v2.object.GetRangeResponse.verify_header:type_name -> neo.fs.v2.session.ResponseVerificationHeader + 33, // 38: neo.fs.v2.object.GetRangeHashRequest.body:type_name -> neo.fs.v2.object.GetRangeHashRequest.Body + 37, // 39: neo.fs.v2.object.GetRangeHashRequest.meta_header:type_name -> neo.fs.v2.session.RequestMetaHeader + 38, // 40: neo.fs.v2.object.GetRangeHashRequest.verify_header:type_name -> neo.fs.v2.session.RequestVerificationHeader + 34, // 41: neo.fs.v2.object.GetRangeHashResponse.body:type_name -> neo.fs.v2.object.GetRangeHashResponse.Body + 39, // 42: neo.fs.v2.object.GetRangeHashResponse.meta_header:type_name -> neo.fs.v2.session.ResponseMetaHeader + 40, // 43: neo.fs.v2.object.GetRangeHashResponse.verify_header:type_name -> neo.fs.v2.session.ResponseVerificationHeader + 35, // 44: neo.fs.v2.object.PutSingleRequest.body:type_name -> neo.fs.v2.object.PutSingleRequest.Body + 37, // 45: neo.fs.v2.object.PutSingleRequest.meta_header:type_name -> neo.fs.v2.session.RequestMetaHeader + 38, // 46: neo.fs.v2.object.PutSingleRequest.verify_header:type_name -> neo.fs.v2.session.RequestVerificationHeader + 36, // 47: neo.fs.v2.object.PutSingleResponse.body:type_name -> neo.fs.v2.object.PutSingleResponse.Body + 39, // 48: neo.fs.v2.object.PutSingleResponse.meta_header:type_name -> neo.fs.v2.session.ResponseMetaHeader + 40, // 49: neo.fs.v2.object.PutSingleResponse.verify_header:type_name -> neo.fs.v2.session.ResponseVerificationHeader + 43, // 50: neo.fs.v2.object.GetRequest.Body.address:type_name -> neo.fs.v2.refs.Address + 20, // 51: neo.fs.v2.object.GetResponse.Body.init:type_name -> neo.fs.v2.object.GetResponse.Body.Init + 44, // 52: neo.fs.v2.object.GetResponse.Body.split_info:type_name -> neo.fs.v2.object.SplitInfo + 45, // 53: neo.fs.v2.object.GetResponse.Body.ec_info:type_name -> neo.fs.v2.object.ECInfo + 46, // 54: neo.fs.v2.object.GetResponse.Body.Init.object_id:type_name -> neo.fs.v2.refs.ObjectID + 42, // 55: neo.fs.v2.object.GetResponse.Body.Init.signature:type_name -> neo.fs.v2.refs.Signature + 41, // 56: neo.fs.v2.object.GetResponse.Body.Init.header:type_name -> neo.fs.v2.object.Header + 22, // 57: neo.fs.v2.object.PutRequest.Body.init:type_name -> neo.fs.v2.object.PutRequest.Body.Init + 46, // 58: neo.fs.v2.object.PutRequest.Body.Init.object_id:type_name -> neo.fs.v2.refs.ObjectID + 42, // 59: neo.fs.v2.object.PutRequest.Body.Init.signature:type_name -> neo.fs.v2.refs.Signature + 41, // 60: neo.fs.v2.object.PutRequest.Body.Init.header:type_name -> neo.fs.v2.object.Header + 46, // 61: neo.fs.v2.object.PutResponse.Body.object_id:type_name -> neo.fs.v2.refs.ObjectID + 43, // 62: neo.fs.v2.object.DeleteRequest.Body.address:type_name -> neo.fs.v2.refs.Address + 43, // 63: neo.fs.v2.object.DeleteResponse.Body.tombstone:type_name -> neo.fs.v2.refs.Address + 43, // 64: neo.fs.v2.object.HeadRequest.Body.address:type_name -> neo.fs.v2.refs.Address + 7, // 65: neo.fs.v2.object.HeadResponse.Body.header:type_name -> neo.fs.v2.object.HeaderWithSignature + 47, // 66: neo.fs.v2.object.HeadResponse.Body.short_header:type_name -> neo.fs.v2.object.ShortHeader + 44, // 67: neo.fs.v2.object.HeadResponse.Body.split_info:type_name -> neo.fs.v2.object.SplitInfo + 45, // 68: neo.fs.v2.object.HeadResponse.Body.ec_info:type_name -> neo.fs.v2.object.ECInfo + 48, // 69: neo.fs.v2.object.SearchRequest.Body.container_id:type_name -> neo.fs.v2.refs.ContainerID + 29, // 70: neo.fs.v2.object.SearchRequest.Body.filters:type_name -> neo.fs.v2.object.SearchRequest.Body.Filter + 49, // 71: neo.fs.v2.object.SearchRequest.Body.Filter.match_type:type_name -> neo.fs.v2.object.MatchType + 46, // 72: neo.fs.v2.object.SearchResponse.Body.id_list:type_name -> neo.fs.v2.refs.ObjectID + 43, // 73: neo.fs.v2.object.GetRangeRequest.Body.address:type_name -> neo.fs.v2.refs.Address + 11, // 74: neo.fs.v2.object.GetRangeRequest.Body.range:type_name -> neo.fs.v2.object.Range + 44, // 75: neo.fs.v2.object.GetRangeResponse.Body.split_info:type_name -> neo.fs.v2.object.SplitInfo + 45, // 76: neo.fs.v2.object.GetRangeResponse.Body.ec_info:type_name -> neo.fs.v2.object.ECInfo + 43, // 77: neo.fs.v2.object.GetRangeHashRequest.Body.address:type_name -> neo.fs.v2.refs.Address + 11, // 78: neo.fs.v2.object.GetRangeHashRequest.Body.ranges:type_name -> neo.fs.v2.object.Range + 50, // 79: neo.fs.v2.object.GetRangeHashRequest.Body.type:type_name -> neo.fs.v2.refs.ChecksumType + 50, // 80: neo.fs.v2.object.GetRangeHashResponse.Body.type:type_name -> neo.fs.v2.refs.ChecksumType + 51, // 81: neo.fs.v2.object.PutSingleRequest.Body.object:type_name -> neo.fs.v2.object.Object + 0, // 82: neo.fs.v2.object.ObjectService.Get:input_type -> neo.fs.v2.object.GetRequest + 2, // 83: neo.fs.v2.object.ObjectService.Put:input_type -> neo.fs.v2.object.PutRequest + 4, // 84: neo.fs.v2.object.ObjectService.Delete:input_type -> neo.fs.v2.object.DeleteRequest + 6, // 85: neo.fs.v2.object.ObjectService.Head:input_type -> neo.fs.v2.object.HeadRequest + 9, // 86: neo.fs.v2.object.ObjectService.Search:input_type -> neo.fs.v2.object.SearchRequest + 12, // 87: neo.fs.v2.object.ObjectService.GetRange:input_type -> neo.fs.v2.object.GetRangeRequest + 14, // 88: neo.fs.v2.object.ObjectService.GetRangeHash:input_type -> neo.fs.v2.object.GetRangeHashRequest + 16, // 89: neo.fs.v2.object.ObjectService.PutSingle:input_type -> neo.fs.v2.object.PutSingleRequest + 1, // 90: neo.fs.v2.object.ObjectService.Get:output_type -> neo.fs.v2.object.GetResponse + 3, // 91: neo.fs.v2.object.ObjectService.Put:output_type -> neo.fs.v2.object.PutResponse + 5, // 92: neo.fs.v2.object.ObjectService.Delete:output_type -> neo.fs.v2.object.DeleteResponse + 8, // 93: neo.fs.v2.object.ObjectService.Head:output_type -> neo.fs.v2.object.HeadResponse + 10, // 94: neo.fs.v2.object.ObjectService.Search:output_type -> neo.fs.v2.object.SearchResponse + 13, // 95: neo.fs.v2.object.ObjectService.GetRange:output_type -> neo.fs.v2.object.GetRangeResponse + 15, // 96: neo.fs.v2.object.ObjectService.GetRangeHash:output_type -> neo.fs.v2.object.GetRangeHashResponse + 17, // 97: neo.fs.v2.object.ObjectService.PutSingle:output_type -> neo.fs.v2.object.PutSingleResponse + 90, // [90:98] is the sub-list for method output_type + 82, // [82:90] is the sub-list for method input_type + 82, // [82:82] is the sub-list for extension type_name + 82, // [82:82] is the sub-list for extension extendee + 0, // [0:82] is the sub-list for field type_name +} + +func init() { file_object_grpc_service_proto_init() } +func file_object_grpc_service_proto_init() { + if File_object_grpc_service_proto != nil { + return + } + file_object_grpc_types_proto_init() + if !protoimpl.UnsafeEnabled { + file_object_grpc_service_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_object_grpc_service_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_object_grpc_service_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PutRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_object_grpc_service_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PutResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_object_grpc_service_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DeleteRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_object_grpc_service_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DeleteResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_object_grpc_service_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*HeadRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_object_grpc_service_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*HeaderWithSignature); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_object_grpc_service_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*HeadResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_object_grpc_service_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SearchRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_object_grpc_service_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SearchResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_object_grpc_service_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Range); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_object_grpc_service_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetRangeRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_object_grpc_service_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetRangeResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_object_grpc_service_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetRangeHashRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_object_grpc_service_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetRangeHashResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_object_grpc_service_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PutSingleRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_object_grpc_service_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PutSingleResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_object_grpc_service_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetRequest_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_object_grpc_service_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetResponse_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_object_grpc_service_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetResponse_Body_Init); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_object_grpc_service_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PutRequest_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_object_grpc_service_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PutRequest_Body_Init); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_object_grpc_service_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PutResponse_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_object_grpc_service_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DeleteRequest_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_object_grpc_service_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DeleteResponse_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_object_grpc_service_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*HeadRequest_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_object_grpc_service_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*HeadResponse_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_object_grpc_service_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SearchRequest_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_object_grpc_service_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SearchRequest_Body_Filter); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_object_grpc_service_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SearchResponse_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_object_grpc_service_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetRangeRequest_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_object_grpc_service_proto_msgTypes[32].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetRangeResponse_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_object_grpc_service_proto_msgTypes[33].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetRangeHashRequest_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_object_grpc_service_proto_msgTypes[34].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetRangeHashResponse_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_object_grpc_service_proto_msgTypes[35].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PutSingleRequest_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_object_grpc_service_proto_msgTypes[36].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PutSingleResponse_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + file_object_grpc_service_proto_msgTypes[19].OneofWrappers = []interface{}{ + (*GetResponse_Body_Init_)(nil), + (*GetResponse_Body_Chunk)(nil), + (*GetResponse_Body_SplitInfo)(nil), + (*GetResponse_Body_EcInfo)(nil), + } + file_object_grpc_service_proto_msgTypes[21].OneofWrappers = []interface{}{ + (*PutRequest_Body_Init_)(nil), + (*PutRequest_Body_Chunk)(nil), + } + file_object_grpc_service_proto_msgTypes[27].OneofWrappers = []interface{}{ + (*HeadResponse_Body_Header)(nil), + (*HeadResponse_Body_ShortHeader)(nil), + (*HeadResponse_Body_SplitInfo)(nil), + (*HeadResponse_Body_EcInfo)(nil), + } + file_object_grpc_service_proto_msgTypes[32].OneofWrappers = []interface{}{ + (*GetRangeResponse_Body_Chunk)(nil), + (*GetRangeResponse_Body_SplitInfo)(nil), + (*GetRangeResponse_Body_EcInfo)(nil), + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_object_grpc_service_proto_rawDesc, + NumEnums: 0, + NumMessages: 37, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_object_grpc_service_proto_goTypes, + DependencyIndexes: file_object_grpc_service_proto_depIdxs, + MessageInfos: file_object_grpc_service_proto_msgTypes, + }.Build() + File_object_grpc_service_proto = out.File + file_object_grpc_service_proto_rawDesc = nil + file_object_grpc_service_proto_goTypes = nil + file_object_grpc_service_proto_depIdxs = nil +} diff --git a/pkg/api/object/grpc/service_grpc.pb.go b/pkg/api/object/grpc/service_grpc.pb.go new file mode 100644 index 000000000..1edf6473e --- /dev/null +++ b/pkg/api/object/grpc/service_grpc.pb.go @@ -0,0 +1,966 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.3.0 +// - protoc v4.25.3 +// source: object/grpc/service.proto + +package object + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +const ( + ObjectService_Get_FullMethodName = "/neo.fs.v2.object.ObjectService/Get" + ObjectService_Put_FullMethodName = "/neo.fs.v2.object.ObjectService/Put" + ObjectService_Delete_FullMethodName = "/neo.fs.v2.object.ObjectService/Delete" + ObjectService_Head_FullMethodName = "/neo.fs.v2.object.ObjectService/Head" + ObjectService_Search_FullMethodName = "/neo.fs.v2.object.ObjectService/Search" + ObjectService_GetRange_FullMethodName = "/neo.fs.v2.object.ObjectService/GetRange" + ObjectService_GetRangeHash_FullMethodName = "/neo.fs.v2.object.ObjectService/GetRangeHash" + ObjectService_PutSingle_FullMethodName = "/neo.fs.v2.object.ObjectService/PutSingle" +) + +// ObjectServiceClient is the client API for ObjectService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type ObjectServiceClient interface { + // Receive full object structure, including Headers and payload. Response uses + // gRPC stream. First response message carries the object with the requested + // address. Chunk messages are parts of the object's payload if it is needed. + // All messages, except the first one, carry payload chunks. The requested + // object can be restored by concatenation of object message payload and all + // chunks keeping the receiving order. + // + // Extended headers can change `Get` behaviour: + // - [ __SYSTEM__NETMAP_EPOCH ] \ + // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ + // Will use the requsted version of Network Map for object placement + // calculation. + // - [ __SYSTEM__NETMAP_LOOKUP_DEPTH ] \ + // (`__NEOFS__NETMAP_LOOKUP_DEPTH` is deprecated) \ + // Will try older versions (starting from `__SYSTEM__NETMAP_EPOCH` + // (`__NEOFS__NETMAP_EPOCH` is deprecated) if specified or the latest one + // otherwise) of Network Map to find an object until the depth limit is + // reached. + // + // Please refer to detailed `XHeader` description. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): \ + // object has been successfully read; + // - Common failures (SECTION_FAILURE_COMMON); + // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ + // read access to the object is denied; + // - **OBJECT_NOT_FOUND** (2049, SECTION_OBJECT): \ + // object not found in container; + // - **OBJECT_ALREADY_REMOVED** (2052, SECTION_OBJECT): \ + // the requested object has been marked as deleted; + // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ + // object container not found; + // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ + // provided session token has expired. + Get(ctx context.Context, in *GetRequest, opts ...grpc.CallOption) (ObjectService_GetClient, error) + // Put the object into container. Request uses gRPC stream. First message + // SHOULD be of PutHeader type. `ContainerID` and `OwnerID` of an object + // SHOULD be set. Session token SHOULD be obtained before `PUT` operation (see + // session package). Chunk messages are considered by server as a part of an + // object payload. All messages, except first one, SHOULD be payload chunks. + // Chunk messages SHOULD be sent in the direct order of fragmentation. + // + // Extended headers can change `Put` behaviour: + // - [ __SYSTEM__NETMAP_EPOCH \ + // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ + // Will use the requsted version of Network Map for object placement + // calculation. + // + // Please refer to detailed `XHeader` description. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): \ + // object has been successfully saved in the container; + // - Common failures (SECTION_FAILURE_COMMON); + // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ + // write access to the container is denied; + // - **LOCKED** (2050, SECTION_OBJECT): \ + // placement of an object of type TOMBSTONE that includes at least one + // locked object is prohibited; + // - **LOCK_NON_REGULAR_OBJECT** (2051, SECTION_OBJECT): \ + // placement of an object of type LOCK that includes at least one object of + // type other than REGULAR is prohibited; + // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ + // object storage container not found; + // - **TOKEN_NOT_FOUND** (4096, SECTION_SESSION): \ + // (for trusted object preparation) session private key does not exist or + // has + // + // been deleted; + // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ + // provided session token has expired. + Put(ctx context.Context, opts ...grpc.CallOption) (ObjectService_PutClient, error) + // Delete the object from a container. There is no immediate removal + // guarantee. Object will be marked for removal and deleted eventually. + // + // Extended headers can change `Delete` behaviour: + // - [ __SYSTEM__NETMAP_EPOCH ] \ + // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ + // Will use the requested version of Network Map for object placement + // calculation. + // + // Please refer to detailed `XHeader` description. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): \ + // object has been successfully marked to be removed from the container; + // - Common failures (SECTION_FAILURE_COMMON); + // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ + // delete access to the object is denied; + // - **OBJECT_NOT_FOUND** (2049, SECTION_OBJECT): \ + // the object could not be deleted because it has not been \ + // found within the container; + // - **LOCKED** (2050, SECTION_OBJECT): \ + // deleting a locked object is prohibited; + // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ + // object container not found; + // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ + // provided session token has expired. + Delete(ctx context.Context, in *DeleteRequest, opts ...grpc.CallOption) (*DeleteResponse, error) + // Returns the object Headers without data payload. By default full header is + // returned. If `main_only` request field is set, the short header with only + // the very minimal information will be returned instead. + // + // Extended headers can change `Head` behaviour: + // - [ __SYSTEM__NETMAP_EPOCH ] \ + // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ + // Will use the requested version of Network Map for object placement + // calculation. + // + // Please refer to detailed `XHeader` description. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): \ + // object header has been successfully read; + // - Common failures (SECTION_FAILURE_COMMON); + // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ + // access to operation HEAD of the object is denied; + // - **OBJECT_NOT_FOUND** (2049, SECTION_OBJECT): \ + // object not found in container; + // - **OBJECT_ALREADY_REMOVED** (2052, SECTION_OBJECT): \ + // the requested object has been marked as deleted; + // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ + // object container not found; + // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ + // provided session token has expired. + Head(ctx context.Context, in *HeadRequest, opts ...grpc.CallOption) (*HeadResponse, error) + // Search objects in container. Search query allows to match by Object + // Header's filed values. Please see the corresponding NeoFS Technical + // Specification section for more details. + // + // Extended headers can change `Search` behaviour: + // - [ __SYSTEM__NETMAP_EPOCH ] \ + // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ + // Will use the requested version of Network Map for object placement + // calculation. + // + // Please refer to detailed `XHeader` description. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): \ + // objects have been successfully selected; + // - Common failures (SECTION_FAILURE_COMMON); + // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ + // access to operation SEARCH of the object is denied; + // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ + // search container not found; + // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ + // provided session token has expired. + Search(ctx context.Context, in *SearchRequest, opts ...grpc.CallOption) (ObjectService_SearchClient, error) + // Get byte range of data payload. Range is set as an (offset, length) tuple. + // Like in `Get` method, the response uses gRPC stream. Requested range can be + // restored by concatenation of all received payload chunks keeping the + // receiving order. + // + // Extended headers can change `GetRange` behaviour: + // - [ __SYSTEM__NETMAP_EPOCH ] \ + // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ + // Will use the requested version of Network Map for object placement + // calculation. + // - [ __SYSTEM__NETMAP_LOOKUP_DEPTH ] \ + // (`__NEOFS__NETMAP_LOOKUP_DEPTH` is deprecated) \ + // Will try older versions of Network Map to find an object until the depth + // limit is reached. + // + // Please refer to detailed `XHeader` description. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): \ + // data range of the object payload has been successfully read; + // - Common failures (SECTION_FAILURE_COMMON); + // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ + // access to operation RANGE of the object is denied; + // - **OBJECT_NOT_FOUND** (2049, SECTION_OBJECT): \ + // object not found in container; + // - **OBJECT_ALREADY_REMOVED** (2052, SECTION_OBJECT): \ + // the requested object has been marked as deleted. + // - **OUT_OF_RANGE** (2053, SECTION_OBJECT): \ + // the requested range is out of bounds; + // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ + // object container not found; + // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ + // provided session token has expired. + GetRange(ctx context.Context, in *GetRangeRequest, opts ...grpc.CallOption) (ObjectService_GetRangeClient, error) + // Returns homomorphic or regular hash of object's payload range after + // applying XOR operation with the provided `salt`. Ranges are set of (offset, + // length) tuples. Hashes order in response corresponds to the ranges order in + // the request. Note that hash is calculated for XORed data. + // + // Extended headers can change `GetRangeHash` behaviour: + // - [ __SYSTEM__NETMAP_EPOCH ] \ + // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ + // Will use the requested version of Network Map for object placement + // calculation. + // - [ __SYSTEM__NETMAP_LOOKUP_DEPTH ] \ + // (`__NEOFS__NETMAP_LOOKUP_DEPTH` is deprecated) \ + // Will try older versions of Network Map to find an object until the depth + // limit is reached. + // + // Please refer to detailed `XHeader` description. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): \ + // data range of the object payload has been successfully hashed; + // - Common failures (SECTION_FAILURE_COMMON); + // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ + // access to operation RANGEHASH of the object is denied; + // - **OBJECT_NOT_FOUND** (2049, SECTION_OBJECT): \ + // object not found in container; + // - **OUT_OF_RANGE** (2053, SECTION_OBJECT): \ + // the requested range is out of bounds; + // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ + // object container not found; + // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ + // provided session token has expired. + GetRangeHash(ctx context.Context, in *GetRangeHashRequest, opts ...grpc.CallOption) (*GetRangeHashResponse, error) + // Put the prepared object into container. + // `ContainerID`, `ObjectID`, `OwnerID`, `PayloadHash` and `PayloadLength` of + // an object MUST be set. + // + // Extended headers can change `Put` behaviour: + // - [ __SYSTEM__NETMAP_EPOCH \ + // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ + // Will use the requested version of Network Map for object placement + // calculation. + // + // Please refer to detailed `XHeader` description. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): \ + // object has been successfully saved in the container; + // - Common failures (SECTION_FAILURE_COMMON); + // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ + // write access to the container is denied; + // - **LOCKED** (2050, SECTION_OBJECT): \ + // placement of an object of type TOMBSTONE that includes at least one + // locked object is prohibited; + // - **LOCK_NON_REGULAR_OBJECT** (2051, SECTION_OBJECT): \ + // placement of an object of type LOCK that includes at least one object of + // type other than REGULAR is prohibited; + // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ + // object storage container not found; + // - **TOKEN_NOT_FOUND** (4096, SECTION_SESSION): \ + // (for trusted object preparation) session private key does not exist or + // has + // + // been deleted; + // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ + // provided session token has expired. + PutSingle(ctx context.Context, in *PutSingleRequest, opts ...grpc.CallOption) (*PutSingleResponse, error) +} + +type objectServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewObjectServiceClient(cc grpc.ClientConnInterface) ObjectServiceClient { + return &objectServiceClient{cc} +} + +func (c *objectServiceClient) Get(ctx context.Context, in *GetRequest, opts ...grpc.CallOption) (ObjectService_GetClient, error) { + stream, err := c.cc.NewStream(ctx, &ObjectService_ServiceDesc.Streams[0], ObjectService_Get_FullMethodName, opts...) + if err != nil { + return nil, err + } + x := &objectServiceGetClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type ObjectService_GetClient interface { + Recv() (*GetResponse, error) + grpc.ClientStream +} + +type objectServiceGetClient struct { + grpc.ClientStream +} + +func (x *objectServiceGetClient) Recv() (*GetResponse, error) { + m := new(GetResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *objectServiceClient) Put(ctx context.Context, opts ...grpc.CallOption) (ObjectService_PutClient, error) { + stream, err := c.cc.NewStream(ctx, &ObjectService_ServiceDesc.Streams[1], ObjectService_Put_FullMethodName, opts...) + if err != nil { + return nil, err + } + x := &objectServicePutClient{stream} + return x, nil +} + +type ObjectService_PutClient interface { + Send(*PutRequest) error + CloseAndRecv() (*PutResponse, error) + grpc.ClientStream +} + +type objectServicePutClient struct { + grpc.ClientStream +} + +func (x *objectServicePutClient) Send(m *PutRequest) error { + return x.ClientStream.SendMsg(m) +} + +func (x *objectServicePutClient) CloseAndRecv() (*PutResponse, error) { + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + m := new(PutResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *objectServiceClient) Delete(ctx context.Context, in *DeleteRequest, opts ...grpc.CallOption) (*DeleteResponse, error) { + out := new(DeleteResponse) + err := c.cc.Invoke(ctx, ObjectService_Delete_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *objectServiceClient) Head(ctx context.Context, in *HeadRequest, opts ...grpc.CallOption) (*HeadResponse, error) { + out := new(HeadResponse) + err := c.cc.Invoke(ctx, ObjectService_Head_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *objectServiceClient) Search(ctx context.Context, in *SearchRequest, opts ...grpc.CallOption) (ObjectService_SearchClient, error) { + stream, err := c.cc.NewStream(ctx, &ObjectService_ServiceDesc.Streams[2], ObjectService_Search_FullMethodName, opts...) + if err != nil { + return nil, err + } + x := &objectServiceSearchClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type ObjectService_SearchClient interface { + Recv() (*SearchResponse, error) + grpc.ClientStream +} + +type objectServiceSearchClient struct { + grpc.ClientStream +} + +func (x *objectServiceSearchClient) Recv() (*SearchResponse, error) { + m := new(SearchResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *objectServiceClient) GetRange(ctx context.Context, in *GetRangeRequest, opts ...grpc.CallOption) (ObjectService_GetRangeClient, error) { + stream, err := c.cc.NewStream(ctx, &ObjectService_ServiceDesc.Streams[3], ObjectService_GetRange_FullMethodName, opts...) + if err != nil { + return nil, err + } + x := &objectServiceGetRangeClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type ObjectService_GetRangeClient interface { + Recv() (*GetRangeResponse, error) + grpc.ClientStream +} + +type objectServiceGetRangeClient struct { + grpc.ClientStream +} + +func (x *objectServiceGetRangeClient) Recv() (*GetRangeResponse, error) { + m := new(GetRangeResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *objectServiceClient) GetRangeHash(ctx context.Context, in *GetRangeHashRequest, opts ...grpc.CallOption) (*GetRangeHashResponse, error) { + out := new(GetRangeHashResponse) + err := c.cc.Invoke(ctx, ObjectService_GetRangeHash_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *objectServiceClient) PutSingle(ctx context.Context, in *PutSingleRequest, opts ...grpc.CallOption) (*PutSingleResponse, error) { + out := new(PutSingleResponse) + err := c.cc.Invoke(ctx, ObjectService_PutSingle_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// ObjectServiceServer is the server API for ObjectService service. +// All implementations should embed UnimplementedObjectServiceServer +// for forward compatibility +type ObjectServiceServer interface { + // Receive full object structure, including Headers and payload. Response uses + // gRPC stream. First response message carries the object with the requested + // address. Chunk messages are parts of the object's payload if it is needed. + // All messages, except the first one, carry payload chunks. The requested + // object can be restored by concatenation of object message payload and all + // chunks keeping the receiving order. + // + // Extended headers can change `Get` behaviour: + // - [ __SYSTEM__NETMAP_EPOCH ] \ + // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ + // Will use the requsted version of Network Map for object placement + // calculation. + // - [ __SYSTEM__NETMAP_LOOKUP_DEPTH ] \ + // (`__NEOFS__NETMAP_LOOKUP_DEPTH` is deprecated) \ + // Will try older versions (starting from `__SYSTEM__NETMAP_EPOCH` + // (`__NEOFS__NETMAP_EPOCH` is deprecated) if specified or the latest one + // otherwise) of Network Map to find an object until the depth limit is + // reached. + // + // Please refer to detailed `XHeader` description. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): \ + // object has been successfully read; + // - Common failures (SECTION_FAILURE_COMMON); + // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ + // read access to the object is denied; + // - **OBJECT_NOT_FOUND** (2049, SECTION_OBJECT): \ + // object not found in container; + // - **OBJECT_ALREADY_REMOVED** (2052, SECTION_OBJECT): \ + // the requested object has been marked as deleted; + // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ + // object container not found; + // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ + // provided session token has expired. + Get(*GetRequest, ObjectService_GetServer) error + // Put the object into container. Request uses gRPC stream. First message + // SHOULD be of PutHeader type. `ContainerID` and `OwnerID` of an object + // SHOULD be set. Session token SHOULD be obtained before `PUT` operation (see + // session package). Chunk messages are considered by server as a part of an + // object payload. All messages, except first one, SHOULD be payload chunks. + // Chunk messages SHOULD be sent in the direct order of fragmentation. + // + // Extended headers can change `Put` behaviour: + // - [ __SYSTEM__NETMAP_EPOCH \ + // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ + // Will use the requsted version of Network Map for object placement + // calculation. + // + // Please refer to detailed `XHeader` description. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): \ + // object has been successfully saved in the container; + // - Common failures (SECTION_FAILURE_COMMON); + // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ + // write access to the container is denied; + // - **LOCKED** (2050, SECTION_OBJECT): \ + // placement of an object of type TOMBSTONE that includes at least one + // locked object is prohibited; + // - **LOCK_NON_REGULAR_OBJECT** (2051, SECTION_OBJECT): \ + // placement of an object of type LOCK that includes at least one object of + // type other than REGULAR is prohibited; + // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ + // object storage container not found; + // - **TOKEN_NOT_FOUND** (4096, SECTION_SESSION): \ + // (for trusted object preparation) session private key does not exist or + // has + // + // been deleted; + // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ + // provided session token has expired. + Put(ObjectService_PutServer) error + // Delete the object from a container. There is no immediate removal + // guarantee. Object will be marked for removal and deleted eventually. + // + // Extended headers can change `Delete` behaviour: + // - [ __SYSTEM__NETMAP_EPOCH ] \ + // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ + // Will use the requested version of Network Map for object placement + // calculation. + // + // Please refer to detailed `XHeader` description. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): \ + // object has been successfully marked to be removed from the container; + // - Common failures (SECTION_FAILURE_COMMON); + // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ + // delete access to the object is denied; + // - **OBJECT_NOT_FOUND** (2049, SECTION_OBJECT): \ + // the object could not be deleted because it has not been \ + // found within the container; + // - **LOCKED** (2050, SECTION_OBJECT): \ + // deleting a locked object is prohibited; + // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ + // object container not found; + // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ + // provided session token has expired. + Delete(context.Context, *DeleteRequest) (*DeleteResponse, error) + // Returns the object Headers without data payload. By default full header is + // returned. If `main_only` request field is set, the short header with only + // the very minimal information will be returned instead. + // + // Extended headers can change `Head` behaviour: + // - [ __SYSTEM__NETMAP_EPOCH ] \ + // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ + // Will use the requested version of Network Map for object placement + // calculation. + // + // Please refer to detailed `XHeader` description. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): \ + // object header has been successfully read; + // - Common failures (SECTION_FAILURE_COMMON); + // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ + // access to operation HEAD of the object is denied; + // - **OBJECT_NOT_FOUND** (2049, SECTION_OBJECT): \ + // object not found in container; + // - **OBJECT_ALREADY_REMOVED** (2052, SECTION_OBJECT): \ + // the requested object has been marked as deleted; + // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ + // object container not found; + // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ + // provided session token has expired. + Head(context.Context, *HeadRequest) (*HeadResponse, error) + // Search objects in container. Search query allows to match by Object + // Header's filed values. Please see the corresponding NeoFS Technical + // Specification section for more details. + // + // Extended headers can change `Search` behaviour: + // - [ __SYSTEM__NETMAP_EPOCH ] \ + // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ + // Will use the requested version of Network Map for object placement + // calculation. + // + // Please refer to detailed `XHeader` description. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): \ + // objects have been successfully selected; + // - Common failures (SECTION_FAILURE_COMMON); + // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ + // access to operation SEARCH of the object is denied; + // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ + // search container not found; + // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ + // provided session token has expired. + Search(*SearchRequest, ObjectService_SearchServer) error + // Get byte range of data payload. Range is set as an (offset, length) tuple. + // Like in `Get` method, the response uses gRPC stream. Requested range can be + // restored by concatenation of all received payload chunks keeping the + // receiving order. + // + // Extended headers can change `GetRange` behaviour: + // - [ __SYSTEM__NETMAP_EPOCH ] \ + // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ + // Will use the requested version of Network Map for object placement + // calculation. + // - [ __SYSTEM__NETMAP_LOOKUP_DEPTH ] \ + // (`__NEOFS__NETMAP_LOOKUP_DEPTH` is deprecated) \ + // Will try older versions of Network Map to find an object until the depth + // limit is reached. + // + // Please refer to detailed `XHeader` description. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): \ + // data range of the object payload has been successfully read; + // - Common failures (SECTION_FAILURE_COMMON); + // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ + // access to operation RANGE of the object is denied; + // - **OBJECT_NOT_FOUND** (2049, SECTION_OBJECT): \ + // object not found in container; + // - **OBJECT_ALREADY_REMOVED** (2052, SECTION_OBJECT): \ + // the requested object has been marked as deleted. + // - **OUT_OF_RANGE** (2053, SECTION_OBJECT): \ + // the requested range is out of bounds; + // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ + // object container not found; + // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ + // provided session token has expired. + GetRange(*GetRangeRequest, ObjectService_GetRangeServer) error + // Returns homomorphic or regular hash of object's payload range after + // applying XOR operation with the provided `salt`. Ranges are set of (offset, + // length) tuples. Hashes order in response corresponds to the ranges order in + // the request. Note that hash is calculated for XORed data. + // + // Extended headers can change `GetRangeHash` behaviour: + // - [ __SYSTEM__NETMAP_EPOCH ] \ + // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ + // Will use the requested version of Network Map for object placement + // calculation. + // - [ __SYSTEM__NETMAP_LOOKUP_DEPTH ] \ + // (`__NEOFS__NETMAP_LOOKUP_DEPTH` is deprecated) \ + // Will try older versions of Network Map to find an object until the depth + // limit is reached. + // + // Please refer to detailed `XHeader` description. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): \ + // data range of the object payload has been successfully hashed; + // - Common failures (SECTION_FAILURE_COMMON); + // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ + // access to operation RANGEHASH of the object is denied; + // - **OBJECT_NOT_FOUND** (2049, SECTION_OBJECT): \ + // object not found in container; + // - **OUT_OF_RANGE** (2053, SECTION_OBJECT): \ + // the requested range is out of bounds; + // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ + // object container not found; + // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ + // provided session token has expired. + GetRangeHash(context.Context, *GetRangeHashRequest) (*GetRangeHashResponse, error) + // Put the prepared object into container. + // `ContainerID`, `ObjectID`, `OwnerID`, `PayloadHash` and `PayloadLength` of + // an object MUST be set. + // + // Extended headers can change `Put` behaviour: + // - [ __SYSTEM__NETMAP_EPOCH \ + // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ + // Will use the requested version of Network Map for object placement + // calculation. + // + // Please refer to detailed `XHeader` description. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): \ + // object has been successfully saved in the container; + // - Common failures (SECTION_FAILURE_COMMON); + // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ + // write access to the container is denied; + // - **LOCKED** (2050, SECTION_OBJECT): \ + // placement of an object of type TOMBSTONE that includes at least one + // locked object is prohibited; + // - **LOCK_NON_REGULAR_OBJECT** (2051, SECTION_OBJECT): \ + // placement of an object of type LOCK that includes at least one object of + // type other than REGULAR is prohibited; + // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ + // object storage container not found; + // - **TOKEN_NOT_FOUND** (4096, SECTION_SESSION): \ + // (for trusted object preparation) session private key does not exist or + // has + // + // been deleted; + // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ + // provided session token has expired. + PutSingle(context.Context, *PutSingleRequest) (*PutSingleResponse, error) +} + +// UnimplementedObjectServiceServer should be embedded to have forward compatible implementations. +type UnimplementedObjectServiceServer struct { +} + +func (UnimplementedObjectServiceServer) Get(*GetRequest, ObjectService_GetServer) error { + return status.Errorf(codes.Unimplemented, "method Get not implemented") +} +func (UnimplementedObjectServiceServer) Put(ObjectService_PutServer) error { + return status.Errorf(codes.Unimplemented, "method Put not implemented") +} +func (UnimplementedObjectServiceServer) Delete(context.Context, *DeleteRequest) (*DeleteResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Delete not implemented") +} +func (UnimplementedObjectServiceServer) Head(context.Context, *HeadRequest) (*HeadResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Head not implemented") +} +func (UnimplementedObjectServiceServer) Search(*SearchRequest, ObjectService_SearchServer) error { + return status.Errorf(codes.Unimplemented, "method Search not implemented") +} +func (UnimplementedObjectServiceServer) GetRange(*GetRangeRequest, ObjectService_GetRangeServer) error { + return status.Errorf(codes.Unimplemented, "method GetRange not implemented") +} +func (UnimplementedObjectServiceServer) GetRangeHash(context.Context, *GetRangeHashRequest) (*GetRangeHashResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetRangeHash not implemented") +} +func (UnimplementedObjectServiceServer) PutSingle(context.Context, *PutSingleRequest) (*PutSingleResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method PutSingle not implemented") +} + +// UnsafeObjectServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to ObjectServiceServer will +// result in compilation errors. +type UnsafeObjectServiceServer interface { + mustEmbedUnimplementedObjectServiceServer() +} + +func RegisterObjectServiceServer(s grpc.ServiceRegistrar, srv ObjectServiceServer) { + s.RegisterService(&ObjectService_ServiceDesc, srv) +} + +func _ObjectService_Get_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(GetRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(ObjectServiceServer).Get(m, &objectServiceGetServer{stream}) +} + +type ObjectService_GetServer interface { + Send(*GetResponse) error + grpc.ServerStream +} + +type objectServiceGetServer struct { + grpc.ServerStream +} + +func (x *objectServiceGetServer) Send(m *GetResponse) error { + return x.ServerStream.SendMsg(m) +} + +func _ObjectService_Put_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(ObjectServiceServer).Put(&objectServicePutServer{stream}) +} + +type ObjectService_PutServer interface { + SendAndClose(*PutResponse) error + Recv() (*PutRequest, error) + grpc.ServerStream +} + +type objectServicePutServer struct { + grpc.ServerStream +} + +func (x *objectServicePutServer) SendAndClose(m *PutResponse) error { + return x.ServerStream.SendMsg(m) +} + +func (x *objectServicePutServer) Recv() (*PutRequest, error) { + m := new(PutRequest) + if err := x.ServerStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func _ObjectService_Delete_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeleteRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ObjectServiceServer).Delete(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ObjectService_Delete_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ObjectServiceServer).Delete(ctx, req.(*DeleteRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ObjectService_Head_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(HeadRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ObjectServiceServer).Head(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ObjectService_Head_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ObjectServiceServer).Head(ctx, req.(*HeadRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ObjectService_Search_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(SearchRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(ObjectServiceServer).Search(m, &objectServiceSearchServer{stream}) +} + +type ObjectService_SearchServer interface { + Send(*SearchResponse) error + grpc.ServerStream +} + +type objectServiceSearchServer struct { + grpc.ServerStream +} + +func (x *objectServiceSearchServer) Send(m *SearchResponse) error { + return x.ServerStream.SendMsg(m) +} + +func _ObjectService_GetRange_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(GetRangeRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(ObjectServiceServer).GetRange(m, &objectServiceGetRangeServer{stream}) +} + +type ObjectService_GetRangeServer interface { + Send(*GetRangeResponse) error + grpc.ServerStream +} + +type objectServiceGetRangeServer struct { + grpc.ServerStream +} + +func (x *objectServiceGetRangeServer) Send(m *GetRangeResponse) error { + return x.ServerStream.SendMsg(m) +} + +func _ObjectService_GetRangeHash_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetRangeHashRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ObjectServiceServer).GetRangeHash(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ObjectService_GetRangeHash_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ObjectServiceServer).GetRangeHash(ctx, req.(*GetRangeHashRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ObjectService_PutSingle_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(PutSingleRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ObjectServiceServer).PutSingle(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ObjectService_PutSingle_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ObjectServiceServer).PutSingle(ctx, req.(*PutSingleRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// ObjectService_ServiceDesc is the grpc.ServiceDesc for ObjectService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var ObjectService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "neo.fs.v2.object.ObjectService", + HandlerType: (*ObjectServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Delete", + Handler: _ObjectService_Delete_Handler, + }, + { + MethodName: "Head", + Handler: _ObjectService_Head_Handler, + }, + { + MethodName: "GetRangeHash", + Handler: _ObjectService_GetRangeHash_Handler, + }, + { + MethodName: "PutSingle", + Handler: _ObjectService_PutSingle_Handler, + }, + }, + Streams: []grpc.StreamDesc{ + { + StreamName: "Get", + Handler: _ObjectService_Get_Handler, + ServerStreams: true, + }, + { + StreamName: "Put", + Handler: _ObjectService_Put_Handler, + ClientStreams: true, + }, + { + StreamName: "Search", + Handler: _ObjectService_Search_Handler, + ServerStreams: true, + }, + { + StreamName: "GetRange", + Handler: _ObjectService_GetRange_Handler, + ServerStreams: true, + }, + }, + Metadata: "object/grpc/service.proto", +} diff --git a/pkg/api/object/grpc/status.pb.go b/pkg/api/object/grpc/status.pb.go new file mode 100644 index 000000000..574c29de5 --- /dev/null +++ b/pkg/api/object/grpc/status.pb.go @@ -0,0 +1,251 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.27.1 +// protoc v3.18.0 +// source: v2/object/grpc/status.proto + +package object + +import ( + reflect "reflect" + sync "sync" + + grpc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/status/grpc" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type StatusCommon int32 + +const ( + StatusCommon_ACCESS_DENIED StatusCommon = 0 +) + +// Enum value maps for StatusCommon. +var ( + StatusCommon_name = map[int32]string{ + 0: "ACCESS_DENIED", + } + StatusCommon_value = map[string]int32{ + "ACCESS_DENIED": 0, + } +) + +func (x StatusCommon) Enum() *StatusCommon { + p := new(StatusCommon) + *p = x + return p +} + +func (x StatusCommon) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (StatusCommon) Descriptor() protoreflect.EnumDescriptor { + return file_v2_object_grpc_status_proto_enumTypes[0].Descriptor() +} + +func (StatusCommon) Type() protoreflect.EnumType { + return &file_v2_object_grpc_status_proto_enumTypes[0] +} + +func (x StatusCommon) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use StatusCommon.Descriptor instead. +func (StatusCommon) EnumDescriptor() ([]byte, []int) { + return file_v2_object_grpc_status_proto_rawDescGZIP(), []int{0} +} + +type StatusPut int32 + +const ( + StatusPut_STATUS_PUT_INCOMPLETE StatusPut = 0 +) + +// Enum value maps for StatusPut. +var ( + StatusPut_name = map[int32]string{ + 0: "STATUS_PUT_INCOMPLETE", + } + StatusPut_value = map[string]int32{ + "STATUS_PUT_INCOMPLETE": 0, + } +) + +func (x StatusPut) Enum() *StatusPut { + p := new(StatusPut) + *p = x + return p +} + +func (x StatusPut) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (StatusPut) Descriptor() protoreflect.EnumDescriptor { + return file_v2_object_grpc_status_proto_enumTypes[1].Descriptor() +} + +func (StatusPut) Type() protoreflect.EnumType { + return &file_v2_object_grpc_status_proto_enumTypes[1] +} + +func (x StatusPut) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use StatusPut.Descriptor instead. +func (StatusPut) EnumDescriptor() ([]byte, []int) { + return file_v2_object_grpc_status_proto_rawDescGZIP(), []int{1} +} + +type PutIncompleteDetail struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Statuses []*grpc.Status `protobuf:"bytes,1,rep,name=statuses,proto3" json:"statuses,omitempty"` +} + +func (x *PutIncompleteDetail) Reset() { + *x = PutIncompleteDetail{} + if protoimpl.UnsafeEnabled { + mi := &file_v2_object_grpc_status_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PutIncompleteDetail) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PutIncompleteDetail) ProtoMessage() {} + +func (x *PutIncompleteDetail) ProtoReflect() protoreflect.Message { + mi := &file_v2_object_grpc_status_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PutIncompleteDetail.ProtoReflect.Descriptor instead. +func (*PutIncompleteDetail) Descriptor() ([]byte, []int) { + return file_v2_object_grpc_status_proto_rawDescGZIP(), []int{0} +} + +func (x *PutIncompleteDetail) GetStatuses() []*grpc.Status { + if x != nil { + return x.Statuses + } + return nil +} + +var File_v2_object_grpc_status_proto protoreflect.FileDescriptor + +var file_v2_object_grpc_status_proto_rawDesc = []byte{ + 0x0a, 0x1b, 0x76, 0x32, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2f, 0x67, 0x72, 0x70, 0x63, + 0x2f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x10, 0x6e, + 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x1a, + 0x1a, 0x76, 0x32, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, + 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x4b, 0x0a, 0x13, 0x50, + 0x75, 0x74, 0x49, 0x6e, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x44, 0x65, 0x74, 0x61, + 0x69, 0x6c, 0x12, 0x34, 0x0a, 0x08, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x65, 0x73, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, + 0x2e, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x08, + 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x65, 0x73, 0x2a, 0x21, 0x0a, 0x0c, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x12, 0x11, 0x0a, 0x0d, 0x41, 0x43, 0x43, 0x45, + 0x53, 0x53, 0x5f, 0x44, 0x45, 0x4e, 0x49, 0x45, 0x44, 0x10, 0x00, 0x2a, 0x26, 0x0a, 0x09, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x50, 0x75, 0x74, 0x12, 0x19, 0x0a, 0x15, 0x53, 0x54, 0x41, 0x54, + 0x55, 0x53, 0x5f, 0x50, 0x55, 0x54, 0x5f, 0x49, 0x4e, 0x43, 0x4f, 0x4d, 0x50, 0x4c, 0x45, 0x54, + 0x45, 0x10, 0x00, 0x42, 0x56, 0x5a, 0x37, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, + 0x6d, 0x2f, 0x6e, 0x73, 0x70, 0x63, 0x63, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x6e, 0x65, 0x6f, 0x66, + 0x73, 0x2d, 0x61, 0x70, 0x69, 0x2d, 0x67, 0x6f, 0x2f, 0x76, 0x32, 0x2f, 0x6f, 0x62, 0x6a, 0x65, + 0x63, 0x74, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x3b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0xaa, 0x02, + 0x1a, 0x4e, 0x65, 0x6f, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, + 0x2e, 0x41, 0x50, 0x49, 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x33, +} + +var ( + file_v2_object_grpc_status_proto_rawDescOnce sync.Once + file_v2_object_grpc_status_proto_rawDescData = file_v2_object_grpc_status_proto_rawDesc +) + +func file_v2_object_grpc_status_proto_rawDescGZIP() []byte { + file_v2_object_grpc_status_proto_rawDescOnce.Do(func() { + file_v2_object_grpc_status_proto_rawDescData = protoimpl.X.CompressGZIP(file_v2_object_grpc_status_proto_rawDescData) + }) + return file_v2_object_grpc_status_proto_rawDescData +} + +var file_v2_object_grpc_status_proto_enumTypes = make([]protoimpl.EnumInfo, 2) +var file_v2_object_grpc_status_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_v2_object_grpc_status_proto_goTypes = []interface{}{ + (StatusCommon)(0), // 0: neo.fs.v2.object.StatusCommon + (StatusPut)(0), // 1: neo.fs.v2.object.StatusPut + (*PutIncompleteDetail)(nil), // 2: neo.fs.v2.object.PutIncompleteDetail + (*grpc.Status)(nil), // 3: neo.fs.v2.status.Status +} +var file_v2_object_grpc_status_proto_depIdxs = []int32{ + 3, // 0: neo.fs.v2.object.PutIncompleteDetail.statuses:type_name -> neo.fs.v2.status.Status + 1, // [1:1] is the sub-list for method output_type + 1, // [1:1] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_v2_object_grpc_status_proto_init() } +func file_v2_object_grpc_status_proto_init() { + if File_v2_object_grpc_status_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_v2_object_grpc_status_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PutIncompleteDetail); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_v2_object_grpc_status_proto_rawDesc, + NumEnums: 2, + NumMessages: 1, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_v2_object_grpc_status_proto_goTypes, + DependencyIndexes: file_v2_object_grpc_status_proto_depIdxs, + EnumInfos: file_v2_object_grpc_status_proto_enumTypes, + MessageInfos: file_v2_object_grpc_status_proto_msgTypes, + }.Build() + File_v2_object_grpc_status_proto = out.File + file_v2_object_grpc_status_proto_rawDesc = nil + file_v2_object_grpc_status_proto_goTypes = nil + file_v2_object_grpc_status_proto_depIdxs = nil +} diff --git a/pkg/api/object/grpc/types.go b/pkg/api/object/grpc/types.go new file mode 100644 index 000000000..4c75cb57f --- /dev/null +++ b/pkg/api/object/grpc/types.go @@ -0,0 +1,197 @@ +package object + +import ( + refs "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs/grpc" + session "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session/grpc" +) + +// SetKey sets key to the object attribute. +func (m *Header_Attribute) SetKey(v string) { + m.Key = v +} + +// SetValue sets value of the object attribute. +func (m *Header_Attribute) SetValue(v string) { + m.Value = v +} + +// SetParent sets identifier of the parent object. +func (m *Header_Split) SetParent(v *refs.ObjectID) { + m.Parent = v +} + +// SetPrevious sets identifier of the previous object in split-chain. +func (m *Header_Split) SetPrevious(v *refs.ObjectID) { + m.Previous = v +} + +// SetParentSignature sets signature of the parent object header. +func (m *Header_Split) SetParentSignature(v *refs.Signature) { + m.ParentSignature = v +} + +// SetParentHeader sets parent header structure. +func (m *Header_Split) SetParentHeader(v *Header) { + m.ParentHeader = v +} + +// SetChildren sets list of the identifiers of the child objects. +func (m *Header_Split) SetChildren(v []*refs.ObjectID) { + m.Children = v +} + +// SetSplitId sets split ID of the object. +func (m *Header_Split) SetSplitId(v []byte) { + m.SplitId = v +} + +// SetContainerId sets identifier of the container. +func (m *Header) SetContainerId(v *refs.ContainerID) { + m.ContainerId = v +} + +// SetOwnerId sets identifier of the object owner. +func (m *Header) SetOwnerId(v *refs.OwnerID) { + m.OwnerId = v +} + +// SetCreationEpoch sets creation epoch number. +func (m *Header) SetCreationEpoch(v uint64) { + m.CreationEpoch = v +} + +// SetVersion sets version of the object format. +func (m *Header) SetVersion(v *refs.Version) { + m.Version = v +} + +// SetPayloadLength sets length of the object payload. +func (m *Header) SetPayloadLength(v uint64) { + m.PayloadLength = v +} + +// SetPayloadHash sets hash of the object payload. +func (m *Header) SetPayloadHash(v *refs.Checksum) { + m.PayloadHash = v +} + +// SetObjectType sets type of the object. +func (m *Header) SetObjectType(v ObjectType) { + m.ObjectType = v +} + +// SetHomomorphicHash sets homomorphic hash of the object payload. +func (m *Header) SetHomomorphicHash(v *refs.Checksum) { + m.HomomorphicHash = v +} + +// SetSessionToken sets session token. +func (m *Header) SetSessionToken(v *session.SessionToken) { + m.SessionToken = v +} + +// SetAttributes sets list of the object attributes. +func (m *Header) SetAttributes(v []*Header_Attribute) { + m.Attributes = v +} + +// SetSplit sets split header. +func (m *Header) SetSplit(v *Header_Split) { + m.Split = v +} + +// SetObjectId sets identifier of the object. +func (m *Object) SetObjectId(v *refs.ObjectID) { + m.ObjectId = v +} + +// SetSignature sets signature of the object identifier. +func (m *Object) SetSignature(v *refs.Signature) { + m.Signature = v +} + +// SetHeader sets header of the object. +func (m *Object) SetHeader(v *Header) { + m.Header = v +} + +// SetPayload sets payload bytes of the object. +func (m *Object) SetPayload(v []byte) { + m.Payload = v +} + +// SetVersion sets version of the object. +func (m *ShortHeader) SetVersion(v *refs.Version) { + m.Version = v +} + +// SetCreationEpoch sets creation epoch number. +func (m *ShortHeader) SetCreationEpoch(v uint64) { + m.CreationEpoch = v +} + +// SetOwnerId sets identifier of the object owner. +func (m *ShortHeader) SetOwnerId(v *refs.OwnerID) { + m.OwnerId = v +} + +// SetObjectType sets type of the object. +func (m *ShortHeader) SetObjectType(v ObjectType) { + m.ObjectType = v +} + +// SetPayloadLength sets length of the object payload. +func (m *ShortHeader) SetPayloadLength(v uint64) { + m.PayloadLength = v +} + +// SetPayloadHash sets hash of the object payload. +func (m *ShortHeader) SetPayloadHash(v *refs.Checksum) { + m.PayloadHash = v +} + +// SetHomomorphicHash sets homomorphic hash of the object payload. +func (m *ShortHeader) SetHomomorphicHash(v *refs.Checksum) { + m.HomomorphicHash = v +} + +// SetSplitId sets id of split hierarchy. +func (m *SplitInfo) SetSplitId(v []byte) { + m.SplitId = v +} + +// SetLastPart sets id of most right child in split hierarchy. +func (m *SplitInfo) SetLastPart(v *refs.ObjectID) { + m.LastPart = v +} + +// SetLink sets id of linking object in split hierarchy. +func (m *SplitInfo) SetLink(v *refs.ObjectID) { + m.Link = v +} + +// FromString parses ObjectType from a string representation, +// It is a reverse action to String(). +// +// Returns true if s was parsed successfully. +func (x *ObjectType) FromString(s string) bool { + i, ok := ObjectType_value[s] + if ok { + *x = ObjectType(i) + } + + return ok +} + +// FromString parses MatchType from a string representation, +// It is a reverse action to String(). +// +// Returns true if s was parsed successfully. +func (x *MatchType) FromString(s string) bool { + i, ok := MatchType_value[s] + if ok { + *x = MatchType(i) + } + + return ok +} diff --git a/pkg/api/object/grpc/types.pb.go b/pkg/api/object/grpc/types.pb.go new file mode 100644 index 000000000..5de750b68 --- /dev/null +++ b/pkg/api/object/grpc/types.pb.go @@ -0,0 +1,1326 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.33.0 +// protoc v4.25.3 +// source: object/grpc/types.proto + +package object + +import ( + grpc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs/grpc" + grpc1 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session/grpc" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// Type of the object payload content. Only `REGULAR` type objects can be split, +// hence `TOMBSTONE` and `LOCK` payload is limited by the +// maximum object size. +// +// String presentation of object type is the same as definition: +// * REGULAR +// * TOMBSTONE +// * LOCK +type ObjectType int32 + +const ( + // Just a normal object + ObjectType_REGULAR ObjectType = 0 + // Used internally to identify deleted objects + ObjectType_TOMBSTONE ObjectType = 1 + // Object lock + ObjectType_LOCK ObjectType = 3 +) + +// Enum value maps for ObjectType. +var ( + ObjectType_name = map[int32]string{ + 0: "REGULAR", + 1: "TOMBSTONE", + 3: "LOCK", + } + ObjectType_value = map[string]int32{ + "REGULAR": 0, + "TOMBSTONE": 1, + "LOCK": 3, + } +) + +func (x ObjectType) Enum() *ObjectType { + p := new(ObjectType) + *p = x + return p +} + +func (x ObjectType) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (ObjectType) Descriptor() protoreflect.EnumDescriptor { + return file_object_grpc_types_proto_enumTypes[0].Descriptor() +} + +func (ObjectType) Type() protoreflect.EnumType { + return &file_object_grpc_types_proto_enumTypes[0] +} + +func (x ObjectType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use ObjectType.Descriptor instead. +func (ObjectType) EnumDescriptor() ([]byte, []int) { + return file_object_grpc_types_proto_rawDescGZIP(), []int{0} +} + +// Type of match expression +type MatchType int32 + +const ( + // Unknown. Not used + MatchType_MATCH_TYPE_UNSPECIFIED MatchType = 0 + // Full string match + MatchType_STRING_EQUAL MatchType = 1 + // Full string mismatch + MatchType_STRING_NOT_EQUAL MatchType = 2 + // Lack of key + MatchType_NOT_PRESENT MatchType = 3 + // String prefix match + MatchType_COMMON_PREFIX MatchType = 4 +) + +// Enum value maps for MatchType. +var ( + MatchType_name = map[int32]string{ + 0: "MATCH_TYPE_UNSPECIFIED", + 1: "STRING_EQUAL", + 2: "STRING_NOT_EQUAL", + 3: "NOT_PRESENT", + 4: "COMMON_PREFIX", + } + MatchType_value = map[string]int32{ + "MATCH_TYPE_UNSPECIFIED": 0, + "STRING_EQUAL": 1, + "STRING_NOT_EQUAL": 2, + "NOT_PRESENT": 3, + "COMMON_PREFIX": 4, + } +) + +func (x MatchType) Enum() *MatchType { + p := new(MatchType) + *p = x + return p +} + +func (x MatchType) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (MatchType) Descriptor() protoreflect.EnumDescriptor { + return file_object_grpc_types_proto_enumTypes[1].Descriptor() +} + +func (MatchType) Type() protoreflect.EnumType { + return &file_object_grpc_types_proto_enumTypes[1] +} + +func (x MatchType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use MatchType.Descriptor instead. +func (MatchType) EnumDescriptor() ([]byte, []int) { + return file_object_grpc_types_proto_rawDescGZIP(), []int{1} +} + +// Short header fields +type ShortHeader struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Object format version. Effectively, the version of API library used to + // create particular object. + Version *grpc.Version `protobuf:"bytes,1,opt,name=version,proto3" json:"version,omitempty"` + // Epoch when the object was created + CreationEpoch uint64 `protobuf:"varint,2,opt,name=creation_epoch,json=creationEpoch,proto3" json:"creation_epoch,omitempty"` + // Object's owner + OwnerId *grpc.OwnerID `protobuf:"bytes,3,opt,name=owner_id,json=ownerID,proto3" json:"owner_id,omitempty"` + // Type of the object payload content + ObjectType ObjectType `protobuf:"varint,4,opt,name=object_type,json=objectType,proto3,enum=neo.fs.v2.object.ObjectType" json:"object_type,omitempty"` + // Size of payload in bytes. + // `0xFFFFFFFFFFFFFFFF` means `payload_length` is unknown + PayloadLength uint64 `protobuf:"varint,5,opt,name=payload_length,json=payloadLength,proto3" json:"payload_length,omitempty"` + // Hash of payload bytes + PayloadHash *grpc.Checksum `protobuf:"bytes,6,opt,name=payload_hash,json=payloadHash,proto3" json:"payload_hash,omitempty"` + // Homomorphic hash of the object payload + HomomorphicHash *grpc.Checksum `protobuf:"bytes,7,opt,name=homomorphic_hash,json=homomorphicHash,proto3" json:"homomorphic_hash,omitempty"` +} + +func (x *ShortHeader) Reset() { + *x = ShortHeader{} + if protoimpl.UnsafeEnabled { + mi := &file_object_grpc_types_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ShortHeader) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ShortHeader) ProtoMessage() {} + +func (x *ShortHeader) ProtoReflect() protoreflect.Message { + mi := &file_object_grpc_types_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ShortHeader.ProtoReflect.Descriptor instead. +func (*ShortHeader) Descriptor() ([]byte, []int) { + return file_object_grpc_types_proto_rawDescGZIP(), []int{0} +} + +func (x *ShortHeader) GetVersion() *grpc.Version { + if x != nil { + return x.Version + } + return nil +} + +func (x *ShortHeader) GetCreationEpoch() uint64 { + if x != nil { + return x.CreationEpoch + } + return 0 +} + +func (x *ShortHeader) GetOwnerId() *grpc.OwnerID { + if x != nil { + return x.OwnerId + } + return nil +} + +func (x *ShortHeader) GetObjectType() ObjectType { + if x != nil { + return x.ObjectType + } + return ObjectType_REGULAR +} + +func (x *ShortHeader) GetPayloadLength() uint64 { + if x != nil { + return x.PayloadLength + } + return 0 +} + +func (x *ShortHeader) GetPayloadHash() *grpc.Checksum { + if x != nil { + return x.PayloadHash + } + return nil +} + +func (x *ShortHeader) GetHomomorphicHash() *grpc.Checksum { + if x != nil { + return x.HomomorphicHash + } + return nil +} + +// Object Header +type Header struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Object format version. Effectively, the version of API library used to + // create particular object + Version *grpc.Version `protobuf:"bytes,1,opt,name=version,proto3" json:"version,omitempty"` + // Object's container + ContainerId *grpc.ContainerID `protobuf:"bytes,2,opt,name=container_id,json=containerID,proto3" json:"container_id,omitempty"` + // Object's owner + OwnerId *grpc.OwnerID `protobuf:"bytes,3,opt,name=owner_id,json=ownerID,proto3" json:"owner_id,omitempty"` + // Object creation Epoch + CreationEpoch uint64 `protobuf:"varint,4,opt,name=creation_epoch,json=creationEpoch,proto3" json:"creation_epoch,omitempty"` + // Size of payload in bytes. + // `0xFFFFFFFFFFFFFFFF` means `payload_length` is unknown. + PayloadLength uint64 `protobuf:"varint,5,opt,name=payload_length,json=payloadLength,proto3" json:"payload_length,omitempty"` + // Hash of payload bytes + PayloadHash *grpc.Checksum `protobuf:"bytes,6,opt,name=payload_hash,json=payloadHash,proto3" json:"payload_hash,omitempty"` + // Type of the object payload content + ObjectType ObjectType `protobuf:"varint,7,opt,name=object_type,json=objectType,proto3,enum=neo.fs.v2.object.ObjectType" json:"object_type,omitempty"` + // Homomorphic hash of the object payload + HomomorphicHash *grpc.Checksum `protobuf:"bytes,8,opt,name=homomorphic_hash,json=homomorphicHash,proto3" json:"homomorphic_hash,omitempty"` + // Session token, if it was used during Object creation. Need it to verify + // integrity and authenticity out of Request scope. + SessionToken *grpc1.SessionToken `protobuf:"bytes,9,opt,name=session_token,json=sessionToken,proto3" json:"session_token,omitempty"` + // User-defined object attributes + Attributes []*Header_Attribute `protobuf:"bytes,10,rep,name=attributes,proto3" json:"attributes,omitempty"` + // Position of the object in the split hierarchy + Split *Header_Split `protobuf:"bytes,11,opt,name=split,proto3" json:"split,omitempty"` + // Erasure code chunk information. + Ec *Header_EC `protobuf:"bytes,12,opt,name=ec,proto3" json:"ec,omitempty"` +} + +func (x *Header) Reset() { + *x = Header{} + if protoimpl.UnsafeEnabled { + mi := &file_object_grpc_types_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Header) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Header) ProtoMessage() {} + +func (x *Header) ProtoReflect() protoreflect.Message { + mi := &file_object_grpc_types_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Header.ProtoReflect.Descriptor instead. +func (*Header) Descriptor() ([]byte, []int) { + return file_object_grpc_types_proto_rawDescGZIP(), []int{1} +} + +func (x *Header) GetVersion() *grpc.Version { + if x != nil { + return x.Version + } + return nil +} + +func (x *Header) GetContainerId() *grpc.ContainerID { + if x != nil { + return x.ContainerId + } + return nil +} + +func (x *Header) GetOwnerId() *grpc.OwnerID { + if x != nil { + return x.OwnerId + } + return nil +} + +func (x *Header) GetCreationEpoch() uint64 { + if x != nil { + return x.CreationEpoch + } + return 0 +} + +func (x *Header) GetPayloadLength() uint64 { + if x != nil { + return x.PayloadLength + } + return 0 +} + +func (x *Header) GetPayloadHash() *grpc.Checksum { + if x != nil { + return x.PayloadHash + } + return nil +} + +func (x *Header) GetObjectType() ObjectType { + if x != nil { + return x.ObjectType + } + return ObjectType_REGULAR +} + +func (x *Header) GetHomomorphicHash() *grpc.Checksum { + if x != nil { + return x.HomomorphicHash + } + return nil +} + +func (x *Header) GetSessionToken() *grpc1.SessionToken { + if x != nil { + return x.SessionToken + } + return nil +} + +func (x *Header) GetAttributes() []*Header_Attribute { + if x != nil { + return x.Attributes + } + return nil +} + +func (x *Header) GetSplit() *Header_Split { + if x != nil { + return x.Split + } + return nil +} + +func (x *Header) GetEc() *Header_EC { + if x != nil { + return x.Ec + } + return nil +} + +// Object structure. Object is immutable and content-addressed. It means +// `ObjectID` will change if the header or the payload changes. It's calculated +// as a hash of header field which contains hash of the object's payload. +// +// For non-regular object types payload format depends on object type specified +// in the header. +type Object struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Object's unique identifier. + ObjectId *grpc.ObjectID `protobuf:"bytes,1,opt,name=object_id,json=objectID,proto3" json:"object_id,omitempty"` + // Signed object_id + Signature *grpc.Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` + // Object metadata headers + Header *Header `protobuf:"bytes,3,opt,name=header,proto3" json:"header,omitempty"` + // Payload bytes + Payload []byte `protobuf:"bytes,4,opt,name=payload,proto3" json:"payload,omitempty"` +} + +func (x *Object) Reset() { + *x = Object{} + if protoimpl.UnsafeEnabled { + mi := &file_object_grpc_types_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Object) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Object) ProtoMessage() {} + +func (x *Object) ProtoReflect() protoreflect.Message { + mi := &file_object_grpc_types_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Object.ProtoReflect.Descriptor instead. +func (*Object) Descriptor() ([]byte, []int) { + return file_object_grpc_types_proto_rawDescGZIP(), []int{2} +} + +func (x *Object) GetObjectId() *grpc.ObjectID { + if x != nil { + return x.ObjectId + } + return nil +} + +func (x *Object) GetSignature() *grpc.Signature { + if x != nil { + return x.Signature + } + return nil +} + +func (x *Object) GetHeader() *Header { + if x != nil { + return x.Header + } + return nil +} + +func (x *Object) GetPayload() []byte { + if x != nil { + return x.Payload + } + return nil +} + +// Meta information of split hierarchy for object assembly. With the last part +// one can traverse linked list of split hierarchy back to the first part and +// assemble the original object. With a linking object one can assemble an +// object right from the object parts. +type SplitInfo struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // 16 byte UUID used to identify the split object hierarchy parts. + SplitId []byte `protobuf:"bytes,1,opt,name=split_id,json=splitId,proto3" json:"split_id,omitempty"` + // The identifier of the last object in split hierarchy parts. It contains + // split header with the original object header. + LastPart *grpc.ObjectID `protobuf:"bytes,2,opt,name=last_part,json=lastPart,proto3" json:"last_part,omitempty"` + // The identifier of a linking object for split hierarchy parts. It contains + // split header with the original object header and a sorted list of + // object parts. + Link *grpc.ObjectID `protobuf:"bytes,3,opt,name=link,proto3" json:"link,omitempty"` +} + +func (x *SplitInfo) Reset() { + *x = SplitInfo{} + if protoimpl.UnsafeEnabled { + mi := &file_object_grpc_types_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SplitInfo) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SplitInfo) ProtoMessage() {} + +func (x *SplitInfo) ProtoReflect() protoreflect.Message { + mi := &file_object_grpc_types_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SplitInfo.ProtoReflect.Descriptor instead. +func (*SplitInfo) Descriptor() ([]byte, []int) { + return file_object_grpc_types_proto_rawDescGZIP(), []int{3} +} + +func (x *SplitInfo) GetSplitId() []byte { + if x != nil { + return x.SplitId + } + return nil +} + +func (x *SplitInfo) GetLastPart() *grpc.ObjectID { + if x != nil { + return x.LastPart + } + return nil +} + +func (x *SplitInfo) GetLink() *grpc.ObjectID { + if x != nil { + return x.Link + } + return nil +} + +// Meta information for the erasure-encoded object. +type ECInfo struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Chunk stored on the node. + Chunks []*ECInfo_Chunk `protobuf:"bytes,1,rep,name=chunks,proto3" json:"chunks,omitempty"` +} + +func (x *ECInfo) Reset() { + *x = ECInfo{} + if protoimpl.UnsafeEnabled { + mi := &file_object_grpc_types_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ECInfo) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ECInfo) ProtoMessage() {} + +func (x *ECInfo) ProtoReflect() protoreflect.Message { + mi := &file_object_grpc_types_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ECInfo.ProtoReflect.Descriptor instead. +func (*ECInfo) Descriptor() ([]byte, []int) { + return file_object_grpc_types_proto_rawDescGZIP(), []int{4} +} + +func (x *ECInfo) GetChunks() []*ECInfo_Chunk { + if x != nil { + return x.Chunks + } + return nil +} + +// `Attribute` is a user-defined Key-Value metadata pair attached to an +// object. +// +// Key name must be an object-unique valid UTF-8 string. Value can't be empty. +// Objects with duplicated attribute names or attributes with empty values +// will be considered invalid. +// +// There are some "well-known" attributes starting with `__SYSTEM__` +// (`__NEOFS__` is deprecated) prefix that affect system behaviour: +// +// - [ __SYSTEM__UPLOAD_ID ] \ +// (`__NEOFS__UPLOAD_ID` is deprecated) \ +// Marks smaller parts of a split bigger object +// - [ __SYSTEM__EXPIRATION_EPOCH ] \ +// (`__NEOFS__EXPIRATION_EPOCH` is deprecated) \ +// The epoch after which object with no LOCKs on it becomes unavailable. +// Locked object continues to be available until each of the LOCKs expire. +// - [ __SYSTEM__TICK_EPOCH ] \ +// (`__NEOFS__TICK_EPOCH` is deprecated) \ +// Decimal number that defines what epoch must produce +// object notification with UTF-8 object address in a +// body (`0` value produces notification right after +// object put) +// - [ __SYSTEM__TICK_TOPIC ] \ +// (`__NEOFS__TICK_TOPIC` is deprecated) \ +// UTF-8 string topic ID that is used for object notification +// +// And some well-known attributes used by applications only: +// +// - Name \ +// Human-friendly name +// - FileName \ +// File name to be associated with the object on saving +// - FilePath \ +// Full path to be associated with the object on saving. Should start with a +// '/' and use '/' as a delimiting symbol. Trailing '/' should be +// interpreted as a virtual directory marker. If an object has conflicting +// FilePath and FileName, FilePath should have higher priority, because it +// is used to construct the directory tree. FilePath with trailing '/' and +// non-empty FileName attribute should not be used together. +// - Timestamp \ +// User-defined local time of object creation in Unix Timestamp format +// - Content-Type \ +// MIME Content Type of object's payload +// +// For detailed description of each well-known attribute please see the +// corresponding section in NeoFS Technical Specification. +type Header_Attribute struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // string key to the object attribute + Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` + // string value of the object attribute + Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` +} + +func (x *Header_Attribute) Reset() { + *x = Header_Attribute{} + if protoimpl.UnsafeEnabled { + mi := &file_object_grpc_types_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Header_Attribute) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Header_Attribute) ProtoMessage() {} + +func (x *Header_Attribute) ProtoReflect() protoreflect.Message { + mi := &file_object_grpc_types_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Header_Attribute.ProtoReflect.Descriptor instead. +func (*Header_Attribute) Descriptor() ([]byte, []int) { + return file_object_grpc_types_proto_rawDescGZIP(), []int{1, 0} +} + +func (x *Header_Attribute) GetKey() string { + if x != nil { + return x.Key + } + return "" +} + +func (x *Header_Attribute) GetValue() string { + if x != nil { + return x.Value + } + return "" +} + +// Bigger objects can be split into a chain of smaller objects. Information +// about inter-dependencies between spawned objects and how to re-construct +// the original one is in the `Split` headers. Parent and children objects +// must be within the same container. +type Header_Split struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Identifier of the origin object. Known only to the minor child. + Parent *grpc.ObjectID `protobuf:"bytes,1,opt,name=parent,proto3" json:"parent,omitempty"` + // Identifier of the left split neighbor + Previous *grpc.ObjectID `protobuf:"bytes,2,opt,name=previous,proto3" json:"previous,omitempty"` + // `signature` field of the parent object. Used to reconstruct parent. + ParentSignature *grpc.Signature `protobuf:"bytes,3,opt,name=parent_signature,json=parentSignature,proto3" json:"parent_signature,omitempty"` + // `header` field of the parent object. Used to reconstruct parent. + ParentHeader *Header `protobuf:"bytes,4,opt,name=parent_header,json=parentHeader,proto3" json:"parent_header,omitempty"` + // List of identifiers of the objects generated by splitting current one. + Children []*grpc.ObjectID `protobuf:"bytes,5,rep,name=children,proto3" json:"children,omitempty"` + // 16 byte UUIDv4 used to identify the split object hierarchy parts. Must be + // unique inside container. All objects participating in the split must have + // the same `split_id` value. + SplitId []byte `protobuf:"bytes,6,opt,name=split_id,json=splitID,proto3" json:"split_id,omitempty"` +} + +func (x *Header_Split) Reset() { + *x = Header_Split{} + if protoimpl.UnsafeEnabled { + mi := &file_object_grpc_types_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Header_Split) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Header_Split) ProtoMessage() {} + +func (x *Header_Split) ProtoReflect() protoreflect.Message { + mi := &file_object_grpc_types_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Header_Split.ProtoReflect.Descriptor instead. +func (*Header_Split) Descriptor() ([]byte, []int) { + return file_object_grpc_types_proto_rawDescGZIP(), []int{1, 1} +} + +func (x *Header_Split) GetParent() *grpc.ObjectID { + if x != nil { + return x.Parent + } + return nil +} + +func (x *Header_Split) GetPrevious() *grpc.ObjectID { + if x != nil { + return x.Previous + } + return nil +} + +func (x *Header_Split) GetParentSignature() *grpc.Signature { + if x != nil { + return x.ParentSignature + } + return nil +} + +func (x *Header_Split) GetParentHeader() *Header { + if x != nil { + return x.ParentHeader + } + return nil +} + +func (x *Header_Split) GetChildren() []*grpc.ObjectID { + if x != nil { + return x.Children + } + return nil +} + +func (x *Header_Split) GetSplitId() []byte { + if x != nil { + return x.SplitId + } + return nil +} + +// Erasure code can be applied to any object. +// Information about encoded object structure is stored in `EC` header. +// All objects belonging to a single EC group have the same `parent` field. +type Header_EC struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Identifier of the origin object. Known to all chunks. + Parent *grpc.ObjectID `protobuf:"bytes,1,opt,name=parent,proto3" json:"parent,omitempty"` + // Index of this chunk. + Index uint32 `protobuf:"varint,2,opt,name=index,proto3" json:"index,omitempty"` + // Total number of chunks in this split. + Total uint32 `protobuf:"varint,3,opt,name=total,proto3" json:"total,omitempty"` + // Total length of a parent header. Used to trim padding zeroes. + HeaderLength uint32 `protobuf:"varint,4,opt,name=header_length,json=headerLength,proto3" json:"header_length,omitempty"` + // Chunk of a parent header. + Header []byte `protobuf:"bytes,5,opt,name=header,proto3" json:"header,omitempty"` +} + +func (x *Header_EC) Reset() { + *x = Header_EC{} + if protoimpl.UnsafeEnabled { + mi := &file_object_grpc_types_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Header_EC) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Header_EC) ProtoMessage() {} + +func (x *Header_EC) ProtoReflect() protoreflect.Message { + mi := &file_object_grpc_types_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Header_EC.ProtoReflect.Descriptor instead. +func (*Header_EC) Descriptor() ([]byte, []int) { + return file_object_grpc_types_proto_rawDescGZIP(), []int{1, 2} +} + +func (x *Header_EC) GetParent() *grpc.ObjectID { + if x != nil { + return x.Parent + } + return nil +} + +func (x *Header_EC) GetIndex() uint32 { + if x != nil { + return x.Index + } + return 0 +} + +func (x *Header_EC) GetTotal() uint32 { + if x != nil { + return x.Total + } + return 0 +} + +func (x *Header_EC) GetHeaderLength() uint32 { + if x != nil { + return x.HeaderLength + } + return 0 +} + +func (x *Header_EC) GetHeader() []byte { + if x != nil { + return x.Header + } + return nil +} + +type ECInfo_Chunk struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Object ID of the chunk. + Id *grpc.ObjectID `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + // Index of the chunk. + Index uint32 `protobuf:"varint,2,opt,name=index,proto3" json:"index,omitempty"` + // Total number of chunks in this split. + Total uint32 `protobuf:"varint,3,opt,name=total,proto3" json:"total,omitempty"` +} + +func (x *ECInfo_Chunk) Reset() { + *x = ECInfo_Chunk{} + if protoimpl.UnsafeEnabled { + mi := &file_object_grpc_types_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ECInfo_Chunk) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ECInfo_Chunk) ProtoMessage() {} + +func (x *ECInfo_Chunk) ProtoReflect() protoreflect.Message { + mi := &file_object_grpc_types_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ECInfo_Chunk.ProtoReflect.Descriptor instead. +func (*ECInfo_Chunk) Descriptor() ([]byte, []int) { + return file_object_grpc_types_proto_rawDescGZIP(), []int{4, 0} +} + +func (x *ECInfo_Chunk) GetId() *grpc.ObjectID { + if x != nil { + return x.Id + } + return nil +} + +func (x *ECInfo_Chunk) GetIndex() uint32 { + if x != nil { + return x.Index + } + return 0 +} + +func (x *ECInfo_Chunk) GetTotal() uint32 { + if x != nil { + return x.Total + } + return 0 +} + +var File_object_grpc_types_proto protoreflect.FileDescriptor + +var file_object_grpc_types_proto_rawDesc = []byte{ + 0x0a, 0x17, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x74, 0x79, + 0x70, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x10, 0x6e, 0x65, 0x6f, 0x2e, 0x66, + 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x1a, 0x15, 0x72, 0x65, 0x66, + 0x73, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x1a, 0x18, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2f, 0x67, 0x72, 0x70, 0x63, + 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x83, 0x03, 0x0a, + 0x0b, 0x53, 0x68, 0x6f, 0x72, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x31, 0x0a, 0x07, + 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, + 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x65, 0x66, 0x73, 0x2e, 0x56, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, + 0x25, 0x0a, 0x0e, 0x63, 0x72, 0x65, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x70, 0x6f, 0x63, + 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x63, 0x72, 0x65, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x32, 0x0a, 0x08, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, + 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, + 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x65, 0x66, 0x73, 0x2e, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x49, + 0x44, 0x52, 0x07, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x49, 0x44, 0x12, 0x3d, 0x0a, 0x0b, 0x6f, 0x62, + 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, + 0x1c, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, + 0x63, 0x74, 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0a, 0x6f, + 0x62, 0x6a, 0x65, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x61, 0x79, + 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x04, 0x52, 0x0d, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, + 0x12, 0x3b, 0x0a, 0x0c, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x68, 0x61, 0x73, 0x68, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, + 0x76, 0x32, 0x2e, 0x72, 0x65, 0x66, 0x73, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, + 0x52, 0x0b, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x61, 0x73, 0x68, 0x12, 0x43, 0x0a, + 0x10, 0x68, 0x6f, 0x6d, 0x6f, 0x6d, 0x6f, 0x72, 0x70, 0x68, 0x69, 0x63, 0x5f, 0x68, 0x61, 0x73, + 0x68, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, + 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x65, 0x66, 0x73, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, + 0x6d, 0x52, 0x0f, 0x68, 0x6f, 0x6d, 0x6f, 0x6d, 0x6f, 0x72, 0x70, 0x68, 0x69, 0x63, 0x48, 0x61, + 0x73, 0x68, 0x22, 0xca, 0x09, 0x0a, 0x06, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x31, 0x0a, + 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, + 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x65, 0x66, 0x73, 0x2e, + 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x12, 0x3e, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, + 0x76, 0x32, 0x2e, 0x72, 0x65, 0x66, 0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, + 0x72, 0x49, 0x44, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x44, + 0x12, 0x32, 0x0a, 0x08, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x72, + 0x65, 0x66, 0x73, 0x2e, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x49, 0x44, 0x52, 0x07, 0x6f, 0x77, 0x6e, + 0x65, 0x72, 0x49, 0x44, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x72, 0x65, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x63, 0x72, + 0x65, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x25, 0x0a, 0x0e, 0x70, + 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x0d, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x4c, 0x65, 0x6e, 0x67, + 0x74, 0x68, 0x12, 0x3b, 0x0a, 0x0c, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x68, 0x61, + 0x73, 0x68, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, + 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x65, 0x66, 0x73, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, + 0x75, 0x6d, 0x52, 0x0b, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x61, 0x73, 0x68, 0x12, + 0x3d, 0x0a, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x07, + 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, + 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x54, 0x79, + 0x70, 0x65, 0x52, 0x0a, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x43, + 0x0a, 0x10, 0x68, 0x6f, 0x6d, 0x6f, 0x6d, 0x6f, 0x72, 0x70, 0x68, 0x69, 0x63, 0x5f, 0x68, 0x61, + 0x73, 0x68, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, + 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x65, 0x66, 0x73, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, + 0x75, 0x6d, 0x52, 0x0f, 0x68, 0x6f, 0x6d, 0x6f, 0x6d, 0x6f, 0x72, 0x70, 0x68, 0x69, 0x63, 0x48, + 0x61, 0x73, 0x68, 0x12, 0x44, 0x0a, 0x0d, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x74, + 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x6e, 0x65, 0x6f, + 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x53, + 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x0c, 0x73, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x42, 0x0a, 0x0a, 0x61, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, + 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, + 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x65, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x34, 0x0a, + 0x05, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x6e, + 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, + 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x2e, 0x53, 0x70, 0x6c, 0x69, 0x74, 0x52, 0x05, 0x73, 0x70, + 0x6c, 0x69, 0x74, 0x12, 0x2b, 0x0a, 0x02, 0x65, 0x63, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1b, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, + 0x63, 0x74, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x2e, 0x45, 0x43, 0x52, 0x02, 0x65, 0x63, + 0x1a, 0x33, 0x0a, 0x09, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x10, 0x0a, + 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, + 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0xc5, 0x02, 0x0a, 0x05, 0x53, 0x70, 0x6c, 0x69, 0x74, 0x12, + 0x30, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x18, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x65, 0x66, 0x73, + 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x44, 0x52, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, + 0x74, 0x12, 0x34, 0x0a, 0x08, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, + 0x72, 0x65, 0x66, 0x73, 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x44, 0x52, 0x08, 0x70, + 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x12, 0x44, 0x0a, 0x10, 0x70, 0x61, 0x72, 0x65, 0x6e, + 0x74, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x19, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x65, + 0x66, 0x73, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x0f, 0x70, 0x61, + 0x72, 0x65, 0x6e, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x3d, 0x0a, + 0x0d, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, + 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0c, + 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x34, 0x0a, 0x08, + 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, + 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x65, 0x66, 0x73, 0x2e, + 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x44, 0x52, 0x08, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, + 0x65, 0x6e, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x49, 0x44, 0x1a, 0x9f, 0x01, + 0x0a, 0x02, 0x45, 0x43, 0x12, 0x30, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, + 0x2e, 0x72, 0x65, 0x66, 0x73, 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x44, 0x52, 0x06, + 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x14, 0x0a, 0x05, + 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x74, 0x6f, 0x74, + 0x61, 0x6c, 0x12, 0x23, 0x0a, 0x0d, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x6c, 0x65, 0x6e, + 0x67, 0x74, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x68, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x22, + 0xc4, 0x01, 0x0a, 0x06, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x35, 0x0a, 0x09, 0x6f, 0x62, + 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, + 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x65, 0x66, 0x73, 0x2e, 0x4f, + 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x44, 0x52, 0x08, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, + 0x44, 0x12, 0x37, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, + 0x2e, 0x72, 0x65, 0x66, 0x73, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, + 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x30, 0x0a, 0x06, 0x68, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6e, 0x65, 0x6f, + 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x48, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, + 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, + 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0x8b, 0x01, 0x0a, 0x09, 0x53, 0x70, 0x6c, 0x69, 0x74, + 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x5f, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x49, 0x64, 0x12, + 0x35, 0x0a, 0x09, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x72, + 0x65, 0x66, 0x73, 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x44, 0x52, 0x08, 0x6c, 0x61, + 0x73, 0x74, 0x50, 0x61, 0x72, 0x74, 0x12, 0x2c, 0x0a, 0x04, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, + 0x2e, 0x72, 0x65, 0x66, 0x73, 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x44, 0x52, 0x04, + 0x6c, 0x69, 0x6e, 0x6b, 0x22, 0x9f, 0x01, 0x0a, 0x06, 0x45, 0x43, 0x49, 0x6e, 0x66, 0x6f, 0x12, + 0x36, 0x0a, 0x06, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x1e, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x6f, 0x62, 0x6a, 0x65, + 0x63, 0x74, 0x2e, 0x45, 0x43, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x43, 0x68, 0x75, 0x6e, 0x6b, 0x52, + 0x06, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x73, 0x1a, 0x5d, 0x0a, 0x05, 0x43, 0x68, 0x75, 0x6e, 0x6b, + 0x12, 0x28, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6e, + 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x65, 0x66, 0x73, 0x2e, 0x4f, 0x62, + 0x6a, 0x65, 0x63, 0x74, 0x49, 0x44, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, + 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, + 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, + 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x2a, 0x32, 0x0a, 0x0a, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, + 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x52, 0x45, 0x47, 0x55, 0x4c, 0x41, 0x52, 0x10, + 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x54, 0x4f, 0x4d, 0x42, 0x53, 0x54, 0x4f, 0x4e, 0x45, 0x10, 0x01, + 0x12, 0x08, 0x0a, 0x04, 0x4c, 0x4f, 0x43, 0x4b, 0x10, 0x03, 0x2a, 0x73, 0x0a, 0x09, 0x4d, 0x61, + 0x74, 0x63, 0x68, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x16, 0x4d, 0x41, 0x54, 0x43, 0x48, + 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, + 0x44, 0x10, 0x00, 0x12, 0x10, 0x0a, 0x0c, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x5f, 0x45, 0x51, + 0x55, 0x41, 0x4c, 0x10, 0x01, 0x12, 0x14, 0x0a, 0x10, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x5f, + 0x4e, 0x4f, 0x54, 0x5f, 0x45, 0x51, 0x55, 0x41, 0x4c, 0x10, 0x02, 0x12, 0x0f, 0x0a, 0x0b, 0x4e, + 0x4f, 0x54, 0x5f, 0x50, 0x52, 0x45, 0x53, 0x45, 0x4e, 0x54, 0x10, 0x03, 0x12, 0x11, 0x0a, 0x0d, + 0x43, 0x4f, 0x4d, 0x4d, 0x4f, 0x4e, 0x5f, 0x50, 0x52, 0x45, 0x46, 0x49, 0x58, 0x10, 0x04, 0x42, + 0x61, 0x5a, 0x42, 0x67, 0x69, 0x74, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2e, 0x69, + 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, 0x75, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x4c, 0x61, 0x62, + 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2d, 0x61, 0x70, 0x69, 0x2d, 0x67, 0x6f, 0x2f, + 0x76, 0x32, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x3b, 0x6f, + 0x62, 0x6a, 0x65, 0x63, 0x74, 0xaa, 0x02, 0x1a, 0x4e, 0x65, 0x6f, 0x2e, 0x46, 0x69, 0x6c, 0x65, + 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x41, 0x50, 0x49, 0x2e, 0x4f, 0x62, 0x6a, 0x65, + 0x63, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_object_grpc_types_proto_rawDescOnce sync.Once + file_object_grpc_types_proto_rawDescData = file_object_grpc_types_proto_rawDesc +) + +func file_object_grpc_types_proto_rawDescGZIP() []byte { + file_object_grpc_types_proto_rawDescOnce.Do(func() { + file_object_grpc_types_proto_rawDescData = protoimpl.X.CompressGZIP(file_object_grpc_types_proto_rawDescData) + }) + return file_object_grpc_types_proto_rawDescData +} + +var file_object_grpc_types_proto_enumTypes = make([]protoimpl.EnumInfo, 2) +var file_object_grpc_types_proto_msgTypes = make([]protoimpl.MessageInfo, 9) +var file_object_grpc_types_proto_goTypes = []interface{}{ + (ObjectType)(0), // 0: neo.fs.v2.object.ObjectType + (MatchType)(0), // 1: neo.fs.v2.object.MatchType + (*ShortHeader)(nil), // 2: neo.fs.v2.object.ShortHeader + (*Header)(nil), // 3: neo.fs.v2.object.Header + (*Object)(nil), // 4: neo.fs.v2.object.Object + (*SplitInfo)(nil), // 5: neo.fs.v2.object.SplitInfo + (*ECInfo)(nil), // 6: neo.fs.v2.object.ECInfo + (*Header_Attribute)(nil), // 7: neo.fs.v2.object.Header.Attribute + (*Header_Split)(nil), // 8: neo.fs.v2.object.Header.Split + (*Header_EC)(nil), // 9: neo.fs.v2.object.Header.EC + (*ECInfo_Chunk)(nil), // 10: neo.fs.v2.object.ECInfo.Chunk + (*grpc.Version)(nil), // 11: neo.fs.v2.refs.Version + (*grpc.OwnerID)(nil), // 12: neo.fs.v2.refs.OwnerID + (*grpc.Checksum)(nil), // 13: neo.fs.v2.refs.Checksum + (*grpc.ContainerID)(nil), // 14: neo.fs.v2.refs.ContainerID + (*grpc1.SessionToken)(nil), // 15: neo.fs.v2.session.SessionToken + (*grpc.ObjectID)(nil), // 16: neo.fs.v2.refs.ObjectID + (*grpc.Signature)(nil), // 17: neo.fs.v2.refs.Signature +} +var file_object_grpc_types_proto_depIdxs = []int32{ + 11, // 0: neo.fs.v2.object.ShortHeader.version:type_name -> neo.fs.v2.refs.Version + 12, // 1: neo.fs.v2.object.ShortHeader.owner_id:type_name -> neo.fs.v2.refs.OwnerID + 0, // 2: neo.fs.v2.object.ShortHeader.object_type:type_name -> neo.fs.v2.object.ObjectType + 13, // 3: neo.fs.v2.object.ShortHeader.payload_hash:type_name -> neo.fs.v2.refs.Checksum + 13, // 4: neo.fs.v2.object.ShortHeader.homomorphic_hash:type_name -> neo.fs.v2.refs.Checksum + 11, // 5: neo.fs.v2.object.Header.version:type_name -> neo.fs.v2.refs.Version + 14, // 6: neo.fs.v2.object.Header.container_id:type_name -> neo.fs.v2.refs.ContainerID + 12, // 7: neo.fs.v2.object.Header.owner_id:type_name -> neo.fs.v2.refs.OwnerID + 13, // 8: neo.fs.v2.object.Header.payload_hash:type_name -> neo.fs.v2.refs.Checksum + 0, // 9: neo.fs.v2.object.Header.object_type:type_name -> neo.fs.v2.object.ObjectType + 13, // 10: neo.fs.v2.object.Header.homomorphic_hash:type_name -> neo.fs.v2.refs.Checksum + 15, // 11: neo.fs.v2.object.Header.session_token:type_name -> neo.fs.v2.session.SessionToken + 7, // 12: neo.fs.v2.object.Header.attributes:type_name -> neo.fs.v2.object.Header.Attribute + 8, // 13: neo.fs.v2.object.Header.split:type_name -> neo.fs.v2.object.Header.Split + 9, // 14: neo.fs.v2.object.Header.ec:type_name -> neo.fs.v2.object.Header.EC + 16, // 15: neo.fs.v2.object.Object.object_id:type_name -> neo.fs.v2.refs.ObjectID + 17, // 16: neo.fs.v2.object.Object.signature:type_name -> neo.fs.v2.refs.Signature + 3, // 17: neo.fs.v2.object.Object.header:type_name -> neo.fs.v2.object.Header + 16, // 18: neo.fs.v2.object.SplitInfo.last_part:type_name -> neo.fs.v2.refs.ObjectID + 16, // 19: neo.fs.v2.object.SplitInfo.link:type_name -> neo.fs.v2.refs.ObjectID + 10, // 20: neo.fs.v2.object.ECInfo.chunks:type_name -> neo.fs.v2.object.ECInfo.Chunk + 16, // 21: neo.fs.v2.object.Header.Split.parent:type_name -> neo.fs.v2.refs.ObjectID + 16, // 22: neo.fs.v2.object.Header.Split.previous:type_name -> neo.fs.v2.refs.ObjectID + 17, // 23: neo.fs.v2.object.Header.Split.parent_signature:type_name -> neo.fs.v2.refs.Signature + 3, // 24: neo.fs.v2.object.Header.Split.parent_header:type_name -> neo.fs.v2.object.Header + 16, // 25: neo.fs.v2.object.Header.Split.children:type_name -> neo.fs.v2.refs.ObjectID + 16, // 26: neo.fs.v2.object.Header.EC.parent:type_name -> neo.fs.v2.refs.ObjectID + 16, // 27: neo.fs.v2.object.ECInfo.Chunk.id:type_name -> neo.fs.v2.refs.ObjectID + 28, // [28:28] is the sub-list for method output_type + 28, // [28:28] is the sub-list for method input_type + 28, // [28:28] is the sub-list for extension type_name + 28, // [28:28] is the sub-list for extension extendee + 0, // [0:28] is the sub-list for field type_name +} + +func init() { file_object_grpc_types_proto_init() } +func file_object_grpc_types_proto_init() { + if File_object_grpc_types_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_object_grpc_types_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ShortHeader); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_object_grpc_types_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Header); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_object_grpc_types_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Object); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_object_grpc_types_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SplitInfo); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_object_grpc_types_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ECInfo); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_object_grpc_types_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Header_Attribute); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_object_grpc_types_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Header_Split); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_object_grpc_types_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Header_EC); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_object_grpc_types_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ECInfo_Chunk); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_object_grpc_types_proto_rawDesc, + NumEnums: 2, + NumMessages: 9, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_object_grpc_types_proto_goTypes, + DependencyIndexes: file_object_grpc_types_proto_depIdxs, + EnumInfos: file_object_grpc_types_proto_enumTypes, + MessageInfos: file_object_grpc_types_proto_msgTypes, + }.Build() + File_object_grpc_types_proto = out.File + file_object_grpc_types_proto_rawDesc = nil + file_object_grpc_types_proto_goTypes = nil + file_object_grpc_types_proto_depIdxs = nil +} diff --git a/pkg/api/object/json.go b/pkg/api/object/json.go new file mode 100644 index 000000000..8e9a59d06 --- /dev/null +++ b/pkg/api/object/json.go @@ -0,0 +1,78 @@ +package object + +import ( + object "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/message" +) + +func (h *ShortHeader) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(h) +} + +func (h *ShortHeader) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(h, data, new(object.ShortHeader)) +} + +func (a *Attribute) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(a) +} + +func (a *Attribute) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(a, data, new(object.Header_Attribute)) +} + +func (h *SplitHeader) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(h) +} + +func (h *SplitHeader) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(h, data, new(object.Header_Split)) +} + +func (h *Header) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(h) +} + +func (h *Header) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(h, data, new(object.Header)) +} + +func (h *HeaderWithSignature) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(h) +} + +func (h *HeaderWithSignature) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(h, data, new(object.HeaderWithSignature)) +} + +func (o *Object) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(o) +} + +func (o *Object) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(o, data, new(object.Object)) +} + +func (s *SplitInfo) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(s) +} + +func (s *SplitInfo) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(s, data, new(object.SplitInfo)) +} + +func (f *SearchFilter) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(f) +} + +func (f *SearchFilter) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(f, data, new(object.SearchRequest_Body_Filter)) +} + +func (r *Range) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(r) +} + +func (r *Range) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(r, data, new(object.Range)) +} diff --git a/pkg/api/object/lock.go b/pkg/api/object/lock.go new file mode 100644 index 000000000..223024f7b --- /dev/null +++ b/pkg/api/object/lock.go @@ -0,0 +1,160 @@ +package object + +import ( + "errors" + "fmt" + + lock "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/lock/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + refsGRPC "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/message" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/util/proto" +) + +// Lock represents object Lock message from NeoFS API V2 protocol. +type Lock struct { + members []refs.ObjectID +} + +// NumberOfMembers returns length of lock list. +func (x *Lock) NumberOfMembers() int { + if x != nil { + return len(x.members) + } + + return 0 +} + +// IterateMembers passes members of the lock list to f. +func (x *Lock) IterateMembers(f func(refs.ObjectID)) { + if x != nil { + for i := range x.members { + f(x.members[i]) + } + } +} + +// SetMembers sets list of locked members. +// Arg must not be mutated for the duration of the Lock. +func (x *Lock) SetMembers(ids []refs.ObjectID) { + x.members = ids +} + +const ( + _ = iota + fNumLockMembers +) + +// StableMarshal encodes the Lock into Protocol Buffers binary format +// with direct field order. +func (x *Lock) StableMarshal(buf []byte) []byte { + if x == nil || len(x.members) == 0 { + return []byte{} + } + + if buf == nil { + buf = make([]byte, x.StableSize()) + } + + var offset int + + for i := range x.members { + offset += proto.NestedStructureMarshal(fNumLockMembers, buf[offset:], &x.members[i]) + } + + return buf +} + +// StableSize size of the buffer required to write the Lock in Protocol Buffers +// binary format. +func (x *Lock) StableSize() (sz int) { + if x != nil { + for i := range x.members { + sz += proto.NestedStructureSize(fNumLockMembers, &x.members[i]) + } + } + + return +} + +// Unmarshal decodes the Lock from its Protocol Buffers binary format. +func (x *Lock) Unmarshal(data []byte) error { + return message.Unmarshal(x, data, new(lock.Lock)) +} + +func (x *Lock) ToGRPCMessage() grpc.Message { + var m *lock.Lock + + if x != nil { + m = new(lock.Lock) + + var members []*refsGRPC.ObjectID + + if x.members != nil { + members = make([]*refsGRPC.ObjectID, len(x.members)) + + for i := range x.members { + members[i] = x.members[i].ToGRPCMessage().(*refsGRPC.ObjectID) + } + } + + m.SetMembers(members) + } + + return m +} + +func (x *Lock) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*lock.Lock) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + members := v.GetMembers() + if members == nil { + x.members = nil + } else { + x.members = make([]refs.ObjectID, len(members)) + var err error + + for i := range x.members { + err = x.members[i].FromGRPCMessage(members[i]) + if err != nil { + return err + } + } + } + + return nil +} + +// WriteLock writes Lock to the Object as a payload content. +// The object must not be nil. +func WriteLock(obj *Object, lock Lock) { + hdr := obj.GetHeader() + if hdr == nil { + hdr = new(Header) + obj.SetHeader(hdr) + } + + hdr.SetObjectType(TypeLock) + + payload := lock.StableMarshal(nil) + obj.SetPayload(payload) +} + +// ReadLock reads Lock from the Object payload content. +func ReadLock(lock *Lock, obj Object) error { + payload := obj.GetPayload() + if len(payload) == 0 { + return errors.New("empty payload") + } + + err := lock.Unmarshal(payload) + if err != nil { + return fmt.Errorf("decode lock content from payload: %w", err) + } + + return nil +} diff --git a/pkg/api/object/lock_test.go b/pkg/api/object/lock_test.go new file mode 100644 index 000000000..10351b7f1 --- /dev/null +++ b/pkg/api/object/lock_test.go @@ -0,0 +1,26 @@ +package object_test + +import ( + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" + objecttest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object/test" + "github.com/stretchr/testify/require" +) + +func TestLockRW(t *testing.T) { + var l object.Lock + var obj object.Object + + require.Error(t, object.ReadLock(&l, obj)) + + l = *objecttest.GenerateLock(false) + + object.WriteLock(&obj, l) + + var l2 object.Lock + + require.NoError(t, object.ReadLock(&l2, obj)) + + require.Equal(t, l, l2) +} diff --git a/pkg/api/object/marshal.go b/pkg/api/object/marshal.go new file mode 100644 index 000000000..fb2521a34 --- /dev/null +++ b/pkg/api/object/marshal.go @@ -0,0 +1,1206 @@ +package object + +import ( + object "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/message" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/util/proto" +) + +const ( + shortHdrVersionField = 1 + shortHdrEpochField = 2 + shortHdrOwnerField = 3 + shortHdrObjectTypeField = 4 + shortHdrPayloadLength = 5 + shortHdrHashField = 6 + shortHdrHomoHashField = 7 + + attributeKeyField = 1 + attributeValueField = 2 + + splitHdrParentField = 1 + splitHdrPreviousField = 2 + splitHdrParentSignatureField = 3 + splitHdrParentHeaderField = 4 + splitHdrChildrenField = 5 + splitHdrSplitIDField = 6 + + ecHdrParentField = 1 + ecHdrIndexField = 2 + ecHdrTotalField = 3 + ecHdrHeaderLengthField = 4 + ecHdrHeaderField = 5 + + hdrVersionField = 1 + hdrContainerIDField = 2 + hdrOwnerIDField = 3 + hdrEpochField = 4 + hdrPayloadLengthField = 5 + hdrPayloadHashField = 6 + hdrObjectTypeField = 7 + hdrHomomorphicHashField = 8 + hdrSessionTokenField = 9 + hdrAttributesField = 10 + hdrSplitField = 11 + hdrECField = 12 + + hdrWithSigHeaderField = 1 + hdrWithSigSignatureField = 2 + + objIDField = 1 + objSignatureField = 2 + objHeaderField = 3 + objPayloadField = 4 + + splitInfoSplitIDField = 1 + splitInfoLastPartField = 2 + splitInfoLinkField = 3 + + getReqBodyAddressField = 1 + getReqBodyRawFlagField = 2 + + getRespInitObjectIDField = 1 + getRespInitSignatureField = 2 + getRespInitHeaderField = 3 + + getRespBodyInitField = 1 + getRespBodyChunkField = 2 + getRespBodySplitInfoField = 3 + + putReqInitObjectIDField = 1 + putReqInitSignatureField = 2 + putReqInitHeaderField = 3 + putReqInitCopiesNumField = 4 + + putReqBodyInitField = 1 + putReqBodyChunkField = 2 + + putRespBodyObjectIDField = 1 + + deleteReqBodyAddressField = 1 + + deleteRespBodyTombstoneFNum = 1 + + headReqBodyAddressField = 1 + headReqBodyMainFlagField = 2 + headReqBodyRawFlagField = 3 + + headRespBodyHeaderField = 1 + headRespBodyShortHeaderField = 2 + headRespBodySplitInfoField = 3 + + searchFilterMatchField = 1 + searchFilterNameField = 2 + searchFilterValueField = 3 + + searchReqBodyContainerIDField = 1 + searchReqBodyVersionField = 2 + searchReqBodyFiltersField = 3 + + searchRespBodyObjectIDsField = 1 + + rangeOffsetField = 1 + rangeLengthField = 2 + + getRangeReqBodyAddressField = 1 + getRangeReqBodyRangeField = 2 + getRangeReqBodyRawField = 3 + + getRangeRespChunkField = 1 + getRangeRespSplitInfoField = 2 + + getRangeHashReqBodyAddressField = 1 + getRangeHashReqBodyRangesField = 2 + getRangeHashReqBodySaltField = 3 + getRangeHashReqBodyTypeField = 4 + + getRangeHashRespBodyTypeField = 1 + getRangeHashRespBodyHashListField = 2 + + putSingleReqObjectField = 1 + putSingleReqCopiesNumberField = 2 +) + +func (h *ShortHeader) StableMarshal(buf []byte) []byte { + if h == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, h.StableSize()) + } + + var offset int + + offset += proto.NestedStructureMarshal(shortHdrVersionField, buf[offset:], h.version) + offset += proto.UInt64Marshal(shortHdrEpochField, buf[offset:], h.creatEpoch) + offset += proto.NestedStructureMarshal(shortHdrOwnerField, buf[offset:], h.ownerID) + offset += proto.EnumMarshal(shortHdrObjectTypeField, buf[offset:], int32(h.typ)) + offset += proto.UInt64Marshal(shortHdrPayloadLength, buf[offset:], h.payloadLen) + offset += proto.NestedStructureMarshal(shortHdrHashField, buf[offset:], h.payloadHash) + proto.NestedStructureMarshal(shortHdrHomoHashField, buf[offset:], h.homoHash) + + return buf +} + +func (h *ShortHeader) StableSize() (size int) { + if h == nil { + return 0 + } + + size += proto.NestedStructureSize(shortHdrVersionField, h.version) + size += proto.UInt64Size(shortHdrEpochField, h.creatEpoch) + size += proto.NestedStructureSize(shortHdrOwnerField, h.ownerID) + size += proto.EnumSize(shortHdrObjectTypeField, int32(h.typ)) + size += proto.UInt64Size(shortHdrPayloadLength, h.payloadLen) + size += proto.NestedStructureSize(shortHdrHashField, h.payloadHash) + size += proto.NestedStructureSize(shortHdrHomoHashField, h.homoHash) + + return size +} + +func (h *ShortHeader) Unmarshal(data []byte) error { + return message.Unmarshal(h, data, new(object.ShortHeader)) +} + +func (a *Attribute) StableMarshal(buf []byte) []byte { + if a == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, a.StableSize()) + } + + var offset int + + offset += proto.StringMarshal(attributeKeyField, buf[offset:], a.key) + proto.StringMarshal(attributeValueField, buf[offset:], a.val) + + return buf +} + +func (a *Attribute) StableSize() (size int) { + if a == nil { + return 0 + } + + size += proto.StringSize(shortHdrVersionField, a.key) + size += proto.StringSize(shortHdrEpochField, a.val) + + return size +} + +func (a *Attribute) Unmarshal(data []byte) error { + return message.Unmarshal(a, data, new(object.Header_Attribute)) +} + +func (h *SplitHeader) StableMarshal(buf []byte) []byte { + if h == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, h.StableSize()) + } + + var offset int + + offset += proto.NestedStructureMarshal(splitHdrParentField, buf[offset:], h.par) + offset += proto.NestedStructureMarshal(splitHdrPreviousField, buf[offset:], h.prev) + offset += proto.NestedStructureMarshal(splitHdrParentSignatureField, buf[offset:], h.parSig) + offset += proto.NestedStructureMarshal(splitHdrParentHeaderField, buf[offset:], h.parHdr) + offset += refs.ObjectIDNestedListMarshal(splitHdrChildrenField, buf[offset:], h.children) + proto.BytesMarshal(splitHdrSplitIDField, buf[offset:], h.splitID) + + return buf +} + +func (h *SplitHeader) StableSize() (size int) { + if h == nil { + return 0 + } + + size += proto.NestedStructureSize(splitHdrParentField, h.par) + size += proto.NestedStructureSize(splitHdrPreviousField, h.prev) + size += proto.NestedStructureSize(splitHdrParentSignatureField, h.parSig) + size += proto.NestedStructureSize(splitHdrParentHeaderField, h.parHdr) + size += refs.ObjectIDNestedListSize(splitHdrChildrenField, h.children) + size += proto.BytesSize(splitHdrSplitIDField, h.splitID) + + return size +} + +func (h *SplitHeader) Unmarshal(data []byte) error { + return message.Unmarshal(h, data, new(object.Header_Split)) +} + +func (h *ECHeader) StableMarshal(buf []byte) []byte { + if h == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, h.StableSize()) + } + + var offset int + + offset += proto.NestedStructureMarshal(ecHdrParentField, buf[offset:], h.Parent) + offset += proto.UInt32Marshal(ecHdrIndexField, buf[offset:], h.Index) + offset += proto.UInt32Marshal(ecHdrTotalField, buf[offset:], h.Total) + offset += proto.UInt32Marshal(ecHdrHeaderLengthField, buf[offset:], h.HeaderLength) + proto.BytesMarshal(ecHdrHeaderField, buf[offset:], h.Header) + return buf +} + +func (h *ECHeader) StableSize() (size int) { + if h == nil { + return 0 + } + + size += proto.NestedStructureSize(ecHdrParentField, h.Parent) + size += proto.UInt32Size(ecHdrIndexField, h.Index) + size += proto.UInt32Size(ecHdrTotalField, h.Total) + size += proto.UInt32Size(ecHdrHeaderLengthField, h.HeaderLength) + size += proto.BytesSize(ecHdrHeaderField, h.Header) + + return size +} + +func (h *ECHeader) Unmarshal(data []byte) error { + return message.Unmarshal(h, data, new(object.Header_EC)) +} + +func (h *Header) StableMarshal(buf []byte) []byte { + if h == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, h.StableSize()) + } + + var offset int + + offset += proto.NestedStructureMarshal(hdrVersionField, buf[offset:], h.version) + offset += proto.NestedStructureMarshal(hdrContainerIDField, buf[offset:], h.cid) + offset += proto.NestedStructureMarshal(hdrOwnerIDField, buf[offset:], h.ownerID) + offset += proto.UInt64Marshal(hdrEpochField, buf[offset:], h.creatEpoch) + offset += proto.UInt64Marshal(hdrPayloadLengthField, buf[offset:], h.payloadLen) + offset += proto.NestedStructureMarshal(hdrPayloadHashField, buf[offset:], h.payloadHash) + offset += proto.EnumMarshal(hdrObjectTypeField, buf[offset:], int32(h.typ)) + offset += proto.NestedStructureMarshal(hdrHomomorphicHashField, buf[offset:], h.homoHash) + offset += proto.NestedStructureMarshal(hdrSessionTokenField, buf[offset:], h.sessionToken) + + for i := range h.attr { + offset += proto.NestedStructureMarshal(hdrAttributesField, buf[offset:], &h.attr[i]) + } + + proto.NestedStructureMarshal(hdrSplitField, buf[offset:], h.split) + proto.NestedStructureMarshal(hdrECField, buf[offset:], h.ec) + + return buf +} + +func (h *Header) StableSize() (size int) { + if h == nil { + return 0 + } + + size += proto.NestedStructureSize(hdrVersionField, h.version) + size += proto.NestedStructureSize(hdrContainerIDField, h.cid) + size += proto.NestedStructureSize(hdrOwnerIDField, h.ownerID) + size += proto.UInt64Size(hdrEpochField, h.creatEpoch) + size += proto.UInt64Size(hdrPayloadLengthField, h.payloadLen) + size += proto.NestedStructureSize(hdrPayloadHashField, h.payloadHash) + size += proto.EnumSize(hdrObjectTypeField, int32(h.typ)) + size += proto.NestedStructureSize(hdrHomomorphicHashField, h.homoHash) + size += proto.NestedStructureSize(hdrSessionTokenField, h.sessionToken) + for i := range h.attr { + size += proto.NestedStructureSize(hdrAttributesField, &h.attr[i]) + } + size += proto.NestedStructureSize(hdrSplitField, h.split) + size += proto.NestedStructureSize(hdrECField, h.ec) + + return size +} + +func (h *Header) Unmarshal(data []byte) error { + return message.Unmarshal(h, data, new(object.Header)) +} + +func (h *HeaderWithSignature) StableMarshal(buf []byte) []byte { + if h == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, h.StableSize()) + } + + var offset int + + offset += proto.NestedStructureMarshal(hdrWithSigHeaderField, buf[offset:], h.header) + proto.NestedStructureMarshal(hdrWithSigSignatureField, buf[offset:], h.signature) + + return buf +} + +func (h *HeaderWithSignature) StableSize() (size int) { + if h == nil { + return 0 + } + + size += proto.NestedStructureSize(hdrVersionField, h.header) + size += proto.NestedStructureSize(hdrContainerIDField, h.signature) + + return size +} + +func (h *HeaderWithSignature) Unmarshal(data []byte) error { + return message.Unmarshal(h, data, new(object.HeaderWithSignature)) +} + +func (o *Object) StableMarshal(buf []byte) []byte { + if o == nil { + return []byte{} + } + + if o.marshalData != nil { + if buf == nil { + return o.marshalData + } + copy(buf, o.marshalData) + return buf + } + + if buf == nil { + buf = make([]byte, o.StableSize()) + } + + var offset int + + offset += proto.NestedStructureMarshal(objIDField, buf[offset:], o.objectID) + offset += proto.NestedStructureMarshal(objSignatureField, buf[offset:], o.idSig) + offset += proto.NestedStructureMarshal(objHeaderField, buf[offset:], o.header) + proto.BytesMarshal(objPayloadField, buf[offset:], o.payload) + + return buf +} + +// SetMarshalData sets marshal data to reduce memory allocations. +// +// It is unsafe to modify/copy object data after setting marshal data. +func (o *Object) SetMarshalData(data []byte) { + if o == nil { + return + } + o.marshalData = data +} + +func (o *Object) StableSize() (size int) { + if o == nil { + return 0 + } + + size += proto.NestedStructureSize(objIDField, o.objectID) + size += proto.NestedStructureSize(objSignatureField, o.idSig) + size += proto.NestedStructureSize(objHeaderField, o.header) + size += proto.BytesSize(objPayloadField, o.payload) + + return size +} + +func (o *Object) Unmarshal(data []byte) error { + return message.Unmarshal(o, data, new(object.Object)) +} + +func (s *SplitInfo) StableMarshal(buf []byte) []byte { + if s == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, s.StableSize()) + } + + var offset int + + offset += proto.BytesMarshal(splitInfoSplitIDField, buf[offset:], s.splitID) + offset += proto.NestedStructureMarshal(splitInfoLastPartField, buf[offset:], s.lastPart) + proto.NestedStructureMarshal(splitInfoLinkField, buf[offset:], s.link) + + return buf +} + +func (s *SplitInfo) StableSize() (size int) { + if s == nil { + return 0 + } + + size += proto.BytesSize(splitInfoSplitIDField, s.splitID) + size += proto.NestedStructureSize(splitInfoLastPartField, s.lastPart) + size += proto.NestedStructureSize(splitInfoLinkField, s.link) + + return size +} + +func (s *SplitInfo) Unmarshal(data []byte) error { + return message.Unmarshal(s, data, new(object.SplitInfo)) +} + +func (r *GetRequestBody) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + var offset int + + offset += proto.NestedStructureMarshal(getReqBodyAddressField, buf[offset:], r.addr) + proto.BoolMarshal(getReqBodyRawFlagField, buf[offset:], r.raw) + + return buf +} + +func (r *GetRequestBody) StableSize() (size int) { + if r == nil { + return 0 + } + + size += proto.NestedStructureSize(getReqBodyAddressField, r.addr) + size += proto.BoolSize(getReqBodyRawFlagField, r.raw) + + return size +} + +func (r *GetRequestBody) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(object.GetRequest_Body)) +} + +func (r *GetObjectPartInit) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + var offset int + + offset += proto.NestedStructureMarshal(getRespInitObjectIDField, buf[offset:], r.id) + offset += proto.NestedStructureMarshal(getRespInitSignatureField, buf[offset:], r.sig) + proto.NestedStructureMarshal(getRespInitHeaderField, buf[offset:], r.hdr) + + return buf +} + +func (r *GetObjectPartInit) StableSize() (size int) { + if r == nil { + return 0 + } + + size += proto.NestedStructureSize(getRespInitObjectIDField, r.id) + size += proto.NestedStructureSize(getRespInitSignatureField, r.sig) + size += proto.NestedStructureSize(getRespInitHeaderField, r.hdr) + + return size +} + +func (r *GetObjectPartInit) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(object.GetResponse_Body_Init)) +} + +func (r *GetResponseBody) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + switch v := r.objPart.(type) { + case nil: + case *GetObjectPartInit: + proto.NestedStructureMarshal(getRespBodyInitField, buf, v) + case *GetObjectPartChunk: + if v != nil { + proto.BytesMarshal(getRespBodyChunkField, buf, v.chunk) + } + case *SplitInfo: + proto.NestedStructureMarshal(getRespBodySplitInfoField, buf, v) + default: + panic("unknown one of object get response body type") + } + + return buf +} + +func (r *GetResponseBody) StableSize() (size int) { + if r == nil { + return 0 + } + + switch v := r.objPart.(type) { + case nil: + case *GetObjectPartInit: + size += proto.NestedStructureSize(getRespBodyInitField, v) + case *GetObjectPartChunk: + if v != nil { + size += proto.BytesSize(getRespBodyChunkField, v.chunk) + } + case *SplitInfo: + size += proto.NestedStructureSize(getRespBodySplitInfoField, v) + default: + panic("unknown one of object get response body type") + } + + return +} + +func (r *GetResponseBody) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(object.GetResponse_Body)) +} + +func (r *PutObjectPartInit) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + var offset int + + offset += proto.NestedStructureMarshal(putReqInitObjectIDField, buf[offset:], r.id) + offset += proto.NestedStructureMarshal(putReqInitSignatureField, buf[offset:], r.sig) + offset += proto.NestedStructureMarshal(putReqInitHeaderField, buf[offset:], r.hdr) + proto.RepeatedUInt32Marshal(putReqInitCopiesNumField, buf[offset:], r.copyNum) + + return buf +} + +func (r *PutObjectPartInit) StableSize() (size int) { + if r == nil { + return 0 + } + + size += proto.NestedStructureSize(putReqInitObjectIDField, r.id) + size += proto.NestedStructureSize(putReqInitSignatureField, r.sig) + size += proto.NestedStructureSize(putReqInitHeaderField, r.hdr) + + arrSize, _ := proto.RepeatedUInt32Size(putReqInitCopiesNumField, r.copyNum) + size += arrSize + + return size +} + +func (r *PutObjectPartInit) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(object.PutRequest_Body_Init)) +} + +func (r *PutRequestBody) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + switch v := r.objPart.(type) { + case nil: + case *PutObjectPartInit: + proto.NestedStructureMarshal(putReqBodyInitField, buf, v) + case *PutObjectPartChunk: + if v != nil { + proto.BytesMarshal(putReqBodyChunkField, buf, v.chunk) + } + default: + panic("unknown one of object put request body type") + } + + return buf +} + +func (r *PutRequestBody) StableSize() (size int) { + if r == nil { + return 0 + } + + switch v := r.objPart.(type) { + case nil: + case *PutObjectPartInit: + size += proto.NestedStructureSize(putReqBodyInitField, v) + case *PutObjectPartChunk: + if v != nil { + size += proto.BytesSize(putReqBodyChunkField, v.chunk) + } + default: + panic("unknown one of object get response body type") + } + + return size +} + +func (r *PutRequestBody) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(object.PutRequest_Body)) +} + +func (r *PutResponseBody) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + proto.NestedStructureMarshal(putRespBodyObjectIDField, buf, r.id) + + return buf +} + +func (r *PutResponseBody) StableSize() (size int) { + if r == nil { + return 0 + } + + size += proto.NestedStructureSize(putRespBodyObjectIDField, r.id) + + return size +} + +func (r *PutResponseBody) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(object.PutResponse_Body)) +} + +func (r *DeleteRequestBody) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + proto.NestedStructureMarshal(deleteReqBodyAddressField, buf, r.addr) + + return buf +} + +func (r *DeleteRequestBody) StableSize() (size int) { + if r == nil { + return 0 + } + + size += proto.NestedStructureSize(deleteReqBodyAddressField, r.addr) + + return size +} + +func (r *DeleteRequestBody) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(object.DeleteRequest_Body)) +} + +func (r *DeleteResponseBody) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + proto.NestedStructureMarshal(deleteRespBodyTombstoneFNum, buf, r.tombstone) + + return buf +} + +func (r *DeleteResponseBody) StableSize() (size int) { + if r == nil { + return 0 + } + + size += proto.NestedStructureSize(deleteRespBodyTombstoneFNum, r.tombstone) + + return size +} + +func (r *DeleteResponseBody) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(object.DeleteResponse_Body)) +} + +func (r *HeadRequestBody) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + var offset int + + offset += proto.NestedStructureMarshal(headReqBodyAddressField, buf[offset:], r.addr) + offset += proto.BoolMarshal(headReqBodyMainFlagField, buf[offset:], r.mainOnly) + proto.BoolMarshal(headReqBodyRawFlagField, buf[offset:], r.raw) + + return buf +} + +func (r *HeadRequestBody) StableSize() (size int) { + if r == nil { + return 0 + } + + size += proto.NestedStructureSize(headReqBodyAddressField, r.addr) + size += proto.BoolSize(headReqBodyMainFlagField, r.mainOnly) + size += proto.BoolSize(headReqBodyRawFlagField, r.raw) + + return size +} + +func (r *HeadRequestBody) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(object.HeadRequest_Body)) +} + +func (r *HeadResponseBody) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + switch v := r.hdrPart.(type) { + case nil: + case *HeaderWithSignature: + if v != nil { + proto.NestedStructureMarshal(headRespBodyHeaderField, buf, v) + } + case *ShortHeader: + if v != nil { + proto.NestedStructureMarshal(headRespBodyShortHeaderField, buf, v) + } + case *SplitInfo: + if v != nil { + proto.NestedStructureMarshal(headRespBodySplitInfoField, buf, v) + } + default: + panic("unknown one of object put request body type") + } + + return buf +} + +func (r *HeadResponseBody) StableSize() (size int) { + if r == nil { + return 0 + } + + switch v := r.hdrPart.(type) { + case nil: + case *HeaderWithSignature: + if v != nil { + size += proto.NestedStructureSize(headRespBodyHeaderField, v) + } + case *ShortHeader: + if v != nil { + size += proto.NestedStructureSize(headRespBodyShortHeaderField, v) + } + case *SplitInfo: + if v != nil { + size += proto.NestedStructureSize(headRespBodySplitInfoField, v) + } + default: + panic("unknown one of object put request body type") + } + + return +} + +func (r *HeadResponseBody) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(object.HeadResponse_Body)) +} + +func (f *SearchFilter) StableMarshal(buf []byte) []byte { + if f == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, f.StableSize()) + } + + var offset int + + offset += proto.EnumMarshal(searchFilterMatchField, buf[offset:], int32(f.matchType)) + offset += proto.StringMarshal(searchFilterNameField, buf[offset:], f.key) + proto.StringMarshal(searchFilterValueField, buf[offset:], f.val) + + return buf +} + +func (f *SearchFilter) StableSize() (size int) { + if f == nil { + return 0 + } + + size += proto.EnumSize(searchFilterMatchField, int32(f.matchType)) + size += proto.StringSize(searchFilterNameField, f.key) + size += proto.StringSize(searchFilterValueField, f.val) + + return size +} + +func (f *SearchFilter) Unmarshal(data []byte) error { + return message.Unmarshal(f, data, new(object.SearchRequest_Body_Filter)) +} + +func (r *SearchRequestBody) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + var offset int + + offset += proto.NestedStructureMarshal(searchReqBodyContainerIDField, buf[offset:], r.cid) + offset += proto.UInt32Marshal(searchReqBodyVersionField, buf[offset:], r.version) + + for i := range r.filters { + offset += proto.NestedStructureMarshal(searchReqBodyFiltersField, buf[offset:], &r.filters[i]) + } + + return buf +} + +func (r *SearchRequestBody) StableSize() (size int) { + if r == nil { + return 0 + } + + size += proto.NestedStructureSize(searchReqBodyContainerIDField, r.cid) + size += proto.UInt32Size(searchReqBodyVersionField, r.version) + + for i := range r.filters { + size += proto.NestedStructureSize(searchReqBodyFiltersField, &r.filters[i]) + } + + return size +} + +func (r *SearchRequestBody) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(object.SearchRequest_Body)) +} + +func (r *SearchResponseBody) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + var offset int + + refs.ObjectIDNestedListMarshal(searchRespBodyObjectIDsField, buf[offset:], r.idList) + + return buf +} + +func (r *SearchResponseBody) StableSize() (size int) { + if r == nil { + return 0 + } + + size += refs.ObjectIDNestedListSize(searchRespBodyObjectIDsField, r.idList) + + return size +} + +func (r *SearchResponseBody) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(object.SearchResponse_Body)) +} + +func (r *Range) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + var offset int + + offset += proto.UInt64Marshal(rangeOffsetField, buf[offset:], r.off) + proto.UInt64Marshal(rangeLengthField, buf[offset:], r.len) + + return buf +} + +func (r *Range) StableSize() (size int) { + if r == nil { + return 0 + } + + size += proto.UInt64Size(rangeOffsetField, r.off) + size += proto.UInt64Size(rangeLengthField, r.len) + + return size +} + +func (r *Range) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(object.Range)) +} + +func (r *GetRangeRequestBody) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + var offset int + + offset += proto.NestedStructureMarshal(getRangeReqBodyAddressField, buf[offset:], r.addr) + offset += proto.NestedStructureMarshal(getRangeReqBodyRangeField, buf[offset:], r.rng) + proto.BoolMarshal(getRangeReqBodyRawField, buf[offset:], r.raw) + + return buf +} + +func (r *GetRangeRequestBody) StableSize() (size int) { + if r == nil { + return 0 + } + + size += proto.NestedStructureSize(getRangeReqBodyAddressField, r.addr) + size += proto.NestedStructureSize(getRangeReqBodyRangeField, r.rng) + size += proto.BoolSize(getRangeReqBodyRawField, r.raw) + + return size +} + +func (r *GetRangeRequestBody) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(object.GetRangeRequest_Body)) +} + +func (r *GetRangeResponseBody) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + switch v := r.rngPart.(type) { + case nil: + case *GetRangePartChunk: + if v != nil { + proto.BytesMarshal(getRangeRespChunkField, buf, v.chunk) + } + case *SplitInfo: + if v != nil { + proto.NestedStructureMarshal(getRangeRespSplitInfoField, buf, v) + } + default: + panic("unknown one of object get range request body type") + } + + return buf +} + +func (r *GetRangeResponseBody) StableSize() (size int) { + if r == nil { + return 0 + } + + switch v := r.rngPart.(type) { + case nil: + case *GetRangePartChunk: + if v != nil { + size += proto.BytesSize(getRangeRespChunkField, v.chunk) + } + case *SplitInfo: + if v != nil { + size = proto.NestedStructureSize(getRangeRespSplitInfoField, v) + } + default: + panic("unknown one of object get range request body type") + } + + return +} + +func (r *GetRangeResponseBody) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(object.GetRangeResponse_Body)) +} + +func (r *GetRangeHashRequestBody) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + var offset int + + offset += proto.NestedStructureMarshal(getRangeHashReqBodyAddressField, buf[offset:], r.addr) + + for i := range r.rngs { + offset += proto.NestedStructureMarshal(getRangeHashReqBodyRangesField, buf[offset:], &r.rngs[i]) + } + + offset += proto.BytesMarshal(getRangeHashReqBodySaltField, buf[offset:], r.salt) + proto.EnumMarshal(getRangeHashReqBodyTypeField, buf[offset:], int32(r.typ)) + + return buf +} + +func (r *GetRangeHashRequestBody) StableSize() (size int) { + if r == nil { + return 0 + } + + size += proto.NestedStructureSize(getRangeHashReqBodyAddressField, r.addr) + + for i := range r.rngs { + size += proto.NestedStructureSize(getRangeHashReqBodyRangesField, &r.rngs[i]) + } + + size += proto.BytesSize(getRangeHashReqBodySaltField, r.salt) + size += proto.EnumSize(getRangeHashReqBodyTypeField, int32(r.typ)) + + return size +} + +func (r *GetRangeHashRequestBody) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(object.GetRangeHashRequest_Body)) +} + +func (r *GetRangeHashResponseBody) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + var offset int + + offset += proto.EnumMarshal(getRangeHashRespBodyTypeField, buf, int32(r.typ)) + proto.RepeatedBytesMarshal(getRangeHashRespBodyHashListField, buf[offset:], r.hashList) + + return buf +} + +func (r *GetRangeHashResponseBody) StableSize() (size int) { + if r == nil { + return 0 + } + + size += proto.EnumSize(getRangeHashRespBodyTypeField, int32(r.typ)) + size += proto.RepeatedBytesSize(getRangeHashRespBodyHashListField, r.hashList) + + return size +} + +func (r *GetRangeHashResponseBody) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(object.GetRangeHashResponse_Body)) +} + +func (r *PutSingleRequestBody) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if r.marshalData != nil { + if buf == nil { + return r.marshalData + } + copy(buf, r.marshalData) + return buf + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + var offset int + offset += proto.NestedStructureMarshal(putSingleReqObjectField, buf[offset:], r.object) + proto.RepeatedUInt32Marshal(putSingleReqCopiesNumberField, buf[offset:], r.copyNum) + + return buf +} + +// SetMarshalData sets marshal data to reduce memory allocations. +// +// It is unsafe to modify/copy request data after setting marshal data. +func (r *PutSingleRequestBody) SetMarshalData(data []byte) { + if r == nil { + return + } + + r.marshalData = data + + proto.NestedStructureSetMarshalData(putSingleReqObjectField, r.marshalData, r.object) +} + +func (r *PutSingleRequestBody) StableSize() int { + if r == nil { + return 0 + } + + var size int + size += proto.NestedStructureSize(putSingleReqObjectField, r.object) + arrSize, _ := proto.RepeatedUInt32Size(putSingleReqCopiesNumberField, r.copyNum) + size += arrSize + + return size +} + +func (r *PutSingleRequestBody) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(object.PutSingleRequest_Body)) +} + +func (r *PutSingleResponseBody) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + return buf +} + +func (r *PutSingleResponseBody) StableSize() int { + return 0 +} + +func (r *PutSingleResponseBody) Unmarshal(data []byte) error { + return message.Unmarshal(r, data, new(object.PutSingleResponse_Body)) +} diff --git a/pkg/api/object/message_test.go b/pkg/api/object/message_test.go new file mode 100644 index 000000000..232342268 --- /dev/null +++ b/pkg/api/object/message_test.go @@ -0,0 +1,58 @@ +package object_test + +import ( + "testing" + + objecttest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object/test" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/message" + messagetest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/message/test" +) + +func TestMessageConvert(t *testing.T) { + messagetest.TestRPCMessage(t, + func(empty bool) message.Message { return objecttest.GenerateShortHeader(empty) }, + func(empty bool) message.Message { return objecttest.GenerateAttribute(empty) }, + func(empty bool) message.Message { return objecttest.GenerateSplitHeader(empty) }, + func(empty bool) message.Message { return objecttest.GenerateHeader(empty) }, + func(empty bool) message.Message { return objecttest.GenerateObject(empty) }, + func(empty bool) message.Message { return objecttest.GenerateSplitInfo(empty) }, + func(empty bool) message.Message { return objecttest.GenerateECInfo(empty) }, + func(empty bool) message.Message { return objecttest.GenerateGetRequestBody(empty) }, + func(empty bool) message.Message { return objecttest.GenerateGetRequest(empty) }, + func(empty bool) message.Message { return objecttest.GenerateGetObjectPartInit(empty) }, + func(empty bool) message.Message { return objecttest.GenerateGetObjectPartChunk(empty) }, + func(empty bool) message.Message { return objecttest.GenerateGetResponseBody(empty) }, + func(empty bool) message.Message { return objecttest.GenerateGetResponse(empty) }, + func(empty bool) message.Message { return objecttest.GeneratePutObjectPartInit(empty) }, + func(empty bool) message.Message { return objecttest.GeneratePutObjectPartChunk(empty) }, + func(empty bool) message.Message { return objecttest.GeneratePutRequestBody(empty) }, + func(empty bool) message.Message { return objecttest.GeneratePutRequest(empty) }, + func(empty bool) message.Message { return objecttest.GeneratePutResponseBody(empty) }, + func(empty bool) message.Message { return objecttest.GeneratePutResponse(empty) }, + func(empty bool) message.Message { return objecttest.GenerateDeleteRequestBody(empty) }, + func(empty bool) message.Message { return objecttest.GenerateDeleteRequest(empty) }, + func(empty bool) message.Message { return objecttest.GenerateDeleteResponseBody(empty) }, + func(empty bool) message.Message { return objecttest.GenerateDeleteResponse(empty) }, + func(empty bool) message.Message { return objecttest.GenerateHeadRequestBody(empty) }, + func(empty bool) message.Message { return objecttest.GenerateHeadRequest(empty) }, + func(empty bool) message.Message { return objecttest.GenerateHeadResponseBody(empty) }, + func(empty bool) message.Message { return objecttest.GenerateHeadResponse(empty) }, + func(empty bool) message.Message { return objecttest.GenerateSearchFilter(empty) }, + func(empty bool) message.Message { return objecttest.GenerateSearchRequestBody(empty) }, + func(empty bool) message.Message { return objecttest.GenerateSearchRequest(empty) }, + func(empty bool) message.Message { return objecttest.GenerateSearchResponseBody(empty) }, + func(empty bool) message.Message { return objecttest.GenerateSearchResponse(empty) }, + func(empty bool) message.Message { return objecttest.GenerateRange(empty) }, + func(empty bool) message.Message { return objecttest.GenerateGetRangeRequestBody(empty) }, + func(empty bool) message.Message { return objecttest.GenerateGetRangeRequest(empty) }, + func(empty bool) message.Message { return objecttest.GenerateGetRangeResponseBody(empty) }, + func(empty bool) message.Message { return objecttest.GenerateGetRangeResponse(empty) }, + func(empty bool) message.Message { return objecttest.GenerateGetRangeHashRequestBody(empty) }, + func(empty bool) message.Message { return objecttest.GenerateGetRangeHashRequest(empty) }, + func(empty bool) message.Message { return objecttest.GenerateGetRangeHashResponseBody(empty) }, + func(empty bool) message.Message { return objecttest.GenerateGetRangeHashResponse(empty) }, + func(empty bool) message.Message { return objecttest.GenerateLock(empty) }, + func(empty bool) message.Message { return objecttest.GeneratePutSingleRequest(empty) }, + func(empty bool) message.Message { return objecttest.GeneratePutSingleResponse(empty) }, + ) +} diff --git a/pkg/api/object/status.go b/pkg/api/object/status.go new file mode 100644 index 000000000..728fa0537 --- /dev/null +++ b/pkg/api/object/status.go @@ -0,0 +1,91 @@ +package object + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/status" + statusgrpc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/status/grpc" +) + +// LocalizeFailStatus checks if passed global status.Code is related to object failure and: +// +// then localizes the code and returns true, +// else leaves the code unchanged and returns false. +// +// Arg must not be nil. +func LocalizeFailStatus(c *status.Code) bool { + return status.LocalizeIfInSection(c, uint32(statusgrpc.Section_SECTION_OBJECT)) +} + +// GlobalizeFail globalizes local code of object failure. +// +// Arg must not be nil. +func GlobalizeFail(c *status.Code) { + c.GlobalizeSection(uint32(statusgrpc.Section_SECTION_OBJECT)) +} + +const ( + // StatusAccessDenied is a local status.Code value for + // ACCESS_DENIED object failure. + StatusAccessDenied status.Code = iota + // StatusNotFound is a local status.Code value for + // OBJECT_NOT_FOUND object failure. + StatusNotFound + // StatusLocked is a local status.Code value for + // LOCKED object failure. + StatusLocked + // StatusLockNonRegularObject is a local status.Code value for + // LOCK_NON_REGULAR_OBJECT object failure. + StatusLockNonRegularObject + // StatusAlreadyRemoved is a local status.Code value for + // OBJECT_ALREADY_REMOVED object failure. + StatusAlreadyRemoved + // StatusOutOfRange is a local status.Code value for + // OUT_OF_RANGE object failure. + StatusOutOfRange +) + +const ( + // detailAccessDeniedDesc is a StatusAccessDenied detail ID for + // human-readable description. + detailAccessDeniedDesc = iota +) + +// WriteAccessDeniedDesc writes human-readable description of StatusAccessDenied +// into status.Status as a detail. The status must not be nil. +// +// Existing details are expected to be ID-unique, otherwise undefined behavior. +func WriteAccessDeniedDesc(st *status.Status, desc string) { + var found bool + + st.IterateDetails(func(d *status.Detail) bool { + if d.ID() == detailAccessDeniedDesc { + found = true + d.SetValue([]byte(desc)) + } + + return found + }) + + if !found { + var d status.Detail + + d.SetID(detailAccessDeniedDesc) + d.SetValue([]byte(desc)) + + st.AppendDetails(d) + } +} + +// ReadAccessDeniedDesc looks up for status detail with human-readable description +// of StatusAccessDenied. Returns empty string if detail is missing. +func ReadAccessDeniedDesc(st status.Status) (desc string) { + st.IterateDetails(func(d *status.Detail) bool { + if d.ID() == detailAccessDeniedDesc { + desc = string(d.Value()) + return true + } + + return false + }) + + return +} diff --git a/pkg/api/object/status_test.go b/pkg/api/object/status_test.go new file mode 100644 index 000000000..60a2ccbd2 --- /dev/null +++ b/pkg/api/object/status_test.go @@ -0,0 +1,35 @@ +package object_test + +import ( + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/status" + statustest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/status/test" + "github.com/stretchr/testify/require" +) + +func TestStatusCodes(t *testing.T) { + statustest.TestCodes(t, object.LocalizeFailStatus, object.GlobalizeFail, + object.StatusAccessDenied, 2048, + object.StatusNotFound, 2049, + object.StatusLocked, 2050, + object.StatusLockNonRegularObject, 2051, + object.StatusAlreadyRemoved, 2052, + object.StatusOutOfRange, 2053, + ) +} + +func TestAccessDeniedDesc(t *testing.T) { + var st status.Status + + require.Empty(t, object.ReadAccessDeniedDesc(st)) + + const desc = "some description" + + object.WriteAccessDeniedDesc(&st, desc) + require.Equal(t, desc, object.ReadAccessDeniedDesc(st)) + + object.WriteAccessDeniedDesc(&st, desc+"1") + require.Equal(t, desc+"1", object.ReadAccessDeniedDesc(st)) +} diff --git a/pkg/api/object/string.go b/pkg/api/object/string.go new file mode 100644 index 000000000..f2466a197 --- /dev/null +++ b/pkg/api/object/string.go @@ -0,0 +1,55 @@ +package object + +import ( + object "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object/grpc" +) + +// String returns string representation of Type. +func (t Type) String() string { + return TypeToGRPCField(t).String() +} + +// FromString parses Type from a string representation. +// It is a reverse action to String(). +// +// Returns true if s was parsed successfully. +func (t *Type) FromString(s string) bool { + var g object.ObjectType + + ok := g.FromString(s) + + if ok { + *t = TypeFromGRPCField(g) + } + + return ok +} + +// TypeFromString converts string to Type. +// +// Deprecated: use FromString method. +func TypeFromString(s string) (t Type) { + t.FromString(s) + return +} + +// String returns string representation of MatchType. +func (t MatchType) String() string { + return MatchTypeToGRPCField(t).String() +} + +// FromString parses MatchType from a string representation. +// It is a reverse action to String(). +// +// Returns true if s was parsed successfully. +func (t *MatchType) FromString(s string) bool { + var g object.MatchType + + ok := g.FromString(s) + + if ok { + *t = MatchTypeFromGRPCField(g) + } + + return ok +} diff --git a/pkg/api/object/test/generate.go b/pkg/api/object/test/generate.go new file mode 100644 index 000000000..1ef1d108e --- /dev/null +++ b/pkg/api/object/test/generate.go @@ -0,0 +1,675 @@ +package objecttest + +import ( + "math/rand" + "time" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + refstest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs/test" + sessiontest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session/test" +) + +func GenerateShortHeader(empty bool) *object.ShortHeader { + m := new(object.ShortHeader) + + if !empty { + m.SetObjectType(13) + m.SetCreationEpoch(100) + m.SetPayloadLength(12321) + m.SetOwnerID(refstest.GenerateOwnerID(false)) + } + + m.SetVersion(refstest.GenerateVersion(empty)) + m.SetHomomorphicHash(refstest.GenerateChecksum(empty)) + m.SetPayloadHash(refstest.GenerateChecksum(empty)) + + return m +} + +func GenerateAttribute(empty bool) *object.Attribute { + m := new(object.Attribute) + + if !empty { + m.SetKey("object key") + m.SetValue("object value") + } + + return m +} + +func GenerateAttributes(empty bool) []object.Attribute { + var res []object.Attribute + + if !empty { + res = append(res, + *GenerateAttribute(false), + *GenerateAttribute(false), + ) + } + + return res +} + +func GenerateSplitHeader(empty bool) *object.SplitHeader { + return generateSplitHeader(empty, true) +} + +func generateSplitHeader(empty, withPar bool) *object.SplitHeader { + m := new(object.SplitHeader) + + if !empty { + m.SetSplitID([]byte{1, 3, 5}) + m.SetParent(refstest.GenerateObjectID(false)) + m.SetPrevious(refstest.GenerateObjectID(false)) + m.SetChildren(refstest.GenerateObjectIDs(false)) + } + + m.SetParentSignature(refstest.GenerateSignature(empty)) + + if withPar { + m.SetParentHeader(generateHeader(empty, false)) + } + + return m +} + +func GenerateHeader(empty bool) *object.Header { + return generateHeader(empty, true) +} + +func generateHeader(empty, withSplit bool) *object.Header { + m := new(object.Header) + + if !empty { + m.SetPayloadLength(777) + m.SetCreationEpoch(432) + m.SetObjectType(111) + m.SetOwnerID(refstest.GenerateOwnerID(false)) + m.SetContainerID(refstest.GenerateContainerID(false)) + m.SetAttributes(GenerateAttributes(false)) + } + + m.SetVersion(refstest.GenerateVersion(empty)) + m.SetPayloadHash(refstest.GenerateChecksum(empty)) + m.SetHomomorphicHash(refstest.GenerateChecksum(empty)) + m.SetSessionToken(sessiontest.GenerateSessionToken(empty)) + + if withSplit { + m.SetSplit(generateSplitHeader(empty, false)) + } + + return m +} + +func GenerateHeaderWithSignature(empty bool) *object.HeaderWithSignature { + m := new(object.HeaderWithSignature) + + m.SetSignature(refstest.GenerateSignature(empty)) + m.SetHeader(GenerateHeader(empty)) + + return m +} + +func GenerateObject(empty bool) *object.Object { + m := new(object.Object) + + if !empty { + m.SetPayload([]byte{7, 8, 9}) + m.SetObjectID(refstest.GenerateObjectID(false)) + } + + m.SetSignature(refstest.GenerateSignature(empty)) + m.SetHeader(GenerateHeader(empty)) + + return m +} + +func GenerateSplitInfo(empty bool) *object.SplitInfo { + m := new(object.SplitInfo) + + if !empty { + m.SetSplitID([]byte("splitID")) + m.SetLastPart(refstest.GenerateObjectID(false)) + m.SetLink(refstest.GenerateObjectID(false)) + } + + return m +} + +func GenerateECInfo(empty bool) *object.ECInfo { + m := new(object.ECInfo) + + if !empty { + m.Chunks = make([]object.ECChunk, 2) + for i := range m.Chunks { + m.Chunks[i] = *GenerateECChunk(false) + } + } + + return m +} + +func GenerateECChunk(empty bool) *object.ECChunk { + m := new(object.ECChunk) + + if !empty { + m.ID = *refstest.GenerateObjectID(false) + m.Index = 4 + m.Total = 7 + } + + return m +} + +func GenerateGetRequestBody(empty bool) *object.GetRequestBody { + m := new(object.GetRequestBody) + + if !empty { + m.SetRaw(true) + m.SetAddress(refstest.GenerateAddress(false)) + } + + return m +} + +func GenerateGetRequest(empty bool) *object.GetRequest { + m := new(object.GetRequest) + + if !empty { + m.SetBody(GenerateGetRequestBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateRequestMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateRequestVerificationHeader(empty)) + + return m +} + +func GenerateGetObjectPartInit(empty bool) *object.GetObjectPartInit { + m := new(object.GetObjectPartInit) + + if !empty { + m.SetObjectID(refstest.GenerateObjectID(false)) + } + + m.SetSignature(refstest.GenerateSignature(empty)) + m.SetHeader(GenerateHeader(empty)) + + return m +} + +func GenerateGetObjectPartChunk(empty bool) *object.GetObjectPartChunk { + m := new(object.GetObjectPartChunk) + + if !empty { + m.SetChunk([]byte("get chunk")) + } + + return m +} + +func GenerateGetResponseBody(empty bool) *object.GetResponseBody { + m := new(object.GetResponseBody) + + if !empty { + switch randomInt(3) { + case 0: + m.SetObjectPart(GenerateGetObjectPartInit(false)) + case 1: + m.SetObjectPart(GenerateGetObjectPartChunk(false)) + case 2: + m.SetObjectPart(GenerateSplitInfo(false)) + } + } + + return m +} + +func GenerateGetResponse(empty bool) *object.GetResponse { + m := new(object.GetResponse) + + if !empty { + m.SetBody(GenerateGetResponseBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateResponseMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateResponseVerificationHeader(empty)) + + return m +} + +func GeneratePutObjectPartInit(empty bool) *object.PutObjectPartInit { + m := new(object.PutObjectPartInit) + + if !empty { + m.SetCopiesNumber([]uint32{234}) + m.SetObjectID(refstest.GenerateObjectID(false)) + } + + m.SetSignature(refstest.GenerateSignature(empty)) + m.SetHeader(GenerateHeader(empty)) + + return m +} + +func GeneratePutObjectPartChunk(empty bool) *object.PutObjectPartChunk { + m := new(object.PutObjectPartChunk) + + if !empty { + m.SetChunk([]byte("put chunk")) + } + + return m +} + +func GeneratePutRequestBody(empty bool) *object.PutRequestBody { + m := new(object.PutRequestBody) + + if !empty { + switch randomInt(2) { + case 0: + m.SetObjectPart(GeneratePutObjectPartInit(false)) + case 1: + m.SetObjectPart(GeneratePutObjectPartChunk(false)) + } + } + + return m +} + +func GeneratePutRequest(empty bool) *object.PutRequest { + m := new(object.PutRequest) + + if !empty { + m.SetBody(GeneratePutRequestBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateRequestMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateRequestVerificationHeader(empty)) + + return m +} + +func GeneratePutResponseBody(empty bool) *object.PutResponseBody { + m := new(object.PutResponseBody) + + if !empty { + m.SetObjectID(refstest.GenerateObjectID(false)) + } + + return m +} + +func GeneratePutResponse(empty bool) *object.PutResponse { + m := new(object.PutResponse) + + if !empty { + m.SetBody(GeneratePutResponseBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateResponseMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateResponseVerificationHeader(empty)) + + return m +} + +func GenerateDeleteRequestBody(empty bool) *object.DeleteRequestBody { + m := new(object.DeleteRequestBody) + + if !empty { + m.SetAddress(refstest.GenerateAddress(false)) + } + + return m +} + +func GenerateDeleteRequest(empty bool) *object.DeleteRequest { + m := new(object.DeleteRequest) + + if !empty { + m.SetBody(GenerateDeleteRequestBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateRequestMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateRequestVerificationHeader(empty)) + + return m +} + +func GenerateDeleteResponseBody(empty bool) *object.DeleteResponseBody { + m := new(object.DeleteResponseBody) + + if !empty { + m.SetTombstone(refstest.GenerateAddress(false)) + } + + return m +} + +func GenerateDeleteResponse(empty bool) *object.DeleteResponse { + m := new(object.DeleteResponse) + + if !empty { + m.SetBody(GenerateDeleteResponseBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateResponseMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateResponseVerificationHeader(empty)) + + return m +} + +func GenerateHeadRequestBody(empty bool) *object.HeadRequestBody { + m := new(object.HeadRequestBody) + + if !empty { + m.SetRaw(true) + m.SetMainOnly(true) + m.SetAddress(refstest.GenerateAddress(false)) + } + + return m +} + +func GenerateHeadRequest(empty bool) *object.HeadRequest { + m := new(object.HeadRequest) + + if !empty { + m.SetBody(GenerateHeadRequestBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateRequestMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateRequestVerificationHeader(empty)) + + return m +} + +func GenerateHeadResponseBody(empty bool) *object.HeadResponseBody { + m := new(object.HeadResponseBody) + + if !empty { + switch randomInt(3) { + case 0: + m.SetHeaderPart(GenerateHeaderWithSignature(false)) + case 1: + m.SetHeaderPart(GenerateShortHeader(false)) + case 2: + m.SetHeaderPart(GenerateSplitInfo(false)) + } + } + + return m +} + +func GenerateHeadResponse(empty bool) *object.HeadResponse { + m := new(object.HeadResponse) + + if !empty { + m.SetBody(GenerateHeadResponseBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateResponseMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateResponseVerificationHeader(empty)) + + return m +} + +func GenerateSearchFilter(empty bool) *object.SearchFilter { + m := new(object.SearchFilter) + + if !empty { + m.SetKey("search filter key") + m.SetValue("search filter val") + m.SetMatchType(987) + } + + return m +} + +func GenerateSearchFilters(empty bool) []object.SearchFilter { + var res []object.SearchFilter + + if !empty { + res = append(res, + *GenerateSearchFilter(false), + *GenerateSearchFilter(false), + ) + } + + return res +} + +func GenerateSearchRequestBody(empty bool) *object.SearchRequestBody { + m := new(object.SearchRequestBody) + + if !empty { + m.SetVersion(555) + m.SetContainerID(refstest.GenerateContainerID(false)) + m.SetFilters(GenerateSearchFilters(false)) + } + + return m +} + +func GenerateSearchRequest(empty bool) *object.SearchRequest { + m := new(object.SearchRequest) + + if !empty { + m.SetBody(GenerateSearchRequestBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateRequestMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateRequestVerificationHeader(empty)) + + return m +} + +func GenerateSearchResponseBody(empty bool) *object.SearchResponseBody { + m := new(object.SearchResponseBody) + + if !empty { + m.SetIDList(refstest.GenerateObjectIDs(false)) + } + + return m +} + +func GenerateSearchResponse(empty bool) *object.SearchResponse { + m := new(object.SearchResponse) + + if !empty { + m.SetBody(GenerateSearchResponseBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateResponseMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateResponseVerificationHeader(empty)) + + return m +} + +func GenerateRange(empty bool) *object.Range { + m := new(object.Range) + + if !empty { + m.SetLength(11) + m.SetOffset(22) + } + + return m +} + +func GenerateRanges(empty bool) []object.Range { + var res []object.Range + + if !empty { + res = append(res, + *GenerateRange(false), + *GenerateRange(false), + ) + } + + return res +} + +func GenerateGetRangeRequestBody(empty bool) *object.GetRangeRequestBody { + m := new(object.GetRangeRequestBody) + + if !empty { + m.SetRaw(true) + m.SetAddress(refstest.GenerateAddress(empty)) + m.SetRange(GenerateRange(empty)) + } + + return m +} + +func GenerateGetRangeRequest(empty bool) *object.GetRangeRequest { + m := new(object.GetRangeRequest) + + if !empty { + m.SetBody(GenerateGetRangeRequestBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateRequestMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateRequestVerificationHeader(empty)) + + return m +} + +func GenerateGetRangePartChunk(empty bool) *object.GetRangePartChunk { + m := new(object.GetRangePartChunk) + + if !empty { + m.SetChunk([]byte("get range chunk")) + } + + return m +} + +func GenerateGetRangeResponseBody(empty bool) *object.GetRangeResponseBody { + m := new(object.GetRangeResponseBody) + + if !empty { + switch randomInt(2) { + case 0: + m.SetRangePart(GenerateGetRangePartChunk(false)) + case 1: + m.SetRangePart(GenerateSplitInfo(false)) + } + } + + return m +} + +func GenerateGetRangeResponse(empty bool) *object.GetRangeResponse { + m := new(object.GetRangeResponse) + + if !empty { + m.SetBody(GenerateGetRangeResponseBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateResponseMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateResponseVerificationHeader(empty)) + + return m +} + +func GenerateGetRangeHashRequestBody(empty bool) *object.GetRangeHashRequestBody { + m := new(object.GetRangeHashRequestBody) + + if !empty { + m.SetSalt([]byte("range hash salt")) + m.SetType(455) + m.SetAddress(refstest.GenerateAddress(false)) + m.SetRanges(GenerateRanges(false)) + } + + return m +} + +func GenerateGetRangeHashRequest(empty bool) *object.GetRangeHashRequest { + m := new(object.GetRangeHashRequest) + + if !empty { + m.SetBody(GenerateGetRangeHashRequestBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateRequestMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateRequestVerificationHeader(empty)) + + return m +} + +func GenerateGetRangeHashResponseBody(empty bool) *object.GetRangeHashResponseBody { + m := new(object.GetRangeHashResponseBody) + + if !empty { + m.SetType(678) + m.SetHashList([][]byte{{1}, {2}}) + } + + return m +} + +func GenerateGetRangeHashResponse(empty bool) *object.GetRangeHashResponse { + m := new(object.GetRangeHashResponse) + + if !empty { + m.SetBody(GenerateGetRangeHashResponseBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateResponseMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateResponseVerificationHeader(empty)) + + return m +} + +func GenerateLock(empty bool) *object.Lock { + m := new(object.Lock) + + if !empty { + m.SetMembers([]refs.ObjectID{ + *refstest.GenerateObjectID(false), + *refstest.GenerateObjectID(false), + }) + } + + return m +} + +func GeneratePutSingleRequest(empty bool) *object.PutSingleRequest { + m := new(object.PutSingleRequest) + + if !empty { + m.SetBody(GeneratePutSingleRequestBody(false)) + } + + m.SetMetaHeader(sessiontest.GenerateRequestMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateRequestVerificationHeader(empty)) + + return m +} + +func GeneratePutSingleRequestBody(empty bool) *object.PutSingleRequestBody { + b := new(object.PutSingleRequestBody) + if !empty { + b.SetObject(GenerateObject(empty)) + b.SetCopiesNumber([]uint32{12345}) + } + return b +} + +func GeneratePutSingleResponse(empty bool) *object.PutSingleResponse { + m := new(object.PutSingleResponse) + if !empty { + m.SetBody(new(object.PutSingleResponseBody)) + } + m.SetMetaHeader(sessiontest.GenerateResponseMetaHeader(empty)) + m.SetVerificationHeader(sessiontest.GenerateResponseVerificationHeader(empty)) + return m +} + +func randomInt(n int) int { + return rand.New(rand.NewSource(time.Now().UnixNano())).Intn(n) +} diff --git a/pkg/api/object/types.go b/pkg/api/object/types.go new file mode 100644 index 000000000..7516d535e --- /dev/null +++ b/pkg/api/object/types.go @@ -0,0 +1,1510 @@ +package object + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" +) + +type Type uint32 + +type MatchType uint32 + +type ShortHeader struct { + version *refs.Version + + creatEpoch uint64 + + ownerID *refs.OwnerID + + typ Type + + payloadLen uint64 + + payloadHash, homoHash *refs.Checksum +} + +type Attribute struct { + key, val string +} + +type SplitHeader struct { + par, prev *refs.ObjectID + + parSig *refs.Signature + + parHdr *Header + + children []refs.ObjectID + + splitID []byte +} + +type ECHeader struct { + Parent *refs.ObjectID + Index uint32 + Total uint32 + Header []byte + HeaderLength uint32 + Signature []byte +} + +type Header struct { + version *refs.Version + + cid *refs.ContainerID + + ownerID *refs.OwnerID + + creatEpoch uint64 + + payloadLen uint64 + + payloadHash, homoHash *refs.Checksum + + typ Type + + sessionToken *session.Token + + attr []Attribute + + split *SplitHeader + + ec *ECHeader +} + +type HeaderWithSignature struct { + header *Header + + signature *refs.Signature +} + +type Object struct { + objectID *refs.ObjectID + + idSig *refs.Signature + + header *Header + + payload []byte + + // marshalData holds marshaled data, must not be marshaled by StableMarshal + marshalData []byte +} + +type SplitInfo struct { + splitID []byte + + lastPart *refs.ObjectID + + link *refs.ObjectID +} + +type ECChunk struct { + ID refs.ObjectID + Index uint32 + Total uint32 +} + +type ECInfo struct { + Chunks []ECChunk +} + +type GetRequestBody struct { + addr *refs.Address + + raw bool +} + +type GetObjectPart interface { + getObjectPart() +} + +type GetObjectPartInit struct { + id *refs.ObjectID + + sig *refs.Signature + + hdr *Header +} + +type GetObjectPartChunk struct { + chunk []byte +} + +type GetRequest struct { + body *GetRequestBody + + session.RequestHeaders +} + +type GetResponseBody struct { + objPart GetObjectPart +} + +type PutObjectPart interface { + putObjectPart() +} + +type PutObjectPartInit struct { + id *refs.ObjectID + + sig *refs.Signature + + hdr *Header + + copyNum []uint32 +} + +type PutObjectPartChunk struct { + chunk []byte +} + +type GetResponse struct { + body *GetResponseBody + + session.ResponseHeaders +} + +type PutRequestBody struct { + objPart PutObjectPart +} + +type PutRequest struct { + body *PutRequestBody + + session.RequestHeaders +} + +type PutResponseBody struct { + id *refs.ObjectID +} + +type PutResponse struct { + body *PutResponseBody + + session.ResponseHeaders +} + +type DeleteRequestBody struct { + addr *refs.Address +} + +type DeleteRequest struct { + body *DeleteRequestBody + + session.RequestHeaders +} + +type DeleteResponseBody struct { + tombstone *refs.Address +} + +type DeleteResponse struct { + body *DeleteResponseBody + + session.ResponseHeaders +} + +type HeadRequestBody struct { + addr *refs.Address + + mainOnly, raw bool +} + +type GetHeaderPart interface { + getHeaderPart() +} + +type HeadRequest struct { + body *HeadRequestBody + + session.RequestHeaders +} + +type HeadResponseBody struct { + hdrPart GetHeaderPart +} + +type HeadResponse struct { + body *HeadResponseBody + + session.ResponseHeaders +} + +type SearchFilter struct { + matchType MatchType + + key, val string +} + +type SearchRequestBody struct { + cid *refs.ContainerID + + version uint32 + + filters []SearchFilter +} + +type SearchRequest struct { + body *SearchRequestBody + + session.RequestHeaders +} + +type SearchResponseBody struct { + idList []refs.ObjectID +} + +type SearchResponse struct { + body *SearchResponseBody + + session.ResponseHeaders +} + +type Range struct { + off, len uint64 +} + +type GetRangeRequestBody struct { + addr *refs.Address + + rng *Range + + raw bool +} + +type GetRangeRequest struct { + body *GetRangeRequestBody + + session.RequestHeaders +} + +type GetRangePart interface { + getRangePart() +} + +type GetRangePartChunk struct { + chunk []byte +} + +type GetRangeResponseBody struct { + rngPart GetRangePart +} + +type GetRangeResponse struct { + body *GetRangeResponseBody + + session.ResponseHeaders +} + +type GetRangeHashRequestBody struct { + addr *refs.Address + + rngs []Range + + salt []byte + + typ refs.ChecksumType +} + +type GetRangeHashRequest struct { + body *GetRangeHashRequestBody + + session.RequestHeaders +} + +type GetRangeHashResponseBody struct { + typ refs.ChecksumType + + hashList [][]byte +} + +type GetRangeHashResponse struct { + body *GetRangeHashResponseBody + + session.ResponseHeaders +} + +type PutSingleRequestBody struct { + object *Object + copyNum []uint32 + + // marshalData holds marshaled data, must not be marshaled by StableMarshal + marshalData []byte +} + +type PutSingleRequest struct { + body *PutSingleRequestBody + + session.RequestHeaders +} + +type PutSingleResponseBody struct{} + +type PutSingleResponse struct { + body *PutSingleResponseBody + + session.ResponseHeaders +} + +const ( + TypeRegular Type = iota + TypeTombstone + _ + TypeLock +) + +const ( + MatchUnknown MatchType = iota + MatchStringEqual + MatchStringNotEqual + MatchNotPresent + MatchCommonPrefix +) + +func (h *ShortHeader) GetVersion() *refs.Version { + if h != nil { + return h.version + } + + return nil +} + +func (h *ShortHeader) SetVersion(v *refs.Version) { + h.version = v +} + +func (h *ShortHeader) GetCreationEpoch() uint64 { + if h != nil { + return h.creatEpoch + } + + return 0 +} + +func (h *ShortHeader) SetCreationEpoch(v uint64) { + h.creatEpoch = v +} + +func (h *ShortHeader) GetOwnerID() *refs.OwnerID { + if h != nil { + return h.ownerID + } + + return nil +} + +func (h *ShortHeader) SetOwnerID(v *refs.OwnerID) { + h.ownerID = v +} + +func (h *ShortHeader) GetObjectType() Type { + if h != nil { + return h.typ + } + + return TypeRegular +} + +func (h *ShortHeader) SetObjectType(v Type) { + h.typ = v +} + +func (h *ShortHeader) GetPayloadLength() uint64 { + if h != nil { + return h.payloadLen + } + + return 0 +} + +func (h *ShortHeader) SetPayloadLength(v uint64) { + h.payloadLen = v +} + +func (h *ShortHeader) GetPayloadHash() *refs.Checksum { + if h != nil { + return h.payloadHash + } + + return nil +} + +func (h *ShortHeader) SetPayloadHash(v *refs.Checksum) { + h.payloadHash = v +} + +func (h *ShortHeader) GetHomomorphicHash() *refs.Checksum { + if h != nil { + return h.homoHash + } + + return nil +} + +func (h *ShortHeader) SetHomomorphicHash(v *refs.Checksum) { + h.homoHash = v +} + +func (h *ShortHeader) getHeaderPart() {} + +func (a *Attribute) GetKey() string { + if a != nil { + return a.key + } + + return "" +} + +func (a *Attribute) SetKey(v string) { + a.key = v +} + +func (a *Attribute) GetValue() string { + if a != nil { + return a.val + } + + return "" +} + +func (a *Attribute) SetValue(v string) { + a.val = v +} + +func (h *SplitHeader) GetParent() *refs.ObjectID { + if h != nil { + return h.par + } + + return nil +} + +func (h *SplitHeader) SetParent(v *refs.ObjectID) { + h.par = v +} + +func (h *SplitHeader) GetPrevious() *refs.ObjectID { + if h != nil { + return h.prev + } + + return nil +} + +func (h *SplitHeader) SetPrevious(v *refs.ObjectID) { + h.prev = v +} + +func (h *SplitHeader) GetParentSignature() *refs.Signature { + if h != nil { + return h.parSig + } + + return nil +} + +func (h *SplitHeader) SetParentSignature(v *refs.Signature) { + h.parSig = v +} + +func (h *SplitHeader) GetParentHeader() *Header { + if h != nil { + return h.parHdr + } + + return nil +} + +func (h *SplitHeader) SetParentHeader(v *Header) { + h.parHdr = v +} + +func (h *SplitHeader) GetChildren() []refs.ObjectID { + if h != nil { + return h.children + } + + return nil +} + +func (h *SplitHeader) SetChildren(v []refs.ObjectID) { + h.children = v +} + +func (h *SplitHeader) GetSplitID() []byte { + if h != nil { + return h.splitID + } + + return nil +} + +func (h *SplitHeader) SetSplitID(v []byte) { + h.splitID = v +} + +func (h *Header) GetVersion() *refs.Version { + if h != nil { + return h.version + } + + return nil +} + +func (h *Header) SetVersion(v *refs.Version) { + h.version = v +} + +func (h *Header) GetContainerID() *refs.ContainerID { + if h != nil { + return h.cid + } + + return nil +} + +func (h *Header) SetContainerID(v *refs.ContainerID) { + h.cid = v +} + +func (h *Header) GetOwnerID() *refs.OwnerID { + if h != nil { + return h.ownerID + } + + return nil +} + +func (h *Header) SetOwnerID(v *refs.OwnerID) { + h.ownerID = v +} + +func (h *Header) GetCreationEpoch() uint64 { + if h != nil { + return h.creatEpoch + } + + return 0 +} + +func (h *Header) SetCreationEpoch(v uint64) { + h.creatEpoch = v +} + +func (h *Header) GetPayloadLength() uint64 { + if h != nil { + return h.payloadLen + } + + return 0 +} + +func (h *Header) SetPayloadLength(v uint64) { + h.payloadLen = v +} + +func (h *Header) GetPayloadHash() *refs.Checksum { + if h != nil { + return h.payloadHash + } + + return nil +} + +func (h *Header) SetPayloadHash(v *refs.Checksum) { + h.payloadHash = v +} + +func (h *Header) GetObjectType() Type { + if h != nil { + return h.typ + } + + return TypeRegular +} + +func (h *Header) SetObjectType(v Type) { + h.typ = v +} + +func (h *Header) GetHomomorphicHash() *refs.Checksum { + if h != nil { + return h.homoHash + } + + return nil +} + +func (h *Header) SetHomomorphicHash(v *refs.Checksum) { + h.homoHash = v +} + +func (h *Header) GetSessionToken() *session.Token { + if h != nil { + return h.sessionToken + } + + return nil +} + +func (h *Header) SetSessionToken(v *session.Token) { + h.sessionToken = v +} + +func (h *Header) GetAttributes() []Attribute { + if h != nil { + return h.attr + } + + return nil +} + +func (h *Header) SetAttributes(v []Attribute) { + h.attr = v +} + +func (h *Header) GetSplit() *SplitHeader { + if h != nil { + return h.split + } + + return nil +} + +func (h *Header) SetSplit(v *SplitHeader) { + h.split = v +} + +func (h *Header) GetEC() *ECHeader { + if h != nil { + return h.ec + } + return nil +} + +func (h *Header) SetEC(v *ECHeader) { + h.ec = v +} + +func (h *HeaderWithSignature) GetHeader() *Header { + if h != nil { + return h.header + } + + return nil +} + +func (h *HeaderWithSignature) SetHeader(v *Header) { + h.header = v +} + +func (h *HeaderWithSignature) GetSignature() *refs.Signature { + if h != nil { + return h.signature + } + + return nil +} + +func (h *HeaderWithSignature) SetSignature(v *refs.Signature) { + h.signature = v +} + +func (h *HeaderWithSignature) getHeaderPart() {} + +func (o *Object) GetObjectID() *refs.ObjectID { + if o != nil { + return o.objectID + } + + return nil +} + +func (o *Object) SetObjectID(v *refs.ObjectID) { + o.objectID = v +} + +func (o *Object) GetSignature() *refs.Signature { + if o != nil { + return o.idSig + } + + return nil +} + +func (o *Object) SetSignature(v *refs.Signature) { + o.idSig = v +} + +func (o *Object) GetHeader() *Header { + if o != nil { + return o.header + } + + return nil +} + +func (o *Object) SetHeader(v *Header) { + o.header = v +} + +func (o *Object) GetPayload() []byte { + if o != nil { + return o.payload + } + + return nil +} + +func (o *Object) SetPayload(v []byte) { + o.payload = v +} + +func (s *SplitInfo) GetSplitID() []byte { + if s != nil { + return s.splitID + } + + return nil +} + +func (s *SplitInfo) SetSplitID(v []byte) { + s.splitID = v +} + +func (s *SplitInfo) GetLastPart() *refs.ObjectID { + if s != nil { + return s.lastPart + } + + return nil +} + +func (s *SplitInfo) SetLastPart(v *refs.ObjectID) { + s.lastPart = v +} + +func (s *SplitInfo) GetLink() *refs.ObjectID { + if s != nil { + return s.link + } + + return nil +} + +func (s *SplitInfo) SetLink(v *refs.ObjectID) { + s.link = v +} + +func (s *SplitInfo) getObjectPart() {} + +func (s *SplitInfo) getHeaderPart() {} + +func (s *SplitInfo) getRangePart() {} + +func (r *GetRequestBody) GetAddress() *refs.Address { + if r != nil { + return r.addr + } + + return nil +} + +func (r *GetRequestBody) SetAddress(v *refs.Address) { + r.addr = v +} + +func (r *GetRequestBody) GetRaw() bool { + if r != nil { + return r.raw + } + + return false +} + +func (r *GetRequestBody) SetRaw(v bool) { + r.raw = v +} + +func (r *GetRequest) GetBody() *GetRequestBody { + if r != nil { + return r.body + } + + return nil +} + +func (r *GetRequest) SetBody(v *GetRequestBody) { + r.body = v +} + +func (r *GetObjectPartInit) GetObjectID() *refs.ObjectID { + if r != nil { + return r.id + } + + return nil +} + +func (r *GetObjectPartInit) SetObjectID(v *refs.ObjectID) { + r.id = v +} + +func (r *GetObjectPartInit) GetSignature() *refs.Signature { + if r != nil { + return r.sig + } + + return nil +} + +func (r *GetObjectPartInit) SetSignature(v *refs.Signature) { + r.sig = v +} + +func (r *GetObjectPartInit) GetHeader() *Header { + if r != nil { + return r.hdr + } + + return nil +} + +func (r *GetObjectPartInit) SetHeader(v *Header) { + r.hdr = v +} + +func (r *GetObjectPartInit) getObjectPart() {} + +func (r *GetObjectPartChunk) GetChunk() []byte { + if r != nil { + return r.chunk + } + + return nil +} + +func (r *GetObjectPartChunk) SetChunk(v []byte) { + r.chunk = v +} + +func (r *GetObjectPartChunk) getObjectPart() {} + +func (r *GetResponseBody) GetObjectPart() GetObjectPart { + if r != nil { + return r.objPart + } + + return nil +} + +func (r *GetResponseBody) SetObjectPart(v GetObjectPart) { + r.objPart = v +} + +func (r *GetResponse) GetBody() *GetResponseBody { + if r != nil { + return r.body + } + + return nil +} + +func (r *GetResponse) SetBody(v *GetResponseBody) { + r.body = v +} + +func (r *PutObjectPartInit) GetObjectID() *refs.ObjectID { + if r != nil { + return r.id + } + + return nil +} + +func (r *PutObjectPartInit) SetObjectID(v *refs.ObjectID) { + r.id = v +} + +func (r *PutObjectPartInit) GetSignature() *refs.Signature { + if r != nil { + return r.sig + } + + return nil +} + +func (r *PutObjectPartInit) SetSignature(v *refs.Signature) { + r.sig = v +} + +func (r *PutObjectPartInit) GetHeader() *Header { + if r != nil { + return r.hdr + } + + return nil +} + +func (r *PutObjectPartInit) SetHeader(v *Header) { + r.hdr = v +} + +func (r *PutObjectPartInit) GetCopiesNumber() []uint32 { + if r != nil { + return r.copyNum + } + + return nil +} + +func (r *PutObjectPartInit) SetCopiesNumber(v []uint32) { + r.copyNum = v +} + +func (r *PutObjectPartInit) putObjectPart() {} + +func (r *PutObjectPartChunk) GetChunk() []byte { + if r != nil { + return r.chunk + } + + return nil +} + +func (r *PutObjectPartChunk) SetChunk(v []byte) { + r.chunk = v +} + +func (r *PutObjectPartChunk) putObjectPart() {} + +func (r *PutRequestBody) GetObjectPart() PutObjectPart { + if r != nil { + return r.objPart + } + + return nil +} + +func (r *PutRequestBody) SetObjectPart(v PutObjectPart) { + r.objPart = v +} + +func (r *PutRequest) GetBody() *PutRequestBody { + if r != nil { + return r.body + } + + return nil +} + +func (r *PutRequest) SetBody(v *PutRequestBody) { + r.body = v +} + +func (r *PutResponseBody) GetObjectID() *refs.ObjectID { + if r != nil { + return r.id + } + + return nil +} + +func (r *PutResponseBody) SetObjectID(v *refs.ObjectID) { + r.id = v +} + +func (r *PutResponse) GetBody() *PutResponseBody { + if r != nil { + return r.body + } + + return nil +} + +func (r *PutResponse) SetBody(v *PutResponseBody) { + r.body = v +} + +func (r *DeleteRequestBody) GetAddress() *refs.Address { + if r != nil { + return r.addr + } + + return nil +} + +func (r *DeleteRequestBody) SetAddress(v *refs.Address) { + r.addr = v +} + +func (r *DeleteRequest) GetBody() *DeleteRequestBody { + if r != nil { + return r.body + } + + return nil +} + +func (r *DeleteRequest) SetBody(v *DeleteRequestBody) { + r.body = v +} + +// GetTombstone returns tombstone address. +func (r *DeleteResponseBody) GetTombstone() *refs.Address { + if r != nil { + return r.tombstone + } + + return nil +} + +// SetTombstone sets tombstone address. +func (r *DeleteResponseBody) SetTombstone(v *refs.Address) { + r.tombstone = v +} + +func (r *DeleteResponse) GetBody() *DeleteResponseBody { + if r != nil { + return r.body + } + + return nil +} + +func (r *DeleteResponse) SetBody(v *DeleteResponseBody) { + r.body = v +} + +func (r *HeadRequestBody) GetAddress() *refs.Address { + if r != nil { + return r.addr + } + + return nil +} + +func (r *HeadRequestBody) SetAddress(v *refs.Address) { + r.addr = v +} + +func (r *HeadRequestBody) GetMainOnly() bool { + if r != nil { + return r.mainOnly + } + + return false +} + +func (r *HeadRequestBody) SetMainOnly(v bool) { + r.mainOnly = v +} + +func (r *HeadRequestBody) GetRaw() bool { + if r != nil { + return r.raw + } + + return false +} + +func (r *HeadRequestBody) SetRaw(v bool) { + r.raw = v +} + +func (r *HeadRequest) GetBody() *HeadRequestBody { + if r != nil { + return r.body + } + + return nil +} + +func (r *HeadRequest) SetBody(v *HeadRequestBody) { + r.body = v +} + +func (r *HeadResponseBody) GetHeaderPart() GetHeaderPart { + if r != nil { + return r.hdrPart + } + + return nil +} + +func (r *HeadResponseBody) SetHeaderPart(v GetHeaderPart) { + r.hdrPart = v +} + +func (r *HeadResponse) GetBody() *HeadResponseBody { + if r != nil { + return r.body + } + + return nil +} + +func (r *HeadResponse) SetBody(v *HeadResponseBody) { + r.body = v +} + +func (f *SearchFilter) GetMatchType() MatchType { + if f != nil { + return f.matchType + } + + return MatchUnknown +} + +func (f *SearchFilter) SetMatchType(v MatchType) { + f.matchType = v +} + +func (f *SearchFilter) GetKey() string { + if f != nil { + return f.key + } + + return "" +} + +func (f *SearchFilter) SetKey(v string) { + f.key = v +} + +func (f *SearchFilter) GetValue() string { + if f != nil { + return f.val + } + + return "" +} + +func (f *SearchFilter) SetValue(v string) { + f.val = v +} + +func (r *SearchRequestBody) GetContainerID() *refs.ContainerID { + if r != nil { + return r.cid + } + + return nil +} + +func (r *SearchRequestBody) SetContainerID(v *refs.ContainerID) { + r.cid = v +} + +func (r *SearchRequestBody) GetVersion() uint32 { + if r != nil { + return r.version + } + + return 0 +} + +func (r *SearchRequestBody) SetVersion(v uint32) { + r.version = v +} + +func (r *SearchRequestBody) GetFilters() []SearchFilter { + if r != nil { + return r.filters + } + + return nil +} + +func (r *SearchRequestBody) SetFilters(v []SearchFilter) { + r.filters = v +} + +func (r *SearchRequest) GetBody() *SearchRequestBody { + if r != nil { + return r.body + } + + return nil +} + +func (r *SearchRequest) SetBody(v *SearchRequestBody) { + r.body = v +} + +func (r *SearchResponseBody) GetIDList() []refs.ObjectID { + if r != nil { + return r.idList + } + + return nil +} + +func (r *SearchResponseBody) SetIDList(v []refs.ObjectID) { + r.idList = v +} + +func (r *SearchResponse) GetBody() *SearchResponseBody { + if r != nil { + return r.body + } + + return nil +} + +func (r *SearchResponse) SetBody(v *SearchResponseBody) { + r.body = v +} + +func (r *Range) GetOffset() uint64 { + if r != nil { + return r.off + } + + return 0 +} + +func (r *Range) SetOffset(v uint64) { + r.off = v +} + +func (r *Range) GetLength() uint64 { + if r != nil { + return r.len + } + + return 0 +} + +func (r *Range) SetLength(v uint64) { + r.len = v +} + +func (r *GetRangeRequestBody) GetAddress() *refs.Address { + if r != nil { + return r.addr + } + + return nil +} + +func (r *GetRangeRequestBody) SetAddress(v *refs.Address) { + r.addr = v +} + +func (r *GetRangeRequestBody) GetRange() *Range { + if r != nil { + return r.rng + } + + return nil +} + +func (r *GetRangeRequestBody) SetRange(v *Range) { + r.rng = v +} + +func (r *GetRangeRequestBody) GetRaw() bool { + if r != nil { + return r.raw + } + + return false +} + +func (r *GetRangeRequestBody) SetRaw(v bool) { + r.raw = v +} + +func (r *GetRangeRequest) GetBody() *GetRangeRequestBody { + if r != nil { + return r.body + } + + return nil +} + +func (r *GetRangeRequest) SetBody(v *GetRangeRequestBody) { + r.body = v +} + +func (r *GetRangePartChunk) GetChunk() []byte { + if r != nil { + return r.chunk + } + + return nil +} + +func (r *GetRangePartChunk) SetChunk(v []byte) { + r.chunk = v +} + +func (r *GetRangePartChunk) getRangePart() {} + +func (r *GetRangeResponseBody) GetRangePart() GetRangePart { + if r != nil { + return r.rngPart + } + + return nil +} + +func (r *GetRangeResponseBody) SetRangePart(v GetRangePart) { + r.rngPart = v +} + +func (r *GetRangeResponse) GetBody() *GetRangeResponseBody { + if r != nil { + return r.body + } + + return nil +} + +func (r *GetRangeResponse) SetBody(v *GetRangeResponseBody) { + r.body = v +} + +func (r *GetRangeHashRequestBody) GetAddress() *refs.Address { + if r != nil { + return r.addr + } + + return nil +} + +func (r *GetRangeHashRequestBody) SetAddress(v *refs.Address) { + r.addr = v +} + +func (r *GetRangeHashRequestBody) GetRanges() []Range { + if r != nil { + return r.rngs + } + + return nil +} + +func (r *GetRangeHashRequestBody) SetRanges(v []Range) { + r.rngs = v +} + +func (r *GetRangeHashRequestBody) GetSalt() []byte { + if r != nil { + return r.salt + } + + return nil +} + +func (r *GetRangeHashRequestBody) SetSalt(v []byte) { + r.salt = v +} + +func (r *GetRangeHashRequestBody) GetType() refs.ChecksumType { + if r != nil { + return r.typ + } + + return refs.UnknownChecksum +} + +func (r *GetRangeHashRequestBody) SetType(v refs.ChecksumType) { + r.typ = v +} + +func (r *GetRangeHashRequest) GetBody() *GetRangeHashRequestBody { + if r != nil { + return r.body + } + + return nil +} + +func (r *GetRangeHashRequest) SetBody(v *GetRangeHashRequestBody) { + r.body = v +} + +func (r *GetRangeHashResponseBody) GetType() refs.ChecksumType { + if r != nil { + return r.typ + } + + return refs.UnknownChecksum +} + +func (r *GetRangeHashResponseBody) SetType(v refs.ChecksumType) { + r.typ = v +} + +func (r *GetRangeHashResponseBody) GetHashList() [][]byte { + if r != nil { + return r.hashList + } + + return nil +} + +func (r *GetRangeHashResponseBody) SetHashList(v [][]byte) { + r.hashList = v +} + +func (r *GetRangeHashResponse) GetBody() *GetRangeHashResponseBody { + if r != nil { + return r.body + } + + return nil +} + +func (r *GetRangeHashResponse) SetBody(v *GetRangeHashResponseBody) { + r.body = v +} + +func (r *PutSingleRequest) GetBody() *PutSingleRequestBody { + if r != nil { + return r.body + } + + return nil +} + +func (r *PutSingleRequest) SetBody(v *PutSingleRequestBody) { + r.body = v +} + +func (b *PutSingleRequestBody) GetObject() *Object { + if b == nil { + return nil + } + return b.object +} + +func (b *PutSingleRequestBody) SetObject(o *Object) { + b.object = o +} + +func (b *PutSingleRequestBody) GetCopiesNumber() []uint32 { + if b == nil { + return nil + } + return b.copyNum +} + +func (b *PutSingleRequestBody) SetCopiesNumber(v []uint32) { + b.copyNum = v +} + +func (r *PutSingleResponse) GetBody() *PutSingleResponseBody { + if r != nil { + return r.body + } + + return nil +} + +func (r *PutSingleResponse) SetBody(v *PutSingleResponseBody) { + r.body = v +} diff --git a/pkg/api/prepare.sh b/pkg/api/prepare.sh new file mode 100755 index 000000000..32048b34d --- /dev/null +++ b/pkg/api/prepare.sh @@ -0,0 +1,36 @@ +#!/bin/bash + +if [ -z "$1" ]; then + echo "usage: ./prepare.sh path/to/frostfs-api" + exit 1 +fi + +API_GO_PATH=$(pwd) +API_PATH=$1 + +# MOVE FILES FROM API REPO +cd "$API_PATH" || exit 1 +ARGS=$(find ./ -name '*.proto' -not -path './vendor/*') +for file in $ARGS; do + dir=$(dirname "$file") + mkdir -p "$API_GO_PATH/$dir/grpc" + cp -r "$dir"/* "$API_GO_PATH/$dir/grpc" +done + +# MODIFY FILES +cd "$API_GO_PATH" || exit 1 +ARGS2=$(find ./ -name '*.proto') +for file in $ARGS2; do + echo "$file" + sed -i "s/import\ \"\(.*\)\/\(.*\)\.proto\";/import\ \"\1\/grpc\/\2\.proto\";/" $file +done + +cd "$API_GO_PATH" || exit 1 +# COMPILE +make protoc + +# REMOVE PROTO DEFINITIONS +ARGS=$(find ./$prefix -name '*.proto' -not -path './vendor/*' -not -path './util/*') +for file in $ARGS; do + rm "$file" +done diff --git a/pkg/api/refs/bench_test.go b/pkg/api/refs/bench_test.go new file mode 100644 index 000000000..b24e674d2 --- /dev/null +++ b/pkg/api/refs/bench_test.go @@ -0,0 +1,53 @@ +package refs + +import ( + "math/rand" + "strconv" + "testing" +) + +func BenchmarkObjectIDSlice(b *testing.B) { + for _, size := range []int{0, 1, 50} { + b.Run(strconv.Itoa(size)+" elements", func(b *testing.B) { + benchmarkObjectIDSlice(b, size) + }) + } +} + +func benchmarkObjectIDSlice(b *testing.B, size int) { + ids := make([]ObjectID, size) + for i := range ids { + ids[i].val = make([]byte, 32) + rand.Read(ids[i].val) + } + raw := ObjectIDListToGRPCMessage(ids) + + b.Run("to grpc message", func(b *testing.B) { + b.ReportAllocs() + for i := 0; i < b.N; i++ { + raw := ObjectIDListToGRPCMessage(ids) + if len(raw) != len(ids) { + b.FailNow() + } + } + }) + b.Run("from grpc message", func(b *testing.B) { + b.ReportAllocs() + for i := 0; i < b.N; i++ { + ids, err := ObjectIDListFromGRPCMessage(raw) + if err != nil || len(raw) != len(ids) { + b.FailNow() + } + } + }) + b.Run("marshal", func(b *testing.B) { + b.ReportAllocs() + for i := 0; i < b.N; i++ { + buf := make([]byte, ObjectIDNestedListSize(1, ids)) + n := ObjectIDNestedListMarshal(1, buf, ids) + if n != len(buf) { + b.FailNow() + } + } + }) +} diff --git a/pkg/api/refs/convert.go b/pkg/api/refs/convert.go new file mode 100644 index 000000000..3ce16798b --- /dev/null +++ b/pkg/api/refs/convert.go @@ -0,0 +1,268 @@ +package refs + +import ( + refs "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/message" +) + +func (o *OwnerID) ToGRPCMessage() grpc.Message { + var m *refs.OwnerID + + if o != nil { + m = new(refs.OwnerID) + + m.SetValue(o.val) + } + + return m +} + +func (o *OwnerID) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*refs.OwnerID) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + o.val = v.GetValue() + + return nil +} + +func (c *ContainerID) ToGRPCMessage() grpc.Message { + var m *refs.ContainerID + + if c != nil { + m = new(refs.ContainerID) + + m.SetValue(c.val) + } + + return m +} + +func (c *ContainerID) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*refs.ContainerID) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + c.val = v.GetValue() + + return nil +} + +func ContainerIDsToGRPCMessage(ids []ContainerID) (res []*refs.ContainerID) { + if ids != nil { + res = make([]*refs.ContainerID, 0, len(ids)) + + for i := range ids { + res = append(res, ids[i].ToGRPCMessage().(*refs.ContainerID)) + } + } + + return +} + +func ContainerIDsFromGRPCMessage(idsV2 []*refs.ContainerID) (res []ContainerID, err error) { + if idsV2 != nil { + res = make([]ContainerID, len(idsV2)) + + for i := range idsV2 { + if idsV2[i] != nil { + err = res[i].FromGRPCMessage(idsV2[i]) + if err != nil { + return + } + } + } + } + + return +} + +func (o *ObjectID) ToGRPCMessage() grpc.Message { + var m *refs.ObjectID + + if o != nil { + m = new(refs.ObjectID) + + m.SetValue(o.val) + } + + return m +} + +func (o *ObjectID) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*refs.ObjectID) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + o.val = v.GetValue() + + return nil +} + +func ObjectIDListToGRPCMessage(ids []ObjectID) (res []*refs.ObjectID) { + if ids != nil { + res = make([]*refs.ObjectID, 0, len(ids)) + + for i := range ids { + res = append(res, ids[i].ToGRPCMessage().(*refs.ObjectID)) + } + } + + return +} + +func ObjectIDListFromGRPCMessage(idsV2 []*refs.ObjectID) (res []ObjectID, err error) { + if idsV2 != nil { + res = make([]ObjectID, len(idsV2)) + + for i := range idsV2 { + if idsV2[i] != nil { + err = res[i].FromGRPCMessage(idsV2[i]) + if err != nil { + return + } + } + } + } + + return +} + +func (a *Address) ToGRPCMessage() grpc.Message { + var m *refs.Address + + if a != nil { + m = new(refs.Address) + + m.SetContainerId(a.cid.ToGRPCMessage().(*refs.ContainerID)) + m.SetObjectId(a.oid.ToGRPCMessage().(*refs.ObjectID)) + } + + return m +} + +func (a *Address) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*refs.Address) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + cid := v.GetContainerId() + if cid == nil { + a.cid = nil + } else { + if a.cid == nil { + a.cid = new(ContainerID) + } + + err = a.cid.FromGRPCMessage(cid) + if err != nil { + return err + } + } + + oid := v.GetObjectId() + if oid == nil { + a.oid = nil + } else { + if a.oid == nil { + a.oid = new(ObjectID) + } + + err = a.oid.FromGRPCMessage(oid) + } + + return err +} + +func ChecksumTypeToGRPC(t ChecksumType) refs.ChecksumType { + return refs.ChecksumType(t) +} + +func ChecksumTypeFromGRPC(t refs.ChecksumType) ChecksumType { + return ChecksumType(t) +} + +func (c *Checksum) ToGRPCMessage() grpc.Message { + var m *refs.Checksum + + if c != nil { + m = new(refs.Checksum) + + m.SetChecksumType(ChecksumTypeToGRPC(c.typ)) + m.SetSum(c.sum) + } + + return m +} + +func (c *Checksum) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*refs.Checksum) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + c.typ = ChecksumTypeFromGRPC(v.GetType()) + c.sum = v.GetSum() + + return nil +} + +func (v *Version) ToGRPCMessage() grpc.Message { + var m *refs.Version + + if v != nil { + m = new(refs.Version) + + m.SetMajor(v.major) + m.SetMinor(v.minor) + } + + return m +} + +func (v *Version) FromGRPCMessage(m grpc.Message) error { + ver, ok := m.(*refs.Version) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + v.major = ver.GetMajor() + v.minor = ver.GetMinor() + + return nil +} + +func (s *Signature) ToGRPCMessage() grpc.Message { + var m *refs.Signature + + if s != nil { + m = new(refs.Signature) + + m.SetKey(s.key) + m.SetSign(s.sign) + m.SetScheme(refs.SignatureScheme(s.scheme)) + } + + return m +} + +func (s *Signature) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*refs.Signature) + if !ok { + return message.NewUnexpectedMessageType(m, s) + } + + s.key = v.GetKey() + s.sign = v.GetSign() + s.scheme = SignatureScheme(v.GetScheme()) + + return nil +} diff --git a/pkg/api/refs/grpc/types.go b/pkg/api/refs/grpc/types.go new file mode 100644 index 000000000..843a2ee7d --- /dev/null +++ b/pkg/api/refs/grpc/types.go @@ -0,0 +1,97 @@ +package refs + +// SetValue sets container identifier in a binary format. +func (x *ContainerID) SetValue(v []byte) { + x.Value = v +} + +// SetValue sets object identifier in a binary format. +func (x *ObjectID) SetValue(v []byte) { + x.Value = v +} + +// SetValue sets owner identifier in a binary format. +func (x *OwnerID) SetValue(v []byte) { + x.Value = v +} + +// SetContainerId sets container identifier of the address. +func (x *Address) SetContainerId(v *ContainerID) { + x.ContainerId = v +} + +// SetObjectId sets object identifier of the address. +func (x *Address) SetObjectId(v *ObjectID) { + x.ObjectId = v +} + +// SetChecksumType in generic checksum structure. +func (x *Checksum) SetChecksumType(v ChecksumType) { + x.Type = v +} + +// SetSum in generic checksum structure. +func (x *Checksum) SetSum(v []byte) { + x.Sum = v +} + +// SetMajor sets major version number. +func (x *Version) SetMajor(v uint32) { + x.Major = v +} + +// SetMinor sets minor version number. +func (x *Version) SetMinor(v uint32) { + x.Minor = v +} + +// SetKey sets public key in a binary format. +func (x *Signature) SetKey(v []byte) { + x.Key = v +} + +// SetSign sets signature. +func (x *Signature) SetSign(v []byte) { + x.Sign = v +} + +// SetScheme sets signature scheme. +func (x *Signature) SetScheme(s SignatureScheme) { + x.Scheme = s +} + +// SetKey sets public key in a binary format. +func (x *SignatureRFC6979) SetKey(v []byte) { + x.Key = v +} + +// SetSign sets signature. +func (x *SignatureRFC6979) SetSign(v []byte) { + x.Sign = v +} + +// FromString parses SignatureScheme from a string representation, +// It is a reverse action to String(). +// +// Returns true if s was parsed successfully. +func (x *SignatureScheme) FromString(s string) bool { + i, ok := SignatureScheme_value[s] + if ok { + *x = SignatureScheme(i) + } + + return ok +} + +// FromString parses ChecksumType from a string representation, +// It is a reverse action to String(). +// +// Returns true if s was parsed successfully. +func (x *ChecksumType) FromString(s string) bool { + i, ok := ChecksumType_value[s] + if ok { + *x = ChecksumType(i) + } + + return ok +} diff --git a/pkg/api/refs/grpc/types.pb.go b/pkg/api/refs/grpc/types.pb.go new file mode 100644 index 000000000..681bb0dbf --- /dev/null +++ b/pkg/api/refs/grpc/types.pb.go @@ -0,0 +1,852 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.33.0 +// protoc v4.25.3 +// source: refs/grpc/types.proto + +package refs + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// Signature scheme describes digital signing scheme used for (key, signature) +// pair. +type SignatureScheme int32 + +const ( + // ECDSA with SHA-512 hashing (FIPS 186-3) + SignatureScheme_ECDSA_SHA512 SignatureScheme = 0 + // Deterministic ECDSA with SHA-256 hashing (RFC 6979) + SignatureScheme_ECDSA_RFC6979_SHA256 SignatureScheme = 1 + // Deterministic ECDSA with SHA-256 hashing using WalletConnect API. + // Here the algorithm is the same, but the message format differs. + SignatureScheme_ECDSA_RFC6979_SHA256_WALLET_CONNECT SignatureScheme = 2 +) + +// Enum value maps for SignatureScheme. +var ( + SignatureScheme_name = map[int32]string{ + 0: "ECDSA_SHA512", + 1: "ECDSA_RFC6979_SHA256", + 2: "ECDSA_RFC6979_SHA256_WALLET_CONNECT", + } + SignatureScheme_value = map[string]int32{ + "ECDSA_SHA512": 0, + "ECDSA_RFC6979_SHA256": 1, + "ECDSA_RFC6979_SHA256_WALLET_CONNECT": 2, + } +) + +func (x SignatureScheme) Enum() *SignatureScheme { + p := new(SignatureScheme) + *p = x + return p +} + +func (x SignatureScheme) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (SignatureScheme) Descriptor() protoreflect.EnumDescriptor { + return file_refs_grpc_types_proto_enumTypes[0].Descriptor() +} + +func (SignatureScheme) Type() protoreflect.EnumType { + return &file_refs_grpc_types_proto_enumTypes[0] +} + +func (x SignatureScheme) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use SignatureScheme.Descriptor instead. +func (SignatureScheme) EnumDescriptor() ([]byte, []int) { + return file_refs_grpc_types_proto_rawDescGZIP(), []int{0} +} + +// Checksum algorithm type. +type ChecksumType int32 + +const ( + // Unknown. Not used + ChecksumType_CHECKSUM_TYPE_UNSPECIFIED ChecksumType = 0 + // Tillich-Zemor homomorphic hash function + ChecksumType_TZ ChecksumType = 1 + // SHA-256 + ChecksumType_SHA256 ChecksumType = 2 +) + +// Enum value maps for ChecksumType. +var ( + ChecksumType_name = map[int32]string{ + 0: "CHECKSUM_TYPE_UNSPECIFIED", + 1: "TZ", + 2: "SHA256", + } + ChecksumType_value = map[string]int32{ + "CHECKSUM_TYPE_UNSPECIFIED": 0, + "TZ": 1, + "SHA256": 2, + } +) + +func (x ChecksumType) Enum() *ChecksumType { + p := new(ChecksumType) + *p = x + return p +} + +func (x ChecksumType) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (ChecksumType) Descriptor() protoreflect.EnumDescriptor { + return file_refs_grpc_types_proto_enumTypes[1].Descriptor() +} + +func (ChecksumType) Type() protoreflect.EnumType { + return &file_refs_grpc_types_proto_enumTypes[1] +} + +func (x ChecksumType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use ChecksumType.Descriptor instead. +func (ChecksumType) EnumDescriptor() ([]byte, []int) { + return file_refs_grpc_types_proto_rawDescGZIP(), []int{1} +} + +// Objects in NeoFS are addressed by their ContainerID and ObjectID. +// +// String presentation of `Address` is a concatenation of string encoded +// `ContainerID` and `ObjectID` delimited by '/' character. +type Address struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Container identifier + ContainerId *ContainerID `protobuf:"bytes,1,opt,name=container_id,json=containerID,proto3" json:"container_id,omitempty"` + // Object identifier + ObjectId *ObjectID `protobuf:"bytes,2,opt,name=object_id,json=objectID,proto3" json:"object_id,omitempty"` +} + +func (x *Address) Reset() { + *x = Address{} + if protoimpl.UnsafeEnabled { + mi := &file_refs_grpc_types_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Address) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Address) ProtoMessage() {} + +func (x *Address) ProtoReflect() protoreflect.Message { + mi := &file_refs_grpc_types_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Address.ProtoReflect.Descriptor instead. +func (*Address) Descriptor() ([]byte, []int) { + return file_refs_grpc_types_proto_rawDescGZIP(), []int{0} +} + +func (x *Address) GetContainerId() *ContainerID { + if x != nil { + return x.ContainerId + } + return nil +} + +func (x *Address) GetObjectId() *ObjectID { + if x != nil { + return x.ObjectId + } + return nil +} + +// NeoFS Object unique identifier. Objects are immutable and content-addressed. +// It means `ObjectID` will change if the `header` or the `payload` changes. +// +// `ObjectID` is a 32 byte long +// [SHA256](https://csrc.nist.gov/publications/detail/fips/180/4/final) hash of +// the object's `header` field, which, in it's turn, contains the hash of the +// object's payload. +// +// String presentation is a +// [base58](https://tools.ietf.org/html/draft-msporny-base58-02) encoded string. +// +// JSON value will be data encoded as a string using standard base64 +// encoding with paddings. Either +// [standard](https://tools.ietf.org/html/rfc4648#section-4) or +// [URL-safe](https://tools.ietf.org/html/rfc4648#section-5) base64 encoding +// with/without paddings are accepted. +type ObjectID struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Object identifier in a binary format + Value []byte `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` +} + +func (x *ObjectID) Reset() { + *x = ObjectID{} + if protoimpl.UnsafeEnabled { + mi := &file_refs_grpc_types_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ObjectID) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ObjectID) ProtoMessage() {} + +func (x *ObjectID) ProtoReflect() protoreflect.Message { + mi := &file_refs_grpc_types_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ObjectID.ProtoReflect.Descriptor instead. +func (*ObjectID) Descriptor() ([]byte, []int) { + return file_refs_grpc_types_proto_rawDescGZIP(), []int{1} +} + +func (x *ObjectID) GetValue() []byte { + if x != nil { + return x.Value + } + return nil +} + +// NeoFS container identifier. Container structures are immutable and +// content-addressed. +// +// `ContainerID` is a 32 byte long +// [SHA256](https://csrc.nist.gov/publications/detail/fips/180/4/final) hash of +// stable-marshalled container message. +// +// String presentation is a +// [base58](https://tools.ietf.org/html/draft-msporny-base58-02) encoded string. +// +// JSON value will be data encoded as a string using standard base64 +// encoding with paddings. Either +// [standard](https://tools.ietf.org/html/rfc4648#section-4) or +// [URL-safe](https://tools.ietf.org/html/rfc4648#section-5) base64 encoding +// with/without paddings are accepted. +type ContainerID struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Container identifier in a binary format. + Value []byte `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` +} + +func (x *ContainerID) Reset() { + *x = ContainerID{} + if protoimpl.UnsafeEnabled { + mi := &file_refs_grpc_types_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ContainerID) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ContainerID) ProtoMessage() {} + +func (x *ContainerID) ProtoReflect() protoreflect.Message { + mi := &file_refs_grpc_types_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ContainerID.ProtoReflect.Descriptor instead. +func (*ContainerID) Descriptor() ([]byte, []int) { + return file_refs_grpc_types_proto_rawDescGZIP(), []int{2} +} + +func (x *ContainerID) GetValue() []byte { + if x != nil { + return x.Value + } + return nil +} + +// `OwnerID` is a derivative of a user's main public key. The transformation +// algorithm is the same as for Neo3 wallet addresses. Neo3 wallet address can +// be directly used as `OwnerID`. +// +// `OwnerID` is a 25 bytes sequence starting with Neo version prefix byte +// followed by 20 bytes of ScrptHash and 4 bytes of checksum. +// +// String presentation is a [Base58 +// Check](https://en.bitcoin.it/wiki/Base58Check_encoding) Encoded string. +// +// JSON value will be data encoded as a string using standard base64 +// encoding with paddings. Either +// [standard](https://tools.ietf.org/html/rfc4648#section-4) or +// [URL-safe](https://tools.ietf.org/html/rfc4648#section-5) base64 encoding +// with/without paddings are accepted. +type OwnerID struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Identifier of the container owner in a binary format + Value []byte `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` +} + +func (x *OwnerID) Reset() { + *x = OwnerID{} + if protoimpl.UnsafeEnabled { + mi := &file_refs_grpc_types_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *OwnerID) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*OwnerID) ProtoMessage() {} + +func (x *OwnerID) ProtoReflect() protoreflect.Message { + mi := &file_refs_grpc_types_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use OwnerID.ProtoReflect.Descriptor instead. +func (*OwnerID) Descriptor() ([]byte, []int) { + return file_refs_grpc_types_proto_rawDescGZIP(), []int{3} +} + +func (x *OwnerID) GetValue() []byte { + if x != nil { + return x.Value + } + return nil +} + +// API version used by a node. +// +// String presentation is a Semantic Versioning 2.0.0 compatible version string +// with 'v' prefix. i.e. `vX.Y`, where `X` is the major number, `Y` is the minor +// number. +type Version struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Major API version + Major uint32 `protobuf:"varint,1,opt,name=major,proto3" json:"major,omitempty"` + // Minor API version + Minor uint32 `protobuf:"varint,2,opt,name=minor,proto3" json:"minor,omitempty"` +} + +func (x *Version) Reset() { + *x = Version{} + if protoimpl.UnsafeEnabled { + mi := &file_refs_grpc_types_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Version) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Version) ProtoMessage() {} + +func (x *Version) ProtoReflect() protoreflect.Message { + mi := &file_refs_grpc_types_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Version.ProtoReflect.Descriptor instead. +func (*Version) Descriptor() ([]byte, []int) { + return file_refs_grpc_types_proto_rawDescGZIP(), []int{4} +} + +func (x *Version) GetMajor() uint32 { + if x != nil { + return x.Major + } + return 0 +} + +func (x *Version) GetMinor() uint32 { + if x != nil { + return x.Minor + } + return 0 +} + +// Signature of something in NeoFS. +type Signature struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Public key used for signing + Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` + // Signature + Sign []byte `protobuf:"bytes,2,opt,name=sign,json=signature,proto3" json:"sign,omitempty"` + // Scheme contains digital signature scheme identifier + Scheme SignatureScheme `protobuf:"varint,3,opt,name=scheme,proto3,enum=neo.fs.v2.refs.SignatureScheme" json:"scheme,omitempty"` +} + +func (x *Signature) Reset() { + *x = Signature{} + if protoimpl.UnsafeEnabled { + mi := &file_refs_grpc_types_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Signature) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Signature) ProtoMessage() {} + +func (x *Signature) ProtoReflect() protoreflect.Message { + mi := &file_refs_grpc_types_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Signature.ProtoReflect.Descriptor instead. +func (*Signature) Descriptor() ([]byte, []int) { + return file_refs_grpc_types_proto_rawDescGZIP(), []int{5} +} + +func (x *Signature) GetKey() []byte { + if x != nil { + return x.Key + } + return nil +} + +func (x *Signature) GetSign() []byte { + if x != nil { + return x.Sign + } + return nil +} + +func (x *Signature) GetScheme() SignatureScheme { + if x != nil { + return x.Scheme + } + return SignatureScheme_ECDSA_SHA512 +} + +// RFC 6979 signature. +type SignatureRFC6979 struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Public key used for signing + Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` + // Deterministic ECDSA with SHA-256 hashing + Sign []byte `protobuf:"bytes,2,opt,name=sign,json=signature,proto3" json:"sign,omitempty"` +} + +func (x *SignatureRFC6979) Reset() { + *x = SignatureRFC6979{} + if protoimpl.UnsafeEnabled { + mi := &file_refs_grpc_types_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SignatureRFC6979) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SignatureRFC6979) ProtoMessage() {} + +func (x *SignatureRFC6979) ProtoReflect() protoreflect.Message { + mi := &file_refs_grpc_types_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SignatureRFC6979.ProtoReflect.Descriptor instead. +func (*SignatureRFC6979) Descriptor() ([]byte, []int) { + return file_refs_grpc_types_proto_rawDescGZIP(), []int{6} +} + +func (x *SignatureRFC6979) GetKey() []byte { + if x != nil { + return x.Key + } + return nil +} + +func (x *SignatureRFC6979) GetSign() []byte { + if x != nil { + return x.Sign + } + return nil +} + +// Checksum message. +// Depending on checksum algorithm type, the string presentation may vary: +// +// - TZ \ +// Hex encoded string without `0x` prefix +// - SHA256 \ +// Hex encoded string without `0x` prefix +type Checksum struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Checksum algorithm type + Type ChecksumType `protobuf:"varint,1,opt,name=type,proto3,enum=neo.fs.v2.refs.ChecksumType" json:"type,omitempty"` + // Checksum itself + Sum []byte `protobuf:"bytes,2,opt,name=sum,proto3" json:"sum,omitempty"` +} + +func (x *Checksum) Reset() { + *x = Checksum{} + if protoimpl.UnsafeEnabled { + mi := &file_refs_grpc_types_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Checksum) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Checksum) ProtoMessage() {} + +func (x *Checksum) ProtoReflect() protoreflect.Message { + mi := &file_refs_grpc_types_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Checksum.ProtoReflect.Descriptor instead. +func (*Checksum) Descriptor() ([]byte, []int) { + return file_refs_grpc_types_proto_rawDescGZIP(), []int{7} +} + +func (x *Checksum) GetType() ChecksumType { + if x != nil { + return x.Type + } + return ChecksumType_CHECKSUM_TYPE_UNSPECIFIED +} + +func (x *Checksum) GetSum() []byte { + if x != nil { + return x.Sum + } + return nil +} + +var File_refs_grpc_types_proto protoreflect.FileDescriptor + +var file_refs_grpc_types_proto_rawDesc = []byte{ + 0x0a, 0x15, 0x72, 0x65, 0x66, 0x73, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x74, 0x79, 0x70, 0x65, + 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, + 0x76, 0x32, 0x2e, 0x72, 0x65, 0x66, 0x73, 0x22, 0x80, 0x01, 0x0a, 0x07, 0x41, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x12, 0x3e, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, + 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, + 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x65, 0x66, 0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, + 0x69, 0x6e, 0x65, 0x72, 0x49, 0x44, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, + 0x72, 0x49, 0x44, 0x12, 0x35, 0x0a, 0x09, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69, 0x64, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, + 0x76, 0x32, 0x2e, 0x72, 0x65, 0x66, 0x73, 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x44, + 0x52, 0x08, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x44, 0x22, 0x20, 0x0a, 0x08, 0x4f, 0x62, + 0x6a, 0x65, 0x63, 0x74, 0x49, 0x44, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x23, 0x0a, 0x0b, + 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x44, 0x12, 0x14, 0x0a, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x22, 0x1f, 0x0a, 0x07, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x49, 0x44, 0x12, 0x14, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x22, 0x35, 0x0a, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, + 0x05, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x6d, 0x61, + 0x6a, 0x6f, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x05, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x22, 0x6f, 0x0a, 0x09, 0x53, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x17, 0x0a, 0x04, 0x73, 0x69, 0x67, 0x6e, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x12, 0x37, 0x0a, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0e, 0x32, 0x1f, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x65, + 0x66, 0x73, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x63, 0x68, 0x65, + 0x6d, 0x65, 0x52, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x22, 0x3d, 0x0a, 0x10, 0x53, 0x69, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x46, 0x43, 0x36, 0x39, 0x37, 0x39, 0x12, 0x10, + 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6b, 0x65, 0x79, + 0x12, 0x17, 0x0a, 0x04, 0x73, 0x69, 0x67, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, + 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x4e, 0x0a, 0x08, 0x43, 0x68, 0x65, + 0x63, 0x6b, 0x73, 0x75, 0x6d, 0x12, 0x30, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, + 0x72, 0x65, 0x66, 0x73, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0x54, 0x79, 0x70, + 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x75, 0x6d, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x73, 0x75, 0x6d, 0x2a, 0x66, 0x0a, 0x0f, 0x53, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x0c, + 0x45, 0x43, 0x44, 0x53, 0x41, 0x5f, 0x53, 0x48, 0x41, 0x35, 0x31, 0x32, 0x10, 0x00, 0x12, 0x18, + 0x0a, 0x14, 0x45, 0x43, 0x44, 0x53, 0x41, 0x5f, 0x52, 0x46, 0x43, 0x36, 0x39, 0x37, 0x39, 0x5f, + 0x53, 0x48, 0x41, 0x32, 0x35, 0x36, 0x10, 0x01, 0x12, 0x27, 0x0a, 0x23, 0x45, 0x43, 0x44, 0x53, + 0x41, 0x5f, 0x52, 0x46, 0x43, 0x36, 0x39, 0x37, 0x39, 0x5f, 0x53, 0x48, 0x41, 0x32, 0x35, 0x36, + 0x5f, 0x57, 0x41, 0x4c, 0x4c, 0x45, 0x54, 0x5f, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x10, + 0x02, 0x2a, 0x41, 0x0a, 0x0c, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0x54, 0x79, 0x70, + 0x65, 0x12, 0x1d, 0x0a, 0x19, 0x43, 0x48, 0x45, 0x43, 0x4b, 0x53, 0x55, 0x4d, 0x5f, 0x54, 0x59, + 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, + 0x12, 0x06, 0x0a, 0x02, 0x54, 0x5a, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x48, 0x41, 0x32, + 0x35, 0x36, 0x10, 0x02, 0x42, 0x5b, 0x5a, 0x3e, 0x67, 0x69, 0x74, 0x2e, 0x66, 0x72, 0x6f, 0x73, + 0x74, 0x66, 0x73, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, 0x75, 0x65, 0x43, 0x6c, 0x6f, + 0x75, 0x64, 0x4c, 0x61, 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2d, 0x61, 0x70, + 0x69, 0x2d, 0x67, 0x6f, 0x2f, 0x76, 0x32, 0x2f, 0x72, 0x65, 0x66, 0x73, 0x2f, 0x67, 0x72, 0x70, + 0x63, 0x3b, 0x72, 0x65, 0x66, 0x73, 0xaa, 0x02, 0x18, 0x4e, 0x65, 0x6f, 0x2e, 0x46, 0x69, 0x6c, + 0x65, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x41, 0x50, 0x49, 0x2e, 0x52, 0x65, 0x66, + 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_refs_grpc_types_proto_rawDescOnce sync.Once + file_refs_grpc_types_proto_rawDescData = file_refs_grpc_types_proto_rawDesc +) + +func file_refs_grpc_types_proto_rawDescGZIP() []byte { + file_refs_grpc_types_proto_rawDescOnce.Do(func() { + file_refs_grpc_types_proto_rawDescData = protoimpl.X.CompressGZIP(file_refs_grpc_types_proto_rawDescData) + }) + return file_refs_grpc_types_proto_rawDescData +} + +var file_refs_grpc_types_proto_enumTypes = make([]protoimpl.EnumInfo, 2) +var file_refs_grpc_types_proto_msgTypes = make([]protoimpl.MessageInfo, 8) +var file_refs_grpc_types_proto_goTypes = []interface{}{ + (SignatureScheme)(0), // 0: neo.fs.v2.refs.SignatureScheme + (ChecksumType)(0), // 1: neo.fs.v2.refs.ChecksumType + (*Address)(nil), // 2: neo.fs.v2.refs.Address + (*ObjectID)(nil), // 3: neo.fs.v2.refs.ObjectID + (*ContainerID)(nil), // 4: neo.fs.v2.refs.ContainerID + (*OwnerID)(nil), // 5: neo.fs.v2.refs.OwnerID + (*Version)(nil), // 6: neo.fs.v2.refs.Version + (*Signature)(nil), // 7: neo.fs.v2.refs.Signature + (*SignatureRFC6979)(nil), // 8: neo.fs.v2.refs.SignatureRFC6979 + (*Checksum)(nil), // 9: neo.fs.v2.refs.Checksum +} +var file_refs_grpc_types_proto_depIdxs = []int32{ + 4, // 0: neo.fs.v2.refs.Address.container_id:type_name -> neo.fs.v2.refs.ContainerID + 3, // 1: neo.fs.v2.refs.Address.object_id:type_name -> neo.fs.v2.refs.ObjectID + 0, // 2: neo.fs.v2.refs.Signature.scheme:type_name -> neo.fs.v2.refs.SignatureScheme + 1, // 3: neo.fs.v2.refs.Checksum.type:type_name -> neo.fs.v2.refs.ChecksumType + 4, // [4:4] is the sub-list for method output_type + 4, // [4:4] is the sub-list for method input_type + 4, // [4:4] is the sub-list for extension type_name + 4, // [4:4] is the sub-list for extension extendee + 0, // [0:4] is the sub-list for field type_name +} + +func init() { file_refs_grpc_types_proto_init() } +func file_refs_grpc_types_proto_init() { + if File_refs_grpc_types_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_refs_grpc_types_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Address); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_refs_grpc_types_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ObjectID); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_refs_grpc_types_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ContainerID); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_refs_grpc_types_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*OwnerID); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_refs_grpc_types_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Version); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_refs_grpc_types_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Signature); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_refs_grpc_types_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SignatureRFC6979); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_refs_grpc_types_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Checksum); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_refs_grpc_types_proto_rawDesc, + NumEnums: 2, + NumMessages: 8, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_refs_grpc_types_proto_goTypes, + DependencyIndexes: file_refs_grpc_types_proto_depIdxs, + EnumInfos: file_refs_grpc_types_proto_enumTypes, + MessageInfos: file_refs_grpc_types_proto_msgTypes, + }.Build() + File_refs_grpc_types_proto = out.File + file_refs_grpc_types_proto_rawDesc = nil + file_refs_grpc_types_proto_goTypes = nil + file_refs_grpc_types_proto_depIdxs = nil +} diff --git a/pkg/api/refs/json.go b/pkg/api/refs/json.go new file mode 100644 index 000000000..422441df9 --- /dev/null +++ b/pkg/api/refs/json.go @@ -0,0 +1,62 @@ +package refs + +import ( + refs "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/message" +) + +func (a *Address) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(a) +} + +func (a *Address) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(a, data, new(refs.Address)) +} + +func (o *ObjectID) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(o) +} + +func (o *ObjectID) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(o, data, new(refs.ObjectID)) +} + +func (c *ContainerID) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(c) +} + +func (c *ContainerID) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(c, data, new(refs.ContainerID)) +} + +func (o *OwnerID) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(o) +} + +func (o *OwnerID) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(o, data, new(refs.OwnerID)) +} + +func (v *Version) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(v) +} + +func (v *Version) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(v, data, new(refs.Version)) +} + +func (s *Signature) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(s) +} + +func (s *Signature) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(s, data, new(refs.Signature)) +} + +func (c *Checksum) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(c) +} + +func (c *Checksum) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(c, data, new(refs.Checksum)) +} diff --git a/pkg/api/refs/marshal.go b/pkg/api/refs/marshal.go new file mode 100644 index 000000000..c8ff445db --- /dev/null +++ b/pkg/api/refs/marshal.go @@ -0,0 +1,264 @@ +package refs + +import ( + "encoding/binary" + + refs "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/message" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/util/proto" + "google.golang.org/protobuf/encoding/protowire" +) + +const ( + ownerIDValField = 1 + + containerIDValField = 1 + + objectIDValField = 1 + + addressContainerField = 1 + addressObjectField = 2 + + checksumTypeField = 1 + checksumValueField = 2 + + signatureKeyField = 1 + signatureValueField = 2 + signatureSchemeField = 3 + + versionMajorField = 1 + versionMinorField = 2 +) + +func (o *OwnerID) StableMarshal(buf []byte) []byte { + if o == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, o.StableSize()) + } + + proto.BytesMarshal(ownerIDValField, buf, o.val) + + return buf +} + +func (o *OwnerID) StableSize() int { + if o == nil { + return 0 + } + + return proto.BytesSize(ownerIDValField, o.val) +} + +func (o *OwnerID) Unmarshal(data []byte) error { + return message.Unmarshal(o, data, new(refs.OwnerID)) +} + +func (c *ContainerID) StableMarshal(buf []byte) []byte { + if c == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, c.StableSize()) + } + + proto.BytesMarshal(containerIDValField, buf, c.val) + + return buf +} + +func (c *ContainerID) StableSize() int { + if c == nil { + return 0 + } + + return proto.BytesSize(containerIDValField, c.val) +} + +func (c *ContainerID) Unmarshal(data []byte) error { + return message.Unmarshal(c, data, new(refs.ContainerID)) +} + +func (o *ObjectID) StableMarshal(buf []byte) []byte { + if o == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, o.StableSize()) + } + + proto.BytesMarshal(objectIDValField, buf, o.val) + + return buf +} + +// ObjectIDNestedListSize returns byte length of nested +// repeated ObjectID field with fNum number. +func ObjectIDNestedListSize(fNum int64, ids []ObjectID) (sz int) { + for i := range ids { + sz += proto.NestedStructureSize(fNum, &ids[i]) + } + + return +} + +func (o *ObjectID) StableSize() int { + if o == nil { + return 0 + } + + return proto.BytesSize(objectIDValField, o.val) +} + +// ObjectIDNestedListMarshal writes protobuf repeated ObjectID field +// with fNum number to buf. +func ObjectIDNestedListMarshal(fNum int64, buf []byte, ids []ObjectID) (off int) { + prefix := protowire.EncodeTag(protowire.Number(fNum), protowire.BytesType) + for i := range ids { + off += binary.PutUvarint(buf[off:], prefix) + + n := ids[i].StableSize() + off += binary.PutUvarint(buf[off:], uint64(n)) + off += proto.BytesMarshal(objectIDValField, buf[off:], ids[i].val) + } + + return +} + +func (o *ObjectID) Unmarshal(data []byte) error { + return message.Unmarshal(o, data, new(refs.ObjectID)) +} + +func (a *Address) StableMarshal(buf []byte) []byte { + if a == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, a.StableSize()) + } + + var offset int + + offset += proto.NestedStructureMarshal(addressContainerField, buf[offset:], a.cid) + proto.NestedStructureMarshal(addressObjectField, buf[offset:], a.oid) + + return buf +} + +func (a *Address) StableSize() (size int) { + if a == nil { + return 0 + } + + size += proto.NestedStructureSize(addressContainerField, a.cid) + size += proto.NestedStructureSize(addressObjectField, a.oid) + + return size +} + +func (a *Address) Unmarshal(data []byte) error { + return message.Unmarshal(a, data, new(refs.Address)) +} + +func (c *Checksum) StableMarshal(buf []byte) []byte { + if c == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, c.StableSize()) + } + + var offset int + + offset += proto.EnumMarshal(checksumTypeField, buf[offset:], int32(c.typ)) + proto.BytesMarshal(checksumValueField, buf[offset:], c.sum) + + return buf +} + +func (c *Checksum) StableSize() (size int) { + if c == nil { + return 0 + } + + size += proto.EnumSize(checksumTypeField, int32(c.typ)) + size += proto.BytesSize(checksumValueField, c.sum) + + return size +} + +func (c *Checksum) Unmarshal(data []byte) error { + return message.Unmarshal(c, data, new(refs.Checksum)) +} + +func (s *Signature) StableMarshal(buf []byte) []byte { + if s == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, s.StableSize()) + } + + var offset int + + offset += proto.BytesMarshal(signatureKeyField, buf[offset:], s.key) + offset += proto.BytesMarshal(signatureValueField, buf[offset:], s.sign) + proto.EnumMarshal(signatureSchemeField, buf[offset:], int32(s.scheme)) + + return buf +} + +func (s *Signature) StableSize() (size int) { + if s == nil { + return 0 + } + + size += proto.BytesSize(signatureKeyField, s.key) + size += proto.BytesSize(signatureValueField, s.sign) + size += proto.EnumSize(signatureSchemeField, int32(s.scheme)) + + return size +} + +func (s *Signature) Unmarshal(data []byte) error { + return message.Unmarshal(s, data, new(refs.Signature)) +} + +func (v *Version) StableMarshal(buf []byte) []byte { + if v == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, v.StableSize()) + } + + var offset int + + offset += proto.UInt32Marshal(versionMajorField, buf[offset:], v.major) + proto.UInt32Marshal(versionMinorField, buf[offset:], v.minor) + + return buf +} + +func (v *Version) StableSize() (size int) { + if v == nil { + return 0 + } + + size += proto.UInt32Size(versionMajorField, v.major) + size += proto.UInt32Size(versionMinorField, v.minor) + + return size +} + +func (v *Version) Unmarshal(data []byte) error { + return message.Unmarshal(v, data, new(refs.Version)) +} diff --git a/pkg/api/refs/message_test.go b/pkg/api/refs/message_test.go new file mode 100644 index 000000000..b2cd0a770 --- /dev/null +++ b/pkg/api/refs/message_test.go @@ -0,0 +1,21 @@ +package refs_test + +import ( + "testing" + + refstest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs/test" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/message" + messagetest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/message/test" +) + +func TestMessageConvert(t *testing.T) { + messagetest.TestRPCMessage(t, + func(empty bool) message.Message { return refstest.GenerateOwnerID(empty) }, + func(empty bool) message.Message { return refstest.GenerateObjectID(empty) }, + func(empty bool) message.Message { return refstest.GenerateContainerID(empty) }, + func(empty bool) message.Message { return refstest.GenerateAddress(empty) }, + func(empty bool) message.Message { return refstest.GenerateChecksum(empty) }, + func(empty bool) message.Message { return refstest.GenerateSignature(empty) }, + func(empty bool) message.Message { return refstest.GenerateVersion(empty) }, + ) +} diff --git a/pkg/api/refs/string.go b/pkg/api/refs/string.go new file mode 100644 index 000000000..89aba25e4 --- /dev/null +++ b/pkg/api/refs/string.go @@ -0,0 +1,47 @@ +package refs + +import ( + refs "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs/grpc" +) + +// String returns string representation of ChecksumType. +func (t ChecksumType) String() string { + return ChecksumTypeToGRPC(t).String() +} + +// FromString parses ChecksumType from a string representation. +// It is a reverse action to String(). +// +// Returns true if s was parsed successfully. +func (t *ChecksumType) FromString(s string) bool { + var g refs.ChecksumType + + ok := g.FromString(s) + + if ok { + *t = ChecksumTypeFromGRPC(g) + } + + return ok +} + +// String returns string representation of SignatureScheme. +func (t SignatureScheme) String() string { + return refs.SignatureScheme(t).String() +} + +// FromString parses SignatureScheme from a string representation. +// It is a reverse action to String(). +// +// Returns true if s was parsed successfully. +func (t *SignatureScheme) FromString(s string) bool { + var g refs.SignatureScheme + + ok := g.FromString(s) + + if ok { + *t = SignatureScheme(g) + } + + return ok +} diff --git a/pkg/api/refs/test/generate.go b/pkg/api/refs/test/generate.go new file mode 100644 index 000000000..87ea4a58b --- /dev/null +++ b/pkg/api/refs/test/generate.go @@ -0,0 +1,108 @@ +package refstest + +import ( + "math/rand" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" +) + +func GenerateVersion(empty bool) *refs.Version { + m := new(refs.Version) + + if !empty { + m.SetMajor(2) + m.SetMinor(1) + } + + return m +} + +func GenerateOwnerID(empty bool) *refs.OwnerID { + m := new(refs.OwnerID) + + if !empty { + m.SetValue([]byte{1, 2, 3}) + } + + return m +} + +func GenerateAddress(empty bool) *refs.Address { + m := new(refs.Address) + + if !empty { + m.SetObjectID(GenerateObjectID(false)) + m.SetContainerID(GenerateContainerID(false)) + } + + return m +} + +func GenerateObjectID(empty bool) *refs.ObjectID { + m := new(refs.ObjectID) + + if !empty { + m.SetValue([]byte{1, 2, 3}) + } + + return m +} + +func GenerateObjectIDs(empty bool) []refs.ObjectID { + var ids []refs.ObjectID + + if !empty { + ids = append(ids, + *GenerateObjectID(false), + *GenerateObjectID(false), + ) + } + + return ids +} + +func GenerateContainerID(empty bool) *refs.ContainerID { + m := new(refs.ContainerID) + + if !empty { + m.SetValue([]byte{1, 2, 3}) + } + + return m +} + +func GenerateContainerIDs(empty bool) []refs.ContainerID { + var res []refs.ContainerID + + if !empty { + res = append(res, + *GenerateContainerID(false), + *GenerateContainerID(false), + ) + } + + return res +} + +func GenerateSignature(empty bool) *refs.Signature { + m := new(refs.Signature) + + if !empty { + m.SetKey([]byte{1}) + m.SetSign([]byte{2}) + m.SetScheme(refs.SignatureScheme(rand.Int31() % 3)) + } + + return m +} + +func GenerateChecksum(empty bool) *refs.Checksum { + m := new(refs.Checksum) + + if !empty { + m.SetType(1) + m.SetSum([]byte{1, 2, 3}) + } + + return m +} diff --git a/pkg/api/refs/types.go b/pkg/api/refs/types.go new file mode 100644 index 000000000..d8f0d9b92 --- /dev/null +++ b/pkg/api/refs/types.go @@ -0,0 +1,194 @@ +package refs + +type OwnerID struct { + val []byte +} + +type ContainerID struct { + val []byte +} + +type ObjectID struct { + val []byte +} + +type Address struct { + cid *ContainerID + + oid *ObjectID +} + +type Checksum struct { + typ ChecksumType + + sum []byte +} + +type ChecksumType uint32 + +type SignatureScheme uint32 + +//nolint:revive +const ( + ECDSA_SHA512 SignatureScheme = iota + ECDSA_RFC6979_SHA256 + ECDSA_RFC6979_SHA256_WALLET_CONNECT +) + +type Signature struct { + key, sign []byte + scheme SignatureScheme +} + +type Version struct { + major, minor uint32 +} + +const ( + UnknownChecksum ChecksumType = iota + TillichZemor + SHA256 +) + +func (o *OwnerID) GetValue() []byte { + if o != nil { + return o.val + } + + return nil +} + +func (o *OwnerID) SetValue(v []byte) { + o.val = v +} + +func (c *ContainerID) GetValue() []byte { + if c != nil { + return c.val + } + + return nil +} + +func (c *ContainerID) SetValue(v []byte) { + c.val = v +} + +func (o *ObjectID) GetValue() []byte { + if o != nil { + return o.val + } + + return nil +} + +func (o *ObjectID) SetValue(v []byte) { + o.val = v +} + +func (a *Address) GetContainerID() *ContainerID { + if a != nil { + return a.cid + } + + return nil +} + +func (a *Address) SetContainerID(v *ContainerID) { + a.cid = v +} + +func (a *Address) GetObjectID() *ObjectID { + if a != nil { + return a.oid + } + + return nil +} + +func (a *Address) SetObjectID(v *ObjectID) { + a.oid = v +} + +func (c *Checksum) GetType() ChecksumType { + if c != nil { + return c.typ + } + + return UnknownChecksum +} + +func (c *Checksum) SetType(v ChecksumType) { + c.typ = v +} + +func (c *Checksum) GetSum() []byte { + if c != nil { + return c.sum + } + + return nil +} + +func (c *Checksum) SetSum(v []byte) { + c.sum = v +} + +func (s *Signature) GetKey() []byte { + if s != nil { + return s.key + } + + return nil +} + +func (s *Signature) SetKey(v []byte) { + s.key = v +} + +func (s *Signature) GetSign() []byte { + if s != nil { + return s.sign + } + + return nil +} + +func (s *Signature) SetSign(v []byte) { + s.sign = v +} + +func (s *Signature) GetScheme() SignatureScheme { + if s != nil { + return s.scheme + } + return 0 +} + +func (s *Signature) SetScheme(scheme SignatureScheme) { + s.scheme = scheme +} + +func (v *Version) GetMajor() uint32 { + if v != nil { + return v.major + } + + return 0 +} + +func (v *Version) SetMajor(val uint32) { + v.major = val +} + +func (v *Version) GetMinor() uint32 { + if v != nil { + return v.minor + } + + return 0 +} + +func (v *Version) SetMinor(val uint32) { + v.minor = val +} diff --git a/pkg/api/rpc/accounting.go b/pkg/api/rpc/accounting.go new file mode 100644 index 000000000..1c9f6bb70 --- /dev/null +++ b/pkg/api/rpc/accounting.go @@ -0,0 +1,29 @@ +package rpc + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/accounting" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/common" +) + +const serviceAccounting = serviceNamePrefix + "accounting.AccountingService" + +const ( + rpcAccountingBalance = "Balance" +) + +// Balance executes AccountingService.Balance RPC. +func Balance( + cli *client.Client, + req *accounting.BalanceRequest, + opts ...client.CallOption, +) (*accounting.BalanceResponse, error) { + resp := new(accounting.BalanceResponse) + + err := client.SendUnary(cli, common.CallMethodInfoUnary(serviceAccounting, rpcAccountingBalance), req, resp, opts...) + if err != nil { + return nil, err + } + + return resp, nil +} diff --git a/pkg/api/rpc/client/call_options.go b/pkg/api/rpc/client/call_options.go new file mode 100644 index 000000000..8134e465f --- /dev/null +++ b/pkg/api/rpc/client/call_options.go @@ -0,0 +1,29 @@ +package client + +import ( + "context" +) + +// CallOption is a messaging session option within Protobuf RPC. +type CallOption func(*callParameters) + +type callParameters struct { + ctx context.Context // nolint:containedctx +} + +func defaultCallParameters() *callParameters { + return &callParameters{ + ctx: context.Background(), + } +} + +// WithContext returns option to specify call context. If provided, all network +// communications will be based on this context. Otherwise, context.Background() +// is used. +// +// Context SHOULD NOT be nil. +func WithContext(ctx context.Context) CallOption { + return func(prm *callParameters) { + prm.ctx = ctx + } +} diff --git a/pkg/api/rpc/client/client.go b/pkg/api/rpc/client/client.go new file mode 100644 index 000000000..7e914dbef --- /dev/null +++ b/pkg/api/rpc/client/client.go @@ -0,0 +1,28 @@ +package client + +import ( + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" +) + +// Client represents client for exchanging messages +// with a remote server using Protobuf RPC. +type Client struct { + cfg +} + +// New creates, configures via options and returns new Client instance. +func New(opts ...Option) *Client { + var c Client + c.initDefault() + + for _, opt := range opts { + opt(&c.cfg) + } + + if c.tlsCfg != nil { + c.grpcDialOpts = append(c.grpcDialOpts, grpc.WithTransportCredentials(credentials.NewTLS(c.tlsCfg))) + } + + return &c +} diff --git a/pkg/api/rpc/client/conn.go b/pkg/api/rpc/client/conn.go new file mode 100644 index 000000000..9fc7a5126 --- /dev/null +++ b/pkg/api/rpc/client/conn.go @@ -0,0 +1,16 @@ +package client + +import ( + "io" +) + +// Conn returns underlying connection. +// +// Returns non-nil result after the first Init() call +// completed without a connection error. +// +// Client should not be used after Close() call +// on the connection: behavior is undefined. +func (c *Client) Conn() io.Closer { + return c.conn +} diff --git a/pkg/api/rpc/client/connect.go b/pkg/api/rpc/client/connect.go new file mode 100644 index 000000000..29f418927 --- /dev/null +++ b/pkg/api/rpc/client/connect.go @@ -0,0 +1,66 @@ +package client + +import ( + "context" + "errors" + "fmt" + "net" + "net/url" + + grpcstd "google.golang.org/grpc" +) + +var errInvalidEndpoint = errors.New("invalid endpoint options") + +func (c *Client) openGRPCConn(ctx context.Context) error { + if c.conn != nil { + return nil + } + + if c.addr == "" { + return errInvalidEndpoint + } + + dialCtx, cancel := context.WithTimeout(ctx, c.dialTimeout) + var err error + + c.conn, err = grpcstd.DialContext(dialCtx, c.addr, c.grpcDialOpts...) + + cancel() + + if err != nil { + return fmt.Errorf("gRPC dial: %w", err) + } + + return nil +} + +// ParseURI parses s as address and returns a host and a flag +// indicating that TLS is enabled. If multi-address is provided +// the argument is returned unchanged. +func ParseURI(s string) (string, bool, error) { + uri, err := url.ParseRequestURI(s) + if err != nil { + return s, false, nil + } + + // check if passed string was parsed correctly + // URIs that do not start with a slash after the scheme are interpreted as: + // `scheme:opaque` => if `opaque` is not empty, then it is supposed that URI + // is in `host:port` format + if uri.Host == "" { + uri.Host = uri.Scheme + uri.Scheme = grpcScheme // assume GRPC by default + if uri.Opaque != "" { + uri.Host = net.JoinHostPort(uri.Host, uri.Opaque) + } + } + + switch uri.Scheme { + case grpcTLSScheme, grpcScheme: + default: + return "", false, fmt.Errorf("unsupported scheme: %s", uri.Scheme) + } + + return uri.Host, uri.Scheme == grpcTLSScheme, nil +} diff --git a/pkg/api/rpc/client/flows.go b/pkg/api/rpc/client/flows.go new file mode 100644 index 000000000..93c99dbef --- /dev/null +++ b/pkg/api/rpc/client/flows.go @@ -0,0 +1,124 @@ +package client + +import ( + "errors" + "io" + "sync" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/message" +) + +// SendUnary initializes communication session by RPC info, performs unary RPC +// and closes the session. +func SendUnary(cli *Client, info common.CallMethodInfo, req, resp message.Message, opts ...CallOption) error { + rw, err := cli.Init(info, opts...) + if err != nil { + return err + } + + err = rw.WriteMessage(req) + if err != nil { + return err + } + + err = rw.ReadMessage(resp) + if err != nil { + return err + } + + return rw.Close() +} + +// MessageWriterCloser wraps MessageWriter +// and io.Closer interfaces. +type MessageWriterCloser interface { + MessageWriter + io.Closer +} + +type clientStreamWriterCloser struct { + MessageReadWriter + + resp message.Message +} + +func (c *clientStreamWriterCloser) Close() error { + err := c.MessageReadWriter.Close() + if err != nil { + return err + } + + return c.ReadMessage(c.resp) +} + +// OpenClientStream initializes communication session by RPC info, opens client-side stream +// and returns its interface. +// +// All stream writes must be performed before the closing. Close must be called once. +func OpenClientStream(cli *Client, info common.CallMethodInfo, resp message.Message, opts ...CallOption) (MessageWriterCloser, error) { + rw, err := cli.Init(info, opts...) + if err != nil { + return nil, err + } + + return &clientStreamWriterCloser{ + MessageReadWriter: rw, + resp: resp, + }, nil +} + +// MessageReaderCloser wraps MessageReader +// and io.Closer interface. +type MessageReaderCloser interface { + MessageReader + io.Closer +} + +type serverStreamReaderCloser struct { + rw MessageReadWriter + + once sync.Once + + req message.Message +} + +func (s *serverStreamReaderCloser) ReadMessage(msg message.Message) error { + var err error + + s.once.Do(func() { + err = s.rw.WriteMessage(s.req) + }) + + if err != nil { + return err + } + + err = s.rw.ReadMessage(msg) + if !errors.Is(err, io.EOF) { + return err + } + + err = s.rw.Close() + if err != nil { + return err + } + + return io.EOF +} + +// OpenServerStream initializes communication session by RPC info, opens server-side stream +// and returns its interface. +// +// All stream reads must be performed before the closing. Close must be called once. +func OpenServerStream(cli *Client, info common.CallMethodInfo, req message.Message, opts ...CallOption) (MessageReader, error) { + rw, err := cli.Init(info, opts...) + if err != nil { + return nil, err + } + + return &serverStreamReaderCloser{ + rw: rw, + req: req, + }, nil +} diff --git a/pkg/api/rpc/client/init.go b/pkg/api/rpc/client/init.go new file mode 100644 index 000000000..c3b979b66 --- /dev/null +++ b/pkg/api/rpc/client/init.go @@ -0,0 +1,69 @@ +package client + +import ( + "context" + "io" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/message" + "google.golang.org/grpc" +) + +// MessageReader is an interface of the Message reader. +type MessageReader interface { + // ReadMessage reads the next Message. + // + // Returns io.EOF if there are no more messages to read. + // ReadMessage should not be called after io.EOF occasion. + ReadMessage(message.Message) error +} + +// MessageWriter is an interface of the Message writer. +type MessageWriter interface { + // WriteMessage writers the next Message. + // + // WriteMessage should not be called after any error. + WriteMessage(message.Message) error +} + +// MessageReadWriter is a component interface +// for transmitting raw Protobuf messages. +type MessageReadWriter interface { + MessageReader + MessageWriter + + // Closes the communication session. + // + // All calls to send/receive messages must be done before closing. + io.Closer +} + +// Init initiates a messaging session and returns the interface for message transmitting. +func (c *Client) Init(info common.CallMethodInfo, opts ...CallOption) (MessageReadWriter, error) { + prm := defaultCallParameters() + + for _, opt := range opts { + opt(prm) + } + + if err := c.openGRPCConn(prm.ctx); err != nil { + return nil, err + } + + ctx, cancel := context.WithCancel(prm.ctx) + stream, err := c.conn.NewStream(ctx, &grpc.StreamDesc{ + StreamName: info.Name, + ServerStreams: info.ServerStream(), + ClientStreams: info.ClientStream(), + }, toMethodName(info)) + if err != nil { + cancel() + return nil, err + } + + return &streamWrapper{ + ClientStream: stream, + cancel: cancel, + timeout: c.rwTimeout, + }, nil +} diff --git a/pkg/api/rpc/client/options.go b/pkg/api/rpc/client/options.go new file mode 100644 index 000000000..0575dfccd --- /dev/null +++ b/pkg/api/rpc/client/options.go @@ -0,0 +1,130 @@ +package client + +import ( + "crypto/tls" + "time" + + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" +) + +const ( + grpcScheme = "grpc" + grpcTLSScheme = "grpcs" +) + +// Option is a Client's option. +type Option func(*cfg) + +type cfg struct { + addr string + + dialTimeout time.Duration + rwTimeout time.Duration + + tlsCfg *tls.Config + grpcDialOpts []grpc.DialOption + + conn *grpc.ClientConn +} + +const ( + defaultDialTimeout = 5 * time.Second + defaultRWTimeout = 1 * time.Minute +) + +func (c *cfg) initDefault() { + c.dialTimeout = defaultDialTimeout + c.rwTimeout = defaultRWTimeout + c.grpcDialOpts = []grpc.DialOption{ + grpc.WithBlock(), + grpc.WithTransportCredentials(insecure.NewCredentials()), + } +} + +// WithNetworkAddress returns option to specify +// network address of the remote server. +// +// Ignored if WithGRPCConn is provided. +func WithNetworkAddress(v string) Option { + return func(c *cfg) { + if v != "" { + c.addr = v + } + } +} + +// WithNetworkURIAddress combines WithNetworkAddress and WithTLSCfg options +// based on arguments. +// +// Do not use along with WithNetworkAddress and WithTLSCfg. +// +// Ignored if WithGRPCConn is provided. +func WithNetworkURIAddress(addr string, tlsCfg *tls.Config) []Option { + host, isTLS, err := ParseURI(addr) + if err != nil { + return nil + } + + opts := make([]Option, 2) + opts[0] = WithNetworkAddress(host) + if isTLS { + if tlsCfg == nil { + tlsCfg = &tls.Config{} + } + opts[1] = WithTLSCfg(tlsCfg) + } else { + opts[1] = WithTLSCfg(nil) + } + + return opts +} + +// WithDialTimeout returns option to specify +// dial timeout of the remote server connection. +// +// Ignored if WithGRPCConn is provided. +func WithDialTimeout(v time.Duration) Option { + return func(c *cfg) { + if v > 0 { + c.dialTimeout = v + } + } +} + +// WithRWTimeout returns option to specify timeout +// for reading and writing single gRPC message. +func WithRWTimeout(v time.Duration) Option { + return func(c *cfg) { + if v > 0 { + c.rwTimeout = v + } + } +} + +// WithTLSCfg returns option to specify +// TLS configuration. +// +// Ignored if WithGRPCConn is provided. +func WithTLSCfg(v *tls.Config) Option { + return func(c *cfg) { + c.tlsCfg = v + } +} + +// WithGRPCConn returns option to specify +// gRPC virtual connection. +func WithGRPCConn(v *grpc.ClientConn) Option { + return func(c *cfg) { + if v != nil { + c.conn = v + } + } +} + +// WithGRPCDialOptions returns an option to specify grpc.DialOption. +func WithGRPCDialOptions(opts []grpc.DialOption) Option { + return func(c *cfg) { + c.grpcDialOpts = append(c.grpcDialOpts, opts...) + } +} diff --git a/pkg/api/rpc/client/options_test.go b/pkg/api/rpc/client/options_test.go new file mode 100644 index 000000000..56704b6c7 --- /dev/null +++ b/pkg/api/rpc/client/options_test.go @@ -0,0 +1,197 @@ +package client + +import ( + "crypto/tls" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestWithNetworkURIAddress(t *testing.T) { + hostPort := "frostfs.example.com:8080" + apiPort := "127.0.0.1:8080" + serverName := "testServer" + + testCases := []struct { + uri string + tlsConfig *tls.Config + + wantHost string + wantTLS bool + }{ + { + uri: grpcScheme + "://" + hostPort, + tlsConfig: nil, + wantHost: "frostfs.example.com:8080", + wantTLS: false, + }, + { + uri: grpcScheme + "://" + hostPort, + tlsConfig: &tls.Config{}, + wantHost: "frostfs.example.com:8080", + wantTLS: false, + }, + { + uri: grpcTLSScheme + "://" + hostPort, + tlsConfig: nil, + wantHost: "frostfs.example.com:8080", + wantTLS: true, + }, + { + uri: grpcTLSScheme + "://" + hostPort, + tlsConfig: &tls.Config{ServerName: serverName}, + wantHost: "frostfs.example.com:8080", + wantTLS: true, + }, + { + uri: "wrongScheme://" + hostPort, + tlsConfig: nil, + wantHost: "", + wantTLS: false, + }, + { + uri: "impossibleToParseIt", + tlsConfig: nil, + wantHost: "impossibleToParseIt", + wantTLS: false, + }, + { + uri: hostPort, + tlsConfig: nil, + wantHost: hostPort, + wantTLS: false, + }, + { + uri: apiPort, + tlsConfig: nil, + wantHost: apiPort, + wantTLS: false, + }, + } + + for _, test := range testCases { + cfg := &cfg{} + opts := WithNetworkURIAddress(test.uri, test.tlsConfig) + + for _, opt := range opts { + opt(cfg) + } + + require.Equal(t, test.wantHost, cfg.addr, test.uri) + require.Equal(t, test.wantTLS, cfg.tlsCfg != nil, test.uri) + // check if custom tlsConfig was applied + if test.tlsConfig != nil && test.wantTLS { + require.Equal(t, test.tlsConfig.ServerName, cfg.tlsCfg.ServerName, test.uri) + } + } +} + +func Test_WithNetworkAddress_WithTLS_WithNetworkURIAddress(t *testing.T) { + addr1, addr2 := "example1.com:8080", "example2.com:8080" + + testCases := []struct { + addr string + withTLS bool + + uri string + + wantHost string + wantTLS bool + }{ + { + addr: addr1, + withTLS: true, + + uri: grpcScheme + "://" + addr2, + + wantHost: addr2, + wantTLS: false, + }, + { + addr: addr1, + withTLS: false, + + uri: grpcTLSScheme + "://" + addr2, + + wantHost: addr2, + wantTLS: true, + }, + } + + for _, test := range testCases { + // order: + // 1. WithNetworkAddress + // 2. WithTLSCfg(if test.withTLS == true) + // 3. WithNetworkURIAddress + config := &cfg{} + opts := []Option{WithNetworkAddress(test.addr)} + + if test.withTLS { + opts = append(opts, WithTLSCfg(&tls.Config{})) + } + + opts = append(opts, WithNetworkURIAddress(test.uri, nil)...) + + for _, opt := range opts { + opt(config) + } + + require.Equal(t, test.wantHost, config.addr, test.addr) + require.Equal(t, test.wantTLS, config.tlsCfg != nil, test.addr) + } +} + +func Test_WithNetworkURIAddress_WithTLS_WithNetworkAddress(t *testing.T) { + addr1, addr2 := "example1.com:8080", "example2.com:8080" + + testCases := []struct { + addr string + withTLS bool + + uri string + + wantHost string + wantTLS bool + }{ + { + uri: grpcScheme + "://" + addr1, + + addr: addr2, + withTLS: true, + + wantHost: addr2, + wantTLS: true, + }, + { + uri: grpcTLSScheme + "://" + addr1, + + addr: addr2, + withTLS: false, + + wantHost: addr2, + wantTLS: true, + }, + } + + for _, test := range testCases { + // order: + // 1. WithNetworkURIAddress + // 2. WithNetworkAddress + // 3. WithTLSCfg(if test.withTLS == true) + config := &cfg{} + opts := WithNetworkURIAddress(test.uri, nil) + + opts = append(opts, WithNetworkAddress(test.addr)) + + if test.withTLS { + opts = append(opts, WithTLSCfg(&tls.Config{})) + } + + for _, opt := range opts { + opt(config) + } + + require.Equal(t, test.wantHost, config.addr, test.uri) + require.Equal(t, test.wantTLS, config.tlsCfg != nil, test.uri) + } +} diff --git a/pkg/api/rpc/client/stream_wrapper.go b/pkg/api/rpc/client/stream_wrapper.go new file mode 100644 index 000000000..fe05e5e01 --- /dev/null +++ b/pkg/api/rpc/client/stream_wrapper.go @@ -0,0 +1,58 @@ +package client + +import ( + "context" + "time" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/message" + "google.golang.org/grpc" +) + +type streamWrapper struct { + grpc.ClientStream + timeout time.Duration + cancel context.CancelFunc +} + +func (w streamWrapper) ReadMessage(m message.Message) error { + // Can be optimized: we can create blank message here. + gm := m.ToGRPCMessage() + + err := w.withTimeout(func() error { + return w.ClientStream.RecvMsg(gm) + }) + if err != nil { + return err + } + + return m.FromGRPCMessage(gm) +} + +func (w streamWrapper) WriteMessage(m message.Message) error { + return w.withTimeout(func() error { + return w.ClientStream.SendMsg(m.ToGRPCMessage()) + }) +} + +func (w *streamWrapper) Close() error { + return w.withTimeout(w.ClientStream.CloseSend) +} + +func (w *streamWrapper) withTimeout(closure func() error) error { + ch := make(chan error, 1) + go func() { + ch <- closure() + close(ch) + }() + + tt := time.NewTimer(w.timeout) + + select { + case err := <-ch: + tt.Stop() + return err + case <-tt.C: + w.cancel() + return context.DeadlineExceeded + } +} diff --git a/pkg/api/rpc/client/util.go b/pkg/api/rpc/client/util.go new file mode 100644 index 000000000..584d7f8b2 --- /dev/null +++ b/pkg/api/rpc/client/util.go @@ -0,0 +1,13 @@ +package client + +import ( + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/common" +) + +const methodNameFmt = "/%s/%s" + +func toMethodName(p common.CallMethodInfo) string { + return fmt.Sprintf(methodNameFmt, p.Service, p.Name) +} diff --git a/pkg/api/rpc/common.go b/pkg/api/rpc/common.go new file mode 100644 index 000000000..7d0bf56be --- /dev/null +++ b/pkg/api/rpc/common.go @@ -0,0 +1,3 @@ +package rpc + +const serviceNamePrefix = "neo.fs.v2." diff --git a/pkg/api/rpc/common/call.go b/pkg/api/rpc/common/call.go new file mode 100644 index 000000000..bc3410aac --- /dev/null +++ b/pkg/api/rpc/common/call.go @@ -0,0 +1,75 @@ +package common + +type callType uint8 + +const ( + _ callType = iota + callUnary + callClientStream + callServerStream + callBidirStream +) + +// CallMethodInfo is an information about the RPC. +type CallMethodInfo struct { + // Name of the service. + Service string + + // Name of the RPC. + Name string + + t callType +} + +// ServerStream checks if CallMethodInfo contains +// information about the server-side streaming RPC. +func (c CallMethodInfo) ServerStream() bool { + return c.t == callServerStream || c.t == callBidirStream +} + +// ClientStream checks if CallMethodInfo contains +// information about the client-side streaming RPC. +func (c CallMethodInfo) ClientStream() bool { + return c.t == callClientStream || c.t == callBidirStream +} + +func (c *CallMethodInfo) setCommon(service, name string) { + c.Service = service + c.Name = name +} + +// CallMethodInfoUnary returns CallMethodInfo structure +// initialized for the unary RPC. +func CallMethodInfoUnary(service, name string) (info CallMethodInfo) { + info.setCommon(service, name) + info.t = callUnary + + return +} + +// CallMethodInfoClientStream returns CallMethodInfo structure +// initialized for the client-side streaming RPC. +func CallMethodInfoClientStream(service, name string) (info CallMethodInfo) { + info.setCommon(service, name) + info.t = callClientStream + + return +} + +// CallMethodInfoServerStream returns CallMethodInfo structure +// initialized for the server-side streaming RPC. +func CallMethodInfoServerStream(service, name string) (info CallMethodInfo) { + info.setCommon(service, name) + info.t = callServerStream + + return +} + +// CallMethodInfoBidirectionalStream returns CallMethodInfo structure +// initialized for the bidirectional streaming RPC. +func CallMethodInfoBidirectionalStream(service, name string) (info CallMethodInfo) { + info.setCommon(service, name) + info.t = callBidirStream + + return +} diff --git a/pkg/api/rpc/common/call_test.go b/pkg/api/rpc/common/call_test.go new file mode 100644 index 000000000..03927d950 --- /dev/null +++ b/pkg/api/rpc/common/call_test.go @@ -0,0 +1,49 @@ +package common_test + +import ( + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/common" + "github.com/stretchr/testify/require" +) + +const ( + testServiceName = "test service" + testRPCName = "test RPC" +) + +func TestCallMethodInfoUnary(t *testing.T) { + i := common.CallMethodInfoUnary(testServiceName, testRPCName) + + require.Equal(t, testServiceName, i.Service) + require.Equal(t, testRPCName, i.Name) + require.False(t, i.ClientStream()) + require.False(t, i.ServerStream()) +} + +func TestCallMethodInfoServerStream(t *testing.T) { + i := common.CallMethodInfoServerStream(testServiceName, testRPCName) + + require.Equal(t, testServiceName, i.Service) + require.Equal(t, testRPCName, i.Name) + require.False(t, i.ClientStream()) + require.True(t, i.ServerStream()) +} + +func TestCallMethodInfoClientStream(t *testing.T) { + i := common.CallMethodInfoClientStream(testServiceName, testRPCName) + + require.Equal(t, testServiceName, i.Service) + require.Equal(t, testRPCName, i.Name) + require.True(t, i.ClientStream()) + require.False(t, i.ServerStream()) +} + +func TestCallMethodInfoBidirectionalStream(t *testing.T) { + i := common.CallMethodInfoBidirectionalStream(testServiceName, testRPCName) + + require.Equal(t, testServiceName, i.Service) + require.Equal(t, testRPCName, i.Name) + require.True(t, i.ClientStream()) + require.True(t, i.ServerStream()) +} diff --git a/pkg/api/rpc/container.go b/pkg/api/rpc/container.go new file mode 100644 index 000000000..6c87b84c5 --- /dev/null +++ b/pkg/api/rpc/container.go @@ -0,0 +1,131 @@ +package rpc + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/container" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/common" +) + +const serviceContainer = serviceNamePrefix + "container.ContainerService" + +const ( + rpcContainerPut = "Put" + rpcContainerGet = "Get" + rpcContainerDel = "Delete" + rpcContainerList = "List" + rpcContainerSetEACL = "SetExtendedACL" + rpcContainerGetEACL = "GetExtendedACL" + rpcContainerUsedSpace = "AnnounceUsedSpace" +) + +// PutContainer executes ContainerService.Put RPC. +func PutContainer( + cli *client.Client, + req *container.PutRequest, + opts ...client.CallOption, +) (*container.PutResponse, error) { + resp := new(container.PutResponse) + + err := client.SendUnary(cli, common.CallMethodInfoUnary(serviceContainer, rpcContainerPut), req, resp, opts...) + if err != nil { + return nil, err + } + + return resp, nil +} + +// GetContainer executes ContainerService.Get RPC. +func GetContainer( + cli *client.Client, + req *container.GetRequest, + opts ...client.CallOption, +) (*container.GetResponse, error) { + resp := new(container.GetResponse) + + err := client.SendUnary(cli, common.CallMethodInfoUnary(serviceContainer, rpcContainerGet), req, resp, opts...) + if err != nil { + return nil, err + } + + return resp, nil +} + +// DeleteContainer executes ContainerService.Delete RPC. +func DeleteContainer( + cli *client.Client, + req *container.DeleteRequest, + opts ...client.CallOption, +) (*container.PutResponse, error) { + resp := new(container.PutResponse) + + err := client.SendUnary(cli, common.CallMethodInfoUnary(serviceContainer, rpcContainerDel), req, resp, opts...) + if err != nil { + return nil, err + } + + return resp, nil +} + +// ListContainers executes ContainerService.List RPC. +func ListContainers( + cli *client.Client, + req *container.ListRequest, + opts ...client.CallOption, +) (*container.ListResponse, error) { + resp := new(container.ListResponse) + + err := client.SendUnary(cli, common.CallMethodInfoUnary(serviceContainer, rpcContainerList), req, resp, opts...) + if err != nil { + return nil, err + } + + return resp, nil +} + +// SetEACL executes ContainerService.SetExtendedACL RPC. +func SetEACL( + cli *client.Client, + req *container.SetExtendedACLRequest, + opts ...client.CallOption, +) (*container.PutResponse, error) { + resp := new(container.PutResponse) + + err := client.SendUnary(cli, common.CallMethodInfoUnary(serviceContainer, rpcContainerSetEACL), req, resp, opts...) + if err != nil { + return nil, err + } + + return resp, nil +} + +// GetEACL executes ContainerService.GetExtendedACL RPC. +func GetEACL( + cli *client.Client, + req *container.GetExtendedACLRequest, + opts ...client.CallOption, +) (*container.GetExtendedACLResponse, error) { + resp := new(container.GetExtendedACLResponse) + + err := client.SendUnary(cli, common.CallMethodInfoUnary(serviceContainer, rpcContainerGetEACL), req, resp, opts...) + if err != nil { + return nil, err + } + + return resp, nil +} + +// AnnounceUsedSpace executes ContainerService.AnnounceUsedSpace RPC. +func AnnounceUsedSpace( + cli *client.Client, + req *container.AnnounceUsedSpaceRequest, + opts ...client.CallOption, +) (*container.PutResponse, error) { + resp := new(container.PutResponse) + + err := client.SendUnary(cli, common.CallMethodInfoUnary(serviceContainer, rpcContainerUsedSpace), req, resp, opts...) + if err != nil { + return nil, err + } + + return resp, nil +} diff --git a/pkg/api/rpc/grpc/init.go b/pkg/api/rpc/grpc/init.go new file mode 100644 index 000000000..0092d3959 --- /dev/null +++ b/pkg/api/rpc/grpc/init.go @@ -0,0 +1,4 @@ +package grpc + +// Message represents raw gRPC message. +type Message any diff --git a/pkg/api/rpc/message/encoding.go b/pkg/api/rpc/message/encoding.go new file mode 100644 index 000000000..6afab531a --- /dev/null +++ b/pkg/api/rpc/message/encoding.go @@ -0,0 +1,48 @@ +package message + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/grpc" + "google.golang.org/protobuf/encoding/protojson" + "google.golang.org/protobuf/proto" +) + +// GRPCConvertedMessage is an interface +// of the gRPC message that is used +// for Message encoding/decoding. +type GRPCConvertedMessage interface { + grpc.Message + proto.Message +} + +// Unmarshal decodes m from its Protobuf binary representation +// via related gRPC message. +// +// gm should be tof the same type as the m.ToGRPCMessage() return. +func Unmarshal(m Message, data []byte, gm GRPCConvertedMessage) error { + if err := proto.Unmarshal(data, gm); err != nil { + return err + } + + return m.FromGRPCMessage(gm) +} + +// MarshalJSON encodes m to Protobuf JSON representation. +func MarshalJSON(m Message) ([]byte, error) { + return protojson.MarshalOptions{ + EmitUnpopulated: true, + }.Marshal( + m.ToGRPCMessage().(proto.Message), + ) +} + +// UnmarshalJSON decodes m from its Protobuf JSON representation +// via related gRPC message. +// +// gm should be tof the same type as the m.ToGRPCMessage() return. +func UnmarshalJSON(m Message, data []byte, gm GRPCConvertedMessage) error { + if err := protojson.Unmarshal(data, gm); err != nil { + return err + } + + return m.FromGRPCMessage(gm) +} diff --git a/pkg/api/rpc/message/message.go b/pkg/api/rpc/message/message.go new file mode 100644 index 000000000..f12ce9530 --- /dev/null +++ b/pkg/api/rpc/message/message.go @@ -0,0 +1,43 @@ +package message + +import ( + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/grpc" +) + +// Message represents raw Protobuf message +// that can be transmitted via several +// transport protocols. +type Message interface { + // Must return gRPC message that can + // be used for gRPC protocol transmission. + ToGRPCMessage() grpc.Message + + // Must restore the message from related + // gRPC message. + // + // If gRPC message is not a related one, + // ErrUnexpectedMessageType can be returned + // to indicate this. + FromGRPCMessage(grpc.Message) error +} + +// ErrUnexpectedMessageType is an error that +// is used to indicate message mismatch. +type ErrUnexpectedMessageType struct { + exp, act any +} + +// NewUnexpectedMessageType initializes an error about message mismatch +// between act and exp. +func NewUnexpectedMessageType(act, exp any) ErrUnexpectedMessageType { + return ErrUnexpectedMessageType{ + exp: exp, + act: act, + } +} + +func (e ErrUnexpectedMessageType) Error() string { + return fmt.Sprintf("unexpected message type %T: expected %T", e.act, e.exp) +} diff --git a/pkg/api/rpc/message/test/message.go b/pkg/api/rpc/message/test/message.go new file mode 100644 index 000000000..32ae9b0ca --- /dev/null +++ b/pkg/api/rpc/message/test/message.go @@ -0,0 +1,73 @@ +package messagetest + +import ( + "encoding/json" + "errors" + "fmt" + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/message" + "github.com/stretchr/testify/require" +) + +type jsonMessage interface { + json.Marshaler + json.Unmarshaler +} + +type binaryMessage interface { + StableMarshal([]byte) []byte + StableSize() int + Unmarshal([]byte) error +} + +func TestRPCMessage(t *testing.T, msgGens ...func(empty bool) message.Message) { + for _, msgGen := range msgGens { + msg := msgGen(false) + + t.Run(fmt.Sprintf("convert_%T", msg), func(t *testing.T) { + msg := msgGen(false) + + err := msg.FromGRPCMessage(100) + + require.True(t, errors.As(err, new(message.ErrUnexpectedMessageType))) + + msg2 := msgGen(true) + + err = msg2.FromGRPCMessage(msg.ToGRPCMessage()) + require.NoError(t, err) + + require.Equal(t, msg, msg2) + }) + + t.Run("encoding", func(t *testing.T) { + if jm, ok := msg.(jsonMessage); ok { + t.Run(fmt.Sprintf("JSON_%T", msg), func(t *testing.T) { + data, err := jm.MarshalJSON() + require.NoError(t, err) + + jm2 := msgGen(true).(jsonMessage) + require.NoError(t, jm2.UnmarshalJSON(data)) + + require.Equal(t, jm, jm2) + }) + } + + if bm, ok := msg.(binaryMessage); ok { + t.Run(fmt.Sprintf("%T.StableSize() does no allocations", bm), func(t *testing.T) { + require.Zero(t, testing.AllocsPerRun(1000, func() { + _ = bm.StableSize() + })) + }) + t.Run(fmt.Sprintf("Binary_%T", msg), func(t *testing.T) { + data := bm.StableMarshal(nil) + + bm2 := msgGen(true).(binaryMessage) + require.NoError(t, bm2.Unmarshal(data)) + + require.Equal(t, bm, bm2) + }) + } + }) + } +} diff --git a/pkg/api/rpc/netmap.go b/pkg/api/rpc/netmap.go new file mode 100644 index 000000000..84e217031 --- /dev/null +++ b/pkg/api/rpc/netmap.go @@ -0,0 +1,63 @@ +package rpc + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/common" +) + +const serviceNetmap = serviceNamePrefix + "netmap.NetmapService" + +const ( + rpcNetmapNodeInfo = "LocalNodeInfo" + rpcNetmapNetInfo = "NetworkInfo" + rpcNetmapSnapshot = "NetmapSnapshot" +) + +// LocalNodeInfo executes NetmapService.LocalNodeInfo RPC. +func LocalNodeInfo( + cli *client.Client, + req *netmap.LocalNodeInfoRequest, + opts ...client.CallOption, +) (*netmap.LocalNodeInfoResponse, error) { + resp := new(netmap.LocalNodeInfoResponse) + + err := client.SendUnary(cli, common.CallMethodInfoUnary(serviceNetmap, rpcNetmapNodeInfo), req, resp, opts...) + if err != nil { + return nil, err + } + + return resp, nil +} + +// NetworkInfo executes NetmapService.NetworkInfo RPC. +func NetworkInfo( + cli *client.Client, + req *netmap.NetworkInfoRequest, + opts ...client.CallOption, +) (*netmap.NetworkInfoResponse, error) { + resp := new(netmap.NetworkInfoResponse) + + err := client.SendUnary(cli, common.CallMethodInfoUnary(serviceNetmap, rpcNetmapNetInfo), req, resp, opts...) + if err != nil { + return nil, err + } + + return resp, nil +} + +// NetMapSnapshot executes NetmapService.NetmapSnapshot RPC. +func NetMapSnapshot( + cli *client.Client, + req *netmap.SnapshotRequest, + opts ...client.CallOption, +) (*netmap.SnapshotResponse, error) { + resp := new(netmap.SnapshotResponse) + + err := client.SendUnary(cli, common.CallMethodInfoUnary(serviceNetmap, rpcNetmapSnapshot), req, resp, opts...) + if err != nil { + return nil, err + } + + return resp, nil +} diff --git a/pkg/api/rpc/object.go b/pkg/api/rpc/object.go new file mode 100644 index 000000000..4127e0ab6 --- /dev/null +++ b/pkg/api/rpc/object.go @@ -0,0 +1,207 @@ +package rpc + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/message" +) + +const serviceObject = serviceNamePrefix + "object.ObjectService" + +const ( + rpcObjectPut = "Put" + rpcObjectGet = "Get" + rpcObjectSearch = "Search" + rpcObjectRange = "GetRange" + rpcObjectHash = "GetRangeHash" + rpcObjectHead = "Head" + rpcObjectDelete = "Delete" + rpcObjectPutSingle = "PutSingle" +) + +// PutRequestWriter is an object.PutRequest +// message streaming component. +type PutRequestWriter struct { + wc client.MessageWriterCloser + + resp message.Message +} + +// Write writes req to the stream. +func (w *PutRequestWriter) Write(req *object.PutRequest) error { + return w.wc.WriteMessage(req) +} + +// Close closes the stream. +func (w *PutRequestWriter) Close() error { + return w.wc.Close() +} + +// PutObject executes ObjectService.Put RPC. +func PutObject( + cli *client.Client, + resp *object.PutResponse, + opts ...client.CallOption, +) (*PutRequestWriter, error) { + wc, err := client.OpenClientStream(cli, common.CallMethodInfoClientStream(serviceObject, rpcObjectPut), resp, opts...) + if err != nil { + return nil, err + } + + return &PutRequestWriter{ + wc: wc, + resp: resp, + }, nil +} + +// GetResponseReader is an object.GetResponse +// stream reader. +type GetResponseReader struct { + r client.MessageReader +} + +// Read reads response from the stream. +// +// Returns io.EOF of streaming is finished. +func (r *GetResponseReader) Read(resp *object.GetResponse) error { + return r.r.ReadMessage(resp) +} + +// GetObject executes ObjectService.Get RPC. +func GetObject( + cli *client.Client, + req *object.GetRequest, + opts ...client.CallOption, +) (*GetResponseReader, error) { + wc, err := client.OpenServerStream(cli, common.CallMethodInfoServerStream(serviceObject, rpcObjectGet), req, opts...) + if err != nil { + return nil, err + } + + return &GetResponseReader{ + r: wc, + }, nil +} + +// GetResponseReader is an object.SearchResponse +// stream reader. +type SearchResponseReader struct { + r client.MessageReader +} + +// Read reads response from the stream. +// +// Returns io.EOF of streaming is finished. +func (r *SearchResponseReader) Read(resp *object.SearchResponse) error { + return r.r.ReadMessage(resp) +} + +// SearchObjects executes ObjectService.Search RPC. +func SearchObjects( + cli *client.Client, + req *object.SearchRequest, + opts ...client.CallOption, +) (*SearchResponseReader, error) { + wc, err := client.OpenServerStream(cli, common.CallMethodInfoServerStream(serviceObject, rpcObjectSearch), req, opts...) + if err != nil { + return nil, err + } + + return &SearchResponseReader{ + r: wc, + }, nil +} + +// GetResponseReader is an object.GetRangeResponse +// stream reader. +type ObjectRangeResponseReader struct { + r client.MessageReader +} + +// Read reads response from the stream. +// +// Returns io.EOF of streaming is finished. +func (r *ObjectRangeResponseReader) Read(resp *object.GetRangeResponse) error { + return r.r.ReadMessage(resp) +} + +// GetObjectRange executes ObjectService.GetRange RPC. +func GetObjectRange( + cli *client.Client, + req *object.GetRangeRequest, + opts ...client.CallOption, +) (*ObjectRangeResponseReader, error) { + wc, err := client.OpenServerStream(cli, common.CallMethodInfoServerStream(serviceObject, rpcObjectRange), req, opts...) + if err != nil { + return nil, err + } + + return &ObjectRangeResponseReader{ + r: wc, + }, nil +} + +// HeadObject executes ObjectService.Head RPC. +func HeadObject( + cli *client.Client, + req *object.HeadRequest, + opts ...client.CallOption, +) (*object.HeadResponse, error) { + resp := new(object.HeadResponse) + + err := client.SendUnary(cli, common.CallMethodInfoUnary(serviceObject, rpcObjectHead), req, resp, opts...) + if err != nil { + return nil, err + } + + return resp, nil +} + +// DeleteObject executes ObjectService.Delete RPC. +func DeleteObject( + cli *client.Client, + req *object.DeleteRequest, + opts ...client.CallOption, +) (*object.DeleteResponse, error) { + resp := new(object.DeleteResponse) + + err := client.SendUnary(cli, common.CallMethodInfoUnary(serviceObject, rpcObjectDelete), req, resp, opts...) + if err != nil { + return nil, err + } + + return resp, nil +} + +// HashObjectRange executes ObjectService.GetRangeHash RPC. +func HashObjectRange( + cli *client.Client, + req *object.GetRangeHashRequest, + opts ...client.CallOption, +) (*object.GetRangeHashResponse, error) { + resp := new(object.GetRangeHashResponse) + + err := client.SendUnary(cli, common.CallMethodInfoUnary(serviceObject, rpcObjectHash), req, resp, opts...) + if err != nil { + return nil, err + } + + return resp, nil +} + +// PutSingleObject executes ObjectService.PutSingle RPC. +func PutSingleObject( + cli *client.Client, + req *object.PutSingleRequest, + opts ...client.CallOption, +) (*object.PutSingleResponse, error) { + resp := new(object.PutSingleResponse) + + err := client.SendUnary(cli, common.CallMethodInfoUnary(serviceObject, rpcObjectPutSingle), req, resp, opts...) + if err != nil { + return nil, err + } + + return resp, nil +} diff --git a/pkg/api/rpc/session.go b/pkg/api/rpc/session.go new file mode 100644 index 000000000..9cc0a22c7 --- /dev/null +++ b/pkg/api/rpc/session.go @@ -0,0 +1,28 @@ +package rpc + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" +) + +const serviceSession = serviceNamePrefix + "session.SessionService" + +const ( + rpcSessionCreate = "Create" +) + +func CreateSession( + cli *client.Client, + req *session.CreateRequest, + opts ...client.CallOption, +) (*session.CreateResponse, error) { + resp := new(session.CreateResponse) + + err := client.SendUnary(cli, common.CallMethodInfoUnary(serviceSession, rpcSessionCreate), req, resp, opts...) + if err != nil { + return nil, err + } + + return resp, nil +} diff --git a/pkg/api/session/convert.go b/pkg/api/session/convert.go new file mode 100644 index 000000000..1787b2131 --- /dev/null +++ b/pkg/api/session/convert.go @@ -0,0 +1,893 @@ +package session + +import ( + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/acl" + aclGRPC "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/acl/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + refsGRPC "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/message" + session "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/status" + statusGRPC "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/status/grpc" +) + +func (c *CreateRequestBody) ToGRPCMessage() grpc.Message { + var m *session.CreateRequest_Body + + if c != nil { + m = new(session.CreateRequest_Body) + + m.SetOwnerId(c.ownerID.ToGRPCMessage().(*refsGRPC.OwnerID)) + m.SetExpiration(c.expiration) + } + + return m +} + +func (c *CreateRequestBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*session.CreateRequest_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + ownerID := v.GetOwnerId() + if ownerID == nil { + c.ownerID = nil + } else { + if c.ownerID == nil { + c.ownerID = new(refs.OwnerID) + } + + err = c.ownerID.FromGRPCMessage(ownerID) + if err != nil { + return err + } + } + + c.expiration = v.GetExpiration() + + return nil +} + +func (c *CreateRequest) ToGRPCMessage() grpc.Message { + var m *session.CreateRequest + + if c != nil { + m = new(session.CreateRequest) + + m.SetBody(c.body.ToGRPCMessage().(*session.CreateRequest_Body)) + c.RequestHeaders.ToMessage(m) + } + + return m +} + +func (c *CreateRequest) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*session.CreateRequest) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + c.body = nil + } else { + if c.body == nil { + c.body = new(CreateRequestBody) + } + + err = c.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return c.RequestHeaders.FromMessage(v) +} + +func (c *CreateResponseBody) ToGRPCMessage() grpc.Message { + var m *session.CreateResponse_Body + + if c != nil { + m = new(session.CreateResponse_Body) + + m.SetSessionKey(c.sessionKey) + m.SetId(c.id) + } + + return m +} + +func (c *CreateResponseBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*session.CreateResponse_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + c.sessionKey = v.GetSessionKey() + c.id = v.GetId() + + return nil +} + +func (c *CreateResponse) ToGRPCMessage() grpc.Message { + var m *session.CreateResponse + + if c != nil { + m = new(session.CreateResponse) + + m.SetBody(c.body.ToGRPCMessage().(*session.CreateResponse_Body)) + c.ResponseHeaders.ToMessage(m) + } + + return m +} + +func (c *CreateResponse) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*session.CreateResponse) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + c.body = nil + } else { + if c.body == nil { + c.body = new(CreateResponseBody) + } + + err = c.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + return c.ResponseHeaders.FromMessage(v) +} + +func (l *TokenLifetime) ToGRPCMessage() grpc.Message { + var m *session.SessionToken_Body_TokenLifetime + + if l != nil { + m = new(session.SessionToken_Body_TokenLifetime) + + m.SetExp(l.exp) + m.SetIat(l.iat) + m.SetNbf(l.nbf) + } + + return m +} + +func (l *TokenLifetime) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*session.SessionToken_Body_TokenLifetime) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + l.exp = v.GetExp() + l.iat = v.GetIat() + l.nbf = v.GetNbf() + + return nil +} + +func (x *XHeader) ToGRPCMessage() grpc.Message { + var m *session.XHeader + + if x != nil { + m = new(session.XHeader) + + m.SetKey(x.key) + m.SetValue(x.val) + } + + return m +} + +func (x *XHeader) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*session.XHeader) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + x.key = v.GetKey() + x.val = v.GetValue() + + return nil +} + +func XHeadersToGRPC(xs []XHeader) (res []*session.XHeader) { + if xs != nil { + res = make([]*session.XHeader, 0, len(xs)) + + for i := range xs { + res = append(res, xs[i].ToGRPCMessage().(*session.XHeader)) + } + } + + return +} + +func XHeadersFromGRPC(xs []*session.XHeader) (res []XHeader, err error) { + if xs != nil { + res = make([]XHeader, len(xs)) + + for i := range xs { + if xs[i] != nil { + err = res[i].FromGRPCMessage(xs[i]) + if err != nil { + return + } + } + } + } + + return +} + +func (t *Token) ToGRPCMessage() grpc.Message { + var m *session.SessionToken + + if t != nil { + m = new(session.SessionToken) + + m.SetBody(t.body.ToGRPCMessage().(*session.SessionToken_Body)) + m.SetSignature(t.sig.ToGRPCMessage().(*refsGRPC.Signature)) + } + + return m +} + +func (t *Token) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*session.SessionToken) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + body := v.GetBody() + if body == nil { + t.body = nil + } else { + if t.body == nil { + t.body = new(TokenBody) + } + + err = t.body.FromGRPCMessage(body) + if err != nil { + return err + } + } + + sig := v.GetSignature() + if sig == nil { + t.sig = nil + } else { + if t.sig == nil { + t.sig = new(refs.Signature) + } + + err = t.sig.FromGRPCMessage(sig) + if err != nil { + return err + } + } + + return nil +} + +func (r *RequestVerificationHeader) ToGRPCMessage() grpc.Message { + var m *session.RequestVerificationHeader + + if r != nil { + m = new(session.RequestVerificationHeader) + + m.SetBodySignature(r.bodySig.ToGRPCMessage().(*refsGRPC.Signature)) + m.SetMetaSignature(r.metaSig.ToGRPCMessage().(*refsGRPC.Signature)) + m.SetOriginSignature(r.originSig.ToGRPCMessage().(*refsGRPC.Signature)) + m.SetOrigin(r.origin.ToGRPCMessage().(*session.RequestVerificationHeader)) + } + + return m +} + +func (r *RequestVerificationHeader) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*session.RequestVerificationHeader) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + originSig := v.GetOriginSignature() + if originSig == nil { + r.originSig = nil + } else { + if r.originSig == nil { + r.originSig = new(refs.Signature) + } + + err = r.originSig.FromGRPCMessage(originSig) + if err != nil { + return err + } + } + + metaSig := v.GetMetaSignature() + if metaSig == nil { + r.metaSig = nil + } else { + if r.metaSig == nil { + r.metaSig = new(refs.Signature) + } + + err = r.metaSig.FromGRPCMessage(metaSig) + if err != nil { + return err + } + } + + bodySig := v.GetBodySignature() + if bodySig == nil { + r.bodySig = nil + } else { + if r.bodySig == nil { + r.bodySig = new(refs.Signature) + } + + err = r.bodySig.FromGRPCMessage(bodySig) + if err != nil { + return err + } + } + + origin := v.GetOrigin() + if origin == nil { + r.origin = nil + } else { + if r.origin == nil { + r.origin = new(RequestVerificationHeader) + } + + err = r.origin.FromGRPCMessage(origin) + if err != nil { + return err + } + } + + return nil +} + +func (r *RequestMetaHeader) ToGRPCMessage() grpc.Message { + var m *session.RequestMetaHeader + + if r != nil { + m = new(session.RequestMetaHeader) + + m.SetVersion(r.version.ToGRPCMessage().(*refsGRPC.Version)) + m.SetSessionToken(r.sessionToken.ToGRPCMessage().(*session.SessionToken)) + m.SetBearerToken(r.bearerToken.ToGRPCMessage().(*aclGRPC.BearerToken)) + m.SetXHeaders(XHeadersToGRPC(r.xHeaders)) + m.SetEpoch(r.epoch) + m.SetTtl(r.ttl) + m.SetOrigin(r.origin.ToGRPCMessage().(*session.RequestMetaHeader)) + m.SetNetworkMagic(r.netMagic) + } + + return m +} + +func (r *RequestMetaHeader) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*session.RequestMetaHeader) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + version := v.GetVersion() + if version == nil { + r.version = nil + } else { + if r.version == nil { + r.version = new(refs.Version) + } + + err = r.version.FromGRPCMessage(version) + if err != nil { + return err + } + } + + sessionToken := v.GetSessionToken() + if sessionToken == nil { + r.sessionToken = nil + } else { + if r.sessionToken == nil { + r.sessionToken = new(Token) + } + + err = r.sessionToken.FromGRPCMessage(sessionToken) + if err != nil { + return err + } + } + + bearerToken := v.GetBearerToken() + if bearerToken == nil { + r.bearerToken = nil + } else { + if r.bearerToken == nil { + r.bearerToken = new(acl.BearerToken) + } + + err = r.bearerToken.FromGRPCMessage(bearerToken) + if err != nil { + return err + } + } + + origin := v.GetOrigin() + if origin == nil { + r.origin = nil + } else { + if r.origin == nil { + r.origin = new(RequestMetaHeader) + } + + err = r.origin.FromGRPCMessage(origin) + if err != nil { + return err + } + } + + r.xHeaders, err = XHeadersFromGRPC(v.GetXHeaders()) + if err != nil { + return err + } + + r.epoch = v.GetEpoch() + r.ttl = v.GetTtl() + r.netMagic = v.GetNetworkMagic() + + return nil +} + +func (r *ResponseVerificationHeader) ToGRPCMessage() grpc.Message { + var m *session.ResponseVerificationHeader + + if r != nil { + m = new(session.ResponseVerificationHeader) + + m.SetBodySignature(r.bodySig.ToGRPCMessage().(*refsGRPC.Signature)) + m.SetMetaSignature(r.metaSig.ToGRPCMessage().(*refsGRPC.Signature)) + m.SetOriginSignature(r.originSig.ToGRPCMessage().(*refsGRPC.Signature)) + m.SetOrigin(r.origin.ToGRPCMessage().(*session.ResponseVerificationHeader)) + } + + return m +} + +func (r *ResponseVerificationHeader) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*session.ResponseVerificationHeader) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + originSig := v.GetOriginSignature() + if originSig == nil { + r.originSig = nil + } else { + if r.originSig == nil { + r.originSig = new(refs.Signature) + } + + err = r.originSig.FromGRPCMessage(originSig) + if err != nil { + return err + } + } + + metaSig := v.GetMetaSignature() + if metaSig == nil { + r.metaSig = nil + } else { + if r.metaSig == nil { + r.metaSig = new(refs.Signature) + } + + err = r.metaSig.FromGRPCMessage(metaSig) + if err != nil { + return err + } + } + + bodySig := v.GetBodySignature() + if bodySig == nil { + r.bodySig = nil + } else { + if r.bodySig == nil { + r.bodySig = new(refs.Signature) + } + + err = r.bodySig.FromGRPCMessage(bodySig) + if err != nil { + return err + } + } + + origin := v.GetOrigin() + if origin == nil { + r.origin = nil + } else { + if r.origin == nil { + r.origin = new(ResponseVerificationHeader) + } + + err = r.origin.FromGRPCMessage(origin) + if err != nil { + return err + } + } + + return nil +} + +func (r *ResponseMetaHeader) ToGRPCMessage() grpc.Message { + var m *session.ResponseMetaHeader + + if r != nil { + m = new(session.ResponseMetaHeader) + + m.SetVersion(r.version.ToGRPCMessage().(*refsGRPC.Version)) + m.SetXHeaders(XHeadersToGRPC(r.xHeaders)) + m.SetEpoch(r.epoch) + m.SetTtl(r.ttl) + m.SetOrigin(r.origin.ToGRPCMessage().(*session.ResponseMetaHeader)) + m.SetStatus(r.status.ToGRPCMessage().(*statusGRPC.Status)) + } + + return m +} + +func (r *ResponseMetaHeader) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*session.ResponseMetaHeader) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + version := v.GetVersion() + if version == nil { + r.version = nil + } else { + if r.version == nil { + r.version = new(refs.Version) + } + + err = r.version.FromGRPCMessage(version) + if err != nil { + return err + } + } + + origin := v.GetOrigin() + if origin == nil { + r.origin = nil + } else { + if r.origin == nil { + r.origin = new(ResponseMetaHeader) + } + + err = r.origin.FromGRPCMessage(origin) + if err != nil { + return err + } + } + + st := v.GetStatus() + if st == nil { + r.status = nil + } else { + if r.status == nil { + r.status = new(status.Status) + } + + err = r.status.FromGRPCMessage(st) + if err != nil { + return err + } + } + + r.xHeaders, err = XHeadersFromGRPC(v.GetXHeaders()) + if err != nil { + return err + } + + r.epoch = v.GetEpoch() + r.ttl = v.GetTtl() + + return nil +} + +func ObjectSessionVerbToGRPCField(v ObjectSessionVerb) session.ObjectSessionContext_Verb { + switch v { + case ObjectVerbPut: + return session.ObjectSessionContext_PUT + case ObjectVerbGet: + return session.ObjectSessionContext_GET + case ObjectVerbHead: + return session.ObjectSessionContext_HEAD + case ObjectVerbSearch: + return session.ObjectSessionContext_SEARCH + case ObjectVerbDelete: + return session.ObjectSessionContext_DELETE + case ObjectVerbRange: + return session.ObjectSessionContext_RANGE + case ObjectVerbRangeHash: + return session.ObjectSessionContext_RANGEHASH + default: + return session.ObjectSessionContext_VERB_UNSPECIFIED + } +} + +func ObjectSessionVerbFromGRPCField(v session.ObjectSessionContext_Verb) ObjectSessionVerb { + switch v { + case session.ObjectSessionContext_PUT: + return ObjectVerbPut + case session.ObjectSessionContext_GET: + return ObjectVerbGet + case session.ObjectSessionContext_HEAD: + return ObjectVerbHead + case session.ObjectSessionContext_SEARCH: + return ObjectVerbSearch + case session.ObjectSessionContext_DELETE: + return ObjectVerbDelete + case session.ObjectSessionContext_RANGE: + return ObjectVerbRange + case session.ObjectSessionContext_RANGEHASH: + return ObjectVerbRangeHash + default: + return ObjectVerbUnknown + } +} + +func (c *ObjectSessionContext) ToGRPCMessage() grpc.Message { + var m *session.ObjectSessionContext + + if c != nil { + m = new(session.ObjectSessionContext) + + m.SetVerb(ObjectSessionVerbToGRPCField(c.verb)) + m.SetTarget(c.cnr.ToGRPCMessage().(*refsGRPC.ContainerID), refs.ObjectIDListToGRPCMessage(c.objs)) + } + + return m +} + +func (c *ObjectSessionContext) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*session.ObjectSessionContext) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + cnr := v.GetTarget().GetContainer() + if cnr == nil { + c.cnr = nil + } else { + if c.cnr == nil { + c.cnr = new(refs.ContainerID) + } + + err = c.cnr.FromGRPCMessage(cnr) + if err != nil { + return err + } + } + + c.objs, err = refs.ObjectIDListFromGRPCMessage(v.GetTarget().GetObjects()) + if err != nil { + return err + } + + c.verb = ObjectSessionVerbFromGRPCField(v.GetVerb()) + + return nil +} + +func (t *TokenBody) ToGRPCMessage() grpc.Message { + var m *session.SessionToken_Body + + if t != nil { + m = new(session.SessionToken_Body) + + switch typ := t.ctx.(type) { + default: + panic(fmt.Sprintf("unknown session context %T", typ)) + case nil: + m.Context = nil + case *ObjectSessionContext: + m.SetObjectSessionContext(typ.ToGRPCMessage().(*session.ObjectSessionContext)) + case *ContainerSessionContext: + m.SetContainerSessionContext(typ.ToGRPCMessage().(*session.ContainerSessionContext)) + } + + m.SetOwnerId(t.ownerID.ToGRPCMessage().(*refsGRPC.OwnerID)) + m.SetId(t.id) + m.SetSessionKey(t.sessionKey) + m.SetLifetime(t.lifetime.ToGRPCMessage().(*session.SessionToken_Body_TokenLifetime)) + } + + return m +} + +func (t *TokenBody) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*session.SessionToken_Body) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + t.ctx = nil + + switch val := v.GetContext().(type) { + default: + err = fmt.Errorf("unknown session context %T", val) + case nil: + case *session.SessionToken_Body_Object: + ctx, ok := t.ctx.(*ObjectSessionContext) + if !ok { + ctx = new(ObjectSessionContext) + t.ctx = ctx + } + + err = ctx.FromGRPCMessage(val.Object) + case *session.SessionToken_Body_Container: + ctx, ok := t.ctx.(*ContainerSessionContext) + if !ok { + ctx = new(ContainerSessionContext) + t.ctx = ctx + } + + err = ctx.FromGRPCMessage(val.Container) + } + + if err != nil { + return err + } + + ownerID := v.GetOwnerId() + if ownerID == nil { + t.ownerID = nil + } else { + if t.ownerID == nil { + t.ownerID = new(refs.OwnerID) + } + + err = t.ownerID.FromGRPCMessage(ownerID) + if err != nil { + return err + } + } + + lifetime := v.GetLifetime() + if lifetime == nil { + t.lifetime = nil + } else { + if t.lifetime == nil { + t.lifetime = new(TokenLifetime) + } + + err = t.lifetime.FromGRPCMessage(lifetime) + if err != nil { + return err + } + } + + t.id = v.GetId() + t.sessionKey = v.GetSessionKey() + + return nil +} + +// ContainerSessionVerbToGRPCField converts ContainerSessionVerb +// to gRPC-generated session.ContainerSessionContext_Verb. +// +// If v is outside of the ContainerSessionVerb enum, +// session.ContainerSessionContext_VERB_UNSPECIFIED is returned. +func ContainerSessionVerbToGRPCField(v ContainerSessionVerb) session.ContainerSessionContext_Verb { + switch v { + default: + return session.ContainerSessionContext_VERB_UNSPECIFIED + case ContainerVerbPut: + return session.ContainerSessionContext_PUT + case ContainerVerbDelete: + return session.ContainerSessionContext_DELETE + case ContainerVerbSetEACL: + return session.ContainerSessionContext_SETEACL + } +} + +// ContainerSessionVerbFromGRPCField converts gRPC-generated +// session.ContainerSessionContext_Verb to ContainerSessionVerb. +// +// If v is outside of the session.ContainerSessionContext_Verb enum, +// ContainerVerbUnknown is returned. +func ContainerSessionVerbFromGRPCField(v session.ContainerSessionContext_Verb) ContainerSessionVerb { + switch v { + default: + return ContainerVerbUnknown + case session.ContainerSessionContext_PUT: + return ContainerVerbPut + case session.ContainerSessionContext_DELETE: + return ContainerVerbDelete + case session.ContainerSessionContext_SETEACL: + return ContainerVerbSetEACL + } +} + +// ToGRPCMessage converts ContainerSessionContext to gRPC-generated +// session.ContainerSessionContext message. +func (x *ContainerSessionContext) ToGRPCMessage() grpc.Message { + var m *session.ContainerSessionContext + + if x != nil { + m = new(session.ContainerSessionContext) + + m.SetVerb(ContainerSessionVerbToGRPCField(x.verb)) + m.SetWildcard(x.wildcard) + m.SetContainerId(x.cid.ToGRPCMessage().(*refsGRPC.ContainerID)) + } + + return m +} + +// FromGRPCMessage tries to restore ContainerSessionContext from grpc.Message. +// +// Returns message.ErrUnexpectedMessageType if m is not +// a gRPC-generated session.ContainerSessionContext message. +func (x *ContainerSessionContext) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*session.ContainerSessionContext) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var err error + + cid := v.GetContainerId() + if cid == nil { + x.cid = nil + } else { + if x.cid == nil { + x.cid = new(refs.ContainerID) + } + + err = x.cid.FromGRPCMessage(cid) + if err != nil { + return err + } + } + + x.verb = ContainerSessionVerbFromGRPCField(v.GetVerb()) + x.wildcard = v.GetWildcard() + + return nil +} diff --git a/pkg/api/session/grpc/client.go b/pkg/api/session/grpc/client.go new file mode 100644 index 000000000..2dfe77ec2 --- /dev/null +++ b/pkg/api/session/grpc/client.go @@ -0,0 +1,62 @@ +package session + +import ( + "context" + "errors" + + "google.golang.org/grpc" +) + +// Client wraps SessionServiceClient +// with pre-defined configurations. +type Client struct { + *cfg + + client SessionServiceClient +} + +// Option represents Client option. +type Option func(*cfg) + +type cfg struct { + callOpts []grpc.CallOption +} + +// ErrNilSessionServiceClient is returned by functions that expect +// a non-nil SessionServiceClient, but received nil. +var ErrNilSessionServiceClient = errors.New("session gRPC client is nil") + +func defaultCfg() *cfg { + return new(cfg) +} + +// NewClient creates, initializes and returns a new Client instance. +// +// Options are applied one by one in order. +func NewClient(c SessionServiceClient, opts ...Option) (*Client, error) { + if c == nil { + return nil, ErrNilSessionServiceClient + } + + cfg := defaultCfg() + for i := range opts { + opts[i](cfg) + } + + return &Client{ + cfg: cfg, + client: c, + }, nil +} + +func (c *Client) Create(ctx context.Context, req *CreateRequest) (*CreateResponse, error) { + return c.client.Create(ctx, req, c.callOpts...) +} + +// WithCallOptions returns Option that configures +// Client to attach call options to each rpc call. +func WithCallOptions(opts []grpc.CallOption) Option { + return func(c *cfg) { + c.callOpts = opts + } +} diff --git a/pkg/api/session/grpc/service.go b/pkg/api/session/grpc/service.go new file mode 100644 index 000000000..0d6c27d30 --- /dev/null +++ b/pkg/api/session/grpc/service.go @@ -0,0 +1,55 @@ +package session + +import ( + refs "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs/grpc" +) + +// SetOwnerId sets identifier of the session initiator. +func (m *CreateRequest_Body) SetOwnerId(v *refs.OwnerID) { + m.OwnerId = v +} + +// SetExpiration sets lifetime of the session. +func (m *CreateRequest_Body) SetExpiration(v uint64) { + m.Expiration = v +} + +// SetBody sets body of the request. +func (m *CreateRequest) SetBody(v *CreateRequest_Body) { + m.Body = v +} + +// SetMetaHeader sets meta header of the request. +func (m *CreateRequest) SetMetaHeader(v *RequestMetaHeader) { + m.MetaHeader = v +} + +// SetVerifyHeader sets verification header of the request. +func (m *CreateRequest) SetVerifyHeader(v *RequestVerificationHeader) { + m.VerifyHeader = v +} + +// SetId sets identifier of the session token. +func (m *CreateResponse_Body) SetId(v []byte) { + m.Id = v +} + +// SetSessionKey sets session public key in a binary format. +func (m *CreateResponse_Body) SetSessionKey(v []byte) { + m.SessionKey = v +} + +// SetBody sets body of the response. +func (m *CreateResponse) SetBody(v *CreateResponse_Body) { + m.Body = v +} + +// SetMetaHeader sets meta header of the response. +func (m *CreateResponse) SetMetaHeader(v *ResponseMetaHeader) { + m.MetaHeader = v +} + +// SetVerifyHeader sets verification header of the response. +func (m *CreateResponse) SetVerifyHeader(v *ResponseVerificationHeader) { + m.VerifyHeader = v +} diff --git a/pkg/api/session/grpc/service.pb.go b/pkg/api/session/grpc/service.pb.go new file mode 100644 index 000000000..40606b765 --- /dev/null +++ b/pkg/api/session/grpc/service.pb.go @@ -0,0 +1,458 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.33.0 +// protoc v4.25.3 +// source: session/grpc/service.proto + +package session + +import ( + grpc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs/grpc" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// Information necessary for opening a session. +type CreateRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Body of a create session token request message. + Body *CreateRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Carries request meta information. Header data is used only to regulate + // message transport and does not affect request execution. + MetaHeader *RequestMetaHeader `protobuf:"bytes,2,opt,name=meta_header,json=metaHeader,proto3" json:"meta_header,omitempty"` + // Carries request verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + VerifyHeader *RequestVerificationHeader `protobuf:"bytes,3,opt,name=verify_header,json=verifyHeader,proto3" json:"verify_header,omitempty"` +} + +func (x *CreateRequest) Reset() { + *x = CreateRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_session_grpc_service_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CreateRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateRequest) ProtoMessage() {} + +func (x *CreateRequest) ProtoReflect() protoreflect.Message { + mi := &file_session_grpc_service_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CreateRequest.ProtoReflect.Descriptor instead. +func (*CreateRequest) Descriptor() ([]byte, []int) { + return file_session_grpc_service_proto_rawDescGZIP(), []int{0} +} + +func (x *CreateRequest) GetBody() *CreateRequest_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *CreateRequest) GetMetaHeader() *RequestMetaHeader { + if x != nil { + return x.MetaHeader + } + return nil +} + +func (x *CreateRequest) GetVerifyHeader() *RequestVerificationHeader { + if x != nil { + return x.VerifyHeader + } + return nil +} + +// Information about the opened session. +type CreateResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Body of create session token response message. + Body *CreateResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Carries response meta information. Header data is used only to regulate + // message transport and does not affect request execution. + MetaHeader *ResponseMetaHeader `protobuf:"bytes,2,opt,name=meta_header,json=metaHeader,proto3" json:"meta_header,omitempty"` + // Carries response verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + VerifyHeader *ResponseVerificationHeader `protobuf:"bytes,3,opt,name=verify_header,json=verifyHeader,proto3" json:"verify_header,omitempty"` +} + +func (x *CreateResponse) Reset() { + *x = CreateResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_session_grpc_service_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CreateResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateResponse) ProtoMessage() {} + +func (x *CreateResponse) ProtoReflect() protoreflect.Message { + mi := &file_session_grpc_service_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CreateResponse.ProtoReflect.Descriptor instead. +func (*CreateResponse) Descriptor() ([]byte, []int) { + return file_session_grpc_service_proto_rawDescGZIP(), []int{1} +} + +func (x *CreateResponse) GetBody() *CreateResponse_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *CreateResponse) GetMetaHeader() *ResponseMetaHeader { + if x != nil { + return x.MetaHeader + } + return nil +} + +func (x *CreateResponse) GetVerifyHeader() *ResponseVerificationHeader { + if x != nil { + return x.VerifyHeader + } + return nil +} + +// Session creation request body +type CreateRequest_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Session initiating user's or node's key derived `OwnerID` + OwnerId *grpc.OwnerID `protobuf:"bytes,1,opt,name=owner_id,json=ownerId,proto3" json:"owner_id,omitempty"` + // Session expiration `Epoch` + Expiration uint64 `protobuf:"varint,2,opt,name=expiration,proto3" json:"expiration,omitempty"` +} + +func (x *CreateRequest_Body) Reset() { + *x = CreateRequest_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_session_grpc_service_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CreateRequest_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateRequest_Body) ProtoMessage() {} + +func (x *CreateRequest_Body) ProtoReflect() protoreflect.Message { + mi := &file_session_grpc_service_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CreateRequest_Body.ProtoReflect.Descriptor instead. +func (*CreateRequest_Body) Descriptor() ([]byte, []int) { + return file_session_grpc_service_proto_rawDescGZIP(), []int{0, 0} +} + +func (x *CreateRequest_Body) GetOwnerId() *grpc.OwnerID { + if x != nil { + return x.OwnerId + } + return nil +} + +func (x *CreateRequest_Body) GetExpiration() uint64 { + if x != nil { + return x.Expiration + } + return 0 +} + +// Session creation response body +type CreateResponse_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Identifier of a newly created session + Id []byte `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + // Public key used for session + SessionKey []byte `protobuf:"bytes,2,opt,name=session_key,json=sessionKey,proto3" json:"session_key,omitempty"` +} + +func (x *CreateResponse_Body) Reset() { + *x = CreateResponse_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_session_grpc_service_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CreateResponse_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateResponse_Body) ProtoMessage() {} + +func (x *CreateResponse_Body) ProtoReflect() protoreflect.Message { + mi := &file_session_grpc_service_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CreateResponse_Body.ProtoReflect.Descriptor instead. +func (*CreateResponse_Body) Descriptor() ([]byte, []int) { + return file_session_grpc_service_proto_rawDescGZIP(), []int{1, 0} +} + +func (x *CreateResponse_Body) GetId() []byte { + if x != nil { + return x.Id + } + return nil +} + +func (x *CreateResponse_Body) GetSessionKey() []byte { + if x != nil { + return x.SessionKey + } + return nil +} + +var File_session_grpc_service_proto protoreflect.FileDescriptor + +var file_session_grpc_service_proto_rawDesc = []byte{ + 0x0a, 0x1a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x73, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x11, 0x6e, 0x65, + 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x1a, + 0x15, 0x72, 0x65, 0x66, 0x73, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x18, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2f, + 0x67, 0x72, 0x70, 0x63, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x22, 0xc0, 0x02, 0x0a, 0x0d, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x39, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x25, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x45, 0x0a, + 0x0b, 0x6d, 0x65, 0x74, 0x61, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, + 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, + 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0a, 0x6d, 0x65, 0x74, 0x61, 0x48, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x12, 0x51, 0x0a, 0x0d, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x5f, 0x68, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x6e, 0x65, + 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0c, 0x76, 0x65, 0x72, 0x69, 0x66, + 0x79, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x1a, 0x5a, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, + 0x32, 0x0a, 0x08, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x17, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x65, + 0x66, 0x73, 0x2e, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x49, 0x44, 0x52, 0x07, 0x6f, 0x77, 0x6e, 0x65, + 0x72, 0x49, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x22, 0xa1, 0x02, 0x0a, 0x0e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, + 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, + 0x64, 0x79, 0x12, 0x46, 0x0a, 0x0b, 0x6d, 0x65, 0x74, 0x61, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, + 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0a, + 0x6d, 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x52, 0x0a, 0x0d, 0x76, 0x65, + 0x72, 0x69, 0x66, 0x79, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x2d, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x56, 0x65, + 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x52, 0x0c, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x1a, 0x37, + 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x73, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79, 0x32, 0x5f, 0x0a, 0x0e, 0x53, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x4d, 0x0a, 0x06, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x12, 0x20, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, + 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, + 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x64, 0x5a, 0x44, 0x67, 0x69, 0x74, 0x2e, + 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, 0x75, + 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x4c, 0x61, 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, + 0x73, 0x2d, 0x61, 0x70, 0x69, 0x2d, 0x67, 0x6f, 0x2f, 0x76, 0x32, 0x2f, 0x73, 0x65, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x3b, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0xaa, 0x02, 0x1b, 0x4e, 0x65, 0x6f, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x61, + 0x67, 0x65, 0x2e, 0x41, 0x50, 0x49, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_session_grpc_service_proto_rawDescOnce sync.Once + file_session_grpc_service_proto_rawDescData = file_session_grpc_service_proto_rawDesc +) + +func file_session_grpc_service_proto_rawDescGZIP() []byte { + file_session_grpc_service_proto_rawDescOnce.Do(func() { + file_session_grpc_service_proto_rawDescData = protoimpl.X.CompressGZIP(file_session_grpc_service_proto_rawDescData) + }) + return file_session_grpc_service_proto_rawDescData +} + +var file_session_grpc_service_proto_msgTypes = make([]protoimpl.MessageInfo, 4) +var file_session_grpc_service_proto_goTypes = []interface{}{ + (*CreateRequest)(nil), // 0: neo.fs.v2.session.CreateRequest + (*CreateResponse)(nil), // 1: neo.fs.v2.session.CreateResponse + (*CreateRequest_Body)(nil), // 2: neo.fs.v2.session.CreateRequest.Body + (*CreateResponse_Body)(nil), // 3: neo.fs.v2.session.CreateResponse.Body + (*RequestMetaHeader)(nil), // 4: neo.fs.v2.session.RequestMetaHeader + (*RequestVerificationHeader)(nil), // 5: neo.fs.v2.session.RequestVerificationHeader + (*ResponseMetaHeader)(nil), // 6: neo.fs.v2.session.ResponseMetaHeader + (*ResponseVerificationHeader)(nil), // 7: neo.fs.v2.session.ResponseVerificationHeader + (*grpc.OwnerID)(nil), // 8: neo.fs.v2.refs.OwnerID +} +var file_session_grpc_service_proto_depIdxs = []int32{ + 2, // 0: neo.fs.v2.session.CreateRequest.body:type_name -> neo.fs.v2.session.CreateRequest.Body + 4, // 1: neo.fs.v2.session.CreateRequest.meta_header:type_name -> neo.fs.v2.session.RequestMetaHeader + 5, // 2: neo.fs.v2.session.CreateRequest.verify_header:type_name -> neo.fs.v2.session.RequestVerificationHeader + 3, // 3: neo.fs.v2.session.CreateResponse.body:type_name -> neo.fs.v2.session.CreateResponse.Body + 6, // 4: neo.fs.v2.session.CreateResponse.meta_header:type_name -> neo.fs.v2.session.ResponseMetaHeader + 7, // 5: neo.fs.v2.session.CreateResponse.verify_header:type_name -> neo.fs.v2.session.ResponseVerificationHeader + 8, // 6: neo.fs.v2.session.CreateRequest.Body.owner_id:type_name -> neo.fs.v2.refs.OwnerID + 0, // 7: neo.fs.v2.session.SessionService.Create:input_type -> neo.fs.v2.session.CreateRequest + 1, // 8: neo.fs.v2.session.SessionService.Create:output_type -> neo.fs.v2.session.CreateResponse + 8, // [8:9] is the sub-list for method output_type + 7, // [7:8] is the sub-list for method input_type + 7, // [7:7] is the sub-list for extension type_name + 7, // [7:7] is the sub-list for extension extendee + 0, // [0:7] is the sub-list for field type_name +} + +func init() { file_session_grpc_service_proto_init() } +func file_session_grpc_service_proto_init() { + if File_session_grpc_service_proto != nil { + return + } + file_session_grpc_types_proto_init() + if !protoimpl.UnsafeEnabled { + file_session_grpc_service_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CreateRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_session_grpc_service_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CreateResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_session_grpc_service_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CreateRequest_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_session_grpc_service_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CreateResponse_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_session_grpc_service_proto_rawDesc, + NumEnums: 0, + NumMessages: 4, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_session_grpc_service_proto_goTypes, + DependencyIndexes: file_session_grpc_service_proto_depIdxs, + MessageInfos: file_session_grpc_service_proto_msgTypes, + }.Build() + File_session_grpc_service_proto = out.File + file_session_grpc_service_proto_rawDesc = nil + file_session_grpc_service_proto_goTypes = nil + file_session_grpc_service_proto_depIdxs = nil +} diff --git a/pkg/api/session/grpc/service_grpc.pb.go b/pkg/api/session/grpc/service_grpc.pb.go new file mode 100644 index 000000000..bdcc3baf8 --- /dev/null +++ b/pkg/api/session/grpc/service_grpc.pb.go @@ -0,0 +1,119 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.3.0 +// - protoc v4.25.3 +// source: session/grpc/service.proto + +package session + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +const ( + SessionService_Create_FullMethodName = "/neo.fs.v2.session.SessionService/Create" +) + +// SessionServiceClient is the client API for SessionService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type SessionServiceClient interface { + // Open a new session between two peers. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): + // session has been successfully opened; + // - Common failures (SECTION_FAILURE_COMMON). + Create(ctx context.Context, in *CreateRequest, opts ...grpc.CallOption) (*CreateResponse, error) +} + +type sessionServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewSessionServiceClient(cc grpc.ClientConnInterface) SessionServiceClient { + return &sessionServiceClient{cc} +} + +func (c *sessionServiceClient) Create(ctx context.Context, in *CreateRequest, opts ...grpc.CallOption) (*CreateResponse, error) { + out := new(CreateResponse) + err := c.cc.Invoke(ctx, SessionService_Create_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// SessionServiceServer is the server API for SessionService service. +// All implementations should embed UnimplementedSessionServiceServer +// for forward compatibility +type SessionServiceServer interface { + // Open a new session between two peers. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): + // session has been successfully opened; + // - Common failures (SECTION_FAILURE_COMMON). + Create(context.Context, *CreateRequest) (*CreateResponse, error) +} + +// UnimplementedSessionServiceServer should be embedded to have forward compatible implementations. +type UnimplementedSessionServiceServer struct { +} + +func (UnimplementedSessionServiceServer) Create(context.Context, *CreateRequest) (*CreateResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Create not implemented") +} + +// UnsafeSessionServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to SessionServiceServer will +// result in compilation errors. +type UnsafeSessionServiceServer interface { + mustEmbedUnimplementedSessionServiceServer() +} + +func RegisterSessionServiceServer(s grpc.ServiceRegistrar, srv SessionServiceServer) { + s.RegisterService(&SessionService_ServiceDesc, srv) +} + +func _SessionService_Create_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CreateRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(SessionServiceServer).Create(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: SessionService_Create_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(SessionServiceServer).Create(ctx, req.(*CreateRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// SessionService_ServiceDesc is the grpc.ServiceDesc for SessionService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var SessionService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "neo.fs.v2.session.SessionService", + HandlerType: (*SessionServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Create", + Handler: _SessionService_Create_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "session/grpc/service.proto", +} diff --git a/pkg/api/session/grpc/types.go b/pkg/api/session/grpc/types.go new file mode 100644 index 000000000..6f601f3ad --- /dev/null +++ b/pkg/api/session/grpc/types.go @@ -0,0 +1,249 @@ +package session + +import ( + acl "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/acl/grpc" + refs "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs/grpc" + status "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/status/grpc" +) + +// SetKey sets key to the X-Header. +func (m *XHeader) SetKey(v string) { + m.Key = v +} + +// SetValue sets value of the X-Header. +func (m *XHeader) SetValue(v string) { + m.Value = v +} + +// SetExp sets epoch number of the token expiration. +func (m *SessionToken_Body_TokenLifetime) SetExp(v uint64) { + m.Exp = v +} + +// SetNbf sets starting epoch number of the token. +func (m *SessionToken_Body_TokenLifetime) SetNbf(v uint64) { + m.Nbf = v +} + +// SetIat sets the number of the epoch in which the token was issued. +func (m *SessionToken_Body_TokenLifetime) SetIat(v uint64) { + m.Iat = v +} + +// SetId sets identifier of the session token. +func (m *SessionToken_Body) SetId(v []byte) { + m.Id = v +} + +// SetOwnerId sets identifier of the session token owner. +func (m *SessionToken_Body) SetOwnerId(v *refs.OwnerID) { + m.OwnerId = v +} + +// SetLifetime sets lifetime of the session token. +func (m *SessionToken_Body) SetLifetime(v *SessionToken_Body_TokenLifetime) { + m.Lifetime = v +} + +// SetSessionKey sets public session key in a binary format. +func (m *SessionToken_Body) SetSessionKey(v []byte) { + m.SessionKey = v +} + +// SetObjectAddressContext sets object context of the session token. +func (m *SessionToken_Body) SetObjectSessionContext(v *ObjectSessionContext) { + m.Context = &SessionToken_Body_Object{ + Object: v, + } +} + +// SetContainerSessionContext sets container context of the session token. +func (m *SessionToken_Body) SetContainerSessionContext(v *ContainerSessionContext) { + m.Context = &SessionToken_Body_Container{ + Container: v, + } +} + +// SetTarget specifies objects involved in the object session. +func (m *ObjectSessionContext) SetTarget(cnr *refs.ContainerID, objs []*refs.ObjectID) { + m.Target = &ObjectSessionContext_Target{ + Container: cnr, + Objects: objs, + } +} + +// SetVerb sets type of request for which the token is issued. +func (m *ObjectSessionContext) SetVerb(v ObjectSessionContext_Verb) { + m.Verb = v +} + +// SetVerb sets type of request for which the token is issued. +func (x *ContainerSessionContext) SetVerb(v ContainerSessionContext_Verb) { + x.Verb = v +} + +// SetWildcard sets wildcard flag of the container session. +func (x *ContainerSessionContext) SetWildcard(v bool) { + x.Wildcard = v +} + +// SetContainerId sets identifier of the container related to the session. +func (x *ContainerSessionContext) SetContainerId(v *refs.ContainerID) { + x.ContainerId = v +} + +// SetBody sets session token body. +func (m *SessionToken) SetBody(v *SessionToken_Body) { + m.Body = v +} + +// SetSignature sets session token signature. +func (m *SessionToken) SetSignature(v *refs.Signature) { + m.Signature = v +} + +// SetVersion sets client protocol version. +func (m *RequestMetaHeader) SetVersion(v *refs.Version) { + m.Version = v +} + +// SetEpoch sets client local epoch. +func (m *RequestMetaHeader) SetEpoch(v uint64) { + m.Epoch = v +} + +// SetTtl sets request TTL. +func (m *RequestMetaHeader) SetTtl(v uint32) { + m.Ttl = v +} + +// SetXHeaders sets request X-Headers. +func (m *RequestMetaHeader) SetXHeaders(v []*XHeader) { + m.XHeaders = v +} + +// SetSessionToken sets session token of the request. +func (m *RequestMetaHeader) SetSessionToken(v *SessionToken) { + m.SessionToken = v +} + +// SetBearerToken sets bearer token of the request. +func (m *RequestMetaHeader) SetBearerToken(v *acl.BearerToken) { + m.BearerToken = v +} + +// SetOrigin sets origin request meta header. +func (m *RequestMetaHeader) SetOrigin(v *RequestMetaHeader) { + m.Origin = v +} + +// GetNetworkMagic returns NeoFS network magic. +func (m *RequestMetaHeader) GetNetworkMagic() uint64 { + if m != nil { + return m.MagicNumber + } + + return 0 +} + +// SetNetworkMagic sets NeoFS network magic. +func (m *RequestMetaHeader) SetNetworkMagic(v uint64) { + m.MagicNumber = v +} + +// SetVersion sets server protocol version. +func (m *ResponseMetaHeader) SetVersion(v *refs.Version) { + m.Version = v +} + +// SetEpoch sets server local epoch. +func (m *ResponseMetaHeader) SetEpoch(v uint64) { + m.Epoch = v +} + +// SetTtl sets response TTL. +func (m *ResponseMetaHeader) SetTtl(v uint32) { + m.Ttl = v +} + +// SetXHeaders sets response X-Headers. +func (m *ResponseMetaHeader) SetXHeaders(v []*XHeader) { + m.XHeaders = v +} + +// SetOrigin sets origin response meta header. +func (m *ResponseMetaHeader) SetOrigin(v *ResponseMetaHeader) { + m.Origin = v +} + +// SetStatus sets response status. +func (m *ResponseMetaHeader) SetStatus(v *status.Status) { + m.Status = v +} + +// SetBodySignature sets signature of the request body. +func (m *RequestVerificationHeader) SetBodySignature(v *refs.Signature) { + m.BodySignature = v +} + +// SetMetaSignature sets signature of the request meta. +func (m *RequestVerificationHeader) SetMetaSignature(v *refs.Signature) { + m.MetaSignature = v +} + +// SetOriginSignature sets signature of the origin verification header of the request. +func (m *RequestVerificationHeader) SetOriginSignature(v *refs.Signature) { + m.OriginSignature = v +} + +// SetOrigin sets origin verification header of the request. +func (m *RequestVerificationHeader) SetOrigin(v *RequestVerificationHeader) { + m.Origin = v +} + +// SetBodySignature sets signature of the response body. +func (m *ResponseVerificationHeader) SetBodySignature(v *refs.Signature) { + m.BodySignature = v +} + +// SetMetaSignature sets signature of the response meta. +func (m *ResponseVerificationHeader) SetMetaSignature(v *refs.Signature) { + m.MetaSignature = v +} + +// SetOriginSignature sets signature of the origin verification header of the response. +func (m *ResponseVerificationHeader) SetOriginSignature(v *refs.Signature) { + m.OriginSignature = v +} + +// SetOrigin sets origin verification header of the response. +func (m *ResponseVerificationHeader) SetOrigin(v *ResponseVerificationHeader) { + m.Origin = v +} + +// FromString parses ObjectSessionContext_Verb from a string representation, +// It is a reverse action to String(). +// +// Returns true if s was parsed successfully. +func (x *ObjectSessionContext_Verb) FromString(s string) bool { + i, ok := ObjectSessionContext_Verb_value[s] + if ok { + *x = ObjectSessionContext_Verb(i) + } + + return ok +} + +// FromString parses ContainerSessionContext_Verb from a string representation, +// It is a reverse action to String(). +// +// Returns true if s was parsed successfully. +func (x *ContainerSessionContext_Verb) FromString(s string) bool { + i, ok := ContainerSessionContext_Verb_value[s] + if ok { + *x = ContainerSessionContext_Verb(i) + } + + return ok +} diff --git a/pkg/api/session/grpc/types.pb.go b/pkg/api/session/grpc/types.pb.go new file mode 100644 index 000000000..71a9fc0be --- /dev/null +++ b/pkg/api/session/grpc/types.pb.go @@ -0,0 +1,1446 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.33.0 +// protoc v4.25.3 +// source: session/grpc/types.proto + +package session + +import ( + grpc1 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/acl/grpc" + grpc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs/grpc" + grpc2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/status/grpc" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// Object request verbs +type ObjectSessionContext_Verb int32 + +const ( + // Unknown verb + ObjectSessionContext_VERB_UNSPECIFIED ObjectSessionContext_Verb = 0 + // Refers to object.Put RPC call + ObjectSessionContext_PUT ObjectSessionContext_Verb = 1 + // Refers to object.Get RPC call + ObjectSessionContext_GET ObjectSessionContext_Verb = 2 + // Refers to object.Head RPC call + ObjectSessionContext_HEAD ObjectSessionContext_Verb = 3 + // Refers to object.Search RPC call + ObjectSessionContext_SEARCH ObjectSessionContext_Verb = 4 + // Refers to object.Delete RPC call + ObjectSessionContext_DELETE ObjectSessionContext_Verb = 5 + // Refers to object.GetRange RPC call + ObjectSessionContext_RANGE ObjectSessionContext_Verb = 6 + // Refers to object.GetRangeHash RPC call + ObjectSessionContext_RANGEHASH ObjectSessionContext_Verb = 7 +) + +// Enum value maps for ObjectSessionContext_Verb. +var ( + ObjectSessionContext_Verb_name = map[int32]string{ + 0: "VERB_UNSPECIFIED", + 1: "PUT", + 2: "GET", + 3: "HEAD", + 4: "SEARCH", + 5: "DELETE", + 6: "RANGE", + 7: "RANGEHASH", + } + ObjectSessionContext_Verb_value = map[string]int32{ + "VERB_UNSPECIFIED": 0, + "PUT": 1, + "GET": 2, + "HEAD": 3, + "SEARCH": 4, + "DELETE": 5, + "RANGE": 6, + "RANGEHASH": 7, + } +) + +func (x ObjectSessionContext_Verb) Enum() *ObjectSessionContext_Verb { + p := new(ObjectSessionContext_Verb) + *p = x + return p +} + +func (x ObjectSessionContext_Verb) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (ObjectSessionContext_Verb) Descriptor() protoreflect.EnumDescriptor { + return file_session_grpc_types_proto_enumTypes[0].Descriptor() +} + +func (ObjectSessionContext_Verb) Type() protoreflect.EnumType { + return &file_session_grpc_types_proto_enumTypes[0] +} + +func (x ObjectSessionContext_Verb) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use ObjectSessionContext_Verb.Descriptor instead. +func (ObjectSessionContext_Verb) EnumDescriptor() ([]byte, []int) { + return file_session_grpc_types_proto_rawDescGZIP(), []int{0, 0} +} + +// Container request verbs +type ContainerSessionContext_Verb int32 + +const ( + // Unknown verb + ContainerSessionContext_VERB_UNSPECIFIED ContainerSessionContext_Verb = 0 + // Refers to container.Put RPC call + ContainerSessionContext_PUT ContainerSessionContext_Verb = 1 + // Refers to container.Delete RPC call + ContainerSessionContext_DELETE ContainerSessionContext_Verb = 2 + // Refers to container.SetExtendedACL RPC call + ContainerSessionContext_SETEACL ContainerSessionContext_Verb = 3 +) + +// Enum value maps for ContainerSessionContext_Verb. +var ( + ContainerSessionContext_Verb_name = map[int32]string{ + 0: "VERB_UNSPECIFIED", + 1: "PUT", + 2: "DELETE", + 3: "SETEACL", + } + ContainerSessionContext_Verb_value = map[string]int32{ + "VERB_UNSPECIFIED": 0, + "PUT": 1, + "DELETE": 2, + "SETEACL": 3, + } +) + +func (x ContainerSessionContext_Verb) Enum() *ContainerSessionContext_Verb { + p := new(ContainerSessionContext_Verb) + *p = x + return p +} + +func (x ContainerSessionContext_Verb) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (ContainerSessionContext_Verb) Descriptor() protoreflect.EnumDescriptor { + return file_session_grpc_types_proto_enumTypes[1].Descriptor() +} + +func (ContainerSessionContext_Verb) Type() protoreflect.EnumType { + return &file_session_grpc_types_proto_enumTypes[1] +} + +func (x ContainerSessionContext_Verb) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use ContainerSessionContext_Verb.Descriptor instead. +func (ContainerSessionContext_Verb) EnumDescriptor() ([]byte, []int) { + return file_session_grpc_types_proto_rawDescGZIP(), []int{1, 0} +} + +// Context information for Session Tokens related to ObjectService requests +type ObjectSessionContext struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Type of request for which the token is issued + Verb ObjectSessionContext_Verb `protobuf:"varint,1,opt,name=verb,proto3,enum=neo.fs.v2.session.ObjectSessionContext_Verb" json:"verb,omitempty"` + // Object session target. MUST be correctly formed and set. If `objects` + // field is not empty, then the session applies only to these elements, + // otherwise, to all objects from the specified container. + Target *ObjectSessionContext_Target `protobuf:"bytes,2,opt,name=target,proto3" json:"target,omitempty"` +} + +func (x *ObjectSessionContext) Reset() { + *x = ObjectSessionContext{} + if protoimpl.UnsafeEnabled { + mi := &file_session_grpc_types_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ObjectSessionContext) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ObjectSessionContext) ProtoMessage() {} + +func (x *ObjectSessionContext) ProtoReflect() protoreflect.Message { + mi := &file_session_grpc_types_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ObjectSessionContext.ProtoReflect.Descriptor instead. +func (*ObjectSessionContext) Descriptor() ([]byte, []int) { + return file_session_grpc_types_proto_rawDescGZIP(), []int{0} +} + +func (x *ObjectSessionContext) GetVerb() ObjectSessionContext_Verb { + if x != nil { + return x.Verb + } + return ObjectSessionContext_VERB_UNSPECIFIED +} + +func (x *ObjectSessionContext) GetTarget() *ObjectSessionContext_Target { + if x != nil { + return x.Target + } + return nil +} + +// Context information for Session Tokens related to ContainerService requests. +type ContainerSessionContext struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Type of request for which the token is issued + Verb ContainerSessionContext_Verb `protobuf:"varint,1,opt,name=verb,proto3,enum=neo.fs.v2.session.ContainerSessionContext_Verb" json:"verb,omitempty"` + // Spreads the action to all owner containers. + // If set, container_id field is ignored. + Wildcard bool `protobuf:"varint,2,opt,name=wildcard,proto3" json:"wildcard,omitempty"` + // Particular container to which the action applies. + // Ignored if wildcard flag is set. + ContainerId *grpc.ContainerID `protobuf:"bytes,3,opt,name=container_id,json=containerID,proto3" json:"container_id,omitempty"` +} + +func (x *ContainerSessionContext) Reset() { + *x = ContainerSessionContext{} + if protoimpl.UnsafeEnabled { + mi := &file_session_grpc_types_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ContainerSessionContext) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ContainerSessionContext) ProtoMessage() {} + +func (x *ContainerSessionContext) ProtoReflect() protoreflect.Message { + mi := &file_session_grpc_types_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ContainerSessionContext.ProtoReflect.Descriptor instead. +func (*ContainerSessionContext) Descriptor() ([]byte, []int) { + return file_session_grpc_types_proto_rawDescGZIP(), []int{1} +} + +func (x *ContainerSessionContext) GetVerb() ContainerSessionContext_Verb { + if x != nil { + return x.Verb + } + return ContainerSessionContext_VERB_UNSPECIFIED +} + +func (x *ContainerSessionContext) GetWildcard() bool { + if x != nil { + return x.Wildcard + } + return false +} + +func (x *ContainerSessionContext) GetContainerId() *grpc.ContainerID { + if x != nil { + return x.ContainerId + } + return nil +} + +// NeoFS Session Token. +type SessionToken struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Session Token contains the proof of trust between peers to be attached in + // requests for further verification. Please see corresponding section of + // NeoFS Technical Specification for details. + Body *SessionToken_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Signature of `SessionToken` information + Signature *grpc.Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` +} + +func (x *SessionToken) Reset() { + *x = SessionToken{} + if protoimpl.UnsafeEnabled { + mi := &file_session_grpc_types_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SessionToken) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SessionToken) ProtoMessage() {} + +func (x *SessionToken) ProtoReflect() protoreflect.Message { + mi := &file_session_grpc_types_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SessionToken.ProtoReflect.Descriptor instead. +func (*SessionToken) Descriptor() ([]byte, []int) { + return file_session_grpc_types_proto_rawDescGZIP(), []int{2} +} + +func (x *SessionToken) GetBody() *SessionToken_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *SessionToken) GetSignature() *grpc.Signature { + if x != nil { + return x.Signature + } + return nil +} + +// Extended headers for Request/Response. They may contain any user-defined +// headers to be interpreted on application level. +// +// Key name must be a unique valid UTF-8 string. Value can't be empty. Requests +// or Responses with duplicated header names or headers with empty values will +// be considered invalid. +// +// There are some "well-known" headers starting with `__SYSTEM__` (`__NEOFS__` +// is deprecated) prefix that affect system behaviour: +// +// - [ __SYSTEM__NETMAP_EPOCH ] \ +// (`__NEOFS__NETMAP_EPOCH` is deprecated) \ +// Netmap epoch to use for object placement calculation. The `value` is string +// encoded `uint64` in decimal presentation. If set to '0' or not set, the +// current epoch only will be used. +// - [ __SYSTEM__NETMAP_LOOKUP_DEPTH ] \ +// (`__NEOFS__NETMAP_LOOKUP_DEPTH` is deprecated) \ +// If object can't be found using current epoch's netmap, this header limits +// how many past epochs the node can look up through. The `value` is string +// encoded `uint64` in decimal presentation. If set to '0' or not set, only +// the current epoch will be used. +type XHeader struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Key of the X-Header + Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` + // Value of the X-Header + Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` +} + +func (x *XHeader) Reset() { + *x = XHeader{} + if protoimpl.UnsafeEnabled { + mi := &file_session_grpc_types_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *XHeader) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*XHeader) ProtoMessage() {} + +func (x *XHeader) ProtoReflect() protoreflect.Message { + mi := &file_session_grpc_types_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use XHeader.ProtoReflect.Descriptor instead. +func (*XHeader) Descriptor() ([]byte, []int) { + return file_session_grpc_types_proto_rawDescGZIP(), []int{3} +} + +func (x *XHeader) GetKey() string { + if x != nil { + return x.Key + } + return "" +} + +func (x *XHeader) GetValue() string { + if x != nil { + return x.Value + } + return "" +} + +// Meta information attached to the request. When forwarded between peers, +// request meta headers are folded in matryoshka style. +type RequestMetaHeader struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Peer's API version used + Version *grpc.Version `protobuf:"bytes,1,opt,name=version,proto3" json:"version,omitempty"` + // Peer's local epoch number. Set to 0 if unknown. + Epoch uint64 `protobuf:"varint,2,opt,name=epoch,proto3" json:"epoch,omitempty"` + // Maximum number of intermediate nodes in the request route + Ttl uint32 `protobuf:"varint,3,opt,name=ttl,proto3" json:"ttl,omitempty"` + // Request X-Headers + XHeaders []*XHeader `protobuf:"bytes,4,rep,name=x_headers,json=xHeaders,proto3" json:"x_headers,omitempty"` + // Session token within which the request is sent + SessionToken *SessionToken `protobuf:"bytes,5,opt,name=session_token,json=sessionToken,proto3" json:"session_token,omitempty"` + // `BearerToken` with eACL overrides for the request + BearerToken *grpc1.BearerToken `protobuf:"bytes,6,opt,name=bearer_token,json=bearerToken,proto3" json:"bearer_token,omitempty"` + // `RequestMetaHeader` of the origin request + Origin *RequestMetaHeader `protobuf:"bytes,7,opt,name=origin,proto3" json:"origin,omitempty"` + // NeoFS network magic. Must match the value for the network + // that the server belongs to. + MagicNumber uint64 `protobuf:"varint,8,opt,name=magic_number,json=magicNumber,proto3" json:"magic_number,omitempty"` +} + +func (x *RequestMetaHeader) Reset() { + *x = RequestMetaHeader{} + if protoimpl.UnsafeEnabled { + mi := &file_session_grpc_types_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RequestMetaHeader) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RequestMetaHeader) ProtoMessage() {} + +func (x *RequestMetaHeader) ProtoReflect() protoreflect.Message { + mi := &file_session_grpc_types_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RequestMetaHeader.ProtoReflect.Descriptor instead. +func (*RequestMetaHeader) Descriptor() ([]byte, []int) { + return file_session_grpc_types_proto_rawDescGZIP(), []int{4} +} + +func (x *RequestMetaHeader) GetVersion() *grpc.Version { + if x != nil { + return x.Version + } + return nil +} + +func (x *RequestMetaHeader) GetEpoch() uint64 { + if x != nil { + return x.Epoch + } + return 0 +} + +func (x *RequestMetaHeader) GetTtl() uint32 { + if x != nil { + return x.Ttl + } + return 0 +} + +func (x *RequestMetaHeader) GetXHeaders() []*XHeader { + if x != nil { + return x.XHeaders + } + return nil +} + +func (x *RequestMetaHeader) GetSessionToken() *SessionToken { + if x != nil { + return x.SessionToken + } + return nil +} + +func (x *RequestMetaHeader) GetBearerToken() *grpc1.BearerToken { + if x != nil { + return x.BearerToken + } + return nil +} + +func (x *RequestMetaHeader) GetOrigin() *RequestMetaHeader { + if x != nil { + return x.Origin + } + return nil +} + +func (x *RequestMetaHeader) GetMagicNumber() uint64 { + if x != nil { + return x.MagicNumber + } + return 0 +} + +// Information about the response +type ResponseMetaHeader struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Peer's API version used + Version *grpc.Version `protobuf:"bytes,1,opt,name=version,proto3" json:"version,omitempty"` + // Peer's local epoch number + Epoch uint64 `protobuf:"varint,2,opt,name=epoch,proto3" json:"epoch,omitempty"` + // Maximum number of intermediate nodes in the request route + Ttl uint32 `protobuf:"varint,3,opt,name=ttl,proto3" json:"ttl,omitempty"` + // Response X-Headers + XHeaders []*XHeader `protobuf:"bytes,4,rep,name=x_headers,json=xHeaders,proto3" json:"x_headers,omitempty"` + // `ResponseMetaHeader` of the origin request + Origin *ResponseMetaHeader `protobuf:"bytes,5,opt,name=origin,proto3" json:"origin,omitempty"` + // Status return + Status *grpc2.Status `protobuf:"bytes,6,opt,name=status,proto3" json:"status,omitempty"` +} + +func (x *ResponseMetaHeader) Reset() { + *x = ResponseMetaHeader{} + if protoimpl.UnsafeEnabled { + mi := &file_session_grpc_types_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ResponseMetaHeader) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ResponseMetaHeader) ProtoMessage() {} + +func (x *ResponseMetaHeader) ProtoReflect() protoreflect.Message { + mi := &file_session_grpc_types_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ResponseMetaHeader.ProtoReflect.Descriptor instead. +func (*ResponseMetaHeader) Descriptor() ([]byte, []int) { + return file_session_grpc_types_proto_rawDescGZIP(), []int{5} +} + +func (x *ResponseMetaHeader) GetVersion() *grpc.Version { + if x != nil { + return x.Version + } + return nil +} + +func (x *ResponseMetaHeader) GetEpoch() uint64 { + if x != nil { + return x.Epoch + } + return 0 +} + +func (x *ResponseMetaHeader) GetTtl() uint32 { + if x != nil { + return x.Ttl + } + return 0 +} + +func (x *ResponseMetaHeader) GetXHeaders() []*XHeader { + if x != nil { + return x.XHeaders + } + return nil +} + +func (x *ResponseMetaHeader) GetOrigin() *ResponseMetaHeader { + if x != nil { + return x.Origin + } + return nil +} + +func (x *ResponseMetaHeader) GetStatus() *grpc2.Status { + if x != nil { + return x.Status + } + return nil +} + +// Verification info for the request signed by all intermediate nodes. +type RequestVerificationHeader struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Request Body signature. Should be generated once by the request initiator. + BodySignature *grpc.Signature `protobuf:"bytes,1,opt,name=body_signature,json=bodySignature,proto3" json:"body_signature,omitempty"` + // Request Meta signature is added and signed by each intermediate node + MetaSignature *grpc.Signature `protobuf:"bytes,2,opt,name=meta_signature,json=metaSignature,proto3" json:"meta_signature,omitempty"` + // Signature of previous hops + OriginSignature *grpc.Signature `protobuf:"bytes,3,opt,name=origin_signature,json=originSignature,proto3" json:"origin_signature,omitempty"` + // Chain of previous hops signatures + Origin *RequestVerificationHeader `protobuf:"bytes,4,opt,name=origin,proto3" json:"origin,omitempty"` +} + +func (x *RequestVerificationHeader) Reset() { + *x = RequestVerificationHeader{} + if protoimpl.UnsafeEnabled { + mi := &file_session_grpc_types_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RequestVerificationHeader) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RequestVerificationHeader) ProtoMessage() {} + +func (x *RequestVerificationHeader) ProtoReflect() protoreflect.Message { + mi := &file_session_grpc_types_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RequestVerificationHeader.ProtoReflect.Descriptor instead. +func (*RequestVerificationHeader) Descriptor() ([]byte, []int) { + return file_session_grpc_types_proto_rawDescGZIP(), []int{6} +} + +func (x *RequestVerificationHeader) GetBodySignature() *grpc.Signature { + if x != nil { + return x.BodySignature + } + return nil +} + +func (x *RequestVerificationHeader) GetMetaSignature() *grpc.Signature { + if x != nil { + return x.MetaSignature + } + return nil +} + +func (x *RequestVerificationHeader) GetOriginSignature() *grpc.Signature { + if x != nil { + return x.OriginSignature + } + return nil +} + +func (x *RequestVerificationHeader) GetOrigin() *RequestVerificationHeader { + if x != nil { + return x.Origin + } + return nil +} + +// Verification info for the response signed by all intermediate nodes +type ResponseVerificationHeader struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Response Body signature. Should be generated once by an answering node. + BodySignature *grpc.Signature `protobuf:"bytes,1,opt,name=body_signature,json=bodySignature,proto3" json:"body_signature,omitempty"` + // Response Meta signature is added and signed by each intermediate node + MetaSignature *grpc.Signature `protobuf:"bytes,2,opt,name=meta_signature,json=metaSignature,proto3" json:"meta_signature,omitempty"` + // Signature of previous hops + OriginSignature *grpc.Signature `protobuf:"bytes,3,opt,name=origin_signature,json=originSignature,proto3" json:"origin_signature,omitempty"` + // Chain of previous hops signatures + Origin *ResponseVerificationHeader `protobuf:"bytes,4,opt,name=origin,proto3" json:"origin,omitempty"` +} + +func (x *ResponseVerificationHeader) Reset() { + *x = ResponseVerificationHeader{} + if protoimpl.UnsafeEnabled { + mi := &file_session_grpc_types_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ResponseVerificationHeader) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ResponseVerificationHeader) ProtoMessage() {} + +func (x *ResponseVerificationHeader) ProtoReflect() protoreflect.Message { + mi := &file_session_grpc_types_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ResponseVerificationHeader.ProtoReflect.Descriptor instead. +func (*ResponseVerificationHeader) Descriptor() ([]byte, []int) { + return file_session_grpc_types_proto_rawDescGZIP(), []int{7} +} + +func (x *ResponseVerificationHeader) GetBodySignature() *grpc.Signature { + if x != nil { + return x.BodySignature + } + return nil +} + +func (x *ResponseVerificationHeader) GetMetaSignature() *grpc.Signature { + if x != nil { + return x.MetaSignature + } + return nil +} + +func (x *ResponseVerificationHeader) GetOriginSignature() *grpc.Signature { + if x != nil { + return x.OriginSignature + } + return nil +} + +func (x *ResponseVerificationHeader) GetOrigin() *ResponseVerificationHeader { + if x != nil { + return x.Origin + } + return nil +} + +// Carries objects involved in the object session. +type ObjectSessionContext_Target struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Indicates which container the session is spread to. Field MUST be set + // and correct. + Container *grpc.ContainerID `protobuf:"bytes,1,opt,name=container,proto3" json:"container,omitempty"` + // Indicates which objects the session is spread to. Objects are expected + // to be stored in the NeoFS container referenced by `container` field. + // Each element MUST have correct format. + Objects []*grpc.ObjectID `protobuf:"bytes,2,rep,name=objects,proto3" json:"objects,omitempty"` +} + +func (x *ObjectSessionContext_Target) Reset() { + *x = ObjectSessionContext_Target{} + if protoimpl.UnsafeEnabled { + mi := &file_session_grpc_types_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ObjectSessionContext_Target) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ObjectSessionContext_Target) ProtoMessage() {} + +func (x *ObjectSessionContext_Target) ProtoReflect() protoreflect.Message { + mi := &file_session_grpc_types_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ObjectSessionContext_Target.ProtoReflect.Descriptor instead. +func (*ObjectSessionContext_Target) Descriptor() ([]byte, []int) { + return file_session_grpc_types_proto_rawDescGZIP(), []int{0, 0} +} + +func (x *ObjectSessionContext_Target) GetContainer() *grpc.ContainerID { + if x != nil { + return x.Container + } + return nil +} + +func (x *ObjectSessionContext_Target) GetObjects() []*grpc.ObjectID { + if x != nil { + return x.Objects + } + return nil +} + +// Session Token body +type SessionToken_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Token identifier is a valid UUIDv4 in binary form + Id []byte `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + // Identifier of the session initiator + OwnerId *grpc.OwnerID `protobuf:"bytes,2,opt,name=owner_id,json=ownerID,proto3" json:"owner_id,omitempty"` + // Lifetime of the session + Lifetime *SessionToken_Body_TokenLifetime `protobuf:"bytes,3,opt,name=lifetime,proto3" json:"lifetime,omitempty"` + // Public key used in session + SessionKey []byte `protobuf:"bytes,4,opt,name=session_key,json=sessionKey,proto3" json:"session_key,omitempty"` + // Session Context information + // + // Types that are assignable to Context: + // + // *SessionToken_Body_Object + // *SessionToken_Body_Container + Context isSessionToken_Body_Context `protobuf_oneof:"context"` +} + +func (x *SessionToken_Body) Reset() { + *x = SessionToken_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_session_grpc_types_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SessionToken_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SessionToken_Body) ProtoMessage() {} + +func (x *SessionToken_Body) ProtoReflect() protoreflect.Message { + mi := &file_session_grpc_types_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SessionToken_Body.ProtoReflect.Descriptor instead. +func (*SessionToken_Body) Descriptor() ([]byte, []int) { + return file_session_grpc_types_proto_rawDescGZIP(), []int{2, 0} +} + +func (x *SessionToken_Body) GetId() []byte { + if x != nil { + return x.Id + } + return nil +} + +func (x *SessionToken_Body) GetOwnerId() *grpc.OwnerID { + if x != nil { + return x.OwnerId + } + return nil +} + +func (x *SessionToken_Body) GetLifetime() *SessionToken_Body_TokenLifetime { + if x != nil { + return x.Lifetime + } + return nil +} + +func (x *SessionToken_Body) GetSessionKey() []byte { + if x != nil { + return x.SessionKey + } + return nil +} + +func (m *SessionToken_Body) GetContext() isSessionToken_Body_Context { + if m != nil { + return m.Context + } + return nil +} + +func (x *SessionToken_Body) GetObject() *ObjectSessionContext { + if x, ok := x.GetContext().(*SessionToken_Body_Object); ok { + return x.Object + } + return nil +} + +func (x *SessionToken_Body) GetContainer() *ContainerSessionContext { + if x, ok := x.GetContext().(*SessionToken_Body_Container); ok { + return x.Container + } + return nil +} + +type isSessionToken_Body_Context interface { + isSessionToken_Body_Context() +} + +type SessionToken_Body_Object struct { + // ObjectService session context + Object *ObjectSessionContext `protobuf:"bytes,5,opt,name=object,proto3,oneof"` +} + +type SessionToken_Body_Container struct { + // ContainerService session context + Container *ContainerSessionContext `protobuf:"bytes,6,opt,name=container,proto3,oneof"` +} + +func (*SessionToken_Body_Object) isSessionToken_Body_Context() {} + +func (*SessionToken_Body_Container) isSessionToken_Body_Context() {} + +// Lifetime parameters of the token. Field names taken from rfc7519. +type SessionToken_Body_TokenLifetime struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Expiration Epoch + Exp uint64 `protobuf:"varint,1,opt,name=exp,proto3" json:"exp,omitempty"` + // Not valid before Epoch + Nbf uint64 `protobuf:"varint,2,opt,name=nbf,proto3" json:"nbf,omitempty"` + // Issued at Epoch + Iat uint64 `protobuf:"varint,3,opt,name=iat,proto3" json:"iat,omitempty"` +} + +func (x *SessionToken_Body_TokenLifetime) Reset() { + *x = SessionToken_Body_TokenLifetime{} + if protoimpl.UnsafeEnabled { + mi := &file_session_grpc_types_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SessionToken_Body_TokenLifetime) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SessionToken_Body_TokenLifetime) ProtoMessage() {} + +func (x *SessionToken_Body_TokenLifetime) ProtoReflect() protoreflect.Message { + mi := &file_session_grpc_types_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SessionToken_Body_TokenLifetime.ProtoReflect.Descriptor instead. +func (*SessionToken_Body_TokenLifetime) Descriptor() ([]byte, []int) { + return file_session_grpc_types_proto_rawDescGZIP(), []int{2, 0, 0} +} + +func (x *SessionToken_Body_TokenLifetime) GetExp() uint64 { + if x != nil { + return x.Exp + } + return 0 +} + +func (x *SessionToken_Body_TokenLifetime) GetNbf() uint64 { + if x != nil { + return x.Nbf + } + return 0 +} + +func (x *SessionToken_Body_TokenLifetime) GetIat() uint64 { + if x != nil { + return x.Iat + } + return 0 +} + +var File_session_grpc_types_proto protoreflect.FileDescriptor + +var file_session_grpc_types_proto_rawDesc = []byte{ + 0x0a, 0x18, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x74, + 0x79, 0x70, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x11, 0x6e, 0x65, 0x6f, 0x2e, + 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x1a, 0x15, 0x72, + 0x65, 0x66, 0x73, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x14, 0x61, 0x63, 0x6c, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x74, + 0x79, 0x70, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x17, 0x73, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x22, 0x85, 0x03, 0x0a, 0x14, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x65, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x40, 0x0a, 0x04, + 0x76, 0x65, 0x72, 0x62, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2c, 0x2e, 0x6e, 0x65, 0x6f, + 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x4f, + 0x62, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x74, + 0x65, 0x78, 0x74, 0x2e, 0x56, 0x65, 0x72, 0x62, 0x52, 0x04, 0x76, 0x65, 0x72, 0x62, 0x12, 0x46, + 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, + 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x2e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, + 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x1a, 0x77, 0x0a, 0x06, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, + 0x12, 0x39, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, + 0x72, 0x65, 0x66, 0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x44, + 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x32, 0x0a, 0x07, 0x6f, + 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6e, + 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x65, 0x66, 0x73, 0x2e, 0x4f, 0x62, + 0x6a, 0x65, 0x63, 0x74, 0x49, 0x44, 0x52, 0x07, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x22, + 0x6a, 0x0a, 0x04, 0x56, 0x65, 0x72, 0x62, 0x12, 0x14, 0x0a, 0x10, 0x56, 0x45, 0x52, 0x42, 0x5f, + 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x07, 0x0a, + 0x03, 0x50, 0x55, 0x54, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x47, 0x45, 0x54, 0x10, 0x02, 0x12, + 0x08, 0x0a, 0x04, 0x48, 0x45, 0x41, 0x44, 0x10, 0x03, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x45, 0x41, + 0x52, 0x43, 0x48, 0x10, 0x04, 0x12, 0x0a, 0x0a, 0x06, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x10, + 0x05, 0x12, 0x09, 0x0a, 0x05, 0x52, 0x41, 0x4e, 0x47, 0x45, 0x10, 0x06, 0x12, 0x0d, 0x0a, 0x09, + 0x52, 0x41, 0x4e, 0x47, 0x45, 0x48, 0x41, 0x53, 0x48, 0x10, 0x07, 0x22, 0xfa, 0x01, 0x0a, 0x17, + 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x43, 0x0a, 0x04, 0x76, 0x65, 0x72, 0x62, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2f, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, + 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, + 0x6e, 0x65, 0x72, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, + 0x74, 0x2e, 0x56, 0x65, 0x72, 0x62, 0x52, 0x04, 0x76, 0x65, 0x72, 0x62, 0x12, 0x1a, 0x0a, 0x08, + 0x77, 0x69, 0x6c, 0x64, 0x63, 0x61, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, + 0x77, 0x69, 0x6c, 0x64, 0x63, 0x61, 0x72, 0x64, 0x12, 0x3e, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, + 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, + 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x65, 0x66, 0x73, 0x2e, + 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x44, 0x52, 0x0b, 0x63, 0x6f, 0x6e, + 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x44, 0x22, 0x3e, 0x0a, 0x04, 0x56, 0x65, 0x72, 0x62, + 0x12, 0x14, 0x0a, 0x10, 0x56, 0x45, 0x52, 0x42, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, + 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x50, 0x55, 0x54, 0x10, 0x01, 0x12, + 0x0a, 0x0a, 0x06, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x53, + 0x45, 0x54, 0x45, 0x41, 0x43, 0x4c, 0x10, 0x03, 0x22, 0xa0, 0x04, 0x0a, 0x0c, 0x53, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x38, 0x0a, 0x04, 0x62, 0x6f, 0x64, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, + 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x53, 0x65, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, + 0x6f, 0x64, 0x79, 0x12, 0x37, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, + 0x76, 0x32, 0x2e, 0x72, 0x65, 0x66, 0x73, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x9c, 0x03, 0x0a, + 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x02, 0x69, 0x64, 0x12, 0x32, 0x0a, 0x08, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x69, + 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, + 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x65, 0x66, 0x73, 0x2e, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x49, 0x44, + 0x52, 0x07, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x49, 0x44, 0x12, 0x4e, 0x0a, 0x08, 0x6c, 0x69, 0x66, + 0x65, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x6e, 0x65, + 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, + 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x2e, 0x42, 0x6f, 0x64, + 0x79, 0x2e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x4c, 0x69, 0x66, 0x65, 0x74, 0x69, 0x6d, 0x65, 0x52, + 0x08, 0x6c, 0x69, 0x66, 0x65, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, + 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79, 0x12, 0x41, 0x0a, 0x06, 0x6f, 0x62, + 0x6a, 0x65, 0x63, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x6e, 0x65, 0x6f, + 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x4f, + 0x62, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x74, + 0x65, 0x78, 0x74, 0x48, 0x00, 0x52, 0x06, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x4a, 0x0a, + 0x09, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x2a, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x53, 0x65, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x48, 0x00, 0x52, 0x09, + 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x1a, 0x45, 0x0a, 0x0d, 0x54, 0x6f, 0x6b, + 0x65, 0x6e, 0x4c, 0x69, 0x66, 0x65, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x78, + 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x65, 0x78, 0x70, 0x12, 0x10, 0x0a, 0x03, + 0x6e, 0x62, 0x66, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x6e, 0x62, 0x66, 0x12, 0x10, + 0x0a, 0x03, 0x69, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x69, 0x61, 0x74, + 0x42, 0x09, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0x31, 0x0a, 0x07, 0x58, + 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x8d, + 0x03, 0x0a, 0x11, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x48, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x12, 0x31, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, + 0x32, 0x2e, 0x72, 0x65, 0x66, 0x73, 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x07, + 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x10, 0x0a, + 0x03, 0x74, 0x74, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x74, 0x74, 0x6c, 0x12, + 0x37, 0x0a, 0x09, 0x78, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, + 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x58, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x08, + 0x78, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x44, 0x0a, 0x0d, 0x73, 0x65, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1f, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, + 0x52, 0x0c, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x3d, + 0x0a, 0x0c, 0x62, 0x65, 0x61, 0x72, 0x65, 0x72, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, + 0x2e, 0x61, 0x63, 0x6c, 0x2e, 0x42, 0x65, 0x61, 0x72, 0x65, 0x72, 0x54, 0x6f, 0x6b, 0x65, 0x6e, + 0x52, 0x0b, 0x62, 0x65, 0x61, 0x72, 0x65, 0x72, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x3c, 0x0a, + 0x06, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, + 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x52, 0x06, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x6d, + 0x61, 0x67, 0x69, 0x63, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, + 0x04, 0x52, 0x0b, 0x6d, 0x61, 0x67, 0x69, 0x63, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0x99, + 0x02, 0x0a, 0x12, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x48, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x31, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, + 0x76, 0x32, 0x2e, 0x72, 0x65, 0x66, 0x73, 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, + 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, + 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x10, + 0x0a, 0x03, 0x74, 0x74, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x74, 0x74, 0x6c, + 0x12, 0x37, 0x0a, 0x09, 0x78, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, + 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x58, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, + 0x08, 0x78, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x3d, 0x0a, 0x06, 0x6f, 0x72, 0x69, + 0x67, 0x69, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, + 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x52, 0x06, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x12, 0x30, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, + 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0xab, 0x02, 0x0a, 0x19, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x40, 0x0a, 0x0e, 0x62, 0x6f, 0x64, 0x79, + 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x19, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x65, 0x66, + 0x73, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x0d, 0x62, 0x6f, 0x64, + 0x79, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x40, 0x0a, 0x0e, 0x6d, 0x65, + 0x74, 0x61, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x72, + 0x65, 0x66, 0x73, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x0d, 0x6d, + 0x65, 0x74, 0x61, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x44, 0x0a, 0x10, + 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, + 0x76, 0x32, 0x2e, 0x72, 0x65, 0x66, 0x73, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x52, 0x0f, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x12, 0x44, 0x0a, 0x06, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, + 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x65, + 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x52, 0x06, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x22, 0xad, 0x02, 0x0a, 0x1a, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x40, 0x0a, 0x0e, 0x62, 0x6f, 0x64, 0x79, 0x5f, + 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x19, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x65, 0x66, 0x73, + 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x0d, 0x62, 0x6f, 0x64, 0x79, + 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x40, 0x0a, 0x0e, 0x6d, 0x65, 0x74, + 0x61, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x19, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x65, + 0x66, 0x73, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x0d, 0x6d, 0x65, + 0x74, 0x61, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x44, 0x0a, 0x10, 0x6f, + 0x72, 0x69, 0x67, 0x69, 0x6e, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, + 0x32, 0x2e, 0x72, 0x65, 0x66, 0x73, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x52, 0x0f, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x12, 0x45, 0x0a, 0x06, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x2d, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x65, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x56, 0x65, + 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x52, 0x06, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x42, 0x64, 0x5a, 0x44, 0x67, 0x69, 0x74, 0x2e, + 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, 0x75, + 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x4c, 0x61, 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, + 0x73, 0x2d, 0x61, 0x70, 0x69, 0x2d, 0x67, 0x6f, 0x2f, 0x76, 0x32, 0x2f, 0x73, 0x65, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x3b, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0xaa, 0x02, 0x1b, 0x4e, 0x65, 0x6f, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x61, + 0x67, 0x65, 0x2e, 0x41, 0x50, 0x49, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_session_grpc_types_proto_rawDescOnce sync.Once + file_session_grpc_types_proto_rawDescData = file_session_grpc_types_proto_rawDesc +) + +func file_session_grpc_types_proto_rawDescGZIP() []byte { + file_session_grpc_types_proto_rawDescOnce.Do(func() { + file_session_grpc_types_proto_rawDescData = protoimpl.X.CompressGZIP(file_session_grpc_types_proto_rawDescData) + }) + return file_session_grpc_types_proto_rawDescData +} + +var file_session_grpc_types_proto_enumTypes = make([]protoimpl.EnumInfo, 2) +var file_session_grpc_types_proto_msgTypes = make([]protoimpl.MessageInfo, 11) +var file_session_grpc_types_proto_goTypes = []interface{}{ + (ObjectSessionContext_Verb)(0), // 0: neo.fs.v2.session.ObjectSessionContext.Verb + (ContainerSessionContext_Verb)(0), // 1: neo.fs.v2.session.ContainerSessionContext.Verb + (*ObjectSessionContext)(nil), // 2: neo.fs.v2.session.ObjectSessionContext + (*ContainerSessionContext)(nil), // 3: neo.fs.v2.session.ContainerSessionContext + (*SessionToken)(nil), // 4: neo.fs.v2.session.SessionToken + (*XHeader)(nil), // 5: neo.fs.v2.session.XHeader + (*RequestMetaHeader)(nil), // 6: neo.fs.v2.session.RequestMetaHeader + (*ResponseMetaHeader)(nil), // 7: neo.fs.v2.session.ResponseMetaHeader + (*RequestVerificationHeader)(nil), // 8: neo.fs.v2.session.RequestVerificationHeader + (*ResponseVerificationHeader)(nil), // 9: neo.fs.v2.session.ResponseVerificationHeader + (*ObjectSessionContext_Target)(nil), // 10: neo.fs.v2.session.ObjectSessionContext.Target + (*SessionToken_Body)(nil), // 11: neo.fs.v2.session.SessionToken.Body + (*SessionToken_Body_TokenLifetime)(nil), // 12: neo.fs.v2.session.SessionToken.Body.TokenLifetime + (*grpc.ContainerID)(nil), // 13: neo.fs.v2.refs.ContainerID + (*grpc.Signature)(nil), // 14: neo.fs.v2.refs.Signature + (*grpc.Version)(nil), // 15: neo.fs.v2.refs.Version + (*grpc1.BearerToken)(nil), // 16: neo.fs.v2.acl.BearerToken + (*grpc2.Status)(nil), // 17: neo.fs.v2.status.Status + (*grpc.ObjectID)(nil), // 18: neo.fs.v2.refs.ObjectID + (*grpc.OwnerID)(nil), // 19: neo.fs.v2.refs.OwnerID +} +var file_session_grpc_types_proto_depIdxs = []int32{ + 0, // 0: neo.fs.v2.session.ObjectSessionContext.verb:type_name -> neo.fs.v2.session.ObjectSessionContext.Verb + 10, // 1: neo.fs.v2.session.ObjectSessionContext.target:type_name -> neo.fs.v2.session.ObjectSessionContext.Target + 1, // 2: neo.fs.v2.session.ContainerSessionContext.verb:type_name -> neo.fs.v2.session.ContainerSessionContext.Verb + 13, // 3: neo.fs.v2.session.ContainerSessionContext.container_id:type_name -> neo.fs.v2.refs.ContainerID + 11, // 4: neo.fs.v2.session.SessionToken.body:type_name -> neo.fs.v2.session.SessionToken.Body + 14, // 5: neo.fs.v2.session.SessionToken.signature:type_name -> neo.fs.v2.refs.Signature + 15, // 6: neo.fs.v2.session.RequestMetaHeader.version:type_name -> neo.fs.v2.refs.Version + 5, // 7: neo.fs.v2.session.RequestMetaHeader.x_headers:type_name -> neo.fs.v2.session.XHeader + 4, // 8: neo.fs.v2.session.RequestMetaHeader.session_token:type_name -> neo.fs.v2.session.SessionToken + 16, // 9: neo.fs.v2.session.RequestMetaHeader.bearer_token:type_name -> neo.fs.v2.acl.BearerToken + 6, // 10: neo.fs.v2.session.RequestMetaHeader.origin:type_name -> neo.fs.v2.session.RequestMetaHeader + 15, // 11: neo.fs.v2.session.ResponseMetaHeader.version:type_name -> neo.fs.v2.refs.Version + 5, // 12: neo.fs.v2.session.ResponseMetaHeader.x_headers:type_name -> neo.fs.v2.session.XHeader + 7, // 13: neo.fs.v2.session.ResponseMetaHeader.origin:type_name -> neo.fs.v2.session.ResponseMetaHeader + 17, // 14: neo.fs.v2.session.ResponseMetaHeader.status:type_name -> neo.fs.v2.status.Status + 14, // 15: neo.fs.v2.session.RequestVerificationHeader.body_signature:type_name -> neo.fs.v2.refs.Signature + 14, // 16: neo.fs.v2.session.RequestVerificationHeader.meta_signature:type_name -> neo.fs.v2.refs.Signature + 14, // 17: neo.fs.v2.session.RequestVerificationHeader.origin_signature:type_name -> neo.fs.v2.refs.Signature + 8, // 18: neo.fs.v2.session.RequestVerificationHeader.origin:type_name -> neo.fs.v2.session.RequestVerificationHeader + 14, // 19: neo.fs.v2.session.ResponseVerificationHeader.body_signature:type_name -> neo.fs.v2.refs.Signature + 14, // 20: neo.fs.v2.session.ResponseVerificationHeader.meta_signature:type_name -> neo.fs.v2.refs.Signature + 14, // 21: neo.fs.v2.session.ResponseVerificationHeader.origin_signature:type_name -> neo.fs.v2.refs.Signature + 9, // 22: neo.fs.v2.session.ResponseVerificationHeader.origin:type_name -> neo.fs.v2.session.ResponseVerificationHeader + 13, // 23: neo.fs.v2.session.ObjectSessionContext.Target.container:type_name -> neo.fs.v2.refs.ContainerID + 18, // 24: neo.fs.v2.session.ObjectSessionContext.Target.objects:type_name -> neo.fs.v2.refs.ObjectID + 19, // 25: neo.fs.v2.session.SessionToken.Body.owner_id:type_name -> neo.fs.v2.refs.OwnerID + 12, // 26: neo.fs.v2.session.SessionToken.Body.lifetime:type_name -> neo.fs.v2.session.SessionToken.Body.TokenLifetime + 2, // 27: neo.fs.v2.session.SessionToken.Body.object:type_name -> neo.fs.v2.session.ObjectSessionContext + 3, // 28: neo.fs.v2.session.SessionToken.Body.container:type_name -> neo.fs.v2.session.ContainerSessionContext + 29, // [29:29] is the sub-list for method output_type + 29, // [29:29] is the sub-list for method input_type + 29, // [29:29] is the sub-list for extension type_name + 29, // [29:29] is the sub-list for extension extendee + 0, // [0:29] is the sub-list for field type_name +} + +func init() { file_session_grpc_types_proto_init() } +func file_session_grpc_types_proto_init() { + if File_session_grpc_types_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_session_grpc_types_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ObjectSessionContext); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_session_grpc_types_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ContainerSessionContext); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_session_grpc_types_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SessionToken); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_session_grpc_types_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*XHeader); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_session_grpc_types_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RequestMetaHeader); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_session_grpc_types_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ResponseMetaHeader); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_session_grpc_types_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RequestVerificationHeader); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_session_grpc_types_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ResponseVerificationHeader); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_session_grpc_types_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ObjectSessionContext_Target); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_session_grpc_types_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SessionToken_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_session_grpc_types_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SessionToken_Body_TokenLifetime); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + file_session_grpc_types_proto_msgTypes[9].OneofWrappers = []interface{}{ + (*SessionToken_Body_Object)(nil), + (*SessionToken_Body_Container)(nil), + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_session_grpc_types_proto_rawDesc, + NumEnums: 2, + NumMessages: 11, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_session_grpc_types_proto_goTypes, + DependencyIndexes: file_session_grpc_types_proto_depIdxs, + EnumInfos: file_session_grpc_types_proto_enumTypes, + MessageInfos: file_session_grpc_types_proto_msgTypes, + }.Build() + File_session_grpc_types_proto = out.File + file_session_grpc_types_proto_rawDesc = nil + file_session_grpc_types_proto_goTypes = nil + file_session_grpc_types_proto_depIdxs = nil +} diff --git a/pkg/api/session/json.go b/pkg/api/session/json.go new file mode 100644 index 000000000..e99bbe01a --- /dev/null +++ b/pkg/api/session/json.go @@ -0,0 +1,129 @@ +package session + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/message" + session "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session/grpc" + "google.golang.org/protobuf/encoding/protojson" +) + +func (c *ObjectSessionContext) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(c) +} + +func (c *ObjectSessionContext) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(c, data, new(session.ObjectSessionContext)) +} + +func (l *TokenLifetime) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(l) +} + +func (l *TokenLifetime) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(l, data, new(session.SessionToken_Body_TokenLifetime)) +} + +func (t *TokenBody) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(t) +} + +func (t *TokenBody) UnmarshalJSON(data []byte) error { + msg := new(session.SessionToken_Body) + + if err := protojson.Unmarshal(data, msg); err != nil { + return err + } + + return t.FromGRPCMessage(msg) +} + +func (t *Token) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(t) +} + +func (t *Token) UnmarshalJSON(data []byte) error { + msg := new(session.SessionToken) + + if err := protojson.Unmarshal(data, msg); err != nil { + return err + } + + return t.FromGRPCMessage(msg) +} + +func (x *XHeader) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(x) +} + +func (x *XHeader) UnmarshalJSON(data []byte) error { + msg := new(session.XHeader) + + if err := protojson.Unmarshal(data, msg); err != nil { + return err + } + + return x.FromGRPCMessage(msg) +} + +func (r *RequestMetaHeader) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(r) +} + +func (r *RequestMetaHeader) UnmarshalJSON(data []byte) error { + msg := new(session.RequestMetaHeader) + + if err := protojson.Unmarshal(data, msg); err != nil { + return err + } + + return r.FromGRPCMessage(msg) +} + +func (r *RequestVerificationHeader) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(r) +} + +func (r *RequestVerificationHeader) UnmarshalJSON(data []byte) error { + msg := new(session.RequestVerificationHeader) + + if err := protojson.Unmarshal(data, msg); err != nil { + return err + } + + return r.FromGRPCMessage(msg) +} + +func (r *ResponseMetaHeader) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(r) +} + +func (r *ResponseMetaHeader) UnmarshalJSON(data []byte) error { + msg := new(session.ResponseMetaHeader) + + if err := protojson.Unmarshal(data, msg); err != nil { + return err + } + + return r.FromGRPCMessage(msg) +} + +func (r *ResponseVerificationHeader) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(r) +} + +func (r *ResponseVerificationHeader) UnmarshalJSON(data []byte) error { + msg := new(session.ResponseVerificationHeader) + + if err := protojson.Unmarshal(data, msg); err != nil { + return err + } + + return r.FromGRPCMessage(msg) +} + +func (x *ContainerSessionContext) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(x) +} + +func (x *ContainerSessionContext) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(x, data, new(session.ContainerSessionContext)) +} diff --git a/pkg/api/session/marshal.go b/pkg/api/session/marshal.go new file mode 100644 index 000000000..227ad49c8 --- /dev/null +++ b/pkg/api/session/marshal.go @@ -0,0 +1,582 @@ +package session + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/message" + session "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/util/proto" + goproto "google.golang.org/protobuf/proto" +) + +const ( + createReqBodyOwnerField = 1 + createReqBodyExpirationField = 2 + + createRespBodyIDField = 1 + createRespBodyKeyField = 2 + + xheaderKeyField = 1 + xheaderValueField = 2 + + lifetimeExpirationField = 1 + lifetimeNotValidBeforeField = 2 + lifetimeIssuedAtField = 3 + + objectCtxVerbField = 1 + objectCtxTargetField = 2 + + sessionTokenBodyIDField = 1 + sessionTokenBodyOwnerField = 2 + sessionTokenBodyLifetimeField = 3 + sessionTokenBodyKeyField = 4 + sessionTokenBodyObjectCtxField = 5 + sessionTokenBodyCnrCtxField = 6 + + sessionTokenBodyField = 1 + sessionTokenSignatureField = 2 + + reqMetaHeaderVersionField = 1 + reqMetaHeaderEpochField = 2 + reqMetaHeaderTTLField = 3 + reqMetaHeaderXHeadersField = 4 + reqMetaHeaderSessionTokenField = 5 + reqMetaHeaderBearerTokenField = 6 + reqMetaHeaderOriginField = 7 + reqMetaHeaderNetMagicField = 8 + + reqVerifHeaderBodySignatureField = 1 + reqVerifHeaderMetaSignatureField = 2 + reqVerifHeaderOriginSignatureField = 3 + reqVerifHeaderOriginField = 4 + + respMetaHeaderVersionField = 1 + respMetaHeaderEpochField = 2 + respMetaHeaderTTLField = 3 + respMetaHeaderXHeadersField = 4 + respMetaHeaderOriginField = 5 + respMetaHeaderStatusField = 6 + + respVerifHeaderBodySignatureField = 1 + respVerifHeaderMetaSignatureField = 2 + respVerifHeaderOriginSignatureField = 3 + respVerifHeaderOriginField = 4 +) + +func (c *CreateRequestBody) StableMarshal(buf []byte) []byte { + if c == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, c.StableSize()) + } + + var offset int + + offset += proto.NestedStructureMarshal(createReqBodyOwnerField, buf[offset:], c.ownerID) + proto.UInt64Marshal(createReqBodyExpirationField, buf[offset:], c.expiration) + + return buf +} + +func (c *CreateRequestBody) StableSize() (size int) { + if c == nil { + return 0 + } + + size += proto.NestedStructureSize(createReqBodyOwnerField, c.ownerID) + size += proto.UInt64Size(createReqBodyExpirationField, c.expiration) + + return size +} + +func (c *CreateRequestBody) Unmarshal(data []byte) error { + return message.Unmarshal(c, data, new(session.CreateRequest_Body)) +} + +func (c *CreateResponseBody) StableMarshal(buf []byte) []byte { + if c == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, c.StableSize()) + } + + var offset int + + offset += proto.BytesMarshal(createRespBodyIDField, buf[offset:], c.id) + proto.BytesMarshal(createRespBodyKeyField, buf[offset:], c.sessionKey) + + return buf +} + +func (c *CreateResponseBody) StableSize() (size int) { + if c == nil { + return 0 + } + + size += proto.BytesSize(createRespBodyIDField, c.id) + size += proto.BytesSize(createRespBodyKeyField, c.sessionKey) + + return size +} + +func (c *CreateResponseBody) Unmarshal(data []byte) error { + return message.Unmarshal(c, data, new(session.CreateResponse_Body)) +} + +func (x *XHeader) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, x.StableSize()) + } + + var offset int + + offset += proto.StringMarshal(xheaderKeyField, buf[offset:], x.key) + proto.StringMarshal(xheaderValueField, buf[offset:], x.val) + + return buf +} + +func (x *XHeader) StableSize() (size int) { + if x == nil { + return 0 + } + + size += proto.StringSize(xheaderKeyField, x.key) + size += proto.StringSize(xheaderValueField, x.val) + + return size +} + +func (x *XHeader) Unmarshal(data []byte) error { + m := new(session.XHeader) + if err := goproto.Unmarshal(data, m); err != nil { + return err + } + + return x.FromGRPCMessage(m) +} + +func (l *TokenLifetime) StableMarshal(buf []byte) []byte { + if l == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, l.StableSize()) + } + + var offset int + + offset += proto.UInt64Marshal(lifetimeExpirationField, buf[offset:], l.exp) + offset += proto.UInt64Marshal(lifetimeNotValidBeforeField, buf[offset:], l.nbf) + proto.UInt64Marshal(lifetimeIssuedAtField, buf[offset:], l.iat) + + return buf +} + +func (l *TokenLifetime) StableSize() (size int) { + if l == nil { + return 0 + } + + size += proto.UInt64Size(lifetimeExpirationField, l.exp) + size += proto.UInt64Size(lifetimeNotValidBeforeField, l.nbf) + size += proto.UInt64Size(lifetimeIssuedAtField, l.iat) + + return size +} + +func (l *TokenLifetime) Unmarshal(data []byte) error { + m := new(session.SessionToken_Body_TokenLifetime) + if err := goproto.Unmarshal(data, m); err != nil { + return err + } + + return l.FromGRPCMessage(m) +} + +func (c *ObjectSessionContext) StableMarshal(buf []byte) []byte { + if c == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, c.StableSize()) + } + + offset := proto.EnumMarshal(objectCtxVerbField, buf, int32(c.verb)) + proto.NestedStructureMarshalUnchecked(objectCtxTargetField, buf[offset:], objectSessionContextTarget{ + cnr: c.cnr, + objs: c.objs, + }) + + return buf +} + +func (c *ObjectSessionContext) StableSize() (size int) { + if c == nil { + return 0 + } + + size += proto.EnumSize(objectCtxVerbField, int32(c.verb)) + size += proto.NestedStructureSizeUnchecked(objectCtxTargetField, objectSessionContextTarget{ + cnr: c.cnr, + objs: c.objs, + }) + + return size +} + +func (c *ObjectSessionContext) Unmarshal(data []byte) error { + m := new(session.ObjectSessionContext) + if err := goproto.Unmarshal(data, m); err != nil { + return err + } + + return c.FromGRPCMessage(m) +} + +const ( + _ = iota + cnrCtxVerbFNum + cnrCtxWildcardFNum + cnrCtxCidFNum +) + +func (x *ContainerSessionContext) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, x.StableSize()) + } + + var offset int + + offset += proto.EnumMarshal(cnrCtxVerbFNum, buf[offset:], int32(ContainerSessionVerbToGRPCField(x.verb))) + offset += proto.BoolMarshal(cnrCtxWildcardFNum, buf[offset:], x.wildcard) + proto.NestedStructureMarshal(cnrCtxCidFNum, buf[offset:], x.cid) + + return buf +} + +func (x *ContainerSessionContext) StableSize() (size int) { + if x == nil { + return 0 + } + + size += proto.EnumSize(cnrCtxVerbFNum, int32(ContainerSessionVerbToGRPCField(x.verb))) + size += proto.BoolSize(cnrCtxWildcardFNum, x.wildcard) + size += proto.NestedStructureSize(cnrCtxCidFNum, x.cid) + + return size +} + +func (x *ContainerSessionContext) Unmarshal(data []byte) error { + return message.Unmarshal(x, data, new(session.ContainerSessionContext)) +} + +func (t *TokenBody) StableMarshal(buf []byte) []byte { + if t == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, t.StableSize()) + } + + var offset int + + offset += proto.BytesMarshal(sessionTokenBodyIDField, buf[offset:], t.id) + offset += proto.NestedStructureMarshal(sessionTokenBodyOwnerField, buf[offset:], t.ownerID) + offset += proto.NestedStructureMarshal(sessionTokenBodyLifetimeField, buf[offset:], t.lifetime) + offset += proto.BytesMarshal(sessionTokenBodyKeyField, buf[offset:], t.sessionKey) + + if t.ctx != nil { + switch v := t.ctx.(type) { + case *ObjectSessionContext: + proto.NestedStructureMarshal(sessionTokenBodyObjectCtxField, buf[offset:], v) + case *ContainerSessionContext: + proto.NestedStructureMarshal(sessionTokenBodyCnrCtxField, buf[offset:], v) + default: + panic("cannot marshal unknown session token context") + } + } + + return buf +} + +func (t *TokenBody) StableSize() (size int) { + if t == nil { + return 0 + } + + size += proto.BytesSize(sessionTokenBodyIDField, t.id) + size += proto.NestedStructureSize(sessionTokenBodyOwnerField, t.ownerID) + size += proto.NestedStructureSize(sessionTokenBodyLifetimeField, t.lifetime) + size += proto.BytesSize(sessionTokenBodyKeyField, t.sessionKey) + + if t.ctx != nil { + switch v := t.ctx.(type) { + case *ObjectSessionContext: + size += proto.NestedStructureSize(sessionTokenBodyObjectCtxField, v) + case *ContainerSessionContext: + size += proto.NestedStructureSize(sessionTokenBodyCnrCtxField, v) + default: + panic("cannot marshal unknown session token context") + } + } + + return size +} + +func (t *TokenBody) Unmarshal(data []byte) error { + m := new(session.SessionToken_Body) + if err := goproto.Unmarshal(data, m); err != nil { + return err + } + + return t.FromGRPCMessage(m) +} + +func (t *Token) StableMarshal(buf []byte) []byte { + if t == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, t.StableSize()) + } + + var offset int + + offset += proto.NestedStructureMarshal(sessionTokenBodyField, buf[offset:], t.body) + proto.NestedStructureMarshal(sessionTokenSignatureField, buf[offset:], t.sig) + + return buf +} + +func (t *Token) StableSize() (size int) { + if t == nil { + return 0 + } + + size += proto.NestedStructureSize(sessionTokenBodyField, t.body) + size += proto.NestedStructureSize(sessionTokenSignatureField, t.sig) + + return size +} + +func (t *Token) Unmarshal(data []byte) error { + m := new(session.SessionToken) + if err := goproto.Unmarshal(data, m); err != nil { + return err + } + + return t.FromGRPCMessage(m) +} + +func (r *RequestMetaHeader) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + var offset int + + offset += proto.NestedStructureMarshal(reqMetaHeaderVersionField, buf[offset:], r.version) + offset += proto.UInt64Marshal(reqMetaHeaderEpochField, buf[offset:], r.epoch) + offset += proto.UInt32Marshal(reqMetaHeaderTTLField, buf[offset:], r.ttl) + + for i := range r.xHeaders { + offset += proto.NestedStructureMarshal(reqMetaHeaderXHeadersField, buf[offset:], &r.xHeaders[i]) + } + + offset += proto.NestedStructureMarshal(reqMetaHeaderSessionTokenField, buf[offset:], r.sessionToken) + offset += proto.NestedStructureMarshal(reqMetaHeaderBearerTokenField, buf[offset:], r.bearerToken) + offset += proto.NestedStructureMarshal(reqMetaHeaderOriginField, buf[offset:], r.origin) + proto.UInt64Marshal(reqMetaHeaderNetMagicField, buf[offset:], r.netMagic) + + return buf +} + +func (r *RequestMetaHeader) StableSize() (size int) { + if r == nil { + return 0 + } + + if r.version != nil { + size += proto.NestedStructureSize(reqMetaHeaderVersionField, r.version) + } + + size += proto.UInt64Size(reqMetaHeaderEpochField, r.epoch) + size += proto.UInt32Size(reqMetaHeaderTTLField, r.ttl) + + for i := range r.xHeaders { + size += proto.NestedStructureSize(reqMetaHeaderXHeadersField, &r.xHeaders[i]) + } + + size += proto.NestedStructureSize(reqMetaHeaderSessionTokenField, r.sessionToken) + size += proto.NestedStructureSize(reqMetaHeaderBearerTokenField, r.bearerToken) + size += proto.NestedStructureSize(reqMetaHeaderOriginField, r.origin) + size += proto.UInt64Size(reqMetaHeaderNetMagicField, r.netMagic) + + return size +} + +func (r *RequestMetaHeader) Unmarshal(data []byte) error { + m := new(session.RequestMetaHeader) + if err := goproto.Unmarshal(data, m); err != nil { + return err + } + + return r.FromGRPCMessage(m) +} + +func (r *RequestVerificationHeader) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + var offset int + + offset += proto.NestedStructureMarshal(reqVerifHeaderBodySignatureField, buf[offset:], r.bodySig) + offset += proto.NestedStructureMarshal(reqVerifHeaderMetaSignatureField, buf[offset:], r.metaSig) + offset += proto.NestedStructureMarshal(reqVerifHeaderOriginSignatureField, buf[offset:], r.originSig) + proto.NestedStructureMarshal(reqVerifHeaderOriginField, buf[offset:], r.origin) + + return buf +} + +func (r *RequestVerificationHeader) StableSize() (size int) { + if r == nil { + return 0 + } + + size += proto.NestedStructureSize(reqVerifHeaderBodySignatureField, r.bodySig) + size += proto.NestedStructureSize(reqVerifHeaderMetaSignatureField, r.metaSig) + size += proto.NestedStructureSize(reqVerifHeaderOriginSignatureField, r.originSig) + size += proto.NestedStructureSize(reqVerifHeaderOriginField, r.origin) + + return size +} + +func (r *RequestVerificationHeader) Unmarshal(data []byte) error { + m := new(session.RequestVerificationHeader) + if err := goproto.Unmarshal(data, m); err != nil { + return err + } + + return r.FromGRPCMessage(m) +} + +func (r *ResponseMetaHeader) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + var offset int + + offset += proto.NestedStructureMarshal(respMetaHeaderVersionField, buf[offset:], r.version) + offset += proto.UInt64Marshal(respMetaHeaderEpochField, buf[offset:], r.epoch) + offset += proto.UInt32Marshal(respMetaHeaderTTLField, buf[offset:], r.ttl) + + for i := range r.xHeaders { + offset += proto.NestedStructureMarshal(respMetaHeaderXHeadersField, buf[offset:], &r.xHeaders[i]) + } + + offset += proto.NestedStructureMarshal(respMetaHeaderOriginField, buf[offset:], r.origin) + proto.NestedStructureMarshal(respMetaHeaderStatusField, buf[offset:], r.status) + + return buf +} + +func (r *ResponseMetaHeader) StableSize() (size int) { + if r == nil { + return 0 + } + + if r.version != nil { + size += proto.NestedStructureSize(respMetaHeaderVersionField, r.version) + } + + size += proto.UInt64Size(respMetaHeaderEpochField, r.epoch) + size += proto.UInt32Size(respMetaHeaderTTLField, r.ttl) + + for i := range r.xHeaders { + size += proto.NestedStructureSize(respMetaHeaderXHeadersField, &r.xHeaders[i]) + } + + size += proto.NestedStructureSize(respMetaHeaderOriginField, r.origin) + size += proto.NestedStructureSize(respMetaHeaderStatusField, r.status) + + return size +} + +func (r *ResponseMetaHeader) Unmarshal(data []byte) error { + m := new(session.ResponseMetaHeader) + if err := goproto.Unmarshal(data, m); err != nil { + return err + } + + return r.FromGRPCMessage(m) +} + +func (r *ResponseVerificationHeader) StableMarshal(buf []byte) []byte { + if r == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + var offset int + + offset += proto.NestedStructureMarshal(respVerifHeaderBodySignatureField, buf[offset:], r.bodySig) + offset += proto.NestedStructureMarshal(respVerifHeaderMetaSignatureField, buf[offset:], r.metaSig) + offset += proto.NestedStructureMarshal(respVerifHeaderOriginSignatureField, buf[offset:], r.originSig) + proto.NestedStructureMarshal(respVerifHeaderOriginField, buf[offset:], r.origin) + + return buf +} + +func (r *ResponseVerificationHeader) StableSize() (size int) { + if r == nil { + return 0 + } + + size += proto.NestedStructureSize(respVerifHeaderBodySignatureField, r.bodySig) + size += proto.NestedStructureSize(respVerifHeaderMetaSignatureField, r.metaSig) + size += proto.NestedStructureSize(respVerifHeaderOriginSignatureField, r.originSig) + size += proto.NestedStructureSize(respVerifHeaderOriginField, r.origin) + + return size +} + +func (r *ResponseVerificationHeader) Unmarshal(data []byte) error { + m := new(session.ResponseVerificationHeader) + if err := goproto.Unmarshal(data, m); err != nil { + return err + } + + return r.FromGRPCMessage(m) +} diff --git a/pkg/api/session/message_test.go b/pkg/api/session/message_test.go new file mode 100644 index 000000000..1d07c6797 --- /dev/null +++ b/pkg/api/session/message_test.go @@ -0,0 +1,27 @@ +package session_test + +import ( + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/message" + rpctest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/message/test" + sessiontest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session/test" +) + +func TestMessageConvert(t *testing.T) { + rpctest.TestRPCMessage(t, + func(empty bool) message.Message { return sessiontest.GenerateCreateRequestBody(empty) }, + func(empty bool) message.Message { return sessiontest.GenerateCreateRequest(empty) }, + func(empty bool) message.Message { return sessiontest.GenerateCreateResponseBody(empty) }, + func(empty bool) message.Message { return sessiontest.GenerateCreateResponse(empty) }, + func(empty bool) message.Message { return sessiontest.GenerateTokenLifetime(empty) }, + func(empty bool) message.Message { return sessiontest.GenerateXHeader(empty) }, + func(empty bool) message.Message { return sessiontest.GenerateSessionTokenBody(empty) }, + func(empty bool) message.Message { return sessiontest.GenerateSessionToken(empty) }, + func(empty bool) message.Message { return sessiontest.GenerateRequestMetaHeader(empty) }, + func(empty bool) message.Message { return sessiontest.GenerateRequestVerificationHeader(empty) }, + func(empty bool) message.Message { return sessiontest.GenerateResponseMetaHeader(empty) }, + func(empty bool) message.Message { return sessiontest.GenerateResponseVerificationHeader(empty) }, + func(empty bool) message.Message { return sessiontest.GenerateContainerSessionContext(empty) }, + ) +} diff --git a/pkg/api/session/status.go b/pkg/api/session/status.go new file mode 100644 index 000000000..123a2b67f --- /dev/null +++ b/pkg/api/session/status.go @@ -0,0 +1,32 @@ +package session + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/status" + statusgrpc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/status/grpc" +) + +// LocalizeFailStatus checks if passed global status.Code is related to session failure and: +// +// then localizes the code and returns true, +// else leaves the code unchanged and returns false. +// +// Arg must not be nil. +func LocalizeFailStatus(c *status.Code) bool { + return status.LocalizeIfInSection(c, uint32(statusgrpc.Section_SECTION_SESSION)) +} + +// GlobalizeFail globalizes local code of session failure. +// +// Arg must not be nil. +func GlobalizeFail(c *status.Code) { + c.GlobalizeSection(uint32(statusgrpc.Section_SECTION_SESSION)) +} + +const ( + // StatusTokenNotFound is a local status.Code value for + // TOKEN_NOT_FOUND session failure. + StatusTokenNotFound status.Code = iota + // StatusTokenExpired is a local status.Code value for + // TOKEN_EXPIRED session failure. + StatusTokenExpired +) diff --git a/pkg/api/session/status_test.go b/pkg/api/session/status_test.go new file mode 100644 index 000000000..bd9d65ac4 --- /dev/null +++ b/pkg/api/session/status_test.go @@ -0,0 +1,15 @@ +package session_test + +import ( + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" + statustest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/status/test" +) + +func TestStatusCodes(t *testing.T) { + statustest.TestCodes(t, session.LocalizeFailStatus, session.GlobalizeFail, + session.StatusTokenNotFound, 4096, + session.StatusTokenExpired, 4097, + ) +} diff --git a/pkg/api/session/string.go b/pkg/api/session/string.go new file mode 100644 index 000000000..1d452baea --- /dev/null +++ b/pkg/api/session/string.go @@ -0,0 +1,47 @@ +package session + +import ( + session "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session/grpc" +) + +// String returns string representation of ObjectSessionVerb. +func (x ObjectSessionVerb) String() string { + return ObjectSessionVerbToGRPCField(x).String() +} + +// FromString parses ObjectSessionVerb from a string representation. +// It is a reverse action to String(). +// +// Returns true if s was parsed successfully. +func (x *ObjectSessionVerb) FromString(s string) bool { + var g session.ObjectSessionContext_Verb + + ok := g.FromString(s) + + if ok { + *x = ObjectSessionVerbFromGRPCField(g) + } + + return ok +} + +// String returns string representation of ContainerSessionVerb. +func (x ContainerSessionVerb) String() string { + return ContainerSessionVerbToGRPCField(x).String() +} + +// FromString parses ContainerSessionVerb from a string representation. +// It is a reverse action to String(). +// +// Returns true if s was parsed successfully. +func (x *ContainerSessionVerb) FromString(s string) bool { + var g session.ContainerSessionContext_Verb + + ok := g.FromString(s) + + if ok { + *x = ContainerSessionVerbFromGRPCField(g) + } + + return ok +} diff --git a/pkg/api/session/test/generate.go b/pkg/api/session/test/generate.go new file mode 100644 index 000000000..db8b88361 --- /dev/null +++ b/pkg/api/session/test/generate.go @@ -0,0 +1,244 @@ +package sessiontest + +import ( + "math/rand" + "time" + + acltest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/acl/test" + refstest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs/test" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" + statustest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/status/test" +) + +func GenerateCreateRequestBody(empty bool) *session.CreateRequestBody { + m := new(session.CreateRequestBody) + + if !empty { + m.SetExpiration(555) + m.SetOwnerID(refstest.GenerateOwnerID(false)) + } + + return m +} + +func GenerateCreateRequest(empty bool) *session.CreateRequest { + m := new(session.CreateRequest) + + if !empty { + m.SetBody(GenerateCreateRequestBody(false)) + } + + m.SetMetaHeader(GenerateRequestMetaHeader(empty)) + m.SetVerificationHeader(GenerateRequestVerificationHeader(empty)) + + return m +} + +func GenerateCreateResponseBody(empty bool) *session.CreateResponseBody { + m := new(session.CreateResponseBody) + + if !empty { + m.SetID([]byte{1, 2, 3}) + m.SetSessionKey([]byte{4, 5, 6}) + } + + return m +} + +func GenerateCreateResponse(empty bool) *session.CreateResponse { + m := new(session.CreateResponse) + + if !empty { + m.SetBody(GenerateCreateResponseBody(false)) + } + + m.SetMetaHeader(GenerateResponseMetaHeader(empty)) + m.SetVerificationHeader(GenerateResponseVerificationHeader(empty)) + + return m +} + +func GenerateResponseVerificationHeader(empty bool) *session.ResponseVerificationHeader { + return generateResponseVerificationHeader(empty, true) +} + +func generateResponseVerificationHeader(empty, withOrigin bool) *session.ResponseVerificationHeader { + m := new(session.ResponseVerificationHeader) + + if !empty { + m.SetBodySignature(refstest.GenerateSignature(false)) + } + + m.SetMetaSignature(refstest.GenerateSignature(empty)) + m.SetOriginSignature(refstest.GenerateSignature(empty)) + + if withOrigin { + m.SetOrigin(generateResponseVerificationHeader(empty, false)) + } + + return m +} + +func GenerateResponseMetaHeader(empty bool) *session.ResponseMetaHeader { + return generateResponseMetaHeader(empty, true) +} + +func generateResponseMetaHeader(empty, withOrigin bool) *session.ResponseMetaHeader { + m := new(session.ResponseMetaHeader) + + if !empty { + m.SetEpoch(13) + m.SetTTL(100) + } + + m.SetXHeaders(GenerateXHeaders(empty)) + m.SetVersion(refstest.GenerateVersion(empty)) + m.SetStatus(statustest.Status(empty)) + + if withOrigin { + m.SetOrigin(generateResponseMetaHeader(empty, false)) + } + + return m +} + +func GenerateRequestVerificationHeader(empty bool) *session.RequestVerificationHeader { + return generateRequestVerificationHeader(empty, true) +} + +func generateRequestVerificationHeader(empty, withOrigin bool) *session.RequestVerificationHeader { + m := new(session.RequestVerificationHeader) + + if !empty { + m.SetBodySignature(refstest.GenerateSignature(false)) + } + + m.SetMetaSignature(refstest.GenerateSignature(empty)) + m.SetOriginSignature(refstest.GenerateSignature(empty)) + + if withOrigin { + m.SetOrigin(generateRequestVerificationHeader(empty, false)) + } + + return m +} + +func GenerateRequestMetaHeader(empty bool) *session.RequestMetaHeader { + return generateRequestMetaHeader(empty, true) +} + +func generateRequestMetaHeader(empty, withOrigin bool) *session.RequestMetaHeader { + m := new(session.RequestMetaHeader) + + if !empty { + m.SetEpoch(13) + m.SetTTL(100) + m.SetNetworkMagic(1337) + } + + m.SetXHeaders(GenerateXHeaders(empty)) + m.SetVersion(refstest.GenerateVersion(empty)) + m.SetSessionToken(GenerateSessionToken(empty)) + m.SetBearerToken(acltest.GenerateBearerToken(empty)) + + if withOrigin { + m.SetOrigin(generateRequestMetaHeader(empty, false)) + } + + return m +} + +func GenerateSessionToken(empty bool) *session.Token { + m := new(session.Token) + + if !empty { + m.SetBody(GenerateSessionTokenBody(false)) + } + + m.SetSignature(refstest.GenerateSignature(empty)) + + return m +} + +func GenerateSessionTokenBody(empty bool) *session.TokenBody { + m := new(session.TokenBody) + + if !empty { + m.SetID([]byte{1}) + m.SetSessionKey([]byte{2}) + m.SetOwnerID(refstest.GenerateOwnerID(false)) + m.SetLifetime(GenerateTokenLifetime(false)) + + switch randomInt(2) { + case 0: + m.SetContext(GenerateObjectSessionContext(false)) + case 1: + m.SetContext(GenerateContainerSessionContext(false)) + } + } + + return m +} + +func GenerateTokenLifetime(empty bool) *session.TokenLifetime { + m := new(session.TokenLifetime) + + if !empty { + m.SetExp(1) + m.SetIat(2) + m.SetExp(3) + } + + return m +} + +func GenerateObjectSessionContext(empty bool) *session.ObjectSessionContext { + m := new(session.ObjectSessionContext) + + if !empty { + m.SetVerb(session.ObjectVerbHead) + m.SetTarget(refstest.GenerateContainerID(false), refstest.GenerateObjectIDs(false)...) + } + + return m +} + +func GenerateContainerSessionContext(empty bool) *session.ContainerSessionContext { + m := new(session.ContainerSessionContext) + + if !empty { + m.SetVerb(session.ContainerVerbDelete) + m.SetWildcard(true) + m.SetContainerID(refstest.GenerateContainerID(false)) + } + + return m +} + +func GenerateXHeader(empty bool) *session.XHeader { + m := new(session.XHeader) + + if !empty { + m.SetKey("key") + m.SetValue("val") + } + + return m +} + +func GenerateXHeaders(empty bool) []session.XHeader { + var xs []session.XHeader + + if !empty { + xs = append(xs, + *GenerateXHeader(false), + *GenerateXHeader(false), + ) + } + + return xs +} + +func randomInt(n int) int { + return rand.New(rand.NewSource(time.Now().UnixNano())).Intn(n) +} diff --git a/pkg/api/session/types.go b/pkg/api/session/types.go new file mode 100644 index 000000000..e640b6af5 --- /dev/null +++ b/pkg/api/session/types.go @@ -0,0 +1,835 @@ +package session + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/acl" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/status" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/util/proto" +) + +type CreateRequestBody struct { + ownerID *refs.OwnerID + + expiration uint64 +} + +type CreateRequest struct { + body *CreateRequestBody + + RequestHeaders +} + +type CreateResponseBody struct { + id []byte + + sessionKey []byte +} + +type CreateResponse struct { + body *CreateResponseBody + + ResponseHeaders +} + +type XHeader struct { + key, val string +} + +type TokenLifetime struct { + exp, nbf, iat uint64 +} + +type ObjectSessionVerb uint32 + +type objectSessionContextTarget struct { + cnr *refs.ContainerID + + objs []refs.ObjectID +} + +const ( + _ = iota + fNumObjectTargetContainer + fNumObjectTargetObjects +) + +func (x objectSessionContextTarget) StableMarshal(buf []byte) []byte { + if buf == nil { + buf = make([]byte, x.StableSize()) + } + + offset := proto.NestedStructureMarshal(fNumObjectTargetContainer, buf, x.cnr) + + for i := range x.objs { + offset += proto.NestedStructureMarshal(fNumObjectTargetObjects, buf[offset:], &x.objs[i]) + } + + return buf +} + +func (x objectSessionContextTarget) StableSize() (size int) { + size += proto.NestedStructureSize(fNumObjectTargetContainer, x.cnr) + + for i := range x.objs { + size += proto.NestedStructureSize(fNumObjectTargetObjects, &x.objs[i]) + } + + return size +} + +type ObjectSessionContext struct { + verb ObjectSessionVerb + + cnr *refs.ContainerID + + objs []refs.ObjectID +} + +type TokenContext interface { + sessionTokenContext() +} + +// Deprecated: use TokenContext instead. +// +//nolint:revive +type SessionTokenContext = TokenContext + +type TokenBody struct { + id []byte + + ownerID *refs.OwnerID + + lifetime *TokenLifetime + + sessionKey []byte + + ctx TokenContext +} + +// Deprecated: use TokenBody instead. +// +//nolint:revive +type SessionTokenBody = TokenBody + +type Token struct { + body *TokenBody + + sig *refs.Signature +} + +// Deprecated: use Token instead. +// +//nolint:revive +type SessionToken = Token + +type RequestVerificationHeader struct { + bodySig, metaSig, originSig *refs.Signature + + origin *RequestVerificationHeader +} + +type RequestMetaHeader struct { + version *refs.Version + + ttl uint32 + + epoch uint64 + + xHeaders []XHeader + + sessionToken *Token + + bearerToken *acl.BearerToken + + origin *RequestMetaHeader + + netMagic uint64 +} + +type ResponseVerificationHeader struct { + bodySig, metaSig, originSig *refs.Signature + + origin *ResponseVerificationHeader +} + +type ResponseMetaHeader struct { + version *refs.Version + + ttl uint32 + + epoch uint64 + + xHeaders []XHeader + + origin *ResponseMetaHeader + + status *status.Status +} + +const ( + ObjectVerbUnknown ObjectSessionVerb = iota + ObjectVerbPut + ObjectVerbGet + ObjectVerbHead + ObjectVerbSearch + ObjectVerbDelete + ObjectVerbRange + ObjectVerbRangeHash +) + +func (c *CreateRequestBody) GetOwnerID() *refs.OwnerID { + if c != nil { + return c.ownerID + } + + return nil +} + +func (c *CreateRequestBody) SetOwnerID(v *refs.OwnerID) { + c.ownerID = v +} + +func (c *CreateRequestBody) GetExpiration() uint64 { + if c != nil { + return c.expiration + } + + return 0 +} + +func (c *CreateRequestBody) SetExpiration(v uint64) { + c.expiration = v +} + +func (c *CreateRequest) GetBody() *CreateRequestBody { + if c != nil { + return c.body + } + + return nil +} + +func (c *CreateRequest) SetBody(v *CreateRequestBody) { + c.body = v +} + +func (c *CreateRequest) GetMetaHeader() *RequestMetaHeader { + if c != nil { + return c.metaHeader + } + + return nil +} + +func (c *CreateRequest) SetMetaHeader(v *RequestMetaHeader) { + c.metaHeader = v +} + +func (c *CreateRequest) GetVerificationHeader() *RequestVerificationHeader { + if c != nil { + return c.verifyHeader + } + + return nil +} + +func (c *CreateRequest) SetVerificationHeader(v *RequestVerificationHeader) { + c.verifyHeader = v +} + +func (c *CreateResponseBody) GetID() []byte { + if c != nil { + return c.id + } + + return nil +} + +func (c *CreateResponseBody) SetID(v []byte) { + c.id = v +} + +func (c *CreateResponseBody) GetSessionKey() []byte { + if c != nil { + return c.sessionKey + } + + return nil +} + +func (c *CreateResponseBody) SetSessionKey(v []byte) { + c.sessionKey = v +} + +func (c *CreateResponse) GetBody() *CreateResponseBody { + if c != nil { + return c.body + } + + return nil +} + +func (c *CreateResponse) SetBody(v *CreateResponseBody) { + c.body = v +} + +func (c *CreateResponse) GetMetaHeader() *ResponseMetaHeader { + if c != nil { + return c.metaHeader + } + + return nil +} + +func (c *CreateResponse) SetMetaHeader(v *ResponseMetaHeader) { + c.metaHeader = v +} + +func (c *CreateResponse) GetVerificationHeader() *ResponseVerificationHeader { + if c != nil { + return c.verifyHeader + } + + return nil +} + +func (c *CreateResponse) SetVerificationHeader(v *ResponseVerificationHeader) { + c.verifyHeader = v +} + +func (x *XHeader) GetKey() string { + if x != nil { + return x.key + } + + return "" +} + +func (x *XHeader) SetKey(v string) { + x.key = v +} + +func (x *XHeader) GetValue() string { + if x != nil { + return x.val + } + + return "" +} + +func (x *XHeader) SetValue(v string) { + x.val = v +} + +func (r *RequestVerificationHeader) GetBodySignature() *refs.Signature { + if r != nil { + return r.bodySig + } + + return nil +} + +func (r *RequestVerificationHeader) SetBodySignature(v *refs.Signature) { + r.bodySig = v +} + +func (r *RequestVerificationHeader) GetMetaSignature() *refs.Signature { + if r != nil { + return r.metaSig + } + + return nil +} + +func (r *RequestVerificationHeader) SetMetaSignature(v *refs.Signature) { + r.metaSig = v +} + +func (r *RequestVerificationHeader) GetOriginSignature() *refs.Signature { + if r != nil { + return r.originSig + } + + return nil +} + +func (r *RequestVerificationHeader) SetOriginSignature(v *refs.Signature) { + r.originSig = v +} + +func (r *RequestVerificationHeader) GetOrigin() *RequestVerificationHeader { + if r != nil { + return r.origin + } + + return nil +} + +func (r *RequestVerificationHeader) SetOrigin(v *RequestVerificationHeader) { + r.origin = v +} + +func (r *RequestMetaHeader) GetVersion() *refs.Version { + if r != nil { + return r.version + } + + return nil +} + +func (r *RequestMetaHeader) SetVersion(v *refs.Version) { + r.version = v +} + +func (r *RequestMetaHeader) GetTTL() uint32 { + if r != nil { + return r.ttl + } + + return 0 +} + +func (r *RequestMetaHeader) SetTTL(v uint32) { + r.ttl = v +} + +func (r *RequestMetaHeader) GetEpoch() uint64 { + if r != nil { + return r.epoch + } + + return 0 +} + +func (r *RequestMetaHeader) SetEpoch(v uint64) { + r.epoch = v +} + +func (r *RequestMetaHeader) GetXHeaders() []XHeader { + if r != nil { + return r.xHeaders + } + + return nil +} + +func (r *RequestMetaHeader) SetXHeaders(v []XHeader) { + r.xHeaders = v +} + +func (r *RequestMetaHeader) GetSessionToken() *Token { + if r != nil { + return r.sessionToken + } + + return nil +} + +func (r *RequestMetaHeader) SetSessionToken(v *Token) { + r.sessionToken = v +} + +func (r *RequestMetaHeader) GetBearerToken() *acl.BearerToken { + if r != nil { + return r.bearerToken + } + + return nil +} + +func (r *RequestMetaHeader) SetBearerToken(v *acl.BearerToken) { + r.bearerToken = v +} + +func (r *RequestMetaHeader) GetOrigin() *RequestMetaHeader { + if r != nil { + return r.origin + } + + return nil +} + +func (r *RequestMetaHeader) SetOrigin(v *RequestMetaHeader) { + r.origin = v +} + +// GetNetworkMagic returns NeoFS network magic. +func (r *RequestMetaHeader) GetNetworkMagic() uint64 { + if r != nil { + return r.netMagic + } + + return 0 +} + +// SetNetworkMagic sets NeoFS network magic. +func (r *RequestMetaHeader) SetNetworkMagic(v uint64) { + r.netMagic = v +} + +func (l *TokenLifetime) GetExp() uint64 { + if l != nil { + return l.exp + } + + return 0 +} + +func (l *TokenLifetime) SetExp(v uint64) { + l.exp = v +} + +func (l *TokenLifetime) GetNbf() uint64 { + if l != nil { + return l.nbf + } + + return 0 +} + +func (l *TokenLifetime) SetNbf(v uint64) { + l.nbf = v +} + +func (l *TokenLifetime) GetIat() uint64 { + if l != nil { + return l.iat + } + + return 0 +} + +func (l *TokenLifetime) SetIat(v uint64) { + l.iat = v +} + +func (r *ResponseVerificationHeader) GetBodySignature() *refs.Signature { + if r != nil { + return r.bodySig + } + + return nil +} + +func (r *ResponseVerificationHeader) SetBodySignature(v *refs.Signature) { + r.bodySig = v +} + +func (r *ResponseVerificationHeader) GetMetaSignature() *refs.Signature { + if r != nil { + return r.metaSig + } + + return nil +} + +func (r *ResponseVerificationHeader) SetMetaSignature(v *refs.Signature) { + r.metaSig = v +} + +func (r *ResponseVerificationHeader) GetOriginSignature() *refs.Signature { + if r != nil { + return r.originSig + } + + return nil +} + +func (r *ResponseVerificationHeader) SetOriginSignature(v *refs.Signature) { + r.originSig = v +} + +func (r *ResponseVerificationHeader) GetOrigin() *ResponseVerificationHeader { + if r != nil { + return r.origin + } + + return nil +} + +func (r *ResponseVerificationHeader) SetOrigin(v *ResponseVerificationHeader) { + r.origin = v +} + +func (r *ResponseMetaHeader) GetVersion() *refs.Version { + if r != nil { + return r.version + } + + return nil +} + +func (r *ResponseMetaHeader) SetVersion(v *refs.Version) { + r.version = v +} + +func (r *ResponseMetaHeader) GetTTL() uint32 { + if r != nil { + return r.ttl + } + + return 0 +} + +func (r *ResponseMetaHeader) SetTTL(v uint32) { + r.ttl = v +} + +func (r *ResponseMetaHeader) GetEpoch() uint64 { + if r != nil { + return r.epoch + } + + return 0 +} + +func (r *ResponseMetaHeader) SetEpoch(v uint64) { + r.epoch = v +} + +func (r *ResponseMetaHeader) GetXHeaders() []XHeader { + if r != nil { + return r.xHeaders + } + + return nil +} + +func (r *ResponseMetaHeader) SetXHeaders(v []XHeader) { + r.xHeaders = v +} + +func (r *ResponseMetaHeader) GetOrigin() *ResponseMetaHeader { + if r != nil { + return r.origin + } + + return nil +} + +func (r *ResponseMetaHeader) SetOrigin(v *ResponseMetaHeader) { + r.origin = v +} + +// GetStatus returns response status. +func (r *ResponseMetaHeader) GetStatus() *status.Status { + if r != nil { + return r.status + } + + return nil +} + +// SetStatus sets response status. +func (r *ResponseMetaHeader) SetStatus(v *status.Status) { + r.status = v +} + +// SetStatus sets status of the message which can carry ResponseMetaHeader. +// +// Sets status field on the "highest" level of meta headers. +// If meta header is missing in message, it is allocated. +func SetStatus(msg interface { + GetMetaHeader() *ResponseMetaHeader + SetMetaHeader(*ResponseMetaHeader) +}, st *status.Status, +) { + meta := msg.GetMetaHeader() + if meta == nil { + meta = new(ResponseMetaHeader) + msg.SetMetaHeader(meta) + } + + meta.SetStatus(st) +} + +func (c *ObjectSessionContext) sessionTokenContext() {} + +func (c *ObjectSessionContext) GetVerb() ObjectSessionVerb { + if c != nil { + return c.verb + } + + return ObjectVerbUnknown +} + +func (c *ObjectSessionContext) SetVerb(v ObjectSessionVerb) { + c.verb = v +} + +func (c *ObjectSessionContext) GetContainer() *refs.ContainerID { + if c != nil { + return c.cnr + } + + return nil +} + +func (c *ObjectSessionContext) GetObjects() []refs.ObjectID { + if c != nil { + return c.objs + } + + return nil +} + +func (c *ObjectSessionContext) SetTarget(cnr *refs.ContainerID, objs ...refs.ObjectID) { + c.cnr = cnr + c.objs = objs +} + +func (t *TokenBody) GetID() []byte { + if t != nil { + return t.id + } + + return nil +} + +func (t *TokenBody) SetID(v []byte) { + t.id = v +} + +func (t *TokenBody) GetOwnerID() *refs.OwnerID { + if t != nil { + return t.ownerID + } + + return nil +} + +func (t *TokenBody) SetOwnerID(v *refs.OwnerID) { + t.ownerID = v +} + +func (t *TokenBody) GetLifetime() *TokenLifetime { + if t != nil { + return t.lifetime + } + + return nil +} + +func (t *TokenBody) SetLifetime(v *TokenLifetime) { + t.lifetime = v +} + +func (t *TokenBody) GetSessionKey() []byte { + if t != nil { + return t.sessionKey + } + + return nil +} + +func (t *TokenBody) SetSessionKey(v []byte) { + t.sessionKey = v +} + +func (t *TokenBody) GetContext() TokenContext { + if t != nil { + return t.ctx + } + + return nil +} + +func (t *TokenBody) SetContext(v TokenContext) { + t.ctx = v +} + +func (t *Token) GetBody() *TokenBody { + if t != nil { + return t.body + } + + return nil +} + +func (t *Token) SetBody(v *TokenBody) { + t.body = v +} + +func (t *Token) GetSignature() *refs.Signature { + if t != nil { + return t.sig + } + + return nil +} + +func (t *Token) SetSignature(v *refs.Signature) { + t.sig = v +} + +// ContainerSessionVerb represents NeoFS API v2 +// session.ContainerSessionContext.Verb enumeration. +type ContainerSessionVerb uint32 + +const ( + // ContainerVerbUnknown corresponds to VERB_UNSPECIFIED enum value. + ContainerVerbUnknown ContainerSessionVerb = iota + + // ContainerVerbPut corresponds to PUT enum value. + ContainerVerbPut + + // ContainerVerbDelete corresponds to DELETE enum value. + ContainerVerbDelete + + // ContainerVerbSetEACL corresponds to SETEACL enum value. + ContainerVerbSetEACL +) + +// ContainerSessionContext represents structure of the +// NeoFS API v2 session.ContainerSessionContext message. +type ContainerSessionContext struct { + verb ContainerSessionVerb + + wildcard bool + + cid *refs.ContainerID +} + +func (x *ContainerSessionContext) sessionTokenContext() {} + +// Verb returns type of request for which the token is issued. +func (x *ContainerSessionContext) Verb() ContainerSessionVerb { + if x != nil { + return x.verb + } + + return ContainerVerbUnknown +} + +// SetVerb sets type of request for which the token is issued. +func (x *ContainerSessionContext) SetVerb(v ContainerSessionVerb) { + x.verb = v +} + +// Wildcard returns wildcard flag of the container session. +func (x *ContainerSessionContext) Wildcard() bool { + if x != nil { + return x.wildcard + } + + return false +} + +// SetWildcard sets wildcard flag of the container session. +func (x *ContainerSessionContext) SetWildcard(v bool) { + x.wildcard = v +} + +// ContainerID returns identifier of the container related to the session. +func (x *ContainerSessionContext) ContainerID() *refs.ContainerID { + if x != nil { + return x.cid + } + + return nil +} + +// SetContainerID sets identifier of the container related to the session. +func (x *ContainerSessionContext) SetContainerID(v *refs.ContainerID) { + x.cid = v +} diff --git a/pkg/api/session/util.go b/pkg/api/session/util.go new file mode 100644 index 000000000..9d6683bf7 --- /dev/null +++ b/pkg/api/session/util.go @@ -0,0 +1,167 @@ +package session + +import ( + session "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session/grpc" +) + +// RequestHeaders represents common part of +// all NeoFS requests including headers. +type RequestHeaders struct { + metaHeader *RequestMetaHeader + + verifyHeader *RequestVerificationHeader +} + +// GetMetaHeader returns meta header of the request. +func (c *RequestHeaders) GetMetaHeader() *RequestMetaHeader { + if c != nil { + return c.metaHeader + } + + return nil +} + +// SetMetaHeader sets meta header of the request. +func (c *RequestHeaders) SetMetaHeader(v *RequestMetaHeader) { + c.metaHeader = v +} + +// GetVerificationHeader returns verification header of the request. +func (c *RequestHeaders) GetVerificationHeader() *RequestVerificationHeader { + if c != nil { + return c.verifyHeader + } + + return nil +} + +// SetVerificationHeader sets verification header of the request. +func (c *RequestHeaders) SetVerificationHeader(v *RequestVerificationHeader) { + c.verifyHeader = v +} + +func (c *RequestHeaders) ToMessage(m interface { + SetMetaHeader(*session.RequestMetaHeader) + SetVerifyHeader(*session.RequestVerificationHeader) +}, +) { + m.SetMetaHeader(c.metaHeader.ToGRPCMessage().(*session.RequestMetaHeader)) + m.SetVerifyHeader(c.verifyHeader.ToGRPCMessage().(*session.RequestVerificationHeader)) +} + +func (c *RequestHeaders) FromMessage(m interface { + GetMetaHeader() *session.RequestMetaHeader + GetVerifyHeader() *session.RequestVerificationHeader +}, +) error { + metaHdr := m.GetMetaHeader() + if metaHdr == nil { + c.metaHeader = nil + } else { + if c.metaHeader == nil { + c.metaHeader = new(RequestMetaHeader) + } + + err := c.metaHeader.FromGRPCMessage(metaHdr) + if err != nil { + return err + } + } + + verifyHdr := m.GetVerifyHeader() + if verifyHdr == nil { + c.verifyHeader = nil + } else { + if c.verifyHeader == nil { + c.verifyHeader = new(RequestVerificationHeader) + } + + err := c.verifyHeader.FromGRPCMessage(verifyHdr) + if err != nil { + return err + } + } + + return nil +} + +// ResponseHeaders represents common part of +// all NeoFS responses including headers. +type ResponseHeaders struct { + metaHeader *ResponseMetaHeader + + verifyHeader *ResponseVerificationHeader +} + +// GetMetaHeader returns meta header of the response. +func (c *ResponseHeaders) GetMetaHeader() *ResponseMetaHeader { + if c != nil { + return c.metaHeader + } + + return nil +} + +// SetMetaHeader sets meta header of the response. +func (c *ResponseHeaders) SetMetaHeader(v *ResponseMetaHeader) { + c.metaHeader = v +} + +// GetVerificationHeader returns verification header of the response. +func (c *ResponseHeaders) GetVerificationHeader() *ResponseVerificationHeader { + if c != nil { + return c.verifyHeader + } + + return nil +} + +// SetVerificationHeader sets verification header of the response. +func (c *ResponseHeaders) SetVerificationHeader(v *ResponseVerificationHeader) { + c.verifyHeader = v +} + +func (c *ResponseHeaders) ToMessage(m interface { + SetMetaHeader(*session.ResponseMetaHeader) + SetVerifyHeader(*session.ResponseVerificationHeader) +}, +) { + m.SetMetaHeader(c.metaHeader.ToGRPCMessage().(*session.ResponseMetaHeader)) + m.SetVerifyHeader(c.verifyHeader.ToGRPCMessage().(*session.ResponseVerificationHeader)) +} + +func (c *ResponseHeaders) FromMessage(m interface { + GetMetaHeader() *session.ResponseMetaHeader + GetVerifyHeader() *session.ResponseVerificationHeader +}, +) error { + metaHdr := m.GetMetaHeader() + if metaHdr == nil { + c.metaHeader = nil + } else { + if c.metaHeader == nil { + c.metaHeader = new(ResponseMetaHeader) + } + + err := c.metaHeader.FromGRPCMessage(metaHdr) + if err != nil { + return err + } + } + + verifyHdr := m.GetVerifyHeader() + if verifyHdr == nil { + c.verifyHeader = nil + } else { + if c.verifyHeader == nil { + c.verifyHeader = new(ResponseVerificationHeader) + } + + err := c.verifyHeader.FromGRPCMessage(verifyHdr) + if err != nil { + return err + } + } + + return nil +} diff --git a/pkg/api/session/xheaders.go b/pkg/api/session/xheaders.go new file mode 100644 index 000000000..c575d5f72 --- /dev/null +++ b/pkg/api/session/xheaders.go @@ -0,0 +1,34 @@ +package session + +// ReservedXHeaderPrefix is a prefix of keys to "well-known" X-headers. +const ReservedXHeaderPrefix = "__SYSTEM__" + +const ( + // XHeaderNetmapEpoch is a key to the reserved X-header that specifies netmap epoch + // to use for object placement calculation. If set to '0' or not set, the current + // epoch only will be used. + XHeaderNetmapEpoch = ReservedXHeaderPrefix + "NETMAP_EPOCH" + + // XHeaderNetmapLookupDepth is a key to the reserved X-header that limits + // how many past epochs back the node will can lookup. If set to '0' or not + // set, the current epoch only will be used. + XHeaderNetmapLookupDepth = ReservedXHeaderPrefix + "NETMAP_LOOKUP_DEPTH" +) + +// ReservedXHeaderPrefixNeoFS is a prefix of keys to "well-known" X-headers. +// Deprecated: use ReservedXHeaderPrefix. +const ReservedXHeaderPrefixNeoFS = "__NEOFS__" + +const ( + // XHeaderNetmapEpochNeoFS is a key to the reserved X-header that specifies netmap epoch + // to use for object placement calculation. If set to '0' or not set, the current + // epoch only will be used. + // Deprecated: use XHeaderNetmapEpoch. + XHeaderNetmapEpochNeoFS = ReservedXHeaderPrefixNeoFS + "NETMAP_EPOCH" + + // XHeaderNetmapLookupDepthNeoFS is a key to the reserved X-header that limits + // how many past epochs back the node will can lookup. If set to '0' or not + // set, the current epoch only will be used. + // Deprecated: use XHeaderNetmapLookupDepth. + XHeaderNetmapLookupDepthNeoFS = ReservedXHeaderPrefixNeoFS + "NETMAP_LOOKUP_DEPTH" +) diff --git a/pkg/api/signature/body.go b/pkg/api/signature/body.go new file mode 100644 index 000000000..fa86fe45f --- /dev/null +++ b/pkg/api/signature/body.go @@ -0,0 +1,109 @@ +package signature + +import ( + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/accounting" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/container" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" +) + +// nolint:funlen +func serviceMessageBody(req any) stableMarshaler { + switch v := req.(type) { + default: + panic(fmt.Sprintf("unsupported session message %T", req)) + + /* Accounting */ + case *accounting.BalanceRequest: + return v.GetBody() + case *accounting.BalanceResponse: + return v.GetBody() + + /* Session */ + case *session.CreateRequest: + return v.GetBody() + case *session.CreateResponse: + return v.GetBody() + + /* Container */ + case *container.PutRequest: + return v.GetBody() + case *container.PutResponse: + return v.GetBody() + case *container.DeleteRequest: + return v.GetBody() + case *container.DeleteResponse: + return v.GetBody() + case *container.GetRequest: + return v.GetBody() + case *container.GetResponse: + return v.GetBody() + case *container.ListRequest: + return v.GetBody() + case *container.ListResponse: + return v.GetBody() + case *container.SetExtendedACLRequest: + return v.GetBody() + case *container.SetExtendedACLResponse: + return v.GetBody() + case *container.GetExtendedACLRequest: + return v.GetBody() + case *container.GetExtendedACLResponse: + return v.GetBody() + case *container.AnnounceUsedSpaceRequest: + return v.GetBody() + case *container.AnnounceUsedSpaceResponse: + return v.GetBody() + + /* Object */ + case *object.PutRequest: + return v.GetBody() + case *object.PutResponse: + return v.GetBody() + case *object.GetRequest: + return v.GetBody() + case *object.GetResponse: + return v.GetBody() + case *object.HeadRequest: + return v.GetBody() + case *object.HeadResponse: + return v.GetBody() + case *object.SearchRequest: + return v.GetBody() + case *object.SearchResponse: + return v.GetBody() + case *object.DeleteRequest: + return v.GetBody() + case *object.DeleteResponse: + return v.GetBody() + case *object.GetRangeRequest: + return v.GetBody() + case *object.GetRangeResponse: + return v.GetBody() + case *object.GetRangeHashRequest: + return v.GetBody() + case *object.GetRangeHashResponse: + return v.GetBody() + case *object.PutSingleRequest: + return v.GetBody() + case *object.PutSingleResponse: + return v.GetBody() + + /* Netmap */ + case *netmap.LocalNodeInfoRequest: + return v.GetBody() + case *netmap.LocalNodeInfoResponse: + return v.GetBody() + case *netmap.NetworkInfoRequest: + return v.GetBody() + case *netmap.NetworkInfoResponse: + return v.GetBody() + case *netmap.SnapshotRequest: + return v.GetBody() + case *netmap.SnapshotResponse: + return v.GetBody() + } +} diff --git a/pkg/api/signature/marshaller.go b/pkg/api/signature/marshaller.go new file mode 100644 index 000000000..ff9beb39c --- /dev/null +++ b/pkg/api/signature/marshaller.go @@ -0,0 +1,26 @@ +package signature + +type stableMarshaler interface { + StableMarshal([]byte) []byte + StableSize() int +} + +type StableMarshalerWrapper struct { + SM stableMarshaler +} + +func (s StableMarshalerWrapper) ReadSignedData(buf []byte) ([]byte, error) { + if s.SM != nil { + return s.SM.StableMarshal(buf), nil + } + + return nil, nil +} + +func (s StableMarshalerWrapper) SignedDataSize() int { + if s.SM != nil { + return s.SM.StableSize() + } + + return 0 +} diff --git a/pkg/api/signature/sign.go b/pkg/api/signature/sign.go new file mode 100644 index 000000000..ce7b99100 --- /dev/null +++ b/pkg/api/signature/sign.go @@ -0,0 +1,122 @@ +package signature + +import ( + "crypto/ecdsa" + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/util/signature" + "golang.org/x/sync/errgroup" +) + +type serviceRequest interface { + GetMetaHeader() *session.RequestMetaHeader + GetVerificationHeader() *session.RequestVerificationHeader + SetVerificationHeader(*session.RequestVerificationHeader) +} + +type serviceResponse interface { + GetMetaHeader() *session.ResponseMetaHeader + GetVerificationHeader() *session.ResponseVerificationHeader + SetVerificationHeader(*session.ResponseVerificationHeader) +} + +type signatureReceiver interface { + SetBodySignature(*refs.Signature) + SetMetaSignature(*refs.Signature) + SetOriginSignature(*refs.Signature) +} + +// SignServiceMessage signes service message with key. +func SignServiceMessage(key *ecdsa.PrivateKey, msg any) error { + switch v := msg.(type) { + case nil: + return nil + case serviceRequest: + return signServiceRequest(key, v) + case serviceResponse: + return signServiceResponse(key, v) + default: + panic(fmt.Sprintf("unsupported session message %T", v)) + } +} + +func signServiceRequest(key *ecdsa.PrivateKey, v serviceRequest) error { + result := &session.RequestVerificationHeader{} + body := serviceMessageBody(v) + meta := v.GetMetaHeader() + header := v.GetVerificationHeader() + if err := signMessageParts(key, body, meta, header, header != nil, result); err != nil { + return err + } + result.SetOrigin(header) + v.SetVerificationHeader(result) + return nil +} + +func signServiceResponse(key *ecdsa.PrivateKey, v serviceResponse) error { + result := &session.ResponseVerificationHeader{} + body := serviceMessageBody(v) + meta := v.GetMetaHeader() + header := v.GetVerificationHeader() + if err := signMessageParts(key, body, meta, header, header != nil, result); err != nil { + return err + } + result.SetOrigin(header) + v.SetVerificationHeader(result) + return nil +} + +func signMessageParts(key *ecdsa.PrivateKey, body, meta, header stableMarshaler, hasHeader bool, result signatureReceiver) error { + eg := &errgroup.Group{} + if !hasHeader { + // sign session message body + eg.Go(func() error { + if err := signServiceMessagePart(key, body, result.SetBodySignature); err != nil { + return fmt.Errorf("could not sign body: %w", err) + } + return nil + }) + } + + // sign meta header + eg.Go(func() error { + if err := signServiceMessagePart(key, meta, result.SetMetaSignature); err != nil { + return fmt.Errorf("could not sign meta header: %w", err) + } + return nil + }) + + // sign verification header origin + eg.Go(func() error { + if err := signServiceMessagePart(key, header, result.SetOriginSignature); err != nil { + return fmt.Errorf("could not sign origin of verification header: %w", err) + } + return nil + }) + return eg.Wait() +} + +func signServiceMessagePart(key *ecdsa.PrivateKey, part stableMarshaler, sigWrite func(*refs.Signature)) error { + var sig *refs.Signature + + wrapper := StableMarshalerWrapper{ + SM: part, + } + // sign part + if err := signature.SignDataWithHandler( + key, + wrapper, + func(s *refs.Signature) { + sig = s + }, + ); err != nil { + return err + } + + // write part signature + sigWrite(sig) + + return nil +} diff --git a/pkg/api/signature/sign_test.go b/pkg/api/signature/sign_test.go new file mode 100644 index 000000000..846d3c55e --- /dev/null +++ b/pkg/api/signature/sign_test.go @@ -0,0 +1,125 @@ +package signature + +import ( + "testing" + + crypto "git.frostfs.info/TrueCloudLab/frostfs-crypto" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/accounting" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" + "github.com/stretchr/testify/require" +) + +func TestBalanceResponse(t *testing.T) { + dec := new(accounting.Decimal) + dec.SetValue(100) + + body := new(accounting.BalanceResponseBody) + body.SetBalance(dec) + + meta := new(session.ResponseMetaHeader) + meta.SetTTL(1) + + req := new(accounting.BalanceResponse) + req.SetBody(body) + req.SetMetaHeader(meta) + + // verify unsigned request + require.Error(t, VerifyServiceMessage(req)) + + key, err := crypto.LoadPrivateKey("Kwk6k2eC3L3QuPvD8aiaNyoSXgQ2YL1bwS5CP1oKoA9waeAze97s") + require.NoError(t, err) + + // sign request + require.NoError(t, SignServiceMessage(key, req)) + + // verification must pass + require.NoError(t, VerifyServiceMessage(req)) + + // add level to meta header matryoshka + meta = new(session.ResponseMetaHeader) + meta.SetOrigin(req.GetMetaHeader()) + req.SetMetaHeader(meta) + + // sign request + require.NoError(t, SignServiceMessage(key, req)) + + // verification must pass + require.NoError(t, VerifyServiceMessage(req)) + + // corrupt body + dec.SetValue(dec.GetValue() + 1) + + // verification must fail + require.Error(t, VerifyServiceMessage(req)) + + // restore body + dec.SetValue(dec.GetValue() - 1) + + // corrupt meta header + meta.SetTTL(meta.GetTTL() + 1) + + // verification must fail + require.Error(t, VerifyServiceMessage(req)) + + // restore meta header + meta.SetTTL(meta.GetTTL() - 1) + + // corrupt origin verification header + req.GetVerificationHeader().SetOrigin(nil) + + // verification must fail + require.Error(t, VerifyServiceMessage(req)) +} + +func BenchmarkSignRequest(b *testing.B) { + key, _ := crypto.LoadPrivateKey("Kwk6k2eC3L3QuPvD8aiaNyoSXgQ2YL1bwS5CP1oKoA9waeAze97s") + + b.ResetTimer() + b.ReportAllocs() + + for i := 0; i < b.N; i++ { + b.StopTimer() + dec := new(accounting.Decimal) + dec.SetValue(100) + + body := new(accounting.BalanceResponseBody) + body.SetBalance(dec) + + meta := new(session.ResponseMetaHeader) + meta.SetTTL(1) + + resp := new(accounting.BalanceResponse) + resp.SetBody(body) + resp.SetMetaHeader(meta) + + b.StartTimer() + SignServiceMessage(key, resp) + } +} + +func BenchmarkVerifyRequest(b *testing.B) { + key, _ := crypto.LoadPrivateKey("Kwk6k2eC3L3QuPvD8aiaNyoSXgQ2YL1bwS5CP1oKoA9waeAze97s") + + b.ResetTimer() + b.ReportAllocs() + + for i := 0; i < b.N; i++ { + b.StopTimer() + dec := new(accounting.Decimal) + dec.SetValue(100) + + body := new(accounting.BalanceResponseBody) + body.SetBalance(dec) + + meta := new(session.ResponseMetaHeader) + meta.SetTTL(1) + + resp := new(accounting.BalanceResponse) + resp.SetBody(body) + resp.SetMetaHeader(meta) + SignServiceMessage(key, resp) + b.StartTimer() + + VerifyServiceMessage(resp) + } +} diff --git a/pkg/api/signature/verify.go b/pkg/api/signature/verify.go new file mode 100644 index 000000000..587f8c2d1 --- /dev/null +++ b/pkg/api/signature/verify.go @@ -0,0 +1,127 @@ +package signature + +import ( + "errors" + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/util/signature" + "golang.org/x/sync/errgroup" +) + +type signatureProvider interface { + GetBodySignature() *refs.Signature + GetMetaSignature() *refs.Signature + GetOriginSignature() *refs.Signature +} + +// VerifyServiceMessage verifies service message. +func VerifyServiceMessage(msg any) error { + switch v := msg.(type) { + case nil: + return nil + case serviceRequest: + return verifyServiceRequest(v) + case serviceResponse: + return verifyServiceResponse(v) + default: + panic(fmt.Sprintf("unsupported session message %T", v)) + } +} + +func verifyServiceRequest(v serviceRequest) error { + meta := v.GetMetaHeader() + verificationHeader := v.GetVerificationHeader() + body := serviceMessageBody(v) + return verifyServiceRequestRecursive(body, meta, verificationHeader) +} + +func verifyServiceRequestRecursive(body stableMarshaler, meta *session.RequestMetaHeader, verify *session.RequestVerificationHeader) error { + verificationHeaderOrigin := verify.GetOrigin() + metaOrigin := meta.GetOrigin() + + stop, err := verifyMessageParts(body, meta, verificationHeaderOrigin, verificationHeaderOrigin != nil, verify) + if err != nil { + return err + } + if stop { + return nil + } + + return verifyServiceRequestRecursive(body, metaOrigin, verificationHeaderOrigin) +} + +func verifyMessageParts(body, meta, originHeader stableMarshaler, hasOriginHeader bool, sigProvider signatureProvider) (stop bool, err error) { + eg := &errgroup.Group{} + + eg.Go(func() error { + if err := verifyServiceMessagePart(meta, sigProvider.GetMetaSignature); err != nil { + return fmt.Errorf("could not verify meta header: %w", err) + } + return nil + }) + + eg.Go(func() error { + if err := verifyServiceMessagePart(originHeader, sigProvider.GetOriginSignature); err != nil { + return fmt.Errorf("could not verify origin of verification header: %w", err) + } + return nil + }) + + if !hasOriginHeader { + eg.Go(func() error { + if err := verifyServiceMessagePart(body, sigProvider.GetBodySignature); err != nil { + return fmt.Errorf("could not verify body: %w", err) + } + return nil + }) + } + + if err := eg.Wait(); err != nil { + return false, err + } + + if !hasOriginHeader { + return true, nil + } + + if sigProvider.GetBodySignature() != nil { + return false, errors.New("body signature misses at the matryoshka upper level") + } + + return false, nil +} + +func verifyServiceResponse(v serviceResponse) error { + meta := v.GetMetaHeader() + verificationHeader := v.GetVerificationHeader() + body := serviceMessageBody(v) + return verifyServiceResponseRecursive(body, meta, verificationHeader) +} + +func verifyServiceResponseRecursive(body stableMarshaler, meta *session.ResponseMetaHeader, verify *session.ResponseVerificationHeader) error { + verificationHeaderOrigin := verify.GetOrigin() + metaOrigin := meta.GetOrigin() + + stop, err := verifyMessageParts(body, meta, verificationHeaderOrigin, verificationHeaderOrigin != nil, verify) + if err != nil { + return err + } + if stop { + return nil + } + + return verifyServiceResponseRecursive(body, metaOrigin, verificationHeaderOrigin) +} + +func verifyServiceMessagePart(part stableMarshaler, sigRdr func() *refs.Signature) error { + wrapper := StableMarshalerWrapper{ + SM: part, + } + + return signature.VerifyDataWithSource( + wrapper, + sigRdr, + ) +} diff --git a/pkg/api/status/convert.go b/pkg/api/status/convert.go new file mode 100644 index 000000000..5631f4a6b --- /dev/null +++ b/pkg/api/status/convert.go @@ -0,0 +1,97 @@ +package status + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/message" + status "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/status/grpc" +) + +func (x *Detail) ToGRPCMessage() grpc.Message { + var m *status.Status_Detail + + if x != nil { + m = new(status.Status_Detail) + + m.SetId(x.id) + m.SetValue(x.val) + } + + return m +} + +func (x *Detail) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*status.Status_Detail) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + x.id = v.GetId() + x.val = v.GetValue() + + return nil +} + +func CodeFromGRPC(v uint32) Code { + return Code(v) +} + +func CodeToGRPC(v Code) uint32 { + return uint32(v) +} + +func (x *Status) ToGRPCMessage() grpc.Message { + var m *status.Status + + if x != nil { + m = new(status.Status) + + m.SetCode(CodeToGRPC(x.code)) + m.SetMessage(x.msg) + + var ds []*status.Status_Detail + + if ln := len(x.details); ln > 0 { + ds = make([]*status.Status_Detail, 0, ln) + + for i := 0; i < ln; i++ { + ds = append(ds, x.details[i].ToGRPCMessage().(*status.Status_Detail)) + } + } + + m.SetDetails(ds) + } + + return m +} + +func (x *Status) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*status.Status) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var ( + ds []Detail + dsV2 = v.GetDetails() + ) + + if dsV2 != nil { + ln := len(dsV2) + + ds = make([]Detail, ln) + + for i := 0; i < ln; i++ { + if dsV2[i] != nil { + if err := ds[i].FromGRPCMessage(dsV2[i]); err != nil { + return err + } + } + } + } + + x.details = ds + x.msg = v.GetMessage() + x.code = CodeFromGRPC(v.GetCode()) + + return nil +} diff --git a/pkg/api/status/details.go b/pkg/api/status/details.go new file mode 100644 index 000000000..5b8f46035 --- /dev/null +++ b/pkg/api/status/details.go @@ -0,0 +1,8 @@ +package status + +// details for WrongMagicNumber code. +const ( + // DetailIDCorrectMagic is an identifier of details with correct network magic + // which can be attached to WrongMagicNumber code. + DetailIDCorrectMagic = iota +) diff --git a/pkg/api/status/grpc/types.go b/pkg/api/status/grpc/types.go new file mode 100644 index 000000000..993f6322e --- /dev/null +++ b/pkg/api/status/grpc/types.go @@ -0,0 +1,26 @@ +package status + +// SetId sets identifier of the Status_Detail. +func (x *Status_Detail) SetId(v uint32) { + x.Id = v +} + +// SetValue sets value of the Status_Detail. +func (x *Status_Detail) SetValue(v []byte) { + x.Value = v +} + +// SetCode sets code of the Status. +func (x *Status) SetCode(v uint32) { + x.Code = v +} + +// SetMessage sets message about the Status. +func (x *Status) SetMessage(v string) { + x.Message = v +} + +// SetDetails sets details of the Status. +func (x *Status) SetDetails(v []*Status_Detail) { + x.Details = v +} diff --git a/pkg/api/status/grpc/types.pb.go b/pkg/api/status/grpc/types.pb.go new file mode 100644 index 000000000..097280501 --- /dev/null +++ b/pkg/api/status/grpc/types.pb.go @@ -0,0 +1,654 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.33.0 +// protoc v4.25.3 +// source: status/grpc/types.proto + +package status + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// Section identifiers. +type Section int32 + +const ( + // Successful return codes. + Section_SECTION_SUCCESS Section = 0 + // Failure codes regardless of the operation. + Section_SECTION_FAILURE_COMMON Section = 1 + // Object service-specific errors. + Section_SECTION_OBJECT Section = 2 + // Container service-specific errors. + Section_SECTION_CONTAINER Section = 3 + // Session service-specific errors. + Section_SECTION_SESSION Section = 4 +) + +// Enum value maps for Section. +var ( + Section_name = map[int32]string{ + 0: "SECTION_SUCCESS", + 1: "SECTION_FAILURE_COMMON", + 2: "SECTION_OBJECT", + 3: "SECTION_CONTAINER", + 4: "SECTION_SESSION", + } + Section_value = map[string]int32{ + "SECTION_SUCCESS": 0, + "SECTION_FAILURE_COMMON": 1, + "SECTION_OBJECT": 2, + "SECTION_CONTAINER": 3, + "SECTION_SESSION": 4, + } +) + +func (x Section) Enum() *Section { + p := new(Section) + *p = x + return p +} + +func (x Section) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (Section) Descriptor() protoreflect.EnumDescriptor { + return file_status_grpc_types_proto_enumTypes[0].Descriptor() +} + +func (Section) Type() protoreflect.EnumType { + return &file_status_grpc_types_proto_enumTypes[0] +} + +func (x Section) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use Section.Descriptor instead. +func (Section) EnumDescriptor() ([]byte, []int) { + return file_status_grpc_types_proto_rawDescGZIP(), []int{0} +} + +// Section of NeoFS successful return codes. +type Success int32 + +const ( + // [**0**] Default success. Not detailed. + // If the server cannot match successful outcome to the code, it should + // use this code. + Success_OK Success = 0 +) + +// Enum value maps for Success. +var ( + Success_name = map[int32]string{ + 0: "OK", + } + Success_value = map[string]int32{ + "OK": 0, + } +) + +func (x Success) Enum() *Success { + p := new(Success) + *p = x + return p +} + +func (x Success) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (Success) Descriptor() protoreflect.EnumDescriptor { + return file_status_grpc_types_proto_enumTypes[1].Descriptor() +} + +func (Success) Type() protoreflect.EnumType { + return &file_status_grpc_types_proto_enumTypes[1] +} + +func (x Success) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use Success.Descriptor instead. +func (Success) EnumDescriptor() ([]byte, []int) { + return file_status_grpc_types_proto_rawDescGZIP(), []int{1} +} + +// Section of failed statuses independent of the operation. +type CommonFail int32 + +const ( + // [**1024**] Internal server error, default failure. Not detailed. + // If the server cannot match failed outcome to the code, it should + // use this code. + CommonFail_INTERNAL CommonFail = 0 + // [**1025**] Wrong magic of the NeoFS network. + // Details: + // - [**0**] Magic number of the served NeoFS network (big-endian 64-bit + // unsigned integer). + CommonFail_WRONG_MAGIC_NUMBER CommonFail = 1 + // [**1026**] Signature verification failure. + CommonFail_SIGNATURE_VERIFICATION_FAIL CommonFail = 2 + // [**1027**] Node is under maintenance. + CommonFail_NODE_UNDER_MAINTENANCE CommonFail = 3 +) + +// Enum value maps for CommonFail. +var ( + CommonFail_name = map[int32]string{ + 0: "INTERNAL", + 1: "WRONG_MAGIC_NUMBER", + 2: "SIGNATURE_VERIFICATION_FAIL", + 3: "NODE_UNDER_MAINTENANCE", + } + CommonFail_value = map[string]int32{ + "INTERNAL": 0, + "WRONG_MAGIC_NUMBER": 1, + "SIGNATURE_VERIFICATION_FAIL": 2, + "NODE_UNDER_MAINTENANCE": 3, + } +) + +func (x CommonFail) Enum() *CommonFail { + p := new(CommonFail) + *p = x + return p +} + +func (x CommonFail) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (CommonFail) Descriptor() protoreflect.EnumDescriptor { + return file_status_grpc_types_proto_enumTypes[2].Descriptor() +} + +func (CommonFail) Type() protoreflect.EnumType { + return &file_status_grpc_types_proto_enumTypes[2] +} + +func (x CommonFail) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use CommonFail.Descriptor instead. +func (CommonFail) EnumDescriptor() ([]byte, []int) { + return file_status_grpc_types_proto_rawDescGZIP(), []int{2} +} + +// Section of statuses for object-related operations. +type Object int32 + +const ( + // [**2048**] Access denied by ACL. + // Details: + // - [**0**] Human-readable description (UTF-8 encoded string). + Object_ACCESS_DENIED Object = 0 + // [**2049**] Object not found. + Object_OBJECT_NOT_FOUND Object = 1 + // [**2050**] Operation rejected by the object lock. + Object_LOCKED Object = 2 + // [**2051**] Locking an object with a non-REGULAR type rejected. + Object_LOCK_NON_REGULAR_OBJECT Object = 3 + // [**2052**] Object has been marked deleted. + Object_OBJECT_ALREADY_REMOVED Object = 4 + // [**2053**] Invalid range has been requested for an object. + Object_OUT_OF_RANGE Object = 5 +) + +// Enum value maps for Object. +var ( + Object_name = map[int32]string{ + 0: "ACCESS_DENIED", + 1: "OBJECT_NOT_FOUND", + 2: "LOCKED", + 3: "LOCK_NON_REGULAR_OBJECT", + 4: "OBJECT_ALREADY_REMOVED", + 5: "OUT_OF_RANGE", + } + Object_value = map[string]int32{ + "ACCESS_DENIED": 0, + "OBJECT_NOT_FOUND": 1, + "LOCKED": 2, + "LOCK_NON_REGULAR_OBJECT": 3, + "OBJECT_ALREADY_REMOVED": 4, + "OUT_OF_RANGE": 5, + } +) + +func (x Object) Enum() *Object { + p := new(Object) + *p = x + return p +} + +func (x Object) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (Object) Descriptor() protoreflect.EnumDescriptor { + return file_status_grpc_types_proto_enumTypes[3].Descriptor() +} + +func (Object) Type() protoreflect.EnumType { + return &file_status_grpc_types_proto_enumTypes[3] +} + +func (x Object) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use Object.Descriptor instead. +func (Object) EnumDescriptor() ([]byte, []int) { + return file_status_grpc_types_proto_rawDescGZIP(), []int{3} +} + +// Section of statuses for container-related operations. +type Container int32 + +const ( + // [**3072**] Container not found. + Container_CONTAINER_NOT_FOUND Container = 0 + // [**3073**] eACL table not found. + Container_EACL_NOT_FOUND Container = 1 +) + +// Enum value maps for Container. +var ( + Container_name = map[int32]string{ + 0: "CONTAINER_NOT_FOUND", + 1: "EACL_NOT_FOUND", + } + Container_value = map[string]int32{ + "CONTAINER_NOT_FOUND": 0, + "EACL_NOT_FOUND": 1, + } +) + +func (x Container) Enum() *Container { + p := new(Container) + *p = x + return p +} + +func (x Container) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (Container) Descriptor() protoreflect.EnumDescriptor { + return file_status_grpc_types_proto_enumTypes[4].Descriptor() +} + +func (Container) Type() protoreflect.EnumType { + return &file_status_grpc_types_proto_enumTypes[4] +} + +func (x Container) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use Container.Descriptor instead. +func (Container) EnumDescriptor() ([]byte, []int) { + return file_status_grpc_types_proto_rawDescGZIP(), []int{4} +} + +// Section of statuses for session-related operations. +type Session int32 + +const ( + // [**4096**] Token not found. + Session_TOKEN_NOT_FOUND Session = 0 + // [**4097**] Token has expired. + Session_TOKEN_EXPIRED Session = 1 +) + +// Enum value maps for Session. +var ( + Session_name = map[int32]string{ + 0: "TOKEN_NOT_FOUND", + 1: "TOKEN_EXPIRED", + } + Session_value = map[string]int32{ + "TOKEN_NOT_FOUND": 0, + "TOKEN_EXPIRED": 1, + } +) + +func (x Session) Enum() *Session { + p := new(Session) + *p = x + return p +} + +func (x Session) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (Session) Descriptor() protoreflect.EnumDescriptor { + return file_status_grpc_types_proto_enumTypes[5].Descriptor() +} + +func (Session) Type() protoreflect.EnumType { + return &file_status_grpc_types_proto_enumTypes[5] +} + +func (x Session) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use Session.Descriptor instead. +func (Session) EnumDescriptor() ([]byte, []int) { + return file_status_grpc_types_proto_rawDescGZIP(), []int{5} +} + +// Declares the general format of the status returns of the NeoFS RPC protocol. +// Status is present in all response messages. Each RPC of NeoFS protocol +// describes the possible outcomes and details of the operation. +// +// Each status is assigned a one-to-one numeric code. Any unique result of an +// operation in NeoFS is unambiguously associated with the code value. +// +// Numerical set of codes is split into 1024-element sections. An enumeration +// is defined for each section. Values can be referred to in the following ways: +// +// * numerical value ranging from 0 to 4,294,967,295 (global code); +// +// - values from enumeration (local code). The formula for the ratio of the +// local code (`L`) of a defined section (`S`) to the global one (`G`): +// `G = 1024 * S + L`. +// +// All outcomes are divided into successful and failed, which corresponds +// to the success or failure of the operation. The definition of success +// follows the semantics of RPC and the description of its purpose. +// The server must not attach code that is the opposite of the outcome type. +// +// See the set of return codes in the description for calls. +// +// Each status can carry a developer-facing error message. It should be a human +// readable text in English. The server should not transmit (and the client +// should not expect) useful information in the message. Field `details` +// should make the return more detailed. +type Status struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The status code + Code uint32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` + // Developer-facing error message + Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"` + // Data detailing the outcome of the operation. Must be unique by ID. + Details []*Status_Detail `protobuf:"bytes,3,rep,name=details,proto3" json:"details,omitempty"` +} + +func (x *Status) Reset() { + *x = Status{} + if protoimpl.UnsafeEnabled { + mi := &file_status_grpc_types_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Status) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Status) ProtoMessage() {} + +func (x *Status) ProtoReflect() protoreflect.Message { + mi := &file_status_grpc_types_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Status.ProtoReflect.Descriptor instead. +func (*Status) Descriptor() ([]byte, []int) { + return file_status_grpc_types_proto_rawDescGZIP(), []int{0} +} + +func (x *Status) GetCode() uint32 { + if x != nil { + return x.Code + } + return 0 +} + +func (x *Status) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + +func (x *Status) GetDetails() []*Status_Detail { + if x != nil { + return x.Details + } + return nil +} + +// Return detail. It contains additional information that can be used to +// analyze the response. Each code defines a set of details that can be +// attached to a status. Client should not handle details that are not +// covered by the code. +type Status_Detail struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Detail ID. The identifier is required to determine the binary format + // of the detail and how to decode it. + Id uint32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` + // Binary status detail. Must follow the format associated with ID. + // The possibility of missing a value must be explicitly allowed. + Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` +} + +func (x *Status_Detail) Reset() { + *x = Status_Detail{} + if protoimpl.UnsafeEnabled { + mi := &file_status_grpc_types_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Status_Detail) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Status_Detail) ProtoMessage() {} + +func (x *Status_Detail) ProtoReflect() protoreflect.Message { + mi := &file_status_grpc_types_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Status_Detail.ProtoReflect.Descriptor instead. +func (*Status_Detail) Descriptor() ([]byte, []int) { + return file_status_grpc_types_proto_rawDescGZIP(), []int{0, 0} +} + +func (x *Status_Detail) GetId() uint32 { + if x != nil { + return x.Id + } + return 0 +} + +func (x *Status_Detail) GetValue() []byte { + if x != nil { + return x.Value + } + return nil +} + +var File_status_grpc_types_proto protoreflect.FileDescriptor + +var file_status_grpc_types_proto_rawDesc = []byte{ + 0x0a, 0x17, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x74, 0x79, + 0x70, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x10, 0x6e, 0x65, 0x6f, 0x2e, 0x66, + 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0xa1, 0x01, 0x0a, 0x06, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x12, 0x39, 0x0a, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x18, + 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, + 0x32, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, + 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x52, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x1a, + 0x2e, 0x0a, 0x06, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2a, + 0x7a, 0x0a, 0x07, 0x53, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x13, 0x0a, 0x0f, 0x53, 0x45, + 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x55, 0x43, 0x43, 0x45, 0x53, 0x53, 0x10, 0x00, 0x12, + 0x1a, 0x0a, 0x16, 0x53, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x55, + 0x52, 0x45, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, 0x4f, 0x4e, 0x10, 0x01, 0x12, 0x12, 0x0a, 0x0e, 0x53, + 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4f, 0x42, 0x4a, 0x45, 0x43, 0x54, 0x10, 0x02, 0x12, + 0x15, 0x0a, 0x11, 0x53, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x43, 0x4f, 0x4e, 0x54, 0x41, + 0x49, 0x4e, 0x45, 0x52, 0x10, 0x03, 0x12, 0x13, 0x0a, 0x0f, 0x53, 0x45, 0x43, 0x54, 0x49, 0x4f, + 0x4e, 0x5f, 0x53, 0x45, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x10, 0x04, 0x2a, 0x11, 0x0a, 0x07, 0x53, + 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x06, 0x0a, 0x02, 0x4f, 0x4b, 0x10, 0x00, 0x2a, 0x6f, + 0x0a, 0x0a, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x46, 0x61, 0x69, 0x6c, 0x12, 0x0c, 0x0a, 0x08, + 0x49, 0x4e, 0x54, 0x45, 0x52, 0x4e, 0x41, 0x4c, 0x10, 0x00, 0x12, 0x16, 0x0a, 0x12, 0x57, 0x52, + 0x4f, 0x4e, 0x47, 0x5f, 0x4d, 0x41, 0x47, 0x49, 0x43, 0x5f, 0x4e, 0x55, 0x4d, 0x42, 0x45, 0x52, + 0x10, 0x01, 0x12, 0x1f, 0x0a, 0x1b, 0x53, 0x49, 0x47, 0x4e, 0x41, 0x54, 0x55, 0x52, 0x45, 0x5f, + 0x56, 0x45, 0x52, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x46, 0x41, 0x49, + 0x4c, 0x10, 0x02, 0x12, 0x1a, 0x0a, 0x16, 0x4e, 0x4f, 0x44, 0x45, 0x5f, 0x55, 0x4e, 0x44, 0x45, + 0x52, 0x5f, 0x4d, 0x41, 0x49, 0x4e, 0x54, 0x45, 0x4e, 0x41, 0x4e, 0x43, 0x45, 0x10, 0x03, 0x2a, + 0x88, 0x01, 0x0a, 0x06, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x11, 0x0a, 0x0d, 0x41, 0x43, + 0x43, 0x45, 0x53, 0x53, 0x5f, 0x44, 0x45, 0x4e, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x14, 0x0a, + 0x10, 0x4f, 0x42, 0x4a, 0x45, 0x43, 0x54, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x46, 0x4f, 0x55, 0x4e, + 0x44, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x4c, 0x4f, 0x43, 0x4b, 0x45, 0x44, 0x10, 0x02, 0x12, + 0x1b, 0x0a, 0x17, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x4e, 0x4f, 0x4e, 0x5f, 0x52, 0x45, 0x47, 0x55, + 0x4c, 0x41, 0x52, 0x5f, 0x4f, 0x42, 0x4a, 0x45, 0x43, 0x54, 0x10, 0x03, 0x12, 0x1a, 0x0a, 0x16, + 0x4f, 0x42, 0x4a, 0x45, 0x43, 0x54, 0x5f, 0x41, 0x4c, 0x52, 0x45, 0x41, 0x44, 0x59, 0x5f, 0x52, + 0x45, 0x4d, 0x4f, 0x56, 0x45, 0x44, 0x10, 0x04, 0x12, 0x10, 0x0a, 0x0c, 0x4f, 0x55, 0x54, 0x5f, + 0x4f, 0x46, 0x5f, 0x52, 0x41, 0x4e, 0x47, 0x45, 0x10, 0x05, 0x2a, 0x38, 0x0a, 0x09, 0x43, 0x6f, + 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x17, 0x0a, 0x13, 0x43, 0x4f, 0x4e, 0x54, 0x41, + 0x49, 0x4e, 0x45, 0x52, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x46, 0x4f, 0x55, 0x4e, 0x44, 0x10, 0x00, + 0x12, 0x12, 0x0a, 0x0e, 0x45, 0x41, 0x43, 0x4c, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x46, 0x4f, 0x55, + 0x4e, 0x44, 0x10, 0x01, 0x2a, 0x31, 0x0a, 0x07, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, + 0x13, 0x0a, 0x0f, 0x54, 0x4f, 0x4b, 0x45, 0x4e, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x46, 0x4f, 0x55, + 0x4e, 0x44, 0x10, 0x00, 0x12, 0x11, 0x0a, 0x0d, 0x54, 0x4f, 0x4b, 0x45, 0x4e, 0x5f, 0x45, 0x58, + 0x50, 0x49, 0x52, 0x45, 0x44, 0x10, 0x01, 0x42, 0x61, 0x5a, 0x42, 0x67, 0x69, 0x74, 0x2e, 0x66, + 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, 0x75, 0x65, + 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x4c, 0x61, 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, + 0x2d, 0x61, 0x70, 0x69, 0x2d, 0x67, 0x6f, 0x2f, 0x76, 0x32, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x3b, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0xaa, 0x02, 0x1a, + 0x4e, 0x65, 0x6f, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, + 0x41, 0x50, 0x49, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, +} + +var ( + file_status_grpc_types_proto_rawDescOnce sync.Once + file_status_grpc_types_proto_rawDescData = file_status_grpc_types_proto_rawDesc +) + +func file_status_grpc_types_proto_rawDescGZIP() []byte { + file_status_grpc_types_proto_rawDescOnce.Do(func() { + file_status_grpc_types_proto_rawDescData = protoimpl.X.CompressGZIP(file_status_grpc_types_proto_rawDescData) + }) + return file_status_grpc_types_proto_rawDescData +} + +var file_status_grpc_types_proto_enumTypes = make([]protoimpl.EnumInfo, 6) +var file_status_grpc_types_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_status_grpc_types_proto_goTypes = []interface{}{ + (Section)(0), // 0: neo.fs.v2.status.Section + (Success)(0), // 1: neo.fs.v2.status.Success + (CommonFail)(0), // 2: neo.fs.v2.status.CommonFail + (Object)(0), // 3: neo.fs.v2.status.Object + (Container)(0), // 4: neo.fs.v2.status.Container + (Session)(0), // 5: neo.fs.v2.status.Session + (*Status)(nil), // 6: neo.fs.v2.status.Status + (*Status_Detail)(nil), // 7: neo.fs.v2.status.Status.Detail +} +var file_status_grpc_types_proto_depIdxs = []int32{ + 7, // 0: neo.fs.v2.status.Status.details:type_name -> neo.fs.v2.status.Status.Detail + 1, // [1:1] is the sub-list for method output_type + 1, // [1:1] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_status_grpc_types_proto_init() } +func file_status_grpc_types_proto_init() { + if File_status_grpc_types_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_status_grpc_types_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Status); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_status_grpc_types_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Status_Detail); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_status_grpc_types_proto_rawDesc, + NumEnums: 6, + NumMessages: 2, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_status_grpc_types_proto_goTypes, + DependencyIndexes: file_status_grpc_types_proto_depIdxs, + EnumInfos: file_status_grpc_types_proto_enumTypes, + MessageInfos: file_status_grpc_types_proto_msgTypes, + }.Build() + File_status_grpc_types_proto = out.File + file_status_grpc_types_proto_rawDesc = nil + file_status_grpc_types_proto_goTypes = nil + file_status_grpc_types_proto_depIdxs = nil +} diff --git a/pkg/api/status/marshal.go b/pkg/api/status/marshal.go new file mode 100644 index 000000000..9ee5370b1 --- /dev/null +++ b/pkg/api/status/marshal.go @@ -0,0 +1,92 @@ +package status + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/message" + status "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/status/grpc" + protoutil "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/util/proto" +) + +const ( + _ = iota + detailIDFNum + detailValueFNum +) + +func (x *Detail) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, x.StableSize()) + } + + var offset int + + offset += protoutil.UInt32Marshal(detailIDFNum, buf[offset:], x.id) + protoutil.BytesMarshal(detailValueFNum, buf[offset:], x.val) + + return buf +} + +func (x *Detail) StableSize() (size int) { + if x == nil { + return 0 + } + + size += protoutil.UInt32Size(detailIDFNum, x.id) + size += protoutil.BytesSize(detailValueFNum, x.val) + + return size +} + +func (x *Detail) Unmarshal(data []byte) error { + return message.Unmarshal(x, data, new(status.Status_Detail)) +} + +const ( + _ = iota + statusCodeFNum + statusMsgFNum + statusDetailsFNum +) + +func (x *Status) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, x.StableSize()) + } + + var offset int + + offset += protoutil.UInt32Marshal(statusCodeFNum, buf[offset:], CodeToGRPC(x.code)) + offset += protoutil.StringMarshal(statusMsgFNum, buf[offset:], x.msg) + + for i := range x.details { + offset += protoutil.NestedStructureMarshal(statusDetailsFNum, buf[offset:], &x.details[i]) + } + + return buf +} + +func (x *Status) StableSize() (size int) { + if x == nil { + return 0 + } + + size += protoutil.UInt32Size(statusCodeFNum, CodeToGRPC(x.code)) + size += protoutil.StringSize(statusMsgFNum, x.msg) + + for i := range x.details { + size += protoutil.NestedStructureSize(statusDetailsFNum, &x.details[i]) + } + + return size +} + +func (x *Status) Unmarshal(data []byte) error { + return message.Unmarshal(x, data, new(status.Status)) +} diff --git a/pkg/api/status/message_test.go b/pkg/api/status/message_test.go new file mode 100644 index 000000000..d6aa51392 --- /dev/null +++ b/pkg/api/status/message_test.go @@ -0,0 +1,16 @@ +package status_test + +import ( + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/message" + messagetest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/message/test" + statustest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/status/test" +) + +func TestMessageConvert(t *testing.T) { + messagetest.TestRPCMessage(t, + func(empty bool) message.Message { return statustest.Detail(empty) }, + func(empty bool) message.Message { return statustest.Status(empty) }, + ) +} diff --git a/pkg/api/status/status.go b/pkg/api/status/status.go new file mode 100644 index 000000000..c1b5272b8 --- /dev/null +++ b/pkg/api/status/status.go @@ -0,0 +1,101 @@ +package status + +const sectionBitSize = 10 + +// InSections checks if the Code is in [i,j] section list. +func (x Code) InSections(i, j uint32) bool { + return uint32(x) >= i< neo.fs.v2.refs.ObjectID + 1, // [1:1] is the sub-list for method output_type + 1, // [1:1] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_tombstone_grpc_types_proto_init() } +func file_tombstone_grpc_types_proto_init() { + if File_tombstone_grpc_types_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_tombstone_grpc_types_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Tombstone); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_tombstone_grpc_types_proto_rawDesc, + NumEnums: 0, + NumMessages: 1, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_tombstone_grpc_types_proto_goTypes, + DependencyIndexes: file_tombstone_grpc_types_proto_depIdxs, + MessageInfos: file_tombstone_grpc_types_proto_msgTypes, + }.Build() + File_tombstone_grpc_types_proto = out.File + file_tombstone_grpc_types_proto_rawDesc = nil + file_tombstone_grpc_types_proto_goTypes = nil + file_tombstone_grpc_types_proto_depIdxs = nil +} diff --git a/pkg/api/tombstone/json.go b/pkg/api/tombstone/json.go new file mode 100644 index 000000000..f48931021 --- /dev/null +++ b/pkg/api/tombstone/json.go @@ -0,0 +1,14 @@ +package tombstone + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/message" + tombstone "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/tombstone/grpc" +) + +func (s *Tombstone) MarshalJSON() ([]byte, error) { + return message.MarshalJSON(s) +} + +func (s *Tombstone) UnmarshalJSON(data []byte) error { + return message.UnmarshalJSON(s, data, new(tombstone.Tombstone)) +} diff --git a/pkg/api/tombstone/marshal.go b/pkg/api/tombstone/marshal.go new file mode 100644 index 000000000..3bd9c0f5a --- /dev/null +++ b/pkg/api/tombstone/marshal.go @@ -0,0 +1,56 @@ +package tombstone + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/message" + tombstone "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/tombstone/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/util/proto" +) + +const ( + expFNum = 1 + splitIDFNum = 2 + membersFNum = 3 +) + +// StableMarshal marshals unified tombstone message in a protobuf +// compatible way without field order shuffle. +func (s *Tombstone) StableMarshal(buf []byte) []byte { + if s == nil { + return []byte{} + } + + if buf == nil { + buf = make([]byte, s.StableSize()) + } + + var offset int + + offset += proto.UInt64Marshal(expFNum, buf[offset:], s.exp) + offset += proto.BytesMarshal(splitIDFNum, buf[offset:], s.splitID) + + for i := range s.members { + offset += proto.NestedStructureMarshal(membersFNum, buf[offset:], &s.members[i]) + } + + return buf +} + +// StableSize returns size of tombstone message marshalled by StableMarshal function. +func (s *Tombstone) StableSize() (size int) { + if s == nil { + return 0 + } + + size += proto.UInt64Size(expFNum, s.exp) + size += proto.BytesSize(splitIDFNum, s.splitID) + for i := range s.members { + size += proto.NestedStructureSize(membersFNum, &s.members[i]) + } + + return size +} + +// Unmarshal unmarshal tombstone message from its binary representation. +func (s *Tombstone) Unmarshal(data []byte) error { + return message.Unmarshal(s, data, new(tombstone.Tombstone)) +} diff --git a/pkg/api/tombstone/message_test.go b/pkg/api/tombstone/message_test.go new file mode 100644 index 000000000..58f6a74c0 --- /dev/null +++ b/pkg/api/tombstone/message_test.go @@ -0,0 +1,15 @@ +package tombstone_test + +import ( + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/message" + messagetest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/message/test" + tombstonetest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/tombstone/test" +) + +func TestMessageConvert(t *testing.T) { + messagetest.TestRPCMessage(t, + func(empty bool) message.Message { return tombstonetest.GenerateTombstone(empty) }, + ) +} diff --git a/pkg/api/tombstone/test/generate.go b/pkg/api/tombstone/test/generate.go new file mode 100644 index 000000000..7500ee1f4 --- /dev/null +++ b/pkg/api/tombstone/test/generate.go @@ -0,0 +1,18 @@ +package tombstonetest + +import ( + refstest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs/test" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/tombstone" +) + +func GenerateTombstone(empty bool) *tombstone.Tombstone { + m := new(tombstone.Tombstone) + + if !empty { + m.SetExpirationEpoch(89) + m.SetSplitID([]byte{3, 2, 1}) + m.SetMembers(refstest.GenerateObjectIDs(false)) + } + + return m +} diff --git a/pkg/api/tombstone/types.go b/pkg/api/tombstone/types.go new file mode 100644 index 000000000..e5e76b5c5 --- /dev/null +++ b/pkg/api/tombstone/types.go @@ -0,0 +1,57 @@ +package tombstone + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" +) + +// Tombstone is a unified structure of Tombstone +// message from proto definition. +type Tombstone struct { + exp uint64 + + splitID []byte + + members []refs.ObjectID +} + +// GetExpirationEpoch returns number of tombstone expiration epoch. +func (s *Tombstone) GetExpirationEpoch() uint64 { + if s != nil { + return s.exp + } + + return 0 +} + +// SetExpirationEpoch sets number of tombstone expiration epoch. +func (s *Tombstone) SetExpirationEpoch(v uint64) { + s.exp = v +} + +// GetSplitID returns identifier of split object hierarchy. +func (s *Tombstone) GetSplitID() []byte { + if s != nil { + return s.splitID + } + + return nil +} + +// SetSplitID sets identifier of split object hierarchy. +func (s *Tombstone) SetSplitID(v []byte) { + s.splitID = v +} + +// GetMembers returns list of objects to be deleted. +func (s *Tombstone) GetMembers() []refs.ObjectID { + if s != nil { + return s.members + } + + return nil +} + +// SetMembers sets list of objects to be deleted. +func (s *Tombstone) SetMembers(v []refs.ObjectID) { + s.members = v +} diff --git a/pkg/api/util/pool/buffer.go b/pkg/api/util/pool/buffer.go new file mode 100644 index 000000000..e0a7185a1 --- /dev/null +++ b/pkg/api/util/pool/buffer.go @@ -0,0 +1,54 @@ +package pool + +import ( + "sync" +) + +// Buffer contains a byte slice. +type Buffer struct { + Data []byte +} + +// BufferPool manages a pool of Buffers. +type BufferPool struct { + poolSliceSize uint32 // Size for the buffer slices in the pool. + buffersPool *sync.Pool +} + +// NewBufferPool creates a BufferPool with a specified size. +func NewBufferPool(poolSliceSize uint32) BufferPool { + pool := sync.Pool{ + New: func() any { + return new(Buffer) + }, + } + return BufferPool{poolSliceSize: poolSliceSize, buffersPool: &pool} +} + +// Get retrieves a Buffer from the pool or creates a new one if necessary. +// It ensures the buffer's capacity is at least the specified size. +func (pool BufferPool) Get(size uint32) *Buffer { + result := pool.buffersPool.Get().(*Buffer) + + if cap(result.Data) < int(size) { + result.Data = make([]byte, size) + } else { + result.Data = result.Data[:size] + } + return result +} + +// Put returns a Buffer to the pool if its capacity does not exceed poolSliceSize. +func (pool BufferPool) Put(buf *Buffer) { + if cap(buf.Data) > int(pool.poolSliceSize) { + return + } + + buf.Data = buf.Data[:0] + pool.buffersPool.Put(buf) +} + +// PoolSliceSize returns the size for buffer slices in the pool. +func (pool BufferPool) PoolSliceSize() uint32 { + return uint32(pool.poolSliceSize) +} diff --git a/pkg/api/util/proto/marshal.go b/pkg/api/util/proto/marshal.go new file mode 100644 index 000000000..26b3eb0be --- /dev/null +++ b/pkg/api/util/proto/marshal.go @@ -0,0 +1,387 @@ +/* +This package contains help functions for stable marshaller. Their usage is +totally optional. One can implement fast stable marshaller without these +runtime function calls. +*/ + +package proto + +import ( + "encoding/binary" + "math" + "math/bits" + + "google.golang.org/protobuf/encoding/protowire" +) + +type ( + stableMarshaler interface { + StableMarshal([]byte) []byte + StableSize() int + } + + setMarshalData[T any] interface { + SetMarshalData([]byte) + StableSize() int + ~*T + } +) + +func BytesMarshal(field int, buf, v []byte) int { + return bytesMarshal(field, buf, v) +} + +func BytesSize(field int, v []byte) int { + return bytesSize(field, v) +} + +func bytesMarshal[T ~[]byte | ~string](field int, buf []byte, v T) int { + if len(v) == 0 { + return 0 + } + return bytesMarshalNoCheck(field, buf, v) +} + +func bytesMarshalNoCheck[T ~[]byte | ~string](field int, buf []byte, v T) int { + prefix := protowire.EncodeTag(protowire.Number(field), protowire.BytesType) + + // buf length check can prevent panic at PutUvarint, but it will make + // marshaller a bit slower. + i := binary.PutUvarint(buf, uint64(prefix)) + i += binary.PutUvarint(buf[i:], uint64(len(v))) + i += copy(buf[i:], v) + + return i +} + +func bytesSize[T ~[]byte | ~string](field int, v T) int { + if len(v) == 0 { + return 0 + } + return bytesSizeNoCheck(field, v) +} + +func bytesSizeNoCheck[T ~[]byte | ~string](field int, v T) int { + return protowire.SizeGroup(protowire.Number(field), protowire.SizeBytes(len(v))) +} + +func StringMarshal(field int, buf []byte, v string) int { + return bytesMarshal(field, buf, v) +} + +func StringSize(field int, v string) int { + return bytesSize(field, v) +} + +func BoolMarshal(field int, buf []byte, v bool) int { + if !v { + return 0 + } + + prefix := protowire.EncodeTag(protowire.Number(field), protowire.VarintType) + + // buf length check can prevent panic at PutUvarint, but it will make + // marshaller a bit slower. + i := binary.PutUvarint(buf, uint64(prefix)) + const boolTrueValue = 0x1 + buf[i] = boolTrueValue + + return i + 1 +} + +func BoolSize(field int, v bool) int { + if !v { + return 0 + } + const boolLength = 1 + return protowire.SizeGroup(protowire.Number(field), boolLength) +} + +func UInt64Marshal(field int, buf []byte, v uint64) int { + if v == 0 { + return 0 + } + + prefix := protowire.EncodeTag(protowire.Number(field), protowire.VarintType) + + // buf length check can prevent panic at PutUvarint, but it will make + // marshaller a bit slower. + i := binary.PutUvarint(buf, uint64(prefix)) + i += binary.PutUvarint(buf[i:], v) + + return i +} + +func UInt64Size(field int, v uint64) int { + if v == 0 { + return 0 + } + return protowire.SizeGroup(protowire.Number(field), protowire.SizeVarint(v)) +} + +func Int64Marshal(field int, buf []byte, v int64) int { + return UInt64Marshal(field, buf, uint64(v)) +} + +func Int64Size(field int, v int64) int { + return UInt64Size(field, uint64(v)) +} + +func UInt32Marshal(field int, buf []byte, v uint32) int { + return UInt64Marshal(field, buf, uint64(v)) +} + +func UInt32Size(field int, v uint32) int { + return UInt64Size(field, uint64(v)) +} + +func Int32Marshal(field int, buf []byte, v int32) int { + return UInt64Marshal(field, buf, uint64(v)) +} + +func Int32Size(field int, v int32) int { + return UInt64Size(field, uint64(v)) +} + +func EnumMarshal(field int, buf []byte, v int32) int { + return UInt64Marshal(field, buf, uint64(v)) +} + +func EnumSize(field int, v int32) int { + return UInt64Size(field, uint64(v)) +} + +func RepeatedBytesMarshal(field int, buf []byte, v [][]byte) int { + var offset int + + for i := range v { + offset += bytesMarshalNoCheck(field, buf[offset:], v[i]) + } + + return offset +} + +func RepeatedBytesSize(field int, v [][]byte) (size int) { + for i := range v { + size += bytesSizeNoCheck(field, v[i]) + } + + return size +} + +func RepeatedStringMarshal(field int, buf []byte, v []string) int { + var offset int + + for i := range v { + offset += bytesMarshalNoCheck(field, buf[offset:], v[i]) + } + + return offset +} + +func RepeatedStringSize(field int, v []string) (size int) { + for i := range v { + size += bytesSizeNoCheck(field, v[i]) + } + + return size +} + +func repeatedUIntSize[T ~uint64 | ~int64 | ~uint32 | ~int32](field int, v []T) (size, arraySize int) { + if len(v) == 0 { + return 0, 0 + } + + for i := range v { + arraySize += protowire.SizeVarint(uint64(v[i])) + } + + size = protowire.SizeGroup(protowire.Number(field), protowire.SizeBytes(arraySize)) + + return +} + +func repeatedUIntMarshal[T ~uint64 | ~int64 | ~uint32 | ~int32](field int, buf []byte, v []T) int { + if len(v) == 0 { + return 0 + } + + prefix := protowire.EncodeTag(protowire.Number(field), protowire.BytesType) + offset := binary.PutUvarint(buf, uint64(prefix)) + + _, arrSize := repeatedUIntSize(field, v) + offset += binary.PutUvarint(buf[offset:], uint64(arrSize)) + for i := range v { + offset += binary.PutUvarint(buf[offset:], uint64(v[i])) + } + + return offset +} + +func RepeatedUInt64Marshal(field int, buf []byte, v []uint64) int { + return repeatedUIntMarshal(field, buf, v) +} + +func RepeatedUInt64Size(field int, v []uint64) (size, arraySize int) { + return repeatedUIntSize(field, v) +} + +func RepeatedInt64Marshal(field int, buf []byte, v []int64) int { + return repeatedUIntMarshal(field, buf, v) +} + +func RepeatedInt64Size(field int, v []int64) (size, arraySize int) { + return repeatedUIntSize(field, v) +} + +func RepeatedUInt32Marshal(field int, buf []byte, v []uint32) int { + return repeatedUIntMarshal(field, buf, v) +} + +func RepeatedUInt32Size(field int, v []uint32) (size, arraySize int) { + return repeatedUIntSize(field, v) +} + +func RepeatedInt32Marshal(field int, buf []byte, v []int32) int { + return repeatedUIntMarshal(field, buf, v) +} + +func RepeatedInt32Size(field int, v []int32) (size, arraySize int) { + return repeatedUIntSize(field, v) +} + +// VarUIntSize returns length of varint byte sequence for uint64 value 'x'. +func VarUIntSize(x uint64) int { + return (bits.Len64(x|1) + 6) / 7 +} + +type ptrStableMarshaler[T any] interface { + stableMarshaler + ~*T +} + +func NestedStructureMarshal[T any, M ptrStableMarshaler[T]](field int64, buf []byte, v M) int { + if v == nil { + return 0 + } + + return NestedStructureMarshalUnchecked(field, buf, v) +} + +func NestedStructureMarshalUnchecked[T stableMarshaler](field int64, buf []byte, v T) int { + n := v.StableSize() + prefix := protowire.EncodeTag(protowire.Number(field), protowire.BytesType) + offset := binary.PutUvarint(buf, prefix) + offset += binary.PutUvarint(buf[offset:], uint64(n)) + v.StableMarshal(buf[offset:]) + + return offset + n +} + +// NestedStructureSetMarshalData calculates offset for field in parentData +// and calls SetMarshalData for nested structure. +// +// Returns marshalled data length of nested structure. +func NestedStructureSetMarshalData[T any, M setMarshalData[T]](field int64, parentData []byte, v M) int { + if v == nil { + return 0 + } + + if parentData == nil { + v.SetMarshalData(nil) + return 0 + } + + n := v.StableSize() + buf := make([]byte, binary.MaxVarintLen64) + prefix := protowire.EncodeTag(protowire.Number(field), protowire.BytesType) + offset := binary.PutUvarint(buf, prefix) + offset += binary.PutUvarint(buf, uint64(n)) + + v.SetMarshalData(parentData[offset : offset+n]) + + return offset + n +} + +func NestedStructureSize[T any, M ptrStableMarshaler[T]](field int64, v M) (size int) { + if v == nil { + return 0 + } + + return NestedStructureSizeUnchecked(field, v) +} + +func NestedStructureSizeUnchecked[T stableMarshaler](field int64, v T) int { + n := v.StableSize() + return protowire.SizeGroup(protowire.Number(field), protowire.SizeBytes(n)) +} + +func Fixed64Marshal(field int, buf []byte, v uint64) int { + if v == 0 { + return 0 + } + + prefix := protowire.EncodeTag(protowire.Number(field), protowire.Fixed64Type) + + // buf length check can prevent panic at PutUvarint, but it will make + // marshaller a bit slower. + i := binary.PutUvarint(buf, uint64(prefix)) + binary.LittleEndian.PutUint64(buf[i:], v) + + return i + 8 +} + +func Fixed64Size(fNum int, v uint64) int { + if v == 0 { + return 0 + } + return protowire.SizeGroup(protowire.Number(fNum), protowire.SizeFixed64()) +} + +func Float64Marshal(field int, buf []byte, v float64) int { + if v == 0 { + return 0 + } + + prefix := protowire.EncodeTag(protowire.Number(field), protowire.Fixed64Type) + + i := binary.PutUvarint(buf, uint64(prefix)) + binary.LittleEndian.PutUint64(buf[i:], math.Float64bits(v)) + + return i + 8 +} + +func Float64Size(fNum int, v float64) int { + if v == 0 { + return 0 + } + return protowire.SizeGroup(protowire.Number(fNum), protowire.SizeFixed64()) +} + +// Fixed32Marshal encodes uint32 value to Protocol Buffers fixed32 field with specified number, +// and writes it to specified buffer. Returns number of bytes written. +// +// Panics if the buffer is undersized. +func Fixed32Marshal(field int, buf []byte, v uint32) int { + if v == 0 { + return 0 + } + + prefix := protowire.EncodeTag(protowire.Number(field), protowire.Fixed32Type) + + // buf length check can prevent panic at PutUvarint, but it will make + // marshaller a bit slower. + i := binary.PutUvarint(buf, uint64(prefix)) + binary.LittleEndian.PutUint32(buf[i:], v) + + return i + 4 +} + +// Fixed32Size returns number of bytes required to encode uint32 value to Protocol Buffers fixed32 field +// with specified number. +func Fixed32Size(fNum int, v uint32) int { + if v == 0 { + return 0 + } + return protowire.SizeGroup(protowire.Number(fNum), protowire.SizeFixed32()) +} diff --git a/pkg/api/util/proto/marshal_test.go b/pkg/api/util/proto/marshal_test.go new file mode 100644 index 000000000..af1e09ec9 --- /dev/null +++ b/pkg/api/util/proto/marshal_test.go @@ -0,0 +1,769 @@ +package proto_test + +import ( + "math" + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/util/proto" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/util/proto/test" + "github.com/stretchr/testify/require" + goproto "google.golang.org/protobuf/proto" +) + +type SomeEnum int32 + +type stablePrimitives struct { + FieldA []byte + FieldB string + FieldC bool + FieldD int32 + FieldE uint32 + FieldF int64 + FieldG uint64 + FieldH SomeEnum + FieldI uint64 // fixed64 + FieldJ float64 + FieldK uint32 // fixed32 +} + +type stableRepPrimitives struct { + FieldA [][]byte + FieldB []string + FieldC []int32 + FieldD []uint32 + FieldE []int64 + FieldF []uint64 +} + +const ( + ENUM_UNKNOWN SomeEnum = 0 + ENUM_POSITIVE SomeEnum = 1 + ENUM_NEGATIVE SomeEnum = -1 +) + +func (s *stablePrimitives) stableMarshal(buf []byte, wrongField bool) ([]byte, error) { + if s == nil { + return []byte{}, nil + } + + if buf == nil { + buf = make([]byte, s.stableSize()) + } + + var i, offset, fieldNum int + + fieldNum = 1 + if wrongField { + fieldNum++ + } + i += proto.BytesMarshal(fieldNum, buf, s.FieldA) + + fieldNum = 2 + if wrongField { + fieldNum++ + } + i += proto.StringMarshal(fieldNum, buf, s.FieldB) + + fieldNum = 200 + if wrongField { + fieldNum++ + } + i += proto.BoolMarshal(fieldNum, buf, s.FieldC) + + fieldNum = 201 + if wrongField { + fieldNum++ + } + i += proto.Int32Marshal(fieldNum, buf, s.FieldD) + + fieldNum = 202 + if wrongField { + fieldNum++ + } + i += proto.UInt32Marshal(fieldNum, buf, s.FieldE) + + fieldNum = 203 + if wrongField { + fieldNum++ + } + i += proto.Int64Marshal(fieldNum, buf, s.FieldF) + + fieldNum = 204 + if wrongField { + fieldNum++ + } + i += proto.UInt64Marshal(fieldNum, buf, s.FieldG) + + fieldNum = 205 + if wrongField { + fieldNum++ + } + i += proto.Fixed64Marshal(fieldNum, buf, s.FieldI) + + fieldNum = 206 + if wrongField { + fieldNum++ + } + i += proto.Float64Marshal(fieldNum, buf, s.FieldJ) + + fieldNum = 207 + if wrongField { + fieldNum++ + } + + offset = proto.Fixed32Marshal(fieldNum, buf, s.FieldK) + + i += offset + + fieldNum = 300 + if wrongField { + fieldNum++ + } + i += proto.EnumMarshal(fieldNum, buf, int32(s.FieldH)) + + return buf, nil +} + +func (s *stablePrimitives) stableSize() int { + return proto.BytesSize(1, s.FieldA) + + proto.StringSize(2, s.FieldB) + + proto.BoolSize(200, s.FieldC) + + proto.Int32Size(201, s.FieldD) + + proto.UInt32Size(202, s.FieldE) + + proto.Int64Size(203, s.FieldF) + + proto.UInt64Size(204, s.FieldG) + + proto.Fixed64Size(205, s.FieldI) + + proto.Float64Size(206, s.FieldJ) + + proto.Fixed32Size(207, s.FieldK) + + proto.EnumSize(300, int32(s.FieldH)) +} + +func (s *stableRepPrimitives) stableMarshal(buf []byte, wrongField bool) ([]byte, error) { + if s == nil { + return []byte{}, nil + } + + if buf == nil { + buf = make([]byte, s.stableSize()) + } + + var i, fieldNum int + + fieldNum = 1 + if wrongField { + fieldNum++ + } + i += proto.RepeatedBytesMarshal(fieldNum, buf, s.FieldA) + + fieldNum = 2 + if wrongField { + fieldNum++ + } + i += proto.RepeatedStringMarshal(fieldNum, buf, s.FieldB) + + fieldNum = 3 + if wrongField { + fieldNum++ + } + i += proto.RepeatedInt32Marshal(fieldNum, buf, s.FieldC) + + fieldNum = 4 + if wrongField { + fieldNum++ + } + i += proto.RepeatedUInt32Marshal(fieldNum, buf, s.FieldD) + + fieldNum = 5 + if wrongField { + fieldNum++ + } + i += proto.RepeatedInt64Marshal(fieldNum, buf, s.FieldE) + + fieldNum = 6 + if wrongField { + fieldNum++ + } + i += proto.RepeatedUInt64Marshal(fieldNum, buf, s.FieldF) + + return buf, nil +} + +func (s *stableRepPrimitives) stableSize() int { + f1 := proto.RepeatedBytesSize(1, s.FieldA) + f2 := proto.RepeatedStringSize(2, s.FieldB) + f3, _ := proto.RepeatedInt32Size(3, s.FieldC) + f4, _ := proto.RepeatedUInt32Size(4, s.FieldD) + f5, _ := proto.RepeatedInt64Size(5, s.FieldE) + f6, _ := proto.RepeatedUInt64Size(6, s.FieldF) + + return f1 + f2 + f3 + f4 + f5 + f6 +} + +func TestBytesMarshal(t *testing.T) { + t.Run("not empty", func(t *testing.T) { + data := []byte("Hello World") + testBytesMarshal(t, data, false) + testBytesMarshal(t, data, true) + }) + + t.Run("empty", func(t *testing.T) { + testBytesMarshal(t, []byte{}, false) + }) + + t.Run("nil", func(t *testing.T) { + testBytesMarshal(t, nil, false) + }) +} + +func TestStringMarshal(t *testing.T) { + t.Run("not empty", func(t *testing.T) { + data := "Hello World" + testStringMarshal(t, data, false) + testStringMarshal(t, data, true) + }) + + t.Run("empty", func(t *testing.T) { + testStringMarshal(t, "", false) + }) +} + +func TestBoolMarshal(t *testing.T) { + t.Run("true", func(t *testing.T) { + testBoolMarshal(t, true, false) + testBoolMarshal(t, true, true) + }) + + t.Run("false", func(t *testing.T) { + testBoolMarshal(t, false, false) + }) +} + +func TestInt32Marshal(t *testing.T) { + t.Run("zero", func(t *testing.T) { + testInt32Marshal(t, 0, false) + }) + + t.Run("positive", func(t *testing.T) { + testInt32Marshal(t, math.MaxInt32, false) + testInt32Marshal(t, math.MaxInt32, true) + }) + + t.Run("negative", func(t *testing.T) { + testInt32Marshal(t, math.MinInt32, false) + testInt32Marshal(t, math.MinInt32, true) + }) +} + +func TestUInt32Marshal(t *testing.T) { + t.Run("zero", func(t *testing.T) { + testUInt32Marshal(t, 0, false) + }) + + t.Run("non zero", func(t *testing.T) { + testUInt32Marshal(t, math.MaxUint32, false) + testUInt32Marshal(t, math.MaxUint32, true) + }) +} + +func TestInt64Marshal(t *testing.T) { + t.Run("zero", func(t *testing.T) { + testInt32Marshal(t, 0, false) + }) + + t.Run("positive", func(t *testing.T) { + testInt64Marshal(t, math.MaxInt64, false) + testInt64Marshal(t, math.MaxInt64, true) + }) + + t.Run("negative", func(t *testing.T) { + testInt64Marshal(t, math.MinInt64, false) + testInt64Marshal(t, math.MinInt64, true) + }) +} + +func TestUInt64Marshal(t *testing.T) { + t.Run("zero", func(t *testing.T) { + testUInt64Marshal(t, 0, false) + }) + + t.Run("non zero", func(t *testing.T) { + testUInt64Marshal(t, math.MaxUint64, false) + testUInt64Marshal(t, math.MaxUint64, true) + }) +} + +func TestEnumMarshal(t *testing.T) { + testEnumMarshal(t, ENUM_UNKNOWN, false) + testEnumMarshal(t, ENUM_POSITIVE, false) + testEnumMarshal(t, ENUM_POSITIVE, true) + testEnumMarshal(t, ENUM_NEGATIVE, false) + testEnumMarshal(t, ENUM_NEGATIVE, true) +} + +func TestRepeatedBytesMarshal(t *testing.T) { + t.Run("not empty", func(t *testing.T) { + data := [][]byte{[]byte("One"), []byte("Two"), []byte("Three")} + testRepeatedBytesMarshal(t, data, false) + testRepeatedBytesMarshal(t, data, true) + }) + + t.Run("empty", func(t *testing.T) { + testRepeatedBytesMarshal(t, [][]byte{}, false) + }) + + t.Run("empty element", func(t *testing.T) { + testRepeatedBytesMarshal(t, [][]byte{{1}, {}}, false) + }) + + t.Run("nil", func(t *testing.T) { + testRepeatedBytesMarshal(t, nil, false) + }) +} + +func TestRepeatedStringMarshal(t *testing.T) { + t.Run("not empty", func(t *testing.T) { + data := []string{"One", "Two", "Three"} + testRepeatedStringMarshal(t, data, false) + testRepeatedStringMarshal(t, data, true) + }) + + t.Run("empty element", func(t *testing.T) { + testRepeatedStringMarshal(t, []string{""}, false) + }) + + t.Run("empty", func(t *testing.T) { + testRepeatedStringMarshal(t, []string{}, false) + }) + + t.Run("nil", func(t *testing.T) { + testRepeatedStringMarshal(t, nil, false) + }) +} + +func TestRepeatedInt32Marshal(t *testing.T) { + t.Run("not empty", func(t *testing.T) { + data := []int32{-1, 0, 1, 2, 3, 4, 5} + testRepeatedInt32Marshal(t, data, false) + testRepeatedInt32Marshal(t, data, true) + }) + + t.Run("empty", func(t *testing.T) { + testRepeatedInt32Marshal(t, []int32{}, false) + }) + + t.Run("nil", func(t *testing.T) { + testRepeatedInt32Marshal(t, nil, false) + }) +} + +func TestRepeatedUInt32Marshal(t *testing.T) { + t.Run("not empty", func(t *testing.T) { + data := []uint32{0, 1, 2, 3, 4, 5} + testRepeatedUInt32Marshal(t, data, false) + testRepeatedUInt32Marshal(t, data, true) + }) + + t.Run("empty", func(t *testing.T) { + testRepeatedUInt32Marshal(t, []uint32{}, false) + }) + + t.Run("nil", func(t *testing.T) { + testRepeatedUInt32Marshal(t, nil, false) + }) +} + +func TestRepeatedInt64Marshal(t *testing.T) { + t.Run("not empty", func(t *testing.T) { + data := []int64{-1, 0, 1, 2, 3, 4, 5} + testRepeatedInt64Marshal(t, data, false) + testRepeatedInt64Marshal(t, data, true) + }) + + t.Run("empty", func(t *testing.T) { + testRepeatedInt64Marshal(t, []int64{}, false) + }) + + t.Run("nil", func(t *testing.T) { + testRepeatedInt64Marshal(t, nil, false) + }) +} + +func TestRepeatedUInt64Marshal(t *testing.T) { + t.Run("not empty", func(t *testing.T) { + data := []uint64{0, 1, 2, 3, 4, 5} + testRepeatedUInt64Marshal(t, data, false) + testRepeatedUInt64Marshal(t, data, true) + }) + + t.Run("empty", func(t *testing.T) { + testRepeatedUInt64Marshal(t, []uint64{}, false) + }) + + t.Run("nil", func(t *testing.T) { + testRepeatedUInt64Marshal(t, nil, false) + }) +} + +func TestFixed64Marshal(t *testing.T) { + t.Run("zero", func(t *testing.T) { + testFixed64Marshal(t, 0, false) + }) + + t.Run("non zero", func(t *testing.T) { + testFixed64Marshal(t, math.MaxUint64, false) + testFixed64Marshal(t, math.MaxUint64, true) + }) +} + +func TestFloat64Marshal(t *testing.T) { + t.Run("zero", func(t *testing.T) { + testFloat64Marshal(t, 0, false) + }) + + t.Run("non zero", func(t *testing.T) { + f := math.Float64frombits(12345677890) + + testFloat64Marshal(t, f, false) + testFloat64Marshal(t, f, true) + }) +} + +func TestFixed32Marshal(t *testing.T) { + t.Run("zero", func(t *testing.T) { + testFixed32Marshal(t, 0, false) + }) + + t.Run("non zero", func(t *testing.T) { + testFixed32Marshal(t, math.MaxUint32, false) + testFixed32Marshal(t, math.MaxUint32, true) + }) +} + +func testMarshal(t *testing.T, c stablePrimitives, tr test.Primitives, wrongField bool) *test.Primitives { + var ( + wire []byte + err error + ) + wire, err = c.stableMarshal(nil, wrongField) + require.NoError(t, err) + + wireGen, err := goproto.Marshal(&tr) + require.NoError(t, err) + + if !wrongField { + // we can check equality because single field cannot be unstable marshalled + require.Equal(t, wireGen, wire) + } else { + require.NotEqual(t, wireGen, wire) + } + + result := new(test.Primitives) + err = goproto.Unmarshal(wire, result) + require.NoError(t, err) + + return result +} + +func testBytesMarshal(t *testing.T, data []byte, wrongField bool) { + var ( + custom = stablePrimitives{FieldA: data} + transport = test.Primitives{FieldA: data} + ) + + result := testMarshal(t, custom, transport, wrongField) + + if !wrongField { + require.Len(t, result.FieldA, len(data)) + if len(data) > 0 { + require.Equal(t, data, result.FieldA) + } + } else { + require.Len(t, result.FieldA, 0) + } +} + +func testStringMarshal(t *testing.T, s string, wrongField bool) { + var ( + custom = stablePrimitives{FieldB: s} + transport = test.Primitives{FieldB: s} + ) + + result := testMarshal(t, custom, transport, wrongField) + + if !wrongField { + require.Len(t, result.FieldB, len(s)) + if len(s) > 0 { + require.Equal(t, s, result.FieldB) + } + } else { + require.Len(t, result.FieldB, 0) + } +} + +func testBoolMarshal(t *testing.T, b bool, wrongField bool) { + var ( + custom = stablePrimitives{FieldC: b} + transport = test.Primitives{FieldC: b} + ) + + result := testMarshal(t, custom, transport, wrongField) + + if !wrongField { + require.Equal(t, b, result.FieldC) + } else { + require.False(t, false, result.FieldC) + } +} + +func testInt32Marshal(t *testing.T, n int32, wrongField bool) { + var ( + custom = stablePrimitives{FieldD: n} + transport = test.Primitives{FieldD: n} + ) + + result := testMarshal(t, custom, transport, wrongField) + + if !wrongField { + require.Equal(t, n, result.FieldD) + } else { + require.EqualValues(t, 0, result.FieldD) + } +} + +func testUInt32Marshal(t *testing.T, n uint32, wrongField bool) { + var ( + custom = stablePrimitives{FieldE: n} + transport = test.Primitives{FieldE: n} + ) + + result := testMarshal(t, custom, transport, wrongField) + + if !wrongField { + require.Equal(t, n, result.FieldE) + } else { + require.EqualValues(t, 0, result.FieldE) + } +} + +func testInt64Marshal(t *testing.T, n int64, wrongField bool) { + var ( + custom = stablePrimitives{FieldF: n} + transport = test.Primitives{FieldF: n} + ) + + result := testMarshal(t, custom, transport, wrongField) + + if !wrongField { + require.Equal(t, n, result.FieldF) + } else { + require.EqualValues(t, 0, result.FieldF) + } +} + +func testUInt64Marshal(t *testing.T, n uint64, wrongField bool) { + var ( + custom = stablePrimitives{FieldG: n} + transport = test.Primitives{FieldG: n} + ) + + result := testMarshal(t, custom, transport, wrongField) + + if !wrongField { + require.Equal(t, n, result.FieldG) + } else { + require.EqualValues(t, 0, result.FieldG) + } +} + +func testFloat64Marshal(t *testing.T, n float64, wrongField bool) { + var ( + custom = stablePrimitives{FieldJ: n} + transport = test.Primitives{FieldJ: n} + ) + + result := testMarshal(t, custom, transport, wrongField) + + if !wrongField { + require.Equal(t, n, result.FieldJ) + } else { + require.EqualValues(t, 0, result.FieldJ) + } +} + +func testEnumMarshal(t *testing.T, e SomeEnum, wrongField bool) { + var ( + custom = stablePrimitives{FieldH: e} + transport = test.Primitives{FieldH: test.Primitives_SomeEnum(e)} + ) + + result := testMarshal(t, custom, transport, wrongField) + + if !wrongField { + require.EqualValues(t, custom.FieldH, result.FieldH) + } else { + require.EqualValues(t, 0, result.FieldH) + } +} + +func testRepMarshal(t *testing.T, c stableRepPrimitives, tr test.RepPrimitives, wrongField bool) *test.RepPrimitives { + var ( + wire []byte + err error + ) + wire, err = c.stableMarshal(nil, wrongField) + require.NoError(t, err) + + wireGen, err := goproto.Marshal(&tr) + require.NoError(t, err) + + if !wrongField { + // we can check equality because single field cannot be unstable marshalled + require.Equal(t, wireGen, wire) + } else { + require.NotEqual(t, wireGen, wire) + } + + result := new(test.RepPrimitives) + err = goproto.Unmarshal(wire, result) + require.NoError(t, err) + + return result +} + +func testRepeatedBytesMarshal(t *testing.T, data [][]byte, wrongField bool) { + var ( + custom = stableRepPrimitives{FieldA: data} + transport = test.RepPrimitives{FieldA: data} + ) + + result := testRepMarshal(t, custom, transport, wrongField) + + if !wrongField { + require.Len(t, result.FieldA, len(data)) + if len(data) > 0 { + require.Equal(t, data, result.FieldA) + } + } else { + require.Len(t, result.FieldA, 0) + } +} + +func testRepeatedStringMarshal(t *testing.T, s []string, wrongField bool) { + var ( + custom = stableRepPrimitives{FieldB: s} + transport = test.RepPrimitives{FieldB: s} + ) + + result := testRepMarshal(t, custom, transport, wrongField) + + if !wrongField { + require.Len(t, result.FieldB, len(s)) + if len(s) > 0 { + require.Equal(t, s, result.FieldB) + } + } else { + require.Len(t, result.FieldB, 0) + } +} + +func testRepeatedInt32Marshal(t *testing.T, n []int32, wrongField bool) { + var ( + custom = stableRepPrimitives{FieldC: n} + transport = test.RepPrimitives{FieldC: n} + ) + + result := testRepMarshal(t, custom, transport, wrongField) + + if !wrongField { + require.Len(t, result.FieldC, len(n)) + if len(n) > 0 { + require.Equal(t, n, result.FieldC) + } + } else { + require.Len(t, result.FieldC, 0) + } +} + +func testRepeatedUInt32Marshal(t *testing.T, n []uint32, wrongField bool) { + var ( + custom = stableRepPrimitives{FieldD: n} + transport = test.RepPrimitives{FieldD: n} + ) + + result := testRepMarshal(t, custom, transport, wrongField) + + if !wrongField { + require.Len(t, result.FieldD, len(n)) + if len(n) > 0 { + require.Equal(t, n, result.FieldD) + } + } else { + require.Len(t, result.FieldD, 0) + } +} + +func testRepeatedInt64Marshal(t *testing.T, n []int64, wrongField bool) { + var ( + custom = stableRepPrimitives{FieldE: n} + transport = test.RepPrimitives{FieldE: n} + ) + + result := testRepMarshal(t, custom, transport, wrongField) + + if !wrongField { + require.Len(t, result.FieldE, len(n)) + if len(n) > 0 { + require.Equal(t, n, result.FieldE) + } + } else { + require.Len(t, result.FieldE, 0) + } +} + +func testRepeatedUInt64Marshal(t *testing.T, n []uint64, wrongField bool) { + var ( + custom = stableRepPrimitives{FieldF: n} + transport = test.RepPrimitives{FieldF: n} + ) + + result := testRepMarshal(t, custom, transport, wrongField) + + if !wrongField { + require.Len(t, result.FieldF, len(n)) + if len(n) > 0 { + require.Equal(t, n, result.FieldF) + } + } else { + require.Len(t, result.FieldF, 0) + } +} + +func testFixed64Marshal(t *testing.T, n uint64, wrongField bool) { + var ( + custom = stablePrimitives{FieldI: n} + transport = test.Primitives{FieldI: n} + ) + + result := testMarshal(t, custom, transport, wrongField) + + if !wrongField { + require.Equal(t, n, result.FieldI) + } else { + require.EqualValues(t, 0, result.FieldI) + } +} + +func testFixed32Marshal(t *testing.T, n uint32, wrongField bool) { + var ( + custom = stablePrimitives{FieldK: n} + transport = test.Primitives{FieldK: n} + ) + + result := testMarshal(t, custom, transport, wrongField) + + if !wrongField { + require.Equal(t, n, result.FieldK) + } else { + require.EqualValues(t, 0, result.FieldK) + } +} diff --git a/pkg/api/util/proto/test/test.pb.go b/pkg/api/util/proto/test/test.pb.go new file mode 100644 index 000000000..0b9f43da2 --- /dev/null +++ b/pkg/api/util/proto/test/test.pb.go @@ -0,0 +1,408 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.33.0 +// protoc v4.25.3 +// source: util/proto/test/test.proto + +package test + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type Primitives_SomeEnum int32 + +const ( + Primitives_UNKNOWN Primitives_SomeEnum = 0 + Primitives_POSITIVE Primitives_SomeEnum = 1 + Primitives_NEGATIVE Primitives_SomeEnum = -1 +) + +// Enum value maps for Primitives_SomeEnum. +var ( + Primitives_SomeEnum_name = map[int32]string{ + 0: "UNKNOWN", + 1: "POSITIVE", + -1: "NEGATIVE", + } + Primitives_SomeEnum_value = map[string]int32{ + "UNKNOWN": 0, + "POSITIVE": 1, + "NEGATIVE": -1, + } +) + +func (x Primitives_SomeEnum) Enum() *Primitives_SomeEnum { + p := new(Primitives_SomeEnum) + *p = x + return p +} + +func (x Primitives_SomeEnum) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (Primitives_SomeEnum) Descriptor() protoreflect.EnumDescriptor { + return file_util_proto_test_test_proto_enumTypes[0].Descriptor() +} + +func (Primitives_SomeEnum) Type() protoreflect.EnumType { + return &file_util_proto_test_test_proto_enumTypes[0] +} + +func (x Primitives_SomeEnum) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use Primitives_SomeEnum.Descriptor instead. +func (Primitives_SomeEnum) EnumDescriptor() ([]byte, []int) { + return file_util_proto_test_test_proto_rawDescGZIP(), []int{0, 0} +} + +type Primitives struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + FieldA []byte `protobuf:"bytes,1,opt,name=field_a,json=fieldA,proto3" json:"field_a,omitempty"` + FieldB string `protobuf:"bytes,2,opt,name=field_b,json=fieldB,proto3" json:"field_b,omitempty"` + FieldC bool `protobuf:"varint,200,opt,name=field_c,json=fieldC,proto3" json:"field_c,omitempty"` + FieldD int32 `protobuf:"varint,201,opt,name=field_d,json=fieldD,proto3" json:"field_d,omitempty"` + FieldE uint32 `protobuf:"varint,202,opt,name=field_e,json=fieldE,proto3" json:"field_e,omitempty"` + FieldF int64 `protobuf:"varint,203,opt,name=field_f,json=fieldF,proto3" json:"field_f,omitempty"` + FieldG uint64 `protobuf:"varint,204,opt,name=field_g,json=fieldG,proto3" json:"field_g,omitempty"` + FieldI uint64 `protobuf:"fixed64,205,opt,name=field_i,json=fieldI,proto3" json:"field_i,omitempty"` + FieldJ float64 `protobuf:"fixed64,206,opt,name=field_j,json=fieldJ,proto3" json:"field_j,omitempty"` + FieldK uint32 `protobuf:"fixed32,207,opt,name=field_k,json=fieldK,proto3" json:"field_k,omitempty"` + FieldH Primitives_SomeEnum `protobuf:"varint,300,opt,name=field_h,json=fieldH,proto3,enum=test.Primitives_SomeEnum" json:"field_h,omitempty"` +} + +func (x *Primitives) Reset() { + *x = Primitives{} + if protoimpl.UnsafeEnabled { + mi := &file_util_proto_test_test_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Primitives) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Primitives) ProtoMessage() {} + +func (x *Primitives) ProtoReflect() protoreflect.Message { + mi := &file_util_proto_test_test_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Primitives.ProtoReflect.Descriptor instead. +func (*Primitives) Descriptor() ([]byte, []int) { + return file_util_proto_test_test_proto_rawDescGZIP(), []int{0} +} + +func (x *Primitives) GetFieldA() []byte { + if x != nil { + return x.FieldA + } + return nil +} + +func (x *Primitives) GetFieldB() string { + if x != nil { + return x.FieldB + } + return "" +} + +func (x *Primitives) GetFieldC() bool { + if x != nil { + return x.FieldC + } + return false +} + +func (x *Primitives) GetFieldD() int32 { + if x != nil { + return x.FieldD + } + return 0 +} + +func (x *Primitives) GetFieldE() uint32 { + if x != nil { + return x.FieldE + } + return 0 +} + +func (x *Primitives) GetFieldF() int64 { + if x != nil { + return x.FieldF + } + return 0 +} + +func (x *Primitives) GetFieldG() uint64 { + if x != nil { + return x.FieldG + } + return 0 +} + +func (x *Primitives) GetFieldI() uint64 { + if x != nil { + return x.FieldI + } + return 0 +} + +func (x *Primitives) GetFieldJ() float64 { + if x != nil { + return x.FieldJ + } + return 0 +} + +func (x *Primitives) GetFieldK() uint32 { + if x != nil { + return x.FieldK + } + return 0 +} + +func (x *Primitives) GetFieldH() Primitives_SomeEnum { + if x != nil { + return x.FieldH + } + return Primitives_UNKNOWN +} + +type RepPrimitives struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + FieldA [][]byte `protobuf:"bytes,1,rep,name=field_a,json=fieldA,proto3" json:"field_a,omitempty"` + FieldB []string `protobuf:"bytes,2,rep,name=field_b,json=fieldB,proto3" json:"field_b,omitempty"` + FieldC []int32 `protobuf:"varint,3,rep,packed,name=field_c,json=fieldC,proto3" json:"field_c,omitempty"` + FieldD []uint32 `protobuf:"varint,4,rep,packed,name=field_d,json=fieldD,proto3" json:"field_d,omitempty"` + FieldE []int64 `protobuf:"varint,5,rep,packed,name=field_e,json=fieldE,proto3" json:"field_e,omitempty"` + FieldF []uint64 `protobuf:"varint,6,rep,packed,name=field_f,json=fieldF,proto3" json:"field_f,omitempty"` +} + +func (x *RepPrimitives) Reset() { + *x = RepPrimitives{} + if protoimpl.UnsafeEnabled { + mi := &file_util_proto_test_test_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RepPrimitives) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RepPrimitives) ProtoMessage() {} + +func (x *RepPrimitives) ProtoReflect() protoreflect.Message { + mi := &file_util_proto_test_test_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RepPrimitives.ProtoReflect.Descriptor instead. +func (*RepPrimitives) Descriptor() ([]byte, []int) { + return file_util_proto_test_test_proto_rawDescGZIP(), []int{1} +} + +func (x *RepPrimitives) GetFieldA() [][]byte { + if x != nil { + return x.FieldA + } + return nil +} + +func (x *RepPrimitives) GetFieldB() []string { + if x != nil { + return x.FieldB + } + return nil +} + +func (x *RepPrimitives) GetFieldC() []int32 { + if x != nil { + return x.FieldC + } + return nil +} + +func (x *RepPrimitives) GetFieldD() []uint32 { + if x != nil { + return x.FieldD + } + return nil +} + +func (x *RepPrimitives) GetFieldE() []int64 { + if x != nil { + return x.FieldE + } + return nil +} + +func (x *RepPrimitives) GetFieldF() []uint64 { + if x != nil { + return x.FieldF + } + return nil +} + +var File_util_proto_test_test_proto protoreflect.FileDescriptor + +var file_util_proto_test_test_proto_rawDesc = []byte{ + 0x0a, 0x1a, 0x75, 0x74, 0x69, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x74, 0x65, 0x73, + 0x74, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x04, 0x74, 0x65, + 0x73, 0x74, 0x22, 0x81, 0x03, 0x0a, 0x0a, 0x50, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, + 0x73, 0x12, 0x17, 0x0a, 0x07, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x61, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x41, 0x12, 0x17, 0x0a, 0x07, 0x66, 0x69, + 0x65, 0x6c, 0x64, 0x5f, 0x62, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x66, 0x69, 0x65, + 0x6c, 0x64, 0x42, 0x12, 0x18, 0x0a, 0x07, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x63, 0x18, 0xc8, + 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x43, 0x12, 0x18, 0x0a, + 0x07, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x64, 0x18, 0xc9, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, + 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x44, 0x12, 0x18, 0x0a, 0x07, 0x66, 0x69, 0x65, 0x6c, 0x64, + 0x5f, 0x65, 0x18, 0xca, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, + 0x45, 0x12, 0x18, 0x0a, 0x07, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x66, 0x18, 0xcb, 0x01, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x46, 0x12, 0x18, 0x0a, 0x07, 0x66, + 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x67, 0x18, 0xcc, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x66, + 0x69, 0x65, 0x6c, 0x64, 0x47, 0x12, 0x18, 0x0a, 0x07, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x69, + 0x18, 0xcd, 0x01, 0x20, 0x01, 0x28, 0x06, 0x52, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x49, 0x12, + 0x18, 0x0a, 0x07, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6a, 0x18, 0xce, 0x01, 0x20, 0x01, 0x28, + 0x01, 0x52, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x4a, 0x12, 0x18, 0x0a, 0x07, 0x66, 0x69, 0x65, + 0x6c, 0x64, 0x5f, 0x6b, 0x18, 0xcf, 0x01, 0x20, 0x01, 0x28, 0x07, 0x52, 0x06, 0x66, 0x69, 0x65, + 0x6c, 0x64, 0x4b, 0x12, 0x33, 0x0a, 0x07, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x68, 0x18, 0xac, + 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x50, 0x72, 0x69, + 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6f, 0x6d, 0x65, 0x45, 0x6e, 0x75, 0x6d, + 0x52, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x48, 0x22, 0x3c, 0x0a, 0x08, 0x53, 0x6f, 0x6d, 0x65, + 0x45, 0x6e, 0x75, 0x6d, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, + 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, 0x56, 0x45, 0x10, 0x01, 0x12, + 0x15, 0x0a, 0x08, 0x4e, 0x45, 0x47, 0x41, 0x54, 0x49, 0x56, 0x45, 0x10, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x22, 0xa5, 0x01, 0x0a, 0x0d, 0x52, 0x65, 0x70, 0x50, 0x72, + 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x12, 0x17, 0x0a, 0x07, 0x66, 0x69, 0x65, 0x6c, + 0x64, 0x5f, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, + 0x41, 0x12, 0x17, 0x0a, 0x07, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x62, 0x18, 0x02, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x42, 0x12, 0x17, 0x0a, 0x07, 0x66, 0x69, + 0x65, 0x6c, 0x64, 0x5f, 0x63, 0x18, 0x03, 0x20, 0x03, 0x28, 0x05, 0x52, 0x06, 0x66, 0x69, 0x65, + 0x6c, 0x64, 0x43, 0x12, 0x17, 0x0a, 0x07, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x64, 0x18, 0x04, + 0x20, 0x03, 0x28, 0x0d, 0x52, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x44, 0x12, 0x17, 0x0a, 0x07, + 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x65, 0x18, 0x05, 0x20, 0x03, 0x28, 0x03, 0x52, 0x06, 0x66, + 0x69, 0x65, 0x6c, 0x64, 0x45, 0x12, 0x17, 0x0a, 0x07, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x66, + 0x18, 0x06, 0x20, 0x03, 0x28, 0x04, 0x52, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x46, 0x42, 0x11, + 0x5a, 0x0f, 0x75, 0x74, 0x69, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x74, 0x65, 0x73, + 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_util_proto_test_test_proto_rawDescOnce sync.Once + file_util_proto_test_test_proto_rawDescData = file_util_proto_test_test_proto_rawDesc +) + +func file_util_proto_test_test_proto_rawDescGZIP() []byte { + file_util_proto_test_test_proto_rawDescOnce.Do(func() { + file_util_proto_test_test_proto_rawDescData = protoimpl.X.CompressGZIP(file_util_proto_test_test_proto_rawDescData) + }) + return file_util_proto_test_test_proto_rawDescData +} + +var file_util_proto_test_test_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_util_proto_test_test_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_util_proto_test_test_proto_goTypes = []interface{}{ + (Primitives_SomeEnum)(0), // 0: test.Primitives.SomeEnum + (*Primitives)(nil), // 1: test.Primitives + (*RepPrimitives)(nil), // 2: test.RepPrimitives +} +var file_util_proto_test_test_proto_depIdxs = []int32{ + 0, // 0: test.Primitives.field_h:type_name -> test.Primitives.SomeEnum + 1, // [1:1] is the sub-list for method output_type + 1, // [1:1] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_util_proto_test_test_proto_init() } +func file_util_proto_test_test_proto_init() { + if File_util_proto_test_test_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_util_proto_test_test_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Primitives); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_util_proto_test_test_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RepPrimitives); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_util_proto_test_test_proto_rawDesc, + NumEnums: 1, + NumMessages: 2, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_util_proto_test_test_proto_goTypes, + DependencyIndexes: file_util_proto_test_test_proto_depIdxs, + EnumInfos: file_util_proto_test_test_proto_enumTypes, + MessageInfos: file_util_proto_test_test_proto_msgTypes, + }.Build() + File_util_proto_test_test_proto = out.File + file_util_proto_test_test_proto_rawDesc = nil + file_util_proto_test_test_proto_goTypes = nil + file_util_proto_test_test_proto_depIdxs = nil +} diff --git a/pkg/api/util/proto/test/test.proto b/pkg/api/util/proto/test/test.proto new file mode 100644 index 000000000..65e350f2a --- /dev/null +++ b/pkg/api/util/proto/test/test.proto @@ -0,0 +1,34 @@ +syntax = "proto3"; + +package test; + +option go_package = "util/proto/test"; + +message Primitives { + bytes field_a = 1; + string field_b = 2; + bool field_c = 200; + int32 field_d = 201; + uint32 field_e = 202; + int64 field_f = 203; + uint64 field_g = 204; + fixed64 field_i = 205; + double field_j = 206; + fixed32 field_k = 207; + + enum SomeEnum { + UNKNOWN = 0; + POSITIVE = 1; + NEGATIVE = -1; + } + SomeEnum field_h = 300; +} + +message RepPrimitives { + repeated bytes field_a = 1; + repeated string field_b = 2; + repeated int32 field_c = 3; + repeated uint32 field_d = 4; + repeated int64 field_e = 5; + repeated uint64 field_f = 6; +} diff --git a/pkg/api/util/protogen/main.go b/pkg/api/util/protogen/main.go new file mode 100644 index 000000000..2d823fe88 --- /dev/null +++ b/pkg/api/util/protogen/main.go @@ -0,0 +1,233 @@ +package main + +import ( + "sort" + "strings" + + "google.golang.org/protobuf/compiler/protogen" + "google.golang.org/protobuf/reflect/protoreflect" +) + +func main() { + protogen.Options{}.Run(func(gen *protogen.Plugin) error { + for _, f := range gen.Files { + //if !f.Generate { + // continue + //} + imp := string(f.GoImportPath) + if strings.HasSuffix(imp, "/tree") || strings.HasSuffix(imp, "/control") { + generateFile(gen, f) + } + } + return nil + }) +} + +// generateFile generates a *.pb.go file enforcing field-order serialization. +func generateFile(gen *protogen.Plugin, file *protogen.File) *protogen.GeneratedFile { + filename := file.GeneratedFilenamePrefix + "_frostfs.pb.go" + g := gen.NewGeneratedFile(filename, file.GoImportPath) + g.P("// Code generated by protoc-gen-go-frostfs. DO NOT EDIT.") + g.P() + g.P("package ", file.GoPackageName) + g.P() + g.P(`import "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/util/proto"`) + + //for _, e := range file.Enums { + // g.P("type " + e.GoIdent.GoName + " int32") + // g.P("const (") + // for _, ev := range e.Values { + // g.P(ev.GoIdent.GoName, " = ", ev.Desc.Number()) + // } + // g.P(")") + //} + for _, msg := range file.Messages { + emitMessage(g, msg) + } + return g +} + +func emitMessage(g *protogen.GeneratedFile, msg *protogen.Message) { + for _, inner := range msg.Messages { + emitMessage(g, inner) + } + + fs := sortFields(msg.Fields) + + // StableSize implementation. + g.P("// StableSize returns the size of x in protobuf format.") + g.P("//") + g.P("// Structures with the same field values have the same binary size.") + g.P("func (x *", msg.GoIdent.GoName, ") StableSize() (size int) {") + g.P("if x == nil { return 0 }") + if len(fs) != 0 { + for _, f := range fs { + if f.Desc.IsList() && marshalers[f.Desc.Kind()].RepeatedDouble { + g.P("var n int") + break + } + } + for _, f := range fs { + emitFieldSize(g, f) + } + } + g.P("return size") + g.P("}\n") + + // StableMarshal implementation. + g.P("// StableMarshal marshals x in protobuf binary format with stable field order.") + g.P("//") + g.P("// If buffer length is less than x.StableSize(), new buffer is allocated.") + g.P("//") + g.P("// Returns any error encountered which did not allow writing the data completely.") + g.P("// Otherwise, returns the buffer in which the data is written.") + g.P("//") + g.P("// Structures with the same field values have the same binary format.") + g.P("func (x *", msg.GoIdent.GoName, ") StableMarshal(buf []byte) []byte {") + if len(fs) != 0 { + g.P("if x == nil { return []byte{} }") + g.P("if buf == nil { buf = make([]byte, x.StableSize()) }") + g.P("var offset int") + for _, f := range fs { + emitFieldMarshal(g, f) + } + } + g.P("return buf") + g.P("}\n") + + if strings.HasSuffix(msg.GoIdent.GoName, "Request") || strings.HasSuffix(msg.GoIdent.GoName, "Response") { + // SignedDataSize implementation (only for requests and responses). + g.P("// ReadSignedData fills buf with signed data of x.") + g.P("// If buffer length is less than x.SignedDataSize(), new buffer is allocated.") + g.P("//") + g.P("// Returns any error encountered which did not allow writing the data completely.") + g.P("// Otherwise, returns the buffer in which the data is written.") + g.P("//") + g.P("// Structures with the same field values have the same signed data.") + g.P("func (x *", msg.GoIdent.GoName, ") SignedDataSize() int {") + g.P("return x.GetBody().StableSize()") + g.P("}\n") + + // ReadSignedData implementation (only for requests and responses). + g.P("// SignedDataSize returns size of the request signed data in bytes.") + g.P("//") + g.P("// Structures with the same field values have the same signed data size.") + g.P("func (x *", msg.GoIdent.GoName, ") ReadSignedData(buf []byte) ([]byte, error) {") + g.P("return x.GetBody().StableMarshal(buf), nil") + g.P("}\n") + + // Signature setters and getters. + g.P("func (x *", msg.GoIdent.GoName, ") SetSignature(sig *Signature) {") + g.P("x.Signature = sig") + g.P("}\n") + } +} + +func emitFieldSize(g *protogen.GeneratedFile, f *protogen.Field) { + m := marshalers[f.Desc.Kind()] + if m.Prefix == "" { + g.P("// FIXME missing field marshaler: ", f.GoName, " of type ", f.Desc.Kind().String()) + g.P(`panic("unimplemented")`) + return + } + + name := castFieldName(f) + if f.Oneof != nil { + name = "x." + f.Oneof.GoName + g.P("if inner, ok := ", name, ".(*", f.GoIdent.GoName, "); ok {") + defer g.P("}") + name = "inner." + f.GoName + } + + switch { + case f.Desc.IsList() && f.Desc.Kind() == protoreflect.MessageKind: + g.P("for i := range ", name, "{") + g.P("size += proto.NestedStructureSize(", f.Desc.Number(), ", ", name, "[i])") + g.P("}") + case f.Desc.IsList(): + if m.RepeatedDouble { + g.P("n, _ = proto.Repeated", m.Prefix, "Size(", f.Desc.Number(), ", ", name, ")") + g.P("size += n") + } else { + g.P("size += proto.Repeated", m.Prefix, "Size(", f.Desc.Number(), ", ", name, ")") + } + default: + g.P("size += proto.", m.Prefix, "Size(", f.Desc.Number(), ", ", name, ")") + } +} + +func emitFieldMarshal(g *protogen.GeneratedFile, f *protogen.Field) { + m := marshalers[f.Desc.Kind()] + if m.Prefix == "" { + g.P("// FIXME missing field marshaler: ", f.GoName, " of type ", f.Desc.Kind().String()) + g.P(`panic("unimplemented")`) + return + } + + name := castFieldName(f) + if f.Oneof != nil { + name = "x." + f.Oneof.GoName + g.P("if inner, ok := ", name, ".(*", f.GoIdent.GoName, "); ok {") + defer g.P("}") + name = "inner." + f.GoName + } + + prefix := m.Prefix + if f.Desc.IsList() { + prefix = "Repeated" + m.Prefix + } + switch { + case f.Desc.IsList() && f.Desc.Kind() == protoreflect.MessageKind: + g.P("for i := range ", name, "{") + g.P("offset += proto.NestedStructureMarshal(", f.Desc.Number(), ", buf[offset:], ", name, "[i])") + g.P("}") + case f.Desc.IsList(): + g.P("offset += proto.Repeated", m.Prefix, "Marshal(", f.Desc.Number(), ", buf[offset:], ", name, ")") + default: + g.P("offset += proto.", prefix, "Marshal(", f.Desc.Number(), ", buf[offset:], ", name, ")") + } +} + +func castFieldName(f *protogen.Field) string { + name := "x." + f.GoName + if f.Desc.Kind() != protoreflect.EnumKind { + return name + } + return "int32(" + name + ")" +} + +type marshalerDesc struct { + Prefix string + RepeatedDouble bool +} + +// Unused kinds are commented. +var marshalers = map[protoreflect.Kind]marshalerDesc{ + protoreflect.BoolKind: {Prefix: "Bool"}, + protoreflect.EnumKind: {Prefix: "Enum"}, + // protoreflect.Int32Kind: "", + // protoreflect.Sint32Kind: "", + protoreflect.Uint32Kind: {Prefix: "UInt32", RepeatedDouble: true}, + protoreflect.Int64Kind: {Prefix: "Int64", RepeatedDouble: true}, + // protoreflect.Sint64Kind: "", + protoreflect.Uint64Kind: {Prefix: "UInt64", RepeatedDouble: true}, + // protoreflect.Sfixed32Kind: "", + protoreflect.Fixed32Kind: {Prefix: "Fixed32", RepeatedDouble: true}, + // protoreflect.FloatKind: "", + // protoreflect.Sfixed64Kind: "", + protoreflect.Fixed64Kind: {Prefix: "Fixed64", RepeatedDouble: true}, + protoreflect.DoubleKind: {Prefix: "Float64"}, + protoreflect.StringKind: {Prefix: "String"}, + protoreflect.BytesKind: {Prefix: "Bytes"}, + protoreflect.MessageKind: {Prefix: "NestedStructure"}, + // protoreflect.GroupKind: "", +} + +func sortFields(fs []*protogen.Field) []*protogen.Field { + res := make([]*protogen.Field, len(fs)) + copy(res, fs) + sort.Slice(res, func(i, j int) bool { + return res[i].Desc.Number() < res[j].Desc.Number() + }) + return res +} diff --git a/pkg/api/util/signature/data.go b/pkg/api/util/signature/data.go new file mode 100644 index 000000000..18249c364 --- /dev/null +++ b/pkg/api/util/signature/data.go @@ -0,0 +1,89 @@ +package signature + +import ( + "crypto/ecdsa" + + crypto "git.frostfs.info/TrueCloudLab/frostfs-crypto" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/util/pool" +) + +const poolSliceMaxSize = 128 * 1024 + +var buffersPool = pool.NewBufferPool(poolSliceMaxSize) + +type DataSource interface { + ReadSignedData([]byte) ([]byte, error) + SignedDataSize() int +} + +type DataWithSignature interface { + DataSource + GetSignature() *refs.Signature + SetSignature(*refs.Signature) +} + +type SignOption func(*cfg) + +type KeySignatureHandler func(*refs.Signature) + +type KeySignatureSource func() *refs.Signature + +func SignDataWithHandler(key *ecdsa.PrivateKey, src DataSource, handler KeySignatureHandler, opts ...SignOption) error { + if key == nil { + return crypto.ErrEmptyPrivateKey + } + + cfg := defaultCfg() + + for i := range opts { + opts[i](cfg) + } + + buffer := buffersPool.Get(uint32(src.SignedDataSize())) + defer buffersPool.Put(buffer) + + data, err := src.ReadSignedData(buffer.Data) + if err != nil { + return err + } + + sigData, err := sign(cfg, key, data) + if err != nil { + return err + } + + sig := new(refs.Signature) + sig.SetScheme(cfg.scheme) + sig.SetKey(crypto.MarshalPublicKey(&key.PublicKey)) + sig.SetSign(sigData) + handler(sig) + + return nil +} + +func VerifyDataWithSource(dataSrc DataSource, sigSrc KeySignatureSource, opts ...SignOption) error { + cfg := defaultCfg() + + for i := range opts { + opts[i](cfg) + } + + buffer := buffersPool.Get(uint32(dataSrc.SignedDataSize())) + defer buffersPool.Put(buffer) + + data, err := dataSrc.ReadSignedData(buffer.Data) + if err != nil { + return err + } + + return verify(cfg, data, sigSrc()) +} + +func SignData(key *ecdsa.PrivateKey, v DataWithSignature, opts ...SignOption) error { + return SignDataWithHandler(key, v, v.SetSignature, opts...) +} + +func VerifyData(src DataWithSignature, opts ...SignOption) error { + return VerifyDataWithSource(src, src.GetSignature, opts...) +} diff --git a/pkg/api/util/signature/options.go b/pkg/api/util/signature/options.go new file mode 100644 index 000000000..b3e78a204 --- /dev/null +++ b/pkg/api/util/signature/options.go @@ -0,0 +1,77 @@ +package signature + +import ( + "crypto/ecdsa" + "encoding/base64" + "fmt" + + crypto "git.frostfs.info/TrueCloudLab/frostfs-crypto" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/util/signature/walletconnect" +) + +type cfg struct { + schemeFixed bool + scheme refs.SignatureScheme +} + +func defaultCfg() *cfg { + return new(cfg) +} + +func verify(cfg *cfg, data []byte, sig *refs.Signature) error { + if !cfg.schemeFixed { + cfg.scheme = sig.GetScheme() + } + + pub := crypto.UnmarshalPublicKey(sig.GetKey()) + if pub == nil { + return crypto.ErrEmptyPublicKey + } + + switch cfg.scheme { + case refs.ECDSA_SHA512: + return crypto.Verify(pub, data, sig.GetSign()) + case refs.ECDSA_RFC6979_SHA256: + return crypto.VerifyRFC6979(pub, data, sig.GetSign()) + case refs.ECDSA_RFC6979_SHA256_WALLET_CONNECT: + buffer := buffersPool.Get(uint32(base64.StdEncoding.EncodedLen(len(data)))) + defer buffersPool.Put(buffer) + base64.StdEncoding.Encode(buffer.Data, data) + if !walletconnect.Verify(pub, buffer.Data, sig.GetSign()) { + return crypto.ErrInvalidSignature + } + return nil + default: + return fmt.Errorf("unsupported signature scheme %s", cfg.scheme) + } +} + +func sign(cfg *cfg, key *ecdsa.PrivateKey, data []byte) ([]byte, error) { + switch cfg.scheme { + case refs.ECDSA_SHA512: + return crypto.Sign(key, data) + case refs.ECDSA_RFC6979_SHA256: + return crypto.SignRFC6979(key, data) + case refs.ECDSA_RFC6979_SHA256_WALLET_CONNECT: + buffer := buffersPool.Get(uint32(base64.StdEncoding.EncodedLen(len(data)))) + defer buffersPool.Put(buffer) + base64.StdEncoding.Encode(buffer.Data, data) + return walletconnect.Sign(key, buffer.Data) + default: + panic(fmt.Sprintf("unsupported scheme %s", cfg.scheme)) + } +} + +func SignWithRFC6979() SignOption { + return func(c *cfg) { + c.schemeFixed = true + c.scheme = refs.ECDSA_RFC6979_SHA256 + } +} + +func SignWithWalletConnect() SignOption { + return func(c *cfg) { + c.scheme = refs.ECDSA_RFC6979_SHA256_WALLET_CONNECT + } +} diff --git a/pkg/api/util/signature/sign_test.go b/pkg/api/util/signature/sign_test.go new file mode 100644 index 000000000..bc6b2b68c --- /dev/null +++ b/pkg/api/util/signature/sign_test.go @@ -0,0 +1,44 @@ +package signature + +import ( + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + "github.com/stretchr/testify/require" +) + +type testData struct { + data []byte + sig *refs.Signature +} + +func (t testData) SignedDataSize() int { return len(t.data) } +func (t testData) ReadSignedData(data []byte) ([]byte, error) { + n := copy(data, t.data) + return data[:n], nil +} +func (t testData) GetSignature() *refs.Signature { return t.sig } +func (t *testData) SetSignature(s *refs.Signature) { t.sig = s } + +func TestWalletConnect(t *testing.T) { + testCases := [...][]byte{ + {}, + {0}, + {1, 2}, + {3, 4, 5}, + {6, 7, 8, 9, 10, 11, 12}, + } + + pk, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + require.NoError(t, err) + + for _, tc := range testCases { + td := &testData{data: tc} + require.NoError(t, SignData(pk, td, SignWithWalletConnect())) + require.Equal(t, refs.ECDSA_RFC6979_SHA256_WALLET_CONNECT, td.sig.GetScheme()) + require.NoError(t, VerifyData(td)) + } +} diff --git a/pkg/api/util/signature/walletconnect/sign.go b/pkg/api/util/signature/walletconnect/sign.go new file mode 100644 index 000000000..b96a84208 --- /dev/null +++ b/pkg/api/util/signature/walletconnect/sign.go @@ -0,0 +1,142 @@ +package walletconnect + +import ( + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "encoding/binary" + "encoding/hex" + + crypto "git.frostfs.info/TrueCloudLab/frostfs-crypto" +) + +const ( + // saltSize is the salt size added to signed message. + saltSize = 16 + // signatureLen is the length of RFC6979 signature. + signatureLen = 64 +) + +// SignedMessage contains mirrors `SignedMessage` struct from the WalletConnect API. +// https://neon.coz.io/wksdk/core/modules.html#SignedMessage +type SignedMessage struct { + Data []byte + Message []byte + PublicKey []byte + Salt []byte +} + +// Sign signs message using WalletConnect API. The returned signature +// contains RFC6979 signature and 16-byte salt. +func Sign(p *ecdsa.PrivateKey, msg []byte) ([]byte, error) { + sm, err := SignMessage(p, msg) + if err != nil { + return nil, err + } + return append(sm.Data, sm.Salt...), nil +} + +// Verify verifies message using WalletConnect API. +func Verify(p *ecdsa.PublicKey, data, sign []byte) bool { + if len(sign) != signatureLen+saltSize { + return false + } + + salt := sign[signatureLen:] + return VerifyMessage(p, SignedMessage{ + Data: sign[:signatureLen], + Message: createMessageWithSalt(data, salt), + Salt: salt, + }) +} + +// SignMessage signs message with a private key and returns structure similar to +// `signMessage` of the WalletConnect API. +// https://github.com/CityOfZion/wallet-connect-sdk/blob/89c236b/packages/wallet-connect-sdk-core/src/index.ts#L496 +// https://github.com/CityOfZion/neon-wallet/blob/1174a9388480e6bbc4f79eb13183c2a573f67ca8/app/context/WalletConnect/helpers.js#L133 +func SignMessage(p *ecdsa.PrivateKey, msg []byte) (SignedMessage, error) { + var salt [saltSize]byte + _, _ = rand.Read(salt[:]) + + msg = createMessageWithSalt(msg, salt[:]) + sign, err := crypto.SignRFC6979(p, msg) + if err != nil { + return SignedMessage{}, err + } + + return SignedMessage{ + Data: sign, + Message: msg, + PublicKey: elliptic.MarshalCompressed(p.Curve, p.X, p.Y), + Salt: salt[:], + }, nil +} + +// VerifyMessage verifies message with a private key and returns structure similar to +// `verifyMessage` of WalletConnect API. +// https://github.com/CityOfZion/wallet-connect-sdk/blob/89c236b/packages/wallet-connect-sdk-core/src/index.ts#L515 +// https://github.com/CityOfZion/neon-wallet/blob/1174a9388480e6bbc4f79eb13183c2a573f67ca8/app/context/WalletConnect/helpers.js#L147 +func VerifyMessage(p *ecdsa.PublicKey, m SignedMessage) bool { + if p == nil { + x, y := elliptic.UnmarshalCompressed(elliptic.P256(), m.PublicKey) + if x == nil || y == nil { + return false + } + p = &ecdsa.PublicKey{ + Curve: elliptic.P256(), + X: x, + Y: y, + } + } + return crypto.VerifyRFC6979(p, m.Message, m.Data) == nil +} + +func createMessageWithSalt(msg, salt []byte) []byte { + // 4 byte prefix + length of the message with salt in bytes + + // + salt + message + 2 byte postfix. + saltedLen := hex.EncodedLen(len(salt)) + len(msg) + data := make([]byte, 4+getVarIntSize(saltedLen)+saltedLen+2) + + n := copy(data, []byte{0x01, 0x00, 0x01, 0xf0}) // fixed prefix + n += putVarUint(data[n:], uint64(saltedLen)) // salt is hex encoded, double its size + n += hex.Encode(data[n:], salt[:]) // for some reason we encode salt in hex + n += copy(data[n:], msg) + copy(data[n:], []byte{0x00, 0x00}) + + return data +} + +// Following functions are copied from github.com/nspcc-dev/neo-go/pkg/io package +// to avoid having another dependency. + +// getVarIntSize returns the size in number of bytes of a variable integer. +// Reference: https://github.com/neo-project/neo/blob/26d04a642ac5a1dd1827dabf5602767e0acba25c/src/neo/IO/Helper.cs#L131 +func getVarIntSize(value int) int { + var size uintptr + + if value < 0xFD { + size = 1 // unit8 + } else if value <= 0xFFFF { + size = 3 // byte + uint16 + } else { + size = 5 // byte + uint32 + } + return int(size) +} + +// putVarUint puts val in varint form to the pre-allocated buffer. +func putVarUint(data []byte, val uint64) int { + if val < 0xfd { + data[0] = byte(val) + return 1 + } + if val <= 0xFFFF { + data[0] = byte(0xfd) + binary.LittleEndian.PutUint16(data[1:], uint16(val)) + return 3 + } + + data[0] = byte(0xfe) + binary.LittleEndian.PutUint32(data[1:], uint32(val)) + return 5 +} diff --git a/pkg/api/util/signature/walletconnect/sign_test.go b/pkg/api/util/signature/walletconnect/sign_test.go new file mode 100644 index 000000000..1b4fe1807 --- /dev/null +++ b/pkg/api/util/signature/walletconnect/sign_test.go @@ -0,0 +1,112 @@ +package walletconnect + +import ( + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "encoding/hex" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestSignMessage(t *testing.T) { + p1, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + require.NoError(t, err) + + msg := []byte("NEO") + result, err := SignMessage(p1, msg) + require.NoError(t, err) + require.Equal(t, elliptic.MarshalCompressed(elliptic.P256(), p1.PublicKey.X, p1.PublicKey.Y), result.PublicKey) + require.Equal(t, saltSize, len(result.Salt)) + require.Equal(t, 64, len(result.Data)) + require.Equal(t, 4+1+16*2+3+2, len(result.Message)) + + require.True(t, VerifyMessage(&p1.PublicKey, result)) + + t.Run("invalid public key", func(t *testing.T) { + p2, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + require.NoError(t, err) + require.False(t, VerifyMessage(&p2.PublicKey, result)) + }) + t.Run("invalid signature", func(t *testing.T) { + result := result + result.Data[0] ^= 0xFF + require.False(t, VerifyMessage(&p1.PublicKey, result)) + }) +} + +func TestSign(t *testing.T) { + p1, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + require.NoError(t, err) + + msg := []byte("NEO") + sign, err := Sign(p1, msg) + require.NoError(t, err) + require.True(t, Verify(&p1.PublicKey, msg, sign)) + + t.Run("invalid public key", func(t *testing.T) { + p2, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + require.NoError(t, err) + require.False(t, Verify(&p2.PublicKey, msg, sign)) + }) + t.Run("invalid signature", func(t *testing.T) { + sign[0] ^= 0xFF + require.False(t, Verify(&p1.PublicKey, msg, sign)) + }) +} + +func TestVerifyNeonWallet(t *testing.T) { + testCases := [...]struct { + publicKey string + data string + salt string + messageHex string + messageOriginal string + }{ + { // Test values from this GIF https://github.com/CityOfZion/neon-wallet/pull/2390 . + publicKey: "02ce6228ba2cb2fc235be93aff9cd5fc0851702eb9791552f60db062f01e3d83f6", + data: "90ab1886ca0bece59b982d9ade8f5598065d651362fb9ce45ad66d0474b89c0b80913c8f0118a282acbdf200a429ba2d81bc52534a53ab41a2c6dfe2f0b4fb1b", + salt: "d41e348afccc2f3ee45cd9f5128b16dc", + messageHex: "010001f05c6434316533343861666363633266336565343563643966353132386231366463436172616c686f2c206d756c65712c206f2062616775697520656820697373756d65726d6f2074616978206c696761646f206e61206d697373e36f3f0000", + messageOriginal: "436172616c686f2c206d756c65712c206f2062616775697520656820697373756d65726d6f2074616978206c696761646f206e61206d697373e36f3f", + }, + { // Test value from wallet connect integration test + publicKey: "03bd9108c0b49f657e9eee50d1399022bd1e436118e5b7529a1b7cd606652f578f", + data: "510caa8cb6db5dedf04d215a064208d64be7496916d890df59aee132db8f2b07532e06f7ea664c4a99e3bcb74b43a35eb9653891b5f8701d2aef9e7526703eaa", + salt: "2c5b189569e92cce12e1c640f23e83ba", + messageHex: "010001f02632633562313839353639653932636365313265316336343066323365383362613132333435360000", + messageOriginal: "313233343536", // ascii string "123456" + }, + { // Test value from wallet connect integration test + publicKey: "03bd9108c0b49f657e9eee50d1399022bd1e436118e5b7529a1b7cd606652f578f", + data: "1e13f248962d8b3b60708b55ddf448d6d6a28c6b43887212a38b00bf6bab695e61261e54451c6e3d5f1f000e5534d166c7ca30f662a296d3a9aafa6d8c173c01", + salt: "58c86b2e74215b4f36b47d731236be3b", + messageHex: "010001f02035386338366232653734323135623466333662343764373331323336626533620000", + messageOriginal: "", // empty string + }, + } + + for _, testCase := range testCases { + rawPub, err := hex.DecodeString(testCase.publicKey) + require.NoError(t, err) + data, err := hex.DecodeString(testCase.data) + require.NoError(t, err) + salt, err := hex.DecodeString(testCase.salt) + require.NoError(t, err) + msg, err := hex.DecodeString(testCase.messageHex) + require.NoError(t, err) + orig, err := hex.DecodeString(testCase.messageOriginal) + require.NoError(t, err) + + require.Equal(t, msg, createMessageWithSalt(orig, salt)) + + sm := SignedMessage{ + Data: data, + Message: msg, + PublicKey: rawPub, + Salt: salt, + } + require.True(t, VerifyMessage(nil, sm)) + } +} diff --git a/pkg/core/client/client.go b/pkg/core/client/client.go index 8c92901f2..c76b65119 100644 --- a/pkg/core/client/client.go +++ b/pkg/core/client/client.go @@ -3,9 +3,9 @@ package client import ( "context" - rawclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" + rawclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" ) // Client is an interface of FrostFS storage diff --git a/pkg/core/client/util.go b/pkg/core/client/util.go index d4bc0cf68..31c9f0ba4 100644 --- a/pkg/core/client/util.go +++ b/pkg/core/client/util.go @@ -5,7 +5,7 @@ import ( "fmt" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" ) func nodeInfoFromKeyAddr(dst *NodeInfo, k []byte, a, external network.AddressGroup) { diff --git a/pkg/core/container/delete.go b/pkg/core/container/delete.go index 8e0aaebb9..5022d4a80 100644 --- a/pkg/core/container/delete.go +++ b/pkg/core/container/delete.go @@ -1,9 +1,9 @@ package container import ( - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/session" ) // RemovalWitness groups the information required diff --git a/pkg/core/container/storage.go b/pkg/core/container/storage.go index 69854f495..f4b9b9249 100644 --- a/pkg/core/container/storage.go +++ b/pkg/core/container/storage.go @@ -1,12 +1,12 @@ package container import ( - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/crypto" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/eacl" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" ) // Container groups information about the FrostFS container stored in the FrostFS network. diff --git a/pkg/core/container/util.go b/pkg/core/container/util.go index 98919284e..ea58c66cf 100644 --- a/pkg/core/container/util.go +++ b/pkg/core/container/util.go @@ -3,8 +3,8 @@ package container import ( "errors" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" ) // WasRemoved checks whether the container ever existed or diff --git a/pkg/core/netmap/nodes.go b/pkg/core/netmap/nodes.go index 17fccc620..d2232cf60 100644 --- a/pkg/core/netmap/nodes.go +++ b/pkg/core/netmap/nodes.go @@ -1,6 +1,6 @@ package netmap -import "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" +import "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" // Node is a named type of netmap.NodeInfo which provides interface needed // in the current repository. Node is expected to be used everywhere instead diff --git a/pkg/core/netmap/storage.go b/pkg/core/netmap/storage.go index 7770c61c7..6289ad7a4 100644 --- a/pkg/core/netmap/storage.go +++ b/pkg/core/netmap/storage.go @@ -1,7 +1,7 @@ package netmap import ( - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" ) // Source is an interface that wraps diff --git a/pkg/core/object/address.go b/pkg/core/object/address.go index a25d853eb..14ac9b14c 100644 --- a/pkg/core/object/address.go +++ b/pkg/core/object/address.go @@ -3,8 +3,8 @@ package object import ( "fmt" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" ) // AddressWithType groups object address with its FrostFS diff --git a/pkg/core/object/fmt.go b/pkg/core/object/fmt.go index e266800b2..c5519fc24 100644 --- a/pkg/core/object/fmt.go +++ b/pkg/core/object/fmt.go @@ -8,17 +8,17 @@ import ( "fmt" "strconv" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/acl" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/crypto/ecdsa" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto/ecdsa" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" ) // FormatValidator represents an object format validator. diff --git a/pkg/core/object/fmt_test.go b/pkg/core/object/fmt_test.go index a8901ad6d..bb96d6a4a 100644 --- a/pkg/core/object/fmt_test.go +++ b/pkg/core/object/fmt_test.go @@ -7,19 +7,19 @@ import ( "strconv" "testing" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" + containerSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/crypto/ecdsa" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + oidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id/test" + sessiontest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/session/test" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - containerSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" - frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto/ecdsa" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" - sessiontest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session/test" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" "github.com/google/uuid" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/stretchr/testify/require" diff --git a/pkg/core/object/object.go b/pkg/core/object/object.go index 9c450966c..c405c5dac 100644 --- a/pkg/core/object/object.go +++ b/pkg/core/object/object.go @@ -1,8 +1,8 @@ package object import ( - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" ) // AddressOf returns the address of the object. diff --git a/pkg/core/object/sender_classifier.go b/pkg/core/object/sender_classifier.go index ac881431e..619e64522 100644 --- a/pkg/core/object/sender_classifier.go +++ b/pkg/core/object/sender_classifier.go @@ -6,12 +6,12 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" core "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/acl" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "go.uber.org/zap" ) diff --git a/pkg/core/version/version.go b/pkg/core/version/version.go index eb759a993..a3cbc0dc2 100644 --- a/pkg/core/version/version.go +++ b/pkg/core/version/version.go @@ -1,7 +1,7 @@ package version import ( - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/version" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/version" ) // IsValid checks if Version is not earlier than the genesis version of the FrostFS. diff --git a/pkg/core/version/version_test.go b/pkg/core/version/version_test.go index 1ef18c521..0198a162d 100644 --- a/pkg/core/version/version_test.go +++ b/pkg/core/version/version_test.go @@ -4,7 +4,7 @@ import ( "testing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/version" - versionSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/version" + versionSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/version" "github.com/stretchr/testify/require" ) diff --git a/pkg/innerring/processors/alphabet/handlers_test.go b/pkg/innerring/processors/alphabet/handlers_test.go index 346901949..25d416b12 100644 --- a/pkg/innerring/processors/alphabet/handlers_test.go +++ b/pkg/innerring/processors/alphabet/handlers_test.go @@ -6,8 +6,8 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors/alphabet" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/timers" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn" "github.com/nspcc-dev/neo-go/pkg/util" diff --git a/pkg/innerring/processors/alphabet/processor.go b/pkg/innerring/processors/alphabet/processor.go index ce6679969..fa105aa80 100644 --- a/pkg/innerring/processors/alphabet/processor.go +++ b/pkg/innerring/processors/alphabet/processor.go @@ -9,8 +9,8 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/metrics" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/panjf2000/ants/v2" diff --git a/pkg/innerring/processors/container/common.go b/pkg/innerring/processors/container/common.go index ba12ebb37..e45c15817 100644 --- a/pkg/innerring/processors/container/common.go +++ b/pkg/innerring/processors/container/common.go @@ -5,10 +5,10 @@ import ( "errors" "fmt" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto/ecdsa" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/crypto/ecdsa" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" ) var ( diff --git a/pkg/innerring/processors/container/handlers_test.go b/pkg/innerring/processors/container/handlers_test.go index a69d0e4c4..8df37c336 100644 --- a/pkg/innerring/processors/container/handlers_test.go +++ b/pkg/innerring/processors/container/handlers_test.go @@ -11,17 +11,17 @@ import ( containercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" cntClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container" containerEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/container" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + containerSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/acl" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/crypto" + frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/crypto/ecdsa" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/eacl" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/version" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" - containerSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto" - frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto/ecdsa" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/version" "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/network/payload" diff --git a/pkg/innerring/processors/container/process_container.go b/pkg/innerring/processors/container/process_container.go index a950997fd..4f3a3b2d4 100644 --- a/pkg/innerring/processors/container/process_container.go +++ b/pkg/innerring/processors/container/process_container.go @@ -8,9 +8,9 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" containerEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/container" - containerSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" + containerSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/session" "github.com/nspcc-dev/neo-go/pkg/network/payload" "github.com/nspcc-dev/neo-go/pkg/util" "go.uber.org/zap" diff --git a/pkg/innerring/processors/container/process_eacl.go b/pkg/innerring/processors/container/process_eacl.go index 8ab0d5c39..3f54f7f58 100644 --- a/pkg/innerring/processors/container/process_eacl.go +++ b/pkg/innerring/processors/container/process_eacl.go @@ -7,8 +7,8 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" cntClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container" containerEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/container" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/eacl" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/session" "go.uber.org/zap" ) diff --git a/pkg/innerring/processors/netmap/cleanup_table.go b/pkg/innerring/processors/netmap/cleanup_table.go index 705e21d99..560e7d5ff 100644 --- a/pkg/innerring/processors/netmap/cleanup_table.go +++ b/pkg/innerring/processors/netmap/cleanup_table.go @@ -4,7 +4,7 @@ import ( "bytes" "sync" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" ) type ( diff --git a/pkg/innerring/processors/netmap/cleanup_table_test.go b/pkg/innerring/processors/netmap/cleanup_table_test.go index ae5620733..fad256f76 100644 --- a/pkg/innerring/processors/netmap/cleanup_table_test.go +++ b/pkg/innerring/processors/netmap/cleanup_table_test.go @@ -3,7 +3,7 @@ package netmap import ( "testing" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/stretchr/testify/require" ) diff --git a/pkg/innerring/processors/netmap/handlers_test.go b/pkg/innerring/processors/netmap/handlers_test.go index b34abb78c..505f122e8 100644 --- a/pkg/innerring/processors/netmap/handlers_test.go +++ b/pkg/innerring/processors/netmap/handlers_test.go @@ -5,16 +5,16 @@ import ( "testing" "time" - v2netmap "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap" netmapContract "git.frostfs.info/TrueCloudLab/frostfs-contract/netmap" + v2netmap "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors/governance" timerEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/timers" cntClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container" netmapclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" netmapEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn" diff --git a/pkg/innerring/processors/netmap/nodevalidation/locode/calls.go b/pkg/innerring/processors/netmap/nodevalidation/locode/calls.go index d071a7792..514c01183 100644 --- a/pkg/innerring/processors/netmap/nodevalidation/locode/calls.go +++ b/pkg/innerring/processors/netmap/nodevalidation/locode/calls.go @@ -4,8 +4,8 @@ import ( "errors" "fmt" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/locode" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" ) var errMissingRequiredAttr = errors.New("missing required attribute in DB record") diff --git a/pkg/innerring/processors/netmap/nodevalidation/locode/calls_test.go b/pkg/innerring/processors/netmap/nodevalidation/locode/calls_test.go index 6697391e8..6cc5bccf4 100644 --- a/pkg/innerring/processors/netmap/nodevalidation/locode/calls_test.go +++ b/pkg/innerring/processors/netmap/nodevalidation/locode/calls_test.go @@ -6,9 +6,9 @@ import ( "testing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors/netmap/nodevalidation/locode" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" locodestd "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/locode" locodedb "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/locode/db" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" "github.com/stretchr/testify/require" ) diff --git a/pkg/innerring/processors/netmap/nodevalidation/maddress/calls.go b/pkg/innerring/processors/netmap/nodevalidation/maddress/calls.go index 126f36582..fc49bd313 100644 --- a/pkg/innerring/processors/netmap/nodevalidation/maddress/calls.go +++ b/pkg/innerring/processors/netmap/nodevalidation/maddress/calls.go @@ -4,7 +4,7 @@ import ( "fmt" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" ) // VerifyAndUpdate calls network.VerifyAddress. diff --git a/pkg/innerring/processors/netmap/nodevalidation/state/validator.go b/pkg/innerring/processors/netmap/nodevalidation/state/validator.go index 4094e50a5..c756e5bbd 100644 --- a/pkg/innerring/processors/netmap/nodevalidation/state/validator.go +++ b/pkg/innerring/processors/netmap/nodevalidation/state/validator.go @@ -9,7 +9,7 @@ package state import ( "errors" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" ) // ErrMaintenanceModeDisallowed is returned when maintenance mode is disallowed. diff --git a/pkg/innerring/processors/netmap/nodevalidation/state/validator_test.go b/pkg/innerring/processors/netmap/nodevalidation/state/validator_test.go index a557628f0..d70f87980 100644 --- a/pkg/innerring/processors/netmap/nodevalidation/state/validator_test.go +++ b/pkg/innerring/processors/netmap/nodevalidation/state/validator_test.go @@ -4,7 +4,7 @@ import ( "testing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors/netmap/nodevalidation/state" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" "github.com/stretchr/testify/require" ) diff --git a/pkg/innerring/processors/netmap/nodevalidation/validator.go b/pkg/innerring/processors/netmap/nodevalidation/validator.go index e9b24e024..53aae2c2e 100644 --- a/pkg/innerring/processors/netmap/nodevalidation/validator.go +++ b/pkg/innerring/processors/netmap/nodevalidation/validator.go @@ -2,7 +2,7 @@ package nodevalidation import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors/netmap" - apinetmap "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" + apinetmap "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" ) // CompositeValidator wraps `netmap.NodeValidator`s. diff --git a/pkg/innerring/processors/netmap/process_cleanup.go b/pkg/innerring/processors/netmap/process_cleanup.go index 170c39e2c..ef79e0320 100644 --- a/pkg/innerring/processors/netmap/process_cleanup.go +++ b/pkg/innerring/processors/netmap/process_cleanup.go @@ -1,8 +1,8 @@ package netmap import ( - v2netmap "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + v2netmap "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/netmap" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "go.uber.org/zap" ) diff --git a/pkg/innerring/processors/netmap/process_peers.go b/pkg/innerring/processors/netmap/process_peers.go index 41e4bfb7e..fcc53066b 100644 --- a/pkg/innerring/processors/netmap/process_peers.go +++ b/pkg/innerring/processors/netmap/process_peers.go @@ -6,7 +6,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" netmapclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" netmapEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/netmap" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" "go.uber.org/zap" ) diff --git a/pkg/innerring/processors/netmap/processor.go b/pkg/innerring/processors/netmap/processor.go index e8fb8721b..6cd193133 100644 --- a/pkg/innerring/processors/netmap/processor.go +++ b/pkg/innerring/processors/netmap/processor.go @@ -10,8 +10,8 @@ import ( cntClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" netmapEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" "github.com/nspcc-dev/neo-go/pkg/core/mempoolevent" "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn" diff --git a/pkg/innerring/processors/netmap/wrappers.go b/pkg/innerring/processors/netmap/wrappers.go index e75fdaf40..8082505cb 100644 --- a/pkg/innerring/processors/netmap/wrappers.go +++ b/pkg/innerring/processors/netmap/wrappers.go @@ -2,7 +2,7 @@ package netmap import ( netmapclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn" "github.com/nspcc-dev/neo-go/pkg/util" diff --git a/pkg/local_object_storage/blobovnicza/blobovnicza_test.go b/pkg/local_object_storage/blobovnicza/blobovnicza_test.go index caee770e8..757dd938f 100644 --- a/pkg/local_object_storage/blobovnicza/blobovnicza_test.go +++ b/pkg/local_object_storage/blobovnicza/blobovnicza_test.go @@ -6,10 +6,10 @@ import ( "os" "testing" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + oidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id/test" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" "github.com/stretchr/testify/require" ) diff --git a/pkg/local_object_storage/blobovnicza/delete.go b/pkg/local_object_storage/blobovnicza/delete.go index ab8575ad7..1374cb122 100644 --- a/pkg/local_object_storage/blobovnicza/delete.go +++ b/pkg/local_object_storage/blobovnicza/delete.go @@ -4,10 +4,10 @@ import ( "context" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.etcd.io/bbolt" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" diff --git a/pkg/local_object_storage/blobovnicza/exists.go b/pkg/local_object_storage/blobovnicza/exists.go index b5d723ee6..ec540e259 100644 --- a/pkg/local_object_storage/blobovnicza/exists.go +++ b/pkg/local_object_storage/blobovnicza/exists.go @@ -3,8 +3,8 @@ package blobovnicza import ( "context" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.etcd.io/bbolt" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" diff --git a/pkg/local_object_storage/blobovnicza/get.go b/pkg/local_object_storage/blobovnicza/get.go index 36cf69d54..e2d45934a 100644 --- a/pkg/local_object_storage/blobovnicza/get.go +++ b/pkg/local_object_storage/blobovnicza/get.go @@ -5,9 +5,9 @@ import ( "context" "errors" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.etcd.io/bbolt" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" diff --git a/pkg/local_object_storage/blobovnicza/get_test.go b/pkg/local_object_storage/blobovnicza/get_test.go index c464abc87..a1fc7187a 100644 --- a/pkg/local_object_storage/blobovnicza/get_test.go +++ b/pkg/local_object_storage/blobovnicza/get_test.go @@ -5,7 +5,7 @@ import ( "path/filepath" "testing" - oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" + oidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id/test" "github.com/stretchr/testify/require" ) diff --git a/pkg/local_object_storage/blobovnicza/iterate.go b/pkg/local_object_storage/blobovnicza/iterate.go index 32b0ccea7..9028d51b3 100644 --- a/pkg/local_object_storage/blobovnicza/iterate.go +++ b/pkg/local_object_storage/blobovnicza/iterate.go @@ -5,8 +5,8 @@ import ( "fmt" "math" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.etcd.io/bbolt" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" diff --git a/pkg/local_object_storage/blobovnicza/iterate_test.go b/pkg/local_object_storage/blobovnicza/iterate_test.go index 5db1e4165..bc1d9d769 100644 --- a/pkg/local_object_storage/blobovnicza/iterate_test.go +++ b/pkg/local_object_storage/blobovnicza/iterate_test.go @@ -7,7 +7,7 @@ import ( "path/filepath" "testing" - oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" + oidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id/test" "github.com/stretchr/testify/require" "go.etcd.io/bbolt" ) diff --git a/pkg/local_object_storage/blobovnicza/move.go b/pkg/local_object_storage/blobovnicza/move.go index 255198f66..59486136d 100644 --- a/pkg/local_object_storage/blobovnicza/move.go +++ b/pkg/local_object_storage/blobovnicza/move.go @@ -4,8 +4,8 @@ import ( "context" "fmt" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.etcd.io/bbolt" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" diff --git a/pkg/local_object_storage/blobovnicza/put.go b/pkg/local_object_storage/blobovnicza/put.go index d15b6e2b2..9ed56b877 100644 --- a/pkg/local_object_storage/blobovnicza/put.go +++ b/pkg/local_object_storage/blobovnicza/put.go @@ -5,8 +5,8 @@ import ( "fmt" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.etcd.io/bbolt" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go b/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go index be51509b6..2e42886c2 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go @@ -8,7 +8,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/compression" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/hrw" ) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/delete.go b/pkg/local_object_storage/blobstor/blobovniczatree/delete.go index 298de3ad6..866d96b9c 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/delete.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/delete.go @@ -10,10 +10,10 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobovnicza" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" "go.uber.org/zap" diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/errors.go b/pkg/local_object_storage/blobstor/blobovniczatree/errors.go index be0fd81c3..3accbf6c3 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/errors.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/errors.go @@ -4,7 +4,7 @@ import ( "errors" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" ) var errClosed = logicerr.New("blobvnicza is closed") diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/exists.go b/pkg/local_object_storage/blobstor/blobovniczatree/exists.go index a64b2bbb1..81f8b454f 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/exists.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/exists.go @@ -8,9 +8,9 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobovnicza" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" "go.uber.org/zap" diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/get.go b/pkg/local_object_storage/blobstor/blobovniczatree/get.go index 5f1856673..2259d4487 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/get.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/get.go @@ -10,11 +10,11 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobovnicza" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" "go.uber.org/zap" diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/get_range.go b/pkg/local_object_storage/blobstor/blobovniczatree/get_range.go index d237ae439..b3497afe7 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/get_range.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/get_range.go @@ -11,11 +11,11 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobovnicza" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" "go.uber.org/zap" diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go b/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go index 942d73a12..68b76015d 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go @@ -11,8 +11,8 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobovnicza" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "git.frostfs.info/TrueCloudLab/hrw" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/iterate_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/iterate_test.go index c322fa7a3..eb77fd15f 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/iterate_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/iterate_test.go @@ -4,7 +4,7 @@ import ( "context" "testing" - oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" + oidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id/test" "github.com/stretchr/testify/require" ) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go index 2302661d5..f9283f44d 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go @@ -13,8 +13,8 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobovnicza" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "go.uber.org/zap" "golang.org/x/sync/errgroup" ) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_failover_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_failover_test.go index 855229405..650cc1ee0 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_failover_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_failover_test.go @@ -11,10 +11,10 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobovnicza" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/internal/blobstortest" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "github.com/stretchr/testify/require" ) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go index 0ac50f36a..ca0f0a10e 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go @@ -8,8 +8,8 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/internal/blobstortest" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "github.com/stretchr/testify/require" "golang.org/x/sync/errgroup" ) diff --git a/pkg/local_object_storage/blobstor/blobstor.go b/pkg/local_object_storage/blobstor/blobstor.go index bc9ab2b99..ec80812e1 100644 --- a/pkg/local_object_storage/blobstor/blobstor.go +++ b/pkg/local_object_storage/blobstor/blobstor.go @@ -6,8 +6,8 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/compression" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "go.uber.org/zap" ) diff --git a/pkg/local_object_storage/blobstor/blobstor_test.go b/pkg/local_object_storage/blobstor/blobstor_test.go index 3dac3bfa4..ebda200b3 100644 --- a/pkg/local_object_storage/blobstor/blobstor_test.go +++ b/pkg/local_object_storage/blobstor/blobstor_test.go @@ -12,7 +12,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/fstree" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/teststore" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" "github.com/stretchr/testify/require" ) diff --git a/pkg/local_object_storage/blobstor/common/delete.go b/pkg/local_object_storage/blobstor/common/delete.go index 1b04eab1a..4dde4f24e 100644 --- a/pkg/local_object_storage/blobstor/common/delete.go +++ b/pkg/local_object_storage/blobstor/common/delete.go @@ -1,7 +1,7 @@ package common import ( - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" ) // DeletePrm groups the parameters of Delete operation. diff --git a/pkg/local_object_storage/blobstor/common/exists.go b/pkg/local_object_storage/blobstor/common/exists.go index d9bdbd33a..8dd1554f2 100644 --- a/pkg/local_object_storage/blobstor/common/exists.go +++ b/pkg/local_object_storage/blobstor/common/exists.go @@ -1,6 +1,6 @@ package common -import oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" +import oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" // ExistsPrm groups the parameters of Exists operation. type ExistsPrm struct { diff --git a/pkg/local_object_storage/blobstor/common/get.go b/pkg/local_object_storage/blobstor/common/get.go index 0d036219f..244b1dfe2 100644 --- a/pkg/local_object_storage/blobstor/common/get.go +++ b/pkg/local_object_storage/blobstor/common/get.go @@ -1,8 +1,8 @@ package common import ( - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" ) type GetPrm struct { diff --git a/pkg/local_object_storage/blobstor/common/get_range.go b/pkg/local_object_storage/blobstor/common/get_range.go index 1c4f95c02..a8280c634 100644 --- a/pkg/local_object_storage/blobstor/common/get_range.go +++ b/pkg/local_object_storage/blobstor/common/get_range.go @@ -1,8 +1,8 @@ package common import ( - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" ) type GetRangePrm struct { diff --git a/pkg/local_object_storage/blobstor/common/iterate.go b/pkg/local_object_storage/blobstor/common/iterate.go index a1b8ff047..c7127fe5d 100644 --- a/pkg/local_object_storage/blobstor/common/iterate.go +++ b/pkg/local_object_storage/blobstor/common/iterate.go @@ -1,6 +1,6 @@ package common -import oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" +import oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" // IterationElement represents a unit of elements through which Iterate operation passes. type IterationElement struct { diff --git a/pkg/local_object_storage/blobstor/common/put.go b/pkg/local_object_storage/blobstor/common/put.go index 51bb9624e..8d52dbe79 100644 --- a/pkg/local_object_storage/blobstor/common/put.go +++ b/pkg/local_object_storage/blobstor/common/put.go @@ -1,8 +1,8 @@ package common import ( - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" ) // PutPrm groups the parameters of Put operation. diff --git a/pkg/local_object_storage/blobstor/common/rebuild.go b/pkg/local_object_storage/blobstor/common/rebuild.go index 9f629ef8c..6adf8eb70 100644 --- a/pkg/local_object_storage/blobstor/common/rebuild.go +++ b/pkg/local_object_storage/blobstor/common/rebuild.go @@ -3,7 +3,7 @@ package common import ( "context" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" ) type RebuildRes struct { diff --git a/pkg/local_object_storage/blobstor/compression/compress.go b/pkg/local_object_storage/blobstor/compression/compress.go index 85ab47692..b27a0346d 100644 --- a/pkg/local_object_storage/blobstor/compression/compress.go +++ b/pkg/local_object_storage/blobstor/compression/compress.go @@ -4,7 +4,7 @@ import ( "bytes" "strings" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" "github.com/klauspost/compress" "github.com/klauspost/compress/zstd" ) diff --git a/pkg/local_object_storage/blobstor/delete.go b/pkg/local_object_storage/blobstor/delete.go index 8930980a6..517ad77d2 100644 --- a/pkg/local_object_storage/blobstor/delete.go +++ b/pkg/local_object_storage/blobstor/delete.go @@ -6,8 +6,8 @@ import ( "time" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" ) diff --git a/pkg/local_object_storage/blobstor/exists_test.go b/pkg/local_object_storage/blobstor/exists_test.go index 783c198b2..1c23fc466 100644 --- a/pkg/local_object_storage/blobstor/exists_test.go +++ b/pkg/local_object_storage/blobstor/exists_test.go @@ -8,9 +8,9 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/teststore" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" - cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id/test" "github.com/stretchr/testify/require" ) diff --git a/pkg/local_object_storage/blobstor/fstree/fstree.go b/pkg/local_object_storage/blobstor/fstree/fstree.go index 76ce5bf17..87e53e306 100644 --- a/pkg/local_object_storage/blobstor/fstree/fstree.go +++ b/pkg/local_object_storage/blobstor/fstree/fstree.go @@ -17,13 +17,13 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/compression" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" "go.uber.org/zap" diff --git a/pkg/local_object_storage/blobstor/fstree/fstree_test.go b/pkg/local_object_storage/blobstor/fstree/fstree_test.go index b81ce43f1..de4f203a2 100644 --- a/pkg/local_object_storage/blobstor/fstree/fstree_test.go +++ b/pkg/local_object_storage/blobstor/fstree/fstree_test.go @@ -7,8 +7,8 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id/test" "github.com/stretchr/testify/require" "golang.org/x/sync/errgroup" ) diff --git a/pkg/local_object_storage/blobstor/fstree/fstree_write_generic.go b/pkg/local_object_storage/blobstor/fstree/fstree_write_generic.go index 8b2622885..57d366537 100644 --- a/pkg/local_object_storage/blobstor/fstree/fstree_write_generic.go +++ b/pkg/local_object_storage/blobstor/fstree/fstree_write_generic.go @@ -10,8 +10,8 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" utilSync "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/sync" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" ) type writer interface { diff --git a/pkg/local_object_storage/blobstor/fstree/fstree_write_linux.go b/pkg/local_object_storage/blobstor/fstree/fstree_write_linux.go index efc5a3d3d..fa8edaab5 100644 --- a/pkg/local_object_storage/blobstor/fstree/fstree_write_linux.go +++ b/pkg/local_object_storage/blobstor/fstree/fstree_write_linux.go @@ -9,7 +9,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" "golang.org/x/sys/unix" ) diff --git a/pkg/local_object_storage/blobstor/get.go b/pkg/local_object_storage/blobstor/get.go index d00ef2f21..a56b096fa 100644 --- a/pkg/local_object_storage/blobstor/get.go +++ b/pkg/local_object_storage/blobstor/get.go @@ -7,9 +7,9 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" ) diff --git a/pkg/local_object_storage/blobstor/get_range.go b/pkg/local_object_storage/blobstor/get_range.go index 9bded4720..1ee9512c7 100644 --- a/pkg/local_object_storage/blobstor/get_range.go +++ b/pkg/local_object_storage/blobstor/get_range.go @@ -8,9 +8,9 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" ) diff --git a/pkg/local_object_storage/blobstor/internal/blobstortest/common.go b/pkg/local_object_storage/blobstor/internal/blobstortest/common.go index c08e39bf1..f6f2340d8 100644 --- a/pkg/local_object_storage/blobstor/internal/blobstortest/common.go +++ b/pkg/local_object_storage/blobstor/internal/blobstortest/common.go @@ -8,10 +8,10 @@ import ( objectCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" - cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + oidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id/test" "github.com/stretchr/testify/require" ) diff --git a/pkg/local_object_storage/blobstor/internal/blobstortest/delete.go b/pkg/local_object_storage/blobstor/internal/blobstortest/delete.go index f551cbf5f..fb8af054b 100644 --- a/pkg/local_object_storage/blobstor/internal/blobstortest/delete.go +++ b/pkg/local_object_storage/blobstor/internal/blobstortest/delete.go @@ -5,8 +5,8 @@ import ( "testing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + oidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id/test" "github.com/stretchr/testify/require" ) diff --git a/pkg/local_object_storage/blobstor/internal/blobstortest/exists.go b/pkg/local_object_storage/blobstor/internal/blobstortest/exists.go index 29d8bafee..b42ed07fe 100644 --- a/pkg/local_object_storage/blobstor/internal/blobstortest/exists.go +++ b/pkg/local_object_storage/blobstor/internal/blobstortest/exists.go @@ -5,7 +5,7 @@ import ( "testing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" - oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" + oidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id/test" "github.com/stretchr/testify/require" ) diff --git a/pkg/local_object_storage/blobstor/internal/blobstortest/get.go b/pkg/local_object_storage/blobstor/internal/blobstortest/get.go index 65c0c3133..3341ba006 100644 --- a/pkg/local_object_storage/blobstor/internal/blobstortest/get.go +++ b/pkg/local_object_storage/blobstor/internal/blobstortest/get.go @@ -5,8 +5,8 @@ import ( "testing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + oidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id/test" "github.com/stretchr/testify/require" ) diff --git a/pkg/local_object_storage/blobstor/internal/blobstortest/get_range.go b/pkg/local_object_storage/blobstor/internal/blobstortest/get_range.go index 9b99c12d5..77792f024 100644 --- a/pkg/local_object_storage/blobstor/internal/blobstortest/get_range.go +++ b/pkg/local_object_storage/blobstor/internal/blobstortest/get_range.go @@ -6,9 +6,9 @@ import ( "testing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" - oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + oidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id/test" "github.com/stretchr/testify/require" ) diff --git a/pkg/local_object_storage/blobstor/iterate.go b/pkg/local_object_storage/blobstor/iterate.go index f213d7547..a69e37333 100644 --- a/pkg/local_object_storage/blobstor/iterate.go +++ b/pkg/local_object_storage/blobstor/iterate.go @@ -7,8 +7,8 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" "go.uber.org/zap" diff --git a/pkg/local_object_storage/blobstor/iterate_test.go b/pkg/local_object_storage/blobstor/iterate_test.go index 079728380..b4e734557 100644 --- a/pkg/local_object_storage/blobstor/iterate_test.go +++ b/pkg/local_object_storage/blobstor/iterate_test.go @@ -8,8 +8,8 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + oidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id/test" "github.com/stretchr/testify/require" ) diff --git a/pkg/local_object_storage/blobstor/logger.go b/pkg/local_object_storage/blobstor/logger.go index 7e057a0e3..731d79d79 100644 --- a/pkg/local_object_storage/blobstor/logger.go +++ b/pkg/local_object_storage/blobstor/logger.go @@ -2,8 +2,8 @@ package blobstor import ( storagelog "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/log" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" ) const ( diff --git a/pkg/local_object_storage/blobstor/memstore/memstore.go b/pkg/local_object_storage/blobstor/memstore/memstore.go index 39bed00bf..1063a9375 100644 --- a/pkg/local_object_storage/blobstor/memstore/memstore.go +++ b/pkg/local_object_storage/blobstor/memstore/memstore.go @@ -8,8 +8,8 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" ) const Type = "memstore" diff --git a/pkg/local_object_storage/blobstor/memstore/memstore_test.go b/pkg/local_object_storage/blobstor/memstore/memstore_test.go index bc9436350..01485e785 100644 --- a/pkg/local_object_storage/blobstor/memstore/memstore_test.go +++ b/pkg/local_object_storage/blobstor/memstore/memstore_test.go @@ -7,8 +7,8 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/internal/blobstortest" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "github.com/stretchr/testify/require" ) diff --git a/pkg/local_object_storage/blobstor/rebuild.go b/pkg/local_object_storage/blobstor/rebuild.go index 101c60752..fd021035b 100644 --- a/pkg/local_object_storage/blobstor/rebuild.go +++ b/pkg/local_object_storage/blobstor/rebuild.go @@ -5,7 +5,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "go.uber.org/zap" ) diff --git a/pkg/local_object_storage/engine/container.go b/pkg/local_object_storage/engine/container.go index e45f502ac..0db024901 100644 --- a/pkg/local_object_storage/engine/container.go +++ b/pkg/local_object_storage/engine/container.go @@ -4,7 +4,7 @@ import ( "context" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" "go.uber.org/zap" ) diff --git a/pkg/local_object_storage/engine/control_test.go b/pkg/local_object_storage/engine/control_test.go index 6bf6beac6..70bf2ac4b 100644 --- a/pkg/local_object_storage/engine/control_test.go +++ b/pkg/local_object_storage/engine/control_test.go @@ -21,8 +21,8 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" - cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" "github.com/stretchr/testify/require" "go.etcd.io/bbolt" ) diff --git a/pkg/local_object_storage/engine/delete.go b/pkg/local_object_storage/engine/delete.go index 68a7325c6..0d2ab3a68 100644 --- a/pkg/local_object_storage/engine/delete.go +++ b/pkg/local_object_storage/engine/delete.go @@ -6,12 +6,12 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" "go.uber.org/zap" diff --git a/pkg/local_object_storage/engine/delete_test.go b/pkg/local_object_storage/engine/delete_test.go index 4a6758012..ec0569641 100644 --- a/pkg/local_object_storage/engine/delete_test.go +++ b/pkg/local_object_storage/engine/delete_test.go @@ -7,12 +7,12 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + oidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id/test" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" - cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" "github.com/stretchr/testify/require" ) diff --git a/pkg/local_object_storage/engine/engine.go b/pkg/local_object_storage/engine/engine.go index e03a08abc..7ceca83d2 100644 --- a/pkg/local_object_storage/engine/engine.go +++ b/pkg/local_object_storage/engine/engine.go @@ -12,9 +12,9 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "go.uber.org/zap" ) diff --git a/pkg/local_object_storage/engine/engine_test.go b/pkg/local_object_storage/engine/engine_test.go index b6858df49..5e820664e 100644 --- a/pkg/local_object_storage/engine/engine_test.go +++ b/pkg/local_object_storage/engine/engine_test.go @@ -14,10 +14,10 @@ import ( meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id/test" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" - cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" "git.frostfs.info/TrueCloudLab/hrw" "github.com/panjf2000/ants/v2" "github.com/stretchr/testify/require" diff --git a/pkg/local_object_storage/engine/error_test.go b/pkg/local_object_storage/engine/error_test.go index 7f48da08a..c900a29e7 100644 --- a/pkg/local_object_storage/engine/error_test.go +++ b/pkg/local_object_storage/engine/error_test.go @@ -17,9 +17,9 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" - cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "github.com/stretchr/testify/require" ) diff --git a/pkg/local_object_storage/engine/evacuate.go b/pkg/local_object_storage/engine/evacuate.go index 81fe47e65..90aba9cae 100644 --- a/pkg/local_object_storage/engine/evacuate.go +++ b/pkg/local_object_storage/engine/evacuate.go @@ -14,12 +14,12 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "git.frostfs.info/TrueCloudLab/hrw" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" diff --git a/pkg/local_object_storage/engine/evacuate_test.go b/pkg/local_object_storage/engine/evacuate_test.go index e8d9a449f..1cd8a4ee5 100644 --- a/pkg/local_object_storage/engine/evacuate_test.go +++ b/pkg/local_object_storage/engine/evacuate_test.go @@ -17,11 +17,11 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "github.com/stretchr/testify/require" "golang.org/x/sync/errgroup" ) diff --git a/pkg/local_object_storage/engine/exists.go b/pkg/local_object_storage/engine/exists.go index ee4dad341..6805337cb 100644 --- a/pkg/local_object_storage/engine/exists.go +++ b/pkg/local_object_storage/engine/exists.go @@ -6,10 +6,10 @@ import ( "sync/atomic" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "golang.org/x/sync/errgroup" ) diff --git a/pkg/local_object_storage/engine/get.go b/pkg/local_object_storage/engine/get.go index f77c44226..6346da128 100644 --- a/pkg/local_object_storage/engine/get.go +++ b/pkg/local_object_storage/engine/get.go @@ -8,12 +8,12 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" "go.uber.org/zap" diff --git a/pkg/local_object_storage/engine/head.go b/pkg/local_object_storage/engine/head.go index ba5e7cc1d..6f7177d5e 100644 --- a/pkg/local_object_storage/engine/head.go +++ b/pkg/local_object_storage/engine/head.go @@ -7,11 +7,11 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" ) // HeadPrm groups the parameters of Head operation. diff --git a/pkg/local_object_storage/engine/head_test.go b/pkg/local_object_storage/engine/head_test.go index 5afc50f07..76e114441 100644 --- a/pkg/local_object_storage/engine/head_test.go +++ b/pkg/local_object_storage/engine/head_test.go @@ -6,9 +6,9 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" - cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "github.com/stretchr/testify/require" ) diff --git a/pkg/local_object_storage/engine/inhume.go b/pkg/local_object_storage/engine/inhume.go index 80eda2204..c7e6ba897 100644 --- a/pkg/local_object_storage/engine/inhume.go +++ b/pkg/local_object_storage/engine/inhume.go @@ -7,13 +7,13 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" "go.uber.org/zap" diff --git a/pkg/local_object_storage/engine/inhume_test.go b/pkg/local_object_storage/engine/inhume_test.go index 9daa113f8..a06fa84ab 100644 --- a/pkg/local_object_storage/engine/inhume_test.go +++ b/pkg/local_object_storage/engine/inhume_test.go @@ -7,8 +7,8 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" - cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" "github.com/stretchr/testify/require" ) diff --git a/pkg/local_object_storage/engine/list_test.go b/pkg/local_object_storage/engine/list_test.go index 7bb1ac0fa..e86155c30 100644 --- a/pkg/local_object_storage/engine/list_test.go +++ b/pkg/local_object_storage/engine/list_test.go @@ -12,9 +12,9 @@ import ( meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" - cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "github.com/stretchr/testify/require" ) diff --git a/pkg/local_object_storage/engine/lock.go b/pkg/local_object_storage/engine/lock.go index 5ad603421..5738bbe92 100644 --- a/pkg/local_object_storage/engine/lock.go +++ b/pkg/local_object_storage/engine/lock.go @@ -6,11 +6,11 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" ) diff --git a/pkg/local_object_storage/engine/lock_test.go b/pkg/local_object_storage/engine/lock_test.go index 7fa7c27ef..c539701ee 100644 --- a/pkg/local_object_storage/engine/lock_test.go +++ b/pkg/local_object_storage/engine/lock_test.go @@ -6,17 +6,17 @@ import ( "testing" "time" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" objectcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + oidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id/test" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" - cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" "github.com/panjf2000/ants/v2" "github.com/stretchr/testify/require" ) diff --git a/pkg/local_object_storage/engine/put.go b/pkg/local_object_storage/engine/put.go index c1cd29cb8..6df650b17 100644 --- a/pkg/local_object_storage/engine/put.go +++ b/pkg/local_object_storage/engine/put.go @@ -9,12 +9,12 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" "go.uber.org/zap" diff --git a/pkg/local_object_storage/engine/range.go b/pkg/local_object_storage/engine/range.go index e45845d6c..8048e6fc7 100644 --- a/pkg/local_object_storage/engine/range.go +++ b/pkg/local_object_storage/engine/range.go @@ -9,12 +9,12 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" "go.uber.org/zap" diff --git a/pkg/local_object_storage/engine/remove_copies.go b/pkg/local_object_storage/engine/remove_copies.go index 00562e4cb..90b659f42 100644 --- a/pkg/local_object_storage/engine/remove_copies.go +++ b/pkg/local_object_storage/engine/remove_copies.go @@ -7,7 +7,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/hrw" "go.uber.org/zap" "golang.org/x/sync/errgroup" diff --git a/pkg/local_object_storage/engine/remove_copies_test.go b/pkg/local_object_storage/engine/remove_copies_test.go index 99963576c..30431c893 100644 --- a/pkg/local_object_storage/engine/remove_copies_test.go +++ b/pkg/local_object_storage/engine/remove_copies_test.go @@ -10,9 +10,9 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/teststore" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" - cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "github.com/stretchr/testify/require" ) diff --git a/pkg/local_object_storage/engine/select.go b/pkg/local_object_storage/engine/select.go index 6a8c9fab9..83109e83a 100644 --- a/pkg/local_object_storage/engine/select.go +++ b/pkg/local_object_storage/engine/select.go @@ -4,10 +4,10 @@ import ( "context" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" ) diff --git a/pkg/local_object_storage/engine/shards.go b/pkg/local_object_storage/engine/shards.go index 4bbf7eff0..8a29561b7 100644 --- a/pkg/local_object_storage/engine/shards.go +++ b/pkg/local_object_storage/engine/shards.go @@ -11,7 +11,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/hrw" "github.com/google/uuid" "github.com/panjf2000/ants/v2" diff --git a/pkg/local_object_storage/engine/tree.go b/pkg/local_object_storage/engine/tree.go index f50b9cb68..03b12db36 100644 --- a/pkg/local_object_storage/engine/tree.go +++ b/pkg/local_object_storage/engine/tree.go @@ -7,9 +7,9 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" + cidSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - cidSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" "go.uber.org/zap" diff --git a/pkg/local_object_storage/engine/tree_test.go b/pkg/local_object_storage/engine/tree_test.go index 2739058e9..3fe0fa598 100644 --- a/pkg/local_object_storage/engine/tree_test.go +++ b/pkg/local_object_storage/engine/tree_test.go @@ -7,8 +7,8 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" - cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" "github.com/stretchr/testify/require" ) diff --git a/pkg/local_object_storage/internal/testutil/generators.go b/pkg/local_object_storage/internal/testutil/generators.go index 383c596af..d4d8cbfaf 100644 --- a/pkg/local_object_storage/internal/testutil/generators.go +++ b/pkg/local_object_storage/internal/testutil/generators.go @@ -5,9 +5,9 @@ import ( "sync/atomic" "testing" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "github.com/stretchr/testify/require" "golang.org/x/exp/rand" ) diff --git a/pkg/local_object_storage/internal/testutil/object.go b/pkg/local_object_storage/internal/testutil/object.go index 60e9211d5..565eaf89e 100644 --- a/pkg/local_object_storage/internal/testutil/object.go +++ b/pkg/local_object_storage/internal/testutil/object.go @@ -3,13 +3,13 @@ package testutil import ( "crypto/sha256" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/checksum" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" - usertest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user/test" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/version" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/checksum" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id/test" + usertest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user/test" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/version" "git.frostfs.info/TrueCloudLab/tzhash/tz" "golang.org/x/exp/rand" ) diff --git a/pkg/local_object_storage/metabase/children.go b/pkg/local_object_storage/metabase/children.go index acd367951..be4194029 100644 --- a/pkg/local_object_storage/metabase/children.go +++ b/pkg/local_object_storage/metabase/children.go @@ -5,8 +5,8 @@ import ( "time" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.etcd.io/bbolt" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" diff --git a/pkg/local_object_storage/metabase/containers.go b/pkg/local_object_storage/metabase/containers.go index 472b2affc..fac7ad955 100644 --- a/pkg/local_object_storage/metabase/containers.go +++ b/pkg/local_object_storage/metabase/containers.go @@ -6,8 +6,8 @@ import ( "time" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "go.etcd.io/bbolt" ) diff --git a/pkg/local_object_storage/metabase/containers_test.go b/pkg/local_object_storage/metabase/containers_test.go index a90cd9d97..f6fb356e1 100644 --- a/pkg/local_object_storage/metabase/containers_test.go +++ b/pkg/local_object_storage/metabase/containers_test.go @@ -8,10 +8,10 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id/test" "github.com/stretchr/testify/require" ) diff --git a/pkg/local_object_storage/metabase/control_test.go b/pkg/local_object_storage/metabase/control_test.go index 0354a5eb6..e6b8ee546 100644 --- a/pkg/local_object_storage/metabase/control_test.go +++ b/pkg/local_object_storage/metabase/control_test.go @@ -7,9 +7,9 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + oidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id/test" "github.com/stretchr/testify/require" ) diff --git a/pkg/local_object_storage/metabase/counter.go b/pkg/local_object_storage/metabase/counter.go index dc85b4697..6ad394334 100644 --- a/pkg/local_object_storage/metabase/counter.go +++ b/pkg/local_object_storage/metabase/counter.go @@ -9,10 +9,10 @@ import ( "time" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.etcd.io/bbolt" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" diff --git a/pkg/local_object_storage/metabase/counter_test.go b/pkg/local_object_storage/metabase/counter_test.go index 1797fc0aa..28e10f1da 100644 --- a/pkg/local_object_storage/metabase/counter_test.go +++ b/pkg/local_object_storage/metabase/counter_test.go @@ -7,10 +7,10 @@ import ( objectcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + oidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id/test" "github.com/stretchr/testify/require" ) diff --git a/pkg/local_object_storage/metabase/db.go b/pkg/local_object_storage/metabase/db.go index f5341ff2e..8a72e2e08 100644 --- a/pkg/local_object_storage/metabase/db.go +++ b/pkg/local_object_storage/metabase/db.go @@ -11,10 +11,10 @@ import ( "sync" "time" - v2object "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + v2object "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "github.com/mr-tron/base58" "go.etcd.io/bbolt" "go.uber.org/zap" diff --git a/pkg/local_object_storage/metabase/db_test.go b/pkg/local_object_storage/metabase/db_test.go index 01e1ed2bc..16fa0e8be 100644 --- a/pkg/local_object_storage/metabase/db_test.go +++ b/pkg/local_object_storage/metabase/db_test.go @@ -6,13 +6,13 @@ import ( "strconv" "testing" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "github.com/stretchr/testify/require" ) diff --git a/pkg/local_object_storage/metabase/delete.go b/pkg/local_object_storage/metabase/delete.go index e591b8661..e220ad82d 100644 --- a/pkg/local_object_storage/metabase/delete.go +++ b/pkg/local_object_storage/metabase/delete.go @@ -10,11 +10,11 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" storagelog "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/log" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.etcd.io/bbolt" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" diff --git a/pkg/local_object_storage/metabase/delete_test.go b/pkg/local_object_storage/metabase/delete_test.go index 2053874d0..f679f531a 100644 --- a/pkg/local_object_storage/metabase/delete_test.go +++ b/pkg/local_object_storage/metabase/delete_test.go @@ -8,11 +8,11 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + oidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id/test" "github.com/stretchr/testify/require" ) diff --git a/pkg/local_object_storage/metabase/exists.go b/pkg/local_object_storage/metabase/exists.go index bca18e21f..c58767f6b 100644 --- a/pkg/local_object_storage/metabase/exists.go +++ b/pkg/local_object_storage/metabase/exists.go @@ -5,14 +5,14 @@ import ( "fmt" "time" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.etcd.io/bbolt" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" diff --git a/pkg/local_object_storage/metabase/exists_test.go b/pkg/local_object_storage/metabase/exists_test.go index 0087c1e31..d3587ecdb 100644 --- a/pkg/local_object_storage/metabase/exists_test.go +++ b/pkg/local_object_storage/metabase/exists_test.go @@ -7,10 +7,10 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id/test" "github.com/stretchr/testify/require" ) diff --git a/pkg/local_object_storage/metabase/expired.go b/pkg/local_object_storage/metabase/expired.go index aa2cb6f20..39a0aff2c 100644 --- a/pkg/local_object_storage/metabase/expired.go +++ b/pkg/local_object_storage/metabase/expired.go @@ -7,11 +7,11 @@ import ( "strconv" "time" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.etcd.io/bbolt" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" diff --git a/pkg/local_object_storage/metabase/expired_test.go b/pkg/local_object_storage/metabase/expired_test.go index bb98745ee..66f2580ec 100644 --- a/pkg/local_object_storage/metabase/expired_test.go +++ b/pkg/local_object_storage/metabase/expired_test.go @@ -5,9 +5,9 @@ import ( "testing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" - cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "github.com/stretchr/testify/require" ) diff --git a/pkg/local_object_storage/metabase/get.go b/pkg/local_object_storage/metabase/get.go index d18331a3d..9cd728ba0 100644 --- a/pkg/local_object_storage/metabase/get.go +++ b/pkg/local_object_storage/metabase/get.go @@ -7,11 +7,11 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.etcd.io/bbolt" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" diff --git a/pkg/local_object_storage/metabase/get_test.go b/pkg/local_object_storage/metabase/get_test.go index af6b41327..ed74e2a8c 100644 --- a/pkg/local_object_storage/metabase/get_test.go +++ b/pkg/local_object_storage/metabase/get_test.go @@ -12,11 +12,11 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + oidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id/test" "github.com/stretchr/testify/require" ) diff --git a/pkg/local_object_storage/metabase/graveyard.go b/pkg/local_object_storage/metabase/graveyard.go index df9a3d302..f106e5d87 100644 --- a/pkg/local_object_storage/metabase/graveyard.go +++ b/pkg/local_object_storage/metabase/graveyard.go @@ -8,8 +8,8 @@ import ( "time" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.etcd.io/bbolt" ) diff --git a/pkg/local_object_storage/metabase/graveyard_test.go b/pkg/local_object_storage/metabase/graveyard_test.go index 75c7e2852..31a6a9737 100644 --- a/pkg/local_object_storage/metabase/graveyard_test.go +++ b/pkg/local_object_storage/metabase/graveyard_test.go @@ -7,8 +7,8 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + oidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id/test" "github.com/stretchr/testify/require" ) diff --git a/pkg/local_object_storage/metabase/inhume.go b/pkg/local_object_storage/metabase/inhume.go index 250504120..9b91934e0 100644 --- a/pkg/local_object_storage/metabase/inhume.go +++ b/pkg/local_object_storage/metabase/inhume.go @@ -10,11 +10,11 @@ import ( storagelog "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/log" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.etcd.io/bbolt" ) diff --git a/pkg/local_object_storage/metabase/inhume_test.go b/pkg/local_object_storage/metabase/inhume_test.go index 163fbec2a..aa3c7a8da 100644 --- a/pkg/local_object_storage/metabase/inhume_test.go +++ b/pkg/local_object_storage/metabase/inhume_test.go @@ -7,10 +7,10 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + oidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id/test" "github.com/stretchr/testify/require" ) diff --git a/pkg/local_object_storage/metabase/iterators.go b/pkg/local_object_storage/metabase/iterators.go index 7b60b7d50..2d9aaa57e 100644 --- a/pkg/local_object_storage/metabase/iterators.go +++ b/pkg/local_object_storage/metabase/iterators.go @@ -7,14 +7,14 @@ import ( "strconv" "time" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "go.etcd.io/bbolt" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" diff --git a/pkg/local_object_storage/metabase/iterators_test.go b/pkg/local_object_storage/metabase/iterators_test.go index 54d56d923..c433d57cc 100644 --- a/pkg/local_object_storage/metabase/iterators_test.go +++ b/pkg/local_object_storage/metabase/iterators_test.go @@ -5,13 +5,13 @@ import ( "strconv" "testing" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" object2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + oidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id/test" "github.com/stretchr/testify/require" ) diff --git a/pkg/local_object_storage/metabase/list.go b/pkg/local_object_storage/metabase/list.go index f7a314452..5f3719cc3 100644 --- a/pkg/local_object_storage/metabase/list.go +++ b/pkg/local_object_storage/metabase/list.go @@ -7,10 +7,10 @@ import ( objectcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.etcd.io/bbolt" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" diff --git a/pkg/local_object_storage/metabase/list_test.go b/pkg/local_object_storage/metabase/list_test.go index 25c0e35bd..e82a12a12 100644 --- a/pkg/local_object_storage/metabase/list_test.go +++ b/pkg/local_object_storage/metabase/list_test.go @@ -9,9 +9,9 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" - cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id/test" "github.com/stretchr/testify/require" "go.etcd.io/bbolt" ) diff --git a/pkg/local_object_storage/metabase/lock.go b/pkg/local_object_storage/metabase/lock.go index 0bc2b06f0..531825762 100644 --- a/pkg/local_object_storage/metabase/lock.go +++ b/pkg/local_object_storage/metabase/lock.go @@ -8,11 +8,11 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.etcd.io/bbolt" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" diff --git a/pkg/local_object_storage/metabase/lock_test.go b/pkg/local_object_storage/metabase/lock_test.go index 2d7bfc1cc..34a15203b 100644 --- a/pkg/local_object_storage/metabase/lock_test.go +++ b/pkg/local_object_storage/metabase/lock_test.go @@ -7,12 +7,12 @@ import ( objectcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" - cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" - objecttest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/test" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + oidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id/test" + objecttest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/test" "github.com/stretchr/testify/require" ) diff --git a/pkg/local_object_storage/metabase/put.go b/pkg/local_object_storage/metabase/put.go index 429d981fe..7a413ac48 100644 --- a/pkg/local_object_storage/metabase/put.go +++ b/pkg/local_object_storage/metabase/put.go @@ -12,10 +12,10 @@ import ( storagelog "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/log" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "github.com/nspcc-dev/neo-go/pkg/io" "go.etcd.io/bbolt" "go.opentelemetry.io/otel/attribute" diff --git a/pkg/local_object_storage/metabase/put_test.go b/pkg/local_object_storage/metabase/put_test.go index 84e4029f2..cc6daf448 100644 --- a/pkg/local_object_storage/metabase/put_test.go +++ b/pkg/local_object_storage/metabase/put_test.go @@ -11,10 +11,10 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + objecttest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id/test" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/rand" - cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - objecttest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" "github.com/stretchr/testify/require" ) diff --git a/pkg/local_object_storage/metabase/select.go b/pkg/local_object_storage/metabase/select.go index e5321c794..0f86012f0 100644 --- a/pkg/local_object_storage/metabase/select.go +++ b/pkg/local_object_storage/metabase/select.go @@ -8,13 +8,13 @@ import ( "strings" "time" - v2object "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + v2object "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.etcd.io/bbolt" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" diff --git a/pkg/local_object_storage/metabase/select_test.go b/pkg/local_object_storage/metabase/select_test.go index 9ff2fd65e..78762b26e 100644 --- a/pkg/local_object_storage/metabase/select_test.go +++ b/pkg/local_object_storage/metabase/select_test.go @@ -6,16 +6,16 @@ import ( "strconv" "testing" - v2object "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + v2object "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" - cidSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/version" + cidSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + oidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id/test" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/version" "github.com/stretchr/testify/require" ) diff --git a/pkg/local_object_storage/metabase/storage_id.go b/pkg/local_object_storage/metabase/storage_id.go index f9767935c..ae69d3fa6 100644 --- a/pkg/local_object_storage/metabase/storage_id.go +++ b/pkg/local_object_storage/metabase/storage_id.go @@ -6,8 +6,8 @@ import ( "time" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.etcd.io/bbolt" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" diff --git a/pkg/local_object_storage/metabase/storage_id_test.go b/pkg/local_object_storage/metabase/storage_id_test.go index aaf6480ab..1a8c8af0f 100644 --- a/pkg/local_object_storage/metabase/storage_id_test.go +++ b/pkg/local_object_storage/metabase/storage_id_test.go @@ -7,7 +7,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "github.com/stretchr/testify/require" ) diff --git a/pkg/local_object_storage/metabase/util.go b/pkg/local_object_storage/metabase/util.go index d46a421a3..883e61cab 100644 --- a/pkg/local_object_storage/metabase/util.go +++ b/pkg/local_object_storage/metabase/util.go @@ -5,9 +5,9 @@ import ( "crypto/sha256" "errors" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "go.etcd.io/bbolt" ) diff --git a/pkg/local_object_storage/pilorama/batch.go b/pkg/local_object_storage/pilorama/batch.go index c65488b74..6bfbd929e 100644 --- a/pkg/local_object_storage/pilorama/batch.go +++ b/pkg/local_object_storage/pilorama/batch.go @@ -6,7 +6,7 @@ import ( "sync" "time" - cidSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + cidSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" "go.etcd.io/bbolt" ) diff --git a/pkg/local_object_storage/pilorama/bench_test.go b/pkg/local_object_storage/pilorama/bench_test.go index 22b951a41..6e196e056 100644 --- a/pkg/local_object_storage/pilorama/bench_test.go +++ b/pkg/local_object_storage/pilorama/bench_test.go @@ -9,7 +9,7 @@ import ( "testing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" - cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" "github.com/stretchr/testify/require" ) diff --git a/pkg/local_object_storage/pilorama/boltdb.go b/pkg/local_object_storage/pilorama/boltdb.go index 17133e8f3..19cf00e58 100644 --- a/pkg/local_object_storage/pilorama/boltdb.go +++ b/pkg/local_object_storage/pilorama/boltdb.go @@ -16,9 +16,9 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" + cidSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - cidSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "github.com/nspcc-dev/neo-go/pkg/io" "go.etcd.io/bbolt" "go.opentelemetry.io/otel/attribute" diff --git a/pkg/local_object_storage/pilorama/forest.go b/pkg/local_object_storage/pilorama/forest.go index dbfc9dccd..15862f940 100644 --- a/pkg/local_object_storage/pilorama/forest.go +++ b/pkg/local_object_storage/pilorama/forest.go @@ -8,7 +8,7 @@ import ( "strings" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" ) var errInvalidKeyFormat = errors.New("invalid format: key must be cid and treeID") diff --git a/pkg/local_object_storage/pilorama/forest_test.go b/pkg/local_object_storage/pilorama/forest_test.go index 383320eb9..1ceb4d8ac 100644 --- a/pkg/local_object_storage/pilorama/forest_test.go +++ b/pkg/local_object_storage/pilorama/forest_test.go @@ -12,9 +12,9 @@ import ( "time" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" - cidSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + cidSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" "github.com/stretchr/testify/require" "golang.org/x/sync/errgroup" ) diff --git a/pkg/local_object_storage/pilorama/interface.go b/pkg/local_object_storage/pilorama/interface.go index 5fefb2e27..37da668aa 100644 --- a/pkg/local_object_storage/pilorama/interface.go +++ b/pkg/local_object_storage/pilorama/interface.go @@ -5,7 +5,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" - cidSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + cidSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" ) // Forest represents CRDT tree. diff --git a/pkg/local_object_storage/shard/container.go b/pkg/local_object_storage/shard/container.go index 364649b50..d82bb7724 100644 --- a/pkg/local_object_storage/shard/container.go +++ b/pkg/local_object_storage/shard/container.go @@ -4,8 +4,8 @@ import ( "context" "fmt" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" ) diff --git a/pkg/local_object_storage/shard/control.go b/pkg/local_object_storage/shard/control.go index 774fe8045..bcc8d4666 100644 --- a/pkg/local_object_storage/shard/control.go +++ b/pkg/local_object_storage/shard/control.go @@ -10,10 +10,10 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.uber.org/zap" ) diff --git a/pkg/local_object_storage/shard/control_test.go b/pkg/local_object_storage/shard/control_test.go index d08747e13..135f947f9 100644 --- a/pkg/local_object_storage/shard/control_test.go +++ b/pkg/local_object_storage/shard/control_test.go @@ -18,15 +18,15 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + oidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id/test" + objecttest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/test" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" - objecttest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/test" "github.com/stretchr/testify/require" "go.etcd.io/bbolt" ) diff --git a/pkg/local_object_storage/shard/delete.go b/pkg/local_object_storage/shard/delete.go index 44f6c6b48..4d592ace8 100644 --- a/pkg/local_object_storage/shard/delete.go +++ b/pkg/local_object_storage/shard/delete.go @@ -7,10 +7,10 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" "go.uber.org/zap" diff --git a/pkg/local_object_storage/shard/delete_test.go b/pkg/local_object_storage/shard/delete_test.go index 9f205fa5d..52b63c705 100644 --- a/pkg/local_object_storage/shard/delete_test.go +++ b/pkg/local_object_storage/shard/delete_test.go @@ -7,8 +7,8 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" "github.com/stretchr/testify/require" ) diff --git a/pkg/local_object_storage/shard/errors.go b/pkg/local_object_storage/shard/errors.go index 045ad1bba..65238d23c 100644 --- a/pkg/local_object_storage/shard/errors.go +++ b/pkg/local_object_storage/shard/errors.go @@ -5,7 +5,7 @@ import ( meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" ) var ErrShardDisabled = logicerr.New("shard disabled") diff --git a/pkg/local_object_storage/shard/exists.go b/pkg/local_object_storage/shard/exists.go index 7296426a6..0c29b29b4 100644 --- a/pkg/local_object_storage/shard/exists.go +++ b/pkg/local_object_storage/shard/exists.go @@ -5,8 +5,8 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" ) diff --git a/pkg/local_object_storage/shard/gc.go b/pkg/local_object_storage/shard/gc.go index 83be3259a..0cbb15459 100644 --- a/pkg/local_object_storage/shard/gc.go +++ b/pkg/local_object_storage/shard/gc.go @@ -8,11 +8,11 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.uber.org/zap" "golang.org/x/sync/errgroup" ) diff --git a/pkg/local_object_storage/shard/gc_internal_test.go b/pkg/local_object_storage/shard/gc_internal_test.go index 6a7941e04..6cc1beb15 100644 --- a/pkg/local_object_storage/shard/gc_internal_test.go +++ b/pkg/local_object_storage/shard/gc_internal_test.go @@ -14,12 +14,12 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "github.com/panjf2000/ants/v2" "github.com/stretchr/testify/require" ) diff --git a/pkg/local_object_storage/shard/gc_test.go b/pkg/local_object_storage/shard/gc_test.go index a438b5def..ace3fdfb6 100644 --- a/pkg/local_object_storage/shard/gc_test.go +++ b/pkg/local_object_storage/shard/gc_test.go @@ -5,19 +5,19 @@ import ( "errors" "testing" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" objectCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + oidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id/test" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" - cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" "github.com/stretchr/testify/require" ) diff --git a/pkg/local_object_storage/shard/get.go b/pkg/local_object_storage/shard/get.go index 2e7c84bcd..4ff0298ed 100644 --- a/pkg/local_object_storage/shard/get.go +++ b/pkg/local_object_storage/shard/get.go @@ -10,12 +10,12 @@ import ( meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" "go.uber.org/zap" diff --git a/pkg/local_object_storage/shard/get_test.go b/pkg/local_object_storage/shard/get_test.go index 8a7c6972d..8826509c8 100644 --- a/pkg/local_object_storage/shard/get_test.go +++ b/pkg/local_object_storage/shard/get_test.go @@ -9,10 +9,10 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id/test" "github.com/stretchr/testify/require" ) diff --git a/pkg/local_object_storage/shard/head.go b/pkg/local_object_storage/shard/head.go index a0ec231af..25976c0ed 100644 --- a/pkg/local_object_storage/shard/head.go +++ b/pkg/local_object_storage/shard/head.go @@ -4,9 +4,9 @@ import ( "context" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" ) diff --git a/pkg/local_object_storage/shard/head_test.go b/pkg/local_object_storage/shard/head_test.go index 1f4631993..f1377a50b 100644 --- a/pkg/local_object_storage/shard/head_test.go +++ b/pkg/local_object_storage/shard/head_test.go @@ -8,9 +8,9 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" "github.com/stretchr/testify/require" ) diff --git a/pkg/local_object_storage/shard/inhume.go b/pkg/local_object_storage/shard/inhume.go index 746177c3a..e43178b0f 100644 --- a/pkg/local_object_storage/shard/inhume.go +++ b/pkg/local_object_storage/shard/inhume.go @@ -7,9 +7,9 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" "go.uber.org/zap" diff --git a/pkg/local_object_storage/shard/inhume_test.go b/pkg/local_object_storage/shard/inhume_test.go index 82754568f..3b91ed2a7 100644 --- a/pkg/local_object_storage/shard/inhume_test.go +++ b/pkg/local_object_storage/shard/inhume_test.go @@ -6,8 +6,8 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" "github.com/stretchr/testify/require" ) diff --git a/pkg/local_object_storage/shard/list.go b/pkg/local_object_storage/shard/list.go index d6e4d7e50..9215fa093 100644 --- a/pkg/local_object_storage/shard/list.go +++ b/pkg/local_object_storage/shard/list.go @@ -7,10 +7,10 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" objectcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" "go.uber.org/zap" diff --git a/pkg/local_object_storage/shard/list_test.go b/pkg/local_object_storage/shard/list_test.go index 8a49a36fd..bed04ec3d 100644 --- a/pkg/local_object_storage/shard/list_test.go +++ b/pkg/local_object_storage/shard/list_test.go @@ -7,7 +7,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" - cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" "github.com/stretchr/testify/require" "golang.org/x/sync/errgroup" ) diff --git a/pkg/local_object_storage/shard/lock.go b/pkg/local_object_storage/shard/lock.go index 52186cbfd..4bcd7bb79 100644 --- a/pkg/local_object_storage/shard/lock.go +++ b/pkg/local_object_storage/shard/lock.go @@ -5,9 +5,9 @@ import ( "fmt" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" ) diff --git a/pkg/local_object_storage/shard/lock_test.go b/pkg/local_object_storage/shard/lock_test.go index 91033efb7..4ca729525 100644 --- a/pkg/local_object_storage/shard/lock_test.go +++ b/pkg/local_object_storage/shard/lock_test.go @@ -11,13 +11,13 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/fstree" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + oidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id/test" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" - cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" "github.com/stretchr/testify/require" "go.uber.org/zap" ) diff --git a/pkg/local_object_storage/shard/metrics_test.go b/pkg/local_object_storage/shard/metrics_test.go index 2ab99eed3..9e0e20205 100644 --- a/pkg/local_object_storage/shard/metrics_test.go +++ b/pkg/local_object_storage/shard/metrics_test.go @@ -14,9 +14,9 @@ import ( meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "github.com/stretchr/testify/require" ) diff --git a/pkg/local_object_storage/shard/put.go b/pkg/local_object_storage/shard/put.go index d7a9e7012..cd76dc872 100644 --- a/pkg/local_object_storage/shard/put.go +++ b/pkg/local_object_storage/shard/put.go @@ -8,8 +8,8 @@ import ( objectCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" "go.uber.org/zap" diff --git a/pkg/local_object_storage/shard/range.go b/pkg/local_object_storage/shard/range.go index 9491543c4..b03d494a3 100644 --- a/pkg/local_object_storage/shard/range.go +++ b/pkg/local_object_storage/shard/range.go @@ -8,10 +8,10 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" ) diff --git a/pkg/local_object_storage/shard/range_test.go b/pkg/local_object_storage/shard/range_test.go index 5a8a29e0c..fafd46f83 100644 --- a/pkg/local_object_storage/shard/range_test.go +++ b/pkg/local_object_storage/shard/range_test.go @@ -13,9 +13,9 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/fstree" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "github.com/stretchr/testify/require" ) diff --git a/pkg/local_object_storage/shard/rebuilder.go b/pkg/local_object_storage/shard/rebuilder.go index f18573c57..266f70e62 100644 --- a/pkg/local_object_storage/shard/rebuilder.go +++ b/pkg/local_object_storage/shard/rebuilder.go @@ -8,8 +8,8 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.uber.org/zap" ) diff --git a/pkg/local_object_storage/shard/reload_test.go b/pkg/local_object_storage/shard/reload_test.go index 511ce0721..1b0b81745 100644 --- a/pkg/local_object_storage/shard/reload_test.go +++ b/pkg/local_object_storage/shard/reload_test.go @@ -11,14 +11,14 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/fstree" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" + checksumtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/checksum/test" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id/test" + sessiontest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/session/test" + usertest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user/test" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/version" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" - checksumtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/checksum/test" - cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" - sessiontest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session/test" - usertest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user/test" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/version" "github.com/stretchr/testify/require" ) diff --git a/pkg/local_object_storage/shard/select.go b/pkg/local_object_storage/shard/select.go index 1615f5fbe..77ef21268 100644 --- a/pkg/local_object_storage/shard/select.go +++ b/pkg/local_object_storage/shard/select.go @@ -5,10 +5,10 @@ import ( "fmt" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" ) diff --git a/pkg/local_object_storage/shard/shard.go b/pkg/local_object_storage/shard/shard.go index 8368f6db4..6cd4ba3a2 100644 --- a/pkg/local_object_storage/shard/shard.go +++ b/pkg/local_object_storage/shard/shard.go @@ -12,10 +12,10 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.uber.org/zap" ) diff --git a/pkg/local_object_storage/shard/shard_test.go b/pkg/local_object_storage/shard/shard_test.go index a5483f632..6b8a35a7f 100644 --- a/pkg/local_object_storage/shard/shard_test.go +++ b/pkg/local_object_storage/shard/shard_test.go @@ -12,10 +12,10 @@ import ( meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "github.com/panjf2000/ants/v2" "github.com/stretchr/testify/require" ) diff --git a/pkg/local_object_storage/shard/shutdown_test.go b/pkg/local_object_storage/shard/shutdown_test.go index de00eabd1..285499bfa 100644 --- a/pkg/local_object_storage/shard/shutdown_test.go +++ b/pkg/local_object_storage/shard/shutdown_test.go @@ -8,8 +8,8 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache" - cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" "github.com/stretchr/testify/require" "golang.org/x/sync/errgroup" ) diff --git a/pkg/local_object_storage/shard/tree.go b/pkg/local_object_storage/shard/tree.go index e78f29277..11f009eba 100644 --- a/pkg/local_object_storage/shard/tree.go +++ b/pkg/local_object_storage/shard/tree.go @@ -6,8 +6,8 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" + cidSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - cidSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" ) diff --git a/pkg/local_object_storage/util/splitinfo.go b/pkg/local_object_storage/util/splitinfo.go index 6ae1c3e46..a26031690 100644 --- a/pkg/local_object_storage/util/splitinfo.go +++ b/pkg/local_object_storage/util/splitinfo.go @@ -1,7 +1,7 @@ package util import ( - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" ) // MergeSplitInfo ignores conflicts and rewrites `to` with non empty values diff --git a/pkg/local_object_storage/util/splitinfo_test.go b/pkg/local_object_storage/util/splitinfo_test.go index 0b7be5af3..ba35273a5 100644 --- a/pkg/local_object_storage/util/splitinfo_test.go +++ b/pkg/local_object_storage/util/splitinfo_test.go @@ -5,8 +5,8 @@ import ( "testing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "github.com/google/uuid" "github.com/stretchr/testify/require" ) diff --git a/pkg/local_object_storage/writecache/cachebbolt.go b/pkg/local_object_storage/writecache/cachebbolt.go index fdba8d409..6b467d29e 100644 --- a/pkg/local_object_storage/writecache/cachebbolt.go +++ b/pkg/local_object_storage/writecache/cachebbolt.go @@ -8,8 +8,8 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/fstree" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "go.etcd.io/bbolt" "go.uber.org/zap" ) diff --git a/pkg/local_object_storage/writecache/delete.go b/pkg/local_object_storage/writecache/delete.go index b1a0511ee..97a42754f 100644 --- a/pkg/local_object_storage/writecache/delete.go +++ b/pkg/local_object_storage/writecache/delete.go @@ -8,8 +8,8 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" storagelog "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/log" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.etcd.io/bbolt" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" diff --git a/pkg/local_object_storage/writecache/flush.go b/pkg/local_object_storage/writecache/flush.go index c3e19c4d2..1f773ef8a 100644 --- a/pkg/local_object_storage/writecache/flush.go +++ b/pkg/local_object_storage/writecache/flush.go @@ -13,9 +13,9 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "github.com/mr-tron/base58" "go.etcd.io/bbolt" "go.opentelemetry.io/otel/attribute" diff --git a/pkg/local_object_storage/writecache/flush_test.go b/pkg/local_object_storage/writecache/flush_test.go index 3c951bebe..d911fb60f 100644 --- a/pkg/local_object_storage/writecache/flush_test.go +++ b/pkg/local_object_storage/writecache/flush_test.go @@ -14,10 +14,10 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + oidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id/test" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" "github.com/stretchr/testify/require" "go.etcd.io/bbolt" "go.uber.org/zap" diff --git a/pkg/local_object_storage/writecache/get.go b/pkg/local_object_storage/writecache/get.go index bf26833bd..001b66047 100644 --- a/pkg/local_object_storage/writecache/get.go +++ b/pkg/local_object_storage/writecache/get.go @@ -8,10 +8,10 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.etcd.io/bbolt" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" diff --git a/pkg/local_object_storage/writecache/iterate.go b/pkg/local_object_storage/writecache/iterate.go index 9ec039f91..2bebbb79d 100644 --- a/pkg/local_object_storage/writecache/iterate.go +++ b/pkg/local_object_storage/writecache/iterate.go @@ -5,7 +5,7 @@ import ( "fmt" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "go.etcd.io/bbolt" ) diff --git a/pkg/local_object_storage/writecache/storage.go b/pkg/local_object_storage/writecache/storage.go index 6cc3b06d0..403b72efb 100644 --- a/pkg/local_object_storage/writecache/storage.go +++ b/pkg/local_object_storage/writecache/storage.go @@ -10,9 +10,9 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/fstree" storagelog "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/log" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.etcd.io/bbolt" "go.uber.org/zap" ) diff --git a/pkg/local_object_storage/writecache/writecache.go b/pkg/local_object_storage/writecache/writecache.go index 71dba61cf..ebc1d62e3 100644 --- a/pkg/local_object_storage/writecache/writecache.go +++ b/pkg/local_object_storage/writecache/writecache.go @@ -9,9 +9,9 @@ import ( meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" ) // Info groups the information about write-cache. diff --git a/pkg/morph/client/balance/balanceOf.go b/pkg/morph/client/balance/balanceOf.go index aae245acd..82d478928 100644 --- a/pkg/morph/client/balance/balanceOf.go +++ b/pkg/morph/client/balance/balanceOf.go @@ -5,7 +5,7 @@ import ( "math/big" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" "github.com/nspcc-dev/neo-go/pkg/encoding/address" ) diff --git a/pkg/morph/client/balance/transfer.go b/pkg/morph/client/balance/transfer.go index 08fb05289..be4f0382e 100644 --- a/pkg/morph/client/balance/transfer.go +++ b/pkg/morph/client/balance/transfer.go @@ -4,7 +4,7 @@ import ( "fmt" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" "github.com/nspcc-dev/neo-go/pkg/encoding/address" ) diff --git a/pkg/morph/client/container/containers_of.go b/pkg/morph/client/container/containers_of.go index c4db0fe6e..27a42ce80 100644 --- a/pkg/morph/client/container/containers_of.go +++ b/pkg/morph/client/container/containers_of.go @@ -5,8 +5,8 @@ import ( "fmt" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" ) diff --git a/pkg/morph/client/container/deletion_info.go b/pkg/morph/client/container/deletion_info.go index dda6bf98c..396686487 100644 --- a/pkg/morph/client/container/deletion_info.go +++ b/pkg/morph/client/container/deletion_info.go @@ -8,9 +8,9 @@ import ( containerContract "git.frostfs.info/TrueCloudLab/frostfs-contract/container" containercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" "github.com/mr-tron/base58" ) diff --git a/pkg/morph/client/container/eacl.go b/pkg/morph/client/container/eacl.go index 8e9455050..94a8d07c1 100644 --- a/pkg/morph/client/container/eacl.go +++ b/pkg/morph/client/container/eacl.go @@ -4,13 +4,13 @@ import ( "crypto/sha256" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/eacl" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/session" ) // GetEACL reads the extended ACL table from FrostFS system diff --git a/pkg/morph/client/container/eacl_set.go b/pkg/morph/client/container/eacl_set.go index c68104593..718043ebb 100644 --- a/pkg/morph/client/container/eacl_set.go +++ b/pkg/morph/client/container/eacl_set.go @@ -3,7 +3,7 @@ package container import ( "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" containercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" ) diff --git a/pkg/morph/client/container/get.go b/pkg/morph/client/container/get.go index 6715f870f..a159a7899 100644 --- a/pkg/morph/client/container/get.go +++ b/pkg/morph/client/container/get.go @@ -5,13 +5,13 @@ import ( "fmt" "strings" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" containerContract "git.frostfs.info/TrueCloudLab/frostfs-contract/container" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" containercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/session" ) type containerSource Client diff --git a/pkg/morph/client/container/list.go b/pkg/morph/client/container/list.go index 6fed46c1a..8e0b43d86 100644 --- a/pkg/morph/client/container/list.go +++ b/pkg/morph/client/container/list.go @@ -4,8 +4,8 @@ import ( "fmt" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" ) // list returns a list of container identifiers belonging diff --git a/pkg/morph/client/container/load.go b/pkg/morph/client/container/load.go index b5263d7a6..b85390b75 100644 --- a/pkg/morph/client/container/load.go +++ b/pkg/morph/client/container/load.go @@ -4,10 +4,10 @@ import ( "crypto/sha256" "fmt" - v2refs "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + v2refs "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" ) // AnnounceLoadPrm groups parameters of AnnounceLoad operation. diff --git a/pkg/morph/client/container/put.go b/pkg/morph/client/container/put.go index ee323af00..80f83d250 100644 --- a/pkg/morph/client/container/put.go +++ b/pkg/morph/client/container/put.go @@ -3,11 +3,11 @@ package container import ( "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" containercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" ) // Put marshals container, and passes it to Wrapper's Put method diff --git a/pkg/morph/client/netmap/client.go b/pkg/morph/client/netmap/client.go index eafa097e9..68f7efc81 100644 --- a/pkg/morph/client/netmap/client.go +++ b/pkg/morph/client/netmap/client.go @@ -4,7 +4,7 @@ import ( "fmt" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn" "github.com/nspcc-dev/neo-go/pkg/util" ) diff --git a/pkg/morph/client/netmap/netmap.go b/pkg/morph/client/netmap/netmap.go index 61bbf5f17..8b8712b0e 100644 --- a/pkg/morph/client/netmap/netmap.go +++ b/pkg/morph/client/netmap/netmap.go @@ -5,7 +5,7 @@ import ( netmapcontract "git.frostfs.info/TrueCloudLab/frostfs-contract/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" ) diff --git a/pkg/morph/client/netmap/netmap_test.go b/pkg/morph/client/netmap/netmap_test.go index a8a306197..699e88a32 100644 --- a/pkg/morph/client/netmap/netmap_test.go +++ b/pkg/morph/client/netmap/netmap_test.go @@ -7,7 +7,7 @@ import ( "testing" netmapcontract "git.frostfs.info/TrueCloudLab/frostfs-contract/netmap" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" "github.com/stretchr/testify/require" ) diff --git a/pkg/morph/client/netmap/peer.go b/pkg/morph/client/netmap/peer.go index 764bbc899..88feb3c21 100644 --- a/pkg/morph/client/netmap/peer.go +++ b/pkg/morph/client/netmap/peer.go @@ -5,7 +5,7 @@ import ( "fmt" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" ) var errFailedToRemovePeerWithoutNotary = errors.New("peer can be forcefully removed only in notary environment") diff --git a/pkg/morph/client/netmap/snapshot.go b/pkg/morph/client/netmap/snapshot.go index ba2c26af7..2d7fb9be4 100644 --- a/pkg/morph/client/netmap/snapshot.go +++ b/pkg/morph/client/netmap/snapshot.go @@ -2,7 +2,7 @@ package netmap import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" ) // GetNetMap calls "snapshot" method and decodes netmap.NetMap from the response. diff --git a/pkg/morph/event/container/delete.go b/pkg/morph/event/container/delete.go index a206307f8..42541ff05 100644 --- a/pkg/morph/event/container/delete.go +++ b/pkg/morph/event/container/delete.go @@ -5,7 +5,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/network/payload" ) diff --git a/pkg/morph/event/container/delete_test.go b/pkg/morph/event/container/delete_test.go index 627c5fcf5..17b839edc 100644 --- a/pkg/morph/event/container/delete_test.go +++ b/pkg/morph/event/container/delete_test.go @@ -5,7 +5,7 @@ import ( "testing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" - cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" "github.com/stretchr/testify/require" ) diff --git a/pkg/morph/event/container/put.go b/pkg/morph/event/container/put.go index 335034bf3..3e1a582f8 100644 --- a/pkg/morph/event/container/put.go +++ b/pkg/morph/event/container/put.go @@ -5,7 +5,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/network/payload" ) diff --git a/pkg/morph/event/container/put_test.go b/pkg/morph/event/container/put_test.go index 3622f9943..2bb460fd0 100644 --- a/pkg/morph/event/container/put_test.go +++ b/pkg/morph/event/container/put_test.go @@ -5,7 +5,7 @@ import ( "testing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" - cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" "github.com/stretchr/testify/require" ) diff --git a/pkg/network/address.go b/pkg/network/address.go index 88f4a571d..f17fb124f 100644 --- a/pkg/network/address.go +++ b/pkg/network/address.go @@ -7,7 +7,7 @@ import ( "net/url" "strings" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client" "github.com/multiformats/go-multiaddr" manet "github.com/multiformats/go-multiaddr/net" ) diff --git a/pkg/network/cache/client.go b/pkg/network/cache/client.go index 371d3c76f..47c731965 100644 --- a/pkg/network/cache/client.go +++ b/pkg/network/cache/client.go @@ -6,7 +6,7 @@ import ( "time" clientcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" ) type ( diff --git a/pkg/network/cache/multi.go b/pkg/network/cache/multi.go index 5dd206283..6384ff59a 100644 --- a/pkg/network/cache/multi.go +++ b/pkg/network/cache/multi.go @@ -7,13 +7,13 @@ import ( "sync" "time" - rawclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" + rawclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client" clientcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" metrics "git.frostfs.info/TrueCloudLab/frostfs-observability/metrics/grpc" tracing "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing/grpc" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" diff --git a/pkg/network/group.go b/pkg/network/group.go index a6de0653e..1af77f198 100644 --- a/pkg/network/group.go +++ b/pkg/network/group.go @@ -5,7 +5,7 @@ import ( "fmt" "sort" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" ) // AddressGroup represents list of network addresses of the node. diff --git a/pkg/network/transport/accounting/grpc/service.go b/pkg/network/transport/accounting/grpc/service.go index 2144a3001..b8c60ed35 100644 --- a/pkg/network/transport/accounting/grpc/service.go +++ b/pkg/network/transport/accounting/grpc/service.go @@ -3,8 +3,8 @@ package accounting import ( "context" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/accounting" - accountingGRPC "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/accounting/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/accounting" + accountingGRPC "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/accounting/grpc" accountingsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/accounting" ) diff --git a/pkg/network/transport/container/grpc/service.go b/pkg/network/transport/container/grpc/service.go index ed514d6d4..47d6490b9 100644 --- a/pkg/network/transport/container/grpc/service.go +++ b/pkg/network/transport/container/grpc/service.go @@ -3,8 +3,8 @@ package container import ( "context" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container" - containerGRPC "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/container" + containerGRPC "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/container/grpc" containersvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/container" ) diff --git a/pkg/network/transport/netmap/grpc/service.go b/pkg/network/transport/netmap/grpc/service.go index 406c77e58..1d3bfe3b6 100644 --- a/pkg/network/transport/netmap/grpc/service.go +++ b/pkg/network/transport/netmap/grpc/service.go @@ -3,8 +3,8 @@ package grpc import ( "context" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap" - netmapGRPC "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/netmap" + netmapGRPC "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/netmap/grpc" netmapsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/netmap" ) diff --git a/pkg/network/transport/object/grpc/get.go b/pkg/network/transport/object/grpc/get.go index e1655c183..2cc704704 100644 --- a/pkg/network/transport/object/grpc/get.go +++ b/pkg/network/transport/object/grpc/get.go @@ -1,8 +1,8 @@ package object import ( - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - objectGRPC "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" + objectGRPC "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object/grpc" ) type getStreamerV2 struct { diff --git a/pkg/network/transport/object/grpc/range.go b/pkg/network/transport/object/grpc/range.go index 391536e8e..e03fa6d7a 100644 --- a/pkg/network/transport/object/grpc/range.go +++ b/pkg/network/transport/object/grpc/range.go @@ -1,8 +1,8 @@ package object import ( - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - objectGRPC "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" + objectGRPC "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object/grpc" ) type getRangeStreamerV2 struct { diff --git a/pkg/network/transport/object/grpc/search.go b/pkg/network/transport/object/grpc/search.go index a151ced09..b5904fd57 100644 --- a/pkg/network/transport/object/grpc/search.go +++ b/pkg/network/transport/object/grpc/search.go @@ -1,8 +1,8 @@ package object import ( - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - objectGRPC "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" + objectGRPC "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object/grpc" ) type searchStreamerV2 struct { diff --git a/pkg/network/transport/object/grpc/service.go b/pkg/network/transport/object/grpc/service.go index 7c6b395d5..44daaa35c 100644 --- a/pkg/network/transport/object/grpc/service.go +++ b/pkg/network/transport/object/grpc/service.go @@ -5,8 +5,8 @@ import ( "errors" "io" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - objectGRPC "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" + objectGRPC "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object/grpc" objectSvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util" ) diff --git a/pkg/network/transport/session/grpc/service.go b/pkg/network/transport/session/grpc/service.go index e0dc74942..dca1a3377 100644 --- a/pkg/network/transport/session/grpc/service.go +++ b/pkg/network/transport/session/grpc/service.go @@ -3,8 +3,8 @@ package session import ( "context" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - sessionGRPC "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" + sessionGRPC "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session/grpc" sessionsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/session" ) diff --git a/pkg/network/validation.go b/pkg/network/validation.go index 92f650119..c035e2586 100644 --- a/pkg/network/validation.go +++ b/pkg/network/validation.go @@ -3,7 +3,7 @@ package network import ( "errors" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" ) const ( diff --git a/pkg/network/validation_test.go b/pkg/network/validation_test.go index 7d3cb9577..bb68357a1 100644 --- a/pkg/network/validation_test.go +++ b/pkg/network/validation_test.go @@ -3,7 +3,7 @@ package network import ( "testing" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" "github.com/stretchr/testify/require" ) diff --git a/pkg/sdk/README.md b/pkg/sdk/README.md new file mode 100644 index 000000000..b7f3f2284 --- /dev/null +++ b/pkg/sdk/README.md @@ -0,0 +1,132 @@ +# frostfs-sdk-go +Go implementation of FrostFS SDK. It contains high-level version-independent wrappers +for structures from [frostfs-api-go](https://git.frostfs.info/TrueCloudLab/frostfs-api-go) as well as +helper functions for simplifying node/dApp implementations. + +## Repository structure + +### accounting +Contains fixed-point `Decimal` type for performing balance calculations. + +### eacl +Contains Extended ACL types for fine-grained access control. +There is also a reference implementation of checking algorithm which is used in FrostFS node. + +### checksum +Contains `Checksum` type encapsulating checksum as well as it's kind. +Currently Sha256 and [Tillich-Zemor hashsum](https://git.frostfs.info/TrueCloudLab/tzhash) are in use. + +### owner +`owner.ID` type represents single account interacting with FrostFS. In v2 version of protocol +it is just raw bytes behing [base58-encoded address](https://docs.neo.org/docs/en-us/basic/concept/wallets.html#address) +in Neo blockchain. Note that for historical reasons it contains +version prefix and checksum in addition to script-hash. + +### token +Contains Bearer token type with several FrostFS-specific methods. + +### ns +In FrostFS there are 2 types of name resolution: DNS and NNS. NNS stands for Neo Name Service +is just a [contract](https://git.frostfs.info/TrueCloudLab/frostfs-contract) deployed on a Neo blockchain. +Basically, NNS is just a DNS-on-chain which can be used for resolving container nice-names as well +as any other name in dApps. See our [CoreDNS plugin](https://github.com/nspcc-dev/coredns/tree/master/plugin/nns) +for the example of how NNS can be integrated in DNS. + +### session +To help lightweight clients interact with FrostFS without sacrificing trust, FrostFS has a concept +of session token. It is signed by client and allows any node with which a session is established +to perform certain actions on behalf of the user. + +### client +Contains client for working with FrostFS. +```go +var prmInit client.PrmInit +prmInit.SetDefaultPrivateKey(key) // private key for request signing + +var c client.Client +c.Init(prmInit) + +var prmDial client.PrmDial +prmDial.SetServerURI("grpcs://localhost:40005") // endpoint address + +err := c.Dial(prmDial) +if err != nil { + return +} + +ctx, cancel := context.WithTimeout(context.Background(), 5 * time.Second) +defer cancel() + +var prm client.PrmBalanceGet +prm.SetAccount(acc) + +res, err := c.BalanceGet(ctx, prm) +if err != nil { + return +} + +fmt.Printf("Balance for %s: %v\n", acc, res.Amount()) +``` + +#### Response status +In FrostFS every operation can fail on multiple levels, so a single `error` doesn't suffice, +e.g. consider a case when object was put on 4 out of 5 replicas. Thus, all request execution +details are contained in `Status` returned from every RPC call. dApp can inspect them +if needed and perform any desired action. In the case above we may want to report +these details to the user as well as retry an operation, possibly with different parameters. +Status wire-format is extendable and each node can report any set of details it wants. +The set of reserved status codes can be found in +[FrostFS API](https://git.frostfs.info/TrueCloudLab/frostfs-api/src/branch/master/status/types.proto). + +### policy +Contains helpers allowing conversion of placing policy from/to JSON representation +and SQL-like human-readable language. +```go +p, _ := policy.Parse(` + REP 2 + SELECT 6 FROM F + FILTER StorageType EQ SSD AS F`) + +// Convert parsed policy back to human-readable text and print. +println(strings.Join(policy.Encode(p), "\n")) +``` + +### netmap +Contains CRUSH-like implementation of container node selection algorithm. Relevant details +are described in this paper http://ceur-ws.org/Vol-2344/short10.pdf . Note that it can be +outdated in some details. + +`netmap/json_tests` subfolder contains language-agnostic tests for selection algorithm. + +```go +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" +) + +func placementNodes(addr *object.Address, p *netmap.PlacementPolicy, frostfsNodes []netmap.NodeInfo) { + // Convert list of nodes in FrostFS API format to the intermediate representation. + nodes := netmap.NodesFromInfo(nodes) + + // Create new netmap (errors are skipped for the sake of clarity). + nm, _ := NewNetmap(nodes) + + // Calculate nodes of container. + cn, _ := nm.GetContainerNodes(p, addr.ContainerID().ToV2().GetValue()) + + // Return list of nodes for each replica to place object on in the order of priority. + return nm.GetPlacementVectors(cn, addr.ObjectID().ToV2().GetValue()) +} +``` + +### pool +Simple pool for managing connections to FrostFS nodes. + +### acl, checksum, version, signature +Contain simple API wrappers. + +### logger +Wrapper over `zap.Logger` which is used across FrostFS codebase. + +### util +Utilities for working with signature-related code. diff --git a/pkg/sdk/accounting/decimal.go b/pkg/sdk/accounting/decimal.go new file mode 100644 index 000000000..bcb4aa7d5 --- /dev/null +++ b/pkg/sdk/accounting/decimal.go @@ -0,0 +1,64 @@ +package accounting + +import "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/accounting" + +// Decimal represents decimal number for accounting operations. +// +// Decimal is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/accounting.Decimal +// message. See ReadFromV2 / WriteToV2 methods. +// +// Instances can be created using built-in var declaration. +// +// Note that direct typecast is not safe and may result in loss of compatibility: +// +// _ = Decimal(accounting.Decimal{}) // not recommended +type Decimal accounting.Decimal + +// ReadFromV2 reads Decimal from the accounting.Decimal message. Checks if the +// message conforms to FrostFS API V2 protocol. +// +// See also WriteToV2. +func (d *Decimal) ReadFromV2(m accounting.Decimal) error { + *d = Decimal(m) + return nil +} + +// WriteToV2 writes Decimal to the accounting.Decimal message. +// The message must not be nil. +// +// See also ReadFromV2. +func (d Decimal) WriteToV2(m *accounting.Decimal) { + *m = (accounting.Decimal)(d) +} + +// Value returns value of the decimal number. +// +// Zero Decimal has zero value. +// +// See also SetValue. +func (d Decimal) Value() int64 { + return (*accounting.Decimal)(&d).GetValue() +} + +// SetValue sets value of the decimal number. +// +// See also Value. +func (d *Decimal) SetValue(v int64) { + (*accounting.Decimal)(d).SetValue(v) +} + +// Precision returns precision of the decimal number. +// +// Zero Decimal has zero precision. +// +// See also SetPrecision. +func (d Decimal) Precision() uint32 { + return (*accounting.Decimal)(&d).GetPrecision() +} + +// SetPrecision sets precision of the decimal number. +// +// See also Precision. +func (d *Decimal) SetPrecision(p uint32) { + (*accounting.Decimal)(d).SetPrecision(p) +} diff --git a/pkg/sdk/accounting/decimal_test.go b/pkg/sdk/accounting/decimal_test.go new file mode 100644 index 000000000..0d444c34e --- /dev/null +++ b/pkg/sdk/accounting/decimal_test.go @@ -0,0 +1,46 @@ +package accounting_test + +import ( + "testing" + + v2accounting "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/accounting" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/accounting" + "github.com/stretchr/testify/require" +) + +func TestDecimalData(t *testing.T) { + const v, p = 4, 2 + + var d accounting.Decimal + + require.Zero(t, d.Value()) + require.Zero(t, d.Precision()) + + d.SetValue(v) + d.SetPrecision(p) + + require.EqualValues(t, v, d.Value()) + require.EqualValues(t, p, d.Precision()) +} + +func TestDecimalMessageV2(t *testing.T) { + var ( + d accounting.Decimal + m v2accounting.Decimal + ) + + m.SetValue(7) + m.SetPrecision(8) + + require.NoError(t, d.ReadFromV2(m)) + + require.EqualValues(t, m.GetValue(), d.Value()) + require.EqualValues(t, m.GetPrecision(), d.Precision()) + + var m2 v2accounting.Decimal + + d.WriteToV2(&m2) + + require.EqualValues(t, d.Value(), m2.GetValue()) + require.EqualValues(t, d.Precision(), m2.GetPrecision()) +} diff --git a/pkg/sdk/accounting/doc.go b/pkg/sdk/accounting/doc.go new file mode 100644 index 000000000..b74f4d19c --- /dev/null +++ b/pkg/sdk/accounting/doc.go @@ -0,0 +1,35 @@ +/* +Package accounting provides primitives to perform accounting operations in FrostFS. + +Decimal type provides functionality to process user balances. For example, when +working with Fixed8 balance precision: + + var dec accounting.Decimal + dec.SetValue(val) + dec.SetPrecision(8) + +Instances can be also used to process FrostFS API V2 protocol messages +(see neo.fs.v2.accounting package in https://git.frostfs.info/TrueCloudLab/frostfs-api). + +On client side: + + import "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/accounting" + + var msg accounting.Decimal + dec.WriteToV2(&msg) + + // send msg + +On server side: + + // recv msg + + var dec accounting.Decimal + dec.ReadFromV2(msg) + + // process dec + +Using package types in an application is recommended to potentially work with +different protocol versions with which these types are compatible. +*/ +package accounting diff --git a/pkg/sdk/accounting/test/decimal.go b/pkg/sdk/accounting/test/decimal.go new file mode 100644 index 000000000..ea9ac26bc --- /dev/null +++ b/pkg/sdk/accounting/test/decimal.go @@ -0,0 +1,16 @@ +package accountingtest + +import ( + "math/rand" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/accounting" +) + +// Decimal returns random accounting.Decimal. +func Decimal() *accounting.Decimal { + var d accounting.Decimal + d.SetValue(rand.Int63()) + d.SetPrecision(rand.Uint32()) + + return &d +} diff --git a/pkg/sdk/accounting/test/doc.go b/pkg/sdk/accounting/test/doc.go new file mode 100644 index 000000000..9c42081b2 --- /dev/null +++ b/pkg/sdk/accounting/test/doc.go @@ -0,0 +1,13 @@ +/* +Package accountingtest provides functions for convenient testing of accounting package API. + +Note that importing the package into source files is highly discouraged. + +Random instance generation functions can be useful when testing expects any value, e.g.: + + import accountingtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/accounting/test" + + dec := accountingtest.Decimal() + // test the value +*/ +package accountingtest diff --git a/pkg/sdk/bearer/bearer.go b/pkg/sdk/bearer/bearer.go new file mode 100644 index 000000000..f3a02f67b --- /dev/null +++ b/pkg/sdk/bearer/bearer.go @@ -0,0 +1,387 @@ +package bearer + +import ( + "crypto/ecdsa" + "errors" + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/acl" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/crypto" + frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/crypto/ecdsa" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/eacl" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" +) + +// Token represents bearer token for object service operations. +// +// Token is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/acl.BearerToken +// message. See ReadFromV2 / WriteToV2 methods. +// +// Instances can be created using built-in var declaration. +type Token struct { + targetUserSet bool + targetUser user.ID + + eaclTableSet bool + eaclTable eacl.Table + + lifetimeSet bool + iat, nbf, exp uint64 + + sigSet bool + sig refs.Signature + + impersonate bool +} + +// reads Token from the acl.BearerToken message. If checkFieldPresence is set, +// returns an error on absence of any protocol-required field. +func (b *Token) readFromV2(m acl.BearerToken, checkFieldPresence bool) error { + var err error + + body := m.GetBody() + if checkFieldPresence && body == nil { + return errors.New("missing token body") + } + + b.impersonate = body.GetImpersonate() + + eaclTable := body.GetEACL() + if b.eaclTableSet = eaclTable != nil; b.eaclTableSet { + b.eaclTable = *eacl.NewTableFromV2(eaclTable) + } else if checkFieldPresence && !b.impersonate { + return errors.New("missing eACL table") + } + + targetUser := body.GetOwnerID() + if b.targetUserSet = targetUser != nil; b.targetUserSet { + err = b.targetUser.ReadFromV2(*targetUser) + if err != nil { + return fmt.Errorf("invalid target user: %w", err) + } + } + + lifetime := body.GetLifetime() + if b.lifetimeSet = lifetime != nil; b.lifetimeSet { + b.iat = lifetime.GetIat() + b.nbf = lifetime.GetNbf() + b.exp = lifetime.GetExp() + } else if checkFieldPresence { + return errors.New("missing token lifetime") + } + + sig := m.GetSignature() + if b.sigSet = sig != nil; sig != nil { + b.sig = *sig + } else if checkFieldPresence { + return errors.New("missing body signature") + } + + return nil +} + +// ReadFromV2 reads Token from the acl.BearerToken message. +// +// See also WriteToV2. +func (b *Token) ReadFromV2(m acl.BearerToken) error { + return b.readFromV2(m, true) +} + +func (b Token) fillBody() *acl.BearerTokenBody { + if !b.eaclTableSet && !b.targetUserSet && !b.lifetimeSet && !b.impersonate { + return nil + } + + var body acl.BearerTokenBody + + if b.eaclTableSet { + body.SetEACL(b.eaclTable.ToV2()) + } + + if b.targetUserSet { + var targetUser refs.OwnerID + b.targetUser.WriteToV2(&targetUser) + + body.SetOwnerID(&targetUser) + } + + if b.lifetimeSet { + var lifetime acl.TokenLifetime + lifetime.SetIat(b.iat) + lifetime.SetNbf(b.nbf) + lifetime.SetExp(b.exp) + + body.SetLifetime(&lifetime) + } + + body.SetImpersonate(b.impersonate) + + return &body +} + +func (b Token) signedData() []byte { + return b.fillBody().StableMarshal(nil) +} + +// WriteToV2 writes Token to the acl.BearerToken message. +// The message must not be nil. +// +// See also ReadFromV2. +func (b Token) WriteToV2(m *acl.BearerToken) { + m.SetBody(b.fillBody()) + + var sig *refs.Signature + + if b.sigSet { + sig = &b.sig + } + + m.SetSignature(sig) +} + +// SetExp sets "exp" (expiration time) claim which identifies the +// expiration time (in FrostFS epochs) after which the Token MUST NOT be +// accepted for processing. The processing of the "exp" claim requires +// that the current epoch MUST be before or equal to the expiration epoch +// listed in the "exp" claim. +// +// Naming is inspired by https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.4. +// +// See also InvalidAt. +func (b *Token) SetExp(exp uint64) { + b.exp = exp + b.lifetimeSet = true +} + +// SetNbf sets "nbf" (not before) claim which identifies the time (in +// FrostFS epochs) before which the Token MUST NOT be accepted for processing. The +// processing of the "nbf" claim requires that the current epoch MUST be +// after or equal to the not-before epoch listed in the "nbf" claim. +// +// Naming is inspired by https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.5. +// +// See also InvalidAt. +func (b *Token) SetNbf(nbf uint64) { + b.nbf = nbf + b.lifetimeSet = true +} + +// SetIat sets "iat" (issued at) claim which identifies the time (in FrostFS +// epochs) at which the Token was issued. This claim can be used to determine +// the age of the Token. +// +// Naming is inspired by https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.6. +// +// See also InvalidAt. +func (b *Token) SetIat(iat uint64) { + b.iat = iat + b.lifetimeSet = true +} + +// InvalidAt asserts "exp", "nbf" and "iat" claims for the given epoch. +// +// Zero Container is invalid in any epoch. +// +// See also SetExp, SetNbf, SetIat. +func (b Token) InvalidAt(epoch uint64) bool { + return !b.lifetimeSet || b.nbf > epoch || b.iat > epoch || b.exp < epoch +} + +// SetEACLTable sets eacl.Table that replaces the one from the issuer's +// container. If table has specified container, bearer token can be used only +// for operations within this specific container. Otherwise, Token can be used +// within any issuer's container. +// +// SetEACLTable MUST be called if Token is going to be transmitted over +// FrostFS API V2 protocol. +// +// See also EACLTable, AssertContainer. +func (b *Token) SetEACLTable(table eacl.Table) { + b.eaclTable = table + b.eaclTableSet = true +} + +// EACLTable returns extended ACL table set by SetEACLTable. +// +// Zero Token has zero eacl.Table. +func (b Token) EACLTable() eacl.Table { + if b.eaclTableSet { + return b.eaclTable + } + + return eacl.Table{} +} + +// SetImpersonate mark token as impersonate to consider token signer as request owner. +// If this field is true extended EACLTable in token body isn't processed. +func (b *Token) SetImpersonate(v bool) { + b.impersonate = v +} + +// Impersonate returns true if token is impersonated. +func (b Token) Impersonate() bool { + return b.impersonate +} + +// AssertContainer checks if the token is valid within the given container. +// +// Note: cnr is assumed to refer to the issuer's container, otherwise the check +// is meaningless. +// +// Zero Token is valid in any container. +// +// See also SetEACLTable. +func (b Token) AssertContainer(cnr cid.ID) bool { + if !b.eaclTableSet { + return true + } + + cnrTable, set := b.eaclTable.CID() + return !set || cnrTable.Equals(cnr) +} + +// ForUser specifies ID of the user who can use the Token for the operations +// within issuer's container(s). +// +// Optional: by default, any user has access to Token usage. +// +// See also AssertUser. +func (b *Token) ForUser(id user.ID) { + b.targetUser = id + b.targetUserSet = true +} + +// AssertUser checks if the Token is issued to the given user. +// +// Zero Token is available to any user. +// +// See also ForUser. +func (b Token) AssertUser(id user.ID) bool { + return !b.targetUserSet || b.targetUser.Equals(id) +} + +// Sign calculates and writes signature of the Token data using issuer's secret. +// Returns signature calculation errors. +// +// Sign MUST be called if Token is going to be transmitted over +// FrostFS API V2 protocol. +// +// Note that any Token mutation is likely to break the signature, so it is +// expected to be calculated as a final stage of Token formation. +// +// See also VerifySignature, Issuer. +func (b *Token) Sign(key ecdsa.PrivateKey) error { + var sig frostfscrypto.Signature + + err := sig.Calculate(frostfsecdsa.Signer(key), b.signedData()) + if err != nil { + return err + } + + sig.WriteToV2(&b.sig) + b.sigSet = true + + return nil +} + +// VerifySignature checks if Token signature is presented and valid. +// +// Zero Token fails the check. +// +// See also Sign. +func (b Token) VerifySignature() bool { + if !b.sigSet { + return false + } + + var sig frostfscrypto.Signature + + // TODO: (#233) check owner<->key relation + return sig.ReadFromV2(b.sig) == nil && sig.Verify(b.signedData()) +} + +// Marshal encodes Token into a binary format of the FrostFS API protocol +// (Protocol Buffers V3 with direct field order). +// +// See also Unmarshal. +func (b Token) Marshal() []byte { + var m acl.BearerToken + b.WriteToV2(&m) + + return m.StableMarshal(nil) +} + +// Unmarshal decodes FrostFS API protocol binary data into the Token +// (Protocol Buffers V3 with direct field order). Returns an error describing +// a format violation. +// +// See also Marshal. +func (b *Token) Unmarshal(data []byte) error { + var m acl.BearerToken + + err := m.Unmarshal(data) + if err != nil { + return err + } + + return b.readFromV2(m, false) +} + +// MarshalJSON encodes Token into a JSON format of the FrostFS API protocol +// (Protocol Buffers V3 JSON). +// +// See also UnmarshalJSON. +func (b Token) MarshalJSON() ([]byte, error) { + var m acl.BearerToken + b.WriteToV2(&m) + + return m.MarshalJSON() +} + +// UnmarshalJSON decodes FrostFS API protocol JSON data into the Token +// (Protocol Buffers V3 JSON). Returns an error describing a format violation. +// +// See also MarshalJSON. +func (b *Token) UnmarshalJSON(data []byte) error { + var m acl.BearerToken + + err := m.UnmarshalJSON(data) + if err != nil { + return err + } + + return b.readFromV2(m, false) +} + +// SigningKeyBytes returns issuer's public key in a binary format of +// FrostFS API protocol. +// +// Unsigned Token has empty key. +// +// See also ResolveIssuer. +func (b Token) SigningKeyBytes() []byte { + if b.sigSet { + return b.sig.GetKey() + } + + return nil +} + +// ResolveIssuer resolves issuer's user.ID from the key used for Token signing. +// Returns zero user.ID if Token is unsigned or key has incorrect format. +// +// See also SigningKeyBytes. +func ResolveIssuer(b Token) (usr user.ID) { + binKey := b.SigningKeyBytes() + + if len(binKey) != 0 { + var key frostfsecdsa.PublicKey + if key.Decode(binKey) == nil { + user.IDFromKey(&usr, ecdsa.PublicKey(key)) + } + } + + return +} diff --git a/pkg/sdk/bearer/bearer_test.go b/pkg/sdk/bearer/bearer_test.go new file mode 100644 index 000000000..b389bcabc --- /dev/null +++ b/pkg/sdk/bearer/bearer_test.go @@ -0,0 +1,394 @@ +package bearer_test + +import ( + "bytes" + "math/rand" + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/acl" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/bearer" + bearertest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/bearer/test" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/crypto" + frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/crypto/ecdsa" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/eacl" + eacltest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/eacl/test" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" + usertest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user/test" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + "github.com/stretchr/testify/require" +) + +// compares binary representations of two eacl.Table instances. +func isEqualEACLTables(t1, t2 eacl.Table) bool { + d1, err := t1.Marshal() + if err != nil { + panic(err) + } + + d2, err := t2.Marshal() + if err != nil { + panic(err) + } + + return bytes.Equal(d1, d2) +} + +func TestToken_SetEACLTable(t *testing.T) { + var val bearer.Token + var m acl.BearerToken + filled := bearertest.Token() + + val.WriteToV2(&m) + require.Zero(t, m.GetBody()) + + val2 := filled + + require.NoError(t, val2.Unmarshal(val.Marshal())) + require.Zero(t, val2.EACLTable()) + + val2 = filled + + jd, err := val.MarshalJSON() + require.NoError(t, err) + + require.NoError(t, val2.UnmarshalJSON(jd)) + require.Zero(t, val2.EACLTable()) + + // set value + + eaclTable := *eacltest.Table() + + val.SetEACLTable(eaclTable) + require.True(t, isEqualEACLTables(eaclTable, val.EACLTable())) + + val.WriteToV2(&m) + eaclTableV2 := eaclTable.ToV2() + require.Equal(t, eaclTableV2, m.GetBody().GetEACL()) + + val2 = filled + + require.NoError(t, val2.Unmarshal(val.Marshal())) + require.True(t, isEqualEACLTables(eaclTable, val.EACLTable())) + + val2 = filled + + jd, err = val.MarshalJSON() + require.NoError(t, err) + + require.NoError(t, val2.UnmarshalJSON(jd)) + require.True(t, isEqualEACLTables(eaclTable, val.EACLTable())) +} + +func TestToken_ForUser(t *testing.T) { + var val bearer.Token + var m acl.BearerToken + filled := bearertest.Token() + + val.WriteToV2(&m) + require.Zero(t, m.GetBody()) + + val2 := filled + + require.NoError(t, val2.Unmarshal(val.Marshal())) + + val2.WriteToV2(&m) + require.Zero(t, m.GetBody()) + + val2 = filled + + jd, err := val.MarshalJSON() + require.NoError(t, err) + + require.NoError(t, val2.UnmarshalJSON(jd)) + + val2.WriteToV2(&m) + require.Zero(t, m.GetBody()) + + // set value + usr := usertest.ID() + + var usrV2 refs.OwnerID + usr.WriteToV2(&usrV2) + + val.ForUser(usr) + + val.WriteToV2(&m) + require.Equal(t, usrV2, *m.GetBody().GetOwnerID()) + + val2 = filled + + require.NoError(t, val2.Unmarshal(val.Marshal())) + + val2.WriteToV2(&m) + require.Equal(t, usrV2, *m.GetBody().GetOwnerID()) + + val2 = filled + + jd, err = val.MarshalJSON() + require.NoError(t, err) + + require.NoError(t, val2.UnmarshalJSON(jd)) + + val2.WriteToV2(&m) + require.Equal(t, usrV2, *m.GetBody().GetOwnerID()) +} + +func testLifetimeClaim(t *testing.T, setter func(*bearer.Token, uint64), getter func(*acl.BearerToken) uint64) { + var val bearer.Token + var m acl.BearerToken + filled := bearertest.Token() + + val.WriteToV2(&m) + require.Zero(t, m.GetBody()) + + val2 := filled + + require.NoError(t, val2.Unmarshal(val.Marshal())) + + val2.WriteToV2(&m) + require.Zero(t, m.GetBody()) + + val2 = filled + + jd, err := val.MarshalJSON() + require.NoError(t, err) + + require.NoError(t, val2.UnmarshalJSON(jd)) + + val2.WriteToV2(&m) + require.Zero(t, m.GetBody()) + + // set value + exp := rand.Uint64() + + setter(&val, exp) + + val.WriteToV2(&m) + require.Equal(t, exp, getter(&m)) + + val2 = filled + + require.NoError(t, val2.Unmarshal(val.Marshal())) + + val2.WriteToV2(&m) + require.Equal(t, exp, getter(&m)) + + val2 = filled + + jd, err = val.MarshalJSON() + require.NoError(t, err) + + require.NoError(t, val2.UnmarshalJSON(jd)) + + val2.WriteToV2(&m) + require.Equal(t, exp, getter(&m)) +} + +func TestToken_SetLifetime(t *testing.T) { + t.Run("iat", func(t *testing.T) { + testLifetimeClaim(t, (*bearer.Token).SetIat, func(token *acl.BearerToken) uint64 { + return token.GetBody().GetLifetime().GetIat() + }) + }) + + t.Run("nbf", func(t *testing.T) { + testLifetimeClaim(t, (*bearer.Token).SetNbf, func(token *acl.BearerToken) uint64 { + return token.GetBody().GetLifetime().GetNbf() + }) + }) + + t.Run("exp", func(t *testing.T) { + testLifetimeClaim(t, (*bearer.Token).SetExp, func(token *acl.BearerToken) uint64 { + return token.GetBody().GetLifetime().GetExp() + }) + }) +} + +func TestToken_InvalidAt(t *testing.T) { + var val bearer.Token + + require.True(t, val.InvalidAt(0)) + require.True(t, val.InvalidAt(1)) + + val.SetIat(1) + val.SetNbf(2) + val.SetExp(4) + + require.True(t, val.InvalidAt(0)) + require.True(t, val.InvalidAt(1)) + require.False(t, val.InvalidAt(2)) + require.False(t, val.InvalidAt(3)) + require.False(t, val.InvalidAt(4)) + require.True(t, val.InvalidAt(5)) +} + +func TestToken_AssertContainer(t *testing.T) { + var val bearer.Token + cnr := cidtest.ID() + + require.True(t, val.AssertContainer(cnr)) + + eaclTable := *eacltest.Table() + + eaclTable.SetCID(cidtest.ID()) + val.SetEACLTable(eaclTable) + require.False(t, val.AssertContainer(cnr)) + + eaclTable.SetCID(cnr) + val.SetEACLTable(eaclTable) + require.True(t, val.AssertContainer(cnr)) +} + +func TestToken_AssertUser(t *testing.T) { + var val bearer.Token + usr := usertest.ID() + + require.True(t, val.AssertUser(usr)) + + val.ForUser(usertest.ID()) + require.False(t, val.AssertUser(usr)) + + val.ForUser(usr) + require.True(t, val.AssertUser(usr)) +} + +func TestToken_Sign(t *testing.T) { + var val bearer.Token + + require.False(t, val.VerifySignature()) + + k, err := keys.NewPrivateKey() + require.NoError(t, err) + + key := k.PrivateKey + val = bearertest.Token() + + require.NoError(t, val.Sign(key)) + + require.True(t, val.VerifySignature()) + + var m acl.BearerToken + val.WriteToV2(&m) + + require.NotZero(t, m.GetSignature().GetKey()) + require.NotZero(t, m.GetSignature().GetSign()) + + val2 := bearertest.Token() + + require.NoError(t, val2.Unmarshal(val.Marshal())) + require.True(t, val2.VerifySignature()) + + jd, err := val.MarshalJSON() + require.NoError(t, err) + + val2 = bearertest.Token() + require.NoError(t, val2.UnmarshalJSON(jd)) + require.True(t, val2.VerifySignature()) +} + +func TestToken_ReadFromV2(t *testing.T) { + var val bearer.Token + var m acl.BearerToken + + require.Error(t, val.ReadFromV2(m)) + + var body acl.BearerTokenBody + m.SetBody(&body) + + require.Error(t, val.ReadFromV2(m)) + + eaclTable := eacltest.Table().ToV2() + body.SetEACL(eaclTable) + + require.Error(t, val.ReadFromV2(m)) + + var lifetime acl.TokenLifetime + body.SetLifetime(&lifetime) + + require.Error(t, val.ReadFromV2(m)) + + const iat, nbf, exp = 1, 2, 3 + lifetime.SetIat(iat) + lifetime.SetNbf(nbf) + lifetime.SetExp(exp) + + body.SetLifetime(&lifetime) + + require.Error(t, val.ReadFromV2(m)) + + var sig refs.Signature + m.SetSignature(&sig) + + require.NoError(t, val.ReadFromV2(m)) + + body.SetEACL(nil) + body.SetImpersonate(true) + require.NoError(t, val.ReadFromV2(m)) + + var m2 acl.BearerToken + + val.WriteToV2(&m2) + require.Equal(t, m, m2) + + usr, usr2 := usertest.ID(), usertest.ID() + + require.True(t, val.AssertUser(usr)) + require.True(t, val.AssertUser(usr2)) + + var usrV2 refs.OwnerID + usr.WriteToV2(&usrV2) + + body.SetOwnerID(&usrV2) + + require.NoError(t, val.ReadFromV2(m)) + + val.WriteToV2(&m2) + require.Equal(t, m, m2) + + require.True(t, val.AssertUser(usr)) + require.False(t, val.AssertUser(usr2)) + + k, err := keys.NewPrivateKey() + require.NoError(t, err) + + signer := frostfsecdsa.Signer(k.PrivateKey) + + var s frostfscrypto.Signature + + require.NoError(t, s.Calculate(signer, body.StableMarshal(nil))) + + s.WriteToV2(&sig) + + require.NoError(t, val.ReadFromV2(m)) + require.True(t, val.VerifySignature()) + require.Equal(t, sig.GetKey(), val.SigningKeyBytes()) +} + +func TestResolveIssuer(t *testing.T) { + k, err := keys.NewPrivateKey() + require.NoError(t, err) + + var val bearer.Token + + require.Zero(t, bearer.ResolveIssuer(val)) + + var m acl.BearerToken + + var sig refs.Signature + sig.SetKey([]byte("invalid key")) + + m.SetSignature(&sig) + + require.NoError(t, val.Unmarshal(m.StableMarshal(nil))) + + require.Zero(t, bearer.ResolveIssuer(val)) + + require.NoError(t, val.Sign(k.PrivateKey)) + + var usr user.ID + user.IDFromKey(&usr, k.PrivateKey.PublicKey) + + require.Equal(t, usr, bearer.ResolveIssuer(val)) +} diff --git a/pkg/sdk/bearer/doc.go b/pkg/sdk/bearer/doc.go new file mode 100644 index 000000000..ea7e841be --- /dev/null +++ b/pkg/sdk/bearer/doc.go @@ -0,0 +1,31 @@ +/* +Package bearer provides bearer token definition. + +Bearer token is attached to the object service requests, and it overwrites +extended ACL of the container. Mainly it is used to provide access of private +data for specific user. Therefore, it must be signed by owner of the container. + +Define bearer token by setting correct lifetime, extended ACL and owner ID of +the user that will attach token to its requests. + + var bearerToken bearer.Token + bearerToken.SetExpiration(500) + bearerToken.SetIssuedAt(10) + bearerToken.SetNotBefore(10) + bearerToken.SetEACL(eaclTable) + bearerToken.SetOwner(ownerID) + +Bearer token must be signed by owner of the container. + + err := bearerToken.Sign(privateKey) + +Provide signed token in JSON or binary format to the request sender. Request +sender can attach this bearer token to the object service requests: + + import sdkClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + + var headParams sdkClient.PrmObjectHead + headParams.WithBearerToken(bearerToken) + response, err := client.ObjectHead(ctx, headParams) +*/ +package bearer diff --git a/pkg/sdk/bearer/test/doc.go b/pkg/sdk/bearer/test/doc.go new file mode 100644 index 000000000..ab4682f30 --- /dev/null +++ b/pkg/sdk/bearer/test/doc.go @@ -0,0 +1,6 @@ +/* +Package bearertest provides functions for testing bearer package. + +Note that this package intended only for tests. +*/ +package bearertest diff --git a/pkg/sdk/bearer/test/generate.go b/pkg/sdk/bearer/test/generate.go new file mode 100644 index 000000000..b456e15b8 --- /dev/null +++ b/pkg/sdk/bearer/test/generate.go @@ -0,0 +1,20 @@ +package bearertest + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/bearer" + eacltest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/eacl/test" + usertest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user/test" +) + +// Token returns random bearer.Token. +// +// Resulting token is unsigned. +func Token() (t bearer.Token) { + t.SetExp(3) + t.SetNbf(2) + t.SetIat(1) + t.ForUser(usertest.ID()) + t.SetEACLTable(*eacltest.Table()) + + return t +} diff --git a/pkg/sdk/checksum/checksum.go b/pkg/sdk/checksum/checksum.go new file mode 100644 index 000000000..9ef4cd403 --- /dev/null +++ b/pkg/sdk/checksum/checksum.go @@ -0,0 +1,162 @@ +package checksum + +import ( + "crypto/sha256" + "encoding/hex" + "errors" + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + "git.frostfs.info/TrueCloudLab/tzhash/tz" +) + +// Checksum represents checksum of some digital data. +// +// Checksum is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs.Checksum +// message. See ReadFromV2 / WriteToV2 methods. +// +// Instances can be created using built-in var declaration. +// +// Note that direct typecast is not safe and may result in loss of compatibility: +// +// _ = Checksum(refs.Checksum{}) // not recommended +type Checksum refs.Checksum + +// Type represents the enumeration +// of checksum types. +type Type refs.ChecksumType + +const ( + // Unknown is an undefined checksum type. + Unknown Type = Type(refs.UnknownChecksum) + + // SHA256 is a SHA256 checksum type. + SHA256 = Type(refs.SHA256) + + // TZ is a Tillich-Zémor checksum type. + TZ = Type(refs.TillichZemor) +) + +// ReadFromV2 reads Checksum from the refs.Checksum message. Checks if the +// message conforms to FrostFS API V2 protocol. +// +// See also WriteToV2. +func (c *Checksum) ReadFromV2(m refs.Checksum) error { + if len(m.GetSum()) == 0 { + return errors.New("missing value") + } + + switch m.GetType() { + default: + return fmt.Errorf("unsupported type %v", m.GetType()) + case refs.SHA256, refs.TillichZemor: + } + + *c = Checksum(m) + + return nil +} + +// WriteToV2 writes Checksum to the refs.Checksum message. +// The message must not be nil. +// +// See also ReadFromV2. +func (c Checksum) WriteToV2(m *refs.Checksum) { + *m = (refs.Checksum)(c) +} + +// Type returns checksum type. +// +// Zero Checksum has Unknown checksum type. +// +// See also SetTillichZemor and SetSHA256. +func (c Checksum) Type() Type { + v2 := (refs.Checksum)(c) + switch v2.GetType() { + case refs.SHA256: + return SHA256 + case refs.TillichZemor: + return TZ + default: + return Unknown + } +} + +// Value returns checksum bytes. Return value +// MUST NOT be mutated. +// +// Zero Checksum has nil sum. +// +// See also SetTillichZemor and SetSHA256. +func (c Checksum) Value() []byte { + v2 := (refs.Checksum)(c) + return v2.GetSum() +} + +// SetSHA256 sets checksum to SHA256 hash. +// +// See also Calculate. +func (c *Checksum) SetSHA256(v [sha256.Size]byte) { + v2 := (*refs.Checksum)(c) + + v2.SetType(refs.SHA256) + v2.SetSum(v[:]) +} + +// Calculate calculates checksum and sets it +// to the passed checksum. Checksum must not be nil. +// +// Does nothing if the passed type is not one of the: +// - SHA256; +// - TZ. +// +// Does not mutate the passed value. +// +// See also SetSHA256, SetTillichZemor. +func Calculate(c *Checksum, t Type, v []byte) { + switch t { + case SHA256: + c.SetSHA256(sha256.Sum256(v)) + case TZ: + c.SetTillichZemor(tz.Sum(v)) + default: + } +} + +// SetTillichZemor sets checksum to Tillich-Zémor hash. +// +// See also Calculate. +func (c *Checksum) SetTillichZemor(v [tz.Size]byte) { + v2 := (*refs.Checksum)(c) + + v2.SetType(refs.TillichZemor) + v2.SetSum(v[:]) +} + +// String implements fmt.Stringer. +// +// String is designed to be human-readable, and its format MAY differ between +// SDK versions. +func (c Checksum) String() string { + v2 := (refs.Checksum)(c) + return fmt.Sprintf("%s:%s", c.Type(), hex.EncodeToString(v2.GetSum())) +} + +// String implements fmt.Stringer. +// +// String is designed to be human-readable, and its format MAY differ between +// SDK versions. +func (m Type) String() string { + var m2 refs.ChecksumType + + switch m { + default: + m2 = refs.UnknownChecksum + case TZ: + m2 = refs.TillichZemor + case SHA256: + m2 = refs.SHA256 + } + + return m2.String() +} diff --git a/pkg/sdk/checksum/checksum_test.go b/pkg/sdk/checksum/checksum_test.go new file mode 100644 index 000000000..5c99a6f1b --- /dev/null +++ b/pkg/sdk/checksum/checksum_test.go @@ -0,0 +1,80 @@ +package checksum + +import ( + "crypto/rand" + "crypto/sha256" + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + "git.frostfs.info/TrueCloudLab/tzhash/tz" + "github.com/stretchr/testify/require" +) + +func TestChecksum(t *testing.T) { + var c Checksum + + cSHA256 := [sha256.Size]byte{} + _, _ = rand.Read(cSHA256[:]) + + c.SetSHA256(cSHA256) + + require.Equal(t, SHA256, c.Type()) + require.Equal(t, cSHA256[:], c.Value()) + + var cV2 refs.Checksum + c.WriteToV2(&cV2) + + require.Equal(t, refs.SHA256, cV2.GetType()) + require.Equal(t, cSHA256[:], cV2.GetSum()) + + cTZ := [tz.Size]byte{} + _, _ = rand.Read(cSHA256[:]) + + c.SetTillichZemor(cTZ) + + require.Equal(t, TZ, c.Type()) + require.Equal(t, cTZ[:], c.Value()) + + c.WriteToV2(&cV2) + + require.Equal(t, refs.TillichZemor, cV2.GetType()) + require.Equal(t, cTZ[:], cV2.GetSum()) +} + +func TestNewChecksum(t *testing.T) { + t.Run("default values", func(t *testing.T) { + var chs Checksum + + // check initial values + require.Equal(t, Unknown, chs.Type()) + require.Nil(t, chs.Value()) + + // convert to v2 message + var chsV2 refs.Checksum + chs.WriteToV2(&chsV2) + + require.Equal(t, refs.UnknownChecksum, chsV2.GetType()) + require.Nil(t, chsV2.GetSum()) + }) +} + +func TestCalculation(t *testing.T) { + var c Checksum + payload := []byte{0, 1, 2, 3, 4, 5} + + t.Run("SHA256", func(t *testing.T) { + orig := sha256.Sum256(payload) + + Calculate(&c, SHA256, payload) + + require.Equal(t, orig[:], c.Value()) + }) + + t.Run("TZ", func(t *testing.T) { + orig := tz.Sum(payload) + + Calculate(&c, TZ, payload) + + require.Equal(t, orig[:], c.Value()) + }) +} diff --git a/pkg/sdk/checksum/doc.go b/pkg/sdk/checksum/doc.go new file mode 100644 index 000000000..859d67f3c --- /dev/null +++ b/pkg/sdk/checksum/doc.go @@ -0,0 +1,18 @@ +/* +Package checksum provides primitives to work with checksums. + +Checksum is a basic type of data checksums. +For example, calculating checksums: + + // retrieving any payload for hashing + + var sha256Sum Checksum + Calculate(&sha256Sum, SHA256, payload) // sha256Sum contains SHA256 hash of the payload + + var tzSum Checksum + Calculate(&tzSum, TZ, payload) // tzSum contains TZ hash of the payload + +Using package types in an application is recommended to potentially work with +different protocol versions with which these types are compatible. +*/ +package checksum diff --git a/pkg/sdk/checksum/example_test.go b/pkg/sdk/checksum/example_test.go new file mode 100644 index 000000000..ea45a2087 --- /dev/null +++ b/pkg/sdk/checksum/example_test.go @@ -0,0 +1,34 @@ +package checksum + +import ( + "bytes" + "crypto/rand" + "crypto/sha256" + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" +) + +func ExampleCalculate() { + payload := []byte{0, 1, 2, 3, 4, 5, 6} + var cs Checksum + + Calculate(&cs, SHA256, payload) + Calculate(&cs, TZ, payload) +} + +func ExampleChecksum_WriteToV2() { + var ( + csRaw [sha256.Size]byte + csV2 refs.Checksum + cs Checksum + ) + + rand.Read(csRaw[:]) + cs.SetSHA256(csRaw) + + cs.WriteToV2(&csV2) + + fmt.Println(bytes.Equal(cs.Value(), csV2.GetSum())) + // Output: true +} diff --git a/pkg/sdk/checksum/test/doc.go b/pkg/sdk/checksum/test/doc.go new file mode 100644 index 000000000..d43d12b8b --- /dev/null +++ b/pkg/sdk/checksum/test/doc.go @@ -0,0 +1,13 @@ +/* +Package checksumtest provides functions for convenient testing of checksum package API. + +Note that importing the package into source files is highly discouraged. + +Random instance generation functions can be useful when testing expects any value, e.g.: + + import checksumtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/checksum/test" + + cs := checksumtest.Checksum() + // test the value +*/ +package checksumtest diff --git a/pkg/sdk/checksum/test/generate.go b/pkg/sdk/checksum/test/generate.go new file mode 100644 index 000000000..d6a9c8da7 --- /dev/null +++ b/pkg/sdk/checksum/test/generate.go @@ -0,0 +1,21 @@ +package checksumtest + +import ( + "crypto/rand" + "crypto/sha256" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/checksum" +) + +// Checksum returns random checksum.Checksum. +func Checksum() checksum.Checksum { + var cs [sha256.Size]byte + + _, _ = rand.Read(cs[:]) + + var x checksum.Checksum + + x.SetSHA256(cs) + + return x +} diff --git a/pkg/sdk/client/accounting.go b/pkg/sdk/client/accounting.go new file mode 100644 index 000000000..9237abaef --- /dev/null +++ b/pkg/sdk/client/accounting.go @@ -0,0 +1,108 @@ +package client + +import ( + "context" + "fmt" + + v2accounting "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/accounting" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + rpcapi "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client" + v2session "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/signature" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/accounting" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" +) + +// PrmBalanceGet groups parameters of BalanceGet operation. +type PrmBalanceGet struct { + XHeaders []string + + Account user.ID +} + +// SetAccount sets identifier of the FrostFS account for which the balance is requested. +// Required parameter. +// +// Deprecated: Use PrmBalanceGet.Account instead. +func (x *PrmBalanceGet) SetAccount(id user.ID) { + x.Account = id +} + +func (x *PrmBalanceGet) buildRequest(c *Client) (*v2accounting.BalanceRequest, error) { + if x.Account.IsEmpty() { + return nil, errorAccountNotSet + } + + var accountV2 refs.OwnerID + x.Account.WriteToV2(&accountV2) + + var body v2accounting.BalanceRequestBody + body.SetOwnerID(&accountV2) + + var req v2accounting.BalanceRequest + req.SetBody(&body) + + c.prepareRequest(&req, new(v2session.RequestMetaHeader)) + return &req, nil +} + +// ResBalanceGet groups resulting values of BalanceGet operation. +type ResBalanceGet struct { + statusRes + + amount accounting.Decimal +} + +// Amount returns current amount of funds on the FrostFS account as decimal number. +func (x ResBalanceGet) Amount() accounting.Decimal { + return x.amount +} + +// BalanceGet requests current balance of the FrostFS account. +// +// Exactly one return value is non-nil. By default, server status is returned in res structure. +// Any client's internal or transport errors are returned as `error`, +// If PrmInit.DisableFrostFSFailuresResolution has been called, unsuccessful +// FrostFS status codes are included in the returned result structure, +// otherwise, are also returned as `error`. +// +// Returns an error if parameters are set incorrectly (see PrmBalanceGet docs). +// Context is required and must not be nil. It is used for network communication. +// +// Return statuses: +// - global (see Client docs). +func (c *Client) BalanceGet(ctx context.Context, prm PrmBalanceGet) (*ResBalanceGet, error) { + req, err := prm.buildRequest(c) + if err != nil { + return nil, err + } + + if err := signature.SignServiceMessage(&c.prm.Key, req); err != nil { + return nil, fmt.Errorf("sign request: %w", err) + } + + resp, err := rpcapi.Balance(&c.c, req, client.WithContext(ctx)) + if err != nil { + return nil, err + } + + var res ResBalanceGet + res.st, err = c.processResponse(resp) + if err != nil || !apistatus.IsSuccessful(res.st) { + return &res, err + } + + const fieldBalance = "balance" + + bal := resp.GetBody().GetBalance() + if bal == nil { + return &res, newErrMissingResponseField(fieldBalance) + } + + if err := res.amount.ReadFromV2(*bal); err != nil { + return &res, newErrInvalidResponseField(fieldBalance, err) + } + return &res, nil +} diff --git a/pkg/sdk/client/api.go b/pkg/sdk/client/api.go new file mode 100644 index 000000000..5280bb824 --- /dev/null +++ b/pkg/sdk/client/api.go @@ -0,0 +1,35 @@ +package client + +import ( + "context" + "fmt" + + v2netmap "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/netmap" + rpcapi "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client" +) + +// interface of FrostFS API server. Exists for test purposes only. +type frostFSAPIServer interface { + netMapSnapshot(context.Context, v2netmap.SnapshotRequest) (*v2netmap.SnapshotResponse, error) +} + +// wrapper over real client connection which communicates over FrostFS API protocol. +// Provides frostFSAPIServer for Client instances used in real applications. +type coreServer client.Client + +// unifies errors of all RPC. +func rpcErr(e error) error { + return fmt.Errorf("rpc failure: %w", e) +} + +// executes NetmapService.NetmapSnapshot RPC declared in FrostFS API protocol +// using underlying client.Client. +func (x *coreServer) netMapSnapshot(ctx context.Context, req v2netmap.SnapshotRequest) (*v2netmap.SnapshotResponse, error) { + resp, err := rpcapi.NetMapSnapshot((*client.Client)(x), &req, client.WithContext(ctx)) + if err != nil { + return nil, rpcErr(err) + } + + return resp, nil +} diff --git a/pkg/sdk/client/client.go b/pkg/sdk/client/client.go new file mode 100644 index 000000000..986312093 --- /dev/null +++ b/pkg/sdk/client/client.go @@ -0,0 +1,251 @@ +package client + +import ( + "context" + "crypto/ecdsa" + "crypto/tls" + "errors" + "time" + + v2accounting "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/accounting" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client" + "google.golang.org/grpc" +) + +// Client represents virtual connection to the FrostFS network to communicate +// with FrostFS server using FrostFS API protocol. It is designed to provide +// an abstraction interface from the protocol details of data transfer over +// a network in FrostFS. +// +// Client can be created using simple Go variable declaration. Before starting +// work with the Client, it SHOULD BE correctly initialized (see Init method). +// Before executing the FrostFS operations using the Client, connection to the +// server MUST BE correctly established (see Dial method and pay attention +// to the mandatory parameters). Using the Client before connecting have +// been established can lead to a panic. After the work, the Client SHOULD BE +// closed (see Close method): it frees internal and system resources which were +// allocated for the period of work of the Client. Calling Init/Dial/Close method +// during the communication process step strongly discouraged as it leads to +// undefined behavior. +// +// Each method which produces a FrostFS API call may return a server response. +// Status responses are returned in the result structure, and can be cast +// to built-in error instance (or in the returned error if the client is +// configured accordingly). Certain statuses can be checked using `apistatus` +// and standard `errors` packages. Note that package provides some helper +// functions to work with status returns (e.g. IsErrContainerNotFound). +// All possible responses are documented in methods, however, some may be +// returned from all of them (pay attention to the presence of the pointer sign): +// - *apistatus.ServerInternal on internal server error; +// - *apistatus.NodeUnderMaintenance if a server is under maintenance; +// - *apistatus.SuccessDefaultV2 on default success. +// +// Client MUST NOT be copied by value: use pointer to Client instead. +// +// See client package overview to get some examples. +type Client struct { + prm PrmInit + + c client.Client + + server frostFSAPIServer +} + +// Init brings the Client instance to its initial state. +// +// One-time method call during application init stage (before Dial) is expected. +// Calling multiple times leads to undefined behavior. +// +// See docs of PrmInit methods for details. See also Dial / Close. +func (c *Client) Init(prm PrmInit) { + c.prm = prm +} + +// Dial establishes a connection to the server from the FrostFS network. +// Returns an error describing failure reason. If failed, the Client +// SHOULD NOT be used. +// +// Uses the context specified by SetContext if it was called with non-nil +// argument, otherwise context.Background() is used. Dial returns context +// errors, see context package docs for details. +// +// Returns an error if required parameters are set incorrectly, look carefully +// at the method documentation. +// +// One-time method call during application start-up stage (after Init ) is expected. +// Calling multiple times leads to undefined behavior. +// +// See also Init / Close. +func (c *Client) Dial(ctx context.Context, prm PrmDial) error { + if prm.Endpoint == "" { + return errorServerAddrUnset + } + + if prm.DialTimeout <= 0 { + prm.DialTimeout = defaultDialTimeout + } + if prm.StreamTimeout <= 0 { + prm.StreamTimeout = defaultStreamTimeout + } + + c.c = *client.New(append( + client.WithNetworkURIAddress(prm.Endpoint, prm.TLSConfig), + client.WithDialTimeout(prm.DialTimeout), + client.WithRWTimeout(prm.StreamTimeout), + client.WithGRPCDialOptions(prm.GRPCDialOptions), + )...) + + c.setFrostFSAPIServer((*coreServer)(&c.c)) + + // TODO: (neofs-api-go#382) perform generic dial stage of the client.Client + _, err := rpc.Balance(&c.c, new(v2accounting.BalanceRequest), + client.WithContext(ctx), + ) + // return context errors since they signal about dial problem + if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) { + return err + } + + return nil +} + +// sets underlying provider of frostFSAPIServer. The method is used for testing as an approach +// to skip Dial stage and override FrostFS API server. MUST NOT be used outside test code. +// In real applications wrapper over git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client +// is statically used. +func (c *Client) setFrostFSAPIServer(server frostFSAPIServer) { + c.server = server +} + +// Close closes underlying connection to the FrostFS server. Implements io.Closer. +// MUST NOT be called before successful Dial. Can be called concurrently +// with server operations processing on running goroutines: in this case +// they are likely to fail due to a connection error. +// +// One-time method call during application shutdown stage (after Init and Dial) +// is expected. Calling multiple times leads to undefined behavior. +// +// See also Init / Dial. +func (c *Client) Close() error { + return c.c.Conn().Close() +} + +// PrmInit groups initialization parameters of Client instances. +// +// See also Init. +type PrmInit struct { + DisableFrostFSErrorResolution bool + + Key ecdsa.PrivateKey + + ResponseInfoCallback func(ResponseMetaInfo) error + + NetMagic uint64 +} + +// SetDefaultPrivateKey sets Client private key to be used for the protocol +// communication by default. +// +// Required for operations without custom key parametrization (see corresponding Prm* docs). +// +// Deprecated: Use PrmInit.Key instead. +func (x *PrmInit) SetDefaultPrivateKey(key ecdsa.PrivateKey) { + x.Key = key +} + +// Deprecated: method is no-op. Option is default. +func (x *PrmInit) ResolveFrostFSFailures() { +} + +// DisableFrostFSFailuresResolution makes the Client to preserve failure statuses of the +// FrostFS protocol only in resulting structure (see corresponding Res* docs). +// These errors are returned from each protocol operation. By default, statuses +// are resolved and returned as a Go built-in errors. +// +// Deprecated: Use PrmInit.DisableFrostFSErrorResolution instead. +func (x *PrmInit) DisableFrostFSFailuresResolution() { + x.DisableFrostFSErrorResolution = true +} + +// SetResponseInfoCallback makes the Client to pass ResponseMetaInfo from each +// FrostFS server response to f. Nil (default) means ignore response meta info. +// +// Deprecated: Use PrmInit.ResponseInfoCallback instead. +func (x *PrmInit) SetResponseInfoCallback(f func(ResponseMetaInfo) error) { + x.ResponseInfoCallback = f +} + +const ( + defaultDialTimeout = 5 * time.Second + defaultStreamTimeout = 10 * time.Second +) + +// PrmDial groups connection parameters for the Client. +// +// See also Dial. +type PrmDial struct { + Endpoint string + + TLSConfig *tls.Config + + // If DialTimeout is non-positive, then it's set to defaultDialTimeout. + DialTimeout time.Duration + + // If StreamTimeout is non-positive, then it's set to defaultStreamTimeout. + StreamTimeout time.Duration + + GRPCDialOptions []grpc.DialOption +} + +// SetServerURI sets server URI in the FrostFS network. +// Required parameter. +// +// Format of the URI: +// +// [scheme://]host:port +// +// Supported schemes: +// +// grpc +// grpcs +// +// See also SetTLSConfig. +// +// Deprecated: Use PrmDial.Endpoint instead. +func (x *PrmDial) SetServerURI(endpoint string) { + x.Endpoint = endpoint +} + +// SetTLSConfig sets tls.Config to open TLS client connection +// to the FrostFS server. Nil (default) means insecure connection. +// +// See also SetServerURI. +// +// Depreacted: Use PrmDial.TLSConfig instead. +func (x *PrmDial) SetTLSConfig(tlsConfig *tls.Config) { + x.TLSConfig = tlsConfig +} + +// SetTimeout sets the timeout for connection to be established. +// MUST BE positive. If not called, 5s timeout will be used by default. +// +// Deprecated: Use PrmDial.DialTimeout instead. +func (x *PrmDial) SetTimeout(timeout time.Duration) { + x.DialTimeout = timeout +} + +// SetStreamTimeout sets the timeout for individual operations in streaming RPC. +// MUST BE positive. If not called, 10s timeout will be used by default. +// +// Deprecated: Use PrmDial.StreamTimeout instead. +func (x *PrmDial) SetStreamTimeout(timeout time.Duration) { + x.StreamTimeout = timeout +} + +// SetGRPCDialOptions sets the gRPC dial options for new gRPC client connection. +// +// Deprecated: Use PrmDial.GRPCDialOptions instead. +func (x *PrmDial) SetGRPCDialOptions(opts ...grpc.DialOption) { + x.GRPCDialOptions = opts +} diff --git a/pkg/sdk/client/client_test.go b/pkg/sdk/client/client_test.go new file mode 100644 index 000000000..da1d24c4a --- /dev/null +++ b/pkg/sdk/client/client_test.go @@ -0,0 +1,67 @@ +package client + +import ( + "context" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "testing" + + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + "github.com/stretchr/testify/require" +) + +/* +File contains common functionality used for client package testing. +*/ + +var key, _ = ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + +var statusErr apistatus.ServerInternal + +func init() { + statusErr.SetMessage("test status error") +} + +func assertStatusErr(tb testing.TB, res interface{ Status() apistatus.Status }) { + require.IsType(tb, &statusErr, res.Status()) + require.Equal(tb, statusErr.Message(), res.Status().(*apistatus.ServerInternal).Message()) +} + +func newClient(server frostFSAPIServer) *Client { + prm := PrmInit{ + Key: *key, + } + + var c Client + c.Init(prm) + c.setFrostFSAPIServer(server) + + return &c +} + +func TestClient_DialContext(t *testing.T) { + var c Client + + // try to connect to any host + prm := PrmDial{ + Endpoint: "localhost:8080", + } + + assert := func(ctx context.Context, errExpected error) { + // expect particular context error according to Dial docs + require.ErrorIs(t, c.Dial(ctx, prm), errExpected) + } + + // create pre-abandoned context + ctx, cancel := context.WithCancel(context.Background()) + cancel() + + assert(ctx, context.Canceled) + + // create "pre-deadlined" context + ctx, cancel = context.WithTimeout(context.Background(), 0) + defer cancel() + + assert(ctx, context.DeadlineExceeded) +} diff --git a/pkg/sdk/client/common.go b/pkg/sdk/client/common.go new file mode 100644 index 000000000..0d4d8eb7d --- /dev/null +++ b/pkg/sdk/client/common.go @@ -0,0 +1,123 @@ +package client + +import ( + "errors" + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client" + v2session "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/signature" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/version" +) + +// structure is embedded to all resulting types in order to inherit status-related methods. +type statusRes struct { + st apistatus.Status +} + +// Status returns server's status return. +// +// Use apistatus package functionality to handle the status. +func (x statusRes) Status() apistatus.Status { + return x.st +} + +func writeXHeadersToMeta(xHeaders []string, h *v2session.RequestMetaHeader) { + if len(xHeaders) == 0 { + return + } + + // TODO (aarifullin): remove the panic when all client parameters will check XHeaders + // within buildRequest invocation. + if len(xHeaders)%2 != 0 { + panic("slice of X-Headers with odd length") + } + + hs := make([]v2session.XHeader, len(xHeaders)/2) + for i := 0; i < len(xHeaders); i += 2 { + hs[i].SetKey(xHeaders[i]) + hs[i].SetValue(xHeaders[i+1]) + } + + h.SetXHeaders(hs) +} + +// error messages. +var ( + errorMissingContainer = errors.New("missing container") + errorMissingObject = errors.New("missing object") + errorAccountNotSet = errors.New("account not set") + errorServerAddrUnset = errors.New("server address is unset or empty") + errorEACLTableNotSet = errors.New("eACL table not set") + errorMissingAnnouncements = errors.New("missing announcements") + errorZeroRangeLength = errors.New("zero range length") + errorMissingRanges = errors.New("missing ranges") + errorInvalidXHeaders = errors.New("xheaders must be presented only as key-value pairs") +) + +type request interface { + GetMetaHeader() *v2session.RequestMetaHeader + SetMetaHeader(*v2session.RequestMetaHeader) + SetVerificationHeader(*v2session.RequestVerificationHeader) +} + +func (c *Client) prepareRequest(req request, meta *v2session.RequestMetaHeader) { + ttl := meta.GetTTL() + if ttl == 0 { + ttl = 2 + } + + verV2 := meta.GetVersion() + if verV2 == nil { + verV2 = new(refs.Version) + version.Current().WriteToV2(verV2) + } + + meta.SetTTL(ttl) + meta.SetVersion(verV2) + meta.SetNetworkMagic(c.prm.NetMagic) + + req.SetMetaHeader(meta) +} + +// processResponse verifies response signature and converts status to an error if needed. +func (c *Client) processResponse(resp responseV2) (apistatus.Status, error) { + if c.prm.ResponseInfoCallback != nil { + rmi := ResponseMetaInfo{ + key: resp.GetVerificationHeader().GetBodySignature().GetKey(), + epoch: resp.GetMetaHeader().GetEpoch(), + } + if err := c.prm.ResponseInfoCallback(rmi); err != nil { + return nil, fmt.Errorf("response callback error: %w", err) + } + } + + err := signature.VerifyServiceMessage(resp) + if err != nil { + return nil, fmt.Errorf("invalid response signature: %w", err) + } + + st := apistatus.FromStatusV2(resp.GetMetaHeader().GetStatus()) + if !c.prm.DisableFrostFSErrorResolution { + return st, apistatus.ErrFromStatus(st) + } + return st, nil +} + +// ExecRaw executes f with underlying git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client.Client +// instance. Communicate over the Protocol Buffers protocol in a more flexible way: +// most often used to transmit data over a fixed version of the FrostFS protocol, as well +// as to support custom services. +// +// The f must not manipulate the client connection passed into it. +// +// Like all other operations, must be called after connecting to the server and +// before closing the connection. +// +// See also Dial and Close. +// See also git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client package docs. +func (c *Client) ExecRaw(f func(client *client.Client) error) error { + return f(&c.c) +} diff --git a/pkg/sdk/client/container.go b/pkg/sdk/client/container.go new file mode 100644 index 000000000..de566f3e0 --- /dev/null +++ b/pkg/sdk/client/container.go @@ -0,0 +1,28 @@ +package client + +import ( + "context" + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container" +) + +// SyncContainerWithNetwork requests network configuration using passed client +// and applies it to the container. Container MUST not be nil. +// +// Note: if container does not match network configuration, SyncContainerWithNetwork +// changes it. +// +// Returns any network/parsing config errors. +// +// See also NetworkInfo, container.ApplyNetworkConfig. +func SyncContainerWithNetwork(ctx context.Context, cnr *container.Container, c *Client) error { + res, err := c.NetworkInfo(ctx, PrmNetworkInfo{}) + if err != nil { + return fmt.Errorf("network info call: %w", err) + } + + container.ApplyNetworkConfig(cnr, res.Info()) + + return nil +} diff --git a/pkg/sdk/client/container_delete.go b/pkg/sdk/client/container_delete.go new file mode 100644 index 000000000..35b7720a2 --- /dev/null +++ b/pkg/sdk/client/container_delete.go @@ -0,0 +1,139 @@ +package client + +import ( + "context" + "fmt" + + v2container "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/container" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + rpcapi "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client" + v2session "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/signature" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/crypto" + frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/crypto/ecdsa" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/session" +) + +// PrmContainerDelete groups parameters of ContainerDelete operation. +type PrmContainerDelete struct { + // FrostFS request X-Headers + XHeaders []string + + ContainerID *cid.ID + + Session *session.Container +} + +// SetContainer sets identifier of the FrostFS container to be removed. +// Required parameter. +// +// Deprecated: Use PrmContainerDelete.Container instead. +func (prm *PrmContainerDelete) SetContainer(id cid.ID) { + prm.ContainerID = &id +} + +func (prm *PrmContainerDelete) buildRequest(c *Client) (*v2container.DeleteRequest, error) { + if prm.ContainerID == nil { + return nil, errorMissingContainer + } + + if len(prm.XHeaders)%2 != 0 { + return nil, errorInvalidXHeaders + } + + var cidV2 refs.ContainerID + prm.ContainerID.WriteToV2(&cidV2) + + // Container contract expects signature of container ID value, + // don't get confused with stable marshaled protobuf container.ID structure. + data := cidV2.GetValue() + + var sig frostfscrypto.Signature + + err := sig.Calculate(frostfsecdsa.SignerRFC6979(c.prm.Key), data) + if err != nil { + return nil, fmt.Errorf("calculate signature: %w", err) + } + + var sigv2 refs.Signature + sig.WriteToV2(&sigv2) + + reqBody := new(v2container.DeleteRequestBody) + reqBody.SetContainerID(&cidV2) + reqBody.SetSignature(&sigv2) + + var meta v2session.RequestMetaHeader + writeXHeadersToMeta(prm.XHeaders, &meta) + + if prm.Session != nil { + var tokv2 v2session.Token + prm.Session.WriteToV2(&tokv2) + + meta.SetSessionToken(&tokv2) + } + + var req v2container.DeleteRequest + req.SetBody(reqBody) + c.prepareRequest(&req, &meta) + return &req, nil +} + +// WithinSession specifies session within which container should be removed. +// +// Creator of the session acquires the authorship of the request. +// This may affect the execution of an operation (e.g. access control). +// +// Must be signed. +// +// Deprecated: Use PrmContainerDelete.Session instead. +func (prm *PrmContainerDelete) WithinSession(tok session.Container) { + prm.Session = &tok +} + +// ResContainerDelete groups resulting values of ContainerDelete operation. +type ResContainerDelete struct { + statusRes +} + +// ContainerDelete sends request to remove the FrostFS container. +// +// Exactly one return value is non-nil. By default, server status is returned in res structure. +// Any client's internal or transport errors are returned as `error`. +// If PrmInit.DisableFrostFSFailuresResolution has been called, unsuccessful +// FrostFS status codes are included in the returned result structure, +// otherwise, are also returned as `error`. +// +// Operation is asynchronous and no guaranteed even in the absence of errors. +// The required time is also not predictable. +// +// Success can be verified by reading by identifier (see GetContainer). +// +// Returns an error if parameters are set incorrectly (see PrmContainerDelete docs). +// Context is required and must not be nil. It is used for network communication. +// +// Exactly one return value is non-nil. Server status return is returned in ResContainerDelete. +// Reflects all internal errors in second return value (transport problems, response processing, etc.). +// +// Return statuses: +// - global (see Client docs). +func (c *Client) ContainerDelete(ctx context.Context, prm PrmContainerDelete) (*ResContainerDelete, error) { + req, err := prm.buildRequest(c) + if err != nil { + return nil, err + } + + if err := signature.SignServiceMessage(&c.prm.Key, req); err != nil { + return nil, fmt.Errorf("sign request: %w", err) + } + + resp, err := rpcapi.DeleteContainer(&c.c, req, client.WithContext(ctx)) + if err != nil { + return nil, err + } + + var res ResContainerDelete + res.st, err = c.processResponse(resp) + return &res, err +} diff --git a/pkg/sdk/client/container_eacl.go b/pkg/sdk/client/container_eacl.go new file mode 100644 index 000000000..9b01e1f32 --- /dev/null +++ b/pkg/sdk/client/container_eacl.go @@ -0,0 +1,123 @@ +package client + +import ( + "context" + "fmt" + + v2container "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/container" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + rpcapi "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client" + v2session "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/signature" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/eacl" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/session" +) + +// PrmContainerEACL groups parameters of ContainerEACL operation. +type PrmContainerEACL struct { + // FrostFS request X-Headers. + XHeaders []string + + ContainerID *cid.ID + + Session *session.Container +} + +// SetContainer sets identifier of the FrostFS container to read the eACL table. +// Required parameter. +// +// Deprecated: Use PrmContainerEACL.ContainerID instead. +func (x *PrmContainerEACL) SetContainer(id cid.ID) { + x.ContainerID = &id +} + +func (x *PrmContainerEACL) buildRequest(c *Client) (*v2container.GetExtendedACLRequest, error) { + if x.ContainerID == nil { + return nil, errorMissingContainer + } + + if len(x.XHeaders)%2 != 0 { + return nil, errorInvalidXHeaders + } + + var cidV2 refs.ContainerID + x.ContainerID.WriteToV2(&cidV2) + + reqBody := new(v2container.GetExtendedACLRequestBody) + reqBody.SetContainerID(&cidV2) + + var meta v2session.RequestMetaHeader + writeXHeadersToMeta(x.XHeaders, &meta) + + if x.Session != nil { + var tokv2 v2session.Token + x.Session.WriteToV2(&tokv2) + + meta.SetSessionToken(&tokv2) + } + + var req v2container.GetExtendedACLRequest + req.SetBody(reqBody) + c.prepareRequest(&req, &meta) + return &req, nil +} + +// ResContainerEACL groups resulting values of ContainerEACL operation. +type ResContainerEACL struct { + statusRes + + table eacl.Table +} + +// Table returns eACL table of the requested container. +func (x ResContainerEACL) Table() eacl.Table { + return x.table +} + +// ContainerEACL reads eACL table of the FrostFS container. +// +// Exactly one return value is non-nil. By default, server status is returned in res structure. +// Any client's internal or transport errors are returned as `error`. +// If PrmInit.DisableFrostFSFailuresResolution has been called, unsuccessful +// FrostFS status codes are included in the returned result structure, +// otherwise, are also returned as `error`. +// +// Returns an error if parameters are set incorrectly (see PrmContainerEACL docs). +// Context is required and must not be nil. It is used for network communication. +// +// Return statuses: +// - global (see Client docs); +// - *apistatus.ContainerNotFound; +// - *apistatus.EACLNotFound. +func (c *Client) ContainerEACL(ctx context.Context, prm PrmContainerEACL) (*ResContainerEACL, error) { + req, err := prm.buildRequest(c) + if err != nil { + return nil, err + } + + if err := signature.SignServiceMessage(&c.prm.Key, req); err != nil { + return nil, fmt.Errorf("sign request: %w", err) + } + + resp, err := rpcapi.GetEACL(&c.c, req, client.WithContext(ctx)) + if err != nil { + return nil, err + } + + var res ResContainerEACL + res.st, err = c.processResponse(resp) + if err != nil || !apistatus.IsSuccessful(res.st) { + return &res, err + } + + eACL := resp.GetBody().GetEACL() + if eACL == nil { + return &res, newErrMissingResponseField("eACL") + } + + res.table = *eacl.NewTableFromV2(eACL) + return &res, nil +} diff --git a/pkg/sdk/client/container_get.go b/pkg/sdk/client/container_get.go new file mode 100644 index 000000000..84c7d985c --- /dev/null +++ b/pkg/sdk/client/container_get.go @@ -0,0 +1,126 @@ +package client + +import ( + "context" + "errors" + "fmt" + + v2container "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/container" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + rpcapi "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client" + v2session "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/signature" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/session" +) + +// PrmContainerGet groups parameters of ContainerGet operation. +type PrmContainerGet struct { + // FrostFS request X-Headers. + XHeaders []string + + ContainerID *cid.ID + + Session *session.Container +} + +// SetContainer sets identifier of the container to be read. +// Required parameter. +// +// Deprecated: Use PrmContainerGet.ContainerID instead. +func (prm *PrmContainerGet) SetContainer(cid cid.ID) { + prm.ContainerID = &cid +} + +func (prm *PrmContainerGet) buildRequest(c *Client) (*v2container.GetRequest, error) { + if prm.ContainerID == nil { + return nil, errorMissingContainer + } + + if len(prm.XHeaders)%2 != 0 { + return nil, errorInvalidXHeaders + } + + var cidV2 refs.ContainerID + prm.ContainerID.WriteToV2(&cidV2) + + reqBody := new(v2container.GetRequestBody) + reqBody.SetContainerID(&cidV2) + + var meta v2session.RequestMetaHeader + writeXHeadersToMeta(prm.XHeaders, &meta) + + if prm.Session != nil { + var tokv2 v2session.Token + prm.Session.WriteToV2(&tokv2) + + meta.SetSessionToken(&tokv2) + } + + var req v2container.GetRequest + req.SetBody(reqBody) + c.prepareRequest(&req, &meta) + return &req, nil +} + +// ResContainerGet groups resulting values of ContainerGet operation. +type ResContainerGet struct { + statusRes + + cnr container.Container +} + +// Container returns structured information about the requested container. +// +// Client doesn't retain value so modification is safe. +func (x ResContainerGet) Container() container.Container { + return x.cnr +} + +// ContainerGet reads FrostFS container by ID. +// +// Exactly one return value is non-nil. By default, server status is returned in res structure. +// Any client's internal or transport errors are returned as `error`. +// If PrmInit.DisableFrostFSFailuresResolution has been called, unsuccessful +// FrostFS status codes are included in the returned result structure, +// otherwise, are also returned as `error`. +// +// Returns an error if parameters are set incorrectly (see PrmContainerGet docs). +// Context is required and must not be nil. It is used for network communication. +// +// Return statuses: +// - global (see Client docs); +// - *apistatus.ContainerNotFound. +func (c *Client) ContainerGet(ctx context.Context, prm PrmContainerGet) (*ResContainerGet, error) { + req, err := prm.buildRequest(c) + if err != nil { + return nil, err + } + + if err := signature.SignServiceMessage(&c.prm.Key, req); err != nil { + return nil, fmt.Errorf("sign request: %w", err) + } + + resp, err := rpcapi.GetContainer(&c.c, req, client.WithContext(ctx)) + if err != nil { + return nil, err + } + + var res ResContainerGet + res.st, err = c.processResponse(resp) + if err != nil || !apistatus.IsSuccessful(res.st) { + return &res, err + } + + cnrV2 := resp.GetBody().GetContainer() + if cnrV2 == nil { + return &res, errors.New("missing container in response") + } + if err := res.cnr.ReadFromV2(*cnrV2); err != nil { + return &res, fmt.Errorf("invalid container in response: %w", err) + } + return &res, nil +} diff --git a/pkg/sdk/client/container_list.go b/pkg/sdk/client/container_list.go new file mode 100644 index 000000000..17118dab9 --- /dev/null +++ b/pkg/sdk/client/container_list.go @@ -0,0 +1,119 @@ +package client + +import ( + "context" + "fmt" + + v2container "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/container" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + rpcapi "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client" + v2session "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/signature" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" +) + +// PrmContainerList groups parameters of ContainerList operation. +type PrmContainerList struct { + XHeaders []string + + Account user.ID + + Session *session.Container +} + +// SetAccount sets identifier of the FrostFS account to list the containers. +// Required parameter. +// +// Deprecated: Use PrmContainerList.Account instead. +func (x *PrmContainerList) SetAccount(id user.ID) { + x.Account = id +} + +func (x *PrmContainerList) buildRequest(c *Client) (*v2container.ListRequest, error) { + if x.Account.IsEmpty() { + return nil, errorAccountNotSet + } + + var ownerV2 refs.OwnerID + x.Account.WriteToV2(&ownerV2) + + reqBody := new(v2container.ListRequestBody) + reqBody.SetOwnerID(&ownerV2) + + var meta v2session.RequestMetaHeader + writeXHeadersToMeta(x.XHeaders, &meta) + + if x.Session != nil { + var tokv2 v2session.Token + x.Session.WriteToV2(&tokv2) + + meta.SetSessionToken(&tokv2) + } + + var req v2container.ListRequest + req.SetBody(reqBody) + c.prepareRequest(&req, &meta) + return &req, nil +} + +// ResContainerList groups resulting values of ContainerList operation. +type ResContainerList struct { + statusRes + + ids []cid.ID +} + +// Containers returns list of identifiers of the account-owned containers. +// +// Client doesn't retain value so modification is safe. +func (x ResContainerList) Containers() []cid.ID { + return x.ids +} + +// ContainerList requests identifiers of the account-owned containers. +// +// Exactly one return value is non-nil. By default, server status is returned in res structure. +// Any client's internal or transport errors are returned as `error`. +// If PrmInit.DisableFrostFSFailuresResolution has been called, unsuccessful +// FrostFS status codes are included in the returned result structure, +// otherwise, are also returned as `error`. +// +// Returns an error if parameters are set incorrectly (see PrmContainerList docs). +// Context is required and must not be nil. It is used for network communication. +// +// Return statuses: +// - global (see Client docs). +func (c *Client) ContainerList(ctx context.Context, prm PrmContainerList) (*ResContainerList, error) { + req, err := prm.buildRequest(c) + if err != nil { + return nil, err + } + + if err := signature.SignServiceMessage(&c.prm.Key, req); err != nil { + return nil, fmt.Errorf("sign request: %w", err) + } + + resp, err := rpcapi.ListContainers(&c.c, req, client.WithContext(ctx)) + if err != nil { + return nil, err + } + + var res ResContainerList + res.st, err = c.processResponse(resp) + if err != nil || !apistatus.IsSuccessful(res.st) { + return &res, err + } + + res.ids = make([]cid.ID, len(resp.GetBody().GetContainerIDs())) + for i, cidV2 := range resp.GetBody().GetContainerIDs() { + if err := res.ids[i].ReadFromV2(cidV2); err != nil { + return &res, fmt.Errorf("invalid ID in the response: %w", err) + } + } + + return &res, nil +} diff --git a/pkg/sdk/client/container_put.go b/pkg/sdk/client/container_put.go new file mode 100644 index 000000000..ff34d2684 --- /dev/null +++ b/pkg/sdk/client/container_put.go @@ -0,0 +1,160 @@ +package client + +import ( + "context" + "fmt" + + v2container "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/container" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + rpcapi "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client" + v2session "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/signature" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/crypto" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/session" +) + +// PrmContainerPut groups parameters of ContainerPut operation. +type PrmContainerPut struct { + // FrostFS request X-Headers + XHeaders []string + + Container *container.Container + + Session *session.Container +} + +// SetContainer sets structured information about new FrostFS container. +// Required parameter. +// +// Deprecated: Use PrmContainerPut.Container instead. +func (x *PrmContainerPut) SetContainer(cnr container.Container) { + x.Container = &cnr +} + +// WithinSession specifies session within which container should be saved. +// +// Creator of the session acquires the authorship of the request. This affects +// the execution of an operation (e.g. access control). +// +// Session is optional, if set the following requirements apply: +// - session operation MUST be session.VerbContainerPut (ForVerb) +// - token MUST be signed using private key of the owner of the container to be saved +// +// Deprecated: Use PrmContainerPut.Session instead. +func (x *PrmContainerPut) WithinSession(s session.Container) { + x.Session = &s +} + +func (x *PrmContainerPut) buildRequest(c *Client) (*v2container.PutRequest, error) { + if x.Container == nil { + return nil, errorMissingContainer + } + + if len(x.XHeaders)%2 != 0 { + return nil, errorInvalidXHeaders + } + + // TODO: check private key is set before forming the request + var cnr v2container.Container + x.Container.WriteToV2(&cnr) + + var sig frostfscrypto.Signature + + err := container.CalculateSignature(&sig, *x.Container, c.prm.Key) + if err != nil { + return nil, fmt.Errorf("calculate container signature: %w", err) + } + + var sigv2 refs.Signature + sig.WriteToV2(&sigv2) + + reqBody := new(v2container.PutRequestBody) + reqBody.SetContainer(&cnr) + reqBody.SetSignature(&sigv2) + + var meta v2session.RequestMetaHeader + writeXHeadersToMeta(x.XHeaders, &meta) + + if x.Session != nil { + var tokv2 v2session.Token + x.Session.WriteToV2(&tokv2) + + meta.SetSessionToken(&tokv2) + } + + var req v2container.PutRequest + req.SetBody(reqBody) + c.prepareRequest(&req, &meta) + return &req, nil +} + +// ResContainerPut groups resulting values of ContainerPut operation. +type ResContainerPut struct { + statusRes + + id cid.ID +} + +// ID returns identifier of the container declared to be stored in the system. +// Used as a link to information about the container (in particular, you can +// asynchronously check if the save was successful). +func (x ResContainerPut) ID() cid.ID { + return x.id +} + +// ContainerPut sends request to save container in FrostFS. +// +// Exactly one return value is non-nil. By default, server status is returned in res structure. +// Any client's internal or transport errors are returned as `error`. +// If PrmInit.DisableFrostFSFailuresResolution has been called, unsuccessful +// FrostFS status codes are included in the returned result structure, +// otherwise, are also returned as `error`. +// +// Operation is asynchronous and no guaranteed even in the absence of errors. +// The required time is also not predictable. +// +// Success can be verified by reading by identifier (see ResContainerPut.ID). +// +// Returns an error if parameters are set incorrectly (see PrmContainerPut docs). +// Context is required and must not be nil. It is used for network communication. +// +// Return statuses: +// - global (see Client docs). +// +// nolint: funlen +func (c *Client) ContainerPut(ctx context.Context, prm PrmContainerPut) (*ResContainerPut, error) { + req, err := prm.buildRequest(c) + if err != nil { + return nil, err + } + + if err := signature.SignServiceMessage(&c.prm.Key, req); err != nil { + return nil, fmt.Errorf("sign request: %w", err) + } + + resp, err := rpcapi.PutContainer(&c.c, req, client.WithContext(ctx)) + if err != nil { + return nil, err + } + + var res ResContainerPut + res.st, err = c.processResponse(resp) + if err != nil || !apistatus.IsSuccessful(res.st) { + return &res, err + } + + const fieldCnrID = "container ID" + + cidV2 := resp.GetBody().GetContainerID() + if cidV2 == nil { + return &res, newErrMissingResponseField(fieldCnrID) + } + if err := res.id.ReadFromV2(*cidV2); err != nil { + return &res, newErrInvalidResponseField(fieldCnrID, err) + } + return &res, nil +} diff --git a/pkg/sdk/client/container_set_eacl.go b/pkg/sdk/client/container_set_eacl.go new file mode 100644 index 000000000..0cb6d64cc --- /dev/null +++ b/pkg/sdk/client/container_set_eacl.go @@ -0,0 +1,136 @@ +package client + +import ( + "context" + "fmt" + + v2container "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/container" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + rpcapi "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client" + v2session "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/signature" + frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/crypto" + frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/crypto/ecdsa" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/eacl" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/session" +) + +// PrmContainerSetEACL groups parameters of ContainerSetEACL operation. +type PrmContainerSetEACL struct { + // FrostFS request X-Headers. + XHeaders []string + + Table *eacl.Table + + Session *session.Container +} + +// SetTable sets eACL table structure to be set for the container. +// Required parameter. +// +// Deprecated: Use PrmContainerSetEACL.Table instead. +func (x *PrmContainerSetEACL) SetTable(table eacl.Table) { + x.Table = &table +} + +// WithinSession specifies session within which extended ACL of the container +// should be saved. +// +// Creator of the session acquires the authorship of the request. This affects +// the execution of an operation (e.g. access control). +// +// Session is optional, if set the following requirements apply: +// - if particular container is specified (ApplyOnlyTo), it MUST equal the container +// for which extended ACL is going to be set +// - session operation MUST be session.VerbContainerSetEACL (ForVerb) +// - token MUST be signed using private key of the owner of the container to be saved +// +// Deprecated: Use PrmContainerSetEACL.Session instead. +func (x *PrmContainerSetEACL) WithinSession(s session.Container) { + x.Session = &s +} + +func (x *PrmContainerSetEACL) buildRequest(c *Client) (*v2container.SetExtendedACLRequest, error) { + if x.Table == nil { + return nil, errorEACLTableNotSet + } + + if len(x.XHeaders)%2 != 0 { + return nil, errorInvalidXHeaders + } + + eaclV2 := x.Table.ToV2() + + var sig frostfscrypto.Signature + + err := sig.Calculate(frostfsecdsa.SignerRFC6979(c.prm.Key), eaclV2.StableMarshal(nil)) + if err != nil { + return nil, fmt.Errorf("calculate signature: %w", err) + } + + var sigv2 refs.Signature + sig.WriteToV2(&sigv2) + + reqBody := new(v2container.SetExtendedACLRequestBody) + reqBody.SetEACL(eaclV2) + reqBody.SetSignature(&sigv2) + + var meta v2session.RequestMetaHeader + writeXHeadersToMeta(x.XHeaders, &meta) + + if x.Session != nil { + var tokv2 v2session.Token + x.Session.WriteToV2(&tokv2) + + meta.SetSessionToken(&tokv2) + } + + var req v2container.SetExtendedACLRequest + req.SetBody(reqBody) + c.prepareRequest(&req, &meta) + return &req, nil +} + +// ResContainerSetEACL groups resulting values of ContainerSetEACL operation. +type ResContainerSetEACL struct { + statusRes +} + +// ContainerSetEACL sends request to update eACL table of the FrostFS container. +// +// Exactly one return value is non-nil. By default, server status is returned in res structure. +// Any client's internal or transport errors are returned as `error`. +// If PrmInit.DisableFrostFSFailuresResolution has been called, unsuccessful +// FrostFS status codes are included in the returned result structure, +// otherwise, are also returned as `error`. +// +// Operation is asynchronous and no guaranteed even in the absence of errors. +// The required time is also not predictable. +// +// Success can be verified by reading by identifier (see EACL). +// +// Returns an error if parameters are set incorrectly (see PrmContainerSetEACL docs). +// Context is required and must not be nil. It is used for network communication. +// +// Return statuses: +// - global (see Client docs). +func (c *Client) ContainerSetEACL(ctx context.Context, prm PrmContainerSetEACL) (*ResContainerSetEACL, error) { + req, err := prm.buildRequest(c) + if err != nil { + return nil, err + } + + if err := signature.SignServiceMessage(&c.prm.Key, req); err != nil { + return nil, fmt.Errorf("sign request: %w", err) + } + + resp, err := rpcapi.SetEACL(&c.c, req, client.WithContext(ctx)) + if err != nil { + return nil, err + } + + var res ResContainerSetEACL + res.st, err = c.processResponse(resp) + return &res, err +} diff --git a/pkg/sdk/client/container_space.go b/pkg/sdk/client/container_space.go new file mode 100644 index 000000000..cba0d71a0 --- /dev/null +++ b/pkg/sdk/client/container_space.go @@ -0,0 +1,92 @@ +package client + +import ( + "context" + "fmt" + + v2container "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/container" + rpcapi "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client" + v2session "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/signature" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container" +) + +// PrmAnnounceSpace groups parameters of ContainerAnnounceUsedSpace operation. +type PrmAnnounceSpace struct { + XHeaders []string + + Announcements []container.SizeEstimation +} + +// SetValues sets values describing volume of space that is used for the container objects. +// Required parameter. Must not be empty. +// +// Must not be mutated before the end of the operation. +// +// Deprecated: Use PrmAnnounceSpace.Announcements instead. +func (x *PrmAnnounceSpace) SetValues(vs []container.SizeEstimation) { + x.Announcements = vs +} + +func (x *PrmAnnounceSpace) buildRequest(c *Client) (*v2container.AnnounceUsedSpaceRequest, error) { + if len(x.Announcements) == 0 { + return nil, errorMissingAnnouncements + } + + v2announce := make([]v2container.UsedSpaceAnnouncement, len(x.Announcements)) + for i := range x.Announcements { + x.Announcements[i].WriteToV2(&v2announce[i]) + } + + reqBody := new(v2container.AnnounceUsedSpaceRequestBody) + reqBody.SetAnnouncements(v2announce) + + var req v2container.AnnounceUsedSpaceRequest + req.SetBody(reqBody) + c.prepareRequest(&req, new(v2session.RequestMetaHeader)) + return &req, nil +} + +// ResAnnounceSpace groups resulting values of ContainerAnnounceUsedSpace operation. +type ResAnnounceSpace struct { + statusRes +} + +// ContainerAnnounceUsedSpace sends request to announce volume of the space used for the container objects. +// +// Exactly one return value is non-nil. By default, server status is returned in res structure. +// Any client's internal or transport errors are returned as `error`. +// If PrmInit.DisableFrostFSFailuresResolution has been called, unsuccessful +// FrostFS status codes are included in the returned result structure, +// otherwise, are also returned as `error`. +// +// Operation is asynchronous and no guaranteed even in the absence of errors. +// The required time is also not predictable. +// +// At this moment success can not be checked. +// +// Returns an error if parameters are set incorrectly (see PrmAnnounceSpace docs). +// Context is required and must not be nil. It is used for network communication. +// +// Return statuses: +// - global (see Client docs). +func (c *Client) ContainerAnnounceUsedSpace(ctx context.Context, prm PrmAnnounceSpace) (*ResAnnounceSpace, error) { + req, err := prm.buildRequest(c) + if err != nil { + return nil, err + } + + if err := signature.SignServiceMessage(&c.prm.Key, req); err != nil { + return nil, fmt.Errorf("sign request: %w", err) + } + + resp, err := rpcapi.AnnounceUsedSpace(&c.c, req, client.WithContext(ctx)) + if err != nil { + return nil, err + } + + var res ResAnnounceSpace + res.st, err = c.processResponse(resp) + return &res, err +} diff --git a/pkg/sdk/client/doc.go b/pkg/sdk/client/doc.go new file mode 100644 index 000000000..0cdcc3a4f --- /dev/null +++ b/pkg/sdk/client/doc.go @@ -0,0 +1,91 @@ +/* +Package client provides FrostFS API client implementation. + +The main component is Client type. It is a virtual connection to the network +and provides methods for executing operations on the server. + +Create client instance: + + var c client.Client + +Initialize client state: + + var prm client.PrmInit + prm.SetDefaultPrivateKey(key) + // ... + + c.Init(prm) + +Connect to the FrostFS server: + + var prm client.PrmDial + prm.SetServerURI("localhost:8080") + prm.SetDefaultPrivateKey(key) + // ... + + err := c.Dial(prm) + // ... + +Execute FrostFS operation on the server: + + var prm client.PrmContainerPut + prm.SetContainer(cnr) + // ... + + res, err := c.ContainerPut(context.Background(), prm) + err := c.Dial(dialPrm) + if err == nil { + err = apistatus.ErrFromStatus(res.Status()) + } + // ... + +Consume custom service of the server: + + syntax = "proto3"; + + service CustomService { + rpc CustomRPC(CustomRPCRequest) returns (CustomRPCResponse); + } + + import "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client" + import "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/common" + + req := new(CustomRPCRequest) + // ... + resp := new(CustomRPCResponse) + + err := c.ExecRaw(func(c *client.Client) error { + return client.SendUnary(c, common.CallMethodInfo{ + Service: "CustomService", + Name: "CustomRPC", + }, req, resp) + }) + // ... + +Close the connection: + + err := c.Close() + // ... + +Note that it's not allowed to override Client behaviour directly: the parameters +for the all operations are write-only and the results of the all operations are +read-only. To be able to override client behavior (e.g. for tests), abstract it +with an interface: + + import "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + + type FrostFSClient interface { + // Operations according to the application needs + CreateContainer(context.Context, container.Container) error + // ... + } + + type client struct { + c *client.Client + } + + func (x *client) CreateContainer(context.Context, container.Container) error { + // ... + } +*/ +package client diff --git a/pkg/sdk/client/errors.go b/pkg/sdk/client/errors.go new file mode 100644 index 000000000..92dea3d33 --- /dev/null +++ b/pkg/sdk/client/errors.go @@ -0,0 +1,73 @@ +package client + +import ( + "fmt" + + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" +) + +// wrapsErrType returns true if any error in the error tree of err is of type E. +func wrapsErrType[E error](err error) bool { + switch e := err.(type) { + case E: + return true + case interface{ Unwrap() error }: + return wrapsErrType[E](e.Unwrap()) + case interface{ Unwrap() []error }: + for _, ei := range e.Unwrap() { + if wrapsErrType[E](ei) { + return true + } + } + return false + default: + return false + } +} + +// IsErrContainerNotFound checks if err corresponds to FrostFS status +// return corresponding to missing container. Supports wrapped errors. +func IsErrContainerNotFound(err error) bool { + return wrapsErrType[*apistatus.ContainerNotFound](err) +} + +// IsErrEACLNotFound checks if err corresponds to FrostFS status +// return corresponding to missing eACL table. Supports wrapped errors. +func IsErrEACLNotFound(err error) bool { + return wrapsErrType[*apistatus.EACLNotFound](err) +} + +// IsErrObjectNotFound checks if err corresponds to FrostFS status +// return corresponding to missing object. Supports wrapped errors. +func IsErrObjectNotFound(err error) bool { + return wrapsErrType[*apistatus.ObjectNotFound](err) +} + +// IsErrObjectAlreadyRemoved checks if err corresponds to FrostFS status +// return corresponding to already removed object. Supports wrapped errors. +func IsErrObjectAlreadyRemoved(err error) bool { + return wrapsErrType[*apistatus.ObjectAlreadyRemoved](err) +} + +// IsErrSessionExpired checks if err corresponds to FrostFS status return +// corresponding to expired session. Supports wrapped errors. +func IsErrSessionExpired(err error) bool { + return wrapsErrType[*apistatus.SessionTokenExpired](err) +} + +// IsErrSessionNotFound checks if err corresponds to FrostFS status return +// corresponding to missing session. Supports wrapped errors. +func IsErrSessionNotFound(err error) bool { + return wrapsErrType[*apistatus.SessionTokenNotFound](err) +} + +// returns error describing missing field with the given name. +func newErrMissingResponseField(name string) error { + return fmt.Errorf("missing %s field in the response", name) +} + +// returns error describing invalid field (according to the FrostFS protocol) +// with the given name and format violation err. +func newErrInvalidResponseField(name string, err error) error { + return fmt.Errorf("invalid %s field in the response: %w", name, err) +} diff --git a/pkg/sdk/client/errors_test.go b/pkg/sdk/client/errors_test.go new file mode 100644 index 000000000..d9b3a7cb3 --- /dev/null +++ b/pkg/sdk/client/errors_test.go @@ -0,0 +1,50 @@ +package client_test + +import ( + "fmt" + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + "github.com/stretchr/testify/require" +) + +func TestErrors(t *testing.T) { + errs := []struct { + check func(error) bool + err error + }{ + { + check: client.IsErrContainerNotFound, + err: new(apistatus.ContainerNotFound), + }, + { + check: client.IsErrEACLNotFound, + err: new(apistatus.EACLNotFound), + }, + { + check: client.IsErrObjectNotFound, + err: new(apistatus.ObjectNotFound), + }, + { + check: client.IsErrObjectAlreadyRemoved, + err: new(apistatus.ObjectAlreadyRemoved), + }, + { + check: client.IsErrSessionExpired, + err: new(apistatus.SessionTokenExpired), + }, + { + check: client.IsErrSessionNotFound, + err: new(apistatus.SessionTokenNotFound), + }, + } + + for i := range errs { + for j := range errs { + nestedErr := fmt.Errorf("top-level context: :%w", fmt.Errorf("inner context: %w", errs[j].err)) + require.Equal(t, i == j, errs[i].check(errs[j].err)) + require.Equal(t, i == j, errs[i].check(nestedErr)) + } + } +} diff --git a/pkg/sdk/client/netmap.go b/pkg/sdk/client/netmap.go new file mode 100644 index 000000000..57ddd1e02 --- /dev/null +++ b/pkg/sdk/client/netmap.go @@ -0,0 +1,263 @@ +package client + +import ( + "context" + "fmt" + + v2netmap "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/netmap" + rpcapi "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client" + v2session "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/signature" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/version" +) + +// PrmEndpointInfo groups parameters of EndpointInfo operation. +type PrmEndpointInfo struct { + XHeaders []string +} + +func (x *PrmEndpointInfo) buildRequest(c *Client) (*v2netmap.LocalNodeInfoRequest, error) { + meta := new(v2session.RequestMetaHeader) + writeXHeadersToMeta(x.XHeaders, meta) + + req := new(v2netmap.LocalNodeInfoRequest) + req.SetBody(new(v2netmap.LocalNodeInfoRequestBody)) + c.prepareRequest(req, meta) + return req, nil +} + +// ResEndpointInfo group resulting values of EndpointInfo operation. +type ResEndpointInfo struct { + statusRes + + version version.Version + + ni netmap.NodeInfo +} + +// LatestVersion returns latest FrostFS API protocol's version in use. +func (x ResEndpointInfo) LatestVersion() version.Version { + return x.version +} + +// NodeInfo returns information about the FrostFS node served on the remote endpoint. +func (x ResEndpointInfo) NodeInfo() netmap.NodeInfo { + return x.ni +} + +// EndpointInfo requests information about the storage node served on the remote endpoint. +// +// Method can be used as a health check to see if node is alive and responds to requests. +// +// Any client's internal or transport errors are returned as `error`. +// If PrmInit.DisableFrostFSFailuresResolution has been called, unsuccessful +// FrostFS status codes are included in the returned result structure, +// otherwise, are also returned as `error`. +// +// Returns an error if parameters are set incorrectly (see PrmEndpointInfo docs). +// Context is required and must not be nil. It is used for network communication. +// +// Exactly one return value is non-nil. Server status return is returned in ResEndpointInfo. +// Reflects all internal errors in second return value (transport problems, response processing, etc.). +// +// Return statuses: +// - global (see Client docs). +func (c *Client) EndpointInfo(ctx context.Context, prm PrmEndpointInfo) (*ResEndpointInfo, error) { + req, err := prm.buildRequest(c) + if err != nil { + return nil, err + } + + if err := signature.SignServiceMessage(&c.prm.Key, req); err != nil { + return nil, fmt.Errorf("sign request: %w", err) + } + + resp, err := rpcapi.LocalNodeInfo(&c.c, req, client.WithContext(ctx)) + if err != nil { + return nil, err + } + + var res ResEndpointInfo + res.st, err = c.processResponse(resp) + if err != nil || !apistatus.IsSuccessful(res.st) { + return &res, err + } + + body := resp.GetBody() + + const fieldVersion = "version" + + verV2 := body.GetVersion() + if verV2 == nil { + return nil, newErrMissingResponseField(fieldVersion) + } + if err := res.version.ReadFromV2(*verV2); err != nil { + return nil, newErrInvalidResponseField(fieldVersion, err) + } + + const fieldNodeInfo = "node info" + + nodeInfoV2 := body.GetNodeInfo() + if nodeInfoV2 == nil { + return nil, newErrMissingResponseField(fieldNodeInfo) + } + if err := res.ni.ReadFromV2(*nodeInfoV2); err != nil { + return nil, newErrInvalidResponseField(fieldNodeInfo, err) + } + return &res, nil +} + +// PrmNetworkInfo groups parameters of NetworkInfo operation. +type PrmNetworkInfo struct { + XHeaders []string +} + +func (x PrmNetworkInfo) buildRequest(c *Client) (*v2netmap.NetworkInfoRequest, error) { + meta := new(v2session.RequestMetaHeader) + writeXHeadersToMeta(x.XHeaders, meta) + + var req v2netmap.NetworkInfoRequest + req.SetBody(new(v2netmap.NetworkInfoRequestBody)) + c.prepareRequest(&req, meta) + return &req, nil +} + +// ResNetworkInfo groups resulting values of NetworkInfo operation. +type ResNetworkInfo struct { + statusRes + + info netmap.NetworkInfo +} + +// Info returns structured information about the FrostFS network. +func (x ResNetworkInfo) Info() netmap.NetworkInfo { + return x.info +} + +// NetworkInfo requests information about the FrostFS network of which the remote server is a part. +// +// Any client's internal or transport errors are returned as `error`. +// If PrmInit.DisableFrostFSFailuresResolution has been called, unsuccessful +// FrostFS status codes are included in the returned result structure, +// otherwise, are also returned as `error`. +// +// Returns an error if parameters are set incorrectly (see PrmNetworkInfo docs). +// Context is required and must not be nil. It is used for network communication. +// +// Exactly one return value is non-nil. Server status return is returned in ResNetworkInfo. +// Reflects all internal errors in second return value (transport problems, response processing, etc.). +// +// Return statuses: +// - global (see Client docs). +func (c *Client) NetworkInfo(ctx context.Context, prm PrmNetworkInfo) (*ResNetworkInfo, error) { + req, err := prm.buildRequest(c) + if err != nil { + return nil, err + } + + if err := signature.SignServiceMessage(&c.prm.Key, req); err != nil { + return nil, fmt.Errorf("sign request: %w", err) + } + + resp, err := rpcapi.NetworkInfo(&c.c, req, client.WithContext(ctx)) + if err != nil { + return nil, err + } + + var res ResNetworkInfo + res.st, err = c.processResponse(resp) + if err != nil || !apistatus.IsSuccessful(res.st) { + return &res, err + } + + const fieldNetInfo = "network info" + + netInfoV2 := resp.GetBody().GetNetworkInfo() + if netInfoV2 == nil { + return nil, newErrMissingResponseField(fieldNetInfo) + } + if err := res.info.ReadFromV2(*netInfoV2); err != nil { + return nil, newErrInvalidResponseField(fieldNetInfo, err) + } + return &res, nil +} + +// PrmNetMapSnapshot groups parameters of NetMapSnapshot operation. +type PrmNetMapSnapshot struct{} + +// ResNetMapSnapshot groups resulting values of NetMapSnapshot operation. +type ResNetMapSnapshot struct { + statusRes + + netMap netmap.NetMap +} + +// NetMap returns current server's local network map. +func (x ResNetMapSnapshot) NetMap() netmap.NetMap { + return x.netMap +} + +// NetMapSnapshot requests current network view of the remote server. +// +// Any client's internal or transport errors are returned as `error`. +// If PrmInit.DisableFrostFSFailuresResolution has been called, unsuccessful +// FrostFS status codes are included in the returned result structure, +// otherwise, are also returned as `error`. +// +// Returns an error if parameters are set incorrectly. +// Context is required and MUST NOT be nil. It is used for network communication. +// +// Exactly one return value is non-nil. Server status return is returned in ResNetMapSnapshot. +// Reflects all internal errors in second return value (transport problems, response processing, etc.). +// +// Return statuses: +// - global (see Client docs). +func (c *Client) NetMapSnapshot(ctx context.Context, _ PrmNetMapSnapshot) (*ResNetMapSnapshot, error) { + // form request body + var body v2netmap.SnapshotRequestBody + + // form meta header + var meta v2session.RequestMetaHeader + + // form request + var req v2netmap.SnapshotRequest + req.SetBody(&body) + c.prepareRequest(&req, &meta) + + err := signature.SignServiceMessage(&c.prm.Key, &req) + if err != nil { + return nil, fmt.Errorf("sign request: %w", err) + } + + resp, err := c.server.netMapSnapshot(ctx, req) + if err != nil { + return nil, err + } + + var res ResNetMapSnapshot + res.st, err = c.processResponse(resp) + if err != nil { + return nil, err + } + + if !apistatus.IsSuccessful(res.st) { + return &res, nil + } + + const fieldNetMap = "network map" + + netMapV2 := resp.GetBody().NetMap() + if netMapV2 == nil { + return nil, newErrMissingResponseField(fieldNetMap) + } + + err = res.netMap.ReadFromV2(*netMapV2) + if err != nil { + return nil, newErrInvalidResponseField(fieldNetMap, err) + } + + return &res, nil +} diff --git a/pkg/sdk/client/netmap_test.go b/pkg/sdk/client/netmap_test.go new file mode 100644 index 000000000..7b72946ea --- /dev/null +++ b/pkg/sdk/client/netmap_test.go @@ -0,0 +1,132 @@ +package client + +import ( + "context" + "errors" + "fmt" + "testing" + + v2netmap "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/signature" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" + "github.com/stretchr/testify/require" +) + +type serverNetMap struct { + errTransport error + + signResponse bool + + statusOK bool + + setNetMap bool + netMap v2netmap.NetMap +} + +func (x *serverNetMap) netMapSnapshot(ctx context.Context, req v2netmap.SnapshotRequest) (*v2netmap.SnapshotResponse, error) { + err := signature.VerifyServiceMessage(&req) + if err != nil { + return nil, err + } + + if x.errTransport != nil { + return nil, x.errTransport + } + + var body v2netmap.SnapshotResponseBody + + if x.setNetMap { + body.SetNetMap(&x.netMap) + } + + var meta session.ResponseMetaHeader + + if !x.statusOK { + meta.SetStatus(statusErr.ToStatusV2()) + } + + var resp v2netmap.SnapshotResponse + resp.SetBody(&body) + resp.SetMetaHeader(&meta) + + if x.signResponse { + err = signature.SignServiceMessage(key, &resp) + if err != nil { + panic(fmt.Sprintf("sign response: %v", err)) + } + } + + return &resp, nil +} + +func TestClient_NetMapSnapshot(t *testing.T) { + var err error + var prm PrmNetMapSnapshot + var res *ResNetMapSnapshot + var srv serverNetMap + c := newClient(&srv) + c.prm.DisableFrostFSFailuresResolution() + ctx := context.Background() + + // request signature + srv.errTransport = errors.New("any error") + + _, err = c.NetMapSnapshot(ctx, prm) + require.ErrorIs(t, err, srv.errTransport) + + srv.errTransport = nil + + // unsigned response + _, err = c.NetMapSnapshot(ctx, prm) + require.Error(t, err) + + srv.signResponse = true + + // status failure + res, err = c.NetMapSnapshot(ctx, prm) + require.NoError(t, err) + assertStatusErr(t, res) + + srv.statusOK = true + + // missing netmap field + _, err = c.NetMapSnapshot(ctx, prm) + require.Error(t, err) + + srv.setNetMap = true + + // invalid network map + var netMap netmap.NetMap + + var node netmap.NodeInfo + // TODO: #260 use instance corrupter + + var nodeV2 v2netmap.NodeInfo + + node.WriteToV2(&nodeV2) + require.Error(t, new(netmap.NodeInfo).ReadFromV2(nodeV2)) + + netMap.SetNodes([]netmap.NodeInfo{node}) + netMap.WriteToV2(&srv.netMap) + + _, err = c.NetMapSnapshot(ctx, prm) + require.Error(t, err) + + // correct network map + // TODO: #260 use instance normalizer + node.SetPublicKey([]byte{1, 2, 3}) + node.SetNetworkEndpoints("1", "2", "3") + + node.WriteToV2(&nodeV2) + require.NoError(t, new(netmap.NodeInfo).ReadFromV2(nodeV2)) + + netMap.SetNodes([]netmap.NodeInfo{node}) + netMap.WriteToV2(&srv.netMap) + + res, err = c.NetMapSnapshot(ctx, prm) + require.NoError(t, err) + require.True(t, apistatus.IsSuccessful(res.Status())) + require.Equal(t, netMap, res.NetMap()) +} diff --git a/pkg/sdk/client/object_delete.go b/pkg/sdk/client/object_delete.go new file mode 100644 index 000000000..7a2c059ed --- /dev/null +++ b/pkg/sdk/client/object_delete.go @@ -0,0 +1,172 @@ +package client + +import ( + "context" + "crypto/ecdsa" + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/acl" + v2object "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" + v2refs "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + rpcapi "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client" + v2session "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/signature" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/bearer" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/session" +) + +// PrmObjectDelete groups parameters of ObjectDelete operation. +type PrmObjectDelete struct { + XHeaders []string + + BearerToken *bearer.Token + + Session *session.Object + + ContainerID *cid.ID + + ObjectID *oid.ID + + Key *ecdsa.PrivateKey +} + +// UseKey specifies private key to sign the requests. +// If key is not provided, then Client default key is used. +// +// Deprecated: Use PrmObjectDelete.Key instead. +func (prm *PrmObjectDelete) UseKey(key ecdsa.PrivateKey) { + prm.Key = &key +} + +// ResObjectDelete groups resulting values of ObjectDelete operation. +type ResObjectDelete struct { + statusRes + + tomb oid.ID +} + +// Tombstone returns identifier of the created tombstone object. +func (x ResObjectDelete) Tombstone() oid.ID { + return x.tomb +} + +func (prm *PrmObjectDelete) buildRequest(c *Client) (*v2object.DeleteRequest, error) { + if prm.ContainerID == nil { + return nil, errorMissingContainer + } + + if prm.ObjectID == nil { + return nil, errorMissingObject + } + + if len(prm.XHeaders)%2 != 0 { + return nil, errorInvalidXHeaders + } + + meta := new(v2session.RequestMetaHeader) + writeXHeadersToMeta(prm.XHeaders, meta) + + if prm.BearerToken != nil { + v2BearerToken := new(acl.BearerToken) + prm.BearerToken.WriteToV2(v2BearerToken) + meta.SetBearerToken(v2BearerToken) + } + + if prm.Session != nil { + v2SessionToken := new(v2session.Token) + prm.Session.WriteToV2(v2SessionToken) + meta.SetSessionToken(v2SessionToken) + } + + addr := new(v2refs.Address) + + cnrV2 := new(v2refs.ContainerID) + prm.ContainerID.WriteToV2(cnrV2) + addr.SetContainerID(cnrV2) + + objV2 := new(v2refs.ObjectID) + prm.ObjectID.WriteToV2(objV2) + addr.SetObjectID(objV2) + + body := new(v2object.DeleteRequestBody) + body.SetAddress(addr) + + req := new(v2object.DeleteRequest) + req.SetBody(body) + c.prepareRequest(req, meta) + + return req, nil +} + +// ObjectDelete marks an object for deletion from the container using FrostFS API protocol. +// As a marker, a special unit called a tombstone is placed in the container. +// It confirms the user's intent to delete the object, and is itself a container object. +// Explicit deletion is done asynchronously, and is generally not guaranteed. +// +// Returns a list of checksums in raw form: the format of hashes and their number +// is left for the caller to check. Client preserves the order of the server's response. +// +// Exactly one return value is non-nil. By default, server status is returned in res structure. +// Any client's internal or transport errors are returned as `error`, +// If PrmInit.DisableFrostFSFailuresResolution has been called, unsuccessful +// FrostFS status codes are included in the returned result structure, +// otherwise, are also returned as `error`. +// +// Returns an error if parameters are set incorrectly (see PrmObjectDelete docs). +// Context is required and must not be nil. It is used for network communication. +// +// Return statuses: +// - global (see Client docs) +// - *apistatus.ContainerNotFound; +// - *apistatus.ObjectAccessDenied; +// - *apistatus.ObjectLocked; +// - *apistatus.SessionTokenExpired. +func (c *Client) ObjectDelete(ctx context.Context, prm PrmObjectDelete) (*ResObjectDelete, error) { + req, err := prm.buildRequest(c) + if err != nil { + return nil, err + } + + key := c.prm.Key + if prm.Key != nil { + key = *prm.Key + } + + err = signature.SignServiceMessage(&key, req) + if err != nil { + return nil, fmt.Errorf("sign request: %w", err) + } + + resp, err := rpcapi.DeleteObject(&c.c, req, client.WithContext(ctx)) + if err != nil { + return nil, err + } + + var res ResObjectDelete + res.st, err = c.processResponse(resp) + if err != nil { + return nil, err + } + + if !apistatus.IsSuccessful(res.st) { + return &res, nil + } + + const fieldTombstone = "tombstone" + + idTombV2 := resp.GetBody().GetTombstone().GetObjectID() + if idTombV2 == nil { + return nil, newErrMissingResponseField(fieldTombstone) + } + + err = res.tomb.ReadFromV2(*idTombV2) + if err != nil { + return nil, newErrInvalidResponseField(fieldTombstone, err) + } + + return &res, nil +} diff --git a/pkg/sdk/client/object_get.go b/pkg/sdk/client/object_get.go new file mode 100644 index 000000000..10364aea5 --- /dev/null +++ b/pkg/sdk/client/object_get.go @@ -0,0 +1,802 @@ +package client + +import ( + "context" + "crypto/ecdsa" + "errors" + "fmt" + "io" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/acl" + v2object "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" + v2refs "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + rpcapi "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client" + v2session "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/signature" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/bearer" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/session" +) + +// PrmObjectGet groups parameters of ObjectGetInit operation. +type PrmObjectGet struct { + XHeaders []string + + BearerToken *bearer.Token + + Session *session.Object + + Raw bool + + Local bool + + ContainerID *cid.ID + + ObjectID *oid.ID + + Key *ecdsa.PrivateKey +} + +func (prm *PrmObjectGet) buildRequest(c *Client) (*v2object.GetRequest, error) { + if prm.ContainerID == nil { + return nil, errorMissingContainer + } + + if prm.ObjectID == nil { + return nil, errorMissingObject + } + + if len(prm.XHeaders)%2 != 0 { + return nil, errorInvalidXHeaders + } + + meta := new(v2session.RequestMetaHeader) + writeXHeadersToMeta(prm.XHeaders, meta) + + if prm.BearerToken != nil { + v2BearerToken := new(acl.BearerToken) + prm.BearerToken.WriteToV2(v2BearerToken) + meta.SetBearerToken(v2BearerToken) + } + + if prm.Session != nil { + v2SessionToken := new(v2session.Token) + prm.Session.WriteToV2(v2SessionToken) + meta.SetSessionToken(v2SessionToken) + } + + if prm.Local { + meta.SetTTL(1) + } + + addr := new(v2refs.Address) + + cnrV2 := new(v2refs.ContainerID) + prm.ContainerID.WriteToV2(cnrV2) + addr.SetContainerID(cnrV2) + + objV2 := new(v2refs.ObjectID) + prm.ObjectID.WriteToV2(objV2) + addr.SetObjectID(objV2) + + body := new(v2object.GetRequestBody) + body.SetRaw(prm.Raw) + body.SetAddress(addr) + + req := new(v2object.GetRequest) + req.SetBody(body) + c.prepareRequest(req, meta) + + return req, nil +} + +// ResObjectGet groups the final result values of ObjectGetInit operation. +type ResObjectGet struct { + statusRes +} + +// ObjectReader is designed to read one object from FrostFS system. +// +// Must be initialized using Client.ObjectGetInit, any other +// usage is unsafe. +type ObjectReader struct { + cancelCtxStream context.CancelFunc + + client *Client + stream interface { + Read(resp *v2object.GetResponse) error + } + + res ResObjectGet + err error + + tailPayload []byte + + remainingPayloadLen int +} + +// UseKey specifies private key to sign the requests. +// If key is not provided, then Client default key is used. +// +// Deprecated: Use PrmObjectGet.Key instead. +func (prm *PrmObjectGet) UseKey(key ecdsa.PrivateKey) { + prm.Key = &key +} + +// ReadHeader reads header of the object. Result means success. +// Failure reason can be received via Close. +func (x *ObjectReader) ReadHeader(dst *object.Object) bool { + var resp v2object.GetResponse + x.err = x.stream.Read(&resp) + if x.err != nil { + return false + } + + x.res.st, x.err = x.client.processResponse(&resp) + if x.err != nil || !apistatus.IsSuccessful(x.res.st) { + return false + } + + var partInit *v2object.GetObjectPartInit + + switch v := resp.GetBody().GetObjectPart().(type) { + default: + x.err = fmt.Errorf("unexpected message instead of heading part: %T", v) + return false + case *v2object.SplitInfo: + x.err = object.NewSplitInfoError(object.NewSplitInfoFromV2(v)) + return false + case *v2object.GetObjectPartInit: + partInit = v + } + + var objv2 v2object.Object + + objv2.SetObjectID(partInit.GetObjectID()) + objv2.SetHeader(partInit.GetHeader()) + objv2.SetSignature(partInit.GetSignature()) + + x.remainingPayloadLen = int(objv2.GetHeader().GetPayloadLength()) + + *dst = *object.NewFromV2(&objv2) // need smth better + + return true +} + +func (x *ObjectReader) readChunk(buf []byte) (int, bool) { + var read int + + // read remaining tail + read = copy(buf, x.tailPayload) + + x.tailPayload = x.tailPayload[read:] + + if len(buf) == read { + return read, true + } + + var chunk []byte + var lastRead int + + for { + var resp v2object.GetResponse + x.err = x.stream.Read(&resp) + if x.err != nil { + return read, false + } + + x.res.st, x.err = x.client.processResponse(&resp) + if x.err != nil || !apistatus.IsSuccessful(x.res.st) { + return read, false + } + + part := resp.GetBody().GetObjectPart() + partChunk, ok := part.(*v2object.GetObjectPartChunk) + if !ok { + x.err = fmt.Errorf("unexpected message instead of chunk part: %T", part) + return read, false + } + + // read new chunk + chunk = partChunk.GetChunk() + if len(chunk) == 0 { + // just skip empty chunks since they are not prohibited by protocol + continue + } + + lastRead = copy(buf[read:], chunk) + + read += lastRead + + if read == len(buf) { + // save the tail + x.tailPayload = append(x.tailPayload, chunk[lastRead:]...) + + return read, true + } + } +} + +// ReadChunk reads another chunk of the object payload. Works similar to +// io.Reader.Read but returns success flag instead of error. +// +// Failure reason can be received via Close. +func (x *ObjectReader) ReadChunk(buf []byte) (int, bool) { + return x.readChunk(buf) +} + +func (x *ObjectReader) close(ignoreEOF bool) (*ResObjectGet, error) { + defer x.cancelCtxStream() + + if x.err != nil { + if !errors.Is(x.err, io.EOF) { + return nil, x.err + } else if !ignoreEOF { + if x.remainingPayloadLen > 0 { + return nil, io.ErrUnexpectedEOF + } + + return nil, io.EOF + } + } + + return &x.res, nil +} + +// Close ends reading the object and returns the result of the operation +// along with the final results. Must be called after using the ObjectReader. +// +// Exactly one return value is non-nil. By default, server status is returned in res structure. +// Any client's internal or transport errors are returned as Go built-in error. +// If Client is tuned to resolve FrostFS API statuses, then FrostFS failures +// codes are returned as error. +// +// Return errors: +// +// *object.SplitInfoError (returned on virtual objects with PrmObjectGet.MakeRaw). +// +// Return statuses: +// - global (see Client docs); +// - *apistatus.ContainerNotFound; +// - *apistatus.ObjectNotFound; +// - *apistatus.ObjectAccessDenied; +// - *apistatus.ObjectAlreadyRemoved; +// - *apistatus.SessionTokenExpired. +func (x *ObjectReader) Close() (*ResObjectGet, error) { + return x.close(true) +} + +// Read implements io.Reader of the object payload. +func (x *ObjectReader) Read(p []byte) (int, error) { + n, ok := x.readChunk(p) + + x.remainingPayloadLen -= n + + if !ok { + res, err := x.close(false) + if err != nil { + return n, err + } + + return n, apistatus.ErrFromStatus(res.Status()) + } + + if x.remainingPayloadLen < 0 { + return n, errors.New("payload size overflow") + } + + return n, nil +} + +// ObjectGetInit initiates reading an object through a remote server using FrostFS API protocol. +// +// The call only opens the transmission channel, explicit fetching is done using the ObjectReader. +// Exactly one return value is non-nil. Resulting reader must be finally closed. +// +// Returns an error if parameters are set incorrectly (see PrmObjectGet docs). +// Context is required and must not be nil. It is used for network communication. +func (c *Client) ObjectGetInit(ctx context.Context, prm PrmObjectGet) (*ObjectReader, error) { + req, err := prm.buildRequest(c) + if err != nil { + return nil, err + } + + key := prm.Key + if key == nil { + key = &c.prm.Key + } + + err = signature.SignServiceMessage(key, req) + if err != nil { + return nil, fmt.Errorf("sign request: %w", err) + } + + ctx, cancel := context.WithCancel(ctx) + + stream, err := rpcapi.GetObject(&c.c, req, client.WithContext(ctx)) + if err != nil { + cancel() + return nil, fmt.Errorf("open stream: %w", err) + } + + var r ObjectReader + r.cancelCtxStream = cancel + r.stream = stream + r.client = c + + return &r, nil +} + +// PrmObjectHead groups parameters of ObjectHead operation. +type PrmObjectHead struct { + XHeaders []string + + BearerToken *bearer.Token + + Session *session.Object + + Raw bool + + Local bool + + ContainerID *cid.ID + + ObjectID *oid.ID + + Key *ecdsa.PrivateKey +} + +// UseKey specifies private key to sign the requests. +// If key is not provided, then Client default key is used. +// +// Deprecated: Use PrmObjectHead.Key instead. +func (prm *PrmObjectHead) UseKey(key ecdsa.PrivateKey) { + prm.Key = &key +} + +// ResObjectHead groups resulting values of ObjectHead operation. +type ResObjectHead struct { + statusRes + + // requested object (response doesn't carry the ID) + idObj oid.ID + + hdr *v2object.HeaderWithSignature +} + +// ReadHeader reads header of the requested object. +// Returns false if header is missing in the response (not read). +func (x *ResObjectHead) ReadHeader(dst *object.Object) bool { + if x.hdr == nil { + return false + } + + var objv2 v2object.Object + + objv2.SetHeader(x.hdr.GetHeader()) + objv2.SetSignature(x.hdr.GetSignature()) + + obj := object.NewFromV2(&objv2) + obj.SetID(x.idObj) + + *dst = *obj + + return true +} + +func (prm *PrmObjectHead) buildRequest(c *Client) (*v2object.HeadRequest, error) { + if prm.ContainerID == nil { + return nil, errorMissingContainer + } + + if prm.ObjectID == nil { + return nil, errorMissingObject + } + + if len(prm.XHeaders)%2 != 0 { + return nil, errorInvalidXHeaders + } + + meta := new(v2session.RequestMetaHeader) + writeXHeadersToMeta(prm.XHeaders, meta) + + if prm.BearerToken != nil { + v2BearerToken := new(acl.BearerToken) + prm.BearerToken.WriteToV2(v2BearerToken) + meta.SetBearerToken(v2BearerToken) + } + + if prm.Session != nil { + v2SessionToken := new(v2session.Token) + prm.Session.WriteToV2(v2SessionToken) + meta.SetSessionToken(v2SessionToken) + } + + if prm.Local { + meta.SetTTL(1) + } + + addr := new(v2refs.Address) + + cnrV2 := new(v2refs.ContainerID) + prm.ContainerID.WriteToV2(cnrV2) + addr.SetContainerID(cnrV2) + + objV2 := new(v2refs.ObjectID) + prm.ObjectID.WriteToV2(objV2) + addr.SetObjectID(objV2) + body := new(v2object.HeadRequestBody) + body.SetRaw(prm.Raw) + body.SetAddress(addr) + + req := new(v2object.HeadRequest) + req.SetBody(body) + c.prepareRequest(req, meta) + + return req, nil +} + +// ObjectHead reads object header through a remote server using FrostFS API protocol. +// +// Exactly one return value is non-nil. By default, server status is returned in res structure. +// Any client's internal or transport errors are returned as `error`, +// If PrmInit.DisableFrostFSFailuresResolution has been called, unsuccessful +// FrostFS status codes are included in the returned result structure, +// otherwise, are also returned as `error`. +// +// Returns an error if parameters are set incorrectly (see PrmObjectHead docs). +// Context is required and must not be nil. It is used for network communication. +// +// Return errors: +// +// *object.SplitInfoError (returned on virtual objects with PrmObjectHead.MakeRaw). +// +// Return statuses: +// - global (see Client docs); +// - *apistatus.ContainerNotFound; +// - *apistatus.ObjectNotFound; +// - *apistatus.ObjectAccessDenied; +// - *apistatus.ObjectAlreadyRemoved; +// - *apistatus.SessionTokenExpired. +func (c *Client) ObjectHead(ctx context.Context, prm PrmObjectHead) (*ResObjectHead, error) { + req, err := prm.buildRequest(c) + if err != nil { + return nil, err + } + + key := c.prm.Key + if prm.Key != nil { + key = *prm.Key + } + + // sign the request + + err = signature.SignServiceMessage(&key, req) + if err != nil { + return nil, fmt.Errorf("sign request: %w", err) + } + + resp, err := rpcapi.HeadObject(&c.c, req, client.WithContext(ctx)) + if err != nil { + return nil, fmt.Errorf("write request: %w", err) + } + + var res ResObjectHead + res.st, err = c.processResponse(resp) + if err != nil { + return nil, err + } + + if !apistatus.IsSuccessful(res.st) { + return &res, nil + } + + res.idObj = *prm.ObjectID + + switch v := resp.GetBody().GetHeaderPart().(type) { + default: + return nil, fmt.Errorf("unexpected header type %T", v) + case *v2object.SplitInfo: + return nil, object.NewSplitInfoError(object.NewSplitInfoFromV2(v)) + case *v2object.HeaderWithSignature: + res.hdr = v + } + + return &res, nil +} + +// PrmObjectRange groups parameters of ObjectRange operation. +type PrmObjectRange struct { + XHeaders []string + + BearerToken *bearer.Token + + Session *session.Object + + Raw bool + + Local bool + + ContainerID *cid.ID + + ObjectID *oid.ID + + Key *ecdsa.PrivateKey + + Offset uint64 + + Length uint64 +} + +func (prm *PrmObjectRange) buildRequest(c *Client) (*v2object.GetRangeRequest, error) { + if prm.Length == 0 { + return nil, errorZeroRangeLength + } + + if prm.ContainerID == nil { + return nil, errorMissingContainer + } + + if prm.ObjectID == nil { + return nil, errorMissingObject + } + + if len(prm.XHeaders)%2 != 0 { + return nil, errorInvalidXHeaders + } + + meta := new(v2session.RequestMetaHeader) + writeXHeadersToMeta(prm.XHeaders, meta) + + if prm.BearerToken != nil { + v2BearerToken := new(acl.BearerToken) + prm.BearerToken.WriteToV2(v2BearerToken) + meta.SetBearerToken(v2BearerToken) + } + + if prm.Session != nil { + v2SessionToken := new(v2session.Token) + prm.Session.WriteToV2(v2SessionToken) + meta.SetSessionToken(v2SessionToken) + } + + if prm.Local { + meta.SetTTL(1) + } + + addr := new(v2refs.Address) + + cnrV2 := new(v2refs.ContainerID) + prm.ContainerID.WriteToV2(cnrV2) + addr.SetContainerID(cnrV2) + + objV2 := new(v2refs.ObjectID) + prm.ObjectID.WriteToV2(objV2) + addr.SetObjectID(objV2) + + rng := new(v2object.Range) + rng.SetLength(prm.Length) + rng.SetOffset(prm.Offset) + + body := new(v2object.GetRangeRequestBody) + body.SetRaw(prm.Raw) + body.SetAddress(addr) + body.SetRange(rng) + + req := new(v2object.GetRangeRequest) + req.SetBody(body) + c.prepareRequest(req, meta) + + return req, nil +} + +// UseKey specifies private key to sign the requests. +// If key is not provided, then Client default key is used. +// +// Deprecated: Use PrmObjectRange.Key instead. +func (prm *PrmObjectRange) UseKey(key ecdsa.PrivateKey) { + prm.Key = &key +} + +// ResObjectRange groups the final result values of ObjectRange operation. +type ResObjectRange struct { + statusRes +} + +// ObjectRangeReader is designed to read payload range of one object +// from FrostFS system. +// +// Must be initialized using Client.ObjectRangeInit, any other +// usage is unsafe. +type ObjectRangeReader struct { + cancelCtxStream context.CancelFunc + + client *Client + + res ResObjectRange + err error + + stream interface { + Read(resp *v2object.GetRangeResponse) error + } + + tailPayload []byte + + remainingPayloadLen int +} + +func (x *ObjectRangeReader) readChunk(buf []byte) (int, bool) { + var read int + + // read remaining tail + read = copy(buf, x.tailPayload) + + x.tailPayload = x.tailPayload[read:] + + if len(buf) == read { + return read, true + } + + var partChunk *v2object.GetRangePartChunk + var chunk []byte + var lastRead int + + for { + var resp v2object.GetRangeResponse + x.err = x.stream.Read(&resp) + if x.err != nil { + return read, false + } + + x.res.st, x.err = x.client.processResponse(&resp) + if x.err != nil || !apistatus.IsSuccessful(x.res.st) { + return read, false + } + + // get chunk message + switch v := resp.GetBody().GetRangePart().(type) { + default: + x.err = fmt.Errorf("unexpected message received: %T", v) + return read, false + case *v2object.SplitInfo: + x.err = object.NewSplitInfoError(object.NewSplitInfoFromV2(v)) + return read, false + case *v2object.GetRangePartChunk: + partChunk = v + } + + chunk = partChunk.GetChunk() + if len(chunk) == 0 { + // just skip empty chunks since they are not prohibited by protocol + continue + } + + lastRead = copy(buf[read:], chunk) + + read += lastRead + + if read == len(buf) { + // save the tail + x.tailPayload = append(x.tailPayload, chunk[lastRead:]...) + + return read, true + } + } +} + +// ReadChunk reads another chunk of the object payload range. +// Works similar to io.Reader.Read but returns success flag instead of error. +// +// Failure reason can be received via Close. +func (x *ObjectRangeReader) ReadChunk(buf []byte) (int, bool) { + return x.readChunk(buf) +} + +func (x *ObjectRangeReader) close(ignoreEOF bool) (*ResObjectRange, error) { + defer x.cancelCtxStream() + + if x.err != nil { + if !errors.Is(x.err, io.EOF) { + return nil, x.err + } else if !ignoreEOF { + if x.remainingPayloadLen > 0 { + return nil, io.ErrUnexpectedEOF + } + + return nil, io.EOF + } + } + + return &x.res, nil +} + +// Close ends reading the payload range and returns the result of the operation +// along with the final results. Must be called after using the ObjectRangeReader. +// +// Exactly one return value is non-nil. By default, server status is returned in res structure. +// Any client's internal or transport errors are returned as Go built-in error. +// If Client is tuned to resolve FrostFS API statuses, then FrostFS failures +// codes are returned as error. +// +// Return errors: +// +// *object.SplitInfoError (returned on virtual objects with PrmObjectRange.MakeRaw). +// +// Return statuses: +// - global (see Client docs); +// - *apistatus.ContainerNotFound; +// - *apistatus.ObjectNotFound; +// - *apistatus.ObjectAccessDenied; +// - *apistatus.ObjectAlreadyRemoved; +// - *apistatus.ObjectOutOfRange; +// - *apistatus.SessionTokenExpired. +func (x *ObjectRangeReader) Close() (*ResObjectRange, error) { + return x.close(true) +} + +// Read implements io.Reader of the object payload. +func (x *ObjectRangeReader) Read(p []byte) (int, error) { + n, ok := x.readChunk(p) + + x.remainingPayloadLen -= n + + if !ok { + res, err := x.close(false) + if err != nil { + return n, err + } + + return n, apistatus.ErrFromStatus(res.Status()) + } + + if x.remainingPayloadLen < 0 { + return n, errors.New("payload range size overflow") + } + + return n, nil +} + +// ObjectRangeInit initiates reading an object's payload range through a remote +// server using FrostFS API protocol. +// +// The call only opens the transmission channel, explicit fetching is done using the ObjectRangeReader. +// Exactly one return value is non-nil. Resulting reader must be finally closed. +// +// Returns an error if parameters are set incorrectly (see PrmObjectRange docs). +// Context is required and must not be nil. It is used for network communication. +func (c *Client) ObjectRangeInit(ctx context.Context, prm PrmObjectRange) (*ObjectRangeReader, error) { + req, err := prm.buildRequest(c) + if err != nil { + return nil, err + } + + key := prm.Key + if key == nil { + key = &c.prm.Key + } + + err = signature.SignServiceMessage(key, req) + if err != nil { + return nil, fmt.Errorf("sign request: %w", err) + } + + ctx, cancel := context.WithCancel(ctx) + + stream, err := rpcapi.GetObjectRange(&c.c, req, client.WithContext(ctx)) + if err != nil { + cancel() + return nil, fmt.Errorf("open stream: %w", err) + } + + var r ObjectRangeReader + r.remainingPayloadLen = int(prm.Length) + r.cancelCtxStream = cancel + r.stream = stream + r.client = c + + return &r, nil +} diff --git a/pkg/sdk/client/object_hash.go b/pkg/sdk/client/object_hash.go new file mode 100644 index 000000000..bc276df76 --- /dev/null +++ b/pkg/sdk/client/object_hash.go @@ -0,0 +1,206 @@ +package client + +import ( + "context" + "crypto/ecdsa" + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/acl" + v2object "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" + v2refs "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + rpcapi "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client" + v2session "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/signature" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/bearer" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/checksum" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/session" +) + +// PrmObjectHash groups parameters of ObjectHash operation. +type PrmObjectHash struct { + XHeaders []string + + BearerToken *bearer.Token + + Session *session.Object + + Local bool + + Ranges []object.Range + + Salt []byte + + ChecksumType checksum.Type + + ContainerID *cid.ID + + ObjectID *oid.ID + + Key *ecdsa.PrivateKey +} + +// UseKey specifies private key to sign the requests. +// If key is not provided, then Client default key is used. +// +// Deprecated: Use PrmObjectHash.Key instead. +func (prm *PrmObjectHash) UseKey(key ecdsa.PrivateKey) { + prm.Key = &key +} + +// TillichZemorAlgo changes the hash function to Tillich-Zemor +// (https://link.springer.com/content/pdf/10.1007/3-540-48658-5_5.pdf). +// +// By default, SHA256 hash function is used/. +// +// Deprecated: Use PrmObjectHash.ChecksumType instead. +func (prm *PrmObjectHash) TillichZemorAlgo() { + prm.ChecksumType = checksum.TZ +} + +// ResObjectHash groups resulting values of ObjectHash operation. +type ResObjectHash struct { + statusRes + + checksums [][]byte +} + +// Checksums returns a list of calculated checksums in range order. +func (x ResObjectHash) Checksums() [][]byte { + return x.checksums +} + +func (prm *PrmObjectHash) buildRequest(c *Client) (*v2object.GetRangeHashRequest, error) { + if prm.ContainerID == nil { + return nil, errorMissingContainer + } + + if prm.ObjectID == nil { + return nil, errorMissingObject + } + + if len(prm.XHeaders)%2 != 0 { + return nil, errorInvalidXHeaders + } + + if len(prm.Ranges) == 0 { + return nil, errorMissingRanges + } + + meta := new(v2session.RequestMetaHeader) + writeXHeadersToMeta(prm.XHeaders, meta) + + if prm.BearerToken != nil { + v2BearerToken := new(acl.BearerToken) + prm.BearerToken.WriteToV2(v2BearerToken) + meta.SetBearerToken(v2BearerToken) + } + + if prm.Session != nil { + v2SessionToken := new(v2session.Token) + prm.Session.WriteToV2(v2SessionToken) + meta.SetSessionToken(v2SessionToken) + } + + if prm.Local { + meta.SetTTL(1) + } + + addr := new(v2refs.Address) + + cnrV2 := new(v2refs.ContainerID) + prm.ContainerID.WriteToV2(cnrV2) + addr.SetContainerID(cnrV2) + + objV2 := new(v2refs.ObjectID) + prm.ObjectID.WriteToV2(objV2) + addr.SetObjectID(objV2) + + rs := make([]v2object.Range, len(prm.Ranges)) + for i := range prm.Ranges { + rs[i].SetOffset(prm.Ranges[i].GetOffset()) + rs[i].SetLength(prm.Ranges[i].GetLength()) + } + + body := new(v2object.GetRangeHashRequestBody) + body.SetAddress(addr) + body.SetRanges(rs) + body.SetSalt(prm.Salt) + + if prm.ChecksumType == checksum.Unknown { + body.SetType(v2refs.SHA256) + } else { + body.SetType(v2refs.ChecksumType(prm.ChecksumType)) + } + + req := new(v2object.GetRangeHashRequest) + req.SetBody(body) + c.prepareRequest(req, meta) + + return req, nil +} + +// ObjectHash requests checksum of the range list of the object payload using +// FrostFS API protocol. +// +// Returns a list of checksums in raw form: the format of hashes and their number +// is left for the caller to check. Client preserves the order of the server's response. +// +// Exactly one return value is non-nil. By default, server status is returned in res structure. +// Any client's internal or transport errors are returned as `error`, +// If PrmInit.DisableFrostFSFailuresResolution has been called, unsuccessful +// FrostFS status codes are included in the returned result structure, +// otherwise, are also returned as `error`. +// +// Returns an error if parameters are set incorrectly (see PrmObjectHash docs). +// Context is required and must not be nil. It is used for network communication. +// +// Return statuses: +// - global (see Client docs); +// - *apistatus.ContainerNotFound; +// - *apistatus.ObjectNotFound; +// - *apistatus.ObjectAccessDenied; +// - *apistatus.ObjectOutOfRange; +// - *apistatus.SessionTokenExpired. +func (c *Client) ObjectHash(ctx context.Context, prm PrmObjectHash) (*ResObjectHash, error) { + req, err := prm.buildRequest(c) + if err != nil { + return nil, err + } + + key := c.prm.Key + if prm.Key != nil { + key = *prm.Key + } + + err = signature.SignServiceMessage(&key, req) + if err != nil { + return nil, fmt.Errorf("sign request: %w", err) + } + + resp, err := rpcapi.HashObjectRange(&c.c, req, client.WithContext(ctx)) + if err != nil { + return nil, fmt.Errorf("write request: %w", err) + } + + var res ResObjectHash + res.st, err = c.processResponse(resp) + if err != nil { + return nil, err + } + + if !apistatus.IsSuccessful(res.st) { + return &res, nil + } + + res.checksums = resp.GetBody().GetHashList() + if len(res.checksums) == 0 { + return nil, newErrMissingResponseField("hash list") + } + + return &res, nil +} diff --git a/pkg/sdk/client/object_put.go b/pkg/sdk/client/object_put.go new file mode 100644 index 000000000..0cc0fa0ff --- /dev/null +++ b/pkg/sdk/client/object_put.go @@ -0,0 +1,187 @@ +package client + +import ( + "context" + "crypto/ecdsa" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/bearer" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/transformer" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/session" +) + +// defaultGRPCPayloadChunkLen default value for maxChunkLen. +// See PrmObjectPutInit.SetGRPCPayloadChunkLen for details. +const defaultGRPCPayloadChunkLen = 3 << 20 + +// PrmObjectPutInit groups parameters of ObjectPutInit operation. +type PrmObjectPutInit struct { + XHeaders []string + + BearerToken *bearer.Token + + Session *session.Object + + Local bool + + CopiesNumber []uint32 + + MaxChunkLength int + + MaxSize uint64 + + EpochSource transformer.EpochSource + + WithoutHomomorphHash bool + + Key *ecdsa.PrivateKey +} + +// SetCopiesNumber sets number of object copies that is enough to consider put successful. +// +// Deprecated: Use PrmObjectPutInit.CopiesNumber instead. +func (x *PrmObjectPutInit) SetCopiesNumber(copiesNumber uint32) { + x.CopiesNumber = []uint32{copiesNumber} +} + +// SetCopiesNumberByVectors sets ordered list of minimal required object copies numbers +// per placement vector. List's length MUST equal container's placement vector number, +// otherwise request will fail. +// +// Deprecated: Use PrmObjectPutInit.CopiesNumber instead. +func (x *PrmObjectPutInit) SetCopiesNumberByVectors(copiesNumbers []uint32) { + x.CopiesNumber = copiesNumbers +} + +// SetGRPCPayloadChunkLen sets maximum chunk length value for gRPC Put request. +// Maximum chunk length restricts maximum byte length of the chunk +// transmitted in a single stream message. It depends on +// server settings and other message fields. +// If not specified or negative value set, default value of 3MiB will be used. +// +// Deprecated: Use PrmObjectPutInit.MaxChunkLength instead. +func (x *PrmObjectPutInit) SetGRPCPayloadChunkLen(v int) { + x.MaxChunkLength = v +} + +// ResObjectPut groups the final result values of ObjectPutInit operation. +type ResObjectPut struct { + statusRes + + obj oid.ID +} + +// StoredObjectID returns identifier of the saved object. +func (x ResObjectPut) StoredObjectID() oid.ID { + return x.obj +} + +// ObjectWriter is designed to write one object or +// multiple parts of one object to FrostFS system. +// +// Must be initialized using Client.ObjectPutInit, any other +// usage is unsafe. +type ObjectWriter interface { + // WriteHeader writes header of the object. Result means success. + // Failure reason can be received via Close. + WriteHeader(context.Context, object.Object) bool + // WritePayloadChunk writes chunk of the object payload. Result means success. + // Failure reason can be received via Close. + WritePayloadChunk(context.Context, []byte) bool + // Close ends writing the object and returns the result of the operation + // along with the final results. Must be called after using the ObjectWriter. + // + // Exactly one return value is non-nil. By default, server status is returned in res structure. + // Any client's internal or transport errors are returned as Go built-in error. + // If Client is tuned to resolve FrostFS API statuses, then FrostFS failures + // codes are returned as error. + // + // Return statuses: + // - global (see Client docs); + // - *apistatus.ContainerNotFound; + // - *apistatus.ObjectAccessDenied; + // - *apistatus.ObjectLocked; + // - *apistatus.LockNonRegularObject; + // - *apistatus.SessionTokenNotFound; + // - *apistatus.SessionTokenExpired. + Close(context.Context) (*ResObjectPut, error) +} + +// UseKey specifies private key to sign the requests. +// If key is not provided, then Client default key is used. +// +// Deprecated: Use PrmObjectPutInit.Key instead. +func (x *PrmObjectPutInit) UseKey(key ecdsa.PrivateKey) { + x.Key = &key +} + +// WithBearerToken attaches bearer token to be used for the operation. +// Should be called once before any writing steps. +// +// Deprecated: Use PrmObjectPutInit.BearerToken instead. +func (x *PrmObjectPutInit) WithBearerToken(t bearer.Token) { + x.BearerToken = &t +} + +// WithinSession specifies session within which object should be stored. +// Should be called once before any writing steps. +// +// Deprecated: Use PrmObjectPutInit.Session instead. +func (x *PrmObjectPutInit) WithinSession(t session.Object) { + x.Session = &t +} + +// MarkLocal tells the server to execute the operation locally. +// +// Deprecated: Use PrmObjectPutInit.Local instead. +func (x *PrmObjectPutInit) MarkLocal() { + x.Local = true +} + +// WithXHeaders specifies list of extended headers (string key-value pairs) +// to be attached to the request. Must have an even length. +// +// Slice must not be mutated until the operation completes. +// +// Deprecated: Use PrmObjectPutInit.XHeaders instead. +func (x *PrmObjectPutInit) WithXHeaders(hs ...string) { + x.XHeaders = hs +} + +// WithObjectMaxSize specifies max object size value and use it during object splitting. +// When specified, start writing to the stream only after the object is formed. +// Continue processing the input only when the previous formed object has been successfully written. +// +// Deprecated: Use PrmObjectPutInit.MaxSize instead. +func (x *PrmObjectPutInit) WithObjectMaxSize(maxSize uint64) { + x.MaxSize = maxSize +} + +// WithoutHomomorphicHash if set to true do not use Tillich-Zémor hash for payload. +// +// Deprecated: Use PrmObjectPutInit.WithoutHomomorphHash instead. +func (x *PrmObjectPutInit) WithoutHomomorphicHash(v bool) { + x.WithoutHomomorphHash = v +} + +// WithEpochSource specifies epoch for object when split it on client side. +// +// Deprecated: Use PrmObjectPutInit.EpochSource instead. +func (x *PrmObjectPutInit) WithEpochSource(es transformer.EpochSource) { + x.EpochSource = es +} + +// ObjectPutInit initiates writing an object through a remote server using FrostFS API protocol. +// +// The call only opens the transmission channel, explicit recording is done using the ObjectWriter. +// Exactly one return value is non-nil. Resulting writer must be finally closed. +// +// Returns an error if parameters are set incorrectly. +// Context is required and must not be nil. It is used for network communication. +func (c *Client) ObjectPutInit(ctx context.Context, prm PrmObjectPutInit) (ObjectWriter, error) { + if prm.MaxSize > 0 { + return c.objectPutInitTransformer(prm) + } + return c.objectPutInitRaw(ctx, prm) +} diff --git a/pkg/sdk/client/object_put_raw.go b/pkg/sdk/client/object_put_raw.go new file mode 100644 index 000000000..bc1e2610f --- /dev/null +++ b/pkg/sdk/client/object_put_raw.go @@ -0,0 +1,180 @@ +package client + +import ( + "context" + "crypto/ecdsa" + "errors" + "fmt" + "io" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/acl" + v2object "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" + rpcapi "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client" + v2session "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/signature" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" +) + +func (c *Client) objectPutInitRaw(ctx context.Context, prm PrmObjectPutInit) (*objectWriterRaw, error) { + if len(prm.XHeaders)%2 != 0 { + return nil, errorInvalidXHeaders + } + + var w objectWriterRaw + stream, err := rpcapi.PutObject(&c.c, &w.respV2, client.WithContext(ctx)) + if err != nil { + return nil, fmt.Errorf("open stream: %w", err) + } + + w.key = &c.prm.Key + if prm.Key != nil { + w.key = prm.Key + } + w.client = c + w.stream = stream + w.partInit.SetCopiesNumber(prm.CopiesNumber) + w.req.SetBody(new(v2object.PutRequestBody)) + if prm.MaxChunkLength > 0 { + w.maxChunkLen = prm.MaxChunkLength + } else { + w.maxChunkLen = defaultGRPCPayloadChunkLen + } + + meta := new(v2session.RequestMetaHeader) + writeXHeadersToMeta(prm.XHeaders, meta) + + if prm.BearerToken != nil { + v2BearerToken := new(acl.BearerToken) + prm.BearerToken.WriteToV2(v2BearerToken) + meta.SetBearerToken(v2BearerToken) + } + + if prm.Session != nil { + v2SessionToken := new(v2session.Token) + prm.Session.WriteToV2(v2SessionToken) + meta.SetSessionToken(v2SessionToken) + } + + if prm.Local { + meta.SetTTL(1) + } + + c.prepareRequest(&w.req, meta) + return &w, nil +} + +type objectWriterRaw struct { + client *Client + stream interface { + Write(*v2object.PutRequest) error + Close() error + } + + key *ecdsa.PrivateKey + res ResObjectPut + err error + chunkCalled bool + respV2 v2object.PutResponse + req v2object.PutRequest + partInit v2object.PutObjectPartInit + partChunk v2object.PutObjectPartChunk + maxChunkLen int +} + +func (x *objectWriterRaw) WriteHeader(_ context.Context, hdr object.Object) bool { + v2Hdr := hdr.ToV2() + + x.partInit.SetObjectID(v2Hdr.GetObjectID()) + x.partInit.SetHeader(v2Hdr.GetHeader()) + x.partInit.SetSignature(v2Hdr.GetSignature()) + + x.req.GetBody().SetObjectPart(&x.partInit) + x.req.SetVerificationHeader(nil) + + x.err = signature.SignServiceMessage(x.key, &x.req) + if x.err != nil { + x.err = fmt.Errorf("sign message: %w", x.err) + return false + } + + x.err = x.stream.Write(&x.req) + return x.err == nil +} + +func (x *objectWriterRaw) WritePayloadChunk(_ context.Context, chunk []byte) bool { + if !x.chunkCalled { + x.chunkCalled = true + x.req.GetBody().SetObjectPart(&x.partChunk) + } + + for ln := len(chunk); ln > 0; ln = len(chunk) { + if ln > x.maxChunkLen { + ln = x.maxChunkLen + } + + // we deal with size limit overflow above, but there is another case: + // what if method is called with "small" chunk many times? We write + // a message to the stream on each call. Alternatively, we could use buffering. + // In most cases, the chunk length does not vary between calls. Given this + // assumption, as well as the length of the payload from the header, it is + // possible to buffer the data of intermediate chunks, and send a message when + // the allocated buffer is filled, or when the last chunk is received. + // It is mentally assumed that allocating and filling the buffer is better than + // synchronous sending, but this needs to be tested. + x.partChunk.SetChunk(chunk[:ln]) + x.req.SetVerificationHeader(nil) + + x.err = signature.SignServiceMessage(x.key, &x.req) + if x.err != nil { + x.err = fmt.Errorf("sign message: %w", x.err) + return false + } + + x.err = x.stream.Write(&x.req) + if x.err != nil { + return false + } + + chunk = chunk[ln:] + } + + return true +} + +func (x *objectWriterRaw) Close(_ context.Context) (*ResObjectPut, error) { + // Ignore io.EOF error, because it is expected error for client-side + // stream termination by the server. E.g. when stream contains invalid + // message. Server returns an error in response message (in status). + if x.err != nil && !errors.Is(x.err, io.EOF) { + return nil, x.err + } + + if x.err = x.stream.Close(); x.err != nil { + return nil, x.err + } + + x.res.st, x.err = x.client.processResponse(&x.respV2) + if x.err != nil { + return nil, x.err + } + + if !apistatus.IsSuccessful(x.res.st) { + return &x.res, nil + } + + const fieldID = "ID" + + idV2 := x.respV2.GetBody().GetObjectID() + if idV2 == nil { + return nil, newErrMissingResponseField(fieldID) + } + + x.err = x.res.obj.ReadFromV2(*idV2) + if x.err != nil { + x.err = newErrInvalidResponseField(fieldID, x.err) + } + + return &x.res, nil +} diff --git a/pkg/sdk/client/object_put_single.go b/pkg/sdk/client/object_put_single.go new file mode 100644 index 000000000..c6a18cd05 --- /dev/null +++ b/pkg/sdk/client/object_put_single.go @@ -0,0 +1,167 @@ +package client + +import ( + "context" + "crypto/ecdsa" + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/acl" + v2object "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" + rpcapi "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client" + v2session "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/signature" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/bearer" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/session" +) + +// PrmObjectPutSingle groups parameters of PutSingle operation. +type PrmObjectPutSingle struct { + XHeaders []string + + BearerToken *bearer.Token + + Session *session.Object + + Local bool + + CopiesNumber []uint32 + + Object *object.Object + + Key *ecdsa.PrivateKey +} + +// SetCopiesNumber sets ordered list of minimal required object copies numbers +// per placement vector. List's length MUST equal container's placement vector number, +// otherwise request will fail. +// +// Deprecated: Use PrmObjectPutSingle.CopiesNumber instead. +func (prm *PrmObjectPutSingle) SetCopiesNumber(v []uint32) { + prm.CopiesNumber = v +} + +// UseKey specifies private key to sign the requests. +// If key is not provided, then Client default key is used. +// +// Deprecated: Use PrmObjectPutSingle.Key instead. +func (prm *PrmObjectPutSingle) UseKey(key *ecdsa.PrivateKey) { + prm.Key = key +} + +// WithBearerToken attaches bearer token to be used for the operation. +// Should be called once before any writing steps. +// +// Deprecated: Use PrmObjectPutSingle.BearerToken instead. +func (prm *PrmObjectPutSingle) WithBearerToken(t bearer.Token) { + prm.BearerToken = &t +} + +// WithinSession specifies session within which object should be stored. +// Should be called once before any writing steps. +// +// Deprecated: Use PrmObjectPutSingle.Session instead. +func (prm *PrmObjectPutSingle) WithinSession(t session.Object) { + prm.Session = &t +} + +// ExecuteLocal tells the server to execute the operation locally. +// +// Deprecated: Use PrmObjectPutSingle.Local instead. +func (prm *PrmObjectPutSingle) ExecuteLocal() { + prm.Local = true +} + +// WithXHeaders specifies list of extended headers (string key-value pairs) +// to be attached to the request. Must have an even length. +// +// Slice must not be mutated until the operation completes. +// +// Deprecated: Use PrmObjectPutSingle.XHeaders instead. +func (prm *PrmObjectPutSingle) WithXHeaders(hs ...string) { + prm.XHeaders = hs +} + +// SetObject specifies prepared object to put. +// +// Deprecated: Use PrmObjectPutSingle.Object instead. +func (prm *PrmObjectPutSingle) SetObject(o *v2object.Object) { + prm.Object = object.NewFromV2(o) +} + +// ResObjectPutSingle groups resulting values of PutSingle operation. +type ResObjectPutSingle struct { + statusRes +} + +func (prm *PrmObjectPutSingle) buildRequest(c *Client) (*v2object.PutSingleRequest, error) { + if len(prm.XHeaders)%2 != 0 { + return nil, errorInvalidXHeaders + } + + body := new(v2object.PutSingleRequestBody) + body.SetCopiesNumber(prm.CopiesNumber) + body.SetObject(prm.Object.ToV2()) + + meta := new(v2session.RequestMetaHeader) + writeXHeadersToMeta(prm.XHeaders, meta) + + if prm.BearerToken != nil { + v2BearerToken := new(acl.BearerToken) + prm.BearerToken.WriteToV2(v2BearerToken) + meta.SetBearerToken(v2BearerToken) + } + + if prm.Session != nil { + v2SessionToken := new(v2session.Token) + prm.Session.WriteToV2(v2SessionToken) + meta.SetSessionToken(v2SessionToken) + } + + if prm.Local { + meta.SetTTL(1) + } + + req := &v2object.PutSingleRequest{} + req.SetBody(body) + c.prepareRequest(req, meta) + + return req, nil +} + +// ObjectPutSingle writes prepared object to FrostFS. +// Object must have payload, also containerID, objectID, ownerID, payload hash, payload length of an object must be set. +// Exactly one return value is non-nil. By default, server status is returned in res structure. +// Any client's internal or transport errors are returned as Go built-in error. +// If Client is tuned to resolve FrostFS API statuses, then FrostFS failures +// codes are returned as error. +func (c *Client) ObjectPutSingle(ctx context.Context, prm PrmObjectPutSingle) (*ResObjectPutSingle, error) { + req, err := prm.buildRequest(c) + if err != nil { + return nil, err + } + + key := &c.prm.Key + if prm.Key != nil { + key = prm.Key + } + + err = signature.SignServiceMessage(key, req) + if err != nil { + return nil, fmt.Errorf("sign request: %w", err) + } + + resp, err := rpcapi.PutSingleObject(&c.c, req, client.WithContext(ctx)) + if err != nil { + return nil, err + } + + var res ResObjectPutSingle + res.st, err = c.processResponse(resp) + if err != nil { + return nil, err + } + + return &res, nil +} diff --git a/pkg/sdk/client/object_put_transformer.go b/pkg/sdk/client/object_put_transformer.go new file mode 100644 index 000000000..1e5ad7b78 --- /dev/null +++ b/pkg/sdk/client/object_put_transformer.go @@ -0,0 +1,128 @@ +package client + +import ( + "context" + + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/transformer" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +func (c *Client) objectPutInitTransformer(prm PrmObjectPutInit) (*objectWriterTransformer, error) { + var w objectWriterTransformer + w.it = internalTarget{ + client: c, + prm: prm, + } + key := &c.prm.Key + if prm.Key != nil { + key = prm.Key + } + w.ot = transformer.NewPayloadSizeLimiter(transformer.Params{ + Key: key, + NextTargetInit: func() transformer.ObjectWriter { return &w.it }, + MaxSize: prm.MaxSize, + WithoutHomomorphicHash: prm.WithoutHomomorphHash, + NetworkState: prm.EpochSource, + }) + return &w, nil +} + +type objectWriterTransformer struct { + ot transformer.ChunkedObjectWriter + it internalTarget + err error +} + +func (x *objectWriterTransformer) WriteHeader(ctx context.Context, hdr object.Object) bool { + x.err = x.ot.WriteHeader(ctx, &hdr) + return x.err == nil +} + +func (x *objectWriterTransformer) WritePayloadChunk(ctx context.Context, chunk []byte) bool { + _, x.err = x.ot.Write(ctx, chunk) + return x.err == nil +} + +func (x *objectWriterTransformer) Close(ctx context.Context) (*ResObjectPut, error) { + if x.err != nil { + return nil, x.err + } + + ai, err := x.ot.Close(ctx) + if err != nil { + return nil, err + } + + if ai != nil && ai.ParentID != nil { + x.it.res.obj = *ai.ParentID + } + return x.it.res, nil +} + +type internalTarget struct { + client *Client + res *ResObjectPut + prm PrmObjectPutInit + useStream bool +} + +func (it *internalTarget) WriteObject(ctx context.Context, o *object.Object) error { + putSingleImplemented, err := it.tryPutSingle(ctx, o) + if putSingleImplemented { + return err + } + it.useStream = true + return it.putAsStream(ctx, o) +} + +func (it *internalTarget) putAsStream(ctx context.Context, o *object.Object) error { + wrt, err := it.client.objectPutInitRaw(ctx, it.prm) + if err != nil { + return err + } + if wrt.WriteHeader(ctx, *o) { + wrt.WritePayloadChunk(ctx, o.Payload()) + } + it.res, err = wrt.Close(ctx) + if err == nil && it.client.prm.DisableFrostFSErrorResolution && !apistatus.IsSuccessful(it.res.st) { + err = apistatus.ErrFromStatus(it.res.st) + } + return err +} + +func (it *internalTarget) tryPutSingle(ctx context.Context, o *object.Object) (bool, error) { + if it.useStream { + return false, nil + } + + prm := PrmObjectPutSingle{ + XHeaders: it.prm.XHeaders, + BearerToken: it.prm.BearerToken, + Session: it.prm.Session, + Local: it.prm.Local, + CopiesNumber: it.prm.CopiesNumber, + Object: o, + Key: it.prm.Key, + } + + res, err := it.client.ObjectPutSingle(ctx, prm) + if err != nil && status.Code(err) == codes.Unimplemented { + return false, err + } + + if err == nil { + id, _ := o.ID() + it.res = &ResObjectPut{ + statusRes: res.statusRes, + obj: id, + } + if it.client.prm.DisableFrostFSErrorResolution && !apistatus.IsSuccessful(it.res.st) { + return true, apistatus.ErrFromStatus(it.res.st) + } + return true, nil + } + return true, err +} diff --git a/pkg/sdk/client/object_search.go b/pkg/sdk/client/object_search.go new file mode 100644 index 000000000..de2f7e548 --- /dev/null +++ b/pkg/sdk/client/object_search.go @@ -0,0 +1,305 @@ +package client + +import ( + "context" + "crypto/ecdsa" + "errors" + "fmt" + "io" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/acl" + v2object "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" + v2refs "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + rpcapi "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client" + v2session "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/signature" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/bearer" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/session" +) + +// PrmObjectSearch groups parameters of ObjectSearch operation. +type PrmObjectSearch struct { + XHeaders []string + + Local bool + + BearerToken *bearer.Token + + Session *session.Object + + ContainerID *cid.ID + + Key *ecdsa.PrivateKey + + Filters object.SearchFilters +} + +// MarkLocal tells the server to execute the operation locally. +// +// Deprecated: Use PrmObjectSearch.Local instead. +func (x *PrmObjectSearch) MarkLocal() { + x.Local = true +} + +// WithinSession specifies session within which the search query must be executed. +// +// Creator of the session acquires the authorship of the request. +// This may affect the execution of an operation (e.g. access control). +// +// Must be signed. +// +// Deprecated: Use PrmObjectSearch.Session instead. +func (x *PrmObjectSearch) WithinSession(t session.Object) { + x.Session = &t +} + +// WithBearerToken attaches bearer token to be used for the operation. +// +// If set, underlying eACL rules will be used in access control. +// +// Must be signed. +// +// Deprecated: Use PrmObjectSearch.BearerToken instead. +func (x *PrmObjectSearch) WithBearerToken(t bearer.Token) { + x.BearerToken = &t +} + +// WithXHeaders specifies list of extended headers (string key-value pairs) +// to be attached to the request. Must have an even length. +// +// Slice must not be mutated until the operation completes. +// +// Deprecated: Use PrmObjectSearch.XHeaders instead. +func (x *PrmObjectSearch) WithXHeaders(hs ...string) { + x.XHeaders = hs +} + +// UseKey specifies private key to sign the requests. +// If key is not provided, then Client default key is used. +// +// Deprecated: Use PrmObjectSearch.Key instead. +func (x *PrmObjectSearch) UseKey(key ecdsa.PrivateKey) { + x.Key = &key +} + +// InContainer specifies the container in which to look for objects. +// Required parameter. +// +// Deprecated: Use PrmObjectSearch.ContainerID instead. +func (x *PrmObjectSearch) InContainer(id cid.ID) { + x.ContainerID = &id +} + +// SetFilters sets filters by which to select objects. All container objects +// match unset/empty filters. +// +// Deprecated: Use PrmObjectSearch.Filters instead. +func (x *PrmObjectSearch) SetFilters(filters object.SearchFilters) { + x.Filters = filters +} + +// ResObjectSearch groups the final result values of ObjectSearch operation. +type ResObjectSearch struct { + statusRes +} + +// ObjectListReader is designed to read list of object identifiers from FrostFS system. +// +// Must be initialized using Client.ObjectSearch, any other usage is unsafe. +type ObjectListReader struct { + client *Client + cancelCtxStream context.CancelFunc + err error + res ResObjectSearch + stream interface { + Read(resp *v2object.SearchResponse) error + } + tail []v2refs.ObjectID +} + +// Read reads another list of the object identifiers. Works similar to +// io.Reader.Read but copies oid.ID and returns success flag instead of error. +// +// Failure reason can be received via Close. +// +// Panics if buf has zero length. +func (x *ObjectListReader) Read(buf []oid.ID) (int, bool) { + if len(buf) == 0 { + panic("empty buffer in ObjectListReader.ReadList") + } + + read := copyIDBuffers(buf, x.tail) + x.tail = x.tail[read:] + + if len(buf) == read { + return read, true + } + + for { + var resp v2object.SearchResponse + x.err = x.stream.Read(&resp) + if x.err != nil { + return read, false + } + + x.res.st, x.err = x.client.processResponse(&resp) + if x.err != nil || !apistatus.IsSuccessful(x.res.st) { + return read, false + } + + // read new chunk of objects + ids := resp.GetBody().GetIDList() + if len(ids) == 0 { + // just skip empty lists since they are not prohibited by protocol + continue + } + + ln := copyIDBuffers(buf[read:], ids) + read += ln + + if read == len(buf) { + // save the tail + x.tail = append(x.tail, ids[ln:]...) + + return read, true + } + } +} + +func copyIDBuffers(dst []oid.ID, src []v2refs.ObjectID) int { + var i int + for ; i < len(dst) && i < len(src); i++ { + _ = dst[i].ReadFromV2(src[i]) + } + return i +} + +// Iterate iterates over the list of found object identifiers. +// f can return true to stop iteration earlier. +// +// Returns an error if object can't be read. +func (x *ObjectListReader) Iterate(f func(oid.ID) bool) error { + buf := make([]oid.ID, 1) + + for { + // Do not check first return value because `len(buf) == 1`, + // so false means nothing was read. + _, ok := x.Read(buf) + if !ok { + res, err := x.Close() + if err != nil { + return err + } + return apistatus.ErrFromStatus(res.Status()) + } + if f(buf[0]) { + return nil + } + } +} + +// Close ends reading list of the matched objects and returns the result of the operation +// along with the final results. Must be called after using the ObjectListReader. +// +// Exactly one return value is non-nil. By default, server status is returned in res structure. +// Any client's internal or transport errors are returned as Go built-in error. +// If Client is tuned to resolve FrostFS API statuses, then FrostFS failures +// codes are returned as error. +// +// Return statuses: +// - global (see Client docs); +// - *apistatus.ContainerNotFound; +// - *apistatus.ObjectAccessDenied; +// - *apistatus.SessionTokenExpired. +func (x *ObjectListReader) Close() (*ResObjectSearch, error) { + defer x.cancelCtxStream() + + if x.err != nil && !errors.Is(x.err, io.EOF) { + return nil, x.err + } + + return &x.res, nil +} + +func (x *PrmObjectSearch) buildRequest(c *Client) (*v2object.SearchRequest, error) { + if x.ContainerID == nil { + return nil, errorMissingContainer + } + + if len(x.XHeaders)%2 != 0 { + return nil, errorInvalidXHeaders + } + + meta := new(v2session.RequestMetaHeader) + writeXHeadersToMeta(x.XHeaders, meta) + + if x.BearerToken != nil { + v2BearerToken := new(acl.BearerToken) + x.BearerToken.WriteToV2(v2BearerToken) + meta.SetBearerToken(v2BearerToken) + } + + if x.Session != nil { + v2SessionToken := new(v2session.Token) + x.Session.WriteToV2(v2SessionToken) + meta.SetSessionToken(v2SessionToken) + } + + if x.Local { + meta.SetTTL(1) + } + cnrV2 := new(v2refs.ContainerID) + x.ContainerID.WriteToV2(cnrV2) + + body := new(v2object.SearchRequestBody) + body.SetVersion(1) + body.SetContainerID(cnrV2) + body.SetFilters(x.Filters.ToV2()) + + req := new(v2object.SearchRequest) + req.SetBody(body) + c.prepareRequest(req, meta) + + return req, nil +} + +// ObjectSearchInit initiates object selection through a remote server using FrostFS API protocol. +// +// The call only opens the transmission channel, explicit fetching of matched objects +// is done using the ObjectListReader. Exactly one return value is non-nil. +// Resulting reader must be finally closed. +// +// Returns an error if parameters are set incorrectly (see PrmObjectSearch docs). +// Context is required and must not be nil. It is used for network communication. +func (c *Client) ObjectSearchInit(ctx context.Context, prm PrmObjectSearch) (*ObjectListReader, error) { + req, err := prm.buildRequest(c) + if err != nil { + return nil, err + } + + key := prm.Key + if key == nil { + key = &c.prm.Key + } + + err = signature.SignServiceMessage(key, req) + if err != nil { + return nil, fmt.Errorf("sign request: %w", err) + } + + var r ObjectListReader + ctx, r.cancelCtxStream = context.WithCancel(ctx) + + r.stream, err = rpcapi.SearchObjects(&c.c, req, client.WithContext(ctx)) + if err != nil { + return nil, fmt.Errorf("open stream: %w", err) + } + r.client = c + + return &r, nil +} diff --git a/pkg/sdk/client/object_search_test.go b/pkg/sdk/client/object_search_test.go new file mode 100644 index 000000000..7b4ba2ba9 --- /dev/null +++ b/pkg/sdk/client/object_search_test.go @@ -0,0 +1,164 @@ +package client + +import ( + "crypto/ecdsa" + "errors" + "fmt" + "io" + "testing" + + v2object "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + signatureV2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/signature" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + oidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id/test" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + "github.com/stretchr/testify/require" +) + +func TestObjectSearch(t *testing.T) { + ids := make([]oid.ID, 20) + for i := range ids { + ids[i] = oidtest.ID() + } + + p, resp := testListReaderResponse(t) + + buf := make([]oid.ID, 2) + checkRead := func(t *testing.T, expected []oid.ID) { + n, ok := resp.Read(buf) + require.True(t, ok == (len(expected) == len(buf)), "expected no error") + require.Equal(t, len(expected), n, "expected %d items to be read", len(expected)) + require.Equal(t, expected, buf[:len(expected)]) + } + + // nil panic + require.Panics(t, func() { resp.Read(nil) }) + + // both ID fetched + resp.stream = newSearchStream(p, nil, ids[:3]) + checkRead(t, ids[:2]) + + // one ID cached, second fetched + resp.stream = newSearchStream(p, nil, ids[3:6]) + checkRead(t, ids[2:4]) + + // both ID cached + resp.stream = nil // shouldn't be called, panic if so + checkRead(t, ids[4:6]) + + // both ID fetched in 2 requests, with empty one in the middle + resp.stream = newSearchStream(p, nil, ids[6:7], nil, ids[7:8]) + checkRead(t, ids[6:8]) + + // read from tail multiple times + resp.stream = newSearchStream(p, nil, ids[8:11]) + buf = buf[:1] + checkRead(t, ids[8:9]) + checkRead(t, ids[9:10]) + checkRead(t, ids[10:11]) + + // handle EOF + buf = buf[:2] + resp.stream = newSearchStream(p, io.EOF, ids[11:12]) + checkRead(t, ids[11:12]) +} + +func TestObjectIterate(t *testing.T) { + ids := make([]oid.ID, 3) + for i := range ids { + ids[i] = oidtest.ID() + } + + t.Run("iterate all sequence", func(t *testing.T) { + p, resp := testListReaderResponse(t) + + resp.stream = newSearchStream(p, io.EOF, ids[0:2], nil, ids[2:3]) + + var actual []oid.ID + require.NoError(t, resp.Iterate(func(id oid.ID) bool { + actual = append(actual, id) + return false + })) + require.Equal(t, ids[:3], actual) + }) + t.Run("stop by return value", func(t *testing.T) { + p, resp := testListReaderResponse(t) + + var actual []oid.ID + resp.stream = &singleStreamResponder{key: p, idList: [][]oid.ID{ids}} + require.NoError(t, resp.Iterate(func(id oid.ID) bool { + actual = append(actual, id) + return len(actual) == 2 + })) + require.Equal(t, ids[:2], actual) + }) + t.Run("stop after error", func(t *testing.T) { + p, resp := testListReaderResponse(t) + expectedErr := errors.New("test error") + + resp.stream = newSearchStream(p, expectedErr, ids[:2]) + + var actual []oid.ID + err := resp.Iterate(func(id oid.ID) bool { + actual = append(actual, id) + return false + }) + require.True(t, errors.Is(err, expectedErr), "got: %v", err) + require.Equal(t, ids[:2], actual) + }) +} + +func testListReaderResponse(t *testing.T) (*ecdsa.PrivateKey, *ObjectListReader) { + p, err := keys.NewPrivateKey() + require.NoError(t, err) + + return &p.PrivateKey, &ObjectListReader{ + cancelCtxStream: func() {}, + client: &Client{}, + tail: nil, + } +} + +func newSearchStream(key *ecdsa.PrivateKey, endError error, idList ...[]oid.ID) *singleStreamResponder { + return &singleStreamResponder{ + key: key, + endError: endError, + idList: idList, + } +} + +type singleStreamResponder struct { + key *ecdsa.PrivateKey + n int + endError error + idList [][]oid.ID +} + +func (s *singleStreamResponder) Read(resp *v2object.SearchResponse) error { + if s.n >= len(s.idList) { + if s.endError != nil { + return s.endError + } + panic("unexpected call to `Read`") + } + + var body v2object.SearchResponseBody + + if s.idList[s.n] != nil { + ids := make([]refs.ObjectID, len(s.idList[s.n])) + for i := range s.idList[s.n] { + s.idList[s.n][i].WriteToV2(&ids[i]) + } + body.SetIDList(ids) + } + resp.SetBody(&body) + + err := signatureV2.SignServiceMessage(s.key, resp) + if err != nil { + panic(fmt.Errorf("error: %w", err)) + } + + s.n++ + return nil +} diff --git a/pkg/sdk/client/response.go b/pkg/sdk/client/response.go new file mode 100644 index 000000000..3c67d83ea --- /dev/null +++ b/pkg/sdk/client/response.go @@ -0,0 +1,27 @@ +package client + +import "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" + +// ResponseMetaInfo groups meta information about any FrostFS API response. +type ResponseMetaInfo struct { + key []byte + + epoch uint64 +} + +type responseV2 interface { + GetMetaHeader() *session.ResponseMetaHeader + GetVerificationHeader() *session.ResponseVerificationHeader +} + +// ResponderKey returns responder's public key in a binary format. +// +// Result must not be mutated. +func (x ResponseMetaInfo) ResponderKey() []byte { + return x.key +} + +// Epoch returns local FrostFS epoch of the server. +func (x ResponseMetaInfo) Epoch() uint64 { + return x.epoch +} diff --git a/pkg/sdk/client/session.go b/pkg/sdk/client/session.go new file mode 100644 index 000000000..c35cf3b7e --- /dev/null +++ b/pkg/sdk/client/session.go @@ -0,0 +1,126 @@ +package client + +import ( + "context" + "crypto/ecdsa" + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + rpcapi "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client" + v2session "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/signature" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" +) + +// PrmSessionCreate groups parameters of SessionCreate operation. +type PrmSessionCreate struct { + XHeaders []string + + Expiration uint64 + + Key *ecdsa.PrivateKey +} + +// SetExp sets number of the last NepFS epoch in the lifetime of the session after which it will be expired. +// +// Deprecated: Use PrmSessionCreate.Expiration instead. +func (x *PrmSessionCreate) SetExp(exp uint64) { + x.Expiration = exp +} + +// UseKey specifies private key to sign the requests and compute token owner. +// If key is not provided, then Client default key is used. +// +// Deprecated: Use PrmSessionCreate.Key instead. +func (x *PrmSessionCreate) UseKey(key ecdsa.PrivateKey) { + x.Key = &key +} + +func (x *PrmSessionCreate) buildRequest(c *Client) (*v2session.CreateRequest, error) { + ownerKey := c.prm.Key.PublicKey + if x.Key != nil { + ownerKey = x.Key.PublicKey + } + var ownerID user.ID + user.IDFromKey(&ownerID, ownerKey) + + var ownerIDV2 refs.OwnerID + ownerID.WriteToV2(&ownerIDV2) + + reqBody := new(v2session.CreateRequestBody) + reqBody.SetOwnerID(&ownerIDV2) + reqBody.SetExpiration(x.Expiration) + + var meta v2session.RequestMetaHeader + writeXHeadersToMeta(x.XHeaders, &meta) + + var req v2session.CreateRequest + req.SetBody(reqBody) + c.prepareRequest(&req, &meta) + return &req, nil +} + +// ResSessionCreate groups resulting values of SessionCreate operation. +type ResSessionCreate struct { + statusRes + + id []byte + + sessionKey []byte +} + +// ID returns identifier of the opened session in a binary FrostFS API protocol format. +// +// Client doesn't retain value so modification is safe. +func (x ResSessionCreate) ID() []byte { + return x.id +} + +// PublicKey returns public key of the opened session in a binary FrostFS API protocol format. +func (x ResSessionCreate) PublicKey() []byte { + return x.sessionKey +} + +// SessionCreate opens a session with the node server on the remote endpoint. +// The session lifetime coincides with the server lifetime. Results can be written +// to session token which can be later attached to the requests. +// +// Exactly one return value is non-nil. By default, server status is returned in res structure. +// Any client's internal or transport errors are returned as `error`. +// If PrmInit.DisableFrostFSFailuresResolution has been called, unsuccessful +// FrostFS status codes are included in the returned result structure, +// otherwise, are also returned as `error`. +// +// Returns an error if parameters are set incorrectly (see PrmSessionCreate docs). +// Context is required and must not be nil. It is used for network communication. +// +// Return statuses: +// - global (see Client docs). +func (c *Client) SessionCreate(ctx context.Context, prm PrmSessionCreate) (*ResSessionCreate, error) { + req, err := prm.buildRequest(c) + if err != nil { + return nil, err + } + + if err := signature.SignServiceMessage(&c.prm.Key, req); err != nil { + return nil, fmt.Errorf("sign request: %w", err) + } + + resp, err := rpcapi.CreateSession(&c.c, req, client.WithContext(ctx)) + if err != nil { + return nil, err + } + + var res ResSessionCreate + res.st, err = c.processResponse(resp) + if err != nil || !apistatus.IsSuccessful(res.st) { + return &res, err + } + + body := resp.GetBody() + res.id = body.GetID() + res.sessionKey = body.GetSessionKey() + return &res, nil +} diff --git a/pkg/sdk/client/status/common.go b/pkg/sdk/client/status/common.go new file mode 100644 index 000000000..4e971bd09 --- /dev/null +++ b/pkg/sdk/client/status/common.go @@ -0,0 +1,240 @@ +package apistatus + +import ( + "encoding/binary" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/status" +) + +// ServerInternal describes failure statuses related to internal server errors. +// Instances provide Status and StatusV2 interfaces. +// +// The status is purely informative, the client should not go into details of the error except for debugging needs. +type ServerInternal struct { + v2 status.Status +} + +func (x *ServerInternal) Error() string { + return errMessageStatusV2( + globalizeCodeV2(status.Internal, status.GlobalizeCommonFail), + x.v2.Message(), + ) +} + +// implements local interface defined in FromStatusV2 func. +func (x *ServerInternal) fromStatusV2(st *status.Status) { + x.v2 = *st +} + +// ToStatusV2 implements StatusV2 interface method. +// If the value was returned by FromStatusV2, returns the source message. +// Otherwise, returns message with +// - code: INTERNAL; +// - string message: empty; +// - details: empty. +func (x ServerInternal) ToStatusV2() *status.Status { + x.v2.SetCode(globalizeCodeV2(status.Internal, status.GlobalizeCommonFail)) + return &x.v2 +} + +// SetMessage sets message describing internal error. +// +// Message should be used for debug purposes only. +func (x *ServerInternal) SetMessage(msg string) { + x.v2.SetMessage(msg) +} + +// Message returns message describing internal server error. +// +// Message should be used for debug purposes only. By default, it is empty. +func (x ServerInternal) Message() string { + return x.v2.Message() +} + +// WriteInternalServerErr writes err message to ServerInternal instance. +func WriteInternalServerErr(x *ServerInternal, err error) { + x.SetMessage(err.Error()) +} + +// WrongMagicNumber describes failure status related to incorrect network magic. +// Instances provide Status and StatusV2 interfaces. +type WrongMagicNumber struct { + v2 status.Status +} + +func (x *WrongMagicNumber) Error() string { + return errMessageStatusV2( + globalizeCodeV2(status.WrongMagicNumber, status.GlobalizeCommonFail), + x.v2.Message(), + ) +} + +// implements local interface defined in FromStatusV2 func. +func (x *WrongMagicNumber) fromStatusV2(st *status.Status) { + x.v2 = *st +} + +// ToStatusV2 implements StatusV2 interface method. +// If the value was returned by FromStatusV2, returns the source message. +// Otherwise, returns message with +// - code: WRONG_MAGIC_NUMBER; +// - string message: empty; +// - details: empty. +func (x WrongMagicNumber) ToStatusV2() *status.Status { + x.v2.SetCode(globalizeCodeV2(status.WrongMagicNumber, status.GlobalizeCommonFail)) + return &x.v2 +} + +// WriteCorrectMagic writes correct network magic. +func (x *WrongMagicNumber) WriteCorrectMagic(magic uint64) { + // serialize the number + buf := make([]byte, 8) + + binary.BigEndian.PutUint64(buf, magic) + + // create corresponding detail + var d status.Detail + + d.SetID(status.DetailIDCorrectMagic) + d.SetValue(buf) + + // attach the detail + x.v2.AppendDetails(d) +} + +// CorrectMagic returns network magic returned by the server. +// Second value indicates presence status: +// - -1 if number is presented in incorrect format +// - 0 if number is not presented +// - +1 otherwise +func (x WrongMagicNumber) CorrectMagic() (magic uint64, ok int8) { + x.v2.IterateDetails(func(d *status.Detail) bool { + if d.ID() == status.DetailIDCorrectMagic { + if val := d.Value(); len(val) == 8 { + magic = binary.BigEndian.Uint64(val) + ok = 1 + } else { + ok = -1 + } + } + + return ok != 0 + }) + + return +} + +// SignatureVerification describes failure status related to signature verification. +// Instances provide Status and StatusV2 interfaces. +type SignatureVerification struct { + v2 status.Status +} + +const defaultSignatureVerificationMsg = "signature verification failed" + +func (x *SignatureVerification) Error() string { + msg := x.v2.Message() + if msg == "" { + msg = defaultSignatureVerificationMsg + } + + return errMessageStatusV2( + globalizeCodeV2(status.SignatureVerificationFail, status.GlobalizeCommonFail), + msg, + ) +} + +// implements local interface defined in FromStatusV2 func. +func (x *SignatureVerification) fromStatusV2(st *status.Status) { + x.v2 = *st +} + +// ToStatusV2 implements StatusV2 interface method. +// If the value was returned by FromStatusV2, returns the source message. +// Otherwise, returns message with +// - code: SIGNATURE_VERIFICATION_FAIL; +// - string message: written message via SetMessage or +// "signature verification failed" as a default message; +// - details: empty. +func (x SignatureVerification) ToStatusV2() *status.Status { + x.v2.SetCode(globalizeCodeV2(status.SignatureVerificationFail, status.GlobalizeCommonFail)) + + if x.v2.Message() == "" { + x.v2.SetMessage(defaultSignatureVerificationMsg) + } + + return &x.v2 +} + +// SetMessage writes signature verification failure message. +// Message should be used for debug purposes only. +// +// See also Message. +func (x *SignatureVerification) SetMessage(v string) { + x.v2.SetMessage(v) +} + +// Message returns status message. Zero status returns empty message. +// Message should be used for debug purposes only. +// +// See also SetMessage. +func (x SignatureVerification) Message() string { + return x.v2.Message() +} + +// NodeUnderMaintenance describes failure status for nodes being under maintenance. +// Instances provide Status and StatusV2 interfaces. +type NodeUnderMaintenance struct { + v2 status.Status +} + +const defaultNodeUnderMaintenanceMsg = "node is under maintenance" + +// Error implements the error interface. +func (x *NodeUnderMaintenance) Error() string { + msg := x.Message() + if msg == "" { + msg = defaultNodeUnderMaintenanceMsg + } + + return errMessageStatusV2( + globalizeCodeV2(status.NodeUnderMaintenance, status.GlobalizeCommonFail), + msg, + ) +} + +func (x *NodeUnderMaintenance) fromStatusV2(st *status.Status) { + x.v2 = *st +} + +// ToStatusV2 implements StatusV2 interface method. +// If the value was returned by FromStatusV2, returns the source message. +// Otherwise, returns message with +// - code: NODE_UNDER_MAINTENANCE; +// - string message: written message via SetMessage or +// "node is under maintenance" as a default message; +// - details: empty. +func (x NodeUnderMaintenance) ToStatusV2() *status.Status { + x.v2.SetCode(globalizeCodeV2(status.NodeUnderMaintenance, status.GlobalizeCommonFail)) + if x.v2.Message() == "" { + x.v2.SetMessage(defaultNodeUnderMaintenanceMsg) + } + + return &x.v2 +} + +// SetMessage writes signature verification failure message. +// Message should be used for debug purposes only. +// +// See also Message. +func (x *NodeUnderMaintenance) SetMessage(v string) { + x.v2.SetMessage(v) +} + +// Message returns status message. Zero status returns empty message. +// Message should be used for debug purposes only. +// +// See also SetMessage. +func (x NodeUnderMaintenance) Message() string { + return x.v2.Message() +} diff --git a/pkg/sdk/client/status/common_test.go b/pkg/sdk/client/status/common_test.go new file mode 100644 index 000000000..be5e30d44 --- /dev/null +++ b/pkg/sdk/client/status/common_test.go @@ -0,0 +1,130 @@ +package apistatus_test + +import ( + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/status" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + "github.com/stretchr/testify/require" +) + +func TestServerInternal_Message(t *testing.T) { + const msg = "some message" + + var st apistatus.ServerInternal + + res := st.Message() + resv2 := apistatus.ToStatusV2(st).Message() + require.Empty(t, res) + require.Empty(t, resv2) + + st.SetMessage(msg) + + res = st.Message() + resv2 = apistatus.ToStatusV2(st).Message() + require.Equal(t, msg, res) + require.Equal(t, msg, resv2) +} + +func TestWrongMagicNumber_CorrectMagic(t *testing.T) { + const magic = 1337 + + var st apistatus.WrongMagicNumber + + res, ok := st.CorrectMagic() + require.Zero(t, res) + require.Zero(t, ok) + + st.WriteCorrectMagic(magic) + + res, ok = st.CorrectMagic() + require.EqualValues(t, magic, res) + require.EqualValues(t, 1, ok) + + // corrupt the value + apistatus.ToStatusV2(st).IterateDetails(func(d *status.Detail) bool { + d.SetValue([]byte{1, 2, 3}) // any slice with len != 8 + return true + }) + + _, ok = st.CorrectMagic() + require.EqualValues(t, -1, ok) +} + +func TestSignatureVerification(t *testing.T) { + t.Run("default", func(t *testing.T) { + var st apistatus.SignatureVerification + + require.Empty(t, st.Message()) + }) + + t.Run("custom message", func(t *testing.T) { + var st apistatus.SignatureVerification + msg := "some message" + + st.SetMessage(msg) + + stV2 := st.ToStatusV2() + + require.Equal(t, msg, st.Message()) + require.Equal(t, msg, stV2.Message()) + }) + + t.Run("empty to V2", func(t *testing.T) { + var st apistatus.SignatureVerification + + stV2 := st.ToStatusV2() + + require.Equal(t, "signature verification failed", stV2.Message()) + }) + + t.Run("non-empty to V2", func(t *testing.T) { + var st apistatus.SignatureVerification + msg := "some other msg" + + st.SetMessage(msg) + + stV2 := st.ToStatusV2() + + require.Equal(t, msg, stV2.Message()) + }) +} + +func TestNodeUnderMaintenance(t *testing.T) { + t.Run("default", func(t *testing.T) { + var st apistatus.NodeUnderMaintenance + + require.Empty(t, st.Message()) + }) + + t.Run("custom message", func(t *testing.T) { + var st apistatus.NodeUnderMaintenance + msg := "some message" + + st.SetMessage(msg) + + stV2 := st.ToStatusV2() + + require.Equal(t, msg, st.Message()) + require.Equal(t, msg, stV2.Message()) + }) + + t.Run("empty to V2", func(t *testing.T) { + var st apistatus.NodeUnderMaintenance + + stV2 := st.ToStatusV2() + + require.Empty(t, "", stV2.Message()) + }) + + t.Run("non-empty to V2", func(t *testing.T) { + var st apistatus.NodeUnderMaintenance + msg := "some other msg" + + st.SetMessage(msg) + + stV2 := st.ToStatusV2() + + require.Equal(t, msg, stV2.Message()) + }) +} diff --git a/pkg/sdk/client/status/container.go b/pkg/sdk/client/status/container.go new file mode 100644 index 000000000..f61e269f2 --- /dev/null +++ b/pkg/sdk/client/status/container.go @@ -0,0 +1,81 @@ +package apistatus + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/container" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/status" +) + +// ContainerNotFound describes status of the failure because of the missing container. +// Instances provide Status and StatusV2 interfaces. +type ContainerNotFound struct { + v2 status.Status +} + +const defaultContainerNotFoundMsg = "container not found" + +func (x *ContainerNotFound) Error() string { + msg := x.v2.Message() + if msg == "" { + msg = defaultContainerNotFoundMsg + } + + return errMessageStatusV2( + globalizeCodeV2(container.StatusNotFound, container.GlobalizeFail), + msg, + ) +} + +// implements local interface defined in FromStatusV2 func. +func (x *ContainerNotFound) fromStatusV2(st *status.Status) { + x.v2 = *st +} + +// ToStatusV2 implements StatusV2 interface method. +// If the value was returned by FromStatusV2, returns the source message. +// Otherwise, returns message with +// - code: CONTAINER_NOT_FOUND; +// - string message: "container not found"; +// - details: empty. +func (x ContainerNotFound) ToStatusV2() *status.Status { + x.v2.SetCode(globalizeCodeV2(container.StatusNotFound, container.GlobalizeFail)) + x.v2.SetMessage(defaultContainerNotFoundMsg) + return &x.v2 +} + +// EACLNotFound describes status of the failure because of the missing eACL +// table. +// Instances provide Status and StatusV2 interfaces. +type EACLNotFound struct { + v2 status.Status +} + +const defaultEACLNotFoundMsg = "eACL not found" + +func (x *EACLNotFound) Error() string { + msg := x.v2.Message() + if msg == "" { + msg = defaultEACLNotFoundMsg + } + + return errMessageStatusV2( + globalizeCodeV2(container.StatusEACLNotFound, container.GlobalizeFail), + msg, + ) +} + +// implements local interface defined in FromStatusV2 func. +func (x *EACLNotFound) fromStatusV2(st *status.Status) { + x.v2 = *st +} + +// ToStatusV2 implements StatusV2 interface method. +// If the value was returned by FromStatusV2, returns the source message. +// Otherwise, returns message with +// - code: EACL_NOT_FOUND; +// - string message: "eACL not found"; +// - details: empty. +func (x EACLNotFound) ToStatusV2() *status.Status { + x.v2.SetCode(globalizeCodeV2(container.StatusEACLNotFound, container.GlobalizeFail)) + x.v2.SetMessage(defaultEACLNotFoundMsg) + return &x.v2 +} diff --git a/pkg/sdk/client/status/object.go b/pkg/sdk/client/status/object.go new file mode 100644 index 000000000..fe9962ce8 --- /dev/null +++ b/pkg/sdk/client/status/object.go @@ -0,0 +1,240 @@ +package apistatus + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/status" +) + +// ObjectLocked describes status of the failure because of the locked object. +// Instances provide Status and StatusV2 interfaces. +type ObjectLocked struct { + v2 status.Status +} + +const defaultObjectLockedMsg = "object is locked" + +func (x *ObjectLocked) Error() string { + msg := x.v2.Message() + if msg == "" { + msg = defaultObjectLockedMsg + } + + return errMessageStatusV2( + globalizeCodeV2(object.StatusLocked, object.GlobalizeFail), + msg, + ) +} + +// implements local interface defined in FromStatusV2 func. +func (x *ObjectLocked) fromStatusV2(st *status.Status) { + x.v2 = *st +} + +// ToStatusV2 implements StatusV2 interface method. +// If the value was returned by FromStatusV2, returns the source message. +// Otherwise, returns message with +// - code: LOCKED; +// - string message: "object is locked"; +// - details: empty. +func (x ObjectLocked) ToStatusV2() *status.Status { + x.v2.SetCode(globalizeCodeV2(object.StatusLocked, object.GlobalizeFail)) + x.v2.SetMessage(defaultObjectLockedMsg) + return &x.v2 +} + +// LockNonRegularObject describes status returned on locking the non-regular object. +// Instances provide Status and StatusV2 interfaces. +type LockNonRegularObject struct { + v2 status.Status +} + +const defaultLockNonRegularObjectMsg = "locking non-regular object is forbidden" + +func (x *LockNonRegularObject) Error() string { + msg := x.v2.Message() + if msg == "" { + msg = defaultLockNonRegularObjectMsg + } + + return errMessageStatusV2( + globalizeCodeV2(object.StatusLockNonRegularObject, object.GlobalizeFail), + msg, + ) +} + +// implements local interface defined in FromStatusV2 func. +func (x *LockNonRegularObject) fromStatusV2(st *status.Status) { + x.v2 = *st +} + +// ToStatusV2 implements StatusV2 interface method. +// If the value was returned by FromStatusV2, returns the source message. +// Otherwise, returns message with +// - code: LOCK_NON_REGULAR_OBJECT; +// - string message: "locking non-regular object is forbidden"; +// - details: empty. +func (x LockNonRegularObject) ToStatusV2() *status.Status { + x.v2.SetCode(globalizeCodeV2(object.StatusLockNonRegularObject, object.GlobalizeFail)) + x.v2.SetMessage(defaultLockNonRegularObjectMsg) + return &x.v2 +} + +// ObjectAccessDenied describes status of the failure because of the access control violation. +// Instances provide Status and StatusV2 interfaces. +type ObjectAccessDenied struct { + v2 status.Status +} + +const defaultObjectAccessDeniedMsg = "access to object operation denied" + +func (x *ObjectAccessDenied) Error() string { + msg := x.v2.Message() + if msg == "" { + msg = defaultObjectAccessDeniedMsg + } + + return errMessageStatusV2( + globalizeCodeV2(object.StatusAccessDenied, object.GlobalizeFail), + msg, + ) +} + +// implements local interface defined in FromStatusV2 func. +func (x *ObjectAccessDenied) fromStatusV2(st *status.Status) { + x.v2 = *st +} + +// ToStatusV2 implements StatusV2 interface method. +// If the value was returned by FromStatusV2, returns the source message. +// Otherwise, returns message with +// - code: ACCESS_DENIED; +// - string message: "access to object operation denied"; +// - details: empty. +func (x ObjectAccessDenied) ToStatusV2() *status.Status { + x.v2.SetCode(globalizeCodeV2(object.StatusAccessDenied, object.GlobalizeFail)) + x.v2.SetMessage(defaultObjectAccessDeniedMsg) + return &x.v2 +} + +// WriteReason writes human-readable access rejection reason. +func (x *ObjectAccessDenied) WriteReason(reason string) { + object.WriteAccessDeniedDesc(&x.v2, reason) +} + +// Reason returns human-readable access rejection reason returned by the server. +// Returns empty value is reason is not presented. +func (x ObjectAccessDenied) Reason() string { + return object.ReadAccessDeniedDesc(x.v2) +} + +// ObjectNotFound describes status of the failure because of the missing object. +// Instances provide Status and StatusV2 interfaces. +type ObjectNotFound struct { + v2 status.Status +} + +const defaultObjectNotFoundMsg = "object not found" + +func (x *ObjectNotFound) Error() string { + msg := x.v2.Message() + if msg == "" { + msg = defaultObjectNotFoundMsg + } + + return errMessageStatusV2( + globalizeCodeV2(object.StatusNotFound, object.GlobalizeFail), + msg, + ) +} + +// implements local interface defined in FromStatusV2 func. +func (x *ObjectNotFound) fromStatusV2(st *status.Status) { + x.v2 = *st +} + +// ToStatusV2 implements StatusV2 interface method. +// If the value was returned by FromStatusV2, returns the source message. +// Otherwise, returns message with +// - code: OBJECT_NOT_FOUND; +// - string message: "object not found"; +// - details: empty. +func (x ObjectNotFound) ToStatusV2() *status.Status { + x.v2.SetCode(globalizeCodeV2(object.StatusNotFound, object.GlobalizeFail)) + x.v2.SetMessage(defaultObjectNotFoundMsg) + return &x.v2 +} + +// ObjectAlreadyRemoved describes status of the failure because object has been +// already removed. Instances provide Status and StatusV2 interfaces. +type ObjectAlreadyRemoved struct { + v2 status.Status +} + +const defaultObjectAlreadyRemovedMsg = "object already removed" + +func (x *ObjectAlreadyRemoved) Error() string { + msg := x.v2.Message() + if msg == "" { + msg = defaultObjectAlreadyRemovedMsg + } + + return errMessageStatusV2( + globalizeCodeV2(object.StatusAlreadyRemoved, object.GlobalizeFail), + msg, + ) +} + +// implements local interface defined in FromStatusV2 func. +func (x *ObjectAlreadyRemoved) fromStatusV2(st *status.Status) { + x.v2 = *st +} + +// ToStatusV2 implements StatusV2 interface method. +// If the value was returned by FromStatusV2, returns the source message. +// Otherwise, returns message with +// - code: OBJECT_ALREADY_REMOVED; +// - string message: "object already removed"; +// - details: empty. +func (x ObjectAlreadyRemoved) ToStatusV2() *status.Status { + x.v2.SetCode(globalizeCodeV2(object.StatusAlreadyRemoved, object.GlobalizeFail)) + x.v2.SetMessage(defaultObjectAlreadyRemovedMsg) + return &x.v2 +} + +// ObjectOutOfRange describes status of the failure because of the incorrect +// provided object ranges. +// Instances provide Status and StatusV2 interfaces. +type ObjectOutOfRange struct { + v2 status.Status +} + +const defaultObjectOutOfRangeMsg = "out of range" + +func (x *ObjectOutOfRange) Error() string { + msg := x.v2.Message() + if msg == "" { + msg = defaultObjectOutOfRangeMsg + } + + return errMessageStatusV2( + globalizeCodeV2(object.StatusOutOfRange, object.GlobalizeFail), + msg, + ) +} + +// implements local interface defined in FromStatusV2 func. +func (x *ObjectOutOfRange) fromStatusV2(st *status.Status) { + x.v2 = *st +} + +// ToStatusV2 implements StatusV2 interface method. +// If the value was returned by FromStatusV2, returns the source message. +// Otherwise, returns message with +// - code: OUT_OF_RANGE; +// - string message: "out of range"; +// - details: empty. +func (x ObjectOutOfRange) ToStatusV2() *status.Status { + x.v2.SetCode(globalizeCodeV2(object.StatusOutOfRange, object.GlobalizeFail)) + x.v2.SetMessage(defaultObjectOutOfRangeMsg) + return &x.v2 +} diff --git a/pkg/sdk/client/status/object_test.go b/pkg/sdk/client/status/object_test.go new file mode 100644 index 000000000..c0330e846 --- /dev/null +++ b/pkg/sdk/client/status/object_test.go @@ -0,0 +1,26 @@ +package apistatus_test + +import ( + "testing" + + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + "github.com/stretchr/testify/require" +) + +func TestObjectAccessDenied_WriteReason(t *testing.T) { + const reason = "any reason" + + var st apistatus.ObjectAccessDenied + + res := st.Reason() + require.Empty(t, res) + detailNum := apistatus.ToStatusV2(st).NumberOfDetails() + require.Zero(t, detailNum) + + st.WriteReason(reason) + + res = st.Reason() + require.Equal(t, reason, res) + detailNum = apistatus.ToStatusV2(st).NumberOfDetails() + require.EqualValues(t, 1, detailNum) +} diff --git a/pkg/sdk/client/status/session.go b/pkg/sdk/client/status/session.go new file mode 100644 index 000000000..20aa22a86 --- /dev/null +++ b/pkg/sdk/client/status/session.go @@ -0,0 +1,80 @@ +package apistatus + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/status" +) + +// SessionTokenNotFound describes status of the failure because of the missing session token. +// Instances provide Status and StatusV2 interfaces. +type SessionTokenNotFound struct { + v2 status.Status +} + +const defaultSessionTokenNotFoundMsg = "session token not found" + +func (x *SessionTokenNotFound) Error() string { + msg := x.v2.Message() + if msg == "" { + msg = defaultSessionTokenNotFoundMsg + } + + return errMessageStatusV2( + globalizeCodeV2(session.StatusTokenNotFound, session.GlobalizeFail), + msg, + ) +} + +// implements local interface defined in FromStatusV2 func. +func (x *SessionTokenNotFound) fromStatusV2(st *status.Status) { + x.v2 = *st +} + +// ToStatusV2 implements StatusV2 interface method. +// If the value was returned by FromStatusV2, returns the source message. +// Otherwise, returns message with +// - code: TOKEN_NOT_FOUND; +// - string message: "session token not found"; +// - details: empty. +func (x SessionTokenNotFound) ToStatusV2() *status.Status { + x.v2.SetCode(globalizeCodeV2(session.StatusTokenNotFound, session.GlobalizeFail)) + x.v2.SetMessage(defaultSessionTokenNotFoundMsg) + return &x.v2 +} + +// SessionTokenExpired describes status of the failure because of the expired session token. +// Instances provide Status and StatusV2 interfaces. +type SessionTokenExpired struct { + v2 status.Status +} + +const defaultSessionTokenExpiredMsg = "expired session token" + +func (x *SessionTokenExpired) Error() string { + msg := x.v2.Message() + if msg == "" { + msg = defaultSessionTokenExpiredMsg + } + + return errMessageStatusV2( + globalizeCodeV2(session.StatusTokenExpired, session.GlobalizeFail), + msg, + ) +} + +// implements local interface defined in FromStatusV2 func. +func (x *SessionTokenExpired) fromStatusV2(st *status.Status) { + x.v2 = *st +} + +// ToStatusV2 implements StatusV2 interface method. +// If the value was returned by FromStatusV2, returns the source message. +// Otherwise, returns message with +// - code: TOKEN_EXPIRED; +// - string message: "expired session token"; +// - details: empty. +func (x SessionTokenExpired) ToStatusV2() *status.Status { + x.v2.SetCode(globalizeCodeV2(session.StatusTokenExpired, session.GlobalizeFail)) + x.v2.SetMessage(defaultSessionTokenExpiredMsg) + return &x.v2 +} diff --git a/pkg/sdk/client/status/status.go b/pkg/sdk/client/status/status.go new file mode 100644 index 000000000..1d66b6b1d --- /dev/null +++ b/pkg/sdk/client/status/status.go @@ -0,0 +1,44 @@ +package apistatus + +// Status defines a variety of FrostFS API status returns. +// +// All statuses are split into two disjoint subsets: successful and failed, and: +// - statuses that implement the build-in error interface are considered failed statuses; +// - all other value types are considered successes (nil is a default success). +// +// In Go code type of success can be determined by a type switch, failure - by a switch with errors.As calls. +// Nil should be considered as a success, and default switch section - as an unrecognized Status. +// +// To convert statuses into errors and vice versa, use functions ErrToStatus and ErrFromStatus, respectively. +// ErrFromStatus function returns nil for successful statuses. However, to simplify the check of statuses for success, +// IsSuccessful function should be used (try to avoid nil comparison). +// It should be noted that using direct typecasting is not a compatible approach. +// +// To transport statuses using the FrostFS API V2 protocol, see StatusV2 interface and FromStatusV2 and ToStatusV2 functions. +type Status any + +// ErrFromStatus converts Status instance to error if it is failed. Returns nil on successful Status. +// +// Note: direct assignment may not be compatibility-safe. +func ErrFromStatus(st Status) error { + if err, ok := st.(error); ok { + return err + } + + return nil +} + +// ErrToStatus converts the error instance to Status instance. +// +// Note: direct assignment may not be compatibility-safe. +func ErrToStatus(err error) Status { + return err +} + +// IsSuccessful checks if status is successful. +// +// Note: direct cast may not be compatibility-safe. +func IsSuccessful(st Status) bool { + _, ok := st.(error) + return !ok +} diff --git a/pkg/sdk/client/status/status_test.go b/pkg/sdk/client/status/status_test.go new file mode 100644 index 000000000..a493ea2da --- /dev/null +++ b/pkg/sdk/client/status/status_test.go @@ -0,0 +1,35 @@ +package apistatus_test + +import ( + "errors" + "testing" + + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + "github.com/stretchr/testify/require" +) + +func TestErrors(t *testing.T) { + t.Run("error source", func(t *testing.T) { + err := errors.New("some error") + + st := apistatus.ErrToStatus(err) + + success := apistatus.IsSuccessful(st) + require.False(t, success) + + res := apistatus.ErrFromStatus(st) + + require.Equal(t, err, res) + }) + + t.Run("non-error source", func(t *testing.T) { + var st apistatus.Status = "any non-error type" + + success := apistatus.IsSuccessful(st) + require.True(t, success) + + res := apistatus.ErrFromStatus(st) + + require.Nil(t, res) + }) +} diff --git a/pkg/sdk/client/status/success.go b/pkg/sdk/client/status/success.go new file mode 100644 index 000000000..9ee28affc --- /dev/null +++ b/pkg/sdk/client/status/success.go @@ -0,0 +1,32 @@ +package apistatus + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/status" +) + +// SuccessDefaultV2 represents Status instance of default success. Implements StatusV2. +type SuccessDefaultV2 struct { + isNil bool + + v2 *status.Status +} + +// implements local interface defined in FromStatusV2 func. +func (x *SuccessDefaultV2) fromStatusV2(st *status.Status) { + x.isNil = st == nil + x.v2 = st +} + +// ToStatusV2 implements StatusV2 interface method. +// If the value was returned by FromStatusV2, returns the source message. +// Otherwise, returns message with +// - code: OK; +// - string message: empty; +// - details: empty. +func (x SuccessDefaultV2) ToStatusV2() *status.Status { + if x.isNil || x.v2 != nil { + return x.v2 + } + + return newStatusV2WithLocalCode(status.OK, status.GlobalizeSuccess) +} diff --git a/pkg/sdk/client/status/unrecognized.go b/pkg/sdk/client/status/unrecognized.go new file mode 100644 index 000000000..0a5638e42 --- /dev/null +++ b/pkg/sdk/client/status/unrecognized.go @@ -0,0 +1,18 @@ +package apistatus + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/status" +) + +type unrecognizedStatusV2 struct { + v2 status.Status +} + +func (x *unrecognizedStatusV2) Error() string { + return errMessageStatusV2("unrecognized", x.v2.Message()) +} + +// implements local interface defined in FromStatusV2 func. +func (x *unrecognizedStatusV2) fromStatusV2(st *status.Status) { + x.v2 = *st +} diff --git a/pkg/sdk/client/status/v2.go b/pkg/sdk/client/status/v2.go new file mode 100644 index 000000000..6fd55d671 --- /dev/null +++ b/pkg/sdk/client/status/v2.go @@ -0,0 +1,150 @@ +package apistatus + +import ( + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/container" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/status" +) + +// StatusV2 defines a variety of Status instances compatible with FrostFS API V2 protocol. +// +// Note: it is not recommended to use this type directly, it is intended for documentation of the library functionality. +type StatusV2 interface { + Status + + // ToStatusV2 returns the status as git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/status.Status message structure. + ToStatusV2() *status.Status +} + +// FromStatusV2 converts status.Status message structure to Status instance. Inverse to ToStatusV2 operation. +// +// If result is not nil, it implements StatusV2. This fact should be taken into account only when passing +// the result to the inverse function ToStatusV2, casts are not compatibility-safe. +// +// Below is the mapping of return codes to Status instance types (with a description of parsing details). +// Note: notice if the return type is a pointer. +// +// Successes: +// - status.OK: *SuccessDefaultV2 (this also includes nil argument). +// +// Common failures: +// - status.Internal: *ServerInternal; +// - status.SignatureVerificationFail: *SignatureVerification. +// +// Object failures: +// - object.StatusLocked: *ObjectLocked; +// - object.StatusLockNonRegularObject: *LockNonRegularObject. +// - object.StatusAccessDenied: *ObjectAccessDenied. +func FromStatusV2(st *status.Status) Status { + var decoder interface { + fromStatusV2(*status.Status) + } + + switch code := st.Code(); { + case status.IsSuccess(code): + //nolint:exhaustive + switch status.LocalizeSuccess(&code); code { + case status.OK: + decoder = new(SuccessDefaultV2) + } + case status.IsCommonFail(code): + switch status.LocalizeCommonFail(&code); code { + case status.Internal: + decoder = new(ServerInternal) + case status.WrongMagicNumber: + decoder = new(WrongMagicNumber) + case status.SignatureVerificationFail: + decoder = new(SignatureVerification) + case status.NodeUnderMaintenance: + decoder = new(NodeUnderMaintenance) + } + case object.LocalizeFailStatus(&code): + switch code { + case object.StatusLocked: + decoder = new(ObjectLocked) + case object.StatusLockNonRegularObject: + decoder = new(LockNonRegularObject) + case object.StatusAccessDenied: + decoder = new(ObjectAccessDenied) + case object.StatusNotFound: + decoder = new(ObjectNotFound) + case object.StatusAlreadyRemoved: + decoder = new(ObjectAlreadyRemoved) + case object.StatusOutOfRange: + decoder = new(ObjectOutOfRange) + } + case container.LocalizeFailStatus(&code): + //nolint:exhaustive + switch code { + case container.StatusNotFound: + decoder = new(ContainerNotFound) + case container.StatusEACLNotFound: + decoder = new(EACLNotFound) + } + case session.LocalizeFailStatus(&code): + //nolint:exhaustive + switch code { + case session.StatusTokenNotFound: + decoder = new(SessionTokenNotFound) + case session.StatusTokenExpired: + decoder = new(SessionTokenExpired) + } + } + + if decoder == nil { + decoder = new(unrecognizedStatusV2) + } + + decoder.fromStatusV2(st) + + return decoder +} + +// ToStatusV2 converts Status instance to status.Status message structure. Inverse to FromStatusV2 operation. +// +// If argument is the StatusV2 instance, it is converted directly. +// Otherwise, successes are converted with status.OK code w/o details and message, +// failures - with status.Internal and error text message w/o details. +func ToStatusV2(st Status) *status.Status { + if v, ok := st.(StatusV2); ok { + return v.ToStatusV2() + } + + if IsSuccessful(st) { + return newStatusV2WithLocalCode(status.OK, status.GlobalizeSuccess) + } + + internalErrorStatus := newStatusV2WithLocalCode(status.Internal, status.GlobalizeCommonFail) + internalErrorStatus.SetMessage(st.(error).Error()) // type cast never panics because IsSuccessful() checks cast + + return internalErrorStatus +} + +func errMessageStatusV2(code any, msg string) string { + const ( + noMsgFmt = "status: code = %v" + msgFmt = noMsgFmt + " message = %s" + ) + + if msg != "" { + return fmt.Sprintf(msgFmt, code, msg) + } + + return fmt.Sprintf(noMsgFmt, code) +} + +func newStatusV2WithLocalCode(code status.Code, globalizer func(*status.Code)) *status.Status { + var st status.Status + + st.SetCode(globalizeCodeV2(code, globalizer)) + + return &st +} + +func globalizeCodeV2(code status.Code, globalizer func(*status.Code)) status.Code { + globalizer(&code) + return code +} diff --git a/pkg/sdk/client/status/v2_test.go b/pkg/sdk/client/status/v2_test.go new file mode 100644 index 000000000..f7bf0f91a --- /dev/null +++ b/pkg/sdk/client/status/v2_test.go @@ -0,0 +1,315 @@ +package apistatus_test + +import ( + "errors" + "testing" + + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + "github.com/stretchr/testify/require" +) + +func TestToStatusV2(t *testing.T) { + type statusConstructor func() apistatus.Status + + for _, testItem := range [...]struct { + status any // Status or statusConstructor + codeV2 uint64 + messageV2 string + }{ + { + status: errors.New("some error"), + codeV2: 1024, + messageV2: "some error", + }, + { + status: 1, + codeV2: 0, + }, + { + status: "text", + codeV2: 0, + }, + { + status: true, + codeV2: 0, + }, + { + status: true, + codeV2: 0, + }, + { + status: nil, + codeV2: 0, + }, + { + status: (statusConstructor)(func() apistatus.Status { + var st apistatus.ServerInternal + + st.SetMessage("internal error message") + + return st + }), + codeV2: 1024, + }, + { + status: (statusConstructor)(func() apistatus.Status { + var st apistatus.WrongMagicNumber + + st.WriteCorrectMagic(322) + + return st + }), + codeV2: 1025, + }, + { + status: (statusConstructor)(func() apistatus.Status { + return new(apistatus.ObjectLocked) + }), + codeV2: 2050, + }, + { + status: (statusConstructor)(func() apistatus.Status { + return new(apistatus.LockNonRegularObject) + }), + codeV2: 2051, + }, + { + status: (statusConstructor)(func() apistatus.Status { + var st apistatus.ObjectAccessDenied + + st.WriteReason("any reason") + + return st + }), + codeV2: 2048, + }, + { + status: (statusConstructor)(func() apistatus.Status { + return new(apistatus.ObjectNotFound) + }), + codeV2: 2049, + }, + { + status: (statusConstructor)(func() apistatus.Status { + return new(apistatus.ObjectAlreadyRemoved) + }), + codeV2: 2052, + }, + { + status: (statusConstructor)(func() apistatus.Status { + return new(apistatus.ObjectOutOfRange) + }), + codeV2: 2053, + }, + { + status: (statusConstructor)(func() apistatus.Status { + return new(apistatus.ContainerNotFound) + }), + codeV2: 3072, + }, + { + status: (statusConstructor)(func() apistatus.Status { + return new(apistatus.EACLNotFound) + }), + codeV2: 3073, + }, + { + status: (statusConstructor)(func() apistatus.Status { + return new(apistatus.SessionTokenNotFound) + }), + codeV2: 4096, + }, + { + status: (statusConstructor)(func() apistatus.Status { + return new(apistatus.SessionTokenExpired) + }), + codeV2: 4097, + }, + { + status: (statusConstructor)(func() apistatus.Status { + return new(apistatus.NodeUnderMaintenance) + }), + codeV2: 1027, + }, + } { + var st apistatus.Status + + if cons, ok := testItem.status.(statusConstructor); ok { + st = cons() + } else { + st = testItem.status + } + + stv2 := apistatus.ToStatusV2(st) + + // must generate the same status.Status message + require.EqualValues(t, testItem.codeV2, stv2.Code()) + if len(testItem.messageV2) > 0 { + require.Equal(t, testItem.messageV2, stv2.Message()) + } + + _, ok := st.(apistatus.StatusV2) + if ok { + // restore and convert again + restored := apistatus.FromStatusV2(stv2) + + res := apistatus.ToStatusV2(restored) + + // must generate the same status.Status message + require.Equal(t, stv2, res) + } + } +} + +func TestFromStatusV2(t *testing.T) { + type statusConstructor func() apistatus.Status + + for _, testItem := range [...]struct { + status any // Status or statusConstructor + codeV2 uint64 + messageV2 string + }{ + { + status: errors.New("some error"), + codeV2: 1024, + messageV2: "some error", + }, + { + status: 1, + codeV2: 0, + }, + { + status: "text", + codeV2: 0, + }, + { + status: true, + codeV2: 0, + }, + { + status: true, + codeV2: 0, + }, + { + status: nil, + codeV2: 0, + }, + { + status: (statusConstructor)(func() apistatus.Status { + var st apistatus.ServerInternal + + st.SetMessage("internal error message") + + return st + }), + codeV2: 1024, + }, + { + status: (statusConstructor)(func() apistatus.Status { + var st apistatus.WrongMagicNumber + + st.WriteCorrectMagic(322) + + return st + }), + codeV2: 1025, + }, + { + status: (statusConstructor)(func() apistatus.Status { + return new(apistatus.ObjectLocked) + }), + codeV2: 2050, + }, + { + status: (statusConstructor)(func() apistatus.Status { + return new(apistatus.LockNonRegularObject) + }), + codeV2: 2051, + }, + { + status: (statusConstructor)(func() apistatus.Status { + var st apistatus.ObjectAccessDenied + + st.WriteReason("any reason") + + return st + }), + codeV2: 2048, + }, + { + status: (statusConstructor)(func() apistatus.Status { + return new(apistatus.ObjectNotFound) + }), + codeV2: 2049, + }, + { + status: (statusConstructor)(func() apistatus.Status { + return new(apistatus.ObjectAlreadyRemoved) + }), + codeV2: 2052, + }, + { + status: statusConstructor(func() apistatus.Status { + return new(apistatus.ObjectOutOfRange) + }), + codeV2: 2053, + }, + { + status: (statusConstructor)(func() apistatus.Status { + return new(apistatus.ContainerNotFound) + }), + codeV2: 3072, + }, + { + status: (statusConstructor)(func() apistatus.Status { + return new(apistatus.EACLNotFound) + }), + codeV2: 3073, + }, + { + status: (statusConstructor)(func() apistatus.Status { + return new(apistatus.SessionTokenNotFound) + }), + codeV2: 4096, + }, + { + status: (statusConstructor)(func() apistatus.Status { + return new(apistatus.SessionTokenExpired) + }), + codeV2: 4097, + }, + { + status: (statusConstructor)(func() apistatus.Status { + return new(apistatus.NodeUnderMaintenance) + }), + codeV2: 1027, + }, + } { + var st apistatus.Status + + if cons, ok := testItem.status.(statusConstructor); ok { + st = cons() + } else { + st = testItem.status + } + + stv2 := apistatus.ToStatusV2(st) + + // must generate the same status.Status message + require.EqualValues(t, testItem.codeV2, stv2.Code()) + if len(testItem.messageV2) > 0 { + require.Equal(t, testItem.messageV2, stv2.Message()) + } + + _, ok := st.(apistatus.StatusV2) + if ok { + // restore and convert again + restored := apistatus.FromStatusV2(stv2) + + res := apistatus.ToStatusV2(restored) + + // must generate the same status.Status message + require.Equal(t, stv2, res) + } + } +} diff --git a/pkg/sdk/container/acl/acl.go b/pkg/sdk/container/acl/acl.go new file mode 100644 index 000000000..eedec575e --- /dev/null +++ b/pkg/sdk/container/acl/acl.go @@ -0,0 +1,83 @@ +package acl + +import "strconv" + +// Op enumerates operations under access control inside container. +// Non-positive values are reserved and depend on context (e.g. unsupported op). +// +// Note that type conversion from- and to numerical types is not recommended, +// use corresponding constants and/or methods instead. +type Op uint32 + +// nolint: unused +const ( + opZero Op = iota // extreme value for testing + + OpObjectGet // Object.Get rpc + OpObjectHead // Object.Head rpc + OpObjectPut // Object.Put rpc + OpObjectDelete // Object.Delete rpc + OpObjectSearch // Object.Search rpc + OpObjectRange // Object.GetRange rpc + OpObjectHash // Object.GetRangeHash rpc + + opLast // extreme value for testing +) + +// String implements fmt.Stringer. +func (x Op) String() string { + switch x { + default: + return "UNKNOWN#" + strconv.FormatUint(uint64(x), 10) + case OpObjectGet: + return "OBJECT_GET" + case OpObjectHead: + return "OBJECT_HEAD" + case OpObjectPut: + return "OBJECT_PUT" + case OpObjectDelete: + return "OBJECT_DELETE" + case OpObjectSearch: + return "OBJECT_SEARCH" + case OpObjectRange: + return "OBJECT_RANGE" + case OpObjectHash: + return "OBJECT_HASH" + } +} + +// Role enumerates roles covered by container ACL. Each role represents +// some party which can be authenticated during container op execution. +// Non-positive values are reserved and depend on context (e.g. unsupported role). +// +// Note that type conversion from- and to numerical types is not recommended, +// use corresponding constants and/or methods instead. +type Role uint32 + +// nolint: unused +const ( + roleZero Role = iota // extreme value for testing + + RoleOwner // container owner + RoleContainer // nodes of the related container + RoleInnerRing // Inner Ring nodes + RoleOthers // all others + + roleLast // extreme value for testing +) + +// String implements fmt.Stringer. +func (x Role) String() string { + switch x { + default: + return "UNKNOWN#" + strconv.FormatUint(uint64(x), 10) + case RoleOwner: + return "OWNER" + case RoleContainer: + return "CONTAINER" + case RoleInnerRing: + return "INNER_RING" + case RoleOthers: + return "OTHERS" + } +} diff --git a/pkg/sdk/container/acl/acl_basic.go b/pkg/sdk/container/acl/acl_basic.go new file mode 100644 index 000000000..7c9ffcce2 --- /dev/null +++ b/pkg/sdk/container/acl/acl_basic.go @@ -0,0 +1,283 @@ +package acl + +import ( + "fmt" + "strconv" + "strings" +) + +// Basic represents basic part of the FrostFS container's ACL. It includes +// common (pretty simple) access rules for operations inside the container. +// See FrostFS Specification for details. +// +// One can find some similarities with the traditional Unix permission, such as +// +// division into scopes: user, group, others +// op-permissions: read, write, etc. +// sticky bit +// +// However, these similarities should only be used for better understanding, +// in general these mechanisms are different. +// +// Instances can be created using built-in var declaration, but look carefully +// at the default values, and how individual permissions are regulated. +// Some frequently used values are presented in exported variables. +// +// Basic instances are comparable: values can be compared directly using +// == operator. +// +// Note that type conversion from- and to numerical types is not recommended, +// use corresponding constants and/or methods instead. +type Basic uint32 + +// FromBits decodes Basic from the numerical representation. +// +// See also Bits. +func (x *Basic) FromBits(bits uint32) { + *x = Basic(bits) +} + +// Bits returns numerical encoding of Basic. +// +// See also FromBits. +func (x Basic) Bits() uint32 { + return uint32(x) +} + +// common bit sections. +const ( + opAmount = 7 + bitsPerOp = 4 + + bitPosFinal = opAmount * bitsPerOp + bitPosSticky = bitPosFinal + 1 +) + +// per-op bit order. +const ( + opBitPosBearer uint8 = iota + opBitPosOthers + opBitPosContainer + opBitPosOwner +) + +// DisableExtension makes Basic FINAL. FINAL indicates the ACL non-extendability +// in the related container. +// +// See also Extendable. +func (x *Basic) DisableExtension() { + setBit((*uint32)(x), bitPosFinal) +} + +// Extendable checks if Basic is NOT made FINAL using DisableExtension. +// +// Zero Basic is extendable. +func (x Basic) Extendable() bool { + return !isBitSet(uint32(x), bitPosFinal) +} + +// MakeSticky makes Basic STICKY. STICKY indicates that only the owner of any +// particular object is allowed to operate on it. +// +// See also Sticky. +func (x *Basic) MakeSticky() { + setBit((*uint32)(x), bitPosSticky) +} + +// Sticky checks if Basic is made STICKY using MakeSticky. +// +// Zero Basic is NOT STICKY. +func (x Basic) Sticky() bool { + return isBitSet(uint32(x), bitPosSticky) +} + +// checks if op is used by the storage nodes within replication mechanism. +func isReplicationOp(op Op) bool { + switch op { + default: + return false + case + OpObjectGet, + OpObjectHead, + OpObjectPut, + OpObjectSearch, + OpObjectHash: + return true + } +} + +// AllowOp allows the parties with the given role to the given operation. +// Op MUST be one of the Op enumeration. Role MUST be one of: +// +// RoleOwner +// RoleContainer +// RoleOthers +// +// and if role is RoleContainer, op MUST NOT be: +// +// OpObjectGet +// OpObjectHead +// OpObjectPut +// OpObjectSearch +// OpObjectHash +// +// See also IsOpAllowed. +func (x *Basic) AllowOp(op Op, role Role) { + var bitPos uint8 + + switch role { + default: + panic(fmt.Sprintf("unable to set rules for unsupported role %v", role)) + case RoleInnerRing: + panic("basic ACL MUST NOT be modified for Inner Ring") + case RoleOwner: + bitPos = opBitPosOwner + case RoleContainer: + if isReplicationOp(op) { + panic("basic ACL for container replication ops MUST NOT be modified") + } + + bitPos = opBitPosContainer + case RoleOthers: + bitPos = opBitPosOthers + } + + setOpBit((*uint32)(x), op, bitPos) +} + +// IsOpAllowed checks if parties with the given role are allowed to the given op +// according to the Basic rules. Op MUST be one of the Op enumeration. +// Role MUST be one of the Role enumeration. +// +// Members with RoleContainer role have exclusive default access to the +// operations of the data replication mechanism: +// +// OpObjectGet +// OpObjectHead +// OpObjectPut +// OpObjectSearch +// OpObjectHash +// +// RoleInnerRing members are allowed to data audit ops only: +// +// OpObjectGet +// OpObjectHead +// OpObjectHash +// OpObjectSearch +// +// Zero Basic prevents any role from accessing any operation in the absence +// of default rights. +// +// See also AllowOp. +func (x Basic) IsOpAllowed(op Op, role Role) bool { + var bitPos uint8 + + switch role { + default: + panic(fmt.Sprintf("role is unsupported %v", role)) + case RoleInnerRing: + switch op { + case + OpObjectGet, + OpObjectHead, + OpObjectHash, + OpObjectSearch: + return true + default: + return false + } + case RoleOwner: + bitPos = opBitPosOwner + case RoleContainer: + if isReplicationOp(op) { + return true + } + + bitPos = opBitPosContainer + case RoleOthers: + bitPos = opBitPosOthers + } + + return isOpBitSet(uint32(x), op, bitPos) +} + +// AllowBearerRules allows bearer to provide extended ACL rules for the given +// operation. Bearer rules doesn't depend on container ACL extensibility. +// +// See also AllowedBearerRules. +func (x *Basic) AllowBearerRules(op Op) { + setOpBit((*uint32)(x), op, opBitPosBearer) +} + +// AllowedBearerRules checks if bearer rules are allowed using AllowBearerRules. +// Op MUST be one of the Op enumeration. +// +// Zero Basic disallows bearer rules for any op. +func (x Basic) AllowedBearerRules(op Op) bool { + return isOpBitSet(uint32(x), op, opBitPosBearer) +} + +// EncodeToString encodes Basic into hexadecimal string. +// +// See also DecodeString. +func (x Basic) EncodeToString() string { + return strconv.FormatUint(uint64(x), 16) +} + +// Names of the frequently used Basic values. +const ( + NamePrivate = "private" + NamePrivateExtended = "eacl-private" + NamePublicRO = "public-read" + NamePublicROExtended = "eacl-public-read" + NamePublicRW = "public-read-write" + NamePublicRWExtended = "eacl-public-read-write" + NamePublicAppend = "public-append" + NamePublicAppendExtended = "eacl-public-append" +) + +// Frequently used Basic values. Bitmasks are taken from the FrostFS Specification. +const ( + Private = Basic(0x1C8C8CCC) // private + PrivateExtended = Basic(0x0C8C8CCC) // eacl-private + PublicRO = Basic(0x1FBF8CFF) // public-read + PublicROExtended = Basic(0x0FBF8CFF) // eacl-public-read + PublicRW = Basic(0x1FBFBFFF) // public-read-write + PublicRWExtended = Basic(0x0FBFBFFF) // eacl-public-read-write + PublicAppend = Basic(0x1FBF9FFF) // public-append + PublicAppendExtended = Basic(0x0FBF9FFF) // eacl-public-append +) + +// DecodeString decodes string calculated using EncodeToString. Also supports +// human-readable names (Name* constants). +func (x *Basic) DecodeString(s string) (e error) { + switch s { + case NamePrivate: + *x = Private + case NamePrivateExtended: + *x = PrivateExtended + case NamePublicRO: + *x = PublicRO + case NamePublicROExtended: + *x = PublicROExtended + case NamePublicRW: + *x = PublicRW + case NamePublicRWExtended: + *x = PublicRWExtended + case NamePublicAppend: + *x = PublicAppend + case NamePublicAppendExtended: + *x = PublicAppendExtended + default: + s = strings.TrimPrefix(strings.ToLower(s), "0x") + + v, err := strconv.ParseUint(s, 16, 32) + if err != nil { + return fmt.Errorf("parse hex: %w", err) + } + + *x = Basic(v) + } + + return nil +} diff --git a/pkg/sdk/container/acl/acl_basic_test.go b/pkg/sdk/container/acl/acl_basic_test.go new file mode 100644 index 000000000..891076475 --- /dev/null +++ b/pkg/sdk/container/acl/acl_basic_test.go @@ -0,0 +1,384 @@ +package acl + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestBasic_DisableExtension(t *testing.T) { + var val, val2 Basic + + require.True(t, val.Extendable()) + val2.FromBits(val.Bits()) + require.True(t, val2.Extendable()) + + val.DisableExtension() + + require.False(t, val.Extendable()) + val2.FromBits(val.Bits()) + require.False(t, val2.Extendable()) +} + +func TestBasic_MakeSticky(t *testing.T) { + var val, val2 Basic + + require.False(t, val.Sticky()) + val2.FromBits(val.Bits()) + require.False(t, val2.Sticky()) + + val.MakeSticky() + + require.True(t, val.Sticky()) + val2.FromBits(val.Bits()) + require.True(t, val2.Sticky()) +} + +func TestBasic_AllowBearerRules(t *testing.T) { + var val Basic + + require.Panics(t, func() { val.AllowBearerRules(opZero) }) + require.Panics(t, func() { val.AllowBearerRules(opLast) }) + + require.Panics(t, func() { val.AllowedBearerRules(opZero) }) + require.Panics(t, func() { val.AllowedBearerRules(opLast) }) + + for op := opZero + 1; op < opLast; op++ { + val := val + + require.False(t, val.AllowedBearerRules(op)) + + val.AllowBearerRules(op) + + for j := opZero + 1; j < opLast; j++ { + if j == op { + require.True(t, val.AllowedBearerRules(j), op) + } else { + require.False(t, val.AllowedBearerRules(j), op) + } + } + } +} + +func TestBasic_AllowOp(t *testing.T) { + var val, val2 Basic + + require.Panics(t, func() { val.IsOpAllowed(opZero, roleZero+1) }) + require.Panics(t, func() { val.IsOpAllowed(opLast, roleZero+1) }) + require.Panics(t, func() { val.IsOpAllowed(opZero+1, roleZero) }) + require.Panics(t, func() { val.IsOpAllowed(opZero+1, roleLast) }) + + for op := opZero + 1; op < opLast; op++ { + require.Panics(t, func() { val.AllowOp(op, RoleInnerRing) }) + + if isReplicationOp(op) { + require.Panics(t, func() { val.AllowOp(op, RoleContainer) }) + require.True(t, val.IsOpAllowed(op, RoleContainer)) + } + } + + require.True(t, val.IsOpAllowed(OpObjectGet, RoleInnerRing)) + require.True(t, val.IsOpAllowed(OpObjectHead, RoleInnerRing)) + require.True(t, val.IsOpAllowed(OpObjectSearch, RoleInnerRing)) + require.True(t, val.IsOpAllowed(OpObjectHash, RoleInnerRing)) + + const op = opZero + 1 + const role = RoleOthers + + require.False(t, val.IsOpAllowed(op, role)) + val2.FromBits(val.Bits()) + require.False(t, val2.IsOpAllowed(op, role)) + + val.AllowOp(op, role) + + require.True(t, val.IsOpAllowed(op, role)) + val2.FromBits(val.Bits()) + require.True(t, val2.IsOpAllowed(op, role)) +} + +type opsExpected struct { + owner, container, innerRing, others, bearer bool +} + +func testOp(t *testing.T, v Basic, op Op, exp opsExpected) { + require.Equal(t, exp.owner, v.IsOpAllowed(op, RoleOwner), op) + require.Equal(t, exp.container, v.IsOpAllowed(op, RoleContainer), op) + require.Equal(t, exp.innerRing, v.IsOpAllowed(op, RoleInnerRing), op) + require.Equal(t, exp.others, v.IsOpAllowed(op, RoleOthers), op) + require.Equal(t, exp.bearer, v.AllowedBearerRules(op), op) +} + +type expected struct { + extendable, sticky bool + + mOps map[Op]opsExpected +} + +func testBasicPredefined(t *testing.T, val Basic, name string, exp expected) { + require.Equal(t, exp.sticky, val.Sticky()) + require.Equal(t, exp.extendable, val.Extendable()) + + for op, exp := range exp.mOps { + testOp(t, val, op, exp) + } + + s := val.EncodeToString() + + var val2 Basic + + require.NoError(t, val2.DecodeString(s)) + require.Equal(t, val, val2) + + require.NoError(t, val2.DecodeString(name)) + require.Equal(t, val, val2) +} + +func TestBasicPredefined(t *testing.T) { + t.Run("private", func(t *testing.T) { + exp := expected{ + extendable: false, + sticky: false, + mOps: map[Op]opsExpected{ + OpObjectHash: { + owner: true, + container: true, + innerRing: true, + others: false, + bearer: false, + }, + OpObjectRange: { + owner: true, + container: false, + innerRing: false, + others: false, + bearer: false, + }, + OpObjectSearch: { + owner: true, + container: true, + innerRing: true, + others: false, + bearer: false, + }, + OpObjectDelete: { + owner: true, + container: false, + innerRing: false, + others: false, + bearer: false, + }, + OpObjectPut: { + owner: true, + container: true, + innerRing: false, + others: false, + bearer: false, + }, + OpObjectHead: { + owner: true, + container: true, + innerRing: true, + others: false, + bearer: false, + }, + OpObjectGet: { + owner: true, + container: true, + innerRing: true, + others: false, + bearer: false, + }, + }, + } + + testBasicPredefined(t, Private, NamePrivate, exp) + exp.extendable = true + testBasicPredefined(t, PrivateExtended, NamePrivateExtended, exp) + }) + + t.Run("public-read", func(t *testing.T) { + exp := expected{ + extendable: false, + sticky: false, + mOps: map[Op]opsExpected{ + OpObjectHash: { + owner: true, + container: true, + innerRing: true, + others: true, + bearer: true, + }, + OpObjectRange: { + owner: true, + container: false, + innerRing: false, + others: true, + bearer: true, + }, + OpObjectSearch: { + owner: true, + container: true, + innerRing: true, + others: true, + bearer: true, + }, + OpObjectDelete: { + owner: true, + container: false, + innerRing: false, + others: false, + bearer: false, + }, + OpObjectPut: { + owner: true, + container: true, + innerRing: false, + others: false, + bearer: false, + }, + OpObjectHead: { + owner: true, + container: true, + innerRing: true, + others: true, + bearer: true, + }, + OpObjectGet: { + owner: true, + container: true, + innerRing: true, + others: true, + bearer: true, + }, + }, + } + + testBasicPredefined(t, PublicRO, NamePublicRO, exp) + exp.extendable = true + testBasicPredefined(t, PublicROExtended, NamePublicROExtended, exp) + }) + + t.Run("public-read-write", func(t *testing.T) { + exp := expected{ + extendable: false, + sticky: false, + mOps: map[Op]opsExpected{ + OpObjectHash: { + owner: true, + container: true, + innerRing: true, + others: true, + bearer: true, + }, + OpObjectRange: { + owner: true, + container: false, + innerRing: false, + others: true, + bearer: true, + }, + OpObjectSearch: { + owner: true, + container: true, + innerRing: true, + others: true, + bearer: true, + }, + OpObjectDelete: { + owner: true, + container: false, + innerRing: false, + others: true, + bearer: true, + }, + OpObjectPut: { + owner: true, + container: true, + innerRing: false, + others: true, + bearer: true, + }, + OpObjectHead: { + owner: true, + container: true, + innerRing: true, + others: true, + bearer: true, + }, + OpObjectGet: { + owner: true, + container: true, + innerRing: true, + others: true, + bearer: true, + }, + }, + } + + testBasicPredefined(t, PublicRW, NamePublicRW, exp) + exp.extendable = true + testBasicPredefined(t, PublicRWExtended, NamePublicRWExtended, exp) + }) + + t.Run("public-append", func(t *testing.T) { + exp := expected{ + extendable: false, + sticky: false, + mOps: map[Op]opsExpected{ + OpObjectHash: { + owner: true, + container: true, + innerRing: true, + others: true, + bearer: true, + }, + OpObjectRange: { + owner: true, + container: false, + innerRing: false, + others: true, + bearer: true, + }, + OpObjectSearch: { + owner: true, + container: true, + innerRing: true, + others: true, + bearer: true, + }, + OpObjectDelete: { + owner: true, + container: false, + innerRing: false, + others: false, + bearer: true, + }, + OpObjectPut: { + owner: true, + container: true, + innerRing: false, + others: true, + bearer: true, + }, + OpObjectHead: { + owner: true, + container: true, + innerRing: true, + others: true, + bearer: true, + }, + OpObjectGet: { + owner: true, + container: true, + innerRing: true, + others: true, + bearer: true, + }, + }, + } + + testBasicPredefined(t, PublicAppend, NamePublicAppend, exp) + exp.extendable = true + testBasicPredefined(t, PublicAppendExtended, NamePublicAppendExtended, exp) + }) +} diff --git a/pkg/sdk/container/acl/doc.go b/pkg/sdk/container/acl/doc.go new file mode 100644 index 000000000..3683e6d21 --- /dev/null +++ b/pkg/sdk/container/acl/doc.go @@ -0,0 +1,8 @@ +/* +Package acl provides functionality to control access to data and operations on them in FrostFS containers. + +Type Basic represents basic ACL of the FrostFS container which specifies the general order of data access. +Basic provides interface of rule composition. Package acl also exports some frequently used settings like +private or public. +*/ +package acl diff --git a/pkg/sdk/container/acl/init.go b/pkg/sdk/container/acl/init.go new file mode 100644 index 000000000..9a0531349 --- /dev/null +++ b/pkg/sdk/container/acl/init.go @@ -0,0 +1,20 @@ +package acl + +func init() { + // left-to-right order of the object operations + orderedOps := [...]Op{ + OpObjectGet, + OpObjectHead, + OpObjectPut, + OpObjectDelete, + OpObjectSearch, + OpObjectRange, + OpObjectHash, + } + + mOrder = make(map[Op]uint8, len(orderedOps)) + + for i := range orderedOps { + mOrder[orderedOps[i]] = uint8(i) + } +} diff --git a/pkg/sdk/container/acl/util.go b/pkg/sdk/container/acl/util.go new file mode 100644 index 000000000..d4e5877e6 --- /dev/null +++ b/pkg/sdk/container/acl/util.go @@ -0,0 +1,37 @@ +package acl + +import "fmt" + +// sets n-th bit in num (starting at 0). +func setBit(num *uint32, n uint8) { + *num |= 1 << n +} + +// checks if n-th bit in num is set (starting at 0). +func isBitSet(num uint32, n uint8) bool { + mask := uint32(1 << n) + return mask != 0 && num&mask == mask +} + +// maps Op to op-section index in Basic. Filled on init. +var mOrder map[Op]uint8 + +// sets n-th bit in num for the given op. Panics if op is unsupported. +func setOpBit(num *uint32, op Op, opBitPos uint8) { + n, ok := mOrder[op] + if !ok { + panic(fmt.Sprintf("op is unsupported %v", op)) + } + + setBit(num, n*bitsPerOp+opBitPos) +} + +// checks if n-th bit in num for the given op is set. Panics if op is unsupported. +func isOpBitSet(num uint32, op Op, n uint8) bool { + off, ok := mOrder[op] + if !ok { + panic(fmt.Sprintf("op is unsupported %v", op)) + } + + return isBitSet(num, bitsPerOp*off+n) +} diff --git a/pkg/sdk/container/acl/util_test.go b/pkg/sdk/container/acl/util_test.go new file mode 100644 index 000000000..b0d99cc77 --- /dev/null +++ b/pkg/sdk/container/acl/util_test.go @@ -0,0 +1,130 @@ +package acl + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestBits(t *testing.T) { + num := uint32(0b10110) + + require.False(t, isBitSet(num, 0)) + require.True(t, isBitSet(num, 1)) + require.True(t, isBitSet(num, 2)) + require.False(t, isBitSet(num, 3)) + require.True(t, isBitSet(num, 4)) + require.False(t, isBitSet(num, 5)) + + setBit(&num, 3) + require.EqualValues(t, 0b11110, num) + + setBit(&num, 6) + require.EqualValues(t, 0b1011110, num) +} + +func TestOpBits(t *testing.T) { + num := uint32(0b_1001_0101_1100_0011_0110_0111_1000_1111) + + require.Panics(t, func() { isOpBitSet(num, opZero, 0) }) + require.Panics(t, func() { isOpBitSet(num, opLast, 0) }) + + cpNum := num + + require.Panics(t, func() { setOpBit(&num, opZero, 0) }) + require.EqualValues(t, cpNum, num) + require.Panics(t, func() { setOpBit(&num, opLast, 0) }) + require.EqualValues(t, cpNum, num) + + for _, tc := range []struct { + op Op + set [4]bool // is bit set (left-to-right) + bits [4]uint32 // result of setting i-th bit (left-to-right) to zero num + }{ + { + op: OpObjectHash, + set: [4]bool{false, true, false, true}, + bits: [4]uint32{ + 0b_0000_1000_0000_0000_0000_0000_0000_0000, + 0b_0000_0100_0000_0000_0000_0000_0000_0000, + 0b_0000_0010_0000_0000_0000_0000_0000_0000, + 0b_0000_0001_0000_0000_0000_0000_0000_0000, + }, + }, + { + op: OpObjectRange, + set: [4]bool{true, true, false, false}, + bits: [4]uint32{ + 0b_0000_0000_1000_0000_0000_0000_0000_0000, + 0b_0000_0000_0100_0000_0000_0000_0000_0000, + 0b_0000_0000_0010_0000_0000_0000_0000_0000, + 0b_0000_0000_0001_0000_0000_0000_0000_0000, + }, + }, + { + op: OpObjectSearch, + set: [4]bool{false, false, true, true}, + bits: [4]uint32{ + 0b_0000_0000_0000_1000_0000_0000_0000_0000, + 0b_0000_0000_0000_0100_0000_0000_0000_0000, + 0b_0000_0000_0000_0010_0000_0000_0000_0000, + 0b_0000_0000_0000_0001_0000_0000_0000_0000, + }, + }, + { + op: OpObjectDelete, + set: [4]bool{false, true, true, false}, + bits: [4]uint32{ + 0b_0000_0000_0000_0000_1000_0000_0000_0000, + 0b_0000_0000_0000_0000_0100_0000_0000_0000, + 0b_0000_0000_0000_0000_0010_0000_0000_0000, + 0b_0000_0000_0000_0000_0001_0000_0000_0000, + }, + }, + { + op: OpObjectPut, + set: [4]bool{false, true, true, true}, + bits: [4]uint32{ + 0b_0000_0000_0000_0000_0000_1000_0000_0000, + 0b_0000_0000_0000_0000_0000_0100_0000_0000, + 0b_0000_0000_0000_0000_0000_0010_0000_0000, + 0b_0000_0000_0000_0000_0000_0001_0000_0000, + }, + }, + { + op: OpObjectHead, + set: [4]bool{true, false, false, false}, + bits: [4]uint32{ + 0b_0000_0000_0000_0000_0000_0000_1000_0000, + 0b_0000_0000_0000_0000_0000_0000_0100_0000, + 0b_0000_0000_0000_0000_0000_0000_0010_0000, + 0b_0000_0000_0000_0000_0000_0000_0001_0000, + }, + }, + { + op: OpObjectGet, + set: [4]bool{true, true, true, true}, + bits: [4]uint32{ + 0b_0000_0000_0000_0000_0000_0000_0000_1000, + 0b_0000_0000_0000_0000_0000_0000_0000_0100, + 0b_0000_0000_0000_0000_0000_0000_0000_0010, + 0b_0000_0000_0000_0000_0000_0000_0000_0001, + }, + }, + } { + for i := range tc.set { + require.EqualValues(t, tc.set[i], isOpBitSet(num, tc.op, uint8(len(tc.set)-1-i)), + fmt.Sprintf("op %s, left bit #%d", tc.op, i), + ) + } + + for i := range tc.bits { + num := uint32(0) + + setOpBit(&num, tc.op, uint8(len(tc.bits)-1-i)) + + require.EqualValues(t, tc.bits[i], num) + } + } +} diff --git a/pkg/sdk/container/container.go b/pkg/sdk/container/container.go new file mode 100644 index 000000000..40056dea1 --- /dev/null +++ b/pkg/sdk/container/container.go @@ -0,0 +1,521 @@ +package container + +import ( + "crypto/ecdsa" + "crypto/sha256" + "errors" + "fmt" + "strconv" + "strings" + "time" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/container" + v2netmap "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/acl" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/crypto" + frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/crypto/ecdsa" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/version" + "github.com/google/uuid" +) + +// Container represents descriptor of the FrostFS container. Container logically +// stores FrostFS objects. Container is one of the basic and at the same time +// necessary data storage units in the FrostFS. Container includes data about the +// owner, rules for placing objects and other information necessary for the +// system functioning. +// +// Container type instances can represent different container states in the +// system, depending on the context. To create new container in FrostFS zero +// instance SHOULD be declared, initialized using Init method and filled using +// dedicated methods. Once container is saved in the FrostFS network, it can't be +// changed: containers stored in the system are immutable, and FrostFS is a CAS +// of containers that are identified by a fixed length value (see cid.ID type). +// Instances for existing containers can be initialized using decoding methods +// (e.g Unmarshal). +// +// Container is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/container.Container +// message. See ReadFromV2 / WriteToV2 methods. +type Container struct { + v2 container.Container +} + +const ( + attributeName = "Name" + attributeTimestamp = "Timestamp" +) + +// reads Container from the container.Container message. If checkFieldPresence is set, +// returns an error on absence of any protocol-required field. +func (x *Container) readFromV2(m container.Container, checkFieldPresence bool) error { + var err error + + ownerV2 := m.GetOwnerID() + if ownerV2 != nil { + var owner user.ID + + err = owner.ReadFromV2(*ownerV2) + if err != nil { + return fmt.Errorf("invalid owner: %w", err) + } + } else if checkFieldPresence { + return errors.New("missing owner") + } + + binNonce := m.GetNonce() + if len(binNonce) > 0 { + var nonce uuid.UUID + + err = nonce.UnmarshalBinary(binNonce) + if err != nil { + return fmt.Errorf("invalid nonce: %w", err) + } else if ver := nonce.Version(); ver != 4 { + return fmt.Errorf("invalid nonce UUID version %d", ver) + } + } else if checkFieldPresence { + return errors.New("missing nonce") + } + + ver := m.GetVersion() + if checkFieldPresence && ver == nil { + return errors.New("missing version") + } + + policyV2 := m.GetPlacementPolicy() + if policyV2 != nil { + var policy netmap.PlacementPolicy + + err = policy.ReadFromV2(*policyV2) + if err != nil { + return fmt.Errorf("invalid placement policy: %w", err) + } + } else if checkFieldPresence { + return errors.New("missing placement policy") + } + + if err := checkAttributes(m); err != nil { + return err + } + + x.v2 = m + + return nil +} + +func checkAttributes(m container.Container) error { + attrs := m.GetAttributes() + mAttr := make(map[string]struct{}, len(attrs)) + var key, val string + var was bool + + for i := range attrs { + key = attrs[i].GetKey() + if key == "" { + return errors.New("empty attribute key") + } + + _, was = mAttr[key] + if was { + return fmt.Errorf("duplicated attribute %s", key) + } + + val = attrs[i].GetValue() + if val == "" { + return fmt.Errorf("empty attribute value %s", key) + } + + var err error + if key == attributeTimestamp { + _, err = strconv.ParseInt(val, 10, 64) + } + + if err != nil { + return fmt.Errorf("invalid attribute value %s: %s (%w)", key, val, err) + } + + mAttr[key] = struct{}{} + } + return nil +} + +// ReadFromV2 reads Container from the container.Container message. Checks if the +// message conforms to FrostFS API V2 protocol. +// +// See also WriteToV2. +func (x *Container) ReadFromV2(m container.Container) error { + return x.readFromV2(m, true) +} + +// WriteToV2 writes Container into the container.Container message. +// The message MUST NOT be nil. +// +// See also ReadFromV2. +func (x Container) WriteToV2(m *container.Container) { + *m = x.v2 +} + +// Marshal encodes Container into a binary format of the FrostFS API protocol +// (Protocol Buffers with direct field order). +// +// See also Unmarshal. +func (x Container) Marshal() []byte { + return x.v2.StableMarshal(nil) +} + +// Unmarshal decodes FrostFS API protocol binary format into the Container +// (Protocol Buffers with direct field order). Returns an error describing +// a format violation. +// +// See also Marshal. +func (x *Container) Unmarshal(data []byte) error { + var m container.Container + + err := m.Unmarshal(data) + if err != nil { + return err + } + + return x.readFromV2(m, false) +} + +// MarshalJSON encodes Container into a JSON format of the FrostFS API protocol +// (Protocol Buffers JSON). +// +// See also UnmarshalJSON. +func (x Container) MarshalJSON() ([]byte, error) { + return x.v2.MarshalJSON() +} + +// UnmarshalJSON decodes FrostFS API protocol JSON format into the Container +// (Protocol Buffers JSON). Returns an error describing a format violation. +// +// See also MarshalJSON. +func (x *Container) UnmarshalJSON(data []byte) error { + return x.v2.UnmarshalJSON(data) +} + +// Init initializes all internal data of the Container required by FrostFS API +// protocol. Init MUST be called when creating a new container. Init SHOULD NOT +// be called multiple times. Init SHOULD NOT be called if the Container instance +// is used for decoding only. +func (x *Container) Init() { + var ver refs.Version + version.Current().WriteToV2(&ver) + + x.v2.SetVersion(&ver) + + nonce, err := uuid.New().MarshalBinary() + if err != nil { + panic(fmt.Sprintf("unexpected error from UUID.MarshalBinary: %v", err)) + } + + x.v2.SetNonce(nonce) +} + +// SetOwner specifies the owner of the Container. Each Container has exactly +// one owner, so SetOwner MUST be called for instances to be saved in the +// FrostFS. +// +// See also Owner. +func (x *Container) SetOwner(owner user.ID) { + var m refs.OwnerID + owner.WriteToV2(&m) + + x.v2.SetOwnerID(&m) +} + +// Owner returns owner of the Container set using SetOwner. +// +// Zero Container has no owner which is incorrect according to FrostFS API +// protocol. +func (x Container) Owner() (res user.ID) { + m := x.v2.GetOwnerID() + if m != nil { + err := res.ReadFromV2(*m) + if err != nil { + panic(fmt.Sprintf("unexpected error from user.ID.ReadFromV2: %v", err)) + } + } + + return +} + +// SetBasicACL specifies basic part of the Container ACL. Basic ACL is used +// to control access inside container storage. +// +// See also BasicACL. +func (x *Container) SetBasicACL(basicACL acl.Basic) { + x.v2.SetBasicACL(basicACL.Bits()) +} + +// BasicACL returns basic ACL set using SetBasicACL. +// +// Zero Container has zero basic ACL which structurally correct but doesn't +// make sense since it denies any access to any party. +func (x Container) BasicACL() (res acl.Basic) { + res.FromBits(x.v2.GetBasicACL()) + return +} + +// SetPlacementPolicy sets placement policy for the objects within the Container. +// FrostFS storage layer strives to follow the specified policy. +// +// See also PlacementPolicy. +func (x *Container) SetPlacementPolicy(policy netmap.PlacementPolicy) { + var m v2netmap.PlacementPolicy + policy.WriteToV2(&m) + + x.v2.SetPlacementPolicy(&m) +} + +// PlacementPolicy returns placement policy set using SetPlacementPolicy. +// +// Zero Container has no placement policy which is incorrect according to +// FrostFS API protocol. +func (x Container) PlacementPolicy() (res netmap.PlacementPolicy) { + m := x.v2.GetPlacementPolicy() + if m != nil { + err := res.ReadFromV2(*m) + if err != nil { + panic(fmt.Sprintf("unexpected error from PlacementPolicy.ReadFromV2: %v", err)) + } + } + + return +} + +// SetAttribute sets Container attribute value by key. Both key and value +// MUST NOT be empty. Attributes set by the creator (owner) are most commonly +// ignored by the FrostFS system and used for application layer. Some attributes +// are so-called system or well-known attributes: they are reserved for system +// needs. System attributes SHOULD NOT be modified using SetAttribute, use +// corresponding methods/functions. List of the reserved keys is documented +// in the particular protocol version. +// +// SetAttribute overwrites existing attribute value. +// +// See also Attribute, IterateAttributes, IterateUserAttributes. +func (x *Container) SetAttribute(key, value string) { + if key == "" { + panic("empty attribute key") + } else if value == "" { + panic("empty attribute value") + } + + attrs := x.v2.GetAttributes() + ln := len(attrs) + + for i := 0; i < ln; i++ { + if attrs[i].GetKey() == key { + attrs[i].SetValue(value) + return + } + } + + attrs = append(attrs, container.Attribute{}) + attrs[ln].SetKey(key) + attrs[ln].SetValue(value) + + x.v2.SetAttributes(attrs) +} + +// Attribute reads value of the Container attribute by key. Empty result means +// attribute absence. +// +// See also SetAttribute, IterateAttributes, IterateUserAttributes. +func (x Container) Attribute(key string) string { + attrs := x.v2.GetAttributes() + for i := range attrs { + if attrs[i].GetKey() == key { + return attrs[i].GetValue() + } + } + + return "" +} + +// IterateAttributes iterates over all Container attributes and passes them +// into f. The handler MUST NOT be nil. +// +// See also SetAttribute, Attribute. +func (x Container) IterateAttributes(f func(key, val string)) { + attrs := x.v2.GetAttributes() + for i := range attrs { + f(attrs[i].GetKey(), attrs[i].GetValue()) + } +} + +// IterateUserAttributes iterates over user Container attributes and passes them +// into f. The handler MUST NOT be nil. +// +// See also SetAttribute, Attribute. +func (x Container) IterateUserAttributes(f func(key, val string)) { + attrs := x.v2.GetAttributes() + for _, attr := range attrs { + key := attr.GetKey() + if !strings.HasPrefix(key, container.SysAttributePrefix) && + !strings.HasPrefix(key, container.SysAttributePrefixNeoFS) { + f(key, attr.GetValue()) + } + } +} + +// SetName sets human-readable name of the Container. Name MUST NOT be empty. +// +// See also Name. +func SetName(cnr *Container, name string) { + cnr.SetAttribute(attributeName, name) +} + +// Name returns container name set using SetName. +// +// Zero Container has no name. +func Name(cnr Container) string { + return cnr.Attribute(attributeName) +} + +// SetCreationTime writes container's creation time in Unix Timestamp format. +// +// See also CreatedAt. +func SetCreationTime(cnr *Container, t time.Time) { + cnr.SetAttribute(attributeTimestamp, strconv.FormatInt(t.Unix(), 10)) +} + +// CreatedAt returns container's creation time set using SetCreationTime. +// +// Zero Container has zero timestamp (in seconds). +func CreatedAt(cnr Container) time.Time { + var sec int64 + + attr := cnr.Attribute(attributeTimestamp) + if attr != "" { + var err error + + sec, err = strconv.ParseInt(cnr.Attribute(attributeTimestamp), 10, 64) + if err != nil { + panic(fmt.Sprintf("parse container timestamp: %v", err)) + } + } + + return time.Unix(sec, 0) +} + +const attributeHomoHashEnabled = "true" + +// DisableHomomorphicHashing sets flag to disable homomorphic hashing of the +// Container data. +// +// See also IsHomomorphicHashingDisabled. +func DisableHomomorphicHashing(cnr *Container) { + cnr.SetAttribute(container.SysAttributeHomomorphicHashing, attributeHomoHashEnabled) +} + +// IsHomomorphicHashingDisabled checks if DisableHomomorphicHashing was called. +// +// Zero Container has enabled hashing. +func IsHomomorphicHashingDisabled(cnr Container) bool { + return cnr.Attribute(container.SysAttributeHomomorphicHashing) == attributeHomoHashEnabled || + cnr.Attribute(container.SysAttributeHomomorphicHashingNeoFS) == attributeHomoHashEnabled +} + +// Domain represents information about container domain registered in the NNS +// contract deployed in the FrostFS network. +type Domain struct { + name, zone string +} + +// SetName sets human-friendly container domain name. +func (x *Domain) SetName(name string) { + x.name = name +} + +// Name returns name set using SetName. +// +// Zero Domain has zero name. +func (x Domain) Name() string { + return x.name +} + +// SetZone sets zone which is used as a TLD of a domain name in NNS contract. +func (x *Domain) SetZone(zone string) { + x.zone = zone +} + +// Zone returns domain zone set using SetZone. +// +// Zero Domain has "container" zone. +func (x Domain) Zone() string { + if x.zone != "" { + return x.zone + } + + return "container" +} + +// WriteDomain writes Domain into the Container. Name MUST NOT be empty. +func WriteDomain(cnr *Container, domain Domain) { + cnr.SetAttribute(container.SysAttributeName, domain.Name()) + cnr.SetAttribute(container.SysAttributeZone, domain.Zone()) +} + +// ReadDomain reads Domain from the Container. Returns value with empty name +// if domain is not specified. +func ReadDomain(cnr Container) (res Domain) { + if name := cnr.Attribute(container.SysAttributeName); name != "" { + res.SetName(name) + res.SetZone(cnr.Attribute(container.SysAttributeZone)) + } else if name = cnr.Attribute(container.SysAttributeNameNeoFS); name != "" { + res.SetName(name) + res.SetZone(cnr.Attribute(container.SysAttributeZoneNeoFS)) + } + + return +} + +// CalculateSignature calculates signature of the Container using provided signer +// and writes it into dst. Signature instance MUST NOT be nil. CalculateSignature +// is expected to be called after all the Container data is filled and before +// saving the Container in the FrostFS network. Note that мany subsequent change +// will most likely break the signature. +// +// See also VerifySignature. +func CalculateSignature(dst *frostfscrypto.Signature, cnr Container, signer ecdsa.PrivateKey) error { + return dst.Calculate(frostfsecdsa.SignerRFC6979(signer), cnr.Marshal()) +} + +// VerifySignature verifies Container signature calculated using CalculateSignature. +// Result means signature correctness. +func VerifySignature(sig frostfscrypto.Signature, cnr Container) bool { + return sig.Verify(cnr.Marshal()) +} + +// CalculateIDFromBinary calculates identifier of the binary-encoded container +// in CAS of the FrostFS containers and writes it into dst. ID instance MUST NOT +// be nil. +// +// See also CalculateID, AssertID. +func CalculateIDFromBinary(dst *cid.ID, cnr []byte) { + dst.SetSHA256(sha256.Sum256(cnr)) +} + +// CalculateID encodes the given Container and passes the result into +// CalculateIDFromBinary. +// +// See also Container.Marshal, AssertID. +func CalculateID(dst *cid.ID, cnr Container) { + CalculateIDFromBinary(dst, cnr.Marshal()) +} + +// AssertID checks if the given Container matches its identifier in CAS of the +// FrostFS containers. +// +// See also CalculateID. +func AssertID(id cid.ID, cnr Container) bool { + var id2 cid.ID + CalculateID(&id2, cnr) + + return id2.Equals(id) +} diff --git a/pkg/sdk/container/container_test.go b/pkg/sdk/container/container_test.go new file mode 100644 index 000000000..4fae8a755 --- /dev/null +++ b/pkg/sdk/container/container_test.go @@ -0,0 +1,333 @@ +package container_test + +import ( + "crypto/sha256" + "strconv" + "testing" + "time" + + v2container "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/container" + v2netmap "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + containertest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/test" + frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/crypto" + netmaptest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap/test" + usertest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user/test" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/version" + "github.com/google/uuid" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + "github.com/stretchr/testify/require" +) + +func TestPlacementPolicyEncoding(t *testing.T) { + v := containertest.Container() + + t.Run("binary", func(t *testing.T) { + var v2 container.Container + require.NoError(t, v2.Unmarshal(v.Marshal())) + + require.Equal(t, v, v2) + }) + + t.Run("json", func(t *testing.T) { + data, err := v.MarshalJSON() + require.NoError(t, err) + + var v2 container.Container + require.NoError(t, v2.UnmarshalJSON(data)) + + require.Equal(t, v, v2) + }) +} + +func TestContainer_Init(t *testing.T) { + val := containertest.Container() + + val.Init() + + var msg v2container.Container + val.WriteToV2(&msg) + + binNonce := msg.GetNonce() + + var nonce uuid.UUID + require.NoError(t, nonce.UnmarshalBinary(binNonce)) + require.EqualValues(t, 4, nonce.Version()) + + verV2 := msg.GetVersion() + require.NotNil(t, verV2) + + var ver version.Version + require.NoError(t, ver.ReadFromV2(*verV2)) + + require.Equal(t, version.Current(), ver) + + var val2 container.Container + require.NoError(t, val2.ReadFromV2(msg)) + + require.Equal(t, val, val2) +} + +func TestContainer_Owner(t *testing.T) { + var val container.Container + + require.Zero(t, val.Owner()) + + val = containertest.Container() + + owner := usertest.ID() + + val.SetOwner(owner) + + var msg v2container.Container + val.WriteToV2(&msg) + + var msgOwner refs.OwnerID + owner.WriteToV2(&msgOwner) + + require.Equal(t, &msgOwner, msg.GetOwnerID()) + + var val2 container.Container + require.NoError(t, val2.ReadFromV2(msg)) + + require.True(t, val2.Owner().Equals(owner)) +} + +func TestContainer_BasicACL(t *testing.T) { + var val container.Container + + require.Zero(t, val.BasicACL()) + + val = containertest.Container() + + basicACL := containertest.BasicACL() + val.SetBasicACL(basicACL) + + var msg v2container.Container + val.WriteToV2(&msg) + + require.EqualValues(t, basicACL.Bits(), msg.GetBasicACL()) + + var val2 container.Container + require.NoError(t, val2.ReadFromV2(msg)) + + require.Equal(t, basicACL, val2.BasicACL()) +} + +func TestContainer_PlacementPolicy(t *testing.T) { + var val container.Container + + require.Zero(t, val.PlacementPolicy()) + + val = containertest.Container() + + pp := netmaptest.PlacementPolicy() + val.SetPlacementPolicy(pp) + + var msgPolicy v2netmap.PlacementPolicy + pp.WriteToV2(&msgPolicy) + + var msg v2container.Container + val.WriteToV2(&msg) + + require.Equal(t, &msgPolicy, msg.GetPlacementPolicy()) + + var val2 container.Container + require.NoError(t, val2.ReadFromV2(msg)) + + require.Equal(t, pp, val2.PlacementPolicy()) +} + +func assertContainsAttribute(t *testing.T, m v2container.Container, key, val string) { + var msgAttr v2container.Attribute + + msgAttr.SetKey(key) + msgAttr.SetValue(val) + require.Contains(t, m.GetAttributes(), msgAttr) +} + +func TestContainer_Attribute(t *testing.T) { + const attrKey1, attrKey2 = v2container.SysAttributePrefix + "key1", v2container.SysAttributePrefixNeoFS + "key2" + const attrVal1, attrVal2 = "val1", "val2" + + val := containertest.Container() + + val.SetAttribute(attrKey1, attrVal1) + val.SetAttribute(attrKey2, attrVal2) + + var i int + val.IterateUserAttributes(func(key, val string) { + i++ + }) + require.Equal(t, 1, i) + + var msg v2container.Container + val.WriteToV2(&msg) + + require.GreaterOrEqual(t, len(msg.GetAttributes()), 2) + assertContainsAttribute(t, msg, attrKey1, attrVal1) + assertContainsAttribute(t, msg, attrKey2, attrVal2) + + var val2 container.Container + require.NoError(t, val2.ReadFromV2(msg)) + + require.Equal(t, attrVal1, val2.Attribute(attrKey1)) + require.Equal(t, attrVal2, val2.Attribute(attrKey2)) + + m := map[string]string{} + + val2.IterateAttributes(func(key, val string) { + m[key] = val + }) + + require.GreaterOrEqual(t, len(m), 2) + require.Equal(t, attrVal1, m[attrKey1]) + require.Equal(t, attrVal2, m[attrKey2]) + + val2.SetAttribute(attrKey1, attrVal1+"_") + require.Equal(t, attrVal1+"_", val2.Attribute(attrKey1)) +} + +func TestSetName(t *testing.T) { + var val container.Container + + require.Panics(t, func() { + container.SetName(&val, "") + }) + + val = containertest.Container() + + const name = "some name" + + container.SetName(&val, name) + + var msg v2container.Container + val.WriteToV2(&msg) + + assertContainsAttribute(t, msg, "Name", name) + + var val2 container.Container + require.NoError(t, val2.ReadFromV2(msg)) + + require.Equal(t, name, container.Name(val2)) +} + +func TestSetCreationTime(t *testing.T) { + var val container.Container + + require.Zero(t, container.CreatedAt(val).Unix()) + + val = containertest.Container() + + creat := time.Now() + + container.SetCreationTime(&val, creat) + + var msg v2container.Container + val.WriteToV2(&msg) + + assertContainsAttribute(t, msg, "Timestamp", strconv.FormatInt(creat.Unix(), 10)) + + var val2 container.Container + require.NoError(t, val2.ReadFromV2(msg)) + + require.Equal(t, creat.Unix(), container.CreatedAt(val2).Unix()) +} + +func TestDisableHomomorphicHashing(t *testing.T) { + var val container.Container + + require.False(t, container.IsHomomorphicHashingDisabled(val)) + + val = containertest.Container() + + container.DisableHomomorphicHashing(&val) + + var msg v2container.Container + val.WriteToV2(&msg) + + assertContainsAttribute(t, msg, v2container.SysAttributePrefix+"DISABLE_HOMOMORPHIC_HASHING", "true") + + var val2 container.Container + require.NoError(t, val2.ReadFromV2(msg)) + + require.True(t, container.IsHomomorphicHashingDisabled(val2)) +} + +func TestWriteDomain(t *testing.T) { + var val container.Container + + require.Zero(t, container.ReadDomain(val).Name()) + + val = containertest.Container() + + const name = "domain name" + + var d container.Domain + d.SetName(name) + + container.WriteDomain(&val, d) + + var msg v2container.Container + val.WriteToV2(&msg) + + assertContainsAttribute(t, msg, v2container.SysAttributeName, name) + assertContainsAttribute(t, msg, v2container.SysAttributeZone, "container") + + const zone = "domain zone" + + d.SetZone(zone) + + container.WriteDomain(&val, d) + + val.WriteToV2(&msg) + + assertContainsAttribute(t, msg, v2container.SysAttributeZone, zone) + + var val2 container.Container + require.NoError(t, val2.ReadFromV2(msg)) + + require.Equal(t, d, container.ReadDomain(val2)) +} + +func TestCalculateID(t *testing.T) { + val := containertest.Container() + + require.False(t, container.AssertID(cidtest.ID(), val)) + + var id cid.ID + container.CalculateID(&id, val) + + var msg refs.ContainerID + id.WriteToV2(&msg) + + h := sha256.Sum256(val.Marshal()) + require.Equal(t, h[:], msg.GetValue()) + + var id2 cid.ID + require.NoError(t, id2.ReadFromV2(msg)) + + require.True(t, container.AssertID(id2, val)) +} + +func TestCalculateSignature(t *testing.T) { + key, err := keys.NewPrivateKey() + require.NoError(t, err) + + val := containertest.Container() + + var sig frostfscrypto.Signature + + require.NoError(t, container.CalculateSignature(&sig, val, key.PrivateKey)) + + var msg refs.Signature + sig.WriteToV2(&msg) + + var sig2 frostfscrypto.Signature + require.NoError(t, sig2.ReadFromV2(msg)) + + require.True(t, container.VerifySignature(sig2, val)) +} diff --git a/pkg/sdk/container/doc.go b/pkg/sdk/container/doc.go new file mode 100644 index 000000000..084098b07 --- /dev/null +++ b/pkg/sdk/container/doc.go @@ -0,0 +1,49 @@ +/* +Package container provides functionality related to the FrostFS containers. + +The base type is Container. To create new container in the FrostFS network +Container instance should be initialized + + var cnr Container + cnr.Init() + // fill all the fields + + // encode cnr and send + +After the container is persisted in the FrostFS network, applications can process +it using the instance of Container types + + // recv binary container + + var cnr Container + + err := cnr.Unmarshal(bin) + // ... + + // process the container data + +Instances can be also used to process FrostFS API V2 protocol messages +(see neo.fs.v2.container package in https://git.frostfs.info/TrueCloudLab/frostfs-api). + +On client side: + + import "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/container" + + var msg container.Container + cnr.WriteToV2(&msg) + + // send msg + +On server side: + + // recv msg + + var cnr Container + cnr.ReadFromV2(msg) + + // process cnr + +Using package types in an application is recommended to potentially work with +different protocol versions with which these types are compatible. +*/ +package container diff --git a/pkg/sdk/container/id/doc.go b/pkg/sdk/container/id/doc.go new file mode 100644 index 000000000..c26c61a22 --- /dev/null +++ b/pkg/sdk/container/id/doc.go @@ -0,0 +1,7 @@ +/* +Package cid provides primitives to work with container identification in FrostFS. + +Using package types in an application is recommended to potentially work with +different protocol versions with which these types are compatible. +*/ +package cid diff --git a/pkg/sdk/container/id/id.go b/pkg/sdk/container/id/id.go new file mode 100644 index 000000000..2a04e7ef6 --- /dev/null +++ b/pkg/sdk/container/id/id.go @@ -0,0 +1,115 @@ +package cid + +import ( + "crypto/sha256" + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + "github.com/mr-tron/base58" +) + +// ID represents FrostFS container identifier. +// +// ID is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs.ContainerID +// message. See ReadFromV2 / WriteToV2 methods. +// +// Instances can be created using built-in var declaration. +// +// Note that direct typecast is not safe and may result in loss of compatibility: +// +// _ = ID([32]byte) // not recommended +type ID [sha256.Size]byte + +// ReadFromV2 reads ID from the refs.ContainerID message. +// Returns an error if the message is malformed according +// to the FrostFS API V2 protocol. +// +// See also WriteToV2. +func (id *ID) ReadFromV2(m refs.ContainerID) error { + return id.Decode(m.GetValue()) +} + +// WriteToV2 writes ID to the refs.ContainerID message. +// The message must not be nil. +// +// See also ReadFromV2. +func (id ID) WriteToV2(m *refs.ContainerID) { + m.SetValue(id[:]) +} + +// Encode encodes ID into 32 bytes of dst. Panics if +// dst length is less than 32. +// +// Zero ID is all zeros. +// +// See also Decode. +func (id ID) Encode(dst []byte) { + if l := len(dst); l < sha256.Size { + panic(fmt.Sprintf("destination length is less than %d bytes: %d", sha256.Size, l)) + } + + copy(dst, id[:]) +} + +// Decode decodes src bytes into ID. +// +// Decode expects that src has 32 bytes length. If the input is malformed, +// Decode returns an error describing format violation. In this case ID +// remains unchanged. +// +// Decode doesn't mutate src. +// +// See also Encode. +func (id *ID) Decode(src []byte) error { + if len(src) != sha256.Size { + return fmt.Errorf("invalid length %d", len(src)) + } + + copy(id[:], src) + + return nil +} + +// SetSHA256 sets container identifier value to SHA256 checksum of container structure. +func (id *ID) SetSHA256(v [sha256.Size]byte) { + copy(id[:], v[:]) +} + +// Equals defines a comparison relation between two ID instances. +// +// Note that comparison using '==' operator is not recommended since it MAY result +// in loss of compatibility. +func (id ID) Equals(id2 ID) bool { + return id == id2 +} + +// EncodeToString encodes ID into FrostFS API protocol string. +// +// Zero ID is base58 encoding of 32 zeros. +// +// See also DecodeString. +func (id ID) EncodeToString() string { + return base58.Encode(id[:]) +} + +// DecodeString decodes string into ID according to FrostFS API protocol. Returns +// an error if s is malformed. +// +// See also DecodeString. +func (id *ID) DecodeString(s string) error { + data, err := base58.Decode(s) + if err != nil { + return fmt.Errorf("decode base58: %w", err) + } + + return id.Decode(data) +} + +// String implements fmt.Stringer. +// +// String is designed to be human-readable, and its format MAY differ between +// SDK versions. String MAY return same result as EncodeToString. String MUST NOT +// be used to encode ID into FrostFS protocol string. +func (id ID) String() string { + return id.EncodeToString() +} diff --git a/pkg/sdk/container/id/id_test.go b/pkg/sdk/container/id/id_test.go new file mode 100644 index 000000000..40114603f --- /dev/null +++ b/pkg/sdk/container/id/id_test.go @@ -0,0 +1,108 @@ +package cid_test + +import ( + "crypto/rand" + "crypto/sha256" + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + "github.com/mr-tron/base58" + "github.com/stretchr/testify/require" +) + +func randSHA256Checksum() (cs [sha256.Size]byte) { + rand.Read(cs[:]) + return +} + +const emptyID = "11111111111111111111111111111111" + +func TestID_ToV2(t *testing.T) { + t.Run("non-zero", func(t *testing.T) { + checksum := randSHA256Checksum() + + id := cidtest.IDWithChecksum(checksum) + + var idV2 refs.ContainerID + id.WriteToV2(&idV2) + + var newID cid.ID + require.NoError(t, newID.ReadFromV2(idV2)) + + require.Equal(t, id, newID) + require.Equal(t, checksum[:], idV2.GetValue()) + }) + + t.Run("zero", func(t *testing.T) { + var ( + x cid.ID + v2 refs.ContainerID + ) + + x.WriteToV2(&v2) + require.Equal(t, emptyID, base58.Encode(v2.GetValue())) + }) +} + +func TestID_Equal(t *testing.T) { + cs := randSHA256Checksum() + + id1 := cidtest.IDWithChecksum(cs) + id2 := cidtest.IDWithChecksum(cs) + + require.True(t, id1.Equals(id2)) + + id3 := cidtest.ID() + + require.False(t, id1.Equals(id3)) +} + +func TestID_String(t *testing.T) { + t.Run("DecodeString/EncodeToString", func(t *testing.T) { + id := cidtest.ID() + var id2 cid.ID + + require.NoError(t, id2.DecodeString(id.EncodeToString())) + require.Equal(t, id, id2) + }) + + t.Run("zero", func(t *testing.T) { + var id cid.ID + + require.Equal(t, emptyID, id.EncodeToString()) + }) +} + +func TestNewFromV2(t *testing.T) { + t.Run("from zero", func(t *testing.T) { + var ( + x cid.ID + v2 refs.ContainerID + ) + + require.Error(t, x.ReadFromV2(v2)) + }) +} + +func TestID_Encode(t *testing.T) { + var id cid.ID + + t.Run("panic", func(t *testing.T) { + dst := make([]byte, sha256.Size-1) + + require.Panics(t, func() { + id.Encode(dst) + }) + }) + + t.Run("correct", func(t *testing.T) { + dst := make([]byte, sha256.Size) + + require.NotPanics(t, func() { + id.Encode(dst) + }) + require.Equal(t, emptyID, id.EncodeToString()) + }) +} diff --git a/pkg/sdk/container/id/test/doc.go b/pkg/sdk/container/id/test/doc.go new file mode 100644 index 000000000..bbf9e9d5c --- /dev/null +++ b/pkg/sdk/container/id/test/doc.go @@ -0,0 +1,13 @@ +/* +Package cidtest provides functions for convenient testing of cid package API. + +Note that importing the package into source files is highly discouraged. + +Random instance generation functions can be useful when testing expects any value, e.g.: + + import cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + + cid := cidtest.ID() + // test the value +*/ +package cidtest diff --git a/pkg/sdk/container/id/test/id.go b/pkg/sdk/container/id/test/id.go new file mode 100644 index 000000000..d14059aca --- /dev/null +++ b/pkg/sdk/container/id/test/id.go @@ -0,0 +1,26 @@ +package cidtest + +import ( + "crypto/rand" + "crypto/sha256" + + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" +) + +// ID returns random cid.ID. +func ID() cid.ID { + checksum := [sha256.Size]byte{} + + _, _ = rand.Read(checksum[:]) + + return IDWithChecksum(checksum) +} + +// IDWithChecksum returns cid.ID initialized +// with specified checksum. +func IDWithChecksum(cs [sha256.Size]byte) cid.ID { + var id cid.ID + id.SetSHA256(cs) + + return id +} diff --git a/pkg/sdk/container/network.go b/pkg/sdk/container/network.go new file mode 100644 index 000000000..dad057584 --- /dev/null +++ b/pkg/sdk/container/network.go @@ -0,0 +1,20 @@ +package container + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" +) + +// ApplyNetworkConfig applies network configuration to the +// container. Changes the container if it does not satisfy +// network configuration. +func ApplyNetworkConfig(cnr *Container, cfg netmap.NetworkInfo) { + if cfg.HomomorphicHashingDisabled() { + DisableHomomorphicHashing(cnr) + } +} + +// AssertNetworkConfig checks if a container matches passed +// network configuration. +func AssertNetworkConfig(cnr Container, cfg netmap.NetworkInfo) bool { + return IsHomomorphicHashingDisabled(cnr) == cfg.HomomorphicHashingDisabled() +} diff --git a/pkg/sdk/container/network_test.go b/pkg/sdk/container/network_test.go new file mode 100644 index 000000000..d45a057ed --- /dev/null +++ b/pkg/sdk/container/network_test.go @@ -0,0 +1,33 @@ +package container_test + +import ( + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container" + containertest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/test" + netmaptest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap/test" + "github.com/stretchr/testify/require" +) + +func TestContainer_NetworkConfig(t *testing.T) { + c := containertest.Container() + nc := netmaptest.NetworkInfo() + + t.Run("default", func(t *testing.T) { + require.False(t, container.IsHomomorphicHashingDisabled(c)) + + res := container.AssertNetworkConfig(c, nc) + + require.True(t, res) + }) + + nc.DisableHomomorphicHashing() + + t.Run("apply", func(t *testing.T) { + require.False(t, container.IsHomomorphicHashingDisabled(c)) + + container.ApplyNetworkConfig(&c, nc) + + require.True(t, container.IsHomomorphicHashingDisabled(c)) + }) +} diff --git a/pkg/sdk/container/size.go b/pkg/sdk/container/size.go new file mode 100644 index 000000000..d661e0d9a --- /dev/null +++ b/pkg/sdk/container/size.go @@ -0,0 +1,104 @@ +package container + +import ( + "errors" + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/container" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" +) + +// SizeEstimation groups information about estimation of the size of the data +// stored in the FrostFS container. +// +// SizeEstimation is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/container.UsedSpaceAnnouncement +// message. See ReadFromV2 / WriteToV2 methods. +type SizeEstimation struct { + m container.UsedSpaceAnnouncement +} + +// ReadFromV2 reads SizeEstimation from the container.UsedSpaceAnnouncement message. +// Checks if the message conforms to FrostFS API V2 protocol. +// +// See also WriteToV2. +func (x *SizeEstimation) ReadFromV2(m container.UsedSpaceAnnouncement) error { + cnrV2 := m.GetContainerID() + if cnrV2 == nil { + return errors.New("missing container") + } + + var cnr cid.ID + + err := cnr.ReadFromV2(*cnrV2) + if err != nil { + return fmt.Errorf("invalid container: %w", err) + } + + x.m = m + + return nil +} + +// WriteToV2 writes SizeEstimation into the container.UsedSpaceAnnouncement message. +// The message MUST NOT be nil. +// +// See also ReadFromV2. +func (x SizeEstimation) WriteToV2(m *container.UsedSpaceAnnouncement) { + *m = x.m +} + +// SetEpoch sets epoch when estimation of the container data size was calculated. +// +// See also Epoch. +func (x *SizeEstimation) SetEpoch(epoch uint64) { + x.m.SetEpoch(epoch) +} + +// Epoch return epoch set using SetEpoch. +// +// Zero SizeEstimation represents estimation in zero epoch. +func (x SizeEstimation) Epoch() uint64 { + return x.m.GetEpoch() +} + +// SetContainer specifies the container for which the amount of data is estimated. +// Required by the FrostFS API protocol. +// +// See also Container. +func (x *SizeEstimation) SetContainer(cnr cid.ID) { + var cidV2 refs.ContainerID + cnr.WriteToV2(&cidV2) + + x.m.SetContainerID(&cidV2) +} + +// Container returns container set using SetContainer. +// +// Zero SizeEstimation is not bound to any container (returns zero) which is +// incorrect according to FrostFS API protocol. +func (x SizeEstimation) Container() (res cid.ID) { + m := x.m.GetContainerID() + if m != nil { + err := res.ReadFromV2(*m) + if err != nil { + panic(fmt.Errorf("unexpected error from cid.ID.ReadFromV2: %w", err)) + } + } + + return +} + +// SetValue sets estimated amount of data (in bytes) in the specified container. +// +// See also Value. +func (x *SizeEstimation) SetValue(value uint64) { + x.m.SetUsedSpace(value) +} + +// Value returns data size estimation set using SetValue. +// +// Zero SizeEstimation has zero value. +func (x SizeEstimation) Value() uint64 { + return x.m.GetUsedSpace() +} diff --git a/pkg/sdk/container/size_test.go b/pkg/sdk/container/size_test.go new file mode 100644 index 000000000..2900ea0c4 --- /dev/null +++ b/pkg/sdk/container/size_test.go @@ -0,0 +1,94 @@ +package container_test + +import ( + "crypto/sha256" + "testing" + + v2container "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/container" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + "github.com/stretchr/testify/require" +) + +func TestSizeEstimation_Epoch(t *testing.T) { + var val container.SizeEstimation + + require.Zero(t, val.Epoch()) + + const epoch = 123 + + val.SetEpoch(epoch) + require.EqualValues(t, epoch, val.Epoch()) + + var msg v2container.UsedSpaceAnnouncement + val.WriteToV2(&msg) + + require.EqualValues(t, epoch, msg.GetEpoch()) +} + +func TestSizeEstimation_Container(t *testing.T) { + var val container.SizeEstimation + + require.Zero(t, val.Container()) + + cnr := cidtest.ID() + + val.SetContainer(cnr) + require.True(t, val.Container().Equals(cnr)) + + var msg v2container.UsedSpaceAnnouncement + val.WriteToV2(&msg) + + var msgCnr refs.ContainerID + cnr.WriteToV2(&msgCnr) + + require.Equal(t, &msgCnr, msg.GetContainerID()) +} + +func TestSizeEstimation_Value(t *testing.T) { + var val container.SizeEstimation + + require.Zero(t, val.Value()) + + const value = 876 + + val.SetValue(value) + require.EqualValues(t, value, val.Value()) + + var msg v2container.UsedSpaceAnnouncement + val.WriteToV2(&msg) + + require.EqualValues(t, value, msg.GetUsedSpace()) +} + +func TestSizeEstimation_ReadFromV2(t *testing.T) { + const epoch = 654 + const value = 903 + var cnrMsg refs.ContainerID + + var msg v2container.UsedSpaceAnnouncement + + var val container.SizeEstimation + + require.Error(t, val.ReadFromV2(msg)) + + msg.SetContainerID(&cnrMsg) + + require.Error(t, val.ReadFromV2(msg)) + + cnrMsg.SetValue(make([]byte, sha256.Size)) + + var cnr cid.ID + require.NoError(t, cnr.ReadFromV2(cnrMsg)) + + msg.SetEpoch(epoch) + msg.SetUsedSpace(value) + + require.NoError(t, val.ReadFromV2(msg)) + + require.EqualValues(t, epoch, val.Epoch()) + require.EqualValues(t, value, val.Value()) + require.EqualValues(t, cnr, val.Container()) +} diff --git a/pkg/sdk/container/test/generate.go b/pkg/sdk/container/test/generate.go new file mode 100644 index 000000000..83153d82c --- /dev/null +++ b/pkg/sdk/container/test/generate.go @@ -0,0 +1,39 @@ +package containertest + +import ( + "math/rand" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/acl" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + netmaptest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap/test" + usertest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user/test" +) + +// Container returns random container.Container. +func Container() (x container.Container) { + owner := usertest.ID() + + x.Init() + x.SetAttribute("some attribute", "value") + x.SetOwner(owner) + x.SetBasicACL(BasicACL()) + x.SetPlacementPolicy(netmaptest.PlacementPolicy()) + + return x +} + +// SizeEstimation returns random container.SizeEstimation. +func SizeEstimation() (x container.SizeEstimation) { + x.SetContainer(cidtest.ID()) + x.SetEpoch(rand.Uint64()) + x.SetValue(rand.Uint64()) + + return x +} + +// BasicACL returns random acl.Basic. +func BasicACL() (x acl.Basic) { + x.FromBits(rand.Uint32()) + return +} diff --git a/pkg/sdk/crypto/crypto_test.go b/pkg/sdk/crypto/crypto_test.go new file mode 100644 index 000000000..27a5b1e53 --- /dev/null +++ b/pkg/sdk/crypto/crypto_test.go @@ -0,0 +1,47 @@ +package frostfscrypto_test + +import ( + "crypto/rand" + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/crypto" + frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/crypto/ecdsa" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + "github.com/stretchr/testify/require" +) + +func TestSignature(t *testing.T) { + data := make([]byte, 512) + rand.Read(data) + + k, err := keys.NewPrivateKey() + require.NoError(t, err) + + var s frostfscrypto.Signature + var m refs.Signature + + for _, f := range []func() frostfscrypto.Signer{ + func() frostfscrypto.Signer { + return frostfsecdsa.Signer(k.PrivateKey) + }, + func() frostfscrypto.Signer { + return frostfsecdsa.SignerRFC6979(k.PrivateKey) + }, + func() frostfscrypto.Signer { + return frostfsecdsa.SignerWalletConnect(k.PrivateKey) + }, + } { + signer := f() + + err := s.Calculate(signer, data) + require.NoError(t, err) + + s.WriteToV2(&m) + + require.NoError(t, s.ReadFromV2(m)) + + valid := s.Verify(data) + require.True(t, valid, "type %T", signer) + } +} diff --git a/pkg/sdk/crypto/doc.go b/pkg/sdk/crypto/doc.go new file mode 100644 index 000000000..643a6fe6d --- /dev/null +++ b/pkg/sdk/crypto/doc.go @@ -0,0 +1,51 @@ +/* +Package frostfscrypto collects FrostFS cryptographic primitives. + +Signer type unifies entities for signing FrostFS data. + + // instantiate Signer + // select data to be signed + + var sig Signature + + err := sig.Calculate(signer, data) + // ... + + // attach signature to the request + +SDK natively supports several signature schemes that are implemented +in nested packages. + +PublicKey allows to verify signatures. + + // get signature to be verified + // compose signed data + + isValid := sig.Verify(data) + // ... + +Signature can be also used to process FrostFS API V2 protocol messages +(see neo.fs.v2.refs package in https://git.frostfs.info/TrueCloudLab/frostfs-api). + +On client side: + + import "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + + var msg refs.Signature + sig.WriteToV2(&msg) + + // send msg + +On server side: + + // recv msg + + var sig frostfscrypto.Signature + sig.ReadFromV2(msg) + + // process sig + +Using package types in an application is recommended to potentially work with +different protocol versions with which these types are compatible. +*/ +package frostfscrypto diff --git a/pkg/sdk/crypto/ecdsa/doc.go b/pkg/sdk/crypto/ecdsa/doc.go new file mode 100644 index 000000000..952b632e4 --- /dev/null +++ b/pkg/sdk/crypto/ecdsa/doc.go @@ -0,0 +1,12 @@ +/* +Package frostfsecdsa collects ECDSA primitives for FrostFS cryptography. + +Signer and PublicKey support ECDSA signature algorithm with SHA-512 hashing. +SignerRFC6979 and PublicKeyRFC6979 implement signature algorithm described in RFC 6979. +All these types provide corresponding interfaces from frostfscrypto package. + +Package import causes registration of next signature schemes via frostfscrypto.RegisterScheme: + - frostfscrypto.ECDSA_SHA512 + - frostfscrypto.ECDSA_DETERMINISTIC_SHA256 +*/ +package frostfsecdsa diff --git a/pkg/sdk/crypto/ecdsa/init.go b/pkg/sdk/crypto/ecdsa/init.go new file mode 100644 index 000000000..8a1fc6938 --- /dev/null +++ b/pkg/sdk/crypto/ecdsa/init.go @@ -0,0 +1,17 @@ +package frostfsecdsa + +import frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/crypto" + +func init() { + frostfscrypto.RegisterScheme(frostfscrypto.ECDSA_SHA512, func() frostfscrypto.PublicKey { + return new(PublicKey) + }) + + frostfscrypto.RegisterScheme(frostfscrypto.ECDSA_DETERMINISTIC_SHA256, func() frostfscrypto.PublicKey { + return new(PublicKeyRFC6979) + }) + + frostfscrypto.RegisterScheme(frostfscrypto.ECDSA_WALLETCONNECT, func() frostfscrypto.PublicKey { + return new(PublicKeyWalletConnect) + }) +} diff --git a/pkg/sdk/crypto/ecdsa/public.go b/pkg/sdk/crypto/ecdsa/public.go new file mode 100644 index 000000000..6812bcfc8 --- /dev/null +++ b/pkg/sdk/crypto/ecdsa/public.go @@ -0,0 +1,126 @@ +package frostfsecdsa + +import ( + "crypto/ecdsa" + "crypto/elliptic" + "crypto/sha256" + "crypto/sha512" + "fmt" + "math/big" + + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" +) + +// PublicKey is a wrapper over ecdsa.PublicKey used for FrostFS needs. +// Provides frostfscrypto.PublicKey interface. +// +// Instances MUST be initialized from ecdsa.PublicKey using type conversion. +type PublicKey ecdsa.PublicKey + +// MaxEncodedSize returns size of the compressed ECDSA public key. +func (x PublicKey) MaxEncodedSize() int { + return 33 +} + +// Encode encodes ECDSA public key in compressed form into buf. +// Uses exactly MaxEncodedSize bytes of the buf. +// +// Encode panics if buf length is less than MaxEncodedSize. +// +// See also Decode. +func (x PublicKey) Encode(buf []byte) int { + if len(buf) < 33 { + panic(fmt.Sprintf("too short buffer %d", len(buf))) + } + + return copy(buf, (*keys.PublicKey)(&x).Bytes()) +} + +// Decode decodes compressed binary representation of the PublicKey. +// +// See also Encode. +func (x *PublicKey) Decode(data []byte) error { + pub, err := keys.NewPublicKeyFromBytes(data, elliptic.P256()) + if err != nil { + return err + } + + *x = (PublicKey)(*pub) + + return nil +} + +// similar to elliptic.Unmarshal but without IsOnCurve check. +func unmarshalXY(data []byte) (x *big.Int, y *big.Int) { + if len(data) != 65 { + return + } else if data[0] != 4 { // uncompressed form + return + } + + p := elliptic.P256().Params().P + x = new(big.Int).SetBytes(data[1:33]) + y = new(big.Int).SetBytes(data[33:]) + + if x.Cmp(p) >= 0 || y.Cmp(p) >= 0 { + x, y = nil, nil + } + + return +} + +// Verify verifies data signature calculated by ECDSA algorithm with SHA-512 hashing. +func (x PublicKey) Verify(data, signature []byte) bool { + h := sha512.Sum512(data) + r, s := unmarshalXY(signature) + + return r != nil && s != nil && ecdsa.Verify((*ecdsa.PublicKey)(&x), h[:], r, s) +} + +// PublicKeyRFC6979 is a wrapper over ecdsa.PublicKey used for FrostFS needs. +// Provides frostfscrypto.PublicKey interface. +// +// Instances MUST be initialized from ecdsa.PublicKey using type conversion. +type PublicKeyRFC6979 ecdsa.PublicKey + +// MaxEncodedSize returns size of the compressed ECDSA public key. +func (x PublicKeyRFC6979) MaxEncodedSize() int { + return 33 +} + +// Encode encodes ECDSA public key in compressed form into buf. +// Uses exactly MaxEncodedSize bytes of the buf. +// +// Encode panics if buf length is less than MaxEncodedSize. +// +// See also Decode. +func (x PublicKeyRFC6979) Encode(buf []byte) int { + if len(buf) < 33 { + panic(fmt.Sprintf("too short buffer %d", len(buf))) + } + + return copy(buf, (*keys.PublicKey)(&x).Bytes()) +} + +// Decode decodes binary representation of the ECDSA public key. +// +// See also Encode. +func (x *PublicKeyRFC6979) Decode(data []byte) error { + pub, err := keys.NewPublicKeyFromBytes(data, elliptic.P256()) + if err != nil { + return err + } + + *x = (PublicKeyRFC6979)(*pub) + + return nil +} + +// Verify verifies data signature calculated by deterministic ECDSA algorithm +// with SHA-256 hashing. +// +// See also RFC 6979. +func (x PublicKeyRFC6979) Verify(data, signature []byte) bool { + h := sha256.Sum256(data) + return (*keys.PublicKey)(&x).Verify(signature, h[:]) +} diff --git a/pkg/sdk/crypto/ecdsa/signer.go b/pkg/sdk/crypto/ecdsa/signer.go new file mode 100644 index 000000000..e60cafdf7 --- /dev/null +++ b/pkg/sdk/crypto/ecdsa/signer.go @@ -0,0 +1,77 @@ +package frostfsecdsa + +import ( + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/sha512" + + frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/crypto" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" +) + +// Signer wraps ecdsa.PrivateKey and represents signer based on ECDSA with +// SHA-512 hashing. Provides frostfscrypto.Signer interface. +// +// Instances MUST be initialized from ecdsa.PrivateKey using type conversion. +type Signer ecdsa.PrivateKey + +// Scheme returns frostfscrypto.ECDSA_SHA512. +// Implements frostfscrypto.Signer. +func (x Signer) Scheme() frostfscrypto.Scheme { + return frostfscrypto.ECDSA_SHA512 +} + +// Sign signs data using ECDSA algorithm with SHA-512 hashing. +// Implements frostfscrypto.Signer. +func (x Signer) Sign(data []byte) ([]byte, error) { + h := sha512.Sum512(data) + r, s, err := ecdsa.Sign(rand.Reader, (*ecdsa.PrivateKey)(&x), h[:]) + if err != nil { + return nil, err + } + + params := elliptic.P256().Params() + curveOrderByteSize := params.P.BitLen() / 8 + + buf := make([]byte, 1+curveOrderByteSize*2) + buf[0] = 4 + + _ = r.FillBytes(buf[1 : 1+curveOrderByteSize]) + _ = s.FillBytes(buf[1+curveOrderByteSize:]) + + return buf, nil +} + +// Public initializes PublicKey and returns it as frostfscrypto.PublicKey. +// Implements frostfscrypto.Signer. +func (x Signer) Public() frostfscrypto.PublicKey { + return (*PublicKey)(&x.PublicKey) +} + +// SignerRFC6979 wraps ecdsa.PrivateKey and represents signer based on deterministic +// ECDSA with SHA-256 hashing (RFC 6979). Provides frostfscrypto.Signer interface. +// +// Instances SHOULD be initialized from ecdsa.PrivateKey using type conversion. +type SignerRFC6979 ecdsa.PrivateKey + +// Scheme returns frostfscrypto.ECDSA_DETERMINISTIC_SHA256. +// Implements frostfscrypto.Signer. +func (x SignerRFC6979) Scheme() frostfscrypto.Scheme { + return frostfscrypto.ECDSA_DETERMINISTIC_SHA256 +} + +// Sign signs data using deterministic ECDSA algorithm with SHA-256 hashing. +// Implements frostfscrypto.Signer. +// +// See also RFC 6979. +func (x SignerRFC6979) Sign(data []byte) ([]byte, error) { + p := keys.PrivateKey{PrivateKey: (ecdsa.PrivateKey)(x)} + return p.Sign(data), nil +} + +// Public initializes PublicKeyRFC6979 and returns it as frostfscrypto.PublicKey. +// Implements frostfscrypto.Signer. +func (x SignerRFC6979) Public() frostfscrypto.PublicKey { + return (*PublicKeyRFC6979)(&x.PublicKey) +} diff --git a/pkg/sdk/crypto/ecdsa/wallet_connect.go b/pkg/sdk/crypto/ecdsa/wallet_connect.go new file mode 100644 index 000000000..ed4f80f54 --- /dev/null +++ b/pkg/sdk/crypto/ecdsa/wallet_connect.go @@ -0,0 +1,85 @@ +package frostfsecdsa + +import ( + "crypto/ecdsa" + "crypto/elliptic" + "encoding/base64" + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/util/signature/walletconnect" + frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/crypto" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" +) + +// SignerWalletConnect is similar to SignerRFC6979 with 2 changes: +// 1. The data is base64 encoded before signing/verifying. +// 2. The signature is a concatenation of the signature itself and 16-byte salt. +// +// Instances MUST be initialized from ecdsa.PrivateKey using type conversion. +type SignerWalletConnect ecdsa.PrivateKey + +// Scheme returns frostfscrypto.ECDSA_WALLETCONNECT. +// Implements frostfscrypto.Signer. +func (x SignerWalletConnect) Scheme() frostfscrypto.Scheme { + return frostfscrypto.ECDSA_WALLETCONNECT +} + +// Sign signs data using ECDSA algorithm with SHA-512 hashing. +// Implements frostfscrypto.Signer. +func (x SignerWalletConnect) Sign(data []byte) ([]byte, error) { + b64 := make([]byte, base64.StdEncoding.EncodedLen(len(data))) + base64.StdEncoding.Encode(b64, data) + return walletconnect.Sign((*ecdsa.PrivateKey)(&x), b64) +} + +// Public initializes PublicKey and returns it as frostfscrypto.PublicKey. +// Implements frostfscrypto.Signer. +func (x SignerWalletConnect) Public() frostfscrypto.PublicKey { + return (*PublicKeyWalletConnect)(&x.PublicKey) +} + +// PublicKeyWalletConnect is a wrapper over ecdsa.PublicKey used for FrostFS needs. +// Provides frostfscrypto.PublicKey interface. +// +// Instances MUST be initialized from ecdsa.PublicKey using type conversion. +type PublicKeyWalletConnect ecdsa.PublicKey + +// MaxEncodedSize returns size of the compressed ECDSA public key. +func (x PublicKeyWalletConnect) MaxEncodedSize() int { + return 33 +} + +// Encode encodes ECDSA public key in compressed form into buf. +// Uses exactly MaxEncodedSize bytes of the buf. +// +// Encode panics if buf length is less than MaxEncodedSize. +// +// See also Decode. +func (x PublicKeyWalletConnect) Encode(buf []byte) int { + if len(buf) < 33 { + panic(fmt.Sprintf("too short buffer %d", len(buf))) + } + + return copy(buf, (*keys.PublicKey)(&x).Bytes()) +} + +// Decode decodes compressed binary representation of the PublicKeyWalletConnect. +// +// See also Encode. +func (x *PublicKeyWalletConnect) Decode(data []byte) error { + pub, err := keys.NewPublicKeyFromBytes(data, elliptic.P256()) + if err != nil { + return err + } + + *x = (PublicKeyWalletConnect)(*pub) + + return nil +} + +// Verify verifies data signature calculated by ECDSA algorithm with SHA-512 hashing. +func (x PublicKeyWalletConnect) Verify(data, signature []byte) bool { + b64 := make([]byte, base64.StdEncoding.EncodedLen(len(data))) + base64.StdEncoding.Encode(b64, data) + return walletconnect.Verify((*ecdsa.PublicKey)(&x), b64, signature) +} diff --git a/pkg/sdk/crypto/signature.go b/pkg/sdk/crypto/signature.go new file mode 100644 index 000000000..76eaecc0f --- /dev/null +++ b/pkg/sdk/crypto/signature.go @@ -0,0 +1,102 @@ +package frostfscrypto + +import ( + "errors" + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" +) + +// Signature represents a confirmation of data integrity received by the +// digital signature mechanism. +// +// Signature is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs.Signature +// message. See ReadFromV2 / WriteToV2 methods. +// +// Note that direct typecast is not safe and may result in loss of compatibility: +// +// _ = Signature(refs.Signature{}) // not recommended +type Signature refs.Signature + +// ReadFromV2 reads Signature from the refs.Signature message. Checks if the +// message conforms to FrostFS API V2 protocol. +// +// See also WriteToV2. +func (x *Signature) ReadFromV2(m refs.Signature) error { + if len(m.GetKey()) == 0 { + return errors.New("missing public key") + } else if len(m.GetSign()) == 0 { + return errors.New("missing signature") + } + + switch m.GetScheme() { + default: + return fmt.Errorf("unsupported scheme %v", m.GetSign()) + case + refs.ECDSA_SHA512, + refs.ECDSA_RFC6979_SHA256, + refs.ECDSA_RFC6979_SHA256_WALLET_CONNECT: + } + + *x = Signature(m) + + return nil +} + +// WriteToV2 writes Signature to the refs.Signature message. +// The message must not be nil. +// +// See also ReadFromV2. +func (x Signature) WriteToV2(m *refs.Signature) { + *m = (refs.Signature)(x) +} + +// Calculate signs data using Signer and encodes public key for subsequent +// verification. +// +// Signer MUST NOT be nil. +// +// See also Verify. +func (x *Signature) Calculate(signer Signer, data []byte) error { + signature, err := signer.Sign(data) + if err != nil { + return fmt.Errorf("signer %T failure: %w", signer, err) + } + + pub := signer.Public() + + key := make([]byte, pub.MaxEncodedSize()) + key = key[:pub.Encode(key)] + + m := (*refs.Signature)(x) + + m.SetScheme(refs.SignatureScheme(signer.Scheme())) + m.SetSign(signature) + m.SetKey(key) + + return nil +} + +// Verify verifies data signature using encoded public key. True means valid +// signature. +// +// Verify fails if signature scheme is not supported (see RegisterScheme). +// +// See also Calculate. +func (x Signature) Verify(data []byte) bool { + m := (*refs.Signature)(&x) + + f, ok := publicKeys[Scheme(m.GetScheme())] + if !ok { + return false + } + + key := f() + + err := key.Decode(m.GetKey()) + if err != nil { + return false + } + + return key.Verify(data, m.GetSign()) +} diff --git a/pkg/sdk/crypto/signer.go b/pkg/sdk/crypto/signer.go new file mode 100644 index 000000000..85464be2f --- /dev/null +++ b/pkg/sdk/crypto/signer.go @@ -0,0 +1,94 @@ +package frostfscrypto + +import ( + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" +) + +// Scheme represents digital signature algorithm with fixed cryptographic hash function. +// +// Negative values are reserved and depend on context (e.g. unsupported scheme). +type Scheme int32 + +//nolint:revive +const ( + _ Scheme = iota - 1 + + ECDSA_SHA512 // ECDSA with SHA-512 hashing (FIPS 186-3) + ECDSA_DETERMINISTIC_SHA256 // Deterministic ECDSA with SHA-256 hashing (RFC 6979) + ECDSA_WALLETCONNECT // Wallet Connect signature scheme +) + +// String implements fmt.Stringer. +func (x Scheme) String() string { + return refs.SignatureScheme(x).String() +} + +// maps Scheme to blank PublicKey constructor. +var publicKeys = make(map[Scheme]func() PublicKey) + +// RegisterScheme registers a function that returns a new blank PublicKey +// instance for the given Scheme. This is intended to be called from the init +// function in packages that implement signature schemes. +// +// RegisterScheme panics if function for the given Scheme is already registered. +// +// Note that RegisterScheme isn't tread-safe. +func RegisterScheme(scheme Scheme, f func() PublicKey) { + _, ok := publicKeys[scheme] + if ok { + panic(fmt.Sprintf("scheme %v is already registered", scheme)) + } + + publicKeys[scheme] = f +} + +// Signer is an interface of entities that can be used for signing operations +// in FrostFS. Unites secret and public parts. For example, an ECDSA private key +// or external auth service. +// +// See also PublicKey. +type Signer interface { + // Scheme returns corresponding signature scheme. + Scheme() Scheme + + // Sign signs digest of the given data. Implementations encapsulate data + // hashing that depends on Scheme. For example, if scheme uses SHA-256, then + // Sign signs SHA-256 hash of the data. + Sign(data []byte) ([]byte, error) + + // Public returns the public key corresponding to the Signer. + Public() PublicKey +} + +// PublicKey represents a public key using fixed signature scheme supported by +// FrostFS. +// +// See also Signer. +type PublicKey interface { + // MaxEncodedSize returns maximum size required for binary-encoded + // public key. + // + // MaxEncodedSize MUST NOT return value greater than any return of + // Encode. + MaxEncodedSize() int + + // Encode encodes public key into buf. Returns number of bytes + // written. + // + // Encode MUST panic if buffer size is insufficient and less than + // MaxEncodedSize (*). Encode MUST return negative value + // on any failure except (*). + // + // Encode is a reverse operation to Decode. + Encode(buf []byte) int + + // Decode decodes binary public key. + // + // Decode is a reverse operation to Encode. + Decode([]byte) error + + // Verify checks signature of the given data. True means correct signature. + Verify(data, signature []byte) bool +} diff --git a/pkg/sdk/crypto/util.go b/pkg/sdk/crypto/util.go new file mode 100644 index 000000000..2da236acf --- /dev/null +++ b/pkg/sdk/crypto/util.go @@ -0,0 +1,9 @@ +package frostfscrypto + +import "encoding/hex" + +// StringifyKeyBinary returns string with HEX representation of source. +// Format can be changed and it's unsafe to rely on it beyond human-readable output. +func StringifyKeyBinary(src []byte) string { + return hex.EncodeToString(src) +} diff --git a/pkg/sdk/doc/image/filter_illustration.svg b/pkg/sdk/doc/image/filter_illustration.svg new file mode 100644 index 000000000..7eedf3d60 --- /dev/null +++ b/pkg/sdk/doc/image/filter_illustration.svg @@ -0,0 +1,4 @@ + + + +
FILTER Color EQ 'Red' AS RedNodes
FILTER Color EQ 'Red' AS RedNodes
FILTER Color EQ 'Blue' AS BlueNodes
FILTER Color EQ 'Blue' AS BlueNodes
FILTER @RedNodes OR @BlueNodes AS MyNodes
FILTER @RedNodes OR @BlueNodes AS MyNodes
*
*
MyNodes
MyNodes
Text is not SVG - cannot display
diff --git a/pkg/sdk/doc/image/placement_policy.svg b/pkg/sdk/doc/image/placement_policy.svg new file mode 100644 index 000000000..2820c64f7 --- /dev/null +++ b/pkg/sdk/doc/image/placement_policy.svg @@ -0,0 +1,4 @@ + + + +
FILTER
FILTER
FILTER
FILTER
FILTER
FILTER
SELECT
SELECT
SELECT
SELECT
SELECT
SELECT
FILTER
FILTER
FILTER
FILTER
FILTER
FILTER
REP
REP
REP
REP
REP
REP
netmap
netmap
Text is not SVG - cannot display
diff --git a/pkg/sdk/doc/image/rep_illustration.svg b/pkg/sdk/doc/image/rep_illustration.svg new file mode 100644 index 000000000..6955499d6 --- /dev/null +++ b/pkg/sdk/doc/image/rep_illustration.svg @@ -0,0 +1,4 @@ + + + +
(...)
(...)
SELECT 2 IN DISTINCT Color FROM RedOrBlueNodes AS MyNodes
SELECT 2 IN DISTINCT Color FROM RedOrBlueNodes AS MyNodes
MyNodes
MyNodes
REP 1 IN MyNodes
REP 1 IN MyNodes
Text is not SVG - cannot display
diff --git a/pkg/sdk/doc/image/sample_netmap.svg b/pkg/sdk/doc/image/sample_netmap.svg new file mode 100644 index 000000000..ea4928ead --- /dev/null +++ b/pkg/sdk/doc/image/sample_netmap.svg @@ -0,0 +1,4 @@ + + + +
C
C
A
A
Netmap
Netmap
B
B
D
D
E
E
F
F
G
G
H
H
I
I
Text is not SVG - cannot display
diff --git a/pkg/sdk/doc/image/select_illustration.svg b/pkg/sdk/doc/image/select_illustration.svg new file mode 100644 index 000000000..83ee78388 --- /dev/null +++ b/pkg/sdk/doc/image/select_illustration.svg @@ -0,0 +1,4 @@ + + + +
FILTER @RedNodes OR @BlueNodes AS RedOrBlueNodes
FILTER @RedNodes OR @BlueNodes AS RedOrBlueNodes
RedOrBlueNodes
RedOrBlueNodes
(...)
(...)
SELECT 2 IN DISTINCT Color FROM RedOrBlueNodes AS MyNodes
SELECT 2 IN DISTINCT Color FROM RedOrBlueNodes AS MyNodes
MyNodes
MyNodes
Text is not SVG - cannot display
diff --git a/pkg/sdk/doc/policy.md b/pkg/sdk/doc/policy.md new file mode 100644 index 000000000..28744efc3 --- /dev/null +++ b/pkg/sdk/doc/policy.md @@ -0,0 +1,446 @@ +# Placement Policy + +This document describes placement policies, their purpose, syntax and semantics. + +## Index + +- [Introduction](#introduction) +- [Operations](#operations) + - [Basic Expressions](#basic-expressions) + - [`FILTER`](#filter) + - [`SELECT`](#select) + - [`REP`](#rep) +- [Policies](#policies) + - [The policy playground](#the-policy-playground) + - [`CBF`](#cbf) + - [`UNIQUE`](#unique) + - [More examples](#more-examples) +- [Appendix 1: Operators](#appendix-1-operators) +- [Appendix 2: Policy playground commands](#appendix-2-policy-playground-commands) + +## Introduction + +The purpose of a **placement policy** is to determine whichs node(s) of a frostfs system will store an object. Namely, given a **netmap** (a set of nodes) and a placement policy, a subset of those nodes is selected to store a given object. An important aspect is that since nodes in a netmap come and go due to distributed nature of the system, this selection must be deterministic and consistent, i.e. different nodes must come to the same conclusion as long as they share the same view of the netmap. + +> ℹ️ Throughout this document, we will consider each node as a dictionary of attributes and a global unique ID. + +One way to think about the placement policy, is as a pipeline of operations which begins with a set of nodes (the entire netmap) and gradually refine it into only the nodes that will be in charge of storing the object. More specifically, each operation in this pipeline takes a set of nodes and transforms it into a subset of those nodes. The transformation is done purely on the basis of the node attributes. + +![Placement policy as a pipeline](./image/placement_policy.svg) + +The three main operations are: +1. `FILTER`: filters a set of nodes based on their attributes. +2. `SELECT`: selects a specific amount of nodes from a set of nodes based on certain conditions. +3. `REP`: specifies how many nodes (and which ones) from a set of nodes are used to store an object. + +In the next sections, we will explore each of them in detail. + +## Operations + +### Basic Expressions + +Before exploring the operations in detail, we must get acquainted with the basic expressions that appear in a placement policy. As mentioned above, the placement policy operates solely on the basis of node attributes, and as such, basic expressions mostly revolve around node attribute comparison. + +A comparison expression expresses whether a node attribute equals a specified value: +``` +AttributeName Operation AttributeValue +``` + +For example, the following expression +```sql +City EQ 'Moscow' +``` +asserts that the node attribute `City` equals the value `Moscow`. + +Comparison expressions can be nested via boolean operators and parentheses. For example, the following expression: +```sql +(City EQ 'Moscow') AND (Disks GT 2) +``` +asserts that the node attribute `City` equals the value `Moscow` and the node attribute `Disks` must be greater than `2`. Note that the arguments can be either a string or a number. + +See [Appendix 1](#appendix-1-operators) for a complete list of supported operators. + +### `FILTER` + +A `FILTER` operation takes as input a set of nodes and returns a subset of those nodes. It's useful for selecting nodes that have (or lack) specific attributes. Its basic syntax is as follows: +```bnf +FILTER AS +``` + +For example, the following filter +```sql +FILTER Color EQ 'Red' AS RedNodes +``` +selects those nodes for which the `Color` attribute equals `Red`, and discards the rest. The filter's identifier is `RedNodes`, which can be used to reference it in other parts of the placement policy. For example, you could reference the above filter in another filter as follows +```sql +FILTER @RedNodes AND (City EQ 'Moscow') AS RedMoscowNodes +``` +which would select those nodes for which the `Color` attribute equals `Red` and the `City` attribute equals `Moscow`. You can think of the `@` operator as embedding the referenced filter expression verbatim where it's used. This makes it easy to compose filters. However, filters can be referenced via `@` only within filter expressions. In other places you can simply use the filter identifier directly. + +> ⚠️ Every filter requires a unique identifier. What would be the use of a filter that you cannot reference? + +The following diagram illustrates the filter operation + +![FILTER](./image/filter_illustration.svg) + +where the nodes are represented as colored circles, with their color representing the value of their `Color` attribute, respectively. + +> ℹ️ A filter referring to all nodes in the netmap always exists and can be referenced by `*`. + +### `SELECT` + +A `SELECT` operation specifies how many and which nodes from a subset previously obtained from a `FILTER` will be available to build replica groups for object storage. It's not that different from a `FILTER` in that it transforms a set of nodes into a subset of those, but while a `FILTER` cannot control the size of the resulting subset and other characteristics, a `SELECT` can. + +Its basic syntax is as follows: +```bnf +SELECT {IN (SAME|DISTINCT) } FROM {AS } +``` + +In a nutshell, a `SELECT` takes a filter result as input and outputs a specific number of nodes, optionally enforcing that all output nodes must either share or differ in a specific attribute. Note that only the output node count and the source filter are required. + +Let's see some examples +```sql +-- Selects exactly one node from the entire netmap +SELECT 1 FROM * + +-- Same as above, but with an identifier for the selection +SELECT 1 FROM * AS ONE + +-- Selects two nodes from the RedOrBlueNodes filter, such that both selected nodes +-- share the same value for the Color attribute, i.e. both red or both blue. +SELECT 2 IN SAME Color FROM RedOrBlueNodes + +-- Selects two nodes from the RedOrBlueNodes filter, such that the selected nodes +-- have distinct values for the Color attribute, i.e. one red and one blue. +-- The selection is also given an identifier. +SELECT 2 IN DISTINCT Color FROM RedOrBlueNodes AS MyNodes +``` + +The last example is illustrated in the following diagram: + +![SELECT](./image/select_illustration.svg) + +> ℹ️ At this point, notice that while `FILTER`'s output is always unique (namely, every node in the input is either filtered in or out), that is not always the case for `SELECT`. In the last example above, there is more than one way to select two nodes with distinct `Color` attribute. Because we require the output to be deterministic and consistent (so that all nodes agree on which nodes to store a given object without having to commmunicate with each other), we need a way to reach this consensus efficiently. Internally, the policy engine uses [Rendezvouz Hashing](https://en.wikipedia.org/wiki/Rendezvous_hashing) to ensure this. If you want more control over what nodes are actually selected, you can always use narrower filters/selections to ensure this. + +### `REP` + +A `REP` operation specifies how many copies of an object need to be stored (`REP` stands for "replica"). A placement policy can contain multiple replica operations, with each of them representing a replica group, i.e. a group of objects associated with the same replica. Following our analogy with a pipeline, `REP` operations are the sink or output nodes. + +Its basic syntax is as follows: +```bnf +REP {IN * * +``` + +We begin by stating all our `REP` operations, followed by all the `SELECT` operations and finally all the `FILTER` operations. Note that this is the reverse order in which they are applied. Also note that at least one `REP` operation is required. + +Here's a complete example: +```sql +REP 1 IN MyNodes +SELECT 2 IN DISTINCT Color FROM RedOrBlueNodes AS MyNodes +FILTER Color EQ 'Red' AS RedNodes +FILTER Color EQ 'Blue' AS BlueNodes +FILTER @RedNodes OR @BlueNodes AS RedOrBlueNodes +``` + +In additional to this basic syntax, there are a couple of additional useful options to specify which nodes and how many nodes are actually selected to store objects. We explore these in the next sections. + +### The policy playground + +> ℹ️ This section assumes you have an up-to-date version of the `frostfs-cli`. + +While simple placement policies have predictable results that can be understood at a glance, more complex ones need careful consideration before deployment. In order to simplify understanding a policy's outcome and experimenting while learning, a builtin tool is provided as part of the `frostfs-cli` for this purpose: the policy playground. + +For the remainder of this guide, we will use the policy playground to setup a virtual netmap (that is, one that doesn't require any networking or deployment) and test various policies. In order to visualize this netmap easily, each node will have three attributes: a character, a shape and a color + +![Sample Netmap](./image/sample_netmap.svg) + +We can start the policy playground as follows: +```sh +$ frostfs-cli container policy-playground +> +``` + +Since we didn't pass any endpoint, the initial netmap is empty, which we can verify with the `ls` command (to list the nodes in the netmap): +```sh +> ls +> +``` + +Nows let's add virtual nodes to represent our test netmap in the figure above +```sh +> add 01 Char:A Shape:Circle Color:Blue +> add 02 Char:B Shape:Circle Color:Green +> add 03 Char:C Shape:Circle Color:Red +> add 04 Char:D Shape:Square Color:Blue +> add 05 Char:E Shape:Square Color:Green +> add 06 Char:F Shape:Square Color:Red +> add 07 Char:G Shape:Diamond Color:Blue +> add 08 Char:H Shape:Diamond Color:Green +> add 09 Char:I Shape:Diamond Color:Red +``` + +and verify that the netmap now contains what we expect +```sh +> ls + 1: id=06 attrs={Char:F Shape:Square Color:Red} + 2: id=08 attrs={Char:H Shape:Diamond Color:Green} + 3: id=01 attrs={Char:A Shape:Circle Color:Blue} + 4: id=04 attrs={Char:D Shape:Square Color:Blue} + 5: id=05 attrs={Char:E Shape:Square Color:Green} + 6: id=09 attrs={Char:I Shape:Diamond Color:Red} + 7: id=02 attrs={Char:B Shape:Circle Color:Green} + 8: id=03 attrs={Char:C Shape:Circle Color:Red} + 9: id=07 attrs={Char:G Shape:Diamond Color:Blue} +``` + +With our sample netmap setup, we can now continue. + +### `CBF` + +Consider the following policy: + +```sql +REP 1 +``` + +It builds a replica consisting of one copy, selected from the entire netmap. If we evaluate this policy in our sample netmap, we obtain a result which is probably unexpected: + +```sh +> eval REP 1 + 1: [06 05 02] +``` + +The `eval` commands evaluates a policy and lists in a separate line the nodes selected for each `REP` operation, in the order they appear in the policy. We were expecting a single node, but we got three instead. The reason is that there's a policy-wide parameter called **container backup factor** (or CBF). This parameter is a multiplier which controls the maximum number of storage nodes: for example, if a policy requires 10 nodes and the CBF is 3, it means that the policy can store an object in up to 10 × 3 nodes. However, if there are not enough nodes and fewer (but at least 10) are used, this is not considered an error. + +The default value for CBF is `3`, which explains our result above, given than every node in the netmap agrees with the policy. The CBF can be explicitly set in the policy right after the `REP` operations. For example + +```sh +> eval REP 1 CBF 1 + 1: [06] +``` + +results in what we expected in the first example. On the other hand + +```sh +> eval REP 1 IN MyNodes SELECT 1 IN SAME Char FROM * AS MyNodes + 1: [01] +``` + +results in a single node despite the default CBF, because there are not enough nodes compatible with the selection. + +### `UNIQUE` + +Consider the following policy: +```sql +REP 1 +REP 1 +CBF 2 +``` + +If we evaluate it +```sh +> eval REP 1 REP 1 CBF 2 + 1: [06 05] + 2: [06 05] +``` + +we find that each replica gets two nodes, in accordance with the CBF. However, these nodes are exactly the same and this might not be desirable. In order to force the policy engine to select different nodes for each replica, we can use the `UNIQUE` option, which is specified right before the `REP` operations. + +In our example, if we change it to +```sql +UNIQUE +REP 1 +REP 1 +CBF 2 +``` + +and evaluate it + +```sh +> eval UNIQUE REP 1 REP 1 CBF 2 + 1: [06 05] + 2: [02 03] +``` + +we now find that the nodes selected for each replica are now distinct from each other. + +### More examples + +This section presents some more examples of placement policies and their result when applied to the sample netmap. Try to figure out the result before looking at it or evaluating the policy. + +#### Example #1 +```sql +REP 1 IN TwoRedNodes +SELECT 2 FROM RedNodes AS TwoRedNodes +FILTER Color EQ 'Red' AS RedNodes +``` + +
+Result + +```sh +> eval REP 1 IN TwoRedNodes SELECT 2 FROM RedNodes AS TwoRedNodes FILTER Color EQ 'Red' AS RedNodes + 1: [06 09 03] +``` + +
+ +#### Example #2 +```sql +REP 1 IN TwoRedNodes +REP 1 IN TwoRedNodes +SELECT 2 FROM RedNodes AS TwoRedNodes +FILTER Color EQ 'Red' AS RedNodes +``` + +
+Result + +```sh +> eval REP 1 REP 1 IN TwoRedNodes SELECT 2 FROM RedNodes AS TwoRedNodes FILTER Color EQ 'Red' AS RedNodes + 1: [06 09 03] + 2: [06 09 03] +``` + +
+ +#### Example #3 +```sql +REP 2 IN MyNodes +REP 2 IN MyNodes +SELECT 2 FROM RedOrBlueNodes AS MyNodes +FILTER Color EQ 'Red' AS RedNodes +FILTER Color EQ 'Blue' AS BlueNodes +FILTER @RedNodes OR @BlueNodes AS RedOrBlueNodes +``` + +
+Result + +```sh +> eval REP 2 IN MyNodes REP 2 IN MyNodes SELECT 2 FROM RedOrBlueNodes AS MyNodes FILTER Color EQ 'Red' AS RedNodes FILTER Color EQ 'Blue' AS BlueNodes FILTER @RedNodes OR @BlueNodes AS RedOrBlueNodes + 1: [06 01 04 03 09 07] + 2: [06 01 04 03 09 07] +``` + +
+ +#### Example #4 +```sql +REP 2 IN MyRedNodes +REP 2 IN MyBlueNodes +CBF 1 +SELECT 2 FROM RedNodes AS MyRedNodes +SELECT 2 FROM BlueNodes AS MyBlueNodes +FILTER Color EQ 'Red' AS RedNodes +FILTER Color EQ 'Blue' AS BlueNodes +``` + +
+Result + +```sh +> eval REP 2 IN MyRedNodes REP 2 IN MyBlueNodes CBF 1 SELECT 2 FROM RedNodes AS MyRedNodes SELECT 2 FROM BlueNodes AS MyBlueNodes FILTER Color EQ 'Red' AS RedNodes FILTER Color EQ 'Blue' AS BlueNodes + 1: [06 03] + 2: [01 04] +``` + +
+ +#### Example #5 +```sql +UNIQUE +REP 1 IN MyGreenNodes +REP 1 IN MyGreenNodes +REP 1 IN MyGreenNodes +CBF 1 +SELECT 1 FROM GreenNodes AS MyGreenNodes +FILTER Color EQ 'Green' AS GreenNodes +``` + +
+Result + +```sh +> eval UNIQUE REP 1 IN MyGreenNodes REP 1 IN MyGreenNodes REP 1 IN MyGreenNodes CBF 1 SELECT 1 FROM GreenNodes AS MyGreenNodes FILTER Color EQ 'Green' AS GreenNodes + 1: [05] + 2: [02] + 3: [08] +``` + +
+ +#### Example #6 +```sql +REP 1 IN MyNodes +REP 2 +CBF 2 +SELECT 1 FROM CuteNodes AS MyNodes +FILTER (Color EQ 'Blue') AND NOT (Shape EQ 'Circle' OR Shape EQ 'Square') AS CuteNodes +``` + +
+Result + +```sh +eval REP 1 IN MyNodes REP 2 CBF 2 SELECT 1 FROM CuteNodes AS MyNodes FILTER (Color EQ 'Blue') AND NOT (Shape EQ 'Circle' OR Shape EQ 'Square') AS CuteNodes + 1: [07] + 2: [06 05 02 03] +``` + +
+ +## Appendix 1: Operators + +Comparison operators (all binary): +- `EQ`: equals +- `NE`: not equal +- `GE`: greater or equal +- `GT`: greater than +- `LE`: less or equal +- `LT`: less than + +Logical operators: +- `NOT`: negation (unary) +- `AND`: conjunction (binary) +- `OR`: disjunction (binary) + +Others: +- `@`: filter reference +- `(`: left parenthesis +- `)`: right parenthesis + +## Appendix 2: Policy playground commands + +- `ls`: list nodes in the current netmap and their attributes +- `add`: add a node to the current netmap. If it already exists, it will be overwritten. +- `remove`: remove a node from the current netmap. +- `eval`: evaluate a placement policy on the current netmap. diff --git a/pkg/sdk/eacl/enums.go b/pkg/sdk/eacl/enums.go new file mode 100644 index 000000000..d91425b95 --- /dev/null +++ b/pkg/sdk/eacl/enums.go @@ -0,0 +1,396 @@ +package eacl + +import ( + v2acl "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/acl" +) + +// Action taken if ContainerEACL record matched request. +// Action is compatible with v2 acl.Action enum. +type Action uint32 + +const ( + // ActionUnknown is an Action value used to mark action as undefined. + ActionUnknown Action = iota + + // ActionAllow is an Action value that allows access to the operation from context. + ActionAllow + + // ActionDeny is an Action value that denies access to the operation from context. + ActionDeny +) + +// Operation is a object service method to match request. +// Operation is compatible with v2 acl.Operation enum. +type Operation uint32 + +const ( + // OperationUnknown is an Operation value used to mark operation as undefined. + OperationUnknown Operation = iota + + // OperationGet is an object get Operation. + OperationGet + + // OperationHead is an Operation of getting the object header. + OperationHead + + // OperationPut is an object put Operation. + OperationPut + + // OperationDelete is an object delete Operation. + OperationDelete + + // OperationSearch is an object search Operation. + OperationSearch + + // OperationRange is an object payload range retrieval Operation. + OperationRange + + // OperationRangeHash is an object payload range hashing Operation. + OperationRangeHash +) + +// Role is a group of request senders to match request. +// Role is compatible with v2 acl.Role enum. +type Role uint32 + +const ( + // RoleUnknown is a Role value used to mark role as undefined. + RoleUnknown Role = iota + + // RoleUser is a group of senders that contains only key of container owner. + RoleUser + + // RoleSystem is a group of senders that contains keys of container nodes and + // inner ring nodes. + RoleSystem + + // RoleOthers is a group of senders that contains none of above keys. + RoleOthers +) + +// Match is binary operation on filer name and value to check if request is matched. +// Match is compatible with v2 acl.MatchType enum. +type Match uint32 + +const ( + // MatchUnknown is a Match value used to mark matcher as undefined. + MatchUnknown Match = iota + + // MatchStringEqual is a Match of string equality. + MatchStringEqual + + // MatchStringNotEqual is a Match of string inequality. + MatchStringNotEqual +) + +// FilterHeaderType indicates source of headers to make matches. +// FilterHeaderType is compatible with v2 acl.HeaderType enum. +type FilterHeaderType uint32 + +const ( + // HeaderTypeUnknown is a FilterHeaderType value used to mark header type as undefined. + HeaderTypeUnknown FilterHeaderType = iota + + // HeaderFromRequest is a FilterHeaderType for request X-Header. + HeaderFromRequest + + // HeaderFromObject is a FilterHeaderType for object header. + HeaderFromObject + + // HeaderFromService is a FilterHeaderType for service header. + HeaderFromService +) + +// ToV2 converts Action to v2 Action enum value. +func (a Action) ToV2() v2acl.Action { + switch a { + case ActionAllow: + return v2acl.ActionAllow + case ActionDeny: + return v2acl.ActionDeny + default: + return v2acl.ActionUnknown + } +} + +// ActionFromV2 converts v2 Action enum value to Action. +func ActionFromV2(action v2acl.Action) (a Action) { + switch action { + case v2acl.ActionAllow: + a = ActionAllow + case v2acl.ActionDeny: + a = ActionDeny + default: + a = ActionUnknown + } + + return a +} + +// String returns string representation of Action. +// +// String mapping: +// - ActionAllow: ALLOW; +// - ActionDeny: DENY; +// - ActionUnknown, default: ACTION_UNSPECIFIED. +func (a Action) String() string { + return a.ToV2().String() +} + +// FromString parses Action from a string representation. +// It is a reverse action to String(). +// +// Returns true if s was parsed successfully. +func (a *Action) FromString(s string) bool { + var g v2acl.Action + + ok := g.FromString(s) + + if ok { + *a = ActionFromV2(g) + } + + return ok +} + +// ToV2 converts Operation to v2 Operation enum value. +func (o Operation) ToV2() v2acl.Operation { + switch o { + case OperationGet: + return v2acl.OperationGet + case OperationHead: + return v2acl.OperationHead + case OperationPut: + return v2acl.OperationPut + case OperationDelete: + return v2acl.OperationDelete + case OperationSearch: + return v2acl.OperationSearch + case OperationRange: + return v2acl.OperationRange + case OperationRangeHash: + return v2acl.OperationRangeHash + default: + return v2acl.OperationUnknown + } +} + +// OperationFromV2 converts v2 Operation enum value to Operation. +func OperationFromV2(operation v2acl.Operation) (o Operation) { + switch operation { + case v2acl.OperationGet: + o = OperationGet + case v2acl.OperationHead: + o = OperationHead + case v2acl.OperationPut: + o = OperationPut + case v2acl.OperationDelete: + o = OperationDelete + case v2acl.OperationSearch: + o = OperationSearch + case v2acl.OperationRange: + o = OperationRange + case v2acl.OperationRangeHash: + o = OperationRangeHash + default: + o = OperationUnknown + } + + return o +} + +// String returns string representation of Operation. +// +// String mapping: +// - OperationGet: GET; +// - OperationHead: HEAD; +// - OperationPut: PUT; +// - OperationDelete: DELETE; +// - OperationSearch: SEARCH; +// - OperationRange: GETRANGE; +// - OperationRangeHash: GETRANGEHASH; +// - OperationUnknown, default: OPERATION_UNSPECIFIED. +func (o Operation) String() string { + return o.ToV2().String() +} + +// FromString parses Operation from a string representation. +// It is a reverse action to String(). +// +// Returns true if s was parsed successfully. +func (o *Operation) FromString(s string) bool { + var g v2acl.Operation + + ok := g.FromString(s) + + if ok { + *o = OperationFromV2(g) + } + + return ok +} + +// ToV2 converts Role to v2 Role enum value. +func (r Role) ToV2() v2acl.Role { + switch r { + case RoleUser: + return v2acl.RoleUser + case RoleSystem: + return v2acl.RoleSystem + case RoleOthers: + return v2acl.RoleOthers + default: + return v2acl.RoleUnknown + } +} + +// RoleFromV2 converts v2 Role enum value to Role. +func RoleFromV2(role v2acl.Role) (r Role) { + switch role { + case v2acl.RoleUser: + r = RoleUser + case v2acl.RoleSystem: + r = RoleSystem + case v2acl.RoleOthers: + r = RoleOthers + default: + r = RoleUnknown + } + + return r +} + +// String returns string representation of Role. +// +// String mapping: +// - RoleUser: USER; +// - RoleSystem: SYSTEM; +// - RoleOthers: OTHERS; +// - RoleUnknown, default: ROLE_UNKNOWN. +func (r Role) String() string { + return r.ToV2().String() +} + +// FromString parses Role from a string representation. +// It is a reverse action to String(). +// +// Returns true if s was parsed successfully. +func (r *Role) FromString(s string) bool { + var g v2acl.Role + + ok := g.FromString(s) + + if ok { + *r = RoleFromV2(g) + } + + return ok +} + +// ToV2 converts Match to v2 MatchType enum value. +func (m Match) ToV2() v2acl.MatchType { + switch m { + case MatchStringEqual: + return v2acl.MatchTypeStringEqual + case MatchStringNotEqual: + return v2acl.MatchTypeStringNotEqual + default: + return v2acl.MatchTypeUnknown + } +} + +// MatchFromV2 converts v2 MatchType enum value to Match. +func MatchFromV2(match v2acl.MatchType) (m Match) { + switch match { + case v2acl.MatchTypeStringEqual: + m = MatchStringEqual + case v2acl.MatchTypeStringNotEqual: + m = MatchStringNotEqual + default: + m = MatchUnknown + } + + return m +} + +// String returns string representation of Match. +// +// String mapping: +// - MatchStringEqual: STRING_EQUAL; +// - MatchStringNotEqual: STRING_NOT_EQUAL; +// - MatchUnknown, default: MATCH_TYPE_UNSPECIFIED. +func (m Match) String() string { + return m.ToV2().String() +} + +// FromString parses Match from a string representation. +// It is a reverse action to String(). +// +// Returns true if s was parsed successfully. +func (m *Match) FromString(s string) bool { + var g v2acl.MatchType + + ok := g.FromString(s) + + if ok { + *m = MatchFromV2(g) + } + + return ok +} + +// ToV2 converts FilterHeaderType to v2 HeaderType enum value. +func (h FilterHeaderType) ToV2() v2acl.HeaderType { + switch h { + case HeaderFromRequest: + return v2acl.HeaderTypeRequest + case HeaderFromObject: + return v2acl.HeaderTypeObject + case HeaderFromService: + return v2acl.HeaderTypeService + default: + return v2acl.HeaderTypeUnknown + } +} + +// FilterHeaderTypeFromV2 converts v2 HeaderType enum value to FilterHeaderType. +func FilterHeaderTypeFromV2(header v2acl.HeaderType) (h FilterHeaderType) { + switch header { + case v2acl.HeaderTypeRequest: + h = HeaderFromRequest + case v2acl.HeaderTypeObject: + h = HeaderFromObject + case v2acl.HeaderTypeService: + h = HeaderFromService + default: + h = HeaderTypeUnknown + } + + return h +} + +// String returns string representation of FilterHeaderType. +// +// String mapping: +// - HeaderFromRequest: REQUEST; +// - HeaderFromObject: OBJECT; +// - HeaderTypeUnknown, default: HEADER_UNSPECIFIED. +func (h FilterHeaderType) String() string { + return h.ToV2().String() +} + +// FromString parses FilterHeaderType from a string representation. +// It is a reverse action to String(). +// +// Returns true if s was parsed successfully. +func (h *FilterHeaderType) FromString(s string) bool { + var g v2acl.HeaderType + + ok := g.FromString(s) + + if ok { + *h = FilterHeaderTypeFromV2(g) + } + + return ok +} diff --git a/pkg/sdk/eacl/enums_test.go b/pkg/sdk/eacl/enums_test.go new file mode 100644 index 000000000..d6fe6f625 --- /dev/null +++ b/pkg/sdk/eacl/enums_test.go @@ -0,0 +1,214 @@ +package eacl_test + +import ( + "testing" + + v2acl "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/acl" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/eacl" + "github.com/stretchr/testify/require" +) + +var ( + eqV2Actions = map[eacl.Action]v2acl.Action{ + eacl.ActionUnknown: v2acl.ActionUnknown, + eacl.ActionAllow: v2acl.ActionAllow, + eacl.ActionDeny: v2acl.ActionDeny, + } + + eqV2Operations = map[eacl.Operation]v2acl.Operation{ + eacl.OperationUnknown: v2acl.OperationUnknown, + eacl.OperationGet: v2acl.OperationGet, + eacl.OperationHead: v2acl.OperationHead, + eacl.OperationPut: v2acl.OperationPut, + eacl.OperationDelete: v2acl.OperationDelete, + eacl.OperationSearch: v2acl.OperationSearch, + eacl.OperationRange: v2acl.OperationRange, + eacl.OperationRangeHash: v2acl.OperationRangeHash, + } + + eqV2Roles = map[eacl.Role]v2acl.Role{ + eacl.RoleUnknown: v2acl.RoleUnknown, + eacl.RoleUser: v2acl.RoleUser, + eacl.RoleSystem: v2acl.RoleSystem, + eacl.RoleOthers: v2acl.RoleOthers, + } + + eqV2Matches = map[eacl.Match]v2acl.MatchType{ + eacl.MatchUnknown: v2acl.MatchTypeUnknown, + eacl.MatchStringEqual: v2acl.MatchTypeStringEqual, + eacl.MatchStringNotEqual: v2acl.MatchTypeStringNotEqual, + } + + eqV2HeaderTypes = map[eacl.FilterHeaderType]v2acl.HeaderType{ + eacl.HeaderTypeUnknown: v2acl.HeaderTypeUnknown, + eacl.HeaderFromRequest: v2acl.HeaderTypeRequest, + eacl.HeaderFromObject: v2acl.HeaderTypeObject, + eacl.HeaderFromService: v2acl.HeaderTypeService, + } +) + +func TestAction(t *testing.T) { + t.Run("known actions", func(t *testing.T) { + for i := eacl.ActionUnknown; i <= eacl.ActionDeny; i++ { + require.Equal(t, eqV2Actions[i], i.ToV2()) + require.Equal(t, eacl.ActionFromV2(i.ToV2()), i) + } + }) + + t.Run("unknown actions", func(t *testing.T) { + require.Equal(t, (eacl.ActionDeny + 1).ToV2(), v2acl.ActionUnknown) + require.Equal(t, eacl.ActionFromV2(v2acl.ActionDeny+1), eacl.ActionUnknown) + }) +} + +func TestOperation(t *testing.T) { + t.Run("known operations", func(t *testing.T) { + for i := eacl.OperationUnknown; i <= eacl.OperationRangeHash; i++ { + require.Equal(t, eqV2Operations[i], i.ToV2()) + require.Equal(t, eacl.OperationFromV2(i.ToV2()), i) + } + }) + + t.Run("unknown operations", func(t *testing.T) { + require.Equal(t, (eacl.OperationRangeHash + 1).ToV2(), v2acl.OperationUnknown) + require.Equal(t, eacl.OperationFromV2(v2acl.OperationRangeHash+1), eacl.OperationUnknown) + }) +} + +func TestRole(t *testing.T) { + t.Run("known roles", func(t *testing.T) { + for i := eacl.RoleUnknown; i <= eacl.RoleOthers; i++ { + require.Equal(t, eqV2Roles[i], i.ToV2()) + require.Equal(t, eacl.RoleFromV2(i.ToV2()), i) + } + }) + + t.Run("unknown roles", func(t *testing.T) { + require.Equal(t, (eacl.RoleOthers + 1).ToV2(), v2acl.RoleUnknown) + require.Equal(t, eacl.RoleFromV2(v2acl.RoleOthers+1), eacl.RoleUnknown) + }) +} + +func TestMatch(t *testing.T) { + t.Run("known matches", func(t *testing.T) { + for i := eacl.MatchUnknown; i <= eacl.MatchStringNotEqual; i++ { + require.Equal(t, eqV2Matches[i], i.ToV2()) + require.Equal(t, eacl.MatchFromV2(i.ToV2()), i) + } + }) + + t.Run("unknown matches", func(t *testing.T) { + require.Equal(t, (eacl.MatchStringNotEqual + 1).ToV2(), v2acl.MatchTypeUnknown) + require.Equal(t, eacl.MatchFromV2(v2acl.MatchTypeStringNotEqual+1), eacl.MatchUnknown) + }) +} + +func TestFilterHeaderType(t *testing.T) { + t.Run("known header types", func(t *testing.T) { + for i := eacl.HeaderTypeUnknown; i <= eacl.HeaderFromService; i++ { + require.Equal(t, eqV2HeaderTypes[i], i.ToV2()) + require.Equal(t, eacl.FilterHeaderTypeFromV2(i.ToV2()), i) + } + }) + + t.Run("unknown header types", func(t *testing.T) { + require.Equal(t, (eacl.HeaderFromService + 1).ToV2(), v2acl.HeaderTypeUnknown) + require.Equal(t, eacl.FilterHeaderTypeFromV2(v2acl.HeaderTypeService+1), eacl.HeaderTypeUnknown) + }) +} + +type enumIface interface { + FromString(string) bool + String() string +} + +type enumStringItem struct { + val enumIface + str string +} + +func testEnumStrings(t *testing.T, e enumIface, items []enumStringItem) { + for _, item := range items { + require.Equal(t, item.str, item.val.String()) + + s := item.val.String() + + require.True(t, e.FromString(s), s) + + require.EqualValues(t, item.val, e, item.val) + } + + // incorrect strings + for _, str := range []string{ + "some string", + "UNSPECIFIED", + } { + require.False(t, e.FromString(str)) + } +} + +func TestAction_String(t *testing.T) { + toPtr := func(v eacl.Action) *eacl.Action { + return &v + } + + testEnumStrings(t, new(eacl.Action), []enumStringItem{ + {val: toPtr(eacl.ActionAllow), str: "ALLOW"}, + {val: toPtr(eacl.ActionDeny), str: "DENY"}, + {val: toPtr(eacl.ActionUnknown), str: "ACTION_UNSPECIFIED"}, + }) +} + +func TestRole_String(t *testing.T) { + toPtr := func(v eacl.Role) *eacl.Role { + return &v + } + + testEnumStrings(t, new(eacl.Role), []enumStringItem{ + {val: toPtr(eacl.RoleUser), str: "USER"}, + {val: toPtr(eacl.RoleSystem), str: "SYSTEM"}, + {val: toPtr(eacl.RoleOthers), str: "OTHERS"}, + {val: toPtr(eacl.RoleUnknown), str: "ROLE_UNSPECIFIED"}, + }) +} + +func TestOperation_String(t *testing.T) { + toPtr := func(v eacl.Operation) *eacl.Operation { + return &v + } + + testEnumStrings(t, new(eacl.Operation), []enumStringItem{ + {val: toPtr(eacl.OperationGet), str: "GET"}, + {val: toPtr(eacl.OperationPut), str: "PUT"}, + {val: toPtr(eacl.OperationHead), str: "HEAD"}, + {val: toPtr(eacl.OperationDelete), str: "DELETE"}, + {val: toPtr(eacl.OperationSearch), str: "SEARCH"}, + {val: toPtr(eacl.OperationRange), str: "GETRANGE"}, + {val: toPtr(eacl.OperationRangeHash), str: "GETRANGEHASH"}, + {val: toPtr(eacl.OperationUnknown), str: "OPERATION_UNSPECIFIED"}, + }) +} + +func TestMatch_String(t *testing.T) { + toPtr := func(v eacl.Match) *eacl.Match { + return &v + } + + testEnumStrings(t, new(eacl.Match), []enumStringItem{ + {val: toPtr(eacl.MatchStringEqual), str: "STRING_EQUAL"}, + {val: toPtr(eacl.MatchStringNotEqual), str: "STRING_NOT_EQUAL"}, + {val: toPtr(eacl.MatchUnknown), str: "MATCH_TYPE_UNSPECIFIED"}, + }) +} + +func TestFilterHeaderType_String(t *testing.T) { + toPtr := func(v eacl.FilterHeaderType) *eacl.FilterHeaderType { + return &v + } + + testEnumStrings(t, new(eacl.FilterHeaderType), []enumStringItem{ + {val: toPtr(eacl.HeaderFromRequest), str: "REQUEST"}, + {val: toPtr(eacl.HeaderFromObject), str: "OBJECT"}, + {val: toPtr(eacl.HeaderTypeUnknown), str: "HEADER_UNSPECIFIED"}, + }) +} diff --git a/pkg/sdk/eacl/filter.go b/pkg/sdk/eacl/filter.go new file mode 100644 index 000000000..8f0d2af67 --- /dev/null +++ b/pkg/sdk/eacl/filter.go @@ -0,0 +1,209 @@ +package eacl + +import ( + "strconv" + + v2acl "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/acl" +) + +// Filter defines check conditions if request header is matched or not. Matched +// header means that request should be processed according to ContainerEACL action. +// +// Filter is compatible with v2 acl.EACLRecord.Filter message. +type Filter struct { + from FilterHeaderType + matcher Match + key filterKey + value stringEncoder +} + +type staticStringer string + +type u64Stringer uint64 + +type filterKey struct { + typ filterKeyType + + str string +} + +// enumeration of reserved filter keys. +type filterKeyType int + +const ( + _ filterKeyType = iota + fKeyObjVersion + fKeyObjID + fKeyObjContainerID + fKeyObjOwnerID + fKeyObjCreationEpoch + fKeyObjPayloadLength + fKeyObjPayloadHash + fKeyObjType + fKeyObjHomomorphicHash + fKeyObjLast // helper, used in tests +) + +func (s staticStringer) EncodeToString() string { + return string(s) +} + +func (u u64Stringer) EncodeToString() string { + return strconv.FormatUint(uint64(u), 10) +} + +// Value returns filtered string value. +func (f Filter) Value() string { + return f.value.EncodeToString() +} + +// Matcher returns filter Match type. +func (f Filter) Matcher() Match { + return f.matcher +} + +// Key returns key to the filtered header. +func (f Filter) Key() string { + return f.key.String() +} + +// From returns FilterHeaderType that defined which header will be filtered. +func (f Filter) From() FilterHeaderType { + return f.from +} + +// ToV2 converts Filter to v2 acl.EACLRecord.Filter message. +// +// Nil Filter converts to nil. +func (f *Filter) ToV2() *v2acl.HeaderFilter { + if f == nil { + return nil + } + + filter := new(v2acl.HeaderFilter) + filter.SetValue(f.value.EncodeToString()) + filter.SetKey(f.key.String()) + filter.SetMatchType(f.matcher.ToV2()) + filter.SetHeaderType(f.from.ToV2()) + + return filter +} + +func (k filterKey) String() string { + switch k.typ { + default: + return k.str + case fKeyObjVersion: + return v2acl.FilterObjectVersion + case fKeyObjID: + return v2acl.FilterObjectID + case fKeyObjContainerID: + return v2acl.FilterObjectContainerID + case fKeyObjOwnerID: + return v2acl.FilterObjectOwnerID + case fKeyObjCreationEpoch: + return v2acl.FilterObjectCreationEpoch + case fKeyObjPayloadLength: + return v2acl.FilterObjectPayloadLength + case fKeyObjPayloadHash: + return v2acl.FilterObjectPayloadHash + case fKeyObjType: + return v2acl.FilterObjectType + case fKeyObjHomomorphicHash: + return v2acl.FilterObjectHomomorphicHash + } +} + +func (k *filterKey) fromString(s string) { + switch s { + default: + k.typ, k.str = 0, s + case v2acl.FilterObjectVersion: + k.typ, k.str = fKeyObjVersion, "" + case v2acl.FilterObjectID: + k.typ, k.str = fKeyObjID, "" + case v2acl.FilterObjectContainerID: + k.typ, k.str = fKeyObjContainerID, "" + case v2acl.FilterObjectOwnerID: + k.typ, k.str = fKeyObjOwnerID, "" + case v2acl.FilterObjectCreationEpoch: + k.typ, k.str = fKeyObjCreationEpoch, "" + case v2acl.FilterObjectPayloadLength: + k.typ, k.str = fKeyObjPayloadLength, "" + case v2acl.FilterObjectPayloadHash: + k.typ, k.str = fKeyObjPayloadHash, "" + case v2acl.FilterObjectType: + k.typ, k.str = fKeyObjType, "" + case v2acl.FilterObjectHomomorphicHash: + k.typ, k.str = fKeyObjHomomorphicHash, "" + } +} + +// NewFilter creates, initializes and returns blank Filter instance. +// +// Defaults: +// - header type: HeaderTypeUnknown; +// - matcher: MatchUnknown; +// - key: ""; +// - value: "". +func NewFilter() *Filter { + return NewFilterFromV2(new(v2acl.HeaderFilter)) +} + +// NewFilterFromV2 converts v2 acl.EACLRecord.Filter message to Filter. +func NewFilterFromV2(filter *v2acl.HeaderFilter) *Filter { + f := new(Filter) + + if filter == nil { + return f + } + + f.from = FilterHeaderTypeFromV2(filter.GetHeaderType()) + f.matcher = MatchFromV2(filter.GetMatchType()) + f.key.fromString(filter.GetKey()) + f.value = staticStringer(filter.GetValue()) + + return f +} + +// Marshal marshals Filter into a protobuf binary form. +func (f *Filter) Marshal() ([]byte, error) { + return f.ToV2().StableMarshal(nil), nil +} + +// Unmarshal unmarshals protobuf binary representation of Filter. +func (f *Filter) Unmarshal(data []byte) error { + fV2 := new(v2acl.HeaderFilter) + if err := fV2.Unmarshal(data); err != nil { + return err + } + + *f = *NewFilterFromV2(fV2) + + return nil +} + +// MarshalJSON encodes Filter to protobuf JSON format. +func (f *Filter) MarshalJSON() ([]byte, error) { + return f.ToV2().MarshalJSON() +} + +// UnmarshalJSON decodes Filter from protobuf JSON format. +func (f *Filter) UnmarshalJSON(data []byte) error { + fV2 := new(v2acl.HeaderFilter) + if err := fV2.UnmarshalJSON(data); err != nil { + return err + } + + *f = *NewFilterFromV2(fV2) + + return nil +} + +// equalFilters compares Filter with each other. +func equalFilters(f1, f2 Filter) bool { + return f1.From() == f2.From() && + f1.Matcher() == f2.Matcher() && + f1.Key() == f2.Key() && + f1.Value() == f2.Value() +} diff --git a/pkg/sdk/eacl/filter_test.go b/pkg/sdk/eacl/filter_test.go new file mode 100644 index 000000000..6a5217257 --- /dev/null +++ b/pkg/sdk/eacl/filter_test.go @@ -0,0 +1,101 @@ +package eacl + +import ( + "strconv" + "testing" + + v2acl "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/acl" + "github.com/stretchr/testify/require" +) + +func newObjectFilter(match Match, key, val string) *Filter { + return &Filter{ + from: HeaderFromObject, + key: filterKey{ + str: key, + }, + matcher: match, + value: staticStringer(val), + } +} + +func TestFilter(t *testing.T) { + filter := newObjectFilter(MatchStringEqual, "some name", "200") + + v2 := filter.ToV2() + require.NotNil(t, v2) + require.Equal(t, v2acl.HeaderTypeObject, v2.GetHeaderType()) + require.EqualValues(t, v2acl.MatchTypeStringEqual, v2.GetMatchType()) + require.Equal(t, filter.Key(), v2.GetKey()) + require.Equal(t, filter.Value(), v2.GetValue()) + + newFilter := NewFilterFromV2(v2) + require.Equal(t, filter, newFilter) + + t.Run("from nil v2 filter", func(t *testing.T) { + require.Equal(t, new(Filter), NewFilterFromV2(nil)) + }) +} + +func TestFilterEncoding(t *testing.T) { + f := newObjectFilter(MatchStringEqual, "key", "value") + + t.Run("binary", func(t *testing.T) { + data, err := f.Marshal() + require.NoError(t, err) + + f2 := NewFilter() + require.NoError(t, f2.Unmarshal(data)) + + require.Equal(t, f, f2) + }) + + t.Run("json", func(t *testing.T) { + data, err := f.MarshalJSON() + require.NoError(t, err) + + d2 := NewFilter() + require.NoError(t, d2.UnmarshalJSON(data)) + + require.Equal(t, f, d2) + }) +} + +func TestFilter_ToV2(t *testing.T) { + t.Run("nil", func(t *testing.T) { + var x *Filter + + require.Nil(t, x.ToV2()) + }) + + t.Run("default values", func(t *testing.T) { + filter := NewFilter() + + // check initial values + require.Empty(t, filter.Key()) + require.Empty(t, filter.Value()) + require.Equal(t, HeaderTypeUnknown, filter.From()) + require.Equal(t, MatchUnknown, filter.Matcher()) + + // convert to v2 message + filterV2 := filter.ToV2() + + require.Empty(t, filterV2.GetKey()) + require.Empty(t, filterV2.GetValue()) + require.Equal(t, v2acl.HeaderTypeUnknown, filterV2.GetHeaderType()) + require.Equal(t, v2acl.MatchTypeUnknown, filterV2.GetMatchType()) + }) + + t.Run("reserved types", func(t *testing.T) { + r := NewRecord() + for i := filterKeyType(1); i < fKeyObjLast; i++ { + r.addObjectReservedFilter(MatchStringEqual, i, staticStringer(strconv.FormatUint(uint64(i), 16))) + } + + for i := range r.filters { + fv2 := r.filters[i].ToV2() + actual := NewFilterFromV2(fv2) + require.Equal(t, actual, &r.filters[i]) + } + }) +} diff --git a/pkg/sdk/eacl/record.go b/pkg/sdk/eacl/record.go new file mode 100644 index 000000000..684de7afb --- /dev/null +++ b/pkg/sdk/eacl/record.go @@ -0,0 +1,302 @@ +package eacl + +import ( + "crypto/ecdsa" + + v2acl "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/acl" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/checksum" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/version" +) + +// Record of the ContainerEACL rule, that defines ContainerEACL action, targets for this action, +// object service operation and filters for request headers. +// +// Record is compatible with v2 acl.EACLRecord message. +type Record struct { + action Action + operation Operation + filters []Filter + targets []Target +} + +// Targets returns list of target subjects to apply ACL rule to. +func (r Record) Targets() []Target { + return r.targets +} + +// SetTargets sets list of target subjects to apply ACL rule to. +func (r *Record) SetTargets(targets ...Target) { + r.targets = targets +} + +// Filters returns list of filters to match and see if rule is applicable. +func (r Record) Filters() []Filter { + return r.filters +} + +// Operation returns FrostFS request verb to match. +func (r Record) Operation() Operation { + return r.operation +} + +// SetOperation sets FrostFS request verb to match. +func (r *Record) SetOperation(operation Operation) { + r.operation = operation +} + +// Action returns rule execution result. +func (r Record) Action() Action { + return r.action +} + +// SetAction sets rule execution result. +func (r *Record) SetAction(action Action) { + r.action = action +} + +// AddRecordTarget adds single Target to the Record. +func AddRecordTarget(r *Record, t *Target) { + r.SetTargets(append(r.Targets(), *t)...) +} + +// AddFormedTarget forms Target with specified Role and list of +// ECDSA public keys and adds it to the Record. +func AddFormedTarget(r *Record, role Role, keys ...ecdsa.PublicKey) { + t := NewTarget() + t.SetRole(role) + + SetTargetECDSAKeys(t, ecdsaKeysToPtrs(keys)...) + AddRecordTarget(r, t) +} + +type stringEncoder interface { + EncodeToString() string +} + +func (r *Record) addFilter(from FilterHeaderType, m Match, keyTyp filterKeyType, key string, val stringEncoder) { + filter := Filter{ + from: from, + key: filterKey{ + typ: keyTyp, + str: key, + }, + matcher: m, + value: val, + } + + r.filters = append(r.filters, filter) +} + +func (r *Record) addObjectFilter(m Match, keyTyp filterKeyType, key string, val stringEncoder) { + r.addFilter(HeaderFromObject, m, keyTyp, key, val) +} + +func (r *Record) addObjectReservedFilter(m Match, typ filterKeyType, val stringEncoder) { + r.addObjectFilter(m, typ, "", val) +} + +// AddFilter adds generic filter. +func (r *Record) AddFilter(from FilterHeaderType, matcher Match, name, value string) { + r.addFilter(from, matcher, 0, name, staticStringer(value)) +} + +// AddObjectAttributeFilter adds filter by object attribute. +func (r *Record) AddObjectAttributeFilter(m Match, key, value string) { + r.addObjectFilter(m, 0, key, staticStringer(value)) +} + +// AddObjectVersionFilter adds filter by object version. +func (r *Record) AddObjectVersionFilter(m Match, v *version.Version) { + r.addObjectReservedFilter(m, fKeyObjVersion, staticStringer(version.EncodeToString(*v))) +} + +// AddObjectIDFilter adds filter by object ID. +func (r *Record) AddObjectIDFilter(m Match, id oid.ID) { + r.addObjectReservedFilter(m, fKeyObjID, id) +} + +// AddObjectContainerIDFilter adds filter by object container ID. +func (r *Record) AddObjectContainerIDFilter(m Match, id cid.ID) { + r.addObjectReservedFilter(m, fKeyObjContainerID, id) +} + +// AddObjectOwnerIDFilter adds filter by object owner ID. +func (r *Record) AddObjectOwnerIDFilter(m Match, id user.ID) { + r.addObjectReservedFilter(m, fKeyObjOwnerID, id) +} + +// AddObjectCreationEpoch adds filter by object creation epoch. +func (r *Record) AddObjectCreationEpoch(m Match, epoch uint64) { + r.addObjectReservedFilter(m, fKeyObjCreationEpoch, u64Stringer(epoch)) +} + +// AddObjectPayloadLengthFilter adds filter by object payload length. +func (r *Record) AddObjectPayloadLengthFilter(m Match, size uint64) { + r.addObjectReservedFilter(m, fKeyObjPayloadLength, u64Stringer(size)) +} + +// AddObjectPayloadHashFilter adds filter by object payload hash value. +func (r *Record) AddObjectPayloadHashFilter(m Match, h checksum.Checksum) { + r.addObjectReservedFilter(m, fKeyObjPayloadHash, staticStringer(h.String())) +} + +// AddObjectTypeFilter adds filter by object type. +func (r *Record) AddObjectTypeFilter(m Match, t object.Type) { + r.addObjectReservedFilter(m, fKeyObjType, staticStringer(t.String())) +} + +// AddObjectHomomorphicHashFilter adds filter by object payload homomorphic hash value. +func (r *Record) AddObjectHomomorphicHashFilter(m Match, h checksum.Checksum) { + r.addObjectReservedFilter(m, fKeyObjHomomorphicHash, staticStringer(h.String())) +} + +// ToV2 converts Record to v2 acl.EACLRecord message. +// +// Nil Record converts to nil. +func (r *Record) ToV2() *v2acl.Record { + if r == nil { + return nil + } + + v2 := new(v2acl.Record) + + if r.targets != nil { + targets := make([]v2acl.Target, len(r.targets)) + for i := range r.targets { + targets[i] = *r.targets[i].ToV2() + } + + v2.SetTargets(targets) + } + + if r.filters != nil { + filters := make([]v2acl.HeaderFilter, len(r.filters)) + for i := range r.filters { + filters[i] = *r.filters[i].ToV2() + } + + v2.SetFilters(filters) + } + + v2.SetAction(r.action.ToV2()) + v2.SetOperation(r.operation.ToV2()) + + return v2 +} + +// NewRecord creates and returns blank Record instance. +// +// Defaults: +// - action: ActionUnknown; +// - operation: OperationUnknown; +// - targets: nil, +// - filters: nil. +func NewRecord() *Record { + return new(Record) +} + +// CreateRecord creates, initializes with parameters and returns Record instance. +func CreateRecord(action Action, operation Operation) *Record { + r := NewRecord() + r.action = action + r.operation = operation + r.targets = []Target{} + r.filters = []Filter{} + + return r +} + +// NewRecordFromV2 converts v2 acl.EACLRecord message to Record. +func NewRecordFromV2(record *v2acl.Record) *Record { + r := NewRecord() + + if record == nil { + return r + } + + r.action = ActionFromV2(record.GetAction()) + r.operation = OperationFromV2(record.GetOperation()) + + v2targets := record.GetTargets() + v2filters := record.GetFilters() + + r.targets = make([]Target, len(v2targets)) + for i := range v2targets { + r.targets[i] = *NewTargetFromV2(&v2targets[i]) + } + + r.filters = make([]Filter, len(v2filters)) + for i := range v2filters { + r.filters[i] = *NewFilterFromV2(&v2filters[i]) + } + + return r +} + +// Marshal marshals Record into a protobuf binary form. +func (r *Record) Marshal() ([]byte, error) { + return r.ToV2().StableMarshal(nil), nil +} + +// Unmarshal unmarshals protobuf binary representation of Record. +func (r *Record) Unmarshal(data []byte) error { + fV2 := new(v2acl.Record) + if err := fV2.Unmarshal(data); err != nil { + return err + } + + *r = *NewRecordFromV2(fV2) + + return nil +} + +// MarshalJSON encodes Record to protobuf JSON format. +func (r *Record) MarshalJSON() ([]byte, error) { + return r.ToV2().MarshalJSON() +} + +// UnmarshalJSON decodes Record from protobuf JSON format. +func (r *Record) UnmarshalJSON(data []byte) error { + tV2 := new(v2acl.Record) + if err := tV2.UnmarshalJSON(data); err != nil { + return err + } + + *r = *NewRecordFromV2(tV2) + + return nil +} + +// equalRecords compares Record with each other. +func equalRecords(r1, r2 Record) bool { + if r1.Operation() != r2.Operation() || + r1.Action() != r2.Action() { + return false + } + + fs1, fs2 := r1.Filters(), r2.Filters() + ts1, ts2 := r1.Targets(), r2.Targets() + + if len(fs1) != len(fs2) || + len(ts1) != len(ts2) { + return false + } + + for i := 0; i < len(fs1); i++ { + if !equalFilters(fs1[i], fs2[i]) { + return false + } + } + + for i := 0; i < len(ts1); i++ { + if !equalTargets(ts1[i], ts2[i]) { + return false + } + } + + return true +} diff --git a/pkg/sdk/eacl/record_test.go b/pkg/sdk/eacl/record_test.go new file mode 100644 index 000000000..ef3c8a012 --- /dev/null +++ b/pkg/sdk/eacl/record_test.go @@ -0,0 +1,245 @@ +package eacl + +import ( + "crypto/ecdsa" + "fmt" + "testing" + + v2acl "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/acl" + checksumtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/checksum/test" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id/test" + usertest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user/test" + versiontest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/version/test" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + "github.com/stretchr/testify/require" +) + +func TestRecord(t *testing.T) { + record := NewRecord() + record.SetOperation(OperationRange) + record.SetAction(ActionAllow) + record.AddFilter(HeaderFromRequest, MatchStringEqual, "A", "B") + record.AddFilter(HeaderFromRequest, MatchStringNotEqual, "C", "D") + + target := NewTarget() + target.SetRole(RoleSystem) + AddRecordTarget(record, target) + + v2 := record.ToV2() + require.NotNil(t, v2) + require.Equal(t, v2acl.OperationRange, v2.GetOperation()) + require.Equal(t, v2acl.ActionAllow, v2.GetAction()) + require.Len(t, v2.GetFilters(), len(record.Filters())) + require.Len(t, v2.GetTargets(), len(record.Targets())) + + newRecord := NewRecordFromV2(v2) + require.Equal(t, record, newRecord) + + t.Run("create record", func(t *testing.T) { + record := CreateRecord(ActionAllow, OperationGet) + require.Equal(t, ActionAllow, record.Action()) + require.Equal(t, OperationGet, record.Operation()) + }) + + t.Run("new from nil v2 record", func(t *testing.T) { + require.Equal(t, new(Record), NewRecordFromV2(nil)) + }) +} + +func TestAddFormedTarget(t *testing.T) { + items := []struct { + role Role + keys []ecdsa.PublicKey + }{ + { + role: RoleUnknown, + keys: []ecdsa.PublicKey{*randomPublicKey(t)}, + }, + { + role: RoleSystem, + keys: []ecdsa.PublicKey{}, + }, + } + + targets := make([]Target, len(items)) + + r := NewRecord() + + for i := range items { + targets[i].SetRole(items[i].role) + SetTargetECDSAKeys(&targets[i], ecdsaKeysToPtrs(items[i].keys)...) + AddFormedTarget(r, items[i].role, items[i].keys...) + } + + tgts := r.Targets() + require.Len(t, tgts, len(targets)) + + for _, tgt := range targets { + require.Contains(t, tgts, tgt) + } +} + +func TestRecord_AddFilter(t *testing.T) { + filters := []Filter{ + *newObjectFilter(MatchStringEqual, "some name", "ContainerID"), + *newObjectFilter(MatchStringNotEqual, "X-Header-Name", "X-Header-Value"), + } + + r := NewRecord() + for _, filter := range filters { + r.AddFilter(filter.From(), filter.Matcher(), filter.Key(), filter.Value()) + } + + require.Equal(t, filters, r.Filters()) +} + +func TestRecordEncoding(t *testing.T) { + r := NewRecord() + r.SetOperation(OperationHead) + r.SetAction(ActionDeny) + r.AddObjectAttributeFilter(MatchStringEqual, "key", "value") + AddFormedTarget(r, RoleSystem, *randomPublicKey(t)) + + t.Run("binary", func(t *testing.T) { + data, err := r.Marshal() + require.NoError(t, err) + + r2 := NewRecord() + require.NoError(t, r2.Unmarshal(data)) + + require.Equal(t, r, r2) + }) + + t.Run("json", func(t *testing.T) { + data, err := r.MarshalJSON() + require.NoError(t, err) + + r2 := NewRecord() + require.NoError(t, r2.UnmarshalJSON(data)) + + require.Equal(t, r, r2) + }) +} + +func TestRecord_ToV2(t *testing.T) { + t.Run("nil", func(t *testing.T) { + var x *Record + + require.Nil(t, x.ToV2()) + }) + + t.Run("default values", func(t *testing.T) { + record := NewRecord() + + // check initial values + require.Equal(t, OperationUnknown, record.Operation()) + require.Equal(t, ActionUnknown, record.Action()) + require.Nil(t, record.Targets()) + require.Nil(t, record.Filters()) + + // convert to v2 message + recordV2 := record.ToV2() + + require.Equal(t, v2acl.OperationUnknown, recordV2.GetOperation()) + require.Equal(t, v2acl.ActionUnknown, recordV2.GetAction()) + require.Nil(t, recordV2.GetTargets()) + require.Nil(t, recordV2.GetFilters()) + }) +} + +func TestReservedRecords(t *testing.T) { + var ( + v = versiontest.Version() + oid = oidtest.ID() + cid = cidtest.ID() + ownerid = usertest.ID() + h = checksumtest.Checksum() + typ = new(object.Type) + ) + + testSuit := []struct { + f func(r *Record) + key string + value string + }{ + { + f: func(r *Record) { r.AddObjectAttributeFilter(MatchStringEqual, "foo", "bar") }, + key: "foo", + value: "bar", + }, + { + f: func(r *Record) { r.AddObjectVersionFilter(MatchStringEqual, &v) }, + key: v2acl.FilterObjectVersion, + value: v.String(), + }, + { + f: func(r *Record) { r.AddObjectIDFilter(MatchStringEqual, oid) }, + key: v2acl.FilterObjectID, + value: oid.EncodeToString(), + }, + { + f: func(r *Record) { r.AddObjectContainerIDFilter(MatchStringEqual, cid) }, + key: v2acl.FilterObjectContainerID, + value: cid.EncodeToString(), + }, + { + f: func(r *Record) { r.AddObjectOwnerIDFilter(MatchStringEqual, ownerid) }, + key: v2acl.FilterObjectOwnerID, + value: ownerid.EncodeToString(), + }, + { + f: func(r *Record) { r.AddObjectCreationEpoch(MatchStringEqual, 100) }, + key: v2acl.FilterObjectCreationEpoch, + value: "100", + }, + { + f: func(r *Record) { r.AddObjectPayloadLengthFilter(MatchStringEqual, 5000) }, + key: v2acl.FilterObjectPayloadLength, + value: "5000", + }, + { + f: func(r *Record) { r.AddObjectPayloadHashFilter(MatchStringEqual, h) }, + key: v2acl.FilterObjectPayloadHash, + value: h.String(), + }, + { + f: func(r *Record) { r.AddObjectHomomorphicHashFilter(MatchStringEqual, h) }, + key: v2acl.FilterObjectHomomorphicHash, + value: h.String(), + }, + { + f: func(r *Record) { + require.True(t, typ.FromString("REGULAR")) + r.AddObjectTypeFilter(MatchStringEqual, *typ) + }, + key: v2acl.FilterObjectType, + value: "REGULAR", + }, + { + f: func(r *Record) { + require.True(t, typ.FromString("TOMBSTONE")) + r.AddObjectTypeFilter(MatchStringEqual, *typ) + }, + key: v2acl.FilterObjectType, + value: "TOMBSTONE", + }, + } + + for n, testCase := range testSuit { + desc := fmt.Sprintf("case #%d", n) + record := NewRecord() + testCase.f(record) + require.Len(t, record.Filters(), 1, desc) + f := record.Filters()[0] + require.Equal(t, f.Key(), testCase.key, desc) + require.Equal(t, f.Value(), testCase.value, desc) + } +} + +func randomPublicKey(t *testing.T) *ecdsa.PublicKey { + p, err := keys.NewPrivateKey() + require.NoError(t, err) + return &p.PrivateKey.PublicKey +} diff --git a/pkg/sdk/eacl/table.go b/pkg/sdk/eacl/table.go new file mode 100644 index 000000000..e6aa8fae3 --- /dev/null +++ b/pkg/sdk/eacl/table.go @@ -0,0 +1,238 @@ +package eacl + +import ( + "crypto/sha256" + "fmt" + + v2acl "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/acl" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/version" +) + +// Table is a group of ContainerEACL records for single container. +// +// Table is compatible with v2 acl.EACLTable message. +type Table struct { + version version.Version + cid *cid.ID + records []Record +} + +// CID returns identifier of the container that should use given access control rules. +func (t Table) CID() (cID cid.ID, isSet bool) { + if t.cid != nil { + cID = *t.cid + isSet = true + } + + return +} + +// SetCID sets identifier of the container that should use given access control rules. +func (t *Table) SetCID(cid cid.ID) { + t.cid = &cid +} + +// Version returns version of eACL format. +func (t Table) Version() version.Version { + return t.version +} + +// SetVersion sets version of eACL format. +func (t *Table) SetVersion(version version.Version) { + t.version = version +} + +// Records returns list of extended ACL rules. +func (t Table) Records() []Record { + return t.records +} + +// AddRecord adds single eACL rule. +func (t *Table) AddRecord(r *Record) { + if r != nil { + t.records = append(t.records, *r) + } +} + +// ToV2 converts Table to v2 acl.EACLTable message. +// +// Nil Table converts to nil. +func (t *Table) ToV2() *v2acl.Table { + if t == nil { + return nil + } + + v2 := new(v2acl.Table) + var cidV2 refs.ContainerID + + if t.cid != nil { + t.cid.WriteToV2(&cidV2) + v2.SetContainerID(&cidV2) + } + + if t.records != nil { + records := make([]v2acl.Record, len(t.records)) + for i := range t.records { + records[i] = *t.records[i].ToV2() + } + + v2.SetRecords(records) + } + + var verV2 refs.Version + t.version.WriteToV2(&verV2) + v2.SetVersion(&verV2) + + return v2 +} + +// NewTable creates, initializes and returns blank Table instance. +// +// Defaults: +// - version: version.Current(); +// - container ID: nil; +// - records: nil; +// - session token: nil; +// - signature: nil. +func NewTable() *Table { + t := new(Table) + t.SetVersion(version.Current()) + + return t +} + +// CreateTable creates, initializes with parameters and returns Table instance. +func CreateTable(cid cid.ID) *Table { + t := NewTable() + t.SetCID(cid) + + return t +} + +// NewTableFromV2 converts v2 acl.EACLTable message to Table. +func NewTableFromV2(table *v2acl.Table) *Table { + t := new(Table) + + if table == nil { + return t + } + + // set version + if v := table.GetVersion(); v != nil { + ver := version.Version{} + ver.SetMajor(v.GetMajor()) + ver.SetMinor(v.GetMinor()) + + t.SetVersion(ver) + } + + // set container id + if id := table.GetContainerID(); id != nil { + if t.cid == nil { + t.cid = new(cid.ID) + } + + var h [sha256.Size]byte + + copy(h[:], id.GetValue()) + t.cid.SetSHA256(h) + } + + // set eacl records + v2records := table.GetRecords() + t.records = make([]Record, len(v2records)) + + for i := range v2records { + t.records[i] = *NewRecordFromV2(&v2records[i]) + } + + return t +} + +// Marshal marshals Table into a protobuf binary form. +func (t *Table) Marshal() ([]byte, error) { + return t.ToV2().StableMarshal(nil), nil +} + +// Unmarshal unmarshals protobuf binary representation of Table. +func (t *Table) Unmarshal(data []byte) error { + fV2 := new(v2acl.Table) + if err := fV2.Unmarshal(data); err != nil { + return err + } + + // format checks + err := checkFormat(fV2) + if err != nil { + return err + } + + *t = *NewTableFromV2(fV2) + + return nil +} + +// MarshalJSON encodes Table to protobuf JSON format. +func (t *Table) MarshalJSON() ([]byte, error) { + return t.ToV2().MarshalJSON() +} + +// UnmarshalJSON decodes Table from protobuf JSON format. +func (t *Table) UnmarshalJSON(data []byte) error { + tV2 := new(v2acl.Table) + if err := tV2.UnmarshalJSON(data); err != nil { + return err + } + + err := checkFormat(tV2) + if err != nil { + return err + } + + *t = *NewTableFromV2(tV2) + + return nil +} + +// EqualTables compares Table with each other. +func EqualTables(t1, t2 Table) bool { + cID1, set1 := t1.CID() + cID2, set2 := t2.CID() + + if set1 != set2 || cID1 != cID2 || + !t1.Version().Equal(t2.Version()) { + return false + } + + rs1, rs2 := t1.Records(), t2.Records() + + if len(rs1) != len(rs2) { + return false + } + + for i := 0; i < len(rs1); i++ { + if !equalRecords(rs1[i], rs2[i]) { + return false + } + } + + return true +} + +func checkFormat(v2 *v2acl.Table) error { + var cID cid.ID + + cidV2 := v2.GetContainerID() + if cidV2 == nil { + return nil + } + + err := cID.ReadFromV2(*cidV2) + if err != nil { + return fmt.Errorf("could not convert V2 container ID: %w", err) + } + + return nil +} diff --git a/pkg/sdk/eacl/table_test.go b/pkg/sdk/eacl/table_test.go new file mode 100644 index 000000000..f2f540e09 --- /dev/null +++ b/pkg/sdk/eacl/table_test.go @@ -0,0 +1,119 @@ +package eacl_test + +import ( + "crypto/sha256" + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/eacl" + eacltest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/eacl/test" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/version" + "github.com/stretchr/testify/require" +) + +func TestTable(t *testing.T) { + var v version.Version + + sha := sha256.Sum256([]byte("container id")) + id := cidtest.IDWithChecksum(sha) + + v.SetMajor(3) + v.SetMinor(2) + + table := eacl.NewTable() + table.SetVersion(v) + table.SetCID(id) + table.AddRecord(eacl.CreateRecord(eacl.ActionAllow, eacl.OperationPut)) + + v2 := table.ToV2() + require.NotNil(t, v2) + require.Equal(t, uint32(3), v2.GetVersion().GetMajor()) + require.Equal(t, uint32(2), v2.GetVersion().GetMinor()) + require.Equal(t, sha[:], v2.GetContainerID().GetValue()) + require.Len(t, v2.GetRecords(), 1) + + newTable := eacl.NewTableFromV2(v2) + require.Equal(t, table, newTable) + + t.Run("new from nil v2 table", func(t *testing.T) { + require.Equal(t, new(eacl.Table), eacl.NewTableFromV2(nil)) + }) + + t.Run("create table", func(t *testing.T) { + id := cidtest.ID() + + table := eacl.CreateTable(id) + cID, set := table.CID() + require.True(t, set) + require.Equal(t, id, cID) + require.Equal(t, version.Current(), table.Version()) + }) +} + +func TestTable_AddRecord(t *testing.T) { + records := []eacl.Record{ + *eacl.CreateRecord(eacl.ActionDeny, eacl.OperationDelete), + *eacl.CreateRecord(eacl.ActionAllow, eacl.OperationPut), + } + + table := eacl.NewTable() + for _, record := range records { + table.AddRecord(&record) + } + + require.Equal(t, records, table.Records()) +} + +func TestTableEncoding(t *testing.T) { + tab := eacltest.Table() + + t.Run("binary", func(t *testing.T) { + data, err := tab.Marshal() + require.NoError(t, err) + + tab2 := eacl.NewTable() + require.NoError(t, tab2.Unmarshal(data)) + + // FIXME: we compare v2 messages because + // Filter contains fmt.Stringer interface + require.Equal(t, tab.ToV2(), tab2.ToV2()) + }) + + t.Run("json", func(t *testing.T) { + data, err := tab.MarshalJSON() + require.NoError(t, err) + + tab2 := eacl.NewTable() + require.NoError(t, tab2.UnmarshalJSON(data)) + + require.Equal(t, tab.ToV2(), tab2.ToV2()) + }) +} + +func TestTable_ToV2(t *testing.T) { + t.Run("nil", func(t *testing.T) { + var x *eacl.Table + + require.Nil(t, x.ToV2()) + }) + + t.Run("default values", func(t *testing.T) { + table := eacl.NewTable() + + // check initial values + require.Equal(t, version.Current(), table.Version()) + require.Nil(t, table.Records()) + _, set := table.CID() + require.False(t, set) + + // convert to v2 message + tableV2 := table.ToV2() + + var verV2 refs.Version + version.Current().WriteToV2(&verV2) + require.Equal(t, verV2, *tableV2.GetVersion()) + require.Nil(t, tableV2.GetRecords()) + require.Nil(t, tableV2.GetContainerID()) + }) +} diff --git a/pkg/sdk/eacl/target.go b/pkg/sdk/eacl/target.go new file mode 100644 index 000000000..20f24298c --- /dev/null +++ b/pkg/sdk/eacl/target.go @@ -0,0 +1,179 @@ +package eacl + +import ( + "bytes" + "crypto/ecdsa" + + v2acl "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/acl" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" +) + +// Target is a group of request senders to match ContainerEACL. Defined by role enum +// and set of public keys. +// +// Target is compatible with v2 acl.EACLRecord.Target message. +type Target struct { + role Role + keys [][]byte +} + +func ecdsaKeysToPtrs(keys []ecdsa.PublicKey) []*ecdsa.PublicKey { + keysPtr := make([]*ecdsa.PublicKey, len(keys)) + + for i := range keys { + keysPtr[i] = &keys[i] + } + + return keysPtr +} + +// BinaryKeys returns list of public keys to identify +// target subject in a binary format. +func (t *Target) BinaryKeys() [][]byte { + return t.keys +} + +// SetBinaryKeys sets list of binary public keys to identify +// target subject. +func (t *Target) SetBinaryKeys(keys [][]byte) { + t.keys = keys +} + +// SetTargetECDSAKeys converts ECDSA public keys to a binary +// format and stores them in Target. +func SetTargetECDSAKeys(t *Target, pubs ...*ecdsa.PublicKey) { + binKeys := t.BinaryKeys() + ln := len(pubs) + + if cap(binKeys) >= ln { + binKeys = binKeys[:0] + } else { + binKeys = make([][]byte, 0, ln) + } + + for i := 0; i < ln; i++ { + binKeys = append(binKeys, (*keys.PublicKey)(pubs[i]).Bytes()) + } + + t.SetBinaryKeys(binKeys) +} + +// TargetECDSAKeys interprets binary public keys of Target +// as ECDSA public keys. If any key has a different format, +// the corresponding element will be nil. +func TargetECDSAKeys(t *Target) []*ecdsa.PublicKey { + binKeys := t.BinaryKeys() + ln := len(binKeys) + + pubs := make([]*ecdsa.PublicKey, ln) + + for i := 0; i < ln; i++ { + p := new(keys.PublicKey) + if p.DecodeBytes(binKeys[i]) == nil { + pubs[i] = (*ecdsa.PublicKey)(p) + } + } + + return pubs +} + +// SetRole sets target subject's role class. +func (t *Target) SetRole(r Role) { + t.role = r +} + +// Role returns target subject's role class. +func (t Target) Role() Role { + return t.role +} + +// ToV2 converts Target to v2 acl.EACLRecord.Target message. +// +// Nil Target converts to nil. +func (t *Target) ToV2() *v2acl.Target { + if t == nil { + return nil + } + + target := new(v2acl.Target) + target.SetRole(t.role.ToV2()) + target.SetKeys(t.keys) + + return target +} + +// NewTarget creates, initializes and returns blank Target instance. +// +// Defaults: +// - role: RoleUnknown; +// - keys: nil. +func NewTarget() *Target { + return NewTargetFromV2(new(v2acl.Target)) +} + +// NewTargetFromV2 converts v2 acl.EACLRecord.Target message to Target. +func NewTargetFromV2(target *v2acl.Target) *Target { + if target == nil { + return new(Target) + } + + return &Target{ + role: RoleFromV2(target.GetRole()), + keys: target.GetKeys(), + } +} + +// Marshal marshals Target into a protobuf binary form. +func (t *Target) Marshal() ([]byte, error) { + return t.ToV2().StableMarshal(nil), nil +} + +// Unmarshal unmarshals protobuf binary representation of Target. +func (t *Target) Unmarshal(data []byte) error { + fV2 := new(v2acl.Target) + if err := fV2.Unmarshal(data); err != nil { + return err + } + + *t = *NewTargetFromV2(fV2) + + return nil +} + +// MarshalJSON encodes Target to protobuf JSON format. +func (t *Target) MarshalJSON() ([]byte, error) { + return t.ToV2().MarshalJSON() +} + +// UnmarshalJSON decodes Target from protobuf JSON format. +func (t *Target) UnmarshalJSON(data []byte) error { + tV2 := new(v2acl.Target) + if err := tV2.UnmarshalJSON(data); err != nil { + return err + } + + *t = *NewTargetFromV2(tV2) + + return nil +} + +// equalTargets compares Target with each other. +func equalTargets(t1, t2 Target) bool { + if t1.Role() != t2.Role() { + return false + } + + keys1, keys2 := t1.BinaryKeys(), t2.BinaryKeys() + + if len(keys1) != len(keys2) { + return false + } + + for i := 0; i < len(keys1); i++ { + if !bytes.Equal(keys1[i], keys2[i]) { + return false + } + } + + return true +} diff --git a/pkg/sdk/eacl/target_test.go b/pkg/sdk/eacl/target_test.go new file mode 100644 index 000000000..d5a9c1f83 --- /dev/null +++ b/pkg/sdk/eacl/target_test.go @@ -0,0 +1,84 @@ +package eacl + +import ( + "crypto/ecdsa" + "testing" + + v2acl "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/acl" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + "github.com/stretchr/testify/require" +) + +func TestTarget(t *testing.T) { + pubs := []*ecdsa.PublicKey{ + randomPublicKey(t), + randomPublicKey(t), + } + + target := NewTarget() + target.SetRole(RoleSystem) + SetTargetECDSAKeys(target, pubs...) + + v2 := target.ToV2() + require.NotNil(t, v2) + require.Equal(t, v2acl.RoleSystem, v2.GetRole()) + require.Len(t, v2.GetKeys(), len(pubs)) + for i, key := range v2.GetKeys() { + require.Equal(t, key, (*keys.PublicKey)(pubs[i]).Bytes()) + } + + newTarget := NewTargetFromV2(v2) + require.Equal(t, target, newTarget) + + t.Run("from nil v2 target", func(t *testing.T) { + require.Equal(t, new(Target), NewTargetFromV2(nil)) + }) +} + +func TestTargetEncoding(t *testing.T) { + tar := NewTarget() + tar.SetRole(RoleSystem) + SetTargetECDSAKeys(tar, randomPublicKey(t)) + + t.Run("binary", func(t *testing.T) { + data, err := tar.Marshal() + require.NoError(t, err) + + tar2 := NewTarget() + require.NoError(t, tar2.Unmarshal(data)) + + require.Equal(t, tar, tar2) + }) + + t.Run("json", func(t *testing.T) { + data, err := tar.MarshalJSON() + require.NoError(t, err) + + tar2 := NewTarget() + require.NoError(t, tar2.UnmarshalJSON(data)) + + require.Equal(t, tar, tar2) + }) +} + +func TestTarget_ToV2(t *testing.T) { + t.Run("nil", func(t *testing.T) { + var x *Target + + require.Nil(t, x.ToV2()) + }) + + t.Run("default values", func(t *testing.T) { + target := NewTarget() + + // check initial values + require.Equal(t, RoleUnknown, target.Role()) + require.Nil(t, target.BinaryKeys()) + + // convert to v2 message + targetV2 := target.ToV2() + + require.Equal(t, v2acl.RoleUnknown, targetV2.GetRole()) + require.Nil(t, targetV2.GetKeys()) + }) +} diff --git a/pkg/sdk/eacl/test/benchmark_test.go b/pkg/sdk/eacl/test/benchmark_test.go new file mode 100644 index 000000000..72c133e05 --- /dev/null +++ b/pkg/sdk/eacl/test/benchmark_test.go @@ -0,0 +1,116 @@ +package eacltest + +import ( + "bytes" + "crypto/rand" + "testing" + + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/eacl" + versiontest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/version/test" + "github.com/stretchr/testify/require" +) + +func baseBenchmarkTableBinaryComparison(b *testing.B, factor int) { + t := TableN(factor) + exp, err := t.Marshal() + require.NoError(b, err) + + b.StopTimer() + b.ResetTimer() + b.StartTimer() + for i := 0; i < b.N; i++ { + got, _ := t.Marshal() + if !bytes.Equal(exp, got) { + b.Fail() + } + } +} + +func baseBenchmarkTableEqualsComparison(b *testing.B, factor int) { + t := TableN(factor) + data, err := t.Marshal() + require.NoError(b, err) + t2 := eacl.NewTable() + err = t2.Unmarshal(data) + require.NoError(b, err) + + b.StopTimer() + b.ResetTimer() + b.StartTimer() + for i := 0; i < b.N; i++ { + if !eacl.EqualTables(*t, *t2) { + b.Fail() + } + } +} + +func BenchmarkTableBinaryComparison(b *testing.B) { + baseBenchmarkTableBinaryComparison(b, 1) +} + +func BenchmarkTableEqualsComparison(b *testing.B) { + baseBenchmarkTableEqualsComparison(b, 1) +} + +func BenchmarkTableBinaryComparison10(b *testing.B) { + baseBenchmarkTableBinaryComparison(b, 10) +} + +func BenchmarkTableEqualsComparison10(b *testing.B) { + baseBenchmarkTableEqualsComparison(b, 10) +} + +func BenchmarkTableBinaryComparison100(b *testing.B) { + baseBenchmarkTableBinaryComparison(b, 100) +} + +func BenchmarkTableEqualsComparison100(b *testing.B) { + baseBenchmarkTableEqualsComparison(b, 100) +} + +// Target returns random eacl.Target. +func TargetN(n int) *eacl.Target { + x := eacl.NewTarget() + + x.SetRole(eacl.RoleSystem) + keys := make([][]byte, n) + + for i := 0; i < n; i++ { + keys[i] = make([]byte, 32) + rand.Read(keys[i]) + } + + x.SetBinaryKeys(keys) + + return x +} + +// Record returns random eacl.Record. +func RecordN(n int) *eacl.Record { + x := eacl.NewRecord() + + x.SetAction(eacl.ActionAllow) + x.SetOperation(eacl.OperationRangeHash) + x.SetTargets(*TargetN(n)) + + for i := 0; i < n; i++ { + x.AddFilter(eacl.HeaderFromObject, eacl.MatchStringEqual, "", cidtest.ID().EncodeToString()) + } + + return x +} + +func TableN(n int) *eacl.Table { + x := eacl.NewTable() + + x.SetCID(cidtest.ID()) + + for i := 0; i < n; i++ { + x.AddRecord(RecordN(n)) + } + + x.SetVersion(versiontest.Version()) + + return x +} diff --git a/pkg/sdk/eacl/test/generate.go b/pkg/sdk/eacl/test/generate.go new file mode 100644 index 000000000..3fa03c4f1 --- /dev/null +++ b/pkg/sdk/eacl/test/generate.go @@ -0,0 +1,45 @@ +package eacltest + +import ( + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/eacl" + usertest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user/test" + versiontest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/version/test" +) + +// Target returns random eacl.Target. +func Target() *eacl.Target { + x := eacl.NewTarget() + + x.SetRole(eacl.RoleSystem) + x.SetBinaryKeys([][]byte{ + {1, 2, 3}, + {4, 5, 6}, + }) + + return x +} + +// Record returns random eacl.Record. +func Record() *eacl.Record { + x := eacl.NewRecord() + + x.SetAction(eacl.ActionAllow) + x.SetOperation(eacl.OperationRangeHash) + x.SetTargets(*Target(), *Target()) + x.AddObjectContainerIDFilter(eacl.MatchStringEqual, cidtest.ID()) + x.AddObjectOwnerIDFilter(eacl.MatchStringNotEqual, usertest.ID()) + + return x +} + +func Table() *eacl.Table { + x := eacl.NewTable() + + x.SetCID(cidtest.ID()) + x.AddRecord(Record()) + x.AddRecord(Record()) + x.SetVersion(versiontest.Version()) + + return x +} diff --git a/pkg/sdk/eacl/types.go b/pkg/sdk/eacl/types.go new file mode 100644 index 000000000..8ed49f2e7 --- /dev/null +++ b/pkg/sdk/eacl/types.go @@ -0,0 +1,91 @@ +package eacl + +import ( + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" +) + +// Header is an interface of string key-value header. +type Header interface { + Key() string + Value() string +} + +// TypedHeaderSource is the interface that wraps +// method for selecting typed headers by type. +type TypedHeaderSource interface { + // HeadersOfType returns the list of key-value headers + // of particular type. + // + // It returns any problem encountered through the boolean + // false value. + HeadersOfType(FilterHeaderType) ([]Header, bool) +} + +// ValidationUnit represents unit of check for Validator. +type ValidationUnit struct { + cid *cid.ID + + role Role + + op Operation + + hdrSrc TypedHeaderSource + + key []byte + + table *Table +} + +// WithContainerID configures ValidationUnit to use v as request's container ID. +func (u *ValidationUnit) WithContainerID(v *cid.ID) *ValidationUnit { + if u != nil { + u.cid = v + } + + return u +} + +// WithRole configures ValidationUnit to use v as request's role. +func (u *ValidationUnit) WithRole(v Role) *ValidationUnit { + if u != nil { + u.role = v + } + + return u +} + +// WithOperation configures ValidationUnit to use v as request's operation. +func (u *ValidationUnit) WithOperation(v Operation) *ValidationUnit { + if u != nil { + u.op = v + } + + return u +} + +// WithHeaderSource configures ValidationUnit to use v as a source of headers. +func (u *ValidationUnit) WithHeaderSource(v TypedHeaderSource) *ValidationUnit { + if u != nil { + u.hdrSrc = v + } + + return u +} + +// WithSenderKey configures ValidationUnit to use as sender's public key. +func (u *ValidationUnit) WithSenderKey(v []byte) *ValidationUnit { + if u != nil { + u.key = v + } + + return u +} + +// WithBearerToken configures ValidationUnit to use v as request's bearer token. +func (u *ValidationUnit) WithEACLTable(table *Table) *ValidationUnit { + if u != nil { + u.table = table + } + + return u +} diff --git a/pkg/sdk/eacl/validator.go b/pkg/sdk/eacl/validator.go new file mode 100644 index 000000000..2ac406afb --- /dev/null +++ b/pkg/sdk/eacl/validator.go @@ -0,0 +1,130 @@ +package eacl + +import ( + "bytes" +) + +// Validator is a tool that calculates +// the action on a request according +// to the extended ACL rule table. +type Validator struct{} + +// NewValidator creates and initializes a new Validator using options. +func NewValidator() *Validator { + return &Validator{} +} + +// CalculateAction calculates action on the request according +// to its information represented in ValidationUnit. +// +// The action is calculated according to the application of +// eACL table of rules to the request. +// +// Second return value is true iff the action was produced by a matching entry. +// +// If no matching table entry is found or some filters are missing, +// ActionAllow is returned and the second return value is false. +func (v *Validator) CalculateAction(unit *ValidationUnit) (Action, bool) { + for _, record := range unit.table.Records() { + // check type of operation + if record.Operation() != unit.op { + continue + } + + // check target + if !targetMatches(unit, &record) { + continue + } + + // check headers + switch val := matchFilters(unit.hdrSrc, record.Filters()); { + case val < 0: + // headers of some type could not be composed => allow + return ActionAllow, false + case val == 0: + return record.Action(), true + } + } + + return ActionAllow, false +} + +// returns: +// - positive value if no matching header is found for at least one filter; +// - zero if at least one suitable header is found for all filters; +// - negative value if the headers of at least one filter cannot be obtained. +func matchFilters(hdrSrc TypedHeaderSource, filters []Filter) int { + matched := 0 + + for _, filter := range filters { + headers, ok := hdrSrc.HeadersOfType(filter.From()) + if !ok { + return -1 + } + + // get headers of filtering type + for _, header := range headers { + // prevent NPE + if header == nil { + continue + } + + // check header name + if header.Key() != filter.Key() { + continue + } + + // get match function + matchFn, ok := mMatchFns[filter.Matcher()] + if !ok { + continue + } + + // check match + if !matchFn(header, &filter) { + continue + } + + // increment match counter + matched++ + + break + } + } + + return len(filters) - matched +} + +// returns true if one of ExtendedACLTarget has +// suitable target OR suitable public key. +func targetMatches(unit *ValidationUnit, record *Record) bool { + for _, target := range record.Targets() { + // check public key match + if pubs := target.BinaryKeys(); len(pubs) != 0 { + for _, key := range pubs { + if bytes.Equal(key, unit.key) { + return true + } + } + continue + } + + // check target group match + if unit.role == target.Role() { + return true + } + } + + return false +} + +// Maps match type to corresponding function. +var mMatchFns = map[Match]func(Header, *Filter) bool{ + MatchStringEqual: func(header Header, filter *Filter) bool { + return header.Value() == filter.Value() + }, + + MatchStringNotEqual: func(header Header, filter *Filter) bool { + return header.Value() != filter.Value() + }, +} diff --git a/pkg/sdk/eacl/validator_test.go b/pkg/sdk/eacl/validator_test.go new file mode 100644 index 000000000..582a6bc3e --- /dev/null +++ b/pkg/sdk/eacl/validator_test.go @@ -0,0 +1,252 @@ +package eacl + +import ( + "crypto/rand" + "testing" + + "github.com/stretchr/testify/require" +) + +func checkAction(t *testing.T, expected Action, v *Validator, vu *ValidationUnit) { + action, ok := v.CalculateAction(vu) + require.True(t, ok) + require.Equal(t, expected, action) +} + +func checkDefaultAction(t *testing.T, v *Validator, vu *ValidationUnit) { + action, ok := v.CalculateAction(vu) + require.False(t, ok) + require.Equal(t, ActionAllow, action) +} + +func TestFilterMatch(t *testing.T) { + tgt := *NewTarget() + tgt.SetRole(RoleOthers) + + t.Run("simple header match", func(t *testing.T) { + tb := NewTable() + + r := newRecord(ActionDeny, OperationUnknown, tgt) + r.AddFilter(HeaderFromObject, MatchStringEqual, "a", "xxx") + tb.AddRecord(r) + + r = newRecord(ActionDeny, OperationUnknown, tgt) + r.AddFilter(HeaderFromRequest, MatchStringNotEqual, "b", "yyy") + tb.AddRecord(r) + + tb.AddRecord(newRecord(ActionAllow, OperationUnknown, tgt)) + + v := NewValidator() + vu := newValidationUnit(RoleOthers, nil, tb) + hs := headers{} + vu.hdrSrc = &hs + + checkAction(t, ActionAllow, v, vu) + + hs.obj = makeHeaders("b", "yyy") + checkAction(t, ActionAllow, v, vu) + + hs.obj = makeHeaders("a", "xxx") + checkAction(t, ActionDeny, v, vu) + + hs.obj = nil + hs.req = makeHeaders("b", "yyy") + checkAction(t, ActionAllow, v, vu) + + hs.req = makeHeaders("b", "abc") + checkAction(t, ActionDeny, v, vu) + }) + + t.Run("all filters must match", func(t *testing.T) { + tb := NewTable() + r := newRecord(ActionDeny, OperationUnknown, tgt) + r.AddFilter(HeaderFromObject, MatchStringEqual, "a", "xxx") + r.AddFilter(HeaderFromRequest, MatchStringEqual, "b", "yyy") + tb.AddRecord(r) + tb.AddRecord(newRecord(ActionAllow, OperationUnknown, tgt)) + + v := NewValidator() + vu := newValidationUnit(RoleOthers, nil, tb) + hs := headers{} + vu.hdrSrc = &hs + + hs.obj = makeHeaders("a", "xxx") + checkAction(t, ActionAllow, v, vu) + + hs.req = makeHeaders("b", "yyy") + checkAction(t, ActionDeny, v, vu) + + hs.obj = nil + checkAction(t, ActionAllow, v, vu) + }) + + t.Run("filters with unknown type are skipped", func(t *testing.T) { + tb := NewTable() + r := newRecord(ActionDeny, OperationUnknown, tgt) + r.AddFilter(HeaderTypeUnknown, MatchStringEqual, "a", "xxx") + tb.AddRecord(r) + + r = newRecord(ActionDeny, OperationUnknown, tgt) + r.AddFilter(0xFF, MatchStringEqual, "b", "yyy") + tb.AddRecord(r) + + tb.AddRecord(newRecord(ActionDeny, OperationUnknown, tgt)) + + v := NewValidator() + vu := newValidationUnit(RoleOthers, nil, tb) + hs := headers{} + vu.hdrSrc = &hs + + checkDefaultAction(t, v, vu) + + hs.obj = makeHeaders("a", "xxx") + checkDefaultAction(t, v, vu) + + hs.obj = nil + hs.req = makeHeaders("b", "yyy") + checkDefaultAction(t, v, vu) + }) + + t.Run("filters with match function are skipped", func(t *testing.T) { + tb := NewTable() + r := newRecord(ActionAllow, OperationUnknown, tgt) + r.AddFilter(HeaderFromObject, 0xFF, "a", "xxx") + tb.AddRecord(r) + tb.AddRecord(newRecord(ActionDeny, OperationUnknown, tgt)) + + v := NewValidator() + vu := newValidationUnit(RoleOthers, nil, tb) + hs := headers{} + vu.hdrSrc = &hs + + checkAction(t, ActionDeny, v, vu) + + hs.obj = makeHeaders("a", "xxx") + checkAction(t, ActionDeny, v, vu) + }) +} + +func TestOperationMatch(t *testing.T) { + tgt := *NewTarget() + tgt.SetRole(RoleOthers) + + t.Run("single operation", func(t *testing.T) { + tb := NewTable() + tb.AddRecord(newRecord(ActionDeny, OperationPut, tgt)) + tb.AddRecord(newRecord(ActionAllow, OperationGet, tgt)) + + v := NewValidator() + vu := newValidationUnit(RoleOthers, nil, tb) + + vu.op = OperationPut + checkAction(t, ActionDeny, v, vu) + + vu.op = OperationGet + checkAction(t, ActionAllow, v, vu) + }) + + t.Run("unknown operation", func(t *testing.T) { + tb := NewTable() + tb.AddRecord(newRecord(ActionDeny, OperationUnknown, tgt)) + tb.AddRecord(newRecord(ActionAllow, OperationGet, tgt)) + + v := NewValidator() + vu := newValidationUnit(RoleOthers, nil, tb) + + // TODO discuss if both next tests should result in DENY + vu.op = OperationPut + checkDefaultAction(t, v, vu) + + vu.op = OperationGet + checkAction(t, ActionAllow, v, vu) + }) +} + +func TestTargetMatches(t *testing.T) { + pubs := makeKeys(t, 3) + + tgt1 := NewTarget() + tgt1.SetBinaryKeys(pubs[0:2]) + tgt1.SetRole(RoleUser) + + tgt2 := NewTarget() + tgt2.SetRole(RoleOthers) + + r := NewRecord() + r.SetTargets(*tgt1, *tgt2) + + u := newValidationUnit(RoleUser, pubs[0], nil) + require.True(t, targetMatches(u, r)) + + u = newValidationUnit(RoleUser, pubs[2], nil) + require.False(t, targetMatches(u, r)) + + u = newValidationUnit(RoleUnknown, pubs[1], nil) + require.True(t, targetMatches(u, r)) + + u = newValidationUnit(RoleOthers, pubs[2], nil) + require.True(t, targetMatches(u, r)) + + u = newValidationUnit(RoleSystem, pubs[2], nil) + require.False(t, targetMatches(u, r)) +} + +func makeKeys(t *testing.T, n int) [][]byte { + pubs := make([][]byte, n) + for i := range pubs { + pubs[i] = make([]byte, 33) + pubs[i][0] = 0x02 + + _, err := rand.Read(pubs[i][1:]) + require.NoError(t, err) + } + return pubs +} + +type ( + hdr struct { + key, value string + } + + headers struct { + obj []Header + req []Header + } +) + +func (h hdr) Key() string { return h.key } +func (h hdr) Value() string { return h.value } + +func makeHeaders(kv ...string) []Header { + hs := make([]Header, len(kv)/2) + for i := 0; i < len(kv); i += 2 { + hs[i/2] = hdr{kv[i], kv[i+1]} + } + return hs +} + +func (h headers) HeadersOfType(ht FilterHeaderType) ([]Header, bool) { + switch ht { + case HeaderFromRequest: + return h.req, true + case HeaderFromObject: + return h.obj, true + default: + return nil, false + } +} + +func newRecord(a Action, op Operation, tgt ...Target) *Record { + r := NewRecord() + r.SetAction(a) + r.SetOperation(op) + r.SetTargets(tgt...) + return r +} + +func newValidationUnit(role Role, key []byte, table *Table) *ValidationUnit { + return new(ValidationUnit). + WithRole(role). + WithSenderKey(key). + WithEACLTable(table) +} diff --git a/pkg/sdk/go.mod b/pkg/sdk/go.mod new file mode 100644 index 000000000..f82581f62 --- /dev/null +++ b/pkg/sdk/go.mod @@ -0,0 +1,47 @@ +module git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk + +go 1.20 + +require ( + git.frostfs.info/TrueCloudLab/frostfs-contract v0.0.0-20230307110621-19a8ef2d02fb + git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 + git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api v0.0.0-00010101000000-000000000000 + git.frostfs.info/TrueCloudLab/hrw v1.2.1 + git.frostfs.info/TrueCloudLab/tzhash v1.8.0 + github.com/antlr4-go/antlr/v4 v4.13.0 + github.com/google/uuid v1.3.0 + github.com/hashicorp/golang-lru/v2 v2.0.2 + github.com/mr-tron/base58 v1.2.0 + github.com/nspcc-dev/neo-go v0.101.2-0.20230601131642-a0117042e8fc + github.com/stretchr/testify v1.8.3 + go.uber.org/zap v1.24.0 + google.golang.org/grpc v1.55.0 + google.golang.org/protobuf v1.33.0 + gopkg.in/yaml.v3 v3.0.1 +) + +require ( + git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 // indirect + github.com/benbjohnson/clock v1.1.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect + github.com/golang/protobuf v1.5.3 // indirect + github.com/gorilla/websocket v1.5.0 // indirect + github.com/hashicorp/golang-lru v0.6.0 // indirect + github.com/nspcc-dev/go-ordered-json v0.0.0-20220111165707-25110be27d22 // indirect + github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230615193820-9185820289ce // indirect + github.com/nspcc-dev/rfc6979 v0.2.0 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/twmb/murmur3 v1.1.8 // indirect + go.uber.org/atomic v1.10.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + golang.org/x/crypto v0.9.0 // indirect + golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc // indirect + golang.org/x/net v0.10.0 // indirect + golang.org/x/sync v0.2.0 // indirect + golang.org/x/sys v0.8.0 // indirect + golang.org/x/text v0.9.0 // indirect + google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect +) + +replace git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api => ./../api diff --git a/pkg/sdk/go.sum b/pkg/sdk/go.sum new file mode 100644 index 000000000..c01e1aa09 --- /dev/null +++ b/pkg/sdk/go.sum @@ -0,0 +1,730 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +git.frostfs.info/TrueCloudLab/frostfs-contract v0.0.0-20230307110621-19a8ef2d02fb h1:S/TrbOOu9qEXZRZ9/Ddw7crnxbBUQLo68PSzQWYrc9M= +git.frostfs.info/TrueCloudLab/frostfs-contract v0.0.0-20230307110621-19a8ef2d02fb/go.mod h1:nkR5gaGeez3Zv2SE7aceP0YwxG2FzIB5cGKpQO2vV2o= +git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSVCB8JNSfPG7Uk4r2oSk= +git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0/go.mod h1:RUIKZATQLJ+TaYQa60X2fTDwfuhMfm8Ar60bQ5fr+vU= +git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= +git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= +git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 h1:M2KR3iBj7WpY3hP10IevfIB9MURr4O9mwVfJ+SjT3HA= +git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0/go.mod h1:okpbKfVYf/BpejtfFTfhZqFP+sZ8rsHrP8Rr/jYPNRc= +git.frostfs.info/TrueCloudLab/tzhash v1.8.0 h1:UFMnUIk0Zh17m8rjGHJMqku2hCgaXDqjqZzS4gsb4UA= +git.frostfs.info/TrueCloudLab/tzhash v1.8.0/go.mod h1:dhY+oy274hV8wGvGL4MwwMpdL3GYvaX1a8GQZQHvlF8= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/CityOfZion/neo-go v0.62.1-pre.0.20191114145240-e740fbe708f8/go.mod h1:MJCkWUBhi9pn/CrYO1Q3P687y2KeahrOPS9BD9LDGb0= +github.com/CityOfZion/neo-go v0.70.1-pre.0.20191209120015-fccb0085941e/go.mod h1:0enZl0az8xA6PVkwzEOwPWVJGqlt/GO4hA4kmQ5Xzig= +github.com/CityOfZion/neo-go v0.70.1-pre.0.20191212173117-32ac01130d4c/go.mod h1:JtlHfeqLywZLswKIKFnAp+yzezY4Dji9qlfQKB2OD/I= +github.com/CityOfZion/neo-go v0.71.1-pre.0.20200129171427-f773ec69fb84/go.mod h1:FLI526IrRWHmcsO+mHsCbj64pJZhwQFTLJZu+A4PGOA= +github.com/Workiva/go-datastructures v1.0.50/go.mod h1:Z+F2Rca0qCsVYDS8z7bAGm8f3UkzuWYS/oBZz5a7VVA= +github.com/abiosoft/ishell v2.0.0+incompatible/go.mod h1:HQR9AqF2R3P4XXpMpI0NAzgHf/aS6+zVXRj14cVk9qg= +github.com/abiosoft/ishell/v2 v2.0.2/go.mod h1:E4oTCXfo6QjoCart0QYa5m9w4S+deXs/P/9jA77A9Bs= +github.com/abiosoft/readline v0.0.0-20180607040430-155bce2042db/go.mod h1:rB3B4rKii8V21ydCbIzH5hZiCQE7f5E9SzUb/ZZx530= +github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/alicebob/gopher-json v0.0.0-20180125190556-5a6b3ba71ee6/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc= +github.com/alicebob/miniredis v2.5.0+incompatible/go.mod h1:8HZjEj4yU0dwhYHky+DxYx+6BMjkBbe5ONFIF1MXffk= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20210521073959-f0d4d129b7f1/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY= +github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI= +github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g= +github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= +github.com/btcsuite/btcd v0.22.0-beta/go.mod h1:9n5ntfhhHQBIhUvlhDvD3Qg6fRUj4jkN0VB8L8svzOA= +github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= +github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o= +github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= +github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= +github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= +github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= +github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash/v2 v2.1.0/go.mod h1:dgIUBU3pDso/gPgZ1osOZ0iQf77oPR28Tjxl5dIMyVM= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= +github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= +github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:rZfgFAXFS/z/lEd6LJmf9HVZ1LkgYiHx5pHhV5DR16M= +github.com/frankban/quicktest v1.14.0/go.mod h1:NeW+ay9A/U67EYXNFA1nPE8e/tnQv/09mUdL/ijj8og= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= +github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= +github.com/go-redis/redis v6.10.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= +github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/golang-lru v0.6.0 h1:uL2shRDx7RTrOrTCUZEGP/wJUFiUI8QT6E7z5o8jga4= +github.com/hashicorp/golang-lru v0.6.0/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/golang-lru/v2 v2.0.2 h1:Dwmkdr5Nc/oBiXgJS3CDHNhJtIHkuZ3DZF5twqnfBdU= +github.com/hashicorp/golang-lru/v2 v2.0.2/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= +github.com/holiman/uint256 v1.2.0/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= +github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= +github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= +github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/nspcc-dev/dbft v0.0.0-20191205084618-dacb1a30c254/go.mod h1:w1Ln2aT+dBlPhLnuZhBV+DfPEdS2CHWWLp5JTScY3bw= +github.com/nspcc-dev/dbft v0.0.0-20191209120240-0d6b7568d9ae/go.mod h1:3FjXOoHmA51EGfb5GS/HOv7VdmngNRTssSeQ729dvGY= +github.com/nspcc-dev/dbft v0.0.0-20200117124306-478e5cfbf03a/go.mod h1:/YFK+XOxxg0Bfm6P92lY5eDSLYfp06XOdL8KAVgXjVk= +github.com/nspcc-dev/dbft v0.0.0-20200219114139-199d286ed6c1/go.mod h1:O0qtn62prQSqizzoagHmuuKoz8QMkU3SzBoKdEvm3aQ= +github.com/nspcc-dev/dbft v0.0.0-20210721160347-1b03241391ac/go.mod h1:U8MSnEShH+o5hexfWJdze6uMFJteP0ko7J2frO7Yu1Y= +github.com/nspcc-dev/dbft v0.0.0-20220902113116-58a5e763e647/go.mod h1:g9xisXmX9NP9MjioaTe862n9SlZTrP+6PVUWLBYOr98= +github.com/nspcc-dev/go-ordered-json v0.0.0-20210915112629-e1b6cce73d02/go.mod h1:79bEUDEviBHJMFV6Iq6in57FEOCMcRhfQnfaf0ETA5U= +github.com/nspcc-dev/go-ordered-json v0.0.0-20220111165707-25110be27d22 h1:n4ZaFCKt1pQJd7PXoMJabZWK9ejjbLOVrkl/lOUmshg= +github.com/nspcc-dev/go-ordered-json v0.0.0-20220111165707-25110be27d22/go.mod h1:79bEUDEviBHJMFV6Iq6in57FEOCMcRhfQnfaf0ETA5U= +github.com/nspcc-dev/hrw v1.0.9/go.mod h1:l/W2vx83vMQo6aStyx2AuZrJ+07lGv2JQGlVkPG06MU= +github.com/nspcc-dev/neo-go v0.73.1-pre.0.20200303142215-f5a1b928ce09/go.mod h1:pPYwPZ2ks+uMnlRLUyXOpLieaDQSEaf4NM3zHVbRjmg= +github.com/nspcc-dev/neo-go v0.98.0/go.mod h1:E3cc1x6RXSXrJb2nDWXTXjnXk3rIqVN8YdFyWv+FrqM= +github.com/nspcc-dev/neo-go v0.99.4/go.mod h1:mKTolfRUfKjFso5HPvGSQtUZc70n0VKBMs16eGuC5gA= +github.com/nspcc-dev/neo-go v0.101.2-0.20230601131642-a0117042e8fc h1:fySIWvUQsitK5e5qYIHnTDCXuPpwzz89SEUEIyY11sg= +github.com/nspcc-dev/neo-go v0.101.2-0.20230601131642-a0117042e8fc/go.mod h1:s9QhjMC784MWqTURovMbyYduIJc86mnCruxcMiAebpc= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220927123257-24c107e3a262/go.mod h1:23bBw0v6pBYcrWs8CBEEDIEDJNbcFoIh8pGGcf2Vv8s= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230615193820-9185820289ce h1:vLGuUNDkmQrWMa4rr4vTd1u8ULqejWxVmNz1L7ocTEI= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230615193820-9185820289ce/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= +github.com/nspcc-dev/neofs-api-go/v2 v2.11.0-pre.0.20211201134523-3604d96f3fe1/go.mod h1:oS8dycEh8PPf2Jjp6+8dlwWyEv2Dy77h/XhhcdxYEFs= +github.com/nspcc-dev/neofs-api-go/v2 v2.11.1/go.mod h1:oS8dycEh8PPf2Jjp6+8dlwWyEv2Dy77h/XhhcdxYEFs= +github.com/nspcc-dev/neofs-crypto v0.2.0/go.mod h1:F/96fUzPM3wR+UGsPi3faVNmFlA9KAEAUQR7dMxZmNA= +github.com/nspcc-dev/neofs-crypto v0.2.3/go.mod h1:8w16GEJbH6791ktVqHN9YRNH3s9BEEKYxGhlFnp0cDw= +github.com/nspcc-dev/neofs-crypto v0.3.0/go.mod h1:8w16GEJbH6791ktVqHN9YRNH3s9BEEKYxGhlFnp0cDw= +github.com/nspcc-dev/neofs-crypto v0.4.0/go.mod h1:6XJ8kbXgOfevbI2WMruOtI+qUJXNwSGM/E9eClXxPHs= +github.com/nspcc-dev/neofs-sdk-go v0.0.0-20211201182451-a5b61c4f6477/go.mod h1:dfMtQWmBHYpl9Dez23TGtIUKiFvCIxUZq/CkSIhEpz4= +github.com/nspcc-dev/neofs-sdk-go v0.0.0-20220113123743-7f3162110659/go.mod h1:/jay1lr3w7NQd/VDBkEhkJmDmyPNsu4W+QV2obsUV40= +github.com/nspcc-dev/rfc6979 v0.1.0/go.mod h1:exhIh1PdpDC5vQmyEsGvc4YDM/lyQp/452QxGq/UEso= +github.com/nspcc-dev/rfc6979 v0.2.0 h1:3e1WNxrN60/6N0DW7+UYisLeZJyfqZTNOjeV/toYvOE= +github.com/nspcc-dev/rfc6979 v0.2.0/go.mod h1:exhIh1PdpDC5vQmyEsGvc4YDM/lyQp/452QxGq/UEso= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.4.2/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.2.1/go.mod h1:XMU6Z2MjaRKVu/dC1qupJI9SiNkDYzz3xecMgSW/F+U= +github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= +github.com/prometheus/client_golang v1.13.0/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5nJFOEMgftOUOmlvYQ= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= +github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= +github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= +github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= +github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/syndtr/goleveldb v0.0.0-20180307113352-169b1b37be73/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0= +github.com/syndtr/goleveldb v1.0.1-0.20210305035536-64b5b1c73954 h1:xQdMZ1WLrgkkvOZ/LDQxjVxMLdby7osSh4ZEVa5sIjs= +github.com/syndtr/goleveldb v1.0.1-0.20210305035536-64b5b1c73954/go.mod h1:u2MKkTVTVJWe5D1rCvame8WqhBd88EuIwODJZ1VHCPM= +github.com/twmb/murmur3 v1.1.5/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ= +github.com/twmb/murmur3 v1.1.8 h1:8Yt9taO/WN3l08xErzjeschgZU2QSrwm1kclYq+0aRg= +github.com/twmb/murmur3 v1.1.8/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ= +github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.22.5/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/virtuald/go-ordered-json v0.0.0-20170621173500-b18e6e673d74 h1:JwtAtbp7r/7QSyGz8mKUbYJBg2+6Cd7OjM8o/GNOcVo= +github.com/virtuald/go-ordered-json v0.0.0-20170621173500-b18e6e673d74/go.mod h1:RmMWU37GKR2s6pgrIEB4ixgpVCt/cf7dnJv3fuH1J1c= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/gopher-lua v0.0.0-20190514113301-1cd887cd7036/go.mod h1:gqRgreBUhTSL0GeU64rtZ3Uq3wtjOa/TB2YfrtkCbVQ= +github.com/yuin/gopher-lua v0.0.0-20191128022950-c6266f4fe8d7/go.mod h1:gqRgreBUhTSL0GeU64rtZ3Uq3wtjOa/TB2YfrtkCbVQ= +go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= +go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= +go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= +go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= +go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= +go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= +go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= +golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= +golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc h1:mCRnTeVUjcrhlRmO0VK8a6k6Rrf6TF9htwo2pJVSjIU= +golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI= +golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210429154555-c04ba851c2a4/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180318012157-96caea41033d/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20201022035929-9cf592e881e9/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A= +google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= +google.golang.org/grpc v1.55.0 h1:3Oj82/tFSCeUrRTg/5E/7d/W5A1tj6Ky1ABAuZuv5ag= +google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/abiosoft/ishell.v2 v2.0.0/go.mod h1:sFp+cGtH6o4s1FtpVPTMcHq2yue+c4DGOVohJCPUzwY= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/pkg/sdk/netmap/Tests.md b/pkg/sdk/netmap/Tests.md new file mode 100644 index 000000000..6671d09af --- /dev/null +++ b/pkg/sdk/netmap/Tests.md @@ -0,0 +1,18 @@ +## Language-agnostic testing +`json_tests` sub-folder contains netmap selection algorithm tests in the following format: + +### File structure +Field|Description +---|--- +`name`|Human readable name for a set of related tests operating on a single netmap. +`nodes`|List of `netmap.NodeInfo` structures coressponding to a nodes in the network. +`tests`|Map from a single test name to a `test` structure. + +### Single test structure +Field|Description +---|--- +`policy`|JSON representation of a netmap policy. +`pivot`|Optional pivot to use in container node selection. +`result`|List of lists of node-indices corresponding to each replica in the placement policy. +`error`|Error that should be raised for this specific test. The actual strings are used in SDK, other implementation may simply check that error has occurred. +`placement`|Optional field containing another test for selecting placement nodes for an object. Can contain `pivot`, `result` and `error` fields with the same meaning as above. Note that if `pivot` is omitted, empty value should be used. diff --git a/pkg/sdk/netmap/aggregator.go b/pkg/sdk/netmap/aggregator.go new file mode 100644 index 000000000..0f577a0d6 --- /dev/null +++ b/pkg/sdk/netmap/aggregator.go @@ -0,0 +1,170 @@ +package netmap + +import ( + "sort" +) + +type ( + // aggregator can calculate some value across all netmap + // such as median, minimum or maximum. + aggregator interface { + Add(float64) + Compute() float64 + } + + // normalizer normalizes weight. + normalizer interface { + Normalize(w float64) float64 + } + + meanAgg struct { + mean float64 + count int + } + + minAgg struct { + min float64 + minFound bool + } + + meanIQRAgg struct { + k float64 + arr []float64 + } + + reverseMinNorm struct { + min float64 + } + + sigmoidNorm struct { + scale float64 + } + + // weightFunc calculates n's weight. + weightFunc = func(NodeInfo) float64 +) + +var ( + _ aggregator = (*meanAgg)(nil) + _ aggregator = (*minAgg)(nil) + _ aggregator = (*meanIQRAgg)(nil) + + _ normalizer = (*reverseMinNorm)(nil) + _ normalizer = (*sigmoidNorm)(nil) +) + +// newWeightFunc returns weightFunc which multiplies normalized +// capacity and price. +func newWeightFunc(capNorm, priceNorm normalizer) weightFunc { + return func(n NodeInfo) float64 { + return capNorm.Normalize(float64(n.capacity())) * priceNorm.Normalize(float64(n.Price())) + } +} + +// newMeanAgg returns an aggregator which +// computes mean value by recalculating it on +// every addition. +func newMeanAgg() aggregator { + return new(meanAgg) +} + +// newMinAgg returns an aggregator which +// computes min value. +func newMinAgg() aggregator { + return new(minAgg) +} + +// newMeanIQRAgg returns an aggregator which +// computes mean value of values from IQR interval. +func newMeanIQRAgg() aggregator { + return new(meanIQRAgg) +} + +// newReverseMinNorm returns a normalizer which +// normalize values in range of 0.0 to 1.0 to a minimum value. +func newReverseMinNorm(min float64) normalizer { + return &reverseMinNorm{min: min} +} + +// newSigmoidNorm returns a normalizer which +// normalize values in range of 0.0 to 1.0 to a scaled sigmoid. +func newSigmoidNorm(scale float64) normalizer { + return &sigmoidNorm{scale: scale} +} + +func (a *meanAgg) Add(n float64) { + c := a.count + 1 + a.mean = a.mean*(float64(a.count)/float64(c)) + n/float64(c) + a.count++ +} + +func (a *meanAgg) Compute() float64 { + return a.mean +} + +func (a *minAgg) Add(n float64) { + if !a.minFound { + a.min = n + a.minFound = true + return + } + + if n < a.min { + a.min = n + } +} + +func (a *minAgg) Compute() float64 { + return a.min +} + +func (a *meanIQRAgg) Add(n float64) { + a.arr = append(a.arr, n) +} + +func (a *meanIQRAgg) Compute() float64 { + l := len(a.arr) + if l == 0 { + return 0 + } + + sort.Slice(a.arr, func(i, j int) bool { return a.arr[i] < a.arr[j] }) + + var min, max float64 + + const minLn = 4 + + if l < minLn { + min, max = a.arr[0], a.arr[l-1] + } else { + start, end := l/minLn, l*3/minLn-1 + iqr := a.k * (a.arr[end] - a.arr[start]) + min, max = a.arr[start]-iqr, a.arr[end]+iqr + } + + count := 0 + sum := float64(0) + + for _, e := range a.arr { + if e >= min && e <= max { + sum += e + count++ + } + } + + return sum / float64(count) +} + +func (r *reverseMinNorm) Normalize(w float64) float64 { + return (r.min + 1) / (w + 1) +} + +func (r *sigmoidNorm) Normalize(w float64) float64 { + if r.scale == 0 { + return 0 + } + + x := w / r.scale + + return x / (1 + x) +} diff --git a/pkg/sdk/netmap/aggregator_test.go b/pkg/sdk/netmap/aggregator_test.go new file mode 100644 index 000000000..d844803c9 --- /dev/null +++ b/pkg/sdk/netmap/aggregator_test.go @@ -0,0 +1,44 @@ +package netmap + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestMinAgg(t *testing.T) { + tests := []struct { + vals []float64 + res float64 + }{ + { + vals: []float64{1, 2, 3, 0, 10}, + res: 0, + }, + { + vals: []float64{10, 0, 10, 0}, + res: 0, + }, + { + vals: []float64{0, 1, 2, 3, 10}, + res: 0, + }, + { + vals: []float64{0, 0, 0, 0}, + res: 0, + }, + { + vals: []float64{10, 10, 10, 10}, + res: 10, + }, + } + + for _, test := range tests { + a := newMinAgg() + for _, val := range test.vals { + a.Add(val) + } + + require.Equal(t, test.res, a.Compute()) + } +} diff --git a/pkg/sdk/netmap/bench_test.go b/pkg/sdk/netmap/bench_test.go new file mode 100644 index 000000000..8a6395f17 --- /dev/null +++ b/pkg/sdk/netmap/bench_test.go @@ -0,0 +1,58 @@ +package netmap + +import ( + "testing" + + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + "github.com/stretchr/testify/require" +) + +func BenchmarkNetmap_ContainerNodes(b *testing.B) { + nodes := []NodeInfo{ + nodeInfoFromAttributes("Country", "Russia", "Order", "1"), + nodeInfoFromAttributes("Country", "Germany", "Order", "2"), + nodeInfoFromAttributes("Country", "Russia", "Order", "3"), + nodeInfoFromAttributes("Country", "France", "Order", "4"), + nodeInfoFromAttributes("Country", "France", "Order", "5"), + nodeInfoFromAttributes("Country", "Russia", "Order", "6"), + nodeInfoFromAttributes("Country", "Russia", "Order", "7"), + nodeInfoFromAttributes("Country", "Germany", "Order", "8"), + nodeInfoFromAttributes("Country", "Germany", "Order", "9"), + nodeInfoFromAttributes("Country", "Russia", "Order", "10"), + nodeInfoFromAttributes("Country", "China", "Order", "11"), + nodeInfoFromAttributes("Country", "China", "Order", "12"), + nodeInfoFromAttributes("Country", "Finland", "Order", "13"), + nodeInfoFromAttributes("Country", "Finland", "Order", "14"), + nodeInfoFromAttributes("Country", "España", "Order", "15"), + nodeInfoFromAttributes("Country", "España", "Order", "16"), + } + + var nm NetMap + nm.SetNodes(nodes) + + policies := []string{ + `REP 2`, + `REP 2 IN X CBF 2 SELECT 2 FROM * AS X`, + } + cnr := cidtest.ID() + + pivot := make([]byte, 32) + cnr.Encode(pivot) + + for i := range policies { + b.Run(policies[i], func(b *testing.B) { + var p PlacementPolicy + require.NoError(b, p.DecodeString(policies[i])) + + b.ResetTimer() + b.ReportAllocs() + + for i := 0; i < b.N; i++ { + _, err := nm.ContainerNodes(p, pivot) + if err != nil { + b.Fatal(err) + } + } + }) + } +} diff --git a/pkg/sdk/netmap/context.go b/pkg/sdk/netmap/context.go new file mode 100644 index 000000000..98d2fda47 --- /dev/null +++ b/pkg/sdk/netmap/context.go @@ -0,0 +1,107 @@ +package netmap + +import ( + "errors" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/netmap" + "git.frostfs.info/TrueCloudLab/hrw" +) + +// context of a placement build process. +type context struct { + // network map to operate on + netMap NetMap + + // cache of processed filters + processedFilters map[string]*netmap.Filter + + // cache of processed selectors + processedSelectors map[string]*netmap.Selector + + // stores results of selector processing + selections map[string][]nodes + + // cache of parsed numeric values + numCache map[string]uint64 + + hrwSeed []byte + + // hrw.Hash of hrwSeed + hrwSeedHash uint64 + + // weightFunc is a weighting function for determining node priority + // which combines low price and high performance + weightFunc weightFunc + + // container backup factor + cbf uint32 + + // nodes already used in previous selections, which is needed when the placement + // policy uses the UNIQUE flag. Nodes marked as used are not used in subsequent + // base selections. + usedNodes map[uint64]bool + + // If true, returns an error when netmap does not contain enough nodes for selection. + // By default best effort is taken. + strict bool +} + +// Various validation errors. +var ( + errInvalidFilterName = errors.New("filter name is invalid") + errInvalidNumber = errors.New("invalid number") + errInvalidFilterOp = errors.New("invalid filter operation") + errFilterNotFound = errors.New("filter not found") + errNonEmptyFilters = errors.New("simple filter contains sub-filters") + errNotEnoughNodes = errors.New("not enough nodes to SELECT from") + errUnnamedTopFilter = errors.New("unnamed top-level filter") +) + +// newContext returns initialized context. +func newContext(nm NetMap) *context { + return &context{ + netMap: nm, + processedFilters: make(map[string]*netmap.Filter), + processedSelectors: make(map[string]*netmap.Selector), + selections: make(map[string][]nodes), + + numCache: make(map[string]uint64), + weightFunc: defaultWeightFunc(nm.nodes), + usedNodes: make(map[uint64]bool), + } +} + +func (c *context) setPivot(pivot []byte) { + if len(pivot) != 0 { + c.hrwSeed = pivot + c.hrwSeedHash = hrw.Hash(pivot) + } +} + +func (c *context) setCBF(cbf uint32) { + if cbf == 0 { + c.cbf = 3 + } else { + c.cbf = cbf + } +} + +func (c *context) addUsedNodes(ns ...NodeInfo) { + for _, n := range ns { + c.usedNodes[n.hash] = true + } +} + +func defaultWeightFunc(ns nodes) weightFunc { + mean := newMeanAgg() + min := newMinAgg() + + for i := range ns { + mean.Add(float64(ns[i].capacity())) + min.Add(float64(ns[i].Price())) + } + + return newWeightFunc( + newSigmoidNorm(mean.Compute()), + newReverseMinNorm(min.Compute())) +} diff --git a/pkg/sdk/netmap/doc.go b/pkg/sdk/netmap/doc.go new file mode 100644 index 000000000..e2273f6fa --- /dev/null +++ b/pkg/sdk/netmap/doc.go @@ -0,0 +1,43 @@ +/* +Package netmap provides functionality for working with information about the +FrostFS network, primarily a layer of storage nodes. + +The package concentrates all the characteristics of FrostFS networks. + +NetMap represents FrostFS network map - one of the main technologies used to +store data in the system. It is composed of information about all storage nodes +(NodeInfo type) in a particular network. NetMap methods allow you to impose +container storage policies (PlacementPolicy type) on a fixed composition of +nodes for selecting nodes corresponding to the placement rules chosen by the +container creator. + +NetworkInfo type is dedicated to descriptive characterization of network state +and settings. + +Instances can be also used to process FrostFS API V2 protocol messages +(see neo.fs.v2.netmap package in https://git.frostfs.info/TrueCloudLab/frostfs-api). + +On client side: + + import "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/netmap" + + var msg netmap.NodeInfo + info.WriteToV2(&msg) + + // send msg + +On server side: + + // recv msg + + var info NodeInfo + + err := info.ReadFromV2(msg) + // ... + + // process info + +Using package types in an application is recommended to potentially work with +different protocol versions with which these types are compatible. +*/ +package netmap diff --git a/pkg/sdk/netmap/filter.go b/pkg/sdk/netmap/filter.go new file mode 100644 index 000000000..5e2c1ae7d --- /dev/null +++ b/pkg/sdk/netmap/filter.go @@ -0,0 +1,149 @@ +package netmap + +import ( + "fmt" + "strconv" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/netmap" +) + +// mainFilterName is a name of the filter +// which points to the whole netmap. +const mainFilterName = "*" + +// processFilters processes filters and returns error is any of them is invalid. +func (c *context) processFilters(p PlacementPolicy) error { + for i := range p.filters { + if err := c.processFilter(p.filters[i], true); err != nil { + return fmt.Errorf("process filter #%d (%s): %w", i, p.filters[i].GetName(), err) + } + } + + return nil +} + +func (c *context) processFilter(f netmap.Filter, top bool) error { + fName := f.GetName() + if fName == mainFilterName { + return fmt.Errorf("%w: '%s' is reserved", errInvalidFilterName, mainFilterName) + } + + if top && fName == "" { + return errUnnamedTopFilter + } + + if !top && fName != "" && c.processedFilters[fName] == nil { + return errFilterNotFound + } + + inner := f.GetFilters() + + switch op := f.GetOp(); op { + case netmap.AND, netmap.OR, netmap.NOT: + for i := range inner { + if err := c.processFilter(inner[i], false); err != nil { + return fmt.Errorf("process inner filter #%d: %w", i, err) + } + } + default: + if len(inner) != 0 { + return errNonEmptyFilters + } else if !top && fName != "" { // named reference + return nil + } + + switch op { + case netmap.EQ, netmap.NE: + case netmap.GT, netmap.GE, netmap.LT, netmap.LE: + val := f.GetValue() + n, err := strconv.ParseUint(val, 10, 64) + if err != nil { + return fmt.Errorf("%w: '%s'", errInvalidNumber, f.GetValue()) + } + + c.numCache[val] = n + default: + return fmt.Errorf("%w: %s", errInvalidFilterOp, op) + } + } + + if top { + c.processedFilters[fName] = &f + } + + return nil +} + +// match matches f against b. It returns no errors because +// filter should have been parsed during context creation +// and missing node properties are considered as a regular fail. +func (c *context) match(f *netmap.Filter, b NodeInfo) bool { + switch f.GetOp() { + case netmap.NOT: + inner := f.GetFilters() + fSub := &inner[0] + if name := inner[0].GetName(); name != "" { + fSub = c.processedFilters[name] + } + return !c.match(fSub, b) + case netmap.AND, netmap.OR: + inner := f.GetFilters() + for i := range inner { + fSub := &inner[i] + if name := inner[i].GetName(); name != "" { + fSub = c.processedFilters[name] + } + + ok := c.match(fSub, b) + if ok == (f.GetOp() == netmap.OR) { + return ok + } + } + + return f.GetOp() == netmap.AND + default: + return c.matchKeyValue(f, b) + } +} + +func (c *context) matchKeyValue(f *netmap.Filter, b NodeInfo) bool { + switch op := f.GetOp(); op { + case netmap.EQ: + return b.Attribute(f.GetKey()) == f.GetValue() + case netmap.NE: + return b.Attribute(f.GetKey()) != f.GetValue() + default: + var attr uint64 + + switch f.GetKey() { + case attrPrice: + attr = b.Price() + case attrCapacity: + attr = b.capacity() + default: + var err error + + attr, err = strconv.ParseUint(b.Attribute(f.GetKey()), 10, 64) + if err != nil { + // Note: because filters are somewhat independent from nodes attributes, + // We don't report an error here, and fail filter instead. + return false + } + } + + switch op { + case netmap.GT: + return attr > c.numCache[f.GetValue()] + case netmap.GE: + return attr >= c.numCache[f.GetValue()] + case netmap.LT: + return attr < c.numCache[f.GetValue()] + case netmap.LE: + return attr <= c.numCache[f.GetValue()] + default: + // do nothing and return false + } + } + // will not happen if context was created from f (maybe panic?) + return false +} diff --git a/pkg/sdk/netmap/filter_test.go b/pkg/sdk/netmap/filter_test.go new file mode 100644 index 000000000..0095e768b --- /dev/null +++ b/pkg/sdk/netmap/filter_test.go @@ -0,0 +1,95 @@ +package netmap + +import ( + "errors" + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/netmap" + "github.com/stretchr/testify/require" +) + +func TestContext_ProcessFilters(t *testing.T) { + fs := []Filter{ + newFilter("StorageSSD", "Storage", "SSD", netmap.EQ), + newFilter("GoodRating", "Rating", "4", netmap.GE), + newFilter("Main", "", "", netmap.AND, + newFilter("StorageSSD", "", "", 0), + newFilter("", "IntField", "123", netmap.LT), + newFilter("GoodRating", "", "", 0)), + } + + c := newContext(NetMap{}) + p := newPlacementPolicy(1, nil, nil, fs) + require.NoError(t, c.processFilters(p)) + require.Equal(t, 3, len(c.processedFilters)) + for _, f := range fs { + require.Equal(t, f.m, *c.processedFilters[f.m.GetName()]) + } + + require.Equal(t, uint64(4), c.numCache[fs[1].m.GetValue()]) + require.Equal(t, uint64(123), c.numCache[fs[2].m.GetFilters()[1].GetValue()]) +} + +func TestContext_ProcessFiltersInvalid(t *testing.T) { + errTestCases := []struct { + name string + filter Filter + err error + }{ + { + "UnnamedTop", + newFilter("", "Storage", "SSD", netmap.EQ), + errUnnamedTopFilter, + }, + { + "InvalidReference", + newFilter("Main", "", "", netmap.AND, + newFilter("StorageSSD", "", "", 0)), + errFilterNotFound, + }, + { + "NonEmptyKeyed", + newFilter("Main", "Storage", "SSD", netmap.EQ, + newFilter("StorageSSD", "", "", 0)), + errNonEmptyFilters, + }, + { + "InvalidNumber", + newFilter("Main", "Rating", "three", netmap.GE), + errInvalidNumber, + }, + { + "InvalidOp", + newFilter("Main", "Rating", "3", 0), + errInvalidFilterOp, + }, + { + "InvalidName", + newFilter("*", "Rating", "3", netmap.GE), + errInvalidFilterName, + }, + } + for _, tc := range errTestCases { + t.Run(tc.name, func(t *testing.T) { + c := newContext(NetMap{}) + p := newPlacementPolicy(1, nil, nil, []Filter{tc.filter}) + err := c.processFilters(p) + require.True(t, errors.Is(err, tc.err), "got: %v", err) + }) + } +} + +func TestFilter_MatchSimple_InvalidOp(t *testing.T) { + var b NodeInfo + b.SetAttribute("Rating", "4") + b.SetAttribute("Country", "Germany") + + f := newFilter("Main", "Rating", "5", netmap.EQ) + c := newContext(NetMap{}) + p := newPlacementPolicy(1, nil, nil, []Filter{f}) + require.NoError(t, c.processFilters(p)) + + // just for the coverage + f.m.SetOp(0) + require.False(t, c.match(&f.m, b)) +} diff --git a/pkg/sdk/netmap/helper_test.go b/pkg/sdk/netmap/helper_test.go new file mode 100644 index 000000000..434e9c3e0 --- /dev/null +++ b/pkg/sdk/netmap/helper_test.go @@ -0,0 +1,49 @@ +package netmap + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/netmap" +) + +func newFilter(name string, k, v string, op netmap.Operation, fs ...Filter) (f Filter) { + f.SetName(name) + f.m.SetKey(k) + f.m.SetOp(op) + f.m.SetValue(v) + inner := make([]netmap.Filter, len(fs)) + for i := range fs { + inner[i] = fs[i].m + } + f.m.SetFilters(inner) + return f +} + +func newSelector(name string, attr string, count uint32, filter string, clause func(*Selector)) (s Selector) { + s.SetName(name) + s.SelectByBucketAttribute(attr) + s.SetNumberOfNodes(count) + clause(&s) + s.SetFilterName(filter) + return s +} + +func newPlacementPolicy(bf uint32, rs []ReplicaDescriptor, ss []Selector, fs []Filter) (p PlacementPolicy) { + p.SetContainerBackupFactor(bf) + p.AddReplicas(rs...) + p.AddSelectors(ss...) + p.AddFilters(fs...) + return p +} + +func newReplica(c uint32, s string) (r ReplicaDescriptor) { + r.SetNumberOfObjects(c) + r.SetSelectorName(s) + return r +} + +func nodeInfoFromAttributes(props ...string) (n NodeInfo) { + for i := 0; i < len(props); i += 2 { + n.SetAttribute(props[i], props[i+1]) + } + + return +} diff --git a/pkg/sdk/netmap/netmap.go b/pkg/sdk/netmap/netmap.go new file mode 100644 index 000000000..4f2e43cf6 --- /dev/null +++ b/pkg/sdk/netmap/netmap.go @@ -0,0 +1,280 @@ +package netmap + +import ( + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/netmap" + "git.frostfs.info/TrueCloudLab/hrw" +) + +// NetMap represents FrostFS network map. It includes information about all +// storage nodes registered in FrostFS the network. +// +// NetMap is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/netmap.NetMap +// message. See ReadFromV2 / WriteToV2 methods. +// +// Instances can be created using built-in var declaration. +type NetMap struct { + epoch uint64 + + nodes []NodeInfo +} + +// ReadFromV2 reads NetMap from the netmap.NetMap message. Checks if the +// message conforms to FrostFS API V2 protocol. +// +// See also WriteToV2. +func (m *NetMap) ReadFromV2(msg netmap.NetMap) error { + var err error + nodes := msg.Nodes() + + if nodes == nil { + m.nodes = nil + } else { + m.nodes = make([]NodeInfo, len(nodes)) + + for i := range nodes { + err = m.nodes[i].ReadFromV2(nodes[i]) + if err != nil { + return fmt.Errorf("invalid node info: %w", err) + } + } + } + + m.epoch = msg.Epoch() + + return nil +} + +// WriteToV2 writes NetMap to the netmap.NetMap message. The message +// MUST NOT be nil. +// +// See also ReadFromV2. +func (m NetMap) WriteToV2(msg *netmap.NetMap) { + var nodes []netmap.NodeInfo + + if m.nodes != nil { + nodes = make([]netmap.NodeInfo, len(m.nodes)) + + for i := range m.nodes { + m.nodes[i].WriteToV2(&nodes[i]) + } + + msg.SetNodes(nodes) + } + + msg.SetEpoch(m.epoch) +} + +// SetNodes sets information list about all storage nodes from the FrostFS network. +// +// Argument MUST NOT be mutated, make a copy first. +// +// See also Nodes. +func (m *NetMap) SetNodes(nodes []NodeInfo) { + m.nodes = nodes +} + +// Nodes returns nodes set using SetNodes. +// +// Return value MUST not be mutated, make a copy first. +func (m NetMap) Nodes() []NodeInfo { + return m.nodes +} + +// SetEpoch specifies revision number of the NetMap. +// +// See also Epoch. +func (m *NetMap) SetEpoch(epoch uint64) { + m.epoch = epoch +} + +// Epoch returns epoch set using SetEpoch. +// +// Zero NetMap has zero revision. +func (m NetMap) Epoch() uint64 { + return m.epoch +} + +// nodes is a slice of NodeInfo instances needed for HRW sorting. +type nodes []NodeInfo + +// assert nodes type provides hrw.Hasher required for HRW sorting. +var _ hrw.Hasher = nodes{} + +// Hash is a function from hrw.Hasher interface. It is implemented +// to support weighted hrw sorting of buckets. Each bucket is already sorted by hrw, +// thus giving us needed "randomness". +func (n nodes) Hash() uint64 { + if len(n) > 0 { + return n[0].Hash() + } + + return 0 +} + +// weights returns slice of nodes weights W. +func (n nodes) weights(wf weightFunc) []float64 { + w := make([]float64, 0, len(n)) + for i := range n { + w = append(w, wf(n[i])) + } + + return w +} + +func flattenNodes(ns []nodes) nodes { + var sz, i int + + for i = range ns { + sz += len(ns[i]) + } + + result := make(nodes, 0, sz) + + for i := range ns { + result = append(result, ns[i]...) + } + + return result +} + +// PlacementVectors sorts container nodes returned by ContainerNodes method +// and returns placement vectors for the entity identified by the given pivot. +// For example, in order to build node list to store the object, binary-encoded +// object identifier can be used as pivot. Result is deterministic for +// the fixed NetMap and parameters. +func (m NetMap) PlacementVectors(vectors [][]NodeInfo, pivot []byte) ([][]NodeInfo, error) { + h := hrw.Hash(pivot) + wf := defaultWeightFunc(m.nodes) + result := make([][]NodeInfo, len(vectors)) + + for i := range vectors { + result[i] = make([]NodeInfo, len(vectors[i])) + copy(result[i], vectors[i]) + hrw.SortHasherSliceByWeightValue(result[i], nodes(result[i]).weights(wf), h) + } + + return result, nil +} + +// SelectFilterNodes returns a two-dimensional list of nodes as a result of applying the +// given SelectFilterExpr to the NetMap. +// If the SelectFilterExpr contains only filters, the result contains a single row with the +// result of the last filter application. +// If the SelectFilterExpr contains only selectors, the result contains the selection rows +// of the last select application. +func (m NetMap) SelectFilterNodes(expr *SelectFilterExpr) ([][]NodeInfo, error) { + p := PlacementPolicy{ + filters: expr.filters, + } + + if expr.selector != nil { + p.selectors = append(p.selectors, *expr.selector) + } + + c := newContext(m) + c.setCBF(expr.cbf) + + if err := c.processFilters(p); err != nil { + return nil, err + } + if err := c.processSelectors(p); err != nil { + return nil, err + } + + if expr.selector == nil { + var ret []NodeInfo + lastFilter := expr.filters[len(expr.filters)-1] + for _, ni := range m.nodes { + if c.match(c.processedFilters[lastFilter.GetName()], ni) { + ret = append(ret, ni) + } + } + return [][]NodeInfo{ret}, nil + } + + sel, err := c.getSelection(*c.processedSelectors[expr.selector.GetName()]) + if err != nil { + return nil, err + } + + var ret [][]NodeInfo + for i, ns := range sel { + ret = append(ret, []NodeInfo{}) + for _, n := range ns { + ret[i] = append(ret[i], n) + } + } + return ret, nil +} + +// ContainerNodes returns two-dimensional list of nodes as a result of applying +// given PlacementPolicy to the NetMap. Each line of the list corresponds to a +// replica descriptor. Line order corresponds to order of ReplicaDescriptor list +// in the policy. Nodes are pre-filtered according to the Filter list from +// the policy, and then selected by Selector list. Result is deterministic for +// the fixed NetMap and parameters. +// +// Result can be used in PlacementVectors. +func (m NetMap) ContainerNodes(p PlacementPolicy, pivot []byte) ([][]NodeInfo, error) { + c := newContext(m) + c.setPivot(pivot) + c.setCBF(p.backupFactor) + + if err := c.processFilters(p); err != nil { + return nil, err + } + + if err := c.processSelectors(p); err != nil { + return nil, err + } + + result := make([][]NodeInfo, len(p.replicas)) + + // Note that the cached selectors are not used when the policy contains the UNIQUE flag. + // This is necessary because each selection vector affects potentially the subsequent vectors + // and thus we call getSelection in such case, in order to take into account nodes previously + // marked as used by earlier replicas. + for i := range p.replicas { + sName := p.replicas[i].GetSelector() + if sName == "" && !(len(p.replicas) == 1 && len(p.selectors) == 1) { + var s netmap.Selector + s.SetCount(p.replicas[i].GetCount()) + s.SetFilter(mainFilterName) + + nodes, err := c.getSelection(s) + if err != nil { + return nil, err + } + + result[i] = append(result[i], flattenNodes(nodes)...) + + if p.unique { + c.addUsedNodes(result[i]...) + } + + continue + } + + if p.unique { + if c.processedSelectors[sName] == nil { + return nil, fmt.Errorf("selector not found: '%s'", sName) + } + nodes, err := c.getSelection(*c.processedSelectors[sName]) + if err != nil { + return nil, err + } + result[i] = append(result[i], flattenNodes(nodes)...) + c.addUsedNodes(result[i]...) + } else { + nodes, ok := c.selections[sName] + if !ok { + return nil, fmt.Errorf("selector not found: REPLICA '%s'", sName) + } + result[i] = append(result[i], flattenNodes(nodes)...) + } + } + + return result, nil +} diff --git a/pkg/sdk/netmap/netmap_test.go b/pkg/sdk/netmap/netmap_test.go new file mode 100644 index 000000000..79e975e92 --- /dev/null +++ b/pkg/sdk/netmap/netmap_test.go @@ -0,0 +1,47 @@ +package netmap_test + +import ( + "testing" + + v2netmap "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" + netmaptest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap/test" + "github.com/stretchr/testify/require" +) + +func TestNetMapNodes(t *testing.T) { + var nm netmap.NetMap + + require.Empty(t, nm.Nodes()) + + nodes := []netmap.NodeInfo{netmaptest.NodeInfo(), netmaptest.NodeInfo()} + + nm.SetNodes(nodes) + require.ElementsMatch(t, nodes, nm.Nodes()) + + nodesV2 := make([]v2netmap.NodeInfo, len(nodes)) + for i := range nodes { + nodes[i].WriteToV2(&nodesV2[i]) + } + + var m v2netmap.NetMap + nm.WriteToV2(&m) + + require.ElementsMatch(t, nodesV2, m.Nodes()) +} + +func TestNetMap_SetEpoch(t *testing.T) { + var nm netmap.NetMap + + require.Zero(t, nm.Epoch()) + + const e = 158 + + nm.SetEpoch(e) + require.EqualValues(t, e, nm.Epoch()) + + var m v2netmap.NetMap + nm.WriteToV2(&m) + + require.EqualValues(t, e, m.Epoch()) +} diff --git a/pkg/sdk/netmap/network_info.go b/pkg/sdk/netmap/network_info.go new file mode 100644 index 000000000..e1df398e7 --- /dev/null +++ b/pkg/sdk/netmap/network_info.go @@ -0,0 +1,485 @@ +package netmap + +import ( + "bytes" + "encoding/binary" + "errors" + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/netmap" + "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" +) + +// NetworkInfo groups information about the FrostFS network state. Mainly used to +// describe the current state of the network. +// +// NetworkInfo is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/netmap.NetworkInfo +// message. See ReadFromV2 / WriteToV2 methods. +// +// Instances can be created using built-in var declaration. +type NetworkInfo struct { + m netmap.NetworkInfo +} + +// reads NetworkInfo from netmap.NetworkInfo message. If checkFieldPresence is set, +// returns an error on absence of any protocol-required field. Verifies format of any +// presented field according to FrostFS API V2 protocol. +func (x *NetworkInfo) readFromV2(m netmap.NetworkInfo, checkFieldPresence bool) error { + c := m.GetNetworkConfig() + if checkFieldPresence && c == nil { + return errors.New("missing network config") + } + + if checkFieldPresence && c.NumberOfParameters() <= 0 { + return errors.New("missing network parameters") + } + + var err error + mNames := make(map[string]struct{}, c.NumberOfParameters()) + + c.IterateParameters(func(prm *netmap.NetworkParameter) bool { + name := string(prm.GetKey()) + + _, was := mNames[name] + if was { + err = fmt.Errorf("duplicated parameter name: %s", name) + return true + } + + mNames[name] = struct{}{} + + switch name { + default: + if len(prm.GetValue()) == 0 { + err = fmt.Errorf("empty attribute value %s", name) + return true + } + case + configAuditFee, + configStoragePrice, + configContainerFee, + configNamedContainerFee, + configEpochDuration, + configIRCandidateFee, + configMaxObjSize, + configWithdrawalFee: + _, err = decodeConfigValueUint64(prm.GetValue()) + case configHomomorphicHashingDisabled, + configMaintenanceModeAllowed: + _, err = decodeConfigValueBool(prm.GetValue()) + } + + if err != nil { + err = fmt.Errorf("invalid %s parameter: %w", name, err) + } + + return err != nil + }) + + if err != nil { + return err + } + + x.m = m + + return nil +} + +// ReadFromV2 reads NetworkInfo from the netmap.NetworkInfo message. Checks if the +// message conforms to FrostFS API V2 protocol. +// +// See also WriteToV2. +func (x *NetworkInfo) ReadFromV2(m netmap.NetworkInfo) error { + return x.readFromV2(m, true) +} + +// WriteToV2 writes NetworkInfo to the netmap.NetworkInfo message. The message +// MUST NOT be nil. +// +// See also ReadFromV2. +func (x NetworkInfo) WriteToV2(m *netmap.NetworkInfo) { + *m = x.m +} + +// CurrentEpoch returns epoch set using SetCurrentEpoch. +// +// Zero NetworkInfo has zero current epoch. +func (x NetworkInfo) CurrentEpoch() uint64 { + return x.m.GetCurrentEpoch() +} + +// SetCurrentEpoch sets current epoch of the FrostFS network. +func (x *NetworkInfo) SetCurrentEpoch(epoch uint64) { + x.m.SetCurrentEpoch(epoch) +} + +// MagicNumber returns magic number set using SetMagicNumber. +// +// Zero NetworkInfo has zero magic. +func (x NetworkInfo) MagicNumber() uint64 { + return x.m.GetMagicNumber() +} + +// SetMagicNumber sets magic number of the FrostFS Sidechain. +// +// See also MagicNumber. +func (x *NetworkInfo) SetMagicNumber(epoch uint64) { + x.m.SetMagicNumber(epoch) +} + +// MsPerBlock returns network parameter set using SetMsPerBlock. +func (x NetworkInfo) MsPerBlock() int64 { + return x.m.GetMsPerBlock() +} + +// SetMsPerBlock sets MillisecondsPerBlock network parameter of the FrostFS Sidechain. +// +// See also MsPerBlock. +func (x *NetworkInfo) SetMsPerBlock(v int64) { + x.m.SetMsPerBlock(v) +} + +func (x *NetworkInfo) setConfig(name string, val []byte) { + c := x.m.GetNetworkConfig() + if c == nil { + c = new(netmap.NetworkConfig) + + var prm netmap.NetworkParameter + prm.SetKey([]byte(name)) + prm.SetValue(val) + + c.SetParameters(prm) + + x.m.SetNetworkConfig(c) + + return + } + + found := false + prms := make([]netmap.NetworkParameter, 0, c.NumberOfParameters()) + + c.IterateParameters(func(prm *netmap.NetworkParameter) bool { + found = bytes.Equal(prm.GetKey(), []byte(name)) + if found { + prm.SetValue(val) + } else { + prms = append(prms, *prm) + } + + return found + }) + + if !found { + prms = append(prms, netmap.NetworkParameter{}) + prms[len(prms)-1].SetKey([]byte(name)) + prms[len(prms)-1].SetValue(val) + + c.SetParameters(prms...) + } +} + +func (x NetworkInfo) configValue(name string) (res []byte) { + x.m.GetNetworkConfig().IterateParameters(func(prm *netmap.NetworkParameter) bool { + if string(prm.GetKey()) == name { + res = prm.GetValue() + + return true + } + + return false + }) + + return +} + +// SetRawNetworkParameter sets named FrostFS network parameter whose value is +// transmitted but not interpreted by the FrostFS API protocol. +// +// Argument MUST NOT be mutated, make a copy first. +// +// See also RawNetworkParameter, IterateRawNetworkParameters. +func (x *NetworkInfo) SetRawNetworkParameter(name string, value []byte) { + x.setConfig(name, value) +} + +// RawNetworkParameter reads raw network parameter set using SetRawNetworkParameter +// by its name. Returns nil if value is missing. +// +// Return value MUST NOT be mutated, make a copy first. +// +// Zero NetworkInfo has no network parameters. +func (x *NetworkInfo) RawNetworkParameter(name string) []byte { + return x.configValue(name) +} + +// IterateRawNetworkParameters iterates over all raw networks parameters set +// using SetRawNetworkParameter and passes them into f. +// +// Handler MUST NOT be nil. Handler MUST NOT mutate value parameter. +// +// Zero NetworkInfo has no network parameters. +func (x *NetworkInfo) IterateRawNetworkParameters(f func(name string, value []byte)) { + c := x.m.GetNetworkConfig() + + c.IterateParameters(func(prm *netmap.NetworkParameter) bool { + name := string(prm.GetKey()) + switch name { + default: + f(name, prm.GetValue()) + case + configAuditFee, + configStoragePrice, + configContainerFee, + configNamedContainerFee, + configEpochDuration, + configIRCandidateFee, + configMaxObjSize, + configWithdrawalFee, + configHomomorphicHashingDisabled, + configMaintenanceModeAllowed: + } + + return false + }) +} + +func (x *NetworkInfo) setConfigUint64(name string, num uint64) { + val := make([]byte, 8) + binary.LittleEndian.PutUint64(val, num) + + x.setConfig(name, val) +} + +func (x *NetworkInfo) setConfigBool(name string, val bool) { + v := stackitem.NewBool(val) + x.setConfig(name, v.Bytes()) +} + +// decodeConfigValueUint64 parses val as little-endian uint64. +// val must be less than 8 bytes in size. +func decodeConfigValueUint64(val []byte) (uint64, error) { + if ln := len(val); ln > 8 { + return 0, fmt.Errorf("invalid uint64 parameter length %d", ln) + } + + res := uint64(0) + for i := len(val) - 1; i >= 0; i-- { + res = res*256 + uint64(val[i]) + } + + return res, nil +} + +// decodeConfigValueBool parses val as boolean contract storage value. +func decodeConfigValueBool(val []byte) (bool, error) { + arr := stackitem.NewByteArray(val) + + res, err := arr.TryBool() + if err != nil { + return false, fmt.Errorf("invalid bool parameter contract format %s", err) + } + + return res, nil +} + +func (x NetworkInfo) configUint64(name string) uint64 { + val := x.configValue(name) + if val == nil { + return 0 + } + + res, err := decodeConfigValueUint64(val) + if err != nil { + // potential panic is OK since value MUST be correct since it is + // verified in ReadFromV2 or set by provided method. + panic(err) + } + + return res +} + +func (x NetworkInfo) configBool(name string) bool { + val := x.configValue(name) + if val == nil { + return false + } + + res, err := decodeConfigValueBool(val) + if err != nil { + // potential panic is OK since value MUST be correct since it is + // verified in ReadFromV2 or set by provided method. + panic(err) + } + + return res +} + +const configAuditFee = "AuditFee" + +// SetAuditFee sets the configuration value of the audit fee for the Inner Ring. +// +// See also AuditFee. +func (x *NetworkInfo) SetAuditFee(fee uint64) { + x.setConfigUint64(configAuditFee, fee) +} + +// AuditFee returns audit fee set using SetAuditFee. +// +// Zero NetworkInfo has zero audit fee. +func (x NetworkInfo) AuditFee() uint64 { + return x.configUint64(configAuditFee) +} + +const configStoragePrice = "BasicIncomeRate" + +// SetStoragePrice sets the price per gigabyte of data storage that data owners +// pay to storage nodes. +// +// See also StoragePrice. +func (x *NetworkInfo) SetStoragePrice(price uint64) { + x.setConfigUint64(configStoragePrice, price) +} + +// StoragePrice returns storage price set using SetStoragePrice. +// +// Zero NetworkInfo has zero storage price. +func (x NetworkInfo) StoragePrice() uint64 { + return x.configUint64(configStoragePrice) +} + +const configContainerFee = "ContainerFee" + +// SetContainerFee sets fee for the container creation that creator pays to +// each Alphabet node. +// +// See also ContainerFee. +func (x *NetworkInfo) SetContainerFee(fee uint64) { + x.setConfigUint64(configContainerFee, fee) +} + +// ContainerFee returns container fee set using SetContainerFee. +// +// Zero NetworkInfo has zero container fee. +func (x NetworkInfo) ContainerFee() uint64 { + return x.configUint64(configContainerFee) +} + +const configNamedContainerFee = "ContainerAliasFee" + +// SetNamedContainerFee sets fee for creation of the named container creation +// that creator pays to each Alphabet node. +// +// See also NamedContainerFee. +func (x *NetworkInfo) SetNamedContainerFee(fee uint64) { + x.setConfigUint64(configNamedContainerFee, fee) +} + +// NamedContainerFee returns container fee set using SetNamedContainerFee. +// +// Zero NetworkInfo has zero container fee. +func (x NetworkInfo) NamedContainerFee() uint64 { + return x.configUint64(configNamedContainerFee) +} + +const configEpochDuration = "EpochDuration" + +// SetEpochDuration sets FrostFS epoch duration measured in number of blocks of +// the FrostFS Sidechain. +// +// See also EpochDuration. +func (x *NetworkInfo) SetEpochDuration(blocks uint64) { + x.setConfigUint64(configEpochDuration, blocks) +} + +// EpochDuration returns epoch duration set using SetEpochDuration. +// +// Zero NetworkInfo has zero iteration number. +func (x NetworkInfo) EpochDuration() uint64 { + return x.configUint64(configEpochDuration) +} + +const configIRCandidateFee = "InnerRingCandidateFee" + +// SetIRCandidateFee sets fee for Inner Ring entrance paid by a new member. +// +// See also IRCandidateFee. +func (x *NetworkInfo) SetIRCandidateFee(fee uint64) { + x.setConfigUint64(configIRCandidateFee, fee) +} + +// IRCandidateFee returns IR entrance fee set using SetIRCandidateFee. +// +// Zero NetworkInfo has zero fee. +func (x NetworkInfo) IRCandidateFee() uint64 { + return x.configUint64(configIRCandidateFee) +} + +const configMaxObjSize = "MaxObjectSize" + +// SetMaxObjectSize sets maximum size of the object stored locally on the +// storage nodes (physical objects). Binary representation of any physically +// stored object MUST NOT overflow the limit. +// +// See also MaxObjectSize. +func (x *NetworkInfo) SetMaxObjectSize(sz uint64) { + x.setConfigUint64(configMaxObjSize, sz) +} + +// MaxObjectSize returns maximum object size set using SetMaxObjectSize. +// +// Zero NetworkInfo has zero maximum size. +func (x NetworkInfo) MaxObjectSize() uint64 { + return x.configUint64(configMaxObjSize) +} + +const configWithdrawalFee = "WithdrawFee" + +// SetWithdrawalFee sets fee for withdrawals from the FrostFS accounts that +// account owners pay to each Alphabet node. +// +// See also WithdrawalFee. +func (x *NetworkInfo) SetWithdrawalFee(sz uint64) { + x.setConfigUint64(configWithdrawalFee, sz) +} + +// WithdrawalFee returns withdrawal fee set using SetWithdrawalFee. +// +// Zero NetworkInfo has zero fee. +func (x NetworkInfo) WithdrawalFee() uint64 { + return x.configUint64(configWithdrawalFee) +} + +const configHomomorphicHashingDisabled = "HomomorphicHashingDisabled" + +// DisableHomomorphicHashing sets flag requiring to disable homomorphic +// hashing of the containers in the network. +// +// See also HomomorphicHashingDisabled. +func (x *NetworkInfo) DisableHomomorphicHashing() { + x.setConfigBool(configHomomorphicHashingDisabled, true) +} + +// HomomorphicHashingDisabled returns the state of the homomorphic +// hashing network setting. +// +// Zero NetworkInfo has enabled homomorphic hashing. +func (x NetworkInfo) HomomorphicHashingDisabled() bool { + return x.configBool(configHomomorphicHashingDisabled) +} + +const configMaintenanceModeAllowed = "MaintenanceModeAllowed" + +// AllowMaintenanceMode sets the flag allowing nodes to go into maintenance mode. +// +// See also MaintenanceModeAllowed. +func (x *NetworkInfo) AllowMaintenanceMode() { + x.setConfigBool(configMaintenanceModeAllowed, true) +} + +// MaintenanceModeAllowed returns true iff network config allows +// maintenance mode for storage nodes. +// +// Zero NetworkInfo has disallows maintenance mode. +func (x NetworkInfo) MaintenanceModeAllowed() bool { + return x.configBool(configMaintenanceModeAllowed) +} diff --git a/pkg/sdk/netmap/network_info_decode_test.go b/pkg/sdk/netmap/network_info_decode_test.go new file mode 100644 index 000000000..c347ac90a --- /dev/null +++ b/pkg/sdk/netmap/network_info_decode_test.go @@ -0,0 +1,63 @@ +package netmap + +import ( + "math/big" + "testing" + + "github.com/nspcc-dev/neo-go/pkg/encoding/bigint" + "github.com/stretchr/testify/require" +) + +func TestDecodeUint64(t *testing.T) { + testCases := []uint64{ + 0, + 12, + 129, + 0x1234, + 0x12345678, + 0x1234567891011, + } + + for _, expected := range testCases { + val := bigint.ToBytes(big.NewInt(int64(expected))) + + actual, err := decodeConfigValueUint64(val) + require.NoError(t, err) + require.Equal(t, expected, actual) + } +} + +func TestDecodeBool(t *testing.T) { + testCases := []struct { + expected bool + raw []byte + }{ + { + false, + []byte{0}, + }, + { + false, + []byte{0, 0, 0, 0}, + }, + { + true, + []byte{1}, + }, + { + true, + []byte{1, 1, 1, 1, 1}, + }, + { + true, + []byte{0, 0, 0, 0, 1}, // neo-go casts any value that does not consist of zeroes as `true` + }, + } + + for _, test := range testCases { + actual, err := decodeConfigValueBool(test.raw) + require.NoError(t, err) + + require.Equal(t, test.expected, actual) + } +} diff --git a/pkg/sdk/netmap/network_info_test.go b/pkg/sdk/netmap/network_info_test.go new file mode 100644 index 000000000..2819cb229 --- /dev/null +++ b/pkg/sdk/netmap/network_info_test.go @@ -0,0 +1,226 @@ +package netmap_test + +import ( + "encoding/binary" + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/netmap" + . "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" + "github.com/stretchr/testify/require" +) + +func TestNetworkInfo_CurrentEpoch(t *testing.T) { + var x NetworkInfo + + require.Zero(t, x.CurrentEpoch()) + + const e = 13 + + x.SetCurrentEpoch(e) + + require.EqualValues(t, e, x.CurrentEpoch()) + + var m netmap.NetworkInfo + x.WriteToV2(&m) + + require.EqualValues(t, e, m.GetCurrentEpoch()) +} + +func TestNetworkInfo_MagicNumber(t *testing.T) { + var x NetworkInfo + + require.Zero(t, x.MagicNumber()) + + const magic = 321 + + x.SetMagicNumber(magic) + + require.EqualValues(t, magic, x.MagicNumber()) + + var m netmap.NetworkInfo + x.WriteToV2(&m) + + require.EqualValues(t, magic, m.GetMagicNumber()) +} + +func TestNetworkInfo_MsPerBlock(t *testing.T) { + var x NetworkInfo + + require.Zero(t, x.MsPerBlock()) + + const ms = 789 + + x.SetMsPerBlock(ms) + + require.EqualValues(t, ms, x.MsPerBlock()) + + var m netmap.NetworkInfo + x.WriteToV2(&m) + + require.EqualValues(t, ms, m.GetMsPerBlock()) +} + +func testConfigValue(t *testing.T, + getter func(x NetworkInfo) any, + setter func(x *NetworkInfo, val any), + val1, val2 any, + v2Key string, v2Val func(val any) []byte, +) { + var x NetworkInfo + + require.Zero(t, getter(x)) + + checkVal := func(exp any) { + require.EqualValues(t, exp, getter(x)) + + var m netmap.NetworkInfo + x.WriteToV2(&m) + + require.EqualValues(t, 1, m.GetNetworkConfig().NumberOfParameters()) + found := false + m.GetNetworkConfig().IterateParameters(func(prm *netmap.NetworkParameter) bool { + require.False(t, found) + require.Equal(t, []byte(v2Key), prm.GetKey()) + require.Equal(t, v2Val(exp), prm.GetValue()) + found = true + return false + }) + require.True(t, found) + } + + setter(&x, val1) + checkVal(val1) + + setter(&x, val2) + checkVal(val2) +} + +func TestNetworkInfo_AuditFee(t *testing.T) { + testConfigValue(t, + func(x NetworkInfo) any { return x.AuditFee() }, + func(info *NetworkInfo, val any) { info.SetAuditFee(val.(uint64)) }, + uint64(1), uint64(2), + "AuditFee", func(val any) []byte { + data := make([]byte, 8) + binary.LittleEndian.PutUint64(data, val.(uint64)) + return data + }, + ) +} + +func TestNetworkInfo_StoragePrice(t *testing.T) { + testConfigValue(t, + func(x NetworkInfo) any { return x.StoragePrice() }, + func(info *NetworkInfo, val any) { info.SetStoragePrice(val.(uint64)) }, + uint64(1), uint64(2), + "BasicIncomeRate", func(val any) []byte { + data := make([]byte, 8) + binary.LittleEndian.PutUint64(data, val.(uint64)) + return data + }, + ) +} + +func TestNetworkInfo_ContainerFee(t *testing.T) { + testConfigValue(t, + func(x NetworkInfo) any { return x.ContainerFee() }, + func(info *NetworkInfo, val any) { info.SetContainerFee(val.(uint64)) }, + uint64(1), uint64(2), + "ContainerFee", func(val any) []byte { + data := make([]byte, 8) + binary.LittleEndian.PutUint64(data, val.(uint64)) + return data + }, + ) +} + +func TestNetworkInfo_NamedContainerFee(t *testing.T) { + testConfigValue(t, + func(x NetworkInfo) any { return x.NamedContainerFee() }, + func(info *NetworkInfo, val any) { info.SetNamedContainerFee(val.(uint64)) }, + uint64(1), uint64(2), + "ContainerAliasFee", func(val any) []byte { + data := make([]byte, 8) + binary.LittleEndian.PutUint64(data, val.(uint64)) + return data + }, + ) +} + +func TestNetworkInfo_IRCandidateFee(t *testing.T) { + testConfigValue(t, + func(x NetworkInfo) any { return x.IRCandidateFee() }, + func(info *NetworkInfo, val any) { info.SetIRCandidateFee(val.(uint64)) }, + uint64(1), uint64(2), + "InnerRingCandidateFee", func(val any) []byte { + data := make([]byte, 8) + binary.LittleEndian.PutUint64(data, val.(uint64)) + return data + }, + ) +} + +func TestNetworkInfo_MaxObjectSize(t *testing.T) { + testConfigValue(t, + func(x NetworkInfo) any { return x.MaxObjectSize() }, + func(info *NetworkInfo, val any) { info.SetMaxObjectSize(val.(uint64)) }, + uint64(1), uint64(2), + "MaxObjectSize", func(val any) []byte { + data := make([]byte, 8) + binary.LittleEndian.PutUint64(data, val.(uint64)) + return data + }, + ) +} + +func TestNetworkInfo_WithdrawalFee(t *testing.T) { + testConfigValue(t, + func(x NetworkInfo) any { return x.WithdrawalFee() }, + func(info *NetworkInfo, val any) { info.SetWithdrawalFee(val.(uint64)) }, + uint64(1), uint64(2), + "WithdrawFee", func(val any) []byte { + data := make([]byte, 8) + binary.LittleEndian.PutUint64(data, val.(uint64)) + return data + }, + ) +} + +func TestNetworkInfo_HomomorphicHashingDisabled(t *testing.T) { + testConfigValue(t, + func(x NetworkInfo) any { return x.HomomorphicHashingDisabled() }, + func(info *NetworkInfo, val any) { + if val.(bool) { + info.DisableHomomorphicHashing() + } + }, + true, true, // it is impossible to enable hashing + "HomomorphicHashingDisabled", func(val any) []byte { + data := make([]byte, 1) + + if val.(bool) { + data[0] = 1 + } + + return data + }, + ) +} + +func TestNetworkInfo_MaintenanceModeAllowed(t *testing.T) { + testConfigValue(t, + func(x NetworkInfo) any { return x.MaintenanceModeAllowed() }, + func(info *NetworkInfo, val any) { + if val.(bool) { + info.AllowMaintenanceMode() + } + }, + true, true, + "MaintenanceModeAllowed", func(val any) []byte { + if val.(bool) { + return []byte{1} + } + return []byte{0} + }, + ) +} diff --git a/pkg/sdk/netmap/node_info.go b/pkg/sdk/netmap/node_info.go new file mode 100644 index 000000000..0bfc1d489 --- /dev/null +++ b/pkg/sdk/netmap/node_info.go @@ -0,0 +1,524 @@ +package netmap + +import ( + "errors" + "fmt" + "sort" + "strconv" + "strings" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/netmap" + frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/crypto" + "git.frostfs.info/TrueCloudLab/hrw" +) + +// NodeInfo groups information about FrostFS storage node which is reflected +// in the FrostFS network map. Storage nodes advertise this information when +// registering with the FrostFS network. After successful registration, information +// about the nodes is available to all network participants to work with the network +// map (mainly to comply with container storage policies). +// +// NodeInfo is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/netmap.NodeInfo +// message. See ReadFromV2 / WriteToV2 methods. +// +// Instances can be created using built-in var declaration. +type NodeInfo struct { + m netmap.NodeInfo + hash uint64 +} + +// reads NodeInfo from netmap.NodeInfo message. If checkFieldPresence is set, +// returns an error on absence of any protocol-required field. Verifies format of any +// presented field according to FrostFS API V2 protocol. +func (x *NodeInfo) readFromV2(m netmap.NodeInfo, checkFieldPresence bool) error { + var err error + + binPublicKey := m.GetPublicKey() + if checkFieldPresence && len(binPublicKey) == 0 { + return errors.New("missing public key") + } + + if checkFieldPresence && m.NumberOfAddresses() <= 0 { + return errors.New("missing network endpoints") + } + + attributes := m.GetAttributes() + mAttr := make(map[string]struct{}, len(attributes)) + for i := range attributes { + key := attributes[i].GetKey() + if key == "" { + return fmt.Errorf("empty key of the attribute #%d", i) + } else if _, ok := mAttr[key]; ok { + return fmt.Errorf("duplicated attbiuted %s", key) + } + + switch { + case key == attrCapacity: + _, err = strconv.ParseUint(attributes[i].GetValue(), 10, 64) + if err != nil { + return fmt.Errorf("invalid %s attribute: %w", attrCapacity, err) + } + case key == attrPrice: + var err error + _, err = strconv.ParseUint(attributes[i].GetValue(), 10, 64) + if err != nil { + return fmt.Errorf("invalid %s attribute: %w", attrPrice, err) + } + default: + if attributes[i].GetValue() == "" { + return fmt.Errorf("empty value of the attribute %s", key) + } + } + } + + x.m = m + x.hash = hrw.Hash(binPublicKey) + + return nil +} + +// ReadFromV2 reads NodeInfo from the netmap.NodeInfo message. Checks if the +// message conforms to FrostFS API V2 protocol. +// +// See also WriteToV2. +func (x *NodeInfo) ReadFromV2(m netmap.NodeInfo) error { + return x.readFromV2(m, true) +} + +// WriteToV2 writes NodeInfo to the netmap.NodeInfo message. The message MUST NOT +// be nil. +// +// See also ReadFromV2. +func (x NodeInfo) WriteToV2(m *netmap.NodeInfo) { + *m = x.m +} + +// Marshal encodes NodeInfo into a binary format of the FrostFS API protocol +// (Protocol Buffers with direct field order). +// +// See also Unmarshal. +func (x NodeInfo) Marshal() []byte { + var m netmap.NodeInfo + x.WriteToV2(&m) + + return m.StableMarshal(nil) +} + +// Unmarshal decodes FrostFS API protocol binary format into the NodeInfo +// (Protocol Buffers with direct field order). Returns an error describing +// a format violation. +// +// See also Marshal. +func (x *NodeInfo) Unmarshal(data []byte) error { + var m netmap.NodeInfo + + err := m.Unmarshal(data) + if err != nil { + return err + } + + return x.readFromV2(m, false) +} + +// MarshalJSON encodes NodeInfo into a JSON format of the FrostFS API protocol +// (Protocol Buffers JSON). +// +// See also UnmarshalJSON. +func (x NodeInfo) MarshalJSON() ([]byte, error) { + var m netmap.NodeInfo + x.WriteToV2(&m) + + return m.MarshalJSON() +} + +// UnmarshalJSON decodes FrostFS API protocol JSON format into the NodeInfo +// (Protocol Buffers JSON). Returns an error describing a format violation. +// +// See also MarshalJSON. +func (x *NodeInfo) UnmarshalJSON(data []byte) error { + var m netmap.NodeInfo + + err := m.UnmarshalJSON(data) + if err != nil { + return err + } + + return x.readFromV2(m, false) +} + +// SetPublicKey sets binary-encoded public key bound to the node. The key +// authenticates the storage node, so it MUST be unique within the network. +// +// Argument MUST NOT be mutated, make a copy first. +// +// See also PublicKey. +func (x *NodeInfo) SetPublicKey(key []byte) { + x.m.SetPublicKey(key) + x.hash = hrw.Hash(x.m.GetPublicKey()) +} + +// PublicKey returns value set using SetPublicKey. +// +// Zero NodeInfo has no public key, which is incorrect according to +// FrostFS system requirements. +// +// Return value MUST not be mutated, make a copy first. +func (x NodeInfo) PublicKey() []byte { + return x.m.GetPublicKey() +} + +// StringifyPublicKey returns HEX representation of PublicKey. +func StringifyPublicKey(node NodeInfo) string { + return frostfscrypto.StringifyKeyBinary(node.PublicKey()) +} + +// SetNetworkEndpoints sets list to the announced node's network endpoints. +// Node MUSt have at least one announced endpoint. List MUST be unique. +// Endpoints are used for communication with the storage node within FrostFS +// network. It is expected that node serves storage node services on these +// endpoints (it also adds a wait on their network availability). +// +// Argument MUST NOT be mutated, make a copy first. +// +// See also IterateNetworkEndpoints. +func (x *NodeInfo) SetNetworkEndpoints(v ...string) { + x.m.SetAddresses(v...) +} + +// NumberOfNetworkEndpoints returns number of network endpoints announced by the node. +// +// See also SetNetworkEndpoints. +func (x NodeInfo) NumberOfNetworkEndpoints() int { + return x.m.NumberOfAddresses() +} + +// IterateNetworkEndpoints iterates over network endpoints announced by the +// node and pass them into f. Breaks iteration on f's true return. Handler +// MUST NOT be nil. +// +// Zero NodeInfo contains no endpoints which is incorrect according to +// FrostFS system requirements. +// +// See also SetNetworkEndpoints. +func (x NodeInfo) IterateNetworkEndpoints(f func(string) bool) { + x.m.IterateAddresses(f) +} + +// IterateNetworkEndpoints is an extra-sugared function over IterateNetworkEndpoints +// method which allows to unconditionally iterate over all node's network endpoints. +func IterateNetworkEndpoints(node NodeInfo, f func(string)) { + node.IterateNetworkEndpoints(func(addr string) bool { + f(addr) + return false + }) +} + +// assert NodeInfo type provides hrw.Hasher required for HRW sorting. +var _ hrw.Hasher = NodeInfo{} + +// Hash implements hrw.Hasher interface. +// +// Hash is needed to support weighted HRW therefore sort function sorts nodes +// based on their public key. Hash isn't expected to be used directly. +func (x NodeInfo) Hash() uint64 { + if x.hash != 0 { + return x.hash + } + return hrw.Hash(x.m.GetPublicKey()) +} + +// less declares "less than" comparison between two NodeInfo instances: +// x1 is less than x2 if it has less Hash(). +// +// Method is needed for internal placement needs. +func less(x1, x2 NodeInfo) bool { + return x1.Hash() < x2.Hash() +} + +func (x *NodeInfo) setNumericAttribute(key string, num uint64) { + x.SetAttribute(key, strconv.FormatUint(num, 10)) +} + +// SetPrice sets the storage cost declared by the node. By default, zero +// price is announced. +func (x *NodeInfo) SetPrice(price uint64) { + x.setNumericAttribute(attrPrice, price) +} + +// Price returns price set using SetPrice. +// +// Zero NodeInfo has zero price. +func (x NodeInfo) Price() uint64 { + val := x.Attribute(attrPrice) + if val == "" { + return 0 + } + + price, err := strconv.ParseUint(val, 10, 64) + if err != nil { + panic(fmt.Sprintf("unexpected price parsing error %s: %v", val, err)) + } + + return price +} + +// SetCapacity sets the storage capacity declared by the node. By default, zero +// capacity is announced. +func (x *NodeInfo) SetCapacity(capacity uint64) { + x.setNumericAttribute(attrCapacity, capacity) +} + +// capacity returns capacity set using SetCapacity. +// +// Zero NodeInfo has zero capacity. +func (x NodeInfo) capacity() uint64 { + val := x.Attribute(attrCapacity) + if val == "" { + return 0 + } + + capacity, err := strconv.ParseUint(val, 10, 64) + if err != nil { + panic(fmt.Sprintf("unexpected capacity parsing error %s: %v", val, err)) + } + + return capacity +} + +const attrUNLOCODE = "UN-LOCODE" + +// SetLOCODE specifies node's geographic location in UN/LOCODE format. Each +// storage node MUST declare it for entrance to the FrostFS network. Node MAY +// declare the code of the nearest location as needed, for example, when it is +// impossible to unambiguously attribute the node to any location from UN/LOCODE +// database. +// +// See also LOCODE. +func (x *NodeInfo) SetLOCODE(locode string) { + x.SetAttribute(attrUNLOCODE, locode) +} + +// LOCODE returns node's location code set using SetLOCODE. +// +// Zero NodeInfo has empty location code which is invalid according to +// FrostFS API system requirement. +func (x NodeInfo) LOCODE() string { + return x.Attribute(attrUNLOCODE) +} + +// SetCountryCode sets code of the country in ISO 3166-1_alpha-2 to which +// storage node belongs (or the closest one). +// +// SetCountryCode is intended only for processing the network registration +// request by the Inner Ring. Other parties SHOULD NOT use it. +func (x *NodeInfo) SetCountryCode(countryCode string) { + x.SetAttribute("CountryCode", countryCode) +} + +// SetCountryName sets short name of the country in ISO-3166 format to which +// storage node belongs (or the closest one). +// +// SetCountryName is intended only for processing the network registration +// request by the Inner Ring. Other parties SHOULD NOT use it. +func (x *NodeInfo) SetCountryName(country string) { + x.SetAttribute("Country", country) +} + +// SetLocationName sets storage node's location name from "NameWoDiacritics" +// column in the UN/LOCODE record corresponding to the specified LOCODE. +// +// SetLocationName is intended only for processing the network registration +// request by the Inner Ring. Other parties SHOULD NOT use it. +func (x *NodeInfo) SetLocationName(location string) { + x.SetAttribute("Location", location) +} + +// SetSubdivisionCode sets storage node's subdivision code from "SubDiv" column in +// the UN/LOCODE record corresponding to the specified LOCODE. +// +// SetSubdivisionCode is intended only for processing the network registration +// request by the Inner Ring. Other parties SHOULD NOT use it. +func (x *NodeInfo) SetSubdivisionCode(subDiv string) { + x.SetAttribute("SubDivCode", subDiv) +} + +// SetSubdivisionName sets storage node's subdivision name in ISO 3166-2 format. +// +// SetSubdivisionName is intended only for processing the network registration +// request by the Inner Ring. Other parties SHOULD NOT use it. +func (x *NodeInfo) SetSubdivisionName(subDiv string) { + x.SetAttribute("SubDiv", subDiv) +} + +// SetContinentName sets name of the storage node's continent from +// Seven-Continent model. +// +// SetContinentName is intended only for processing the network registration +// request by the Inner Ring. Other parties SHOULD NOT use it. +func (x *NodeInfo) SetContinentName(continent string) { + x.SetAttribute("Continent", continent) +} + +// Enumeration of well-known attributes. +const ( + // attrPrice is a key to the node attribute that indicates the + // price in GAS tokens for storing one GB of data during one Epoch. + attrPrice = "Price" + + // attrCapacity is a key to the node attribute that indicates the + // total available disk space in Gigabytes. + attrCapacity = "Capacity" + + // attrExternalAddr is a key for the attribute storing node external addresses. + attrExternalAddr = "ExternalAddr" + // sepExternalAddr is a separator for multi-value ExternalAddr attribute. + sepExternalAddr = "," +) + +// SetExternalAddresses sets multi-addresses to use +// to connect to this node from outside. +// +// Panics if addr is an empty list. +func (x *NodeInfo) SetExternalAddresses(addr ...string) { + x.SetAttribute(attrExternalAddr, strings.Join(addr, sepExternalAddr)) +} + +// ExternalAddresses returns list of multi-addresses to use +// to connect to this node from outside. +func (x NodeInfo) ExternalAddresses() []string { + a := x.Attribute(attrExternalAddr) + if len(a) == 0 { + return nil + } + + return strings.Split(a, sepExternalAddr) +} + +// NumberOfAttributes returns number of attributes announced by the node. +// +// See also SetAttribute. +func (x NodeInfo) NumberOfAttributes() int { + return len(x.m.GetAttributes()) +} + +// IterateAttributes iterates over all node attributes and passes the into f. +// Handler MUST NOT be nil. +func (x NodeInfo) IterateAttributes(f func(key, value string)) { + a := x.m.GetAttributes() + for i := range a { + f(a[i].GetKey(), a[i].GetValue()) + } +} + +// SetAttribute sets value of the node attribute value by the given key. +// Both key and value MUST NOT be empty. +func (x *NodeInfo) SetAttribute(key, value string) { + if key == "" { + panic("empty key in SetAttribute") + } else if value == "" { + panic("empty value in SetAttribute") + } + + a := x.m.GetAttributes() + for i := range a { + if a[i].GetKey() == key { + a[i].SetValue(value) + return + } + } + + a = append(a, netmap.Attribute{}) + a[len(a)-1].SetKey(key) + a[len(a)-1].SetValue(value) + + x.m.SetAttributes(a) +} + +// Attribute returns value of the node attribute set using SetAttribute by the +// given key. Returns empty string if attribute is missing. +func (x NodeInfo) Attribute(key string) string { + a := x.m.GetAttributes() + for i := range a { + if a[i].GetKey() == key { + return a[i].GetValue() + } + } + + return "" +} + +// SortAttributes sorts node attributes set using SetAttribute lexicographically. +// The method is only needed to make NodeInfo consistent, e.g. for signing. +func (x *NodeInfo) SortAttributes() { + as := x.m.GetAttributes() + if len(as) == 0 { + return + } + + sort.Slice(as, func(i, j int) bool { + switch strings.Compare(as[i].GetKey(), as[j].GetKey()) { + case -1: + return true + case 1: + return false + default: + return as[i].GetValue() < as[j].GetValue() + } + }) + + x.m.SetAttributes(as) +} + +// SetOffline sets the state of the node to "offline". When a node updates +// information about itself in the network map, this action is interpreted as +// an intention to leave the network. +func (x *NodeInfo) SetOffline() { + x.m.SetState(netmap.Offline) +} + +// IsOffline checks if the node is in the "offline" state. +// +// Zero NodeInfo has undefined state which is not offline (note that it does not +// mean online). +// +// See also SetOffline. +func (x NodeInfo) IsOffline() bool { + return x.m.GetState() == netmap.Offline +} + +// SetOnline sets the state of the node to "online". When a node updates +// information about itself in the network map, this +// action is interpreted as an intention to enter the network. +// +// See also IsOnline. +func (x *NodeInfo) SetOnline() { + x.m.SetState(netmap.Online) +} + +// IsOnline checks if the node is in the "online" state. +// +// Zero NodeInfo has undefined state which is not online (note that it does not +// mean offline). +// +// See also SetOnline. +func (x NodeInfo) IsOnline() bool { + return x.m.GetState() == netmap.Online +} + +// SetMaintenance sets the state of the node to "maintenance". When a node updates +// information about itself in the network map, this +// state declares temporal unavailability for a node. +// +// See also IsMaintenance. +func (x *NodeInfo) SetMaintenance() { + x.m.SetState(netmap.Maintenance) +} + +// IsMaintenance checks if the node is in the "maintenance" state. +// +// Zero NodeInfo has undefined state. +// +// See also SetMaintenance. +func (x NodeInfo) IsMaintenance() bool { + return x.m.GetState() == netmap.Maintenance +} diff --git a/pkg/sdk/netmap/node_info_test.go b/pkg/sdk/netmap/node_info_test.go new file mode 100644 index 000000000..1d1c01838 --- /dev/null +++ b/pkg/sdk/netmap/node_info_test.go @@ -0,0 +1,61 @@ +package netmap + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestNodeInfo_SetAttribute(t *testing.T) { + var n NodeInfo + + const key = "some key" + val := "some value" + + require.Zero(t, n.Attribute(val)) + + n.SetAttribute(key, val) + require.Equal(t, val, n.Attribute(key)) + + val = "some other value" + + n.SetAttribute(key, val) + require.Equal(t, val, n.Attribute(key)) +} + +func TestNodeInfo_Status(t *testing.T) { + var n NodeInfo + + require.False(t, n.IsOnline()) + require.False(t, n.IsOffline()) + require.False(t, n.IsMaintenance()) + + n.SetOnline() + require.True(t, n.IsOnline()) + require.False(t, n.IsOffline()) + require.False(t, n.IsMaintenance()) + + n.SetOffline() + require.True(t, n.IsOffline()) + require.False(t, n.IsOnline()) + require.False(t, n.IsMaintenance()) + + n.SetMaintenance() + require.True(t, n.IsMaintenance()) + require.False(t, n.IsOnline()) + require.False(t, n.IsOffline()) +} + +func TestNodeInfo_ExternalAddr(t *testing.T) { + var n NodeInfo + + require.Empty(t, n.ExternalAddresses()) + require.Panics(t, func() { n.SetExternalAddresses() }) + + addr := []string{"1", "2", "3"} + n.SetExternalAddresses(addr[0]) + require.Equal(t, addr[:1], n.ExternalAddresses()) + + n.SetExternalAddresses(addr[1:]...) + require.Equal(t, addr[1:], n.ExternalAddresses()) +} diff --git a/pkg/sdk/netmap/parser/Query.g4 b/pkg/sdk/netmap/parser/Query.g4 new file mode 100644 index 000000000..72fa880a1 --- /dev/null +++ b/pkg/sdk/netmap/parser/Query.g4 @@ -0,0 +1,49 @@ +parser grammar Query; + +options { + tokenVocab = QueryLexer; +} + +policy: UNIQUE? repStmt+ cbfStmt? selectStmt* filterStmt* EOF; + +selectFilterExpr: cbfStmt? selectStmt? filterStmt* EOF; + +repStmt: + REP Count = NUMBER1 // number of object replicas + (IN Selector = ident)?; // optional selector name + +cbfStmt: CBF BackupFactor = NUMBER1; // container backup factor + +selectStmt: + SELECT Count = NUMBER1 // number of nodes to select without container backup factor *) + (IN clause? Bucket = ident)? // bucket name + FROM Filter = identWC // filter reference or whole netmap + (AS Name = ident)? // optional selector name + ; + +clause: CLAUSE_SAME | CLAUSE_DISTINCT; // nodes from distinct buckets + +filterExpr: + Op = NOT_OP '(' F1 = filterExpr ')' + | F1 = filterExpr Op = AND_OP F2 = filterExpr + | F1 = filterExpr Op = OR_OP F2 = filterExpr + | '(' Inner = filterExpr ')' + | expr + ; + +filterStmt: + FILTER Expr = filterExpr + AS Name = ident // obligatory filter name + ; + +expr: + AT Filter = ident // reference to named filter + | Key = filterKey SIMPLE_OP Value = filterValue // attribute comparison + ; + +filterKey : ident | STRING; +filterValue : ident | number | STRING; +number : ZERO | NUMBER1; +keyword : REP | IN | AS | SELECT | FROM | FILTER; +ident : keyword | IDENT; +identWC : ident | WILDCARD; diff --git a/pkg/sdk/netmap/parser/Query.interp b/pkg/sdk/netmap/parser/Query.interp new file mode 100644 index 000000000..a8fb219e6 --- /dev/null +++ b/pkg/sdk/netmap/parser/Query.interp @@ -0,0 +1,72 @@ +token literal names: +null +'NOT' +'AND' +'OR' +null +'UNIQUE' +'REP' +'IN' +'AS' +'CBF' +'SELECT' +'FROM' +'FILTER' +'*' +'SAME' +'DISTINCT' +'(' +')' +'@' +null +null +'0' +null +null + +token symbolic names: +null +NOT_OP +AND_OP +OR_OP +SIMPLE_OP +UNIQUE +REP +IN +AS +CBF +SELECT +FROM +FILTER +WILDCARD +CLAUSE_SAME +CLAUSE_DISTINCT +L_PAREN +R_PAREN +AT +IDENT +NUMBER1 +ZERO +STRING +WS + +rule names: +policy +selectFilterExpr +repStmt +cbfStmt +selectStmt +clause +filterExpr +filterStmt +expr +filterKey +filterValue +number +keyword +ident +identWC + + +atn: +[4, 1, 23, 154, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 1, 0, 3, 0, 32, 8, 0, 1, 0, 4, 0, 35, 8, 0, 11, 0, 12, 0, 36, 1, 0, 3, 0, 40, 8, 0, 1, 0, 5, 0, 43, 8, 0, 10, 0, 12, 0, 46, 9, 0, 1, 0, 5, 0, 49, 8, 0, 10, 0, 12, 0, 52, 9, 0, 1, 0, 1, 0, 1, 1, 3, 1, 57, 8, 1, 1, 1, 3, 1, 60, 8, 1, 1, 1, 5, 1, 63, 8, 1, 10, 1, 12, 1, 66, 9, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2, 3, 2, 74, 8, 2, 1, 3, 1, 3, 1, 3, 1, 4, 1, 4, 1, 4, 1, 4, 3, 4, 83, 8, 4, 1, 4, 3, 4, 86, 8, 4, 1, 4, 1, 4, 1, 4, 1, 4, 3, 4, 92, 8, 4, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 3, 6, 107, 8, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 5, 6, 115, 8, 6, 10, 6, 12, 6, 118, 9, 6, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 3, 8, 131, 8, 8, 1, 9, 1, 9, 3, 9, 135, 8, 9, 1, 10, 1, 10, 1, 10, 3, 10, 140, 8, 10, 1, 11, 1, 11, 1, 12, 1, 12, 1, 13, 1, 13, 3, 13, 148, 8, 13, 1, 14, 1, 14, 3, 14, 152, 8, 14, 1, 14, 0, 1, 12, 15, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 0, 3, 1, 0, 14, 15, 1, 0, 20, 21, 2, 0, 6, 8, 10, 12, 160, 0, 31, 1, 0, 0, 0, 2, 56, 1, 0, 0, 0, 4, 69, 1, 0, 0, 0, 6, 75, 1, 0, 0, 0, 8, 78, 1, 0, 0, 0, 10, 93, 1, 0, 0, 0, 12, 106, 1, 0, 0, 0, 14, 119, 1, 0, 0, 0, 16, 130, 1, 0, 0, 0, 18, 134, 1, 0, 0, 0, 20, 139, 1, 0, 0, 0, 22, 141, 1, 0, 0, 0, 24, 143, 1, 0, 0, 0, 26, 147, 1, 0, 0, 0, 28, 151, 1, 0, 0, 0, 30, 32, 5, 5, 0, 0, 31, 30, 1, 0, 0, 0, 31, 32, 1, 0, 0, 0, 32, 34, 1, 0, 0, 0, 33, 35, 3, 4, 2, 0, 34, 33, 1, 0, 0, 0, 35, 36, 1, 0, 0, 0, 36, 34, 1, 0, 0, 0, 36, 37, 1, 0, 0, 0, 37, 39, 1, 0, 0, 0, 38, 40, 3, 6, 3, 0, 39, 38, 1, 0, 0, 0, 39, 40, 1, 0, 0, 0, 40, 44, 1, 0, 0, 0, 41, 43, 3, 8, 4, 0, 42, 41, 1, 0, 0, 0, 43, 46, 1, 0, 0, 0, 44, 42, 1, 0, 0, 0, 44, 45, 1, 0, 0, 0, 45, 50, 1, 0, 0, 0, 46, 44, 1, 0, 0, 0, 47, 49, 3, 14, 7, 0, 48, 47, 1, 0, 0, 0, 49, 52, 1, 0, 0, 0, 50, 48, 1, 0, 0, 0, 50, 51, 1, 0, 0, 0, 51, 53, 1, 0, 0, 0, 52, 50, 1, 0, 0, 0, 53, 54, 5, 0, 0, 1, 54, 1, 1, 0, 0, 0, 55, 57, 3, 6, 3, 0, 56, 55, 1, 0, 0, 0, 56, 57, 1, 0, 0, 0, 57, 59, 1, 0, 0, 0, 58, 60, 3, 8, 4, 0, 59, 58, 1, 0, 0, 0, 59, 60, 1, 0, 0, 0, 60, 64, 1, 0, 0, 0, 61, 63, 3, 14, 7, 0, 62, 61, 1, 0, 0, 0, 63, 66, 1, 0, 0, 0, 64, 62, 1, 0, 0, 0, 64, 65, 1, 0, 0, 0, 65, 67, 1, 0, 0, 0, 66, 64, 1, 0, 0, 0, 67, 68, 5, 0, 0, 1, 68, 3, 1, 0, 0, 0, 69, 70, 5, 6, 0, 0, 70, 73, 5, 20, 0, 0, 71, 72, 5, 7, 0, 0, 72, 74, 3, 26, 13, 0, 73, 71, 1, 0, 0, 0, 73, 74, 1, 0, 0, 0, 74, 5, 1, 0, 0, 0, 75, 76, 5, 9, 0, 0, 76, 77, 5, 20, 0, 0, 77, 7, 1, 0, 0, 0, 78, 79, 5, 10, 0, 0, 79, 85, 5, 20, 0, 0, 80, 82, 5, 7, 0, 0, 81, 83, 3, 10, 5, 0, 82, 81, 1, 0, 0, 0, 82, 83, 1, 0, 0, 0, 83, 84, 1, 0, 0, 0, 84, 86, 3, 26, 13, 0, 85, 80, 1, 0, 0, 0, 85, 86, 1, 0, 0, 0, 86, 87, 1, 0, 0, 0, 87, 88, 5, 11, 0, 0, 88, 91, 3, 28, 14, 0, 89, 90, 5, 8, 0, 0, 90, 92, 3, 26, 13, 0, 91, 89, 1, 0, 0, 0, 91, 92, 1, 0, 0, 0, 92, 9, 1, 0, 0, 0, 93, 94, 7, 0, 0, 0, 94, 11, 1, 0, 0, 0, 95, 96, 6, 6, -1, 0, 96, 97, 5, 1, 0, 0, 97, 98, 5, 16, 0, 0, 98, 99, 3, 12, 6, 0, 99, 100, 5, 17, 0, 0, 100, 107, 1, 0, 0, 0, 101, 102, 5, 16, 0, 0, 102, 103, 3, 12, 6, 0, 103, 104, 5, 17, 0, 0, 104, 107, 1, 0, 0, 0, 105, 107, 3, 16, 8, 0, 106, 95, 1, 0, 0, 0, 106, 101, 1, 0, 0, 0, 106, 105, 1, 0, 0, 0, 107, 116, 1, 0, 0, 0, 108, 109, 10, 4, 0, 0, 109, 110, 5, 2, 0, 0, 110, 115, 3, 12, 6, 5, 111, 112, 10, 3, 0, 0, 112, 113, 5, 3, 0, 0, 113, 115, 3, 12, 6, 4, 114, 108, 1, 0, 0, 0, 114, 111, 1, 0, 0, 0, 115, 118, 1, 0, 0, 0, 116, 114, 1, 0, 0, 0, 116, 117, 1, 0, 0, 0, 117, 13, 1, 0, 0, 0, 118, 116, 1, 0, 0, 0, 119, 120, 5, 12, 0, 0, 120, 121, 3, 12, 6, 0, 121, 122, 5, 8, 0, 0, 122, 123, 3, 26, 13, 0, 123, 15, 1, 0, 0, 0, 124, 125, 5, 18, 0, 0, 125, 131, 3, 26, 13, 0, 126, 127, 3, 18, 9, 0, 127, 128, 5, 4, 0, 0, 128, 129, 3, 20, 10, 0, 129, 131, 1, 0, 0, 0, 130, 124, 1, 0, 0, 0, 130, 126, 1, 0, 0, 0, 131, 17, 1, 0, 0, 0, 132, 135, 3, 26, 13, 0, 133, 135, 5, 22, 0, 0, 134, 132, 1, 0, 0, 0, 134, 133, 1, 0, 0, 0, 135, 19, 1, 0, 0, 0, 136, 140, 3, 26, 13, 0, 137, 140, 3, 22, 11, 0, 138, 140, 5, 22, 0, 0, 139, 136, 1, 0, 0, 0, 139, 137, 1, 0, 0, 0, 139, 138, 1, 0, 0, 0, 140, 21, 1, 0, 0, 0, 141, 142, 7, 1, 0, 0, 142, 23, 1, 0, 0, 0, 143, 144, 7, 2, 0, 0, 144, 25, 1, 0, 0, 0, 145, 148, 3, 24, 12, 0, 146, 148, 5, 19, 0, 0, 147, 145, 1, 0, 0, 0, 147, 146, 1, 0, 0, 0, 148, 27, 1, 0, 0, 0, 149, 152, 3, 26, 13, 0, 150, 152, 5, 13, 0, 0, 151, 149, 1, 0, 0, 0, 151, 150, 1, 0, 0, 0, 152, 29, 1, 0, 0, 0, 20, 31, 36, 39, 44, 50, 56, 59, 64, 73, 82, 85, 91, 106, 114, 116, 130, 134, 139, 147, 151] \ No newline at end of file diff --git a/pkg/sdk/netmap/parser/Query.tokens b/pkg/sdk/netmap/parser/Query.tokens new file mode 100644 index 000000000..6376ea255 --- /dev/null +++ b/pkg/sdk/netmap/parser/Query.tokens @@ -0,0 +1,41 @@ +NOT_OP=1 +AND_OP=2 +OR_OP=3 +SIMPLE_OP=4 +UNIQUE=5 +REP=6 +IN=7 +AS=8 +CBF=9 +SELECT=10 +FROM=11 +FILTER=12 +WILDCARD=13 +CLAUSE_SAME=14 +CLAUSE_DISTINCT=15 +L_PAREN=16 +R_PAREN=17 +AT=18 +IDENT=19 +NUMBER1=20 +ZERO=21 +STRING=22 +WS=23 +'NOT'=1 +'AND'=2 +'OR'=3 +'UNIQUE'=5 +'REP'=6 +'IN'=7 +'AS'=8 +'CBF'=9 +'SELECT'=10 +'FROM'=11 +'FILTER'=12 +'*'=13 +'SAME'=14 +'DISTINCT'=15 +'('=16 +')'=17 +'@'=18 +'0'=21 diff --git a/pkg/sdk/netmap/parser/QueryLexer.g4 b/pkg/sdk/netmap/parser/QueryLexer.g4 new file mode 100644 index 000000000..c9b5ae681 --- /dev/null +++ b/pkg/sdk/netmap/parser/QueryLexer.g4 @@ -0,0 +1,43 @@ +lexer grammar QueryLexer; + +NOT_OP : 'NOT'; +AND_OP : 'AND'; +OR_OP : 'OR'; +SIMPLE_OP : 'EQ' | 'NE' | 'GE' | 'GT' | 'LT' | 'LE'; + +UNIQUE : 'UNIQUE'; +REP : 'REP'; +IN : 'IN'; +AS : 'AS'; +CBF : 'CBF'; +SELECT : 'SELECT'; +FROM : 'FROM'; +FILTER : 'FILTER'; +WILDCARD : '*'; + +CLAUSE_SAME : 'SAME'; +CLAUSE_DISTINCT : 'DISTINCT'; + +L_PAREN : '('; +R_PAREN : ')'; +AT : '@'; + +IDENT : Nondigit (Digit | Nondigit)* ; +fragment Digit : [0-9] ; +fragment Nondigit : [a-zA-Z_] ; + +NUMBER1 : [1-9] Digit* ; +ZERO : '0' ; + +// Taken from antlr4 json grammar with minor corrections. +// https://github.com/antlr/grammars-v4/blob/master/json/JSON.g4 +STRING : '"' (ESC | SAFECODEPOINTDOUBLE)* '"' + | '\'' (ESC | SAFECODEPOINTSINGLE)* '\'' ; + +fragment ESC : '\\' (['"\\/bfnrt] | UNICODE) ; +fragment UNICODE : 'u' HEX HEX HEX HEX ; +fragment HEX : [0-9a-fA-F] ; +fragment SAFECODEPOINTSINGLE : ~ ['\\\u0000-\u001F] ; +fragment SAFECODEPOINTDOUBLE : ~ ["\\\u0000-\u001F] ; + +WS : [ \t\n\r] + -> skip ; diff --git a/pkg/sdk/netmap/parser/QueryLexer.interp b/pkg/sdk/netmap/parser/QueryLexer.interp new file mode 100644 index 000000000..95db14431 --- /dev/null +++ b/pkg/sdk/netmap/parser/QueryLexer.interp @@ -0,0 +1,93 @@ +token literal names: +null +'NOT' +'AND' +'OR' +null +'UNIQUE' +'REP' +'IN' +'AS' +'CBF' +'SELECT' +'FROM' +'FILTER' +'*' +'SAME' +'DISTINCT' +'(' +')' +'@' +null +null +'0' +null +null + +token symbolic names: +null +NOT_OP +AND_OP +OR_OP +SIMPLE_OP +UNIQUE +REP +IN +AS +CBF +SELECT +FROM +FILTER +WILDCARD +CLAUSE_SAME +CLAUSE_DISTINCT +L_PAREN +R_PAREN +AT +IDENT +NUMBER1 +ZERO +STRING +WS + +rule names: +NOT_OP +AND_OP +OR_OP +SIMPLE_OP +UNIQUE +REP +IN +AS +CBF +SELECT +FROM +FILTER +WILDCARD +CLAUSE_SAME +CLAUSE_DISTINCT +L_PAREN +R_PAREN +AT +IDENT +Digit +Nondigit +NUMBER1 +ZERO +STRING +ESC +UNICODE +HEX +SAFECODEPOINTSINGLE +SAFECODEPOINTDOUBLE +WS + +channel names: +DEFAULT_TOKEN_CHANNEL +HIDDEN + +mode names: +DEFAULT_MODE + +atn: +[4, 0, 23, 213, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 3, 3, 85, 8, 3, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 7, 1, 8, 1, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 15, 1, 15, 1, 16, 1, 16, 1, 17, 1, 17, 1, 18, 1, 18, 1, 18, 5, 18, 152, 8, 18, 10, 18, 12, 18, 155, 9, 18, 1, 19, 1, 19, 1, 20, 1, 20, 1, 21, 1, 21, 5, 21, 163, 8, 21, 10, 21, 12, 21, 166, 9, 21, 1, 22, 1, 22, 1, 23, 1, 23, 1, 23, 5, 23, 173, 8, 23, 10, 23, 12, 23, 176, 9, 23, 1, 23, 1, 23, 1, 23, 1, 23, 5, 23, 182, 8, 23, 10, 23, 12, 23, 185, 9, 23, 1, 23, 3, 23, 188, 8, 23, 1, 24, 1, 24, 1, 24, 3, 24, 193, 8, 24, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 26, 1, 26, 1, 27, 1, 27, 1, 28, 1, 28, 1, 29, 4, 29, 208, 8, 29, 11, 29, 12, 29, 209, 1, 29, 1, 29, 0, 0, 30, 1, 1, 3, 2, 5, 3, 7, 4, 9, 5, 11, 6, 13, 7, 15, 8, 17, 9, 19, 10, 21, 11, 23, 12, 25, 13, 27, 14, 29, 15, 31, 16, 33, 17, 35, 18, 37, 19, 39, 0, 41, 0, 43, 20, 45, 21, 47, 22, 49, 0, 51, 0, 53, 0, 55, 0, 57, 0, 59, 23, 1, 0, 8, 1, 0, 48, 57, 3, 0, 65, 90, 95, 95, 97, 122, 1, 0, 49, 57, 9, 0, 34, 34, 39, 39, 47, 47, 92, 92, 98, 98, 102, 102, 110, 110, 114, 114, 116, 116, 3, 0, 48, 57, 65, 70, 97, 102, 3, 0, 0, 31, 39, 39, 92, 92, 3, 0, 0, 31, 34, 34, 92, 92, 3, 0, 9, 10, 13, 13, 32, 32, 220, 0, 1, 1, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 9, 1, 0, 0, 0, 0, 11, 1, 0, 0, 0, 0, 13, 1, 0, 0, 0, 0, 15, 1, 0, 0, 0, 0, 17, 1, 0, 0, 0, 0, 19, 1, 0, 0, 0, 0, 21, 1, 0, 0, 0, 0, 23, 1, 0, 0, 0, 0, 25, 1, 0, 0, 0, 0, 27, 1, 0, 0, 0, 0, 29, 1, 0, 0, 0, 0, 31, 1, 0, 0, 0, 0, 33, 1, 0, 0, 0, 0, 35, 1, 0, 0, 0, 0, 37, 1, 0, 0, 0, 0, 43, 1, 0, 0, 0, 0, 45, 1, 0, 0, 0, 0, 47, 1, 0, 0, 0, 0, 59, 1, 0, 0, 0, 1, 61, 1, 0, 0, 0, 3, 65, 1, 0, 0, 0, 5, 69, 1, 0, 0, 0, 7, 84, 1, 0, 0, 0, 9, 86, 1, 0, 0, 0, 11, 93, 1, 0, 0, 0, 13, 97, 1, 0, 0, 0, 15, 100, 1, 0, 0, 0, 17, 103, 1, 0, 0, 0, 19, 107, 1, 0, 0, 0, 21, 114, 1, 0, 0, 0, 23, 119, 1, 0, 0, 0, 25, 126, 1, 0, 0, 0, 27, 128, 1, 0, 0, 0, 29, 133, 1, 0, 0, 0, 31, 142, 1, 0, 0, 0, 33, 144, 1, 0, 0, 0, 35, 146, 1, 0, 0, 0, 37, 148, 1, 0, 0, 0, 39, 156, 1, 0, 0, 0, 41, 158, 1, 0, 0, 0, 43, 160, 1, 0, 0, 0, 45, 167, 1, 0, 0, 0, 47, 187, 1, 0, 0, 0, 49, 189, 1, 0, 0, 0, 51, 194, 1, 0, 0, 0, 53, 200, 1, 0, 0, 0, 55, 202, 1, 0, 0, 0, 57, 204, 1, 0, 0, 0, 59, 207, 1, 0, 0, 0, 61, 62, 5, 78, 0, 0, 62, 63, 5, 79, 0, 0, 63, 64, 5, 84, 0, 0, 64, 2, 1, 0, 0, 0, 65, 66, 5, 65, 0, 0, 66, 67, 5, 78, 0, 0, 67, 68, 5, 68, 0, 0, 68, 4, 1, 0, 0, 0, 69, 70, 5, 79, 0, 0, 70, 71, 5, 82, 0, 0, 71, 6, 1, 0, 0, 0, 72, 73, 5, 69, 0, 0, 73, 85, 5, 81, 0, 0, 74, 75, 5, 78, 0, 0, 75, 85, 5, 69, 0, 0, 76, 77, 5, 71, 0, 0, 77, 85, 5, 69, 0, 0, 78, 79, 5, 71, 0, 0, 79, 85, 5, 84, 0, 0, 80, 81, 5, 76, 0, 0, 81, 85, 5, 84, 0, 0, 82, 83, 5, 76, 0, 0, 83, 85, 5, 69, 0, 0, 84, 72, 1, 0, 0, 0, 84, 74, 1, 0, 0, 0, 84, 76, 1, 0, 0, 0, 84, 78, 1, 0, 0, 0, 84, 80, 1, 0, 0, 0, 84, 82, 1, 0, 0, 0, 85, 8, 1, 0, 0, 0, 86, 87, 5, 85, 0, 0, 87, 88, 5, 78, 0, 0, 88, 89, 5, 73, 0, 0, 89, 90, 5, 81, 0, 0, 90, 91, 5, 85, 0, 0, 91, 92, 5, 69, 0, 0, 92, 10, 1, 0, 0, 0, 93, 94, 5, 82, 0, 0, 94, 95, 5, 69, 0, 0, 95, 96, 5, 80, 0, 0, 96, 12, 1, 0, 0, 0, 97, 98, 5, 73, 0, 0, 98, 99, 5, 78, 0, 0, 99, 14, 1, 0, 0, 0, 100, 101, 5, 65, 0, 0, 101, 102, 5, 83, 0, 0, 102, 16, 1, 0, 0, 0, 103, 104, 5, 67, 0, 0, 104, 105, 5, 66, 0, 0, 105, 106, 5, 70, 0, 0, 106, 18, 1, 0, 0, 0, 107, 108, 5, 83, 0, 0, 108, 109, 5, 69, 0, 0, 109, 110, 5, 76, 0, 0, 110, 111, 5, 69, 0, 0, 111, 112, 5, 67, 0, 0, 112, 113, 5, 84, 0, 0, 113, 20, 1, 0, 0, 0, 114, 115, 5, 70, 0, 0, 115, 116, 5, 82, 0, 0, 116, 117, 5, 79, 0, 0, 117, 118, 5, 77, 0, 0, 118, 22, 1, 0, 0, 0, 119, 120, 5, 70, 0, 0, 120, 121, 5, 73, 0, 0, 121, 122, 5, 76, 0, 0, 122, 123, 5, 84, 0, 0, 123, 124, 5, 69, 0, 0, 124, 125, 5, 82, 0, 0, 125, 24, 1, 0, 0, 0, 126, 127, 5, 42, 0, 0, 127, 26, 1, 0, 0, 0, 128, 129, 5, 83, 0, 0, 129, 130, 5, 65, 0, 0, 130, 131, 5, 77, 0, 0, 131, 132, 5, 69, 0, 0, 132, 28, 1, 0, 0, 0, 133, 134, 5, 68, 0, 0, 134, 135, 5, 73, 0, 0, 135, 136, 5, 83, 0, 0, 136, 137, 5, 84, 0, 0, 137, 138, 5, 73, 0, 0, 138, 139, 5, 78, 0, 0, 139, 140, 5, 67, 0, 0, 140, 141, 5, 84, 0, 0, 141, 30, 1, 0, 0, 0, 142, 143, 5, 40, 0, 0, 143, 32, 1, 0, 0, 0, 144, 145, 5, 41, 0, 0, 145, 34, 1, 0, 0, 0, 146, 147, 5, 64, 0, 0, 147, 36, 1, 0, 0, 0, 148, 153, 3, 41, 20, 0, 149, 152, 3, 39, 19, 0, 150, 152, 3, 41, 20, 0, 151, 149, 1, 0, 0, 0, 151, 150, 1, 0, 0, 0, 152, 155, 1, 0, 0, 0, 153, 151, 1, 0, 0, 0, 153, 154, 1, 0, 0, 0, 154, 38, 1, 0, 0, 0, 155, 153, 1, 0, 0, 0, 156, 157, 7, 0, 0, 0, 157, 40, 1, 0, 0, 0, 158, 159, 7, 1, 0, 0, 159, 42, 1, 0, 0, 0, 160, 164, 7, 2, 0, 0, 161, 163, 3, 39, 19, 0, 162, 161, 1, 0, 0, 0, 163, 166, 1, 0, 0, 0, 164, 162, 1, 0, 0, 0, 164, 165, 1, 0, 0, 0, 165, 44, 1, 0, 0, 0, 166, 164, 1, 0, 0, 0, 167, 168, 5, 48, 0, 0, 168, 46, 1, 0, 0, 0, 169, 174, 5, 34, 0, 0, 170, 173, 3, 49, 24, 0, 171, 173, 3, 57, 28, 0, 172, 170, 1, 0, 0, 0, 172, 171, 1, 0, 0, 0, 173, 176, 1, 0, 0, 0, 174, 172, 1, 0, 0, 0, 174, 175, 1, 0, 0, 0, 175, 177, 1, 0, 0, 0, 176, 174, 1, 0, 0, 0, 177, 188, 5, 34, 0, 0, 178, 183, 5, 39, 0, 0, 179, 182, 3, 49, 24, 0, 180, 182, 3, 55, 27, 0, 181, 179, 1, 0, 0, 0, 181, 180, 1, 0, 0, 0, 182, 185, 1, 0, 0, 0, 183, 181, 1, 0, 0, 0, 183, 184, 1, 0, 0, 0, 184, 186, 1, 0, 0, 0, 185, 183, 1, 0, 0, 0, 186, 188, 5, 39, 0, 0, 187, 169, 1, 0, 0, 0, 187, 178, 1, 0, 0, 0, 188, 48, 1, 0, 0, 0, 189, 192, 5, 92, 0, 0, 190, 193, 7, 3, 0, 0, 191, 193, 3, 51, 25, 0, 192, 190, 1, 0, 0, 0, 192, 191, 1, 0, 0, 0, 193, 50, 1, 0, 0, 0, 194, 195, 5, 117, 0, 0, 195, 196, 3, 53, 26, 0, 196, 197, 3, 53, 26, 0, 197, 198, 3, 53, 26, 0, 198, 199, 3, 53, 26, 0, 199, 52, 1, 0, 0, 0, 200, 201, 7, 4, 0, 0, 201, 54, 1, 0, 0, 0, 202, 203, 8, 5, 0, 0, 203, 56, 1, 0, 0, 0, 204, 205, 8, 6, 0, 0, 205, 58, 1, 0, 0, 0, 206, 208, 7, 7, 0, 0, 207, 206, 1, 0, 0, 0, 208, 209, 1, 0, 0, 0, 209, 207, 1, 0, 0, 0, 209, 210, 1, 0, 0, 0, 210, 211, 1, 0, 0, 0, 211, 212, 6, 29, 0, 0, 212, 60, 1, 0, 0, 0, 12, 0, 84, 151, 153, 164, 172, 174, 181, 183, 187, 192, 209, 1, 6, 0, 0] \ No newline at end of file diff --git a/pkg/sdk/netmap/parser/QueryLexer.tokens b/pkg/sdk/netmap/parser/QueryLexer.tokens new file mode 100644 index 000000000..6376ea255 --- /dev/null +++ b/pkg/sdk/netmap/parser/QueryLexer.tokens @@ -0,0 +1,41 @@ +NOT_OP=1 +AND_OP=2 +OR_OP=3 +SIMPLE_OP=4 +UNIQUE=5 +REP=6 +IN=7 +AS=8 +CBF=9 +SELECT=10 +FROM=11 +FILTER=12 +WILDCARD=13 +CLAUSE_SAME=14 +CLAUSE_DISTINCT=15 +L_PAREN=16 +R_PAREN=17 +AT=18 +IDENT=19 +NUMBER1=20 +ZERO=21 +STRING=22 +WS=23 +'NOT'=1 +'AND'=2 +'OR'=3 +'UNIQUE'=5 +'REP'=6 +'IN'=7 +'AS'=8 +'CBF'=9 +'SELECT'=10 +'FROM'=11 +'FILTER'=12 +'*'=13 +'SAME'=14 +'DISTINCT'=15 +'('=16 +')'=17 +'@'=18 +'0'=21 diff --git a/pkg/sdk/netmap/parser/generate.go b/pkg/sdk/netmap/parser/generate.go new file mode 100644 index 000000000..66a855bd3 --- /dev/null +++ b/pkg/sdk/netmap/parser/generate.go @@ -0,0 +1,4 @@ +package parser + +// ANTLR can be downloaded from https://www.antlr.org/download/antlr-4.13.0-complete.jar +//go:generate java -Xmx500M -cp "./antlr-4.13.0-complete.jar:$CLASSPATH" org.antlr.v4.Tool -Dlanguage=Go -no-listener -visitor QueryLexer.g4 Query.g4 diff --git a/pkg/sdk/netmap/parser/query_base_visitor.go b/pkg/sdk/netmap/parser/query_base_visitor.go new file mode 100644 index 000000000..981106f51 --- /dev/null +++ b/pkg/sdk/netmap/parser/query_base_visitor.go @@ -0,0 +1,69 @@ +// Code generated from Query.g4 by ANTLR 4.13.0. DO NOT EDIT. + +package parser // Query + +import "github.com/antlr4-go/antlr/v4" + +type BaseQueryVisitor struct { + *antlr.BaseParseTreeVisitor +} + +func (v *BaseQueryVisitor) VisitPolicy(ctx *PolicyContext) interface{} { + return v.VisitChildren(ctx) +} + +func (v *BaseQueryVisitor) VisitSelectFilterExpr(ctx *SelectFilterExprContext) interface{} { + return v.VisitChildren(ctx) +} + +func (v *BaseQueryVisitor) VisitRepStmt(ctx *RepStmtContext) interface{} { + return v.VisitChildren(ctx) +} + +func (v *BaseQueryVisitor) VisitCbfStmt(ctx *CbfStmtContext) interface{} { + return v.VisitChildren(ctx) +} + +func (v *BaseQueryVisitor) VisitSelectStmt(ctx *SelectStmtContext) interface{} { + return v.VisitChildren(ctx) +} + +func (v *BaseQueryVisitor) VisitClause(ctx *ClauseContext) interface{} { + return v.VisitChildren(ctx) +} + +func (v *BaseQueryVisitor) VisitFilterExpr(ctx *FilterExprContext) interface{} { + return v.VisitChildren(ctx) +} + +func (v *BaseQueryVisitor) VisitFilterStmt(ctx *FilterStmtContext) interface{} { + return v.VisitChildren(ctx) +} + +func (v *BaseQueryVisitor) VisitExpr(ctx *ExprContext) interface{} { + return v.VisitChildren(ctx) +} + +func (v *BaseQueryVisitor) VisitFilterKey(ctx *FilterKeyContext) interface{} { + return v.VisitChildren(ctx) +} + +func (v *BaseQueryVisitor) VisitFilterValue(ctx *FilterValueContext) interface{} { + return v.VisitChildren(ctx) +} + +func (v *BaseQueryVisitor) VisitNumber(ctx *NumberContext) interface{} { + return v.VisitChildren(ctx) +} + +func (v *BaseQueryVisitor) VisitKeyword(ctx *KeywordContext) interface{} { + return v.VisitChildren(ctx) +} + +func (v *BaseQueryVisitor) VisitIdent(ctx *IdentContext) interface{} { + return v.VisitChildren(ctx) +} + +func (v *BaseQueryVisitor) VisitIdentWC(ctx *IdentWCContext) interface{} { + return v.VisitChildren(ctx) +} diff --git a/pkg/sdk/netmap/parser/query_lexer.go b/pkg/sdk/netmap/parser/query_lexer.go new file mode 100644 index 000000000..c1ae141a6 --- /dev/null +++ b/pkg/sdk/netmap/parser/query_lexer.go @@ -0,0 +1,222 @@ +// Code generated from QueryLexer.g4 by ANTLR 4.13.0. DO NOT EDIT. + +package parser + +import ( + "fmt" + "github.com/antlr4-go/antlr/v4" + "sync" + "unicode" +) + +// Suppress unused import error +var _ = fmt.Printf +var _ = sync.Once{} +var _ = unicode.IsLetter + +type QueryLexer struct { + *antlr.BaseLexer + channelNames []string + modeNames []string + // TODO: EOF string +} + +var QueryLexerLexerStaticData struct { + once sync.Once + serializedATN []int32 + ChannelNames []string + ModeNames []string + LiteralNames []string + SymbolicNames []string + RuleNames []string + PredictionContextCache *antlr.PredictionContextCache + atn *antlr.ATN + decisionToDFA []*antlr.DFA +} + +func querylexerLexerInit() { + staticData := &QueryLexerLexerStaticData + staticData.ChannelNames = []string{ + "DEFAULT_TOKEN_CHANNEL", "HIDDEN", + } + staticData.ModeNames = []string{ + "DEFAULT_MODE", + } + staticData.LiteralNames = []string{ + "", "'NOT'", "'AND'", "'OR'", "", "'UNIQUE'", "'REP'", "'IN'", "'AS'", + "'CBF'", "'SELECT'", "'FROM'", "'FILTER'", "'*'", "'SAME'", "'DISTINCT'", + "'('", "')'", "'@'", "", "", "'0'", + } + staticData.SymbolicNames = []string{ + "", "NOT_OP", "AND_OP", "OR_OP", "SIMPLE_OP", "UNIQUE", "REP", "IN", + "AS", "CBF", "SELECT", "FROM", "FILTER", "WILDCARD", "CLAUSE_SAME", + "CLAUSE_DISTINCT", "L_PAREN", "R_PAREN", "AT", "IDENT", "NUMBER1", "ZERO", + "STRING", "WS", + } + staticData.RuleNames = []string{ + "NOT_OP", "AND_OP", "OR_OP", "SIMPLE_OP", "UNIQUE", "REP", "IN", "AS", + "CBF", "SELECT", "FROM", "FILTER", "WILDCARD", "CLAUSE_SAME", "CLAUSE_DISTINCT", + "L_PAREN", "R_PAREN", "AT", "IDENT", "Digit", "Nondigit", "NUMBER1", + "ZERO", "STRING", "ESC", "UNICODE", "HEX", "SAFECODEPOINTSINGLE", "SAFECODEPOINTDOUBLE", + "WS", + } + staticData.PredictionContextCache = antlr.NewPredictionContextCache() + staticData.serializedATN = []int32{ + 4, 0, 23, 213, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, + 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, + 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, + 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, + 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, + 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 3, 1, 3, 1, 3, 1, + 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 3, 3, 85, 8, 3, 1, 4, + 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 1, 5, 1, 6, 1, 6, + 1, 6, 1, 7, 1, 7, 1, 7, 1, 8, 1, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 9, + 1, 9, 1, 9, 1, 9, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 11, 1, 11, 1, 11, + 1, 11, 1, 11, 1, 11, 1, 11, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 1, 13, 1, + 13, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 15, + 1, 15, 1, 16, 1, 16, 1, 17, 1, 17, 1, 18, 1, 18, 1, 18, 5, 18, 152, 8, + 18, 10, 18, 12, 18, 155, 9, 18, 1, 19, 1, 19, 1, 20, 1, 20, 1, 21, 1, 21, + 5, 21, 163, 8, 21, 10, 21, 12, 21, 166, 9, 21, 1, 22, 1, 22, 1, 23, 1, + 23, 1, 23, 5, 23, 173, 8, 23, 10, 23, 12, 23, 176, 9, 23, 1, 23, 1, 23, + 1, 23, 1, 23, 5, 23, 182, 8, 23, 10, 23, 12, 23, 185, 9, 23, 1, 23, 3, + 23, 188, 8, 23, 1, 24, 1, 24, 1, 24, 3, 24, 193, 8, 24, 1, 25, 1, 25, 1, + 25, 1, 25, 1, 25, 1, 25, 1, 26, 1, 26, 1, 27, 1, 27, 1, 28, 1, 28, 1, 29, + 4, 29, 208, 8, 29, 11, 29, 12, 29, 209, 1, 29, 1, 29, 0, 0, 30, 1, 1, 3, + 2, 5, 3, 7, 4, 9, 5, 11, 6, 13, 7, 15, 8, 17, 9, 19, 10, 21, 11, 23, 12, + 25, 13, 27, 14, 29, 15, 31, 16, 33, 17, 35, 18, 37, 19, 39, 0, 41, 0, 43, + 20, 45, 21, 47, 22, 49, 0, 51, 0, 53, 0, 55, 0, 57, 0, 59, 23, 1, 0, 8, + 1, 0, 48, 57, 3, 0, 65, 90, 95, 95, 97, 122, 1, 0, 49, 57, 9, 0, 34, 34, + 39, 39, 47, 47, 92, 92, 98, 98, 102, 102, 110, 110, 114, 114, 116, 116, + 3, 0, 48, 57, 65, 70, 97, 102, 3, 0, 0, 31, 39, 39, 92, 92, 3, 0, 0, 31, + 34, 34, 92, 92, 3, 0, 9, 10, 13, 13, 32, 32, 220, 0, 1, 1, 0, 0, 0, 0, + 3, 1, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 9, 1, 0, 0, 0, 0, + 11, 1, 0, 0, 0, 0, 13, 1, 0, 0, 0, 0, 15, 1, 0, 0, 0, 0, 17, 1, 0, 0, 0, + 0, 19, 1, 0, 0, 0, 0, 21, 1, 0, 0, 0, 0, 23, 1, 0, 0, 0, 0, 25, 1, 0, 0, + 0, 0, 27, 1, 0, 0, 0, 0, 29, 1, 0, 0, 0, 0, 31, 1, 0, 0, 0, 0, 33, 1, 0, + 0, 0, 0, 35, 1, 0, 0, 0, 0, 37, 1, 0, 0, 0, 0, 43, 1, 0, 0, 0, 0, 45, 1, + 0, 0, 0, 0, 47, 1, 0, 0, 0, 0, 59, 1, 0, 0, 0, 1, 61, 1, 0, 0, 0, 3, 65, + 1, 0, 0, 0, 5, 69, 1, 0, 0, 0, 7, 84, 1, 0, 0, 0, 9, 86, 1, 0, 0, 0, 11, + 93, 1, 0, 0, 0, 13, 97, 1, 0, 0, 0, 15, 100, 1, 0, 0, 0, 17, 103, 1, 0, + 0, 0, 19, 107, 1, 0, 0, 0, 21, 114, 1, 0, 0, 0, 23, 119, 1, 0, 0, 0, 25, + 126, 1, 0, 0, 0, 27, 128, 1, 0, 0, 0, 29, 133, 1, 0, 0, 0, 31, 142, 1, + 0, 0, 0, 33, 144, 1, 0, 0, 0, 35, 146, 1, 0, 0, 0, 37, 148, 1, 0, 0, 0, + 39, 156, 1, 0, 0, 0, 41, 158, 1, 0, 0, 0, 43, 160, 1, 0, 0, 0, 45, 167, + 1, 0, 0, 0, 47, 187, 1, 0, 0, 0, 49, 189, 1, 0, 0, 0, 51, 194, 1, 0, 0, + 0, 53, 200, 1, 0, 0, 0, 55, 202, 1, 0, 0, 0, 57, 204, 1, 0, 0, 0, 59, 207, + 1, 0, 0, 0, 61, 62, 5, 78, 0, 0, 62, 63, 5, 79, 0, 0, 63, 64, 5, 84, 0, + 0, 64, 2, 1, 0, 0, 0, 65, 66, 5, 65, 0, 0, 66, 67, 5, 78, 0, 0, 67, 68, + 5, 68, 0, 0, 68, 4, 1, 0, 0, 0, 69, 70, 5, 79, 0, 0, 70, 71, 5, 82, 0, + 0, 71, 6, 1, 0, 0, 0, 72, 73, 5, 69, 0, 0, 73, 85, 5, 81, 0, 0, 74, 75, + 5, 78, 0, 0, 75, 85, 5, 69, 0, 0, 76, 77, 5, 71, 0, 0, 77, 85, 5, 69, 0, + 0, 78, 79, 5, 71, 0, 0, 79, 85, 5, 84, 0, 0, 80, 81, 5, 76, 0, 0, 81, 85, + 5, 84, 0, 0, 82, 83, 5, 76, 0, 0, 83, 85, 5, 69, 0, 0, 84, 72, 1, 0, 0, + 0, 84, 74, 1, 0, 0, 0, 84, 76, 1, 0, 0, 0, 84, 78, 1, 0, 0, 0, 84, 80, + 1, 0, 0, 0, 84, 82, 1, 0, 0, 0, 85, 8, 1, 0, 0, 0, 86, 87, 5, 85, 0, 0, + 87, 88, 5, 78, 0, 0, 88, 89, 5, 73, 0, 0, 89, 90, 5, 81, 0, 0, 90, 91, + 5, 85, 0, 0, 91, 92, 5, 69, 0, 0, 92, 10, 1, 0, 0, 0, 93, 94, 5, 82, 0, + 0, 94, 95, 5, 69, 0, 0, 95, 96, 5, 80, 0, 0, 96, 12, 1, 0, 0, 0, 97, 98, + 5, 73, 0, 0, 98, 99, 5, 78, 0, 0, 99, 14, 1, 0, 0, 0, 100, 101, 5, 65, + 0, 0, 101, 102, 5, 83, 0, 0, 102, 16, 1, 0, 0, 0, 103, 104, 5, 67, 0, 0, + 104, 105, 5, 66, 0, 0, 105, 106, 5, 70, 0, 0, 106, 18, 1, 0, 0, 0, 107, + 108, 5, 83, 0, 0, 108, 109, 5, 69, 0, 0, 109, 110, 5, 76, 0, 0, 110, 111, + 5, 69, 0, 0, 111, 112, 5, 67, 0, 0, 112, 113, 5, 84, 0, 0, 113, 20, 1, + 0, 0, 0, 114, 115, 5, 70, 0, 0, 115, 116, 5, 82, 0, 0, 116, 117, 5, 79, + 0, 0, 117, 118, 5, 77, 0, 0, 118, 22, 1, 0, 0, 0, 119, 120, 5, 70, 0, 0, + 120, 121, 5, 73, 0, 0, 121, 122, 5, 76, 0, 0, 122, 123, 5, 84, 0, 0, 123, + 124, 5, 69, 0, 0, 124, 125, 5, 82, 0, 0, 125, 24, 1, 0, 0, 0, 126, 127, + 5, 42, 0, 0, 127, 26, 1, 0, 0, 0, 128, 129, 5, 83, 0, 0, 129, 130, 5, 65, + 0, 0, 130, 131, 5, 77, 0, 0, 131, 132, 5, 69, 0, 0, 132, 28, 1, 0, 0, 0, + 133, 134, 5, 68, 0, 0, 134, 135, 5, 73, 0, 0, 135, 136, 5, 83, 0, 0, 136, + 137, 5, 84, 0, 0, 137, 138, 5, 73, 0, 0, 138, 139, 5, 78, 0, 0, 139, 140, + 5, 67, 0, 0, 140, 141, 5, 84, 0, 0, 141, 30, 1, 0, 0, 0, 142, 143, 5, 40, + 0, 0, 143, 32, 1, 0, 0, 0, 144, 145, 5, 41, 0, 0, 145, 34, 1, 0, 0, 0, + 146, 147, 5, 64, 0, 0, 147, 36, 1, 0, 0, 0, 148, 153, 3, 41, 20, 0, 149, + 152, 3, 39, 19, 0, 150, 152, 3, 41, 20, 0, 151, 149, 1, 0, 0, 0, 151, 150, + 1, 0, 0, 0, 152, 155, 1, 0, 0, 0, 153, 151, 1, 0, 0, 0, 153, 154, 1, 0, + 0, 0, 154, 38, 1, 0, 0, 0, 155, 153, 1, 0, 0, 0, 156, 157, 7, 0, 0, 0, + 157, 40, 1, 0, 0, 0, 158, 159, 7, 1, 0, 0, 159, 42, 1, 0, 0, 0, 160, 164, + 7, 2, 0, 0, 161, 163, 3, 39, 19, 0, 162, 161, 1, 0, 0, 0, 163, 166, 1, + 0, 0, 0, 164, 162, 1, 0, 0, 0, 164, 165, 1, 0, 0, 0, 165, 44, 1, 0, 0, + 0, 166, 164, 1, 0, 0, 0, 167, 168, 5, 48, 0, 0, 168, 46, 1, 0, 0, 0, 169, + 174, 5, 34, 0, 0, 170, 173, 3, 49, 24, 0, 171, 173, 3, 57, 28, 0, 172, + 170, 1, 0, 0, 0, 172, 171, 1, 0, 0, 0, 173, 176, 1, 0, 0, 0, 174, 172, + 1, 0, 0, 0, 174, 175, 1, 0, 0, 0, 175, 177, 1, 0, 0, 0, 176, 174, 1, 0, + 0, 0, 177, 188, 5, 34, 0, 0, 178, 183, 5, 39, 0, 0, 179, 182, 3, 49, 24, + 0, 180, 182, 3, 55, 27, 0, 181, 179, 1, 0, 0, 0, 181, 180, 1, 0, 0, 0, + 182, 185, 1, 0, 0, 0, 183, 181, 1, 0, 0, 0, 183, 184, 1, 0, 0, 0, 184, + 186, 1, 0, 0, 0, 185, 183, 1, 0, 0, 0, 186, 188, 5, 39, 0, 0, 187, 169, + 1, 0, 0, 0, 187, 178, 1, 0, 0, 0, 188, 48, 1, 0, 0, 0, 189, 192, 5, 92, + 0, 0, 190, 193, 7, 3, 0, 0, 191, 193, 3, 51, 25, 0, 192, 190, 1, 0, 0, + 0, 192, 191, 1, 0, 0, 0, 193, 50, 1, 0, 0, 0, 194, 195, 5, 117, 0, 0, 195, + 196, 3, 53, 26, 0, 196, 197, 3, 53, 26, 0, 197, 198, 3, 53, 26, 0, 198, + 199, 3, 53, 26, 0, 199, 52, 1, 0, 0, 0, 200, 201, 7, 4, 0, 0, 201, 54, + 1, 0, 0, 0, 202, 203, 8, 5, 0, 0, 203, 56, 1, 0, 0, 0, 204, 205, 8, 6, + 0, 0, 205, 58, 1, 0, 0, 0, 206, 208, 7, 7, 0, 0, 207, 206, 1, 0, 0, 0, + 208, 209, 1, 0, 0, 0, 209, 207, 1, 0, 0, 0, 209, 210, 1, 0, 0, 0, 210, + 211, 1, 0, 0, 0, 211, 212, 6, 29, 0, 0, 212, 60, 1, 0, 0, 0, 12, 0, 84, + 151, 153, 164, 172, 174, 181, 183, 187, 192, 209, 1, 6, 0, 0, + } + deserializer := antlr.NewATNDeserializer(nil) + staticData.atn = deserializer.Deserialize(staticData.serializedATN) + atn := staticData.atn + staticData.decisionToDFA = make([]*antlr.DFA, len(atn.DecisionToState)) + decisionToDFA := staticData.decisionToDFA + for index, state := range atn.DecisionToState { + decisionToDFA[index] = antlr.NewDFA(state, index) + } +} + +// QueryLexerInit initializes any static state used to implement QueryLexer. By default the +// static state used to implement the lexer is lazily initialized during the first call to +// NewQueryLexer(). You can call this function if you wish to initialize the static state ahead +// of time. +func QueryLexerInit() { + staticData := &QueryLexerLexerStaticData + staticData.once.Do(querylexerLexerInit) +} + +// NewQueryLexer produces a new lexer instance for the optional input antlr.CharStream. +func NewQueryLexer(input antlr.CharStream) *QueryLexer { + QueryLexerInit() + l := new(QueryLexer) + l.BaseLexer = antlr.NewBaseLexer(input) + staticData := &QueryLexerLexerStaticData + l.Interpreter = antlr.NewLexerATNSimulator(l, staticData.atn, staticData.decisionToDFA, staticData.PredictionContextCache) + l.channelNames = staticData.ChannelNames + l.modeNames = staticData.ModeNames + l.RuleNames = staticData.RuleNames + l.LiteralNames = staticData.LiteralNames + l.SymbolicNames = staticData.SymbolicNames + l.GrammarFileName = "QueryLexer.g4" + // TODO: l.EOF = antlr.TokenEOF + + return l +} + +// QueryLexer tokens. +const ( + QueryLexerNOT_OP = 1 + QueryLexerAND_OP = 2 + QueryLexerOR_OP = 3 + QueryLexerSIMPLE_OP = 4 + QueryLexerUNIQUE = 5 + QueryLexerREP = 6 + QueryLexerIN = 7 + QueryLexerAS = 8 + QueryLexerCBF = 9 + QueryLexerSELECT = 10 + QueryLexerFROM = 11 + QueryLexerFILTER = 12 + QueryLexerWILDCARD = 13 + QueryLexerCLAUSE_SAME = 14 + QueryLexerCLAUSE_DISTINCT = 15 + QueryLexerL_PAREN = 16 + QueryLexerR_PAREN = 17 + QueryLexerAT = 18 + QueryLexerIDENT = 19 + QueryLexerNUMBER1 = 20 + QueryLexerZERO = 21 + QueryLexerSTRING = 22 + QueryLexerWS = 23 +) diff --git a/pkg/sdk/netmap/parser/query_parser.go b/pkg/sdk/netmap/parser/query_parser.go new file mode 100644 index 000000000..db19c9378 --- /dev/null +++ b/pkg/sdk/netmap/parser/query_parser.go @@ -0,0 +1,3095 @@ +// Code generated from Query.g4 by ANTLR 4.13.0. DO NOT EDIT. + +package parser // Query + +import ( + "fmt" + "strconv" + "sync" + + "github.com/antlr4-go/antlr/v4" +) + +// Suppress unused import errors +var _ = fmt.Printf +var _ = strconv.Itoa +var _ = sync.Once{} + +type Query struct { + *antlr.BaseParser +} + +var QueryParserStaticData struct { + once sync.Once + serializedATN []int32 + LiteralNames []string + SymbolicNames []string + RuleNames []string + PredictionContextCache *antlr.PredictionContextCache + atn *antlr.ATN + decisionToDFA []*antlr.DFA +} + +func queryParserInit() { + staticData := &QueryParserStaticData + staticData.LiteralNames = []string{ + "", "'NOT'", "'AND'", "'OR'", "", "'UNIQUE'", "'REP'", "'IN'", "'AS'", + "'CBF'", "'SELECT'", "'FROM'", "'FILTER'", "'*'", "'SAME'", "'DISTINCT'", + "'('", "')'", "'@'", "", "", "'0'", + } + staticData.SymbolicNames = []string{ + "", "NOT_OP", "AND_OP", "OR_OP", "SIMPLE_OP", "UNIQUE", "REP", "IN", + "AS", "CBF", "SELECT", "FROM", "FILTER", "WILDCARD", "CLAUSE_SAME", + "CLAUSE_DISTINCT", "L_PAREN", "R_PAREN", "AT", "IDENT", "NUMBER1", "ZERO", + "STRING", "WS", + } + staticData.RuleNames = []string{ + "policy", "selectFilterExpr", "repStmt", "cbfStmt", "selectStmt", "clause", + "filterExpr", "filterStmt", "expr", "filterKey", "filterValue", "number", + "keyword", "ident", "identWC", + } + staticData.PredictionContextCache = antlr.NewPredictionContextCache() + staticData.serializedATN = []int32{ + 4, 1, 23, 154, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, + 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, + 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 1, 0, 3, 0, + 32, 8, 0, 1, 0, 4, 0, 35, 8, 0, 11, 0, 12, 0, 36, 1, 0, 3, 0, 40, 8, 0, + 1, 0, 5, 0, 43, 8, 0, 10, 0, 12, 0, 46, 9, 0, 1, 0, 5, 0, 49, 8, 0, 10, + 0, 12, 0, 52, 9, 0, 1, 0, 1, 0, 1, 1, 3, 1, 57, 8, 1, 1, 1, 3, 1, 60, 8, + 1, 1, 1, 5, 1, 63, 8, 1, 10, 1, 12, 1, 66, 9, 1, 1, 1, 1, 1, 1, 2, 1, 2, + 1, 2, 1, 2, 3, 2, 74, 8, 2, 1, 3, 1, 3, 1, 3, 1, 4, 1, 4, 1, 4, 1, 4, 3, + 4, 83, 8, 4, 1, 4, 3, 4, 86, 8, 4, 1, 4, 1, 4, 1, 4, 1, 4, 3, 4, 92, 8, + 4, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, + 6, 1, 6, 3, 6, 107, 8, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 5, 6, 115, + 8, 6, 10, 6, 12, 6, 118, 9, 6, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 8, 1, 8, + 1, 8, 1, 8, 1, 8, 1, 8, 3, 8, 131, 8, 8, 1, 9, 1, 9, 3, 9, 135, 8, 9, 1, + 10, 1, 10, 1, 10, 3, 10, 140, 8, 10, 1, 11, 1, 11, 1, 12, 1, 12, 1, 13, + 1, 13, 3, 13, 148, 8, 13, 1, 14, 1, 14, 3, 14, 152, 8, 14, 1, 14, 0, 1, + 12, 15, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 0, 3, 1, + 0, 14, 15, 1, 0, 20, 21, 2, 0, 6, 8, 10, 12, 160, 0, 31, 1, 0, 0, 0, 2, + 56, 1, 0, 0, 0, 4, 69, 1, 0, 0, 0, 6, 75, 1, 0, 0, 0, 8, 78, 1, 0, 0, 0, + 10, 93, 1, 0, 0, 0, 12, 106, 1, 0, 0, 0, 14, 119, 1, 0, 0, 0, 16, 130, + 1, 0, 0, 0, 18, 134, 1, 0, 0, 0, 20, 139, 1, 0, 0, 0, 22, 141, 1, 0, 0, + 0, 24, 143, 1, 0, 0, 0, 26, 147, 1, 0, 0, 0, 28, 151, 1, 0, 0, 0, 30, 32, + 5, 5, 0, 0, 31, 30, 1, 0, 0, 0, 31, 32, 1, 0, 0, 0, 32, 34, 1, 0, 0, 0, + 33, 35, 3, 4, 2, 0, 34, 33, 1, 0, 0, 0, 35, 36, 1, 0, 0, 0, 36, 34, 1, + 0, 0, 0, 36, 37, 1, 0, 0, 0, 37, 39, 1, 0, 0, 0, 38, 40, 3, 6, 3, 0, 39, + 38, 1, 0, 0, 0, 39, 40, 1, 0, 0, 0, 40, 44, 1, 0, 0, 0, 41, 43, 3, 8, 4, + 0, 42, 41, 1, 0, 0, 0, 43, 46, 1, 0, 0, 0, 44, 42, 1, 0, 0, 0, 44, 45, + 1, 0, 0, 0, 45, 50, 1, 0, 0, 0, 46, 44, 1, 0, 0, 0, 47, 49, 3, 14, 7, 0, + 48, 47, 1, 0, 0, 0, 49, 52, 1, 0, 0, 0, 50, 48, 1, 0, 0, 0, 50, 51, 1, + 0, 0, 0, 51, 53, 1, 0, 0, 0, 52, 50, 1, 0, 0, 0, 53, 54, 5, 0, 0, 1, 54, + 1, 1, 0, 0, 0, 55, 57, 3, 6, 3, 0, 56, 55, 1, 0, 0, 0, 56, 57, 1, 0, 0, + 0, 57, 59, 1, 0, 0, 0, 58, 60, 3, 8, 4, 0, 59, 58, 1, 0, 0, 0, 59, 60, + 1, 0, 0, 0, 60, 64, 1, 0, 0, 0, 61, 63, 3, 14, 7, 0, 62, 61, 1, 0, 0, 0, + 63, 66, 1, 0, 0, 0, 64, 62, 1, 0, 0, 0, 64, 65, 1, 0, 0, 0, 65, 67, 1, + 0, 0, 0, 66, 64, 1, 0, 0, 0, 67, 68, 5, 0, 0, 1, 68, 3, 1, 0, 0, 0, 69, + 70, 5, 6, 0, 0, 70, 73, 5, 20, 0, 0, 71, 72, 5, 7, 0, 0, 72, 74, 3, 26, + 13, 0, 73, 71, 1, 0, 0, 0, 73, 74, 1, 0, 0, 0, 74, 5, 1, 0, 0, 0, 75, 76, + 5, 9, 0, 0, 76, 77, 5, 20, 0, 0, 77, 7, 1, 0, 0, 0, 78, 79, 5, 10, 0, 0, + 79, 85, 5, 20, 0, 0, 80, 82, 5, 7, 0, 0, 81, 83, 3, 10, 5, 0, 82, 81, 1, + 0, 0, 0, 82, 83, 1, 0, 0, 0, 83, 84, 1, 0, 0, 0, 84, 86, 3, 26, 13, 0, + 85, 80, 1, 0, 0, 0, 85, 86, 1, 0, 0, 0, 86, 87, 1, 0, 0, 0, 87, 88, 5, + 11, 0, 0, 88, 91, 3, 28, 14, 0, 89, 90, 5, 8, 0, 0, 90, 92, 3, 26, 13, + 0, 91, 89, 1, 0, 0, 0, 91, 92, 1, 0, 0, 0, 92, 9, 1, 0, 0, 0, 93, 94, 7, + 0, 0, 0, 94, 11, 1, 0, 0, 0, 95, 96, 6, 6, -1, 0, 96, 97, 5, 1, 0, 0, 97, + 98, 5, 16, 0, 0, 98, 99, 3, 12, 6, 0, 99, 100, 5, 17, 0, 0, 100, 107, 1, + 0, 0, 0, 101, 102, 5, 16, 0, 0, 102, 103, 3, 12, 6, 0, 103, 104, 5, 17, + 0, 0, 104, 107, 1, 0, 0, 0, 105, 107, 3, 16, 8, 0, 106, 95, 1, 0, 0, 0, + 106, 101, 1, 0, 0, 0, 106, 105, 1, 0, 0, 0, 107, 116, 1, 0, 0, 0, 108, + 109, 10, 4, 0, 0, 109, 110, 5, 2, 0, 0, 110, 115, 3, 12, 6, 5, 111, 112, + 10, 3, 0, 0, 112, 113, 5, 3, 0, 0, 113, 115, 3, 12, 6, 4, 114, 108, 1, + 0, 0, 0, 114, 111, 1, 0, 0, 0, 115, 118, 1, 0, 0, 0, 116, 114, 1, 0, 0, + 0, 116, 117, 1, 0, 0, 0, 117, 13, 1, 0, 0, 0, 118, 116, 1, 0, 0, 0, 119, + 120, 5, 12, 0, 0, 120, 121, 3, 12, 6, 0, 121, 122, 5, 8, 0, 0, 122, 123, + 3, 26, 13, 0, 123, 15, 1, 0, 0, 0, 124, 125, 5, 18, 0, 0, 125, 131, 3, + 26, 13, 0, 126, 127, 3, 18, 9, 0, 127, 128, 5, 4, 0, 0, 128, 129, 3, 20, + 10, 0, 129, 131, 1, 0, 0, 0, 130, 124, 1, 0, 0, 0, 130, 126, 1, 0, 0, 0, + 131, 17, 1, 0, 0, 0, 132, 135, 3, 26, 13, 0, 133, 135, 5, 22, 0, 0, 134, + 132, 1, 0, 0, 0, 134, 133, 1, 0, 0, 0, 135, 19, 1, 0, 0, 0, 136, 140, 3, + 26, 13, 0, 137, 140, 3, 22, 11, 0, 138, 140, 5, 22, 0, 0, 139, 136, 1, + 0, 0, 0, 139, 137, 1, 0, 0, 0, 139, 138, 1, 0, 0, 0, 140, 21, 1, 0, 0, + 0, 141, 142, 7, 1, 0, 0, 142, 23, 1, 0, 0, 0, 143, 144, 7, 2, 0, 0, 144, + 25, 1, 0, 0, 0, 145, 148, 3, 24, 12, 0, 146, 148, 5, 19, 0, 0, 147, 145, + 1, 0, 0, 0, 147, 146, 1, 0, 0, 0, 148, 27, 1, 0, 0, 0, 149, 152, 3, 26, + 13, 0, 150, 152, 5, 13, 0, 0, 151, 149, 1, 0, 0, 0, 151, 150, 1, 0, 0, + 0, 152, 29, 1, 0, 0, 0, 20, 31, 36, 39, 44, 50, 56, 59, 64, 73, 82, 85, + 91, 106, 114, 116, 130, 134, 139, 147, 151, + } + deserializer := antlr.NewATNDeserializer(nil) + staticData.atn = deserializer.Deserialize(staticData.serializedATN) + atn := staticData.atn + staticData.decisionToDFA = make([]*antlr.DFA, len(atn.DecisionToState)) + decisionToDFA := staticData.decisionToDFA + for index, state := range atn.DecisionToState { + decisionToDFA[index] = antlr.NewDFA(state, index) + } +} + +// QueryInit initializes any static state used to implement Query. By default the +// static state used to implement the parser is lazily initialized during the first call to +// NewQuery(). You can call this function if you wish to initialize the static state ahead +// of time. +func QueryInit() { + staticData := &QueryParserStaticData + staticData.once.Do(queryParserInit) +} + +// NewQuery produces a new parser instance for the optional input antlr.TokenStream. +func NewQuery(input antlr.TokenStream) *Query { + QueryInit() + this := new(Query) + this.BaseParser = antlr.NewBaseParser(input) + staticData := &QueryParserStaticData + this.Interpreter = antlr.NewParserATNSimulator(this, staticData.atn, staticData.decisionToDFA, staticData.PredictionContextCache) + this.RuleNames = staticData.RuleNames + this.LiteralNames = staticData.LiteralNames + this.SymbolicNames = staticData.SymbolicNames + this.GrammarFileName = "Query.g4" + + return this +} + +// Query tokens. +const ( + QueryEOF = antlr.TokenEOF + QueryNOT_OP = 1 + QueryAND_OP = 2 + QueryOR_OP = 3 + QuerySIMPLE_OP = 4 + QueryUNIQUE = 5 + QueryREP = 6 + QueryIN = 7 + QueryAS = 8 + QueryCBF = 9 + QuerySELECT = 10 + QueryFROM = 11 + QueryFILTER = 12 + QueryWILDCARD = 13 + QueryCLAUSE_SAME = 14 + QueryCLAUSE_DISTINCT = 15 + QueryL_PAREN = 16 + QueryR_PAREN = 17 + QueryAT = 18 + QueryIDENT = 19 + QueryNUMBER1 = 20 + QueryZERO = 21 + QuerySTRING = 22 + QueryWS = 23 +) + +// Query rules. +const ( + QueryRULE_policy = 0 + QueryRULE_selectFilterExpr = 1 + QueryRULE_repStmt = 2 + QueryRULE_cbfStmt = 3 + QueryRULE_selectStmt = 4 + QueryRULE_clause = 5 + QueryRULE_filterExpr = 6 + QueryRULE_filterStmt = 7 + QueryRULE_expr = 8 + QueryRULE_filterKey = 9 + QueryRULE_filterValue = 10 + QueryRULE_number = 11 + QueryRULE_keyword = 12 + QueryRULE_ident = 13 + QueryRULE_identWC = 14 +) + +// IPolicyContext is an interface to support dynamic dispatch. +type IPolicyContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // Getter signatures + EOF() antlr.TerminalNode + UNIQUE() antlr.TerminalNode + AllRepStmt() []IRepStmtContext + RepStmt(i int) IRepStmtContext + CbfStmt() ICbfStmtContext + AllSelectStmt() []ISelectStmtContext + SelectStmt(i int) ISelectStmtContext + AllFilterStmt() []IFilterStmtContext + FilterStmt(i int) IFilterStmtContext + + // IsPolicyContext differentiates from other interfaces. + IsPolicyContext() +} + +type PolicyContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyPolicyContext() *PolicyContext { + var p = new(PolicyContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryRULE_policy + return p +} + +func InitEmptyPolicyContext(p *PolicyContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryRULE_policy +} + +func (*PolicyContext) IsPolicyContext() {} + +func NewPolicyContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *PolicyContext { + var p = new(PolicyContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = QueryRULE_policy + + return p +} + +func (s *PolicyContext) GetParser() antlr.Parser { return s.parser } + +func (s *PolicyContext) EOF() antlr.TerminalNode { + return s.GetToken(QueryEOF, 0) +} + +func (s *PolicyContext) UNIQUE() antlr.TerminalNode { + return s.GetToken(QueryUNIQUE, 0) +} + +func (s *PolicyContext) AllRepStmt() []IRepStmtContext { + children := s.GetChildren() + len := 0 + for _, ctx := range children { + if _, ok := ctx.(IRepStmtContext); ok { + len++ + } + } + + tst := make([]IRepStmtContext, len) + i := 0 + for _, ctx := range children { + if t, ok := ctx.(IRepStmtContext); ok { + tst[i] = t.(IRepStmtContext) + i++ + } + } + + return tst +} + +func (s *PolicyContext) RepStmt(i int) IRepStmtContext { + var t antlr.RuleContext + j := 0 + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IRepStmtContext); ok { + if j == i { + t = ctx.(antlr.RuleContext) + break + } + j++ + } + } + + if t == nil { + return nil + } + + return t.(IRepStmtContext) +} + +func (s *PolicyContext) CbfStmt() ICbfStmtContext { + var t antlr.RuleContext + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(ICbfStmtContext); ok { + t = ctx.(antlr.RuleContext) + break + } + } + + if t == nil { + return nil + } + + return t.(ICbfStmtContext) +} + +func (s *PolicyContext) AllSelectStmt() []ISelectStmtContext { + children := s.GetChildren() + len := 0 + for _, ctx := range children { + if _, ok := ctx.(ISelectStmtContext); ok { + len++ + } + } + + tst := make([]ISelectStmtContext, len) + i := 0 + for _, ctx := range children { + if t, ok := ctx.(ISelectStmtContext); ok { + tst[i] = t.(ISelectStmtContext) + i++ + } + } + + return tst +} + +func (s *PolicyContext) SelectStmt(i int) ISelectStmtContext { + var t antlr.RuleContext + j := 0 + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(ISelectStmtContext); ok { + if j == i { + t = ctx.(antlr.RuleContext) + break + } + j++ + } + } + + if t == nil { + return nil + } + + return t.(ISelectStmtContext) +} + +func (s *PolicyContext) AllFilterStmt() []IFilterStmtContext { + children := s.GetChildren() + len := 0 + for _, ctx := range children { + if _, ok := ctx.(IFilterStmtContext); ok { + len++ + } + } + + tst := make([]IFilterStmtContext, len) + i := 0 + for _, ctx := range children { + if t, ok := ctx.(IFilterStmtContext); ok { + tst[i] = t.(IFilterStmtContext) + i++ + } + } + + return tst +} + +func (s *PolicyContext) FilterStmt(i int) IFilterStmtContext { + var t antlr.RuleContext + j := 0 + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IFilterStmtContext); ok { + if j == i { + t = ctx.(antlr.RuleContext) + break + } + j++ + } + } + + if t == nil { + return nil + } + + return t.(IFilterStmtContext) +} + +func (s *PolicyContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *PolicyContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *PolicyContext) Accept(visitor antlr.ParseTreeVisitor) interface{} { + switch t := visitor.(type) { + case QueryVisitor: + return t.VisitPolicy(s) + + default: + return t.VisitChildren(s) + } +} + +func (p *Query) Policy() (localctx IPolicyContext) { + localctx = NewPolicyContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 0, QueryRULE_policy) + var _la int + + p.EnterOuterAlt(localctx, 1) + p.SetState(31) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + _la = p.GetTokenStream().LA(1) + + if _la == QueryUNIQUE { + { + p.SetState(30) + p.Match(QueryUNIQUE) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + + } + p.SetState(34) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + _la = p.GetTokenStream().LA(1) + + for ok := true; ok; ok = _la == QueryREP { + { + p.SetState(33) + p.RepStmt() + } + + p.SetState(36) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + _la = p.GetTokenStream().LA(1) + } + p.SetState(39) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + _la = p.GetTokenStream().LA(1) + + if _la == QueryCBF { + { + p.SetState(38) + p.CbfStmt() + } + + } + p.SetState(44) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + _la = p.GetTokenStream().LA(1) + + for _la == QuerySELECT { + { + p.SetState(41) + p.SelectStmt() + } + + p.SetState(46) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + _la = p.GetTokenStream().LA(1) + } + p.SetState(50) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + _la = p.GetTokenStream().LA(1) + + for _la == QueryFILTER { + { + p.SetState(47) + p.FilterStmt() + } + + p.SetState(52) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + _la = p.GetTokenStream().LA(1) + } + { + p.SetState(53) + p.Match(QueryEOF) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + +errorExit: + if p.HasError() { + v := p.GetError() + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + p.SetError(nil) + } + p.ExitRule() + return localctx + goto errorExit // Trick to prevent compiler error if the label is not used +} + +// ISelectFilterExprContext is an interface to support dynamic dispatch. +type ISelectFilterExprContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // Getter signatures + EOF() antlr.TerminalNode + CbfStmt() ICbfStmtContext + SelectStmt() ISelectStmtContext + AllFilterStmt() []IFilterStmtContext + FilterStmt(i int) IFilterStmtContext + + // IsSelectFilterExprContext differentiates from other interfaces. + IsSelectFilterExprContext() +} + +type SelectFilterExprContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptySelectFilterExprContext() *SelectFilterExprContext { + var p = new(SelectFilterExprContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryRULE_selectFilterExpr + return p +} + +func InitEmptySelectFilterExprContext(p *SelectFilterExprContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryRULE_selectFilterExpr +} + +func (*SelectFilterExprContext) IsSelectFilterExprContext() {} + +func NewSelectFilterExprContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *SelectFilterExprContext { + var p = new(SelectFilterExprContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = QueryRULE_selectFilterExpr + + return p +} + +func (s *SelectFilterExprContext) GetParser() antlr.Parser { return s.parser } + +func (s *SelectFilterExprContext) EOF() antlr.TerminalNode { + return s.GetToken(QueryEOF, 0) +} + +func (s *SelectFilterExprContext) CbfStmt() ICbfStmtContext { + var t antlr.RuleContext + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(ICbfStmtContext); ok { + t = ctx.(antlr.RuleContext) + break + } + } + + if t == nil { + return nil + } + + return t.(ICbfStmtContext) +} + +func (s *SelectFilterExprContext) SelectStmt() ISelectStmtContext { + var t antlr.RuleContext + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(ISelectStmtContext); ok { + t = ctx.(antlr.RuleContext) + break + } + } + + if t == nil { + return nil + } + + return t.(ISelectStmtContext) +} + +func (s *SelectFilterExprContext) AllFilterStmt() []IFilterStmtContext { + children := s.GetChildren() + len := 0 + for _, ctx := range children { + if _, ok := ctx.(IFilterStmtContext); ok { + len++ + } + } + + tst := make([]IFilterStmtContext, len) + i := 0 + for _, ctx := range children { + if t, ok := ctx.(IFilterStmtContext); ok { + tst[i] = t.(IFilterStmtContext) + i++ + } + } + + return tst +} + +func (s *SelectFilterExprContext) FilterStmt(i int) IFilterStmtContext { + var t antlr.RuleContext + j := 0 + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IFilterStmtContext); ok { + if j == i { + t = ctx.(antlr.RuleContext) + break + } + j++ + } + } + + if t == nil { + return nil + } + + return t.(IFilterStmtContext) +} + +func (s *SelectFilterExprContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *SelectFilterExprContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *SelectFilterExprContext) Accept(visitor antlr.ParseTreeVisitor) interface{} { + switch t := visitor.(type) { + case QueryVisitor: + return t.VisitSelectFilterExpr(s) + + default: + return t.VisitChildren(s) + } +} + +func (p *Query) SelectFilterExpr() (localctx ISelectFilterExprContext) { + localctx = NewSelectFilterExprContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 2, QueryRULE_selectFilterExpr) + var _la int + + p.EnterOuterAlt(localctx, 1) + p.SetState(56) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + _la = p.GetTokenStream().LA(1) + + if _la == QueryCBF { + { + p.SetState(55) + p.CbfStmt() + } + + } + p.SetState(59) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + _la = p.GetTokenStream().LA(1) + + if _la == QuerySELECT { + { + p.SetState(58) + p.SelectStmt() + } + + } + p.SetState(64) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + _la = p.GetTokenStream().LA(1) + + for _la == QueryFILTER { + { + p.SetState(61) + p.FilterStmt() + } + + p.SetState(66) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + _la = p.GetTokenStream().LA(1) + } + { + p.SetState(67) + p.Match(QueryEOF) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + +errorExit: + if p.HasError() { + v := p.GetError() + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + p.SetError(nil) + } + p.ExitRule() + return localctx + goto errorExit // Trick to prevent compiler error if the label is not used +} + +// IRepStmtContext is an interface to support dynamic dispatch. +type IRepStmtContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // GetCount returns the Count token. + GetCount() antlr.Token + + // SetCount sets the Count token. + SetCount(antlr.Token) + + // GetSelector returns the Selector rule contexts. + GetSelector() IIdentContext + + // SetSelector sets the Selector rule contexts. + SetSelector(IIdentContext) + + // Getter signatures + REP() antlr.TerminalNode + NUMBER1() antlr.TerminalNode + IN() antlr.TerminalNode + Ident() IIdentContext + + // IsRepStmtContext differentiates from other interfaces. + IsRepStmtContext() +} + +type RepStmtContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser + Count antlr.Token + Selector IIdentContext +} + +func NewEmptyRepStmtContext() *RepStmtContext { + var p = new(RepStmtContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryRULE_repStmt + return p +} + +func InitEmptyRepStmtContext(p *RepStmtContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryRULE_repStmt +} + +func (*RepStmtContext) IsRepStmtContext() {} + +func NewRepStmtContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *RepStmtContext { + var p = new(RepStmtContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = QueryRULE_repStmt + + return p +} + +func (s *RepStmtContext) GetParser() antlr.Parser { return s.parser } + +func (s *RepStmtContext) GetCount() antlr.Token { return s.Count } + +func (s *RepStmtContext) SetCount(v antlr.Token) { s.Count = v } + +func (s *RepStmtContext) GetSelector() IIdentContext { return s.Selector } + +func (s *RepStmtContext) SetSelector(v IIdentContext) { s.Selector = v } + +func (s *RepStmtContext) REP() antlr.TerminalNode { + return s.GetToken(QueryREP, 0) +} + +func (s *RepStmtContext) NUMBER1() antlr.TerminalNode { + return s.GetToken(QueryNUMBER1, 0) +} + +func (s *RepStmtContext) IN() antlr.TerminalNode { + return s.GetToken(QueryIN, 0) +} + +func (s *RepStmtContext) Ident() IIdentContext { + var t antlr.RuleContext + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IIdentContext); ok { + t = ctx.(antlr.RuleContext) + break + } + } + + if t == nil { + return nil + } + + return t.(IIdentContext) +} + +func (s *RepStmtContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *RepStmtContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *RepStmtContext) Accept(visitor antlr.ParseTreeVisitor) interface{} { + switch t := visitor.(type) { + case QueryVisitor: + return t.VisitRepStmt(s) + + default: + return t.VisitChildren(s) + } +} + +func (p *Query) RepStmt() (localctx IRepStmtContext) { + localctx = NewRepStmtContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 4, QueryRULE_repStmt) + var _la int + + p.EnterOuterAlt(localctx, 1) + { + p.SetState(69) + p.Match(QueryREP) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + { + p.SetState(70) + + var _m = p.Match(QueryNUMBER1) + + localctx.(*RepStmtContext).Count = _m + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + p.SetState(73) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + _la = p.GetTokenStream().LA(1) + + if _la == QueryIN { + { + p.SetState(71) + p.Match(QueryIN) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + { + p.SetState(72) + + var _x = p.Ident() + + localctx.(*RepStmtContext).Selector = _x + } + + } + +errorExit: + if p.HasError() { + v := p.GetError() + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + p.SetError(nil) + } + p.ExitRule() + return localctx + goto errorExit // Trick to prevent compiler error if the label is not used +} + +// ICbfStmtContext is an interface to support dynamic dispatch. +type ICbfStmtContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // GetBackupFactor returns the BackupFactor token. + GetBackupFactor() antlr.Token + + // SetBackupFactor sets the BackupFactor token. + SetBackupFactor(antlr.Token) + + // Getter signatures + CBF() antlr.TerminalNode + NUMBER1() antlr.TerminalNode + + // IsCbfStmtContext differentiates from other interfaces. + IsCbfStmtContext() +} + +type CbfStmtContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser + BackupFactor antlr.Token +} + +func NewEmptyCbfStmtContext() *CbfStmtContext { + var p = new(CbfStmtContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryRULE_cbfStmt + return p +} + +func InitEmptyCbfStmtContext(p *CbfStmtContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryRULE_cbfStmt +} + +func (*CbfStmtContext) IsCbfStmtContext() {} + +func NewCbfStmtContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *CbfStmtContext { + var p = new(CbfStmtContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = QueryRULE_cbfStmt + + return p +} + +func (s *CbfStmtContext) GetParser() antlr.Parser { return s.parser } + +func (s *CbfStmtContext) GetBackupFactor() antlr.Token { return s.BackupFactor } + +func (s *CbfStmtContext) SetBackupFactor(v antlr.Token) { s.BackupFactor = v } + +func (s *CbfStmtContext) CBF() antlr.TerminalNode { + return s.GetToken(QueryCBF, 0) +} + +func (s *CbfStmtContext) NUMBER1() antlr.TerminalNode { + return s.GetToken(QueryNUMBER1, 0) +} + +func (s *CbfStmtContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *CbfStmtContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *CbfStmtContext) Accept(visitor antlr.ParseTreeVisitor) interface{} { + switch t := visitor.(type) { + case QueryVisitor: + return t.VisitCbfStmt(s) + + default: + return t.VisitChildren(s) + } +} + +func (p *Query) CbfStmt() (localctx ICbfStmtContext) { + localctx = NewCbfStmtContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 6, QueryRULE_cbfStmt) + p.EnterOuterAlt(localctx, 1) + { + p.SetState(75) + p.Match(QueryCBF) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + { + p.SetState(76) + + var _m = p.Match(QueryNUMBER1) + + localctx.(*CbfStmtContext).BackupFactor = _m + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + +errorExit: + if p.HasError() { + v := p.GetError() + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + p.SetError(nil) + } + p.ExitRule() + return localctx + goto errorExit // Trick to prevent compiler error if the label is not used +} + +// ISelectStmtContext is an interface to support dynamic dispatch. +type ISelectStmtContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // GetCount returns the Count token. + GetCount() antlr.Token + + // SetCount sets the Count token. + SetCount(antlr.Token) + + // GetBucket returns the Bucket rule contexts. + GetBucket() IIdentContext + + // GetFilter returns the Filter rule contexts. + GetFilter() IIdentWCContext + + // GetName returns the Name rule contexts. + GetName() IIdentContext + + // SetBucket sets the Bucket rule contexts. + SetBucket(IIdentContext) + + // SetFilter sets the Filter rule contexts. + SetFilter(IIdentWCContext) + + // SetName sets the Name rule contexts. + SetName(IIdentContext) + + // Getter signatures + SELECT() antlr.TerminalNode + FROM() antlr.TerminalNode + NUMBER1() antlr.TerminalNode + IdentWC() IIdentWCContext + IN() antlr.TerminalNode + AS() antlr.TerminalNode + AllIdent() []IIdentContext + Ident(i int) IIdentContext + Clause() IClauseContext + + // IsSelectStmtContext differentiates from other interfaces. + IsSelectStmtContext() +} + +type SelectStmtContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser + Count antlr.Token + Bucket IIdentContext + Filter IIdentWCContext + Name IIdentContext +} + +func NewEmptySelectStmtContext() *SelectStmtContext { + var p = new(SelectStmtContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryRULE_selectStmt + return p +} + +func InitEmptySelectStmtContext(p *SelectStmtContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryRULE_selectStmt +} + +func (*SelectStmtContext) IsSelectStmtContext() {} + +func NewSelectStmtContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *SelectStmtContext { + var p = new(SelectStmtContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = QueryRULE_selectStmt + + return p +} + +func (s *SelectStmtContext) GetParser() antlr.Parser { return s.parser } + +func (s *SelectStmtContext) GetCount() antlr.Token { return s.Count } + +func (s *SelectStmtContext) SetCount(v antlr.Token) { s.Count = v } + +func (s *SelectStmtContext) GetBucket() IIdentContext { return s.Bucket } + +func (s *SelectStmtContext) GetFilter() IIdentWCContext { return s.Filter } + +func (s *SelectStmtContext) GetName() IIdentContext { return s.Name } + +func (s *SelectStmtContext) SetBucket(v IIdentContext) { s.Bucket = v } + +func (s *SelectStmtContext) SetFilter(v IIdentWCContext) { s.Filter = v } + +func (s *SelectStmtContext) SetName(v IIdentContext) { s.Name = v } + +func (s *SelectStmtContext) SELECT() antlr.TerminalNode { + return s.GetToken(QuerySELECT, 0) +} + +func (s *SelectStmtContext) FROM() antlr.TerminalNode { + return s.GetToken(QueryFROM, 0) +} + +func (s *SelectStmtContext) NUMBER1() antlr.TerminalNode { + return s.GetToken(QueryNUMBER1, 0) +} + +func (s *SelectStmtContext) IdentWC() IIdentWCContext { + var t antlr.RuleContext + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IIdentWCContext); ok { + t = ctx.(antlr.RuleContext) + break + } + } + + if t == nil { + return nil + } + + return t.(IIdentWCContext) +} + +func (s *SelectStmtContext) IN() antlr.TerminalNode { + return s.GetToken(QueryIN, 0) +} + +func (s *SelectStmtContext) AS() antlr.TerminalNode { + return s.GetToken(QueryAS, 0) +} + +func (s *SelectStmtContext) AllIdent() []IIdentContext { + children := s.GetChildren() + len := 0 + for _, ctx := range children { + if _, ok := ctx.(IIdentContext); ok { + len++ + } + } + + tst := make([]IIdentContext, len) + i := 0 + for _, ctx := range children { + if t, ok := ctx.(IIdentContext); ok { + tst[i] = t.(IIdentContext) + i++ + } + } + + return tst +} + +func (s *SelectStmtContext) Ident(i int) IIdentContext { + var t antlr.RuleContext + j := 0 + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IIdentContext); ok { + if j == i { + t = ctx.(antlr.RuleContext) + break + } + j++ + } + } + + if t == nil { + return nil + } + + return t.(IIdentContext) +} + +func (s *SelectStmtContext) Clause() IClauseContext { + var t antlr.RuleContext + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IClauseContext); ok { + t = ctx.(antlr.RuleContext) + break + } + } + + if t == nil { + return nil + } + + return t.(IClauseContext) +} + +func (s *SelectStmtContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *SelectStmtContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *SelectStmtContext) Accept(visitor antlr.ParseTreeVisitor) interface{} { + switch t := visitor.(type) { + case QueryVisitor: + return t.VisitSelectStmt(s) + + default: + return t.VisitChildren(s) + } +} + +func (p *Query) SelectStmt() (localctx ISelectStmtContext) { + localctx = NewSelectStmtContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 8, QueryRULE_selectStmt) + var _la int + + p.EnterOuterAlt(localctx, 1) + { + p.SetState(78) + p.Match(QuerySELECT) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + { + p.SetState(79) + + var _m = p.Match(QueryNUMBER1) + + localctx.(*SelectStmtContext).Count = _m + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + p.SetState(85) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + _la = p.GetTokenStream().LA(1) + + if _la == QueryIN { + { + p.SetState(80) + p.Match(QueryIN) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + p.SetState(82) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + _la = p.GetTokenStream().LA(1) + + if _la == QueryCLAUSE_SAME || _la == QueryCLAUSE_DISTINCT { + { + p.SetState(81) + p.Clause() + } + + } + { + p.SetState(84) + + var _x = p.Ident() + + localctx.(*SelectStmtContext).Bucket = _x + } + + } + { + p.SetState(87) + p.Match(QueryFROM) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + { + p.SetState(88) + + var _x = p.IdentWC() + + localctx.(*SelectStmtContext).Filter = _x + } + p.SetState(91) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + _la = p.GetTokenStream().LA(1) + + if _la == QueryAS { + { + p.SetState(89) + p.Match(QueryAS) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + { + p.SetState(90) + + var _x = p.Ident() + + localctx.(*SelectStmtContext).Name = _x + } + + } + +errorExit: + if p.HasError() { + v := p.GetError() + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + p.SetError(nil) + } + p.ExitRule() + return localctx + goto errorExit // Trick to prevent compiler error if the label is not used +} + +// IClauseContext is an interface to support dynamic dispatch. +type IClauseContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // Getter signatures + CLAUSE_SAME() antlr.TerminalNode + CLAUSE_DISTINCT() antlr.TerminalNode + + // IsClauseContext differentiates from other interfaces. + IsClauseContext() +} + +type ClauseContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyClauseContext() *ClauseContext { + var p = new(ClauseContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryRULE_clause + return p +} + +func InitEmptyClauseContext(p *ClauseContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryRULE_clause +} + +func (*ClauseContext) IsClauseContext() {} + +func NewClauseContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *ClauseContext { + var p = new(ClauseContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = QueryRULE_clause + + return p +} + +func (s *ClauseContext) GetParser() antlr.Parser { return s.parser } + +func (s *ClauseContext) CLAUSE_SAME() antlr.TerminalNode { + return s.GetToken(QueryCLAUSE_SAME, 0) +} + +func (s *ClauseContext) CLAUSE_DISTINCT() antlr.TerminalNode { + return s.GetToken(QueryCLAUSE_DISTINCT, 0) +} + +func (s *ClauseContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *ClauseContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *ClauseContext) Accept(visitor antlr.ParseTreeVisitor) interface{} { + switch t := visitor.(type) { + case QueryVisitor: + return t.VisitClause(s) + + default: + return t.VisitChildren(s) + } +} + +func (p *Query) Clause() (localctx IClauseContext) { + localctx = NewClauseContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 10, QueryRULE_clause) + var _la int + + p.EnterOuterAlt(localctx, 1) + { + p.SetState(93) + _la = p.GetTokenStream().LA(1) + + if !(_la == QueryCLAUSE_SAME || _la == QueryCLAUSE_DISTINCT) { + p.GetErrorHandler().RecoverInline(p) + } else { + p.GetErrorHandler().ReportMatch(p) + p.Consume() + } + } + +errorExit: + if p.HasError() { + v := p.GetError() + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + p.SetError(nil) + } + p.ExitRule() + return localctx + goto errorExit // Trick to prevent compiler error if the label is not used +} + +// IFilterExprContext is an interface to support dynamic dispatch. +type IFilterExprContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // GetOp returns the Op token. + GetOp() antlr.Token + + // SetOp sets the Op token. + SetOp(antlr.Token) + + // GetF1 returns the F1 rule contexts. + GetF1() IFilterExprContext + + // GetInner returns the Inner rule contexts. + GetInner() IFilterExprContext + + // GetF2 returns the F2 rule contexts. + GetF2() IFilterExprContext + + // SetF1 sets the F1 rule contexts. + SetF1(IFilterExprContext) + + // SetInner sets the Inner rule contexts. + SetInner(IFilterExprContext) + + // SetF2 sets the F2 rule contexts. + SetF2(IFilterExprContext) + + // Getter signatures + L_PAREN() antlr.TerminalNode + R_PAREN() antlr.TerminalNode + NOT_OP() antlr.TerminalNode + AllFilterExpr() []IFilterExprContext + FilterExpr(i int) IFilterExprContext + Expr() IExprContext + AND_OP() antlr.TerminalNode + OR_OP() antlr.TerminalNode + + // IsFilterExprContext differentiates from other interfaces. + IsFilterExprContext() +} + +type FilterExprContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser + F1 IFilterExprContext + Op antlr.Token + Inner IFilterExprContext + F2 IFilterExprContext +} + +func NewEmptyFilterExprContext() *FilterExprContext { + var p = new(FilterExprContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryRULE_filterExpr + return p +} + +func InitEmptyFilterExprContext(p *FilterExprContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryRULE_filterExpr +} + +func (*FilterExprContext) IsFilterExprContext() {} + +func NewFilterExprContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *FilterExprContext { + var p = new(FilterExprContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = QueryRULE_filterExpr + + return p +} + +func (s *FilterExprContext) GetParser() antlr.Parser { return s.parser } + +func (s *FilterExprContext) GetOp() antlr.Token { return s.Op } + +func (s *FilterExprContext) SetOp(v antlr.Token) { s.Op = v } + +func (s *FilterExprContext) GetF1() IFilterExprContext { return s.F1 } + +func (s *FilterExprContext) GetInner() IFilterExprContext { return s.Inner } + +func (s *FilterExprContext) GetF2() IFilterExprContext { return s.F2 } + +func (s *FilterExprContext) SetF1(v IFilterExprContext) { s.F1 = v } + +func (s *FilterExprContext) SetInner(v IFilterExprContext) { s.Inner = v } + +func (s *FilterExprContext) SetF2(v IFilterExprContext) { s.F2 = v } + +func (s *FilterExprContext) L_PAREN() antlr.TerminalNode { + return s.GetToken(QueryL_PAREN, 0) +} + +func (s *FilterExprContext) R_PAREN() antlr.TerminalNode { + return s.GetToken(QueryR_PAREN, 0) +} + +func (s *FilterExprContext) NOT_OP() antlr.TerminalNode { + return s.GetToken(QueryNOT_OP, 0) +} + +func (s *FilterExprContext) AllFilterExpr() []IFilterExprContext { + children := s.GetChildren() + len := 0 + for _, ctx := range children { + if _, ok := ctx.(IFilterExprContext); ok { + len++ + } + } + + tst := make([]IFilterExprContext, len) + i := 0 + for _, ctx := range children { + if t, ok := ctx.(IFilterExprContext); ok { + tst[i] = t.(IFilterExprContext) + i++ + } + } + + return tst +} + +func (s *FilterExprContext) FilterExpr(i int) IFilterExprContext { + var t antlr.RuleContext + j := 0 + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IFilterExprContext); ok { + if j == i { + t = ctx.(antlr.RuleContext) + break + } + j++ + } + } + + if t == nil { + return nil + } + + return t.(IFilterExprContext) +} + +func (s *FilterExprContext) Expr() IExprContext { + var t antlr.RuleContext + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IExprContext); ok { + t = ctx.(antlr.RuleContext) + break + } + } + + if t == nil { + return nil + } + + return t.(IExprContext) +} + +func (s *FilterExprContext) AND_OP() antlr.TerminalNode { + return s.GetToken(QueryAND_OP, 0) +} + +func (s *FilterExprContext) OR_OP() antlr.TerminalNode { + return s.GetToken(QueryOR_OP, 0) +} + +func (s *FilterExprContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *FilterExprContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *FilterExprContext) Accept(visitor antlr.ParseTreeVisitor) interface{} { + switch t := visitor.(type) { + case QueryVisitor: + return t.VisitFilterExpr(s) + + default: + return t.VisitChildren(s) + } +} + +func (p *Query) FilterExpr() (localctx IFilterExprContext) { + return p.filterExpr(0) +} + +func (p *Query) filterExpr(_p int) (localctx IFilterExprContext) { + var _parentctx antlr.ParserRuleContext = p.GetParserRuleContext() + + _parentState := p.GetState() + localctx = NewFilterExprContext(p, p.GetParserRuleContext(), _parentState) + var _prevctx IFilterExprContext = localctx + var _ antlr.ParserRuleContext = _prevctx // TODO: To prevent unused variable warning. + _startState := 12 + p.EnterRecursionRule(localctx, 12, QueryRULE_filterExpr, _p) + var _alt int + + p.EnterOuterAlt(localctx, 1) + p.SetState(106) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + + switch p.GetTokenStream().LA(1) { + case QueryNOT_OP: + { + p.SetState(96) + + var _m = p.Match(QueryNOT_OP) + + localctx.(*FilterExprContext).Op = _m + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + { + p.SetState(97) + p.Match(QueryL_PAREN) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + { + p.SetState(98) + + var _x = p.filterExpr(0) + + localctx.(*FilterExprContext).F1 = _x + } + { + p.SetState(99) + p.Match(QueryR_PAREN) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + + case QueryL_PAREN: + { + p.SetState(101) + p.Match(QueryL_PAREN) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + { + p.SetState(102) + + var _x = p.filterExpr(0) + + localctx.(*FilterExprContext).Inner = _x + } + { + p.SetState(103) + p.Match(QueryR_PAREN) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + + case QueryREP, QueryIN, QueryAS, QuerySELECT, QueryFROM, QueryFILTER, QueryAT, QueryIDENT, QuerySTRING: + { + p.SetState(105) + p.Expr() + } + + default: + p.SetError(antlr.NewNoViableAltException(p, nil, nil, nil, nil, nil)) + goto errorExit + } + p.GetParserRuleContext().SetStop(p.GetTokenStream().LT(-1)) + p.SetState(116) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + _alt = p.GetInterpreter().AdaptivePredict(p.BaseParser, p.GetTokenStream(), 14, p.GetParserRuleContext()) + if p.HasError() { + goto errorExit + } + for _alt != 2 && _alt != antlr.ATNInvalidAltNumber { + if _alt == 1 { + if p.GetParseListeners() != nil { + p.TriggerExitRuleEvent() + } + _prevctx = localctx + p.SetState(114) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + + switch p.GetInterpreter().AdaptivePredict(p.BaseParser, p.GetTokenStream(), 13, p.GetParserRuleContext()) { + case 1: + localctx = NewFilterExprContext(p, _parentctx, _parentState) + localctx.(*FilterExprContext).F1 = _prevctx + p.PushNewRecursionContext(localctx, _startState, QueryRULE_filterExpr) + p.SetState(108) + + if !(p.Precpred(p.GetParserRuleContext(), 4)) { + p.SetError(antlr.NewFailedPredicateException(p, "p.Precpred(p.GetParserRuleContext(), 4)", "")) + goto errorExit + } + { + p.SetState(109) + + var _m = p.Match(QueryAND_OP) + + localctx.(*FilterExprContext).Op = _m + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + { + p.SetState(110) + + var _x = p.filterExpr(5) + + localctx.(*FilterExprContext).F2 = _x + } + + case 2: + localctx = NewFilterExprContext(p, _parentctx, _parentState) + localctx.(*FilterExprContext).F1 = _prevctx + p.PushNewRecursionContext(localctx, _startState, QueryRULE_filterExpr) + p.SetState(111) + + if !(p.Precpred(p.GetParserRuleContext(), 3)) { + p.SetError(antlr.NewFailedPredicateException(p, "p.Precpred(p.GetParserRuleContext(), 3)", "")) + goto errorExit + } + { + p.SetState(112) + + var _m = p.Match(QueryOR_OP) + + localctx.(*FilterExprContext).Op = _m + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + { + p.SetState(113) + + var _x = p.filterExpr(4) + + localctx.(*FilterExprContext).F2 = _x + } + + case antlr.ATNInvalidAltNumber: + goto errorExit + } + + } + p.SetState(118) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + _alt = p.GetInterpreter().AdaptivePredict(p.BaseParser, p.GetTokenStream(), 14, p.GetParserRuleContext()) + if p.HasError() { + goto errorExit + } + } + +errorExit: + if p.HasError() { + v := p.GetError() + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + p.SetError(nil) + } + p.UnrollRecursionContexts(_parentctx) + return localctx + goto errorExit // Trick to prevent compiler error if the label is not used +} + +// IFilterStmtContext is an interface to support dynamic dispatch. +type IFilterStmtContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // GetExpr returns the Expr rule contexts. + GetExpr() IFilterExprContext + + // GetName returns the Name rule contexts. + GetName() IIdentContext + + // SetExpr sets the Expr rule contexts. + SetExpr(IFilterExprContext) + + // SetName sets the Name rule contexts. + SetName(IIdentContext) + + // Getter signatures + FILTER() antlr.TerminalNode + AS() antlr.TerminalNode + FilterExpr() IFilterExprContext + Ident() IIdentContext + + // IsFilterStmtContext differentiates from other interfaces. + IsFilterStmtContext() +} + +type FilterStmtContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser + Expr IFilterExprContext + Name IIdentContext +} + +func NewEmptyFilterStmtContext() *FilterStmtContext { + var p = new(FilterStmtContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryRULE_filterStmt + return p +} + +func InitEmptyFilterStmtContext(p *FilterStmtContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryRULE_filterStmt +} + +func (*FilterStmtContext) IsFilterStmtContext() {} + +func NewFilterStmtContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *FilterStmtContext { + var p = new(FilterStmtContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = QueryRULE_filterStmt + + return p +} + +func (s *FilterStmtContext) GetParser() antlr.Parser { return s.parser } + +func (s *FilterStmtContext) GetExpr() IFilterExprContext { return s.Expr } + +func (s *FilterStmtContext) GetName() IIdentContext { return s.Name } + +func (s *FilterStmtContext) SetExpr(v IFilterExprContext) { s.Expr = v } + +func (s *FilterStmtContext) SetName(v IIdentContext) { s.Name = v } + +func (s *FilterStmtContext) FILTER() antlr.TerminalNode { + return s.GetToken(QueryFILTER, 0) +} + +func (s *FilterStmtContext) AS() antlr.TerminalNode { + return s.GetToken(QueryAS, 0) +} + +func (s *FilterStmtContext) FilterExpr() IFilterExprContext { + var t antlr.RuleContext + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IFilterExprContext); ok { + t = ctx.(antlr.RuleContext) + break + } + } + + if t == nil { + return nil + } + + return t.(IFilterExprContext) +} + +func (s *FilterStmtContext) Ident() IIdentContext { + var t antlr.RuleContext + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IIdentContext); ok { + t = ctx.(antlr.RuleContext) + break + } + } + + if t == nil { + return nil + } + + return t.(IIdentContext) +} + +func (s *FilterStmtContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *FilterStmtContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *FilterStmtContext) Accept(visitor antlr.ParseTreeVisitor) interface{} { + switch t := visitor.(type) { + case QueryVisitor: + return t.VisitFilterStmt(s) + + default: + return t.VisitChildren(s) + } +} + +func (p *Query) FilterStmt() (localctx IFilterStmtContext) { + localctx = NewFilterStmtContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 14, QueryRULE_filterStmt) + p.EnterOuterAlt(localctx, 1) + { + p.SetState(119) + p.Match(QueryFILTER) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + { + p.SetState(120) + + var _x = p.filterExpr(0) + + localctx.(*FilterStmtContext).Expr = _x + } + { + p.SetState(121) + p.Match(QueryAS) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + { + p.SetState(122) + + var _x = p.Ident() + + localctx.(*FilterStmtContext).Name = _x + } + +errorExit: + if p.HasError() { + v := p.GetError() + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + p.SetError(nil) + } + p.ExitRule() + return localctx + goto errorExit // Trick to prevent compiler error if the label is not used +} + +// IExprContext is an interface to support dynamic dispatch. +type IExprContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // GetFilter returns the Filter rule contexts. + GetFilter() IIdentContext + + // GetKey returns the Key rule contexts. + GetKey() IFilterKeyContext + + // GetValue returns the Value rule contexts. + GetValue() IFilterValueContext + + // SetFilter sets the Filter rule contexts. + SetFilter(IIdentContext) + + // SetKey sets the Key rule contexts. + SetKey(IFilterKeyContext) + + // SetValue sets the Value rule contexts. + SetValue(IFilterValueContext) + + // Getter signatures + AT() antlr.TerminalNode + Ident() IIdentContext + SIMPLE_OP() antlr.TerminalNode + FilterKey() IFilterKeyContext + FilterValue() IFilterValueContext + + // IsExprContext differentiates from other interfaces. + IsExprContext() +} + +type ExprContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser + Filter IIdentContext + Key IFilterKeyContext + Value IFilterValueContext +} + +func NewEmptyExprContext() *ExprContext { + var p = new(ExprContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryRULE_expr + return p +} + +func InitEmptyExprContext(p *ExprContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryRULE_expr +} + +func (*ExprContext) IsExprContext() {} + +func NewExprContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *ExprContext { + var p = new(ExprContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = QueryRULE_expr + + return p +} + +func (s *ExprContext) GetParser() antlr.Parser { return s.parser } + +func (s *ExprContext) GetFilter() IIdentContext { return s.Filter } + +func (s *ExprContext) GetKey() IFilterKeyContext { return s.Key } + +func (s *ExprContext) GetValue() IFilterValueContext { return s.Value } + +func (s *ExprContext) SetFilter(v IIdentContext) { s.Filter = v } + +func (s *ExprContext) SetKey(v IFilterKeyContext) { s.Key = v } + +func (s *ExprContext) SetValue(v IFilterValueContext) { s.Value = v } + +func (s *ExprContext) AT() antlr.TerminalNode { + return s.GetToken(QueryAT, 0) +} + +func (s *ExprContext) Ident() IIdentContext { + var t antlr.RuleContext + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IIdentContext); ok { + t = ctx.(antlr.RuleContext) + break + } + } + + if t == nil { + return nil + } + + return t.(IIdentContext) +} + +func (s *ExprContext) SIMPLE_OP() antlr.TerminalNode { + return s.GetToken(QuerySIMPLE_OP, 0) +} + +func (s *ExprContext) FilterKey() IFilterKeyContext { + var t antlr.RuleContext + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IFilterKeyContext); ok { + t = ctx.(antlr.RuleContext) + break + } + } + + if t == nil { + return nil + } + + return t.(IFilterKeyContext) +} + +func (s *ExprContext) FilterValue() IFilterValueContext { + var t antlr.RuleContext + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IFilterValueContext); ok { + t = ctx.(antlr.RuleContext) + break + } + } + + if t == nil { + return nil + } + + return t.(IFilterValueContext) +} + +func (s *ExprContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *ExprContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *ExprContext) Accept(visitor antlr.ParseTreeVisitor) interface{} { + switch t := visitor.(type) { + case QueryVisitor: + return t.VisitExpr(s) + + default: + return t.VisitChildren(s) + } +} + +func (p *Query) Expr() (localctx IExprContext) { + localctx = NewExprContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 16, QueryRULE_expr) + p.SetState(130) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + + switch p.GetTokenStream().LA(1) { + case QueryAT: + p.EnterOuterAlt(localctx, 1) + { + p.SetState(124) + p.Match(QueryAT) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + { + p.SetState(125) + + var _x = p.Ident() + + localctx.(*ExprContext).Filter = _x + } + + case QueryREP, QueryIN, QueryAS, QuerySELECT, QueryFROM, QueryFILTER, QueryIDENT, QuerySTRING: + p.EnterOuterAlt(localctx, 2) + { + p.SetState(126) + + var _x = p.FilterKey() + + localctx.(*ExprContext).Key = _x + } + { + p.SetState(127) + p.Match(QuerySIMPLE_OP) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + { + p.SetState(128) + + var _x = p.FilterValue() + + localctx.(*ExprContext).Value = _x + } + + default: + p.SetError(antlr.NewNoViableAltException(p, nil, nil, nil, nil, nil)) + goto errorExit + } + +errorExit: + if p.HasError() { + v := p.GetError() + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + p.SetError(nil) + } + p.ExitRule() + return localctx + goto errorExit // Trick to prevent compiler error if the label is not used +} + +// IFilterKeyContext is an interface to support dynamic dispatch. +type IFilterKeyContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // Getter signatures + Ident() IIdentContext + STRING() antlr.TerminalNode + + // IsFilterKeyContext differentiates from other interfaces. + IsFilterKeyContext() +} + +type FilterKeyContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyFilterKeyContext() *FilterKeyContext { + var p = new(FilterKeyContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryRULE_filterKey + return p +} + +func InitEmptyFilterKeyContext(p *FilterKeyContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryRULE_filterKey +} + +func (*FilterKeyContext) IsFilterKeyContext() {} + +func NewFilterKeyContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *FilterKeyContext { + var p = new(FilterKeyContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = QueryRULE_filterKey + + return p +} + +func (s *FilterKeyContext) GetParser() antlr.Parser { return s.parser } + +func (s *FilterKeyContext) Ident() IIdentContext { + var t antlr.RuleContext + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IIdentContext); ok { + t = ctx.(antlr.RuleContext) + break + } + } + + if t == nil { + return nil + } + + return t.(IIdentContext) +} + +func (s *FilterKeyContext) STRING() antlr.TerminalNode { + return s.GetToken(QuerySTRING, 0) +} + +func (s *FilterKeyContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *FilterKeyContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *FilterKeyContext) Accept(visitor antlr.ParseTreeVisitor) interface{} { + switch t := visitor.(type) { + case QueryVisitor: + return t.VisitFilterKey(s) + + default: + return t.VisitChildren(s) + } +} + +func (p *Query) FilterKey() (localctx IFilterKeyContext) { + localctx = NewFilterKeyContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 18, QueryRULE_filterKey) + p.SetState(134) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + + switch p.GetTokenStream().LA(1) { + case QueryREP, QueryIN, QueryAS, QuerySELECT, QueryFROM, QueryFILTER, QueryIDENT: + p.EnterOuterAlt(localctx, 1) + { + p.SetState(132) + p.Ident() + } + + case QuerySTRING: + p.EnterOuterAlt(localctx, 2) + { + p.SetState(133) + p.Match(QuerySTRING) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + + default: + p.SetError(antlr.NewNoViableAltException(p, nil, nil, nil, nil, nil)) + goto errorExit + } + +errorExit: + if p.HasError() { + v := p.GetError() + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + p.SetError(nil) + } + p.ExitRule() + return localctx + goto errorExit // Trick to prevent compiler error if the label is not used +} + +// IFilterValueContext is an interface to support dynamic dispatch. +type IFilterValueContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // Getter signatures + Ident() IIdentContext + Number() INumberContext + STRING() antlr.TerminalNode + + // IsFilterValueContext differentiates from other interfaces. + IsFilterValueContext() +} + +type FilterValueContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyFilterValueContext() *FilterValueContext { + var p = new(FilterValueContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryRULE_filterValue + return p +} + +func InitEmptyFilterValueContext(p *FilterValueContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryRULE_filterValue +} + +func (*FilterValueContext) IsFilterValueContext() {} + +func NewFilterValueContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *FilterValueContext { + var p = new(FilterValueContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = QueryRULE_filterValue + + return p +} + +func (s *FilterValueContext) GetParser() antlr.Parser { return s.parser } + +func (s *FilterValueContext) Ident() IIdentContext { + var t antlr.RuleContext + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IIdentContext); ok { + t = ctx.(antlr.RuleContext) + break + } + } + + if t == nil { + return nil + } + + return t.(IIdentContext) +} + +func (s *FilterValueContext) Number() INumberContext { + var t antlr.RuleContext + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(INumberContext); ok { + t = ctx.(antlr.RuleContext) + break + } + } + + if t == nil { + return nil + } + + return t.(INumberContext) +} + +func (s *FilterValueContext) STRING() antlr.TerminalNode { + return s.GetToken(QuerySTRING, 0) +} + +func (s *FilterValueContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *FilterValueContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *FilterValueContext) Accept(visitor antlr.ParseTreeVisitor) interface{} { + switch t := visitor.(type) { + case QueryVisitor: + return t.VisitFilterValue(s) + + default: + return t.VisitChildren(s) + } +} + +func (p *Query) FilterValue() (localctx IFilterValueContext) { + localctx = NewFilterValueContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 20, QueryRULE_filterValue) + p.SetState(139) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + + switch p.GetTokenStream().LA(1) { + case QueryREP, QueryIN, QueryAS, QuerySELECT, QueryFROM, QueryFILTER, QueryIDENT: + p.EnterOuterAlt(localctx, 1) + { + p.SetState(136) + p.Ident() + } + + case QueryNUMBER1, QueryZERO: + p.EnterOuterAlt(localctx, 2) + { + p.SetState(137) + p.Number() + } + + case QuerySTRING: + p.EnterOuterAlt(localctx, 3) + { + p.SetState(138) + p.Match(QuerySTRING) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + + default: + p.SetError(antlr.NewNoViableAltException(p, nil, nil, nil, nil, nil)) + goto errorExit + } + +errorExit: + if p.HasError() { + v := p.GetError() + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + p.SetError(nil) + } + p.ExitRule() + return localctx + goto errorExit // Trick to prevent compiler error if the label is not used +} + +// INumberContext is an interface to support dynamic dispatch. +type INumberContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // Getter signatures + ZERO() antlr.TerminalNode + NUMBER1() antlr.TerminalNode + + // IsNumberContext differentiates from other interfaces. + IsNumberContext() +} + +type NumberContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyNumberContext() *NumberContext { + var p = new(NumberContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryRULE_number + return p +} + +func InitEmptyNumberContext(p *NumberContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryRULE_number +} + +func (*NumberContext) IsNumberContext() {} + +func NewNumberContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *NumberContext { + var p = new(NumberContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = QueryRULE_number + + return p +} + +func (s *NumberContext) GetParser() antlr.Parser { return s.parser } + +func (s *NumberContext) ZERO() antlr.TerminalNode { + return s.GetToken(QueryZERO, 0) +} + +func (s *NumberContext) NUMBER1() antlr.TerminalNode { + return s.GetToken(QueryNUMBER1, 0) +} + +func (s *NumberContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *NumberContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *NumberContext) Accept(visitor antlr.ParseTreeVisitor) interface{} { + switch t := visitor.(type) { + case QueryVisitor: + return t.VisitNumber(s) + + default: + return t.VisitChildren(s) + } +} + +func (p *Query) Number() (localctx INumberContext) { + localctx = NewNumberContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 22, QueryRULE_number) + var _la int + + p.EnterOuterAlt(localctx, 1) + { + p.SetState(141) + _la = p.GetTokenStream().LA(1) + + if !(_la == QueryNUMBER1 || _la == QueryZERO) { + p.GetErrorHandler().RecoverInline(p) + } else { + p.GetErrorHandler().ReportMatch(p) + p.Consume() + } + } + +errorExit: + if p.HasError() { + v := p.GetError() + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + p.SetError(nil) + } + p.ExitRule() + return localctx + goto errorExit // Trick to prevent compiler error if the label is not used +} + +// IKeywordContext is an interface to support dynamic dispatch. +type IKeywordContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // Getter signatures + REP() antlr.TerminalNode + IN() antlr.TerminalNode + AS() antlr.TerminalNode + SELECT() antlr.TerminalNode + FROM() antlr.TerminalNode + FILTER() antlr.TerminalNode + + // IsKeywordContext differentiates from other interfaces. + IsKeywordContext() +} + +type KeywordContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyKeywordContext() *KeywordContext { + var p = new(KeywordContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryRULE_keyword + return p +} + +func InitEmptyKeywordContext(p *KeywordContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryRULE_keyword +} + +func (*KeywordContext) IsKeywordContext() {} + +func NewKeywordContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *KeywordContext { + var p = new(KeywordContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = QueryRULE_keyword + + return p +} + +func (s *KeywordContext) GetParser() antlr.Parser { return s.parser } + +func (s *KeywordContext) REP() antlr.TerminalNode { + return s.GetToken(QueryREP, 0) +} + +func (s *KeywordContext) IN() antlr.TerminalNode { + return s.GetToken(QueryIN, 0) +} + +func (s *KeywordContext) AS() antlr.TerminalNode { + return s.GetToken(QueryAS, 0) +} + +func (s *KeywordContext) SELECT() antlr.TerminalNode { + return s.GetToken(QuerySELECT, 0) +} + +func (s *KeywordContext) FROM() antlr.TerminalNode { + return s.GetToken(QueryFROM, 0) +} + +func (s *KeywordContext) FILTER() antlr.TerminalNode { + return s.GetToken(QueryFILTER, 0) +} + +func (s *KeywordContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *KeywordContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *KeywordContext) Accept(visitor antlr.ParseTreeVisitor) interface{} { + switch t := visitor.(type) { + case QueryVisitor: + return t.VisitKeyword(s) + + default: + return t.VisitChildren(s) + } +} + +func (p *Query) Keyword() (localctx IKeywordContext) { + localctx = NewKeywordContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 24, QueryRULE_keyword) + var _la int + + p.EnterOuterAlt(localctx, 1) + { + p.SetState(143) + _la = p.GetTokenStream().LA(1) + + if !((int64(_la) & ^0x3f) == 0 && ((int64(1)<<_la)&7616) != 0) { + p.GetErrorHandler().RecoverInline(p) + } else { + p.GetErrorHandler().ReportMatch(p) + p.Consume() + } + } + +errorExit: + if p.HasError() { + v := p.GetError() + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + p.SetError(nil) + } + p.ExitRule() + return localctx + goto errorExit // Trick to prevent compiler error if the label is not used +} + +// IIdentContext is an interface to support dynamic dispatch. +type IIdentContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // Getter signatures + Keyword() IKeywordContext + IDENT() antlr.TerminalNode + + // IsIdentContext differentiates from other interfaces. + IsIdentContext() +} + +type IdentContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyIdentContext() *IdentContext { + var p = new(IdentContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryRULE_ident + return p +} + +func InitEmptyIdentContext(p *IdentContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryRULE_ident +} + +func (*IdentContext) IsIdentContext() {} + +func NewIdentContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *IdentContext { + var p = new(IdentContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = QueryRULE_ident + + return p +} + +func (s *IdentContext) GetParser() antlr.Parser { return s.parser } + +func (s *IdentContext) Keyword() IKeywordContext { + var t antlr.RuleContext + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IKeywordContext); ok { + t = ctx.(antlr.RuleContext) + break + } + } + + if t == nil { + return nil + } + + return t.(IKeywordContext) +} + +func (s *IdentContext) IDENT() antlr.TerminalNode { + return s.GetToken(QueryIDENT, 0) +} + +func (s *IdentContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *IdentContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *IdentContext) Accept(visitor antlr.ParseTreeVisitor) interface{} { + switch t := visitor.(type) { + case QueryVisitor: + return t.VisitIdent(s) + + default: + return t.VisitChildren(s) + } +} + +func (p *Query) Ident() (localctx IIdentContext) { + localctx = NewIdentContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 26, QueryRULE_ident) + p.SetState(147) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + + switch p.GetTokenStream().LA(1) { + case QueryREP, QueryIN, QueryAS, QuerySELECT, QueryFROM, QueryFILTER: + p.EnterOuterAlt(localctx, 1) + { + p.SetState(145) + p.Keyword() + } + + case QueryIDENT: + p.EnterOuterAlt(localctx, 2) + { + p.SetState(146) + p.Match(QueryIDENT) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + + default: + p.SetError(antlr.NewNoViableAltException(p, nil, nil, nil, nil, nil)) + goto errorExit + } + +errorExit: + if p.HasError() { + v := p.GetError() + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + p.SetError(nil) + } + p.ExitRule() + return localctx + goto errorExit // Trick to prevent compiler error if the label is not used +} + +// IIdentWCContext is an interface to support dynamic dispatch. +type IIdentWCContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // Getter signatures + Ident() IIdentContext + WILDCARD() antlr.TerminalNode + + // IsIdentWCContext differentiates from other interfaces. + IsIdentWCContext() +} + +type IdentWCContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyIdentWCContext() *IdentWCContext { + var p = new(IdentWCContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryRULE_identWC + return p +} + +func InitEmptyIdentWCContext(p *IdentWCContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = QueryRULE_identWC +} + +func (*IdentWCContext) IsIdentWCContext() {} + +func NewIdentWCContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *IdentWCContext { + var p = new(IdentWCContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = QueryRULE_identWC + + return p +} + +func (s *IdentWCContext) GetParser() antlr.Parser { return s.parser } + +func (s *IdentWCContext) Ident() IIdentContext { + var t antlr.RuleContext + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IIdentContext); ok { + t = ctx.(antlr.RuleContext) + break + } + } + + if t == nil { + return nil + } + + return t.(IIdentContext) +} + +func (s *IdentWCContext) WILDCARD() antlr.TerminalNode { + return s.GetToken(QueryWILDCARD, 0) +} + +func (s *IdentWCContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *IdentWCContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *IdentWCContext) Accept(visitor antlr.ParseTreeVisitor) interface{} { + switch t := visitor.(type) { + case QueryVisitor: + return t.VisitIdentWC(s) + + default: + return t.VisitChildren(s) + } +} + +func (p *Query) IdentWC() (localctx IIdentWCContext) { + localctx = NewIdentWCContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 28, QueryRULE_identWC) + p.SetState(151) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + + switch p.GetTokenStream().LA(1) { + case QueryREP, QueryIN, QueryAS, QuerySELECT, QueryFROM, QueryFILTER, QueryIDENT: + p.EnterOuterAlt(localctx, 1) + { + p.SetState(149) + p.Ident() + } + + case QueryWILDCARD: + p.EnterOuterAlt(localctx, 2) + { + p.SetState(150) + p.Match(QueryWILDCARD) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + + default: + p.SetError(antlr.NewNoViableAltException(p, nil, nil, nil, nil, nil)) + goto errorExit + } + +errorExit: + if p.HasError() { + v := p.GetError() + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + p.SetError(nil) + } + p.ExitRule() + return localctx + goto errorExit // Trick to prevent compiler error if the label is not used +} + +func (p *Query) Sempred(localctx antlr.RuleContext, ruleIndex, predIndex int) bool { + switch ruleIndex { + case 6: + var t *FilterExprContext = nil + if localctx != nil { + t = localctx.(*FilterExprContext) + } + return p.FilterExpr_Sempred(t, predIndex) + + default: + panic("No predicate with index: " + fmt.Sprint(ruleIndex)) + } +} + +func (p *Query) FilterExpr_Sempred(localctx antlr.RuleContext, predIndex int) bool { + switch predIndex { + case 0: + return p.Precpred(p.GetParserRuleContext(), 4) + + case 1: + return p.Precpred(p.GetParserRuleContext(), 3) + + default: + panic("No predicate with index: " + fmt.Sprint(predIndex)) + } +} diff --git a/pkg/sdk/netmap/parser/query_visitor.go b/pkg/sdk/netmap/parser/query_visitor.go new file mode 100644 index 000000000..7550d99eb --- /dev/null +++ b/pkg/sdk/netmap/parser/query_visitor.go @@ -0,0 +1,55 @@ +// Code generated from Query.g4 by ANTLR 4.13.0. DO NOT EDIT. + +package parser // Query + +import "github.com/antlr4-go/antlr/v4" + +// A complete Visitor for a parse tree produced by Query. +type QueryVisitor interface { + antlr.ParseTreeVisitor + + // Visit a parse tree produced by Query#policy. + VisitPolicy(ctx *PolicyContext) interface{} + + // Visit a parse tree produced by Query#selectFilterExpr. + VisitSelectFilterExpr(ctx *SelectFilterExprContext) interface{} + + // Visit a parse tree produced by Query#repStmt. + VisitRepStmt(ctx *RepStmtContext) interface{} + + // Visit a parse tree produced by Query#cbfStmt. + VisitCbfStmt(ctx *CbfStmtContext) interface{} + + // Visit a parse tree produced by Query#selectStmt. + VisitSelectStmt(ctx *SelectStmtContext) interface{} + + // Visit a parse tree produced by Query#clause. + VisitClause(ctx *ClauseContext) interface{} + + // Visit a parse tree produced by Query#filterExpr. + VisitFilterExpr(ctx *FilterExprContext) interface{} + + // Visit a parse tree produced by Query#filterStmt. + VisitFilterStmt(ctx *FilterStmtContext) interface{} + + // Visit a parse tree produced by Query#expr. + VisitExpr(ctx *ExprContext) interface{} + + // Visit a parse tree produced by Query#filterKey. + VisitFilterKey(ctx *FilterKeyContext) interface{} + + // Visit a parse tree produced by Query#filterValue. + VisitFilterValue(ctx *FilterValueContext) interface{} + + // Visit a parse tree produced by Query#number. + VisitNumber(ctx *NumberContext) interface{} + + // Visit a parse tree produced by Query#keyword. + VisitKeyword(ctx *KeywordContext) interface{} + + // Visit a parse tree produced by Query#ident. + VisitIdent(ctx *IdentContext) interface{} + + // Visit a parse tree produced by Query#identWC. + VisitIdentWC(ctx *IdentWCContext) interface{} +} diff --git a/pkg/sdk/netmap/policy.go b/pkg/sdk/netmap/policy.go new file mode 100644 index 000000000..a35b17166 --- /dev/null +++ b/pkg/sdk/netmap/policy.go @@ -0,0 +1,954 @@ +package netmap + +import ( + "errors" + "fmt" + "io" + "strconv" + "strings" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap/parser" + "github.com/antlr4-go/antlr/v4" +) + +// PlacementPolicy declares policy to store objects in the FrostFS container. +// Within itself, PlacementPolicy represents a set of rules to select a subset +// of nodes from FrostFS network map - node-candidates for object storage. +// +// PlacementPolicy is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/netmap.PlacementPolicy +// message. See ReadFromV2 / WriteToV2 methods. +// +// Instances can be created using built-in var declaration. +type PlacementPolicy struct { + backupFactor uint32 + + filters []netmap.Filter + + selectors []netmap.Selector + + replicas []netmap.Replica + + unique bool +} + +func (p *PlacementPolicy) readFromV2(m netmap.PlacementPolicy, checkFieldPresence bool) error { + p.replicas = m.GetReplicas() + if checkFieldPresence && len(p.replicas) == 0 { + return errors.New("missing replicas") + } + + p.backupFactor = m.GetContainerBackupFactor() + p.selectors = m.GetSelectors() + p.filters = m.GetFilters() + p.unique = m.GetUnique() + + return nil +} + +// Marshal encodes PlacementPolicy into a binary format of the FrostFS API +// protocol (Protocol Buffers with direct field order). +// +// See also Unmarshal. +func (p PlacementPolicy) Marshal() []byte { + var m netmap.PlacementPolicy + p.WriteToV2(&m) + + return m.StableMarshal(nil) +} + +// Unmarshal decodes FrostFS API protocol binary format into the PlacementPolicy +// (Protocol Buffers with direct field order). Returns an error describing +// a format violation. +// +// See also Marshal. +func (p *PlacementPolicy) Unmarshal(data []byte) error { + var m netmap.PlacementPolicy + + err := m.Unmarshal(data) + if err != nil { + return err + } + + return p.readFromV2(m, false) +} + +// MarshalJSON encodes PlacementPolicy into a JSON format of the FrostFS API +// protocol (Protocol Buffers JSON). +// +// See also UnmarshalJSON. +func (p PlacementPolicy) MarshalJSON() ([]byte, error) { + var m netmap.PlacementPolicy + p.WriteToV2(&m) + + return m.MarshalJSON() +} + +// UnmarshalJSON decodes FrostFS API protocol JSON format into the PlacementPolicy +// (Protocol Buffers JSON). Returns an error describing a format violation. +// +// See also MarshalJSON. +func (p *PlacementPolicy) UnmarshalJSON(data []byte) error { + var m netmap.PlacementPolicy + + err := m.UnmarshalJSON(data) + if err != nil { + return err + } + + return p.readFromV2(m, false) +} + +// ReadFromV2 reads PlacementPolicy from the netmap.PlacementPolicy message. +// Checks if the message conforms to FrostFS API V2 protocol. +// +// See also WriteToV2. +func (p *PlacementPolicy) ReadFromV2(m netmap.PlacementPolicy) error { + return p.readFromV2(m, true) +} + +// WriteToV2 writes PlacementPolicy to the session.Token message. +// The message must not be nil. +// +// See also ReadFromV2. +func (p PlacementPolicy) WriteToV2(m *netmap.PlacementPolicy) { + m.SetContainerBackupFactor(p.backupFactor) + m.SetFilters(p.filters) + m.SetSelectors(p.selectors) + m.SetReplicas(p.replicas) + m.SetUnique(p.unique) +} + +// ReplicaDescriptor replica descriptor characterizes replicas of objects from +// the subset selected by a particular Selector. +type ReplicaDescriptor struct { + m netmap.Replica +} + +// SetNumberOfObjects sets number of object replicas. +func (r *ReplicaDescriptor) SetNumberOfObjects(c uint32) { + r.m.SetCount(c) +} + +// NumberOfObjects returns number set using SetNumberOfObjects. +// +// Zero ReplicaDescriptor has zero number of objects. +func (r ReplicaDescriptor) NumberOfObjects() uint32 { + return r.m.GetCount() +} + +// SetSelectorName sets name of the related Selector. +// +// Zero ReplicaDescriptor references to the root bucket's selector: it contains +// all possible nodes to store the object. +func (r *ReplicaDescriptor) SetSelectorName(s string) { + r.m.SetSelector(s) +} + +// AddReplicas adds a bunch object replica's characteristics. +// +// See also IterateReplicas. +func (p *PlacementPolicy) AddReplicas(rs ...ReplicaDescriptor) { + off := len(p.replicas) + + p.replicas = append(p.replicas, make([]netmap.Replica, len(rs))...) + + for i := range rs { + p.replicas[off+i] = rs[i].m + } +} + +// NumberOfReplicas returns number of replica descriptors set using AddReplicas. +// +// Zero PlacementPolicy has no replicas which is incorrect according to the +// FrostFS API protocol. +func (p PlacementPolicy) NumberOfReplicas() int { + return len(p.replicas) +} + +// ReplicaNumberByIndex returns number of object replicas from the i-th replica +// descriptor. Index MUST be in range [0; NumberOfReplicas()). +// +// Zero PlacementPolicy has no replicas. +func (p PlacementPolicy) ReplicaNumberByIndex(i int) uint32 { + return p.replicas[i].GetCount() +} + +// SetContainerBackupFactor sets container backup factor: it controls how deep +// FrostFS will search for nodes alternatives to include into container's nodes subset. +// +// Zero PlacementPolicy has zero container backup factor. +func (p *PlacementPolicy) SetContainerBackupFactor(f uint32) { + p.backupFactor = f +} + +// SetUnique sets the unique flag: it controls whether the selected replica buckets +// are disjoint or not. +// +// Zero PlacementPolicy has false unique flag. +func (p *PlacementPolicy) SetUnique(b bool) { + p.unique = b +} + +// Selector describes the bucket selection operator: choose a number of nodes +// from the bucket taking the nearest nodes to the related container by hash distance. +type Selector struct { + m netmap.Selector +} + +// SetName sets name with which the Selector can be referenced. +// +// Zero Selector is unnamed. +func (s *Selector) SetName(name string) { + s.m.SetName(name) +} + +// SetNumberOfNodes sets number of nodes to select from the bucket. +// +// Zero Selector selects nothing. +func (s *Selector) SetNumberOfNodes(num uint32) { + s.m.SetCount(num) +} + +// SelectByBucketAttribute sets attribute of the bucket to select nodes from. +// +// Zero Selector has empty attribute. +func (s *Selector) SelectByBucketAttribute(bucket string) { + s.m.SetAttribute(bucket) +} + +// SetClause sets the clause for the Selector. +func (s *Selector) SetClause(clause netmap.Clause) { + s.m.SetClause(clause) +} + +// SelectSame makes selection algorithm to select only nodes having the same values +// of the bucket attribute. +// +// Zero Selector doesn't specify selection modifier so nodes are selected randomly. +// +// See also SelectByBucketAttribute. +func (s *Selector) SelectSame() { + s.m.SetClause(netmap.Same) +} + +// SelectDistinct makes selection algorithm to select only nodes having the different values +// of the bucket attribute. +// +// Zero Selector doesn't specify selection modifier so nodes are selected randomly. +// +// See also SelectByBucketAttribute. +func (s *Selector) SelectDistinct() { + s.m.SetClause(netmap.Distinct) +} + +// SetFilterName sets reference to pre-filtering nodes for selection. +// +// Zero Selector has no filtering reference. +// +// See also Filter.SetName. +func (s *Selector) SetFilterName(f string) { + s.m.SetFilter(f) +} + +// AddSelectors adds a Selector bunch to form the subset of the nodes +// to store container objects. +// +// Zero PlacementPolicy does not declare selectors. +func (p *PlacementPolicy) AddSelectors(ss ...Selector) { + off := len(p.selectors) + + p.selectors = append(p.selectors, make([]netmap.Selector, len(ss))...) + + for i := range ss { + p.selectors[off+i] = ss[i].m + } +} + +// Filter contains rules for filtering the node sets. +type Filter struct { + m netmap.Filter +} + +// SetName sets name with which the Filter can be referenced or, for inner filters, +// to which the Filter references. Top-level filters MUST be named. The name +// MUST NOT be '*'. +// +// Zero Filter is unnamed. +func (x *Filter) SetName(name string) { + x.m.SetName(name) +} + +func (x *Filter) setAttribute(key string, op netmap.Operation, val string) { + x.m.SetKey(key) + x.m.SetOp(op) + x.m.SetValue(val) +} + +// Equal applies the rule to accept only nodes with the same attribute value. +// +// Method SHOULD NOT be called along with other similar methods. +func (x *Filter) Equal(key, value string) { + x.setAttribute(key, netmap.EQ, value) +} + +// NotEqual applies the rule to accept only nodes with the distinct attribute value. +// +// Method SHOULD NOT be called along with other similar methods. +func (x *Filter) NotEqual(key, value string) { + x.setAttribute(key, netmap.NE, value) +} + +// NumericGT applies the rule to accept only nodes with the numeric attribute +// greater than given number. +// +// Method SHOULD NOT be called along with other similar methods. +func (x *Filter) NumericGT(key string, num int64) { + x.setAttribute(key, netmap.GT, strconv.FormatInt(num, 10)) +} + +// NumericGE applies the rule to accept only nodes with the numeric attribute +// greater than or equal to given number. +// +// Method SHOULD NOT be called along with other similar methods. +func (x *Filter) NumericGE(key string, num int64) { + x.setAttribute(key, netmap.GE, strconv.FormatInt(num, 10)) +} + +// NumericLT applies the rule to accept only nodes with the numeric attribute +// less than given number. +// +// Method SHOULD NOT be called along with other similar methods. +func (x *Filter) NumericLT(key string, num int64) { + x.setAttribute(key, netmap.LT, strconv.FormatInt(num, 10)) +} + +// NumericLE applies the rule to accept only nodes with the numeric attribute +// less than or equal to given number. +// +// Method SHOULD NOT be called along with other similar methods. +func (x *Filter) NumericLE(key string, num int64) { + x.setAttribute(key, netmap.LE, strconv.FormatInt(num, 10)) +} + +func (x *Filter) setInnerFilters(op netmap.Operation, filters []Filter) { + x.setAttribute("", op, "") + + inner := x.m.GetFilters() + if rem := len(filters) - len(inner); rem > 0 { + inner = append(inner, make([]netmap.Filter, rem)...) + } + + for i := range filters { + inner[i] = filters[i].m + } + + x.m.SetFilters(inner) +} + +// LogicalOR applies the rule to accept only nodes which satisfy at least one +// of the given filters. +// +// Method SHOULD NOT be called along with other similar methods. +func (x *Filter) LogicalOR(filters ...Filter) { + x.setInnerFilters(netmap.OR, filters) +} + +// LogicalAND applies the rule to accept only nodes which satisfy all the given +// filters. +// +// Method SHOULD NOT be called along with other similar methods. +func (x *Filter) LogicalAND(filters ...Filter) { + x.setInnerFilters(netmap.AND, filters) +} + +// AddFilters adds a Filter bunch that will be applied when selecting nodes. +// +// Zero PlacementPolicy has no filters. +func (p *PlacementPolicy) AddFilters(fs ...Filter) { + off := len(p.filters) + + p.filters = append(p.filters, make([]netmap.Filter, len(fs))...) + + for i := range fs { + p.filters[off+i] = fs[i].m + } +} + +// WriteStringTo encodes PlacementPolicy into human-readably query and writes +// the result into w. Returns w's errors directly. +// +// See also DecodeString. +// nolint: funlen +func (p PlacementPolicy) WriteStringTo(w io.StringWriter) (err error) { + if p.unique { + if _, err := w.WriteString("UNIQUE\n"); err != nil { + return err + } + } + + delim := "" + + for i := range p.replicas { + c := p.replicas[i].GetCount() + s := p.replicas[i].GetSelector() + + if s != "" { + _, err = w.WriteString(fmt.Sprintf("%sREP %d IN %s", delim, c, s)) + } else { + _, err = w.WriteString(fmt.Sprintf("%sREP %d", delim, c)) + } + + if err != nil { + return err + } + + delim = "\n" + } + + if p.backupFactor > 0 { + _, err = w.WriteString(fmt.Sprintf("\nCBF %d", p.backupFactor)) + if err != nil { + return err + } + } + + var s string + + for i := range p.selectors { + _, err = w.WriteString(fmt.Sprintf("\nSELECT %d", p.selectors[i].GetCount())) + if err != nil { + return err + } + + if s = p.selectors[i].GetAttribute(); s != "" { + var clause string + + switch p.selectors[i].GetClause() { + case netmap.Same: + clause = "SAME " + case netmap.Distinct: + clause = "DISTINCT " + default: + clause = "" + } + + _, err = w.WriteString(fmt.Sprintf(" IN %s%s", clause, s)) + if err != nil { + return err + } + } + + if s = p.selectors[i].GetFilter(); s != "" { + _, err = w.WriteString(" FROM " + s) + if err != nil { + return err + } + } + + if s = p.selectors[i].GetName(); s != "" { + _, err = w.WriteString(" AS " + s) + if err != nil { + return err + } + } + } + + for i := range p.filters { + _, err = w.WriteString("\nFILTER ") + if err != nil { + return err + } + + err = writeFilterStringTo(w, p.filters[i], false) + if err != nil { + return err + } + } + + return nil +} + +func writeFilterStringTo(w io.StringWriter, f netmap.Filter, mayNeedOuterBrackets bool) error { + var err error + var s string + op := f.GetOp() + unspecified := op == 0 + + if s = f.GetKey(); s != "" { + _, err = w.WriteString(fmt.Sprintf("%s %s %s", escapeString(s), op, escapeString(f.GetValue()))) + if err != nil { + return err + } + } else if s = f.GetName(); unspecified && s != "" { + _, err = w.WriteString(fmt.Sprintf("@%s", s)) + if err != nil { + return err + } + } + + inner := f.GetFilters() + + if op == netmap.NOT { + _, err = w.WriteString(op.String() + " (") + if err != nil { + return err + } + err = writeFilterStringTo(w, inner[0], false) + if err != nil { + return err + } + _, err = w.WriteString(")") + if err != nil { + return err + } + } else { + useBrackets := mayNeedOuterBrackets && op == netmap.OR && len(inner) > 1 + if useBrackets { + _, err = w.WriteString("(") + if err != nil { + return err + } + } + for i := range inner { + if i != 0 { + _, err = w.WriteString(" " + op.String() + " ") + if err != nil { + return err + } + } + err = writeFilterStringTo(w, inner[i], true) + if err != nil { + return err + } + } + if useBrackets { + _, err = w.WriteString(")") + if err != nil { + return err + } + } + } + + if s = f.GetName(); s != "" && !unspecified { + _, err = w.WriteString(" AS " + s) + if err != nil { + return err + } + } + + return nil +} + +// DecodeString decodes PlacementPolicy from the string composed using +// WriteStringTo. Returns error if s is malformed. +func (p *PlacementPolicy) DecodeString(s string) error { + var v policyVisitor + + input := antlr.NewInputStream(s) + lexer := parser.NewQueryLexer(input) + lexer.RemoveErrorListeners() + lexer.AddErrorListener(&v) + stream := antlr.NewCommonTokenStream(lexer, 0) + + pp := parser.NewQuery(stream) + pp.BuildParseTrees = true + + pp.RemoveErrorListeners() + pp.AddErrorListener(&v) + pl := pp.Policy().Accept(&v) + + if len(v.errors) != 0 { + return v.errors[0] + } + + parsed, ok := pl.(*PlacementPolicy) + if !ok { + return fmt.Errorf("unexpected parsed instance type %T", pl) + } else if parsed == nil { + return errors.New("parsed nil value") + } + + if err := validatePolicy(*parsed); err != nil { + return fmt.Errorf("invalid policy: %w", err) + } + + *p = *parsed + + return nil +} + +// SelectFilterExpr is an expression containing only selectors and filters. +// It's useful to evaluate their effect before being used in a policy. +type SelectFilterExpr struct { + cbf uint32 + selector *netmap.Selector + filters []netmap.Filter +} + +// DecodeString decodes a string into a SelectFilterExpr. +// Returns an error if s is malformed. +func DecodeSelectFilterString(s string) (*SelectFilterExpr, error) { + var v policyVisitor + + input := antlr.NewInputStream(s) + lexer := parser.NewQueryLexer(input) + lexer.RemoveErrorListeners() + lexer.AddErrorListener(&v) + stream := antlr.NewCommonTokenStream(lexer, 0) + + pp := parser.NewQuery(stream) + pp.BuildParseTrees = true + + pp.RemoveErrorListeners() + pp.AddErrorListener(&v) + sfExpr := pp.SelectFilterExpr().Accept(&v) + + if len(v.errors) != 0 { + return nil, v.errors[0] + } + + parsed, ok := sfExpr.(*SelectFilterExpr) + if !ok { + return nil, fmt.Errorf("unexpected parsed instance type %T", sfExpr) + } + + return parsed, nil +} + +var ( + // errUnknownFilter is returned when a value of FROM in a query is unknown. + errUnknownFilter = errors.New("filter not found") + // errUnknownSelector is returned when a value of IN is unknown. + errUnknownSelector = errors.New("policy: selector not found") + // errSyntaxError is returned for errors found by ANTLR parser. + errSyntaxError = errors.New("policy: syntax error") + // errRedundantSelector is returned for errors found by selectors policy validator. + errRedundantSelector = errors.New("policy: found redundant selector") + // errUnnamedSelector is returned for errors found by selectors policy validator. + errUnnamedSelector = errors.New("policy: unnamed selectors are useless, " + + "make sure to pair REP and SELECT clauses: \"REP .. IN X\" + \"SELECT ... AS X\"") + // errRedundantSelector is returned for errors found by filters policy validator. + errRedundantFilter = errors.New("policy: found redundant filter") +) + +type policyVisitor struct { + errors []error + parser.BaseQueryVisitor + antlr.DefaultErrorListener +} + +func (p *policyVisitor) SyntaxError(_ antlr.Recognizer, _ any, line, column int, msg string, _ antlr.RecognitionException) { + p.reportError(fmt.Errorf("%w: line %d:%d %s", errSyntaxError, line, column, msg)) +} + +func (p *policyVisitor) reportError(err error) any { + p.errors = append(p.errors, err) + return nil +} + +// VisitPolicy implements parser.QueryVisitor interface. +func (p *policyVisitor) VisitPolicy(ctx *parser.PolicyContext) any { + if len(p.errors) != 0 { + return nil + } + + pl := new(PlacementPolicy) + + pl.unique = ctx.UNIQUE() != nil + + repStmts := ctx.AllRepStmt() + pl.replicas = make([]netmap.Replica, 0, len(repStmts)) + + for _, r := range repStmts { + res, ok := r.Accept(p).(*netmap.Replica) + if !ok { + return nil + } + + pl.replicas = append(pl.replicas, *res) + } + + if cbfStmt := ctx.CbfStmt(); cbfStmt != nil { + cbf, ok := cbfStmt.(*parser.CbfStmtContext).Accept(p).(uint32) + if !ok { + return nil + } + pl.SetContainerBackupFactor(cbf) + } + + selStmts := ctx.AllSelectStmt() + pl.selectors = make([]netmap.Selector, 0, len(selStmts)) + + for _, s := range selStmts { + res, ok := s.Accept(p).(*netmap.Selector) + if !ok { + return nil + } + + pl.selectors = append(pl.selectors, *res) + } + + filtStmts := ctx.AllFilterStmt() + pl.filters = make([]netmap.Filter, 0, len(filtStmts)) + + for _, f := range filtStmts { + pl.filters = append(pl.filters, *f.Accept(p).(*netmap.Filter)) + } + + return pl +} + +func (p *policyVisitor) VisitSelectFilterExpr(ctx *parser.SelectFilterExprContext) any { + if len(p.errors) != 0 { + return nil + } + + sfExpr := new(SelectFilterExpr) + + if cbfStmt := ctx.CbfStmt(); cbfStmt != nil { + cbf, ok := cbfStmt.(*parser.CbfStmtContext).Accept(p).(uint32) + if !ok { + return nil + } + sfExpr.cbf = cbf + } + + if selStmt := ctx.SelectStmt(); selStmt != nil { + sel, ok := selStmt.Accept(p).(*netmap.Selector) + if !ok { + return nil + } + sfExpr.selector = sel + } + + filtStmts := ctx.AllFilterStmt() + sfExpr.filters = make([]netmap.Filter, 0, len(filtStmts)) + + for _, f := range filtStmts { + sfExpr.filters = append(sfExpr.filters, *f.Accept(p).(*netmap.Filter)) + } + + return sfExpr +} + +func (p *policyVisitor) VisitCbfStmt(ctx *parser.CbfStmtContext) any { + cbf, err := strconv.ParseUint(ctx.GetBackupFactor().GetText(), 10, 32) + if err != nil { + return p.reportError(errInvalidNumber) + } + + return uint32(cbf) +} + +// VisitRepStmt implements parser.QueryVisitor interface. +func (p *policyVisitor) VisitRepStmt(ctx *parser.RepStmtContext) any { + num, err := strconv.ParseUint(ctx.GetCount().GetText(), 10, 32) + if err != nil { + return p.reportError(errInvalidNumber) + } + + rs := new(netmap.Replica) + rs.SetCount(uint32(num)) + + if sel := ctx.GetSelector(); sel != nil { + rs.SetSelector(sel.GetText()) + } + + return rs +} + +// VisitSelectStmt implements parser.QueryVisitor interface. +func (p *policyVisitor) VisitSelectStmt(ctx *parser.SelectStmtContext) any { + res, err := strconv.ParseUint(ctx.GetCount().GetText(), 10, 32) + if err != nil { + return p.reportError(errInvalidNumber) + } + + s := new(netmap.Selector) + s.SetCount(uint32(res)) + + if clStmt := ctx.Clause(); clStmt != nil { + s.SetClause(clauseFromString(clStmt.GetText())) + } + + if bStmt := ctx.GetBucket(); bStmt != nil { + s.SetAttribute(ctx.GetBucket().GetText()) + } + + s.SetFilter(ctx.GetFilter().GetText()) // either ident or wildcard + + if ctx.AS() != nil { + s.SetName(ctx.GetName().GetText()) + } + return s +} + +// VisitFilterStmt implements parser.QueryVisitor interface. +func (p *policyVisitor) VisitFilterStmt(ctx *parser.FilterStmtContext) any { + f := p.VisitFilterExpr(ctx.GetExpr().(*parser.FilterExprContext)).(*netmap.Filter) + f.SetName(ctx.GetName().GetText()) + return f +} + +func (p *policyVisitor) VisitFilterExpr(ctx *parser.FilterExprContext) any { + if eCtx := ctx.Expr(); eCtx != nil { + return eCtx.Accept(p) + } + + if inner := ctx.GetInner(); inner != nil { + return inner.Accept(p) + } + + f := new(netmap.Filter) + op := operationFromString(ctx.GetOp().GetText()) + f.SetOp(op) + + if op == netmap.NOT { + f1 := *ctx.GetF1().Accept(p).(*netmap.Filter) + f.SetFilters([]netmap.Filter{f1}) + return f + } + + f1 := *ctx.GetF1().Accept(p).(*netmap.Filter) + f2 := *ctx.GetF2().Accept(p).(*netmap.Filter) + + // Consider f1=(.. AND ..) AND f2. This can be merged because our AND operation + // is of arbitrary arity. ANTLR generates left-associative parse-tree by default. + if f1.GetOp() == op { + f.SetFilters(append(f1.GetFilters(), f2)) + return f + } + + f.SetFilters([]netmap.Filter{f1, f2}) + + return f +} + +// VisitFilterKey implements parser.QueryVisitor interface. +func (p *policyVisitor) VisitFilterKey(ctx *parser.FilterKeyContext) any { + if id := ctx.Ident(); id != nil { + return id.GetText() + } + + str := ctx.STRING().GetText() + return str[1 : len(str)-1] +} + +func (p *policyVisitor) VisitFilterValue(ctx *parser.FilterValueContext) any { + if id := ctx.Ident(); id != nil { + return id.GetText() + } + + if num := ctx.Number(); num != nil { + return num.GetText() + } + + str := ctx.STRING().GetText() + return str[1 : len(str)-1] +} + +// VisitExpr implements parser.QueryVisitor interface. +func (p *policyVisitor) VisitExpr(ctx *parser.ExprContext) any { + f := new(netmap.Filter) + if flt := ctx.GetFilter(); flt != nil { + f.SetName(flt.GetText()) + return f + } + + key := ctx.GetKey().Accept(p) + opStr := ctx.SIMPLE_OP().GetText() + value := ctx.GetValue().Accept(p) + + f.SetKey(key.(string)) + f.SetOp(operationFromString(opStr)) + f.SetValue(value.(string)) + + return f +} + +// validatePolicy checks high-level constraints such as filter link in SELECT +// being actually defined in FILTER section. +func validatePolicy(p PlacementPolicy) error { + canOmitNames := len(p.selectors) == 1 && len(p.replicas) == 1 + seenFilters := map[string]bool{} + expectedFilters := map[string]struct{}{} + for i := range p.filters { + seenFilters[p.filters[i].GetName()] = true + for _, f := range p.filters[i].GetFilters() { + if f.GetName() != "" { + expectedFilters[f.GetName()] = struct{}{} + } + } + } + + seenSelectors := map[string]*netmap.Selector{} + for i := range p.selectors { + if p.selectors[i].GetName() == "" && !canOmitNames { + return errUnnamedSelector + } + if flt := p.selectors[i].GetFilter(); flt != mainFilterName { + expectedFilters[flt] = struct{}{} + if !seenFilters[flt] { + return fmt.Errorf("%w: '%s'", errUnknownFilter, flt) + } + } + seenSelectors[p.selectors[i].GetName()] = &p.selectors[i] + } + + for _, f := range p.filters { + if _, ok := expectedFilters[f.GetName()]; !ok { + return fmt.Errorf("%w: '%s'", errRedundantFilter, f.GetName()) + } + } + + expectedSelectors := map[string]struct{}{} + for i := range p.replicas { + selName := p.replicas[i].GetSelector() + if selName != "" || canOmitNames { + expectedSelectors[selName] = struct{}{} + if seenSelectors[selName] == nil { + return fmt.Errorf("%w: '%s'", errUnknownSelector, selName) + } + } + } + + for _, s := range p.selectors { + if _, ok := expectedSelectors[s.GetName()]; !ok { + return fmt.Errorf("%w: to use selector '%s' use keyword IN", errRedundantSelector, s.GetName()) + } + } + + return nil +} + +func clauseFromString(s string) (c netmap.Clause) { + if !c.FromString(strings.ToUpper(s)) { + // Such errors should be handled by ANTLR code thus this panic. + panic(fmt.Errorf("BUG: invalid clause: %s", c)) + } + + return +} + +func operationFromString(s string) (op netmap.Operation) { + if !op.FromString(strings.ToUpper(s)) { + // Such errors should be handled by ANTLR code thus this panic. + panic(fmt.Errorf("BUG: invalid operation: %s", op)) + } + + return +} + +// escapeString returns single quote wrapped string. +// Wrapping rules must be kept in sync with QueryLexer.g4. +// Currently only ASCII letters, digits and underscore can be parsed without quotes. +func escapeString(s string) string { + for _, r := range s { + if 'a' <= r && r <= 'z' || 'A' <= r && r <= 'Z' || '0' <= r && r <= '9' || r == '_' { + continue + } + return "'" + s + "'" + } + return s +} diff --git a/pkg/sdk/netmap/policy_decode_test.go b/pkg/sdk/netmap/policy_decode_test.go new file mode 100644 index 000000000..0c78fa8aa --- /dev/null +++ b/pkg/sdk/netmap/policy_decode_test.go @@ -0,0 +1,70 @@ +package netmap + +import ( + "strings" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestDecodeString(t *testing.T) { + testCases := []string{ + `REP 2 +CBF 2 +SELECT 2 FROM *`, + `REP 1 IN X +CBF 1 +SELECT 2 IN SAME Location FROM * AS X`, + + `REP 1 IN X +REP 2 IN Y +CBF 1 +SELECT 2 FROM * AS X +SELECT 3 FROM * AS Y`, + + `REP 1 IN X +SELECT 2 IN City FROM Good AS X +FILTER Country EQ RU AS FromRU +FILTER Country EQ EN AS FromEN +FILTER @FromRU AND @FromEN AND Rating GT 7 AS Good`, + + `REP 7 IN SPB +SELECT 1 IN City FROM SPBSSD AS SPB +FILTER City EQ SPB AND SSD EQ true OR City EQ SPB AND Rating GE 5 AS SPBSSD`, + + `REP 7 IN SPB +SELECT 1 IN City FROM SPBSSD AS SPB +FILTER NOT (NOT (City EQ SPB) AND SSD EQ true OR City EQ SPB AND Rating GE 5) AS SPBSSD`, + + `REP 1 IN FNODE +CBF 1 +SELECT 1 FROM F AS FNODE +FILTER Node EQ '10.78.8.11' AS F`, + + `UNIQUE +REP 1 +REP 1`, + } + + var p PlacementPolicy + + for _, testCase := range testCases { + require.NoError(t, p.DecodeString(testCase), "unable parse %s", testCase) + var b strings.Builder + require.NoError(t, p.WriteStringTo(&b)) + require.Equal(t, testCase, b.String()) + } + + invalidTestCases := map[string]error{ + `?REP 1`: errSyntaxError, + `REP 1 trailing garbage`: errSyntaxError, + `REP 1 REP 1 SELECT 4 FROM *`: errUnnamedSelector, + `REP 1 SELECT 4 FROM * SELECT 1 FROM *`: errUnnamedSelector, + `REP 1 IN X SELECT 4 FROM *`: errUnknownSelector, + `REP 1 IN X REP 2 SELECT 4 FROM * AS X FILTER 'UN-LOCODE' EQ 'RU LED' AS F`: errRedundantFilter, + } + + for i := range invalidTestCases { + require.ErrorIs(t, p.DecodeString(i), invalidTestCases[i], "#%s", i) + } +} diff --git a/pkg/sdk/netmap/policy_test.go b/pkg/sdk/netmap/policy_test.go new file mode 100644 index 000000000..83fbda3b5 --- /dev/null +++ b/pkg/sdk/netmap/policy_test.go @@ -0,0 +1,129 @@ +package netmap_test + +import ( + "strings" + "testing" + + . "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" + netmaptest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap/test" + "github.com/stretchr/testify/require" +) + +func TestPlacementPolicyEncoding(t *testing.T) { + v := netmaptest.PlacementPolicy() + + t.Run("binary", func(t *testing.T) { + var v2 PlacementPolicy + require.NoError(t, v2.Unmarshal(v.Marshal())) + + require.Equal(t, v, v2) + }) + + t.Run("json", func(t *testing.T) { + data, err := v.MarshalJSON() + require.NoError(t, err) + + var v2 PlacementPolicy + require.NoError(t, v2.UnmarshalJSON(data)) + + require.Equal(t, v, v2) + }) +} + +func TestPlacementPolicyWriteString(t *testing.T) { + testCases := []struct { + name string + input string + output string // If the output is empty, make it equal to input. + }{ + { + name: "no compound operators", + input: `REP 1 +CBF 1 +SELECT 1 FROM Color +FILTER Color EQ Red AS Color`, + }, + { + name: "no brackets in single level same-operator chain", + input: `REP 1 +CBF 1 +SELECT 1 FROM Color +FILTER Color EQ Red OR Color EQ Blue OR Color EQ Green AS Color`, + }, + { + name: "no brackets aroung higher precedence op", + input: `REP 1 +CBF 1 +SELECT 1 FROM Color +FILTER Color EQ Red OR Color EQ Blue AND Color NE Green AS Color`, + }, + { + name: "no brackets aroung higher precedence op, even if present in the input", + input: `REP 1 +CBF 1 +SELECT 1 FROM Color +FILTER Color EQ Red OR (Color EQ Blue AND Color NE Green) AS Color`, + output: `REP 1 +CBF 1 +SELECT 1 FROM Color +FILTER Color EQ Red OR Color EQ Blue AND Color NE Green AS Color`, + }, + { + name: "brackets aroung lower precedence op", + input: `REP 1 +CBF 1 +SELECT 1 FROM Color +FILTER (Color EQ Red OR Color EQ Blue) AND Color NE Green AS Color`, + }, + { + name: "no extra brackets for bracketed same-operator chain", + input: `REP 1 +CBF 1 +SELECT 1 FROM Color +FILTER (Color EQ Red OR Color EQ Blue OR Color EQ Yellow) AND Color NE Green AS Color`, + }, + } + + for _, tc := range testCases { + var p PlacementPolicy + require.NoError(t, p.DecodeString(tc.input)) + + var sb strings.Builder + require.NoError(t, p.WriteStringTo(&sb)) + + if tc.output == "" { + require.Equal(t, tc.input, sb.String()) + } else { + require.Equal(t, tc.output, sb.String()) + + var p1 PlacementPolicy + require.NoError(t, p1.DecodeString(tc.output)) + require.Equal(t, p, p1) + } + } +} + +func TestDecodeSelectFilterExpr(t *testing.T) { + for _, s := range []string{ + "SELECT 1 FROM *", + "FILTER Color EQ 'Red' AS RedNode", + ` + FILTER Color EQ 'Red' AS RedNode + FILTER @RedNode AND Shape EQ 'Cirle' AS RedCircleNode + `, + ` + SELECT 1 FROM RedCircleNode + FILTER Color EQ 'Red' AS RedNode + FILTER @RedNode AND Shape EQ 'Cirle' AS RedCircleNode + `, + ` + CBF 1 + SELECT 1 FROM RedCircleNode + FILTER Color EQ 'Red' AS RedNode + FILTER @RedNode AND Shape EQ 'Cirle' AS RedCircleNode + `, + } { + _, err := DecodeSelectFilterString(s) + require.NoError(t, err) + } +} diff --git a/pkg/sdk/netmap/selector.go b/pkg/sdk/netmap/selector.go new file mode 100644 index 000000000..bd379f45c --- /dev/null +++ b/pkg/sdk/netmap/selector.go @@ -0,0 +1,177 @@ +package netmap + +import ( + "fmt" + "sort" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/netmap" + "git.frostfs.info/TrueCloudLab/hrw" +) + +// processSelectors processes selectors and returns error is any of them is invalid. +func (c *context) processSelectors(p PlacementPolicy) error { + for i := range p.selectors { + fName := p.selectors[i].GetFilter() + if fName != mainFilterName { + _, ok := c.processedFilters[p.selectors[i].GetFilter()] + if !ok { + return fmt.Errorf("%w: SELECT FROM '%s'", errFilterNotFound, fName) + } + } + + sName := p.selectors[i].GetName() + + c.processedSelectors[sName] = &p.selectors[i] + + result, err := c.getSelection(p.selectors[i]) + if err != nil { + return err + } + + c.selections[sName] = result + } + + return nil +} + +// calcNodesCount returns number of buckets and minimum number of nodes in every bucket +// for the given selector. +func calcNodesCount(s netmap.Selector) (int, int) { + switch s.GetClause() { + case netmap.Same: + return 1, int(s.GetCount()) + default: + return int(s.GetCount()), 1 + } +} + +// calcBucketWeight computes weight for a node bucket. +func calcBucketWeight(ns nodes, a aggregator, wf weightFunc) float64 { + for i := range ns { + a.Add(wf(ns[i])) + } + + return a.Compute() +} + +// getSelection returns nodes grouped by s.attribute. +// Last argument specifies if more buckets can be used to fulfill CBF. +func (c *context) getSelection(s netmap.Selector) ([]nodes, error) { + bucketCount, nodesInBucket := calcNodesCount(s) + buckets := c.getSelectionBase(s) + + if c.strict && len(buckets) < bucketCount { + return nil, fmt.Errorf("%w: '%s'", errNotEnoughNodes, s.GetName()) + } + + // We need deterministic output in case there is no pivot. + // If pivot is set, buckets are sorted by HRW. + // However, because initial order influences HRW order for buckets with equal weights, + // we also need to have deterministic input to HRW sorting routine. + if len(c.hrwSeed) == 0 { + if s.GetAttribute() == "" { + sort.Slice(buckets, func(i, j int) bool { + return less(buckets[i].nodes[0], buckets[j].nodes[0]) + }) + } else { + sort.Slice(buckets, func(i, j int) bool { + return buckets[i].attr < buckets[j].attr + }) + } + } + + maxNodesInBucket := nodesInBucket * int(c.cbf) + res := make([]nodes, 0, len(buckets)) + fallback := make([]nodes, 0, len(buckets)) + + for i := range buckets { + ns := buckets[i].nodes + if len(ns) >= maxNodesInBucket { + res = append(res, ns[:maxNodesInBucket]) + } else if len(ns) >= nodesInBucket { + fallback = append(fallback, ns) + } + } + + if len(res) < bucketCount { + // Fallback to using minimum allowed backup factor (1). + res = append(res, fallback...) + if c.strict && len(res) < bucketCount { + return nil, fmt.Errorf("%w: '%s'", errNotEnoughNodes, s.GetName()) + } + } + + if len(c.hrwSeed) != 0 { + weights := make([]float64, len(res)) + for i := range res { + weights[i] = calcBucketWeight(res[i], newMeanIQRAgg(), c.weightFunc) + } + + hrw.SortHasherSliceByWeightValue(res, weights, c.hrwSeedHash) + } + + if len(res) < bucketCount { + if len(res) == 0 { + return nil, errNotEnoughNodes + } + bucketCount = len(res) + } + + if s.GetAttribute() == "" { + res, fallback = res[:bucketCount], res[bucketCount:] + for i := range fallback { + index := i % bucketCount + if len(res[index]) >= maxNodesInBucket { + break + } + res[index] = append(res[index], fallback[i]...) + } + } + + return res[:bucketCount], nil +} + +type nodeAttrPair struct { + attr string + nodes nodes +} + +// getSelectionBase returns nodes grouped by selector attribute. +// It it guaranteed that each pair will contain at least one node. +func (c *context) getSelectionBase(s netmap.Selector) []nodeAttrPair { + fName := s.GetFilter() + f := c.processedFilters[fName] + isMain := fName == mainFilterName + result := []nodeAttrPair{} + nodeMap := map[string][]NodeInfo{} + attr := s.GetAttribute() + + for i := range c.netMap.nodes { + if c.usedNodes[c.netMap.nodes[i].hash] { + continue + } + if isMain || c.match(f, c.netMap.nodes[i]) { + if attr == "" { + // Default attribute is transparent identifier which is different for every node. + result = append(result, nodeAttrPair{attr: "", nodes: nodes{c.netMap.nodes[i]}}) + } else { + v := c.netMap.nodes[i].Attribute(attr) + nodeMap[v] = append(nodeMap[v], c.netMap.nodes[i]) + } + } + } + + if attr != "" { + for k, ns := range nodeMap { + result = append(result, nodeAttrPair{attr: k, nodes: ns}) + } + } + + if len(c.hrwSeed) != 0 { + for i := range result { + hrw.SortHasherSliceByWeightValue(result[i].nodes, result[i].nodes.weights(c.weightFunc), c.hrwSeedHash) + } + } + + return result +} diff --git a/pkg/sdk/netmap/selector_test.go b/pkg/sdk/netmap/selector_test.go new file mode 100644 index 000000000..dcacb01f8 --- /dev/null +++ b/pkg/sdk/netmap/selector_test.go @@ -0,0 +1,508 @@ +package netmap + +import ( + "crypto/rand" + "encoding/binary" + "fmt" + mrand "math/rand" + "sort" + "strconv" + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/netmap" + "git.frostfs.info/TrueCloudLab/hrw" + "github.com/stretchr/testify/require" +) + +func BenchmarkHRWSort(b *testing.B) { + const netmapSize = 1000 + + vectors := make([]nodes, netmapSize) + weights := make([]float64, netmapSize) + for i := range vectors { + key := make([]byte, 33) + rand.Read(key) + + var node NodeInfo + node.SetPrice(1) + node.SetCapacity(100) + node.SetPublicKey(key) + + vectors[i] = nodes{node} + weights[i] = float64(mrand.Uint32()%10) / 10.0 + } + + pivot := mrand.Uint64() + b.Run("sort by index, no weight", func(b *testing.B) { + realNodes := make([]nodes, netmapSize) + b.ResetTimer() + for i := 0; i < b.N; i++ { + b.StopTimer() + copy(realNodes, vectors) + b.StartTimer() + + hrw.SortSliceByIndex(realNodes, pivot) + } + }) + b.Run("sort by value, no weight", func(b *testing.B) { + realNodes := make([]nodes, netmapSize) + b.ResetTimer() + for i := 0; i < b.N; i++ { + b.StopTimer() + copy(realNodes, vectors) + b.StartTimer() + + hrw.SortHasherSliceByValue(realNodes, pivot) + } + }) + b.Run("only sort by index", func(b *testing.B) { + realNodes := make([]nodes, netmapSize) + b.ResetTimer() + for i := 0; i < b.N; i++ { + b.StopTimer() + copy(realNodes, vectors) + b.StartTimer() + + hrw.SortSliceByWeightIndex(realNodes, weights, pivot) + } + }) + b.Run("sort by value", func(b *testing.B) { + realNodes := make([]nodes, netmapSize) + b.ResetTimer() + for i := 0; i < b.N; i++ { + b.StopTimer() + copy(realNodes, vectors) + b.StartTimer() + + hrw.SortHasherSliceByWeightValue(realNodes, weights, pivot) + } + }) + b.Run("sort by ID, then by index (deterministic)", func(b *testing.B) { + realNodes := make([]nodes, netmapSize) + b.ResetTimer() + for i := 0; i < b.N; i++ { + b.StopTimer() + copy(realNodes, vectors) + b.StartTimer() + + sort.Slice(vectors, func(i, j int) bool { + return less(vectors[i][0], vectors[j][0]) + }) + hrw.SortSliceByWeightIndex(realNodes, weights, pivot) + } + }) +} + +func BenchmarkPolicyHRWType(b *testing.B) { + const netmapSize = 100 + + p := newPlacementPolicy(1, + []ReplicaDescriptor{ + newReplica(1, "loc1"), + newReplica(1, "loc2"), + }, + []Selector{ + newSelector("loc1", "Location", 1, "loc1", (*Selector).SelectSame), + newSelector("loc2", "Location", 1, "loc2", (*Selector).SelectSame), + }, + []Filter{ + newFilter("loc1", "Location", "Shanghai", netmap.EQ), + newFilter("loc2", "Location", "Shanghai", netmap.NE), + }) + + nodes := make([]NodeInfo, netmapSize) + for i := range nodes { + var loc string + switch i % 20 { + case 0: + loc = "Shanghai" + default: + loc = strconv.Itoa(i % 20) + } + + // Having the same price and capacity ensures equal weights for all nodes. + // This way placement is more dependent on the initial order. + nodes[i] = nodeInfoFromAttributes("Location", loc, "Price", "1", "Capacity", "10") + pub := make([]byte, 33) + pub[0] = byte(i) + nodes[i].SetPublicKey(pub) + } + + var nm NetMap + nm.SetNodes(nodes) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + _, err := nm.ContainerNodes(p, []byte{1}) + if err != nil { + b.Fatal() + } + } +} + +func TestPlacementPolicy_DeterministicOrder(t *testing.T) { + const netmapSize = 100 + + p := newPlacementPolicy(1, + []ReplicaDescriptor{ + newReplica(1, "loc1"), + newReplica(1, "loc2"), + }, + []Selector{ + newSelector("loc1", "Location", 1, "loc1", (*Selector).SelectSame), + newSelector("loc2", "Location", 1, "loc2", (*Selector).SelectSame), + }, + []Filter{ + newFilter("loc1", "Location", "Shanghai", netmap.EQ), + newFilter("loc2", "Location", "Shanghai", netmap.NE), + }) + + nodeList := make([]NodeInfo, netmapSize) + for i := range nodeList { + var loc string + switch i % 20 { + case 0: + loc = "Shanghai" + default: + loc = strconv.Itoa(i % 20) + } + + // Having the same price and capacity ensures equal weights for all nodes. + // This way placement is more dependent on the initial order. + nodeList[i] = nodeInfoFromAttributes("Location", loc, "Price", "1", "Capacity", "10") + pub := make([]byte, 33) + pub[0] = byte(i) + nodeList[i].SetPublicKey(pub) + } + + var nm NetMap + nm.SetNodes(nodeList) + + getIndices := func(t *testing.T) (uint64, uint64) { + v, err := nm.ContainerNodes(p, []byte{1}) + require.NoError(t, err) + + nss := make([]nodes, len(v)) + for i := range v { + nss[i] = v[i] + } + + ns := flattenNodes(nss) + require.Equal(t, 2, len(ns)) + return ns[0].Hash(), ns[1].Hash() + } + + a, b := getIndices(t) + for i := 0; i < 10; i++ { + x, y := getIndices(t) + require.Equal(t, a, x) + require.Equal(t, b, y) + } +} + +func TestPlacementPolicy_ProcessSelectors(t *testing.T) { + p := newPlacementPolicy(2, nil, + []Selector{ + newSelector("SameRU", "City", 2, "FromRU", (*Selector).SelectSame), + newSelector("DistinctRU", "City", 2, "FromRU", (*Selector).SelectDistinct), + newSelector("Good", "Country", 2, "Good", (*Selector).SelectDistinct), + newSelector("Main", "Country", 3, "*", (*Selector).SelectDistinct), + }, + []Filter{ + newFilter("FromRU", "Country", "Russia", netmap.EQ), + newFilter("Good", "Rating", "4", netmap.GE), + }) + nodes := []NodeInfo{ + nodeInfoFromAttributes("Country", "Russia", "Rating", "1", "City", "SPB"), + nodeInfoFromAttributes("Country", "Germany", "Rating", "5", "City", "Berlin"), + nodeInfoFromAttributes("Country", "Russia", "Rating", "6", "City", "Moscow"), + nodeInfoFromAttributes("Country", "France", "Rating", "4", "City", "Paris"), + nodeInfoFromAttributes("Country", "France", "Rating", "1", "City", "Lyon"), + nodeInfoFromAttributes("Country", "Russia", "Rating", "5", "City", "SPB"), + nodeInfoFromAttributes("Country", "Russia", "Rating", "7", "City", "Moscow"), + nodeInfoFromAttributes("Country", "Germany", "Rating", "3", "City", "Darmstadt"), + nodeInfoFromAttributes("Country", "Germany", "Rating", "7", "City", "Frankfurt"), + nodeInfoFromAttributes("Country", "Russia", "Rating", "9", "City", "SPB"), + nodeInfoFromAttributes("Country", "Russia", "Rating", "9", "City", "SPB"), + } + + var nm NetMap + nm.SetNodes(nodes) + c := newContext(nm) + c.setCBF(p.backupFactor) + require.NoError(t, c.processFilters(p)) + require.NoError(t, c.processSelectors(p)) + + for _, s := range p.selectors { + sel := c.selections[s.GetName()] + s := c.processedSelectors[s.GetName()] + bucketCount, nodesInBucket := calcNodesCount(*s) + nodesInBucket *= int(c.cbf) + targ := fmt.Sprintf("selector '%s'", s.GetName()) + require.Equal(t, bucketCount, len(sel), targ) + fName := s.GetFilter() + for _, res := range sel { + require.Equal(t, nodesInBucket, len(res), targ) + for j := range res { + require.True(t, fName == mainFilterName || c.match(c.processedFilters[fName], res[j]), targ) + } + } + } +} + +func TestPlacementPolicy_Unique(t *testing.T) { + p := newPlacementPolicy(2, + []ReplicaDescriptor{ + newReplica(1, "S"), + newReplica(1, "S"), + }, + []Selector{ + newSelector("S", "City", 1, "*", (*Selector).SelectSame), + }, + []Filter{}) + p.unique = true + + var nodes []NodeInfo + for i, city := range []string{"Moscow", "Berlin", "Shenzhen"} { + for j := 0; j < 3; j++ { + node := nodeInfoFromAttributes("City", city) + node.SetPublicKey(binary.BigEndian.AppendUint16(nil, uint16(i*4+j))) + nodes = append(nodes, node) + } + } + + var nm NetMap + nm.SetNodes(nodes) + + v, err := nm.ContainerNodes(p, nil) + require.NoError(t, err) + for i, vi := range v { + for _, ni := range vi { + for j := 0; j < i; j++ { + for _, nj := range v[j] { + require.NotEqual(t, ni.hash, nj.hash) + } + } + } + } +} + +func TestPlacementPolicy_SingleOmitNames(t *testing.T) { + nodes := []NodeInfo{ + nodeInfoFromAttributes("ID", "1", "Country", "Russia", "City", "SPB"), + nodeInfoFromAttributes("ID", "2", "Country", "Germany", "City", "Berlin"), + nodeInfoFromAttributes("ID", "3", "Country", "Russia", "City", "Moscow"), + nodeInfoFromAttributes("ID", "4", "Country", "France", "City", "Paris"), + nodeInfoFromAttributes("ID", "5", "Country", "France", "City", "Lyon"), + nodeInfoFromAttributes("ID", "6", "Country", "Russia", "City", "SPB"), + nodeInfoFromAttributes("ID", "7", "Country", "Russia", "City", "Moscow"), + nodeInfoFromAttributes("ID", "8", "Country", "Germany", "City", "Darmstadt"), + nodeInfoFromAttributes("ID", "9", "Country", "Germany", "City", "Frankfurt"), + nodeInfoFromAttributes("ID", "10", "Country", "Russia", "City", "SPB"), + nodeInfoFromAttributes("ID", "11", "Country", "Russia", "City", "Moscow"), + nodeInfoFromAttributes("ID", "12", "Country", "Germany", "City", "London"), + } + for i := range nodes { + pub := make([]byte, 33) + rand.Read(pub) + nodes[i].SetPublicKey(pub) + } + + var nm NetMap + nm.SetNodes(nodes) + + for _, unique := range []bool{false, true} { + t.Run(fmt.Sprintf("unique=%t", unique), func(t *testing.T) { + ssNamed := []Selector{newSelector("X", "City", 2, "FromRU", (*Selector).SelectDistinct)} + fsNamed := []Filter{newFilter("FromRU", "Country", "Russia", netmap.EQ)} + rsNamed := []ReplicaDescriptor{newReplica(1, "X")} + pNamed := newPlacementPolicy(3, rsNamed, ssNamed, fsNamed) + pNamed.unique = unique + + vNamed, err := nm.ContainerNodes(pNamed, []byte{1}) + require.NoError(t, err) + + ssUnnamed := []Selector{newSelector("", "City", 2, "FromRU", (*Selector).SelectDistinct)} + fsUnnamed := []Filter{newFilter("FromRU", "Country", "Russia", netmap.EQ)} + rsUnnamed := []ReplicaDescriptor{newReplica(1, "")} + pUnnamed := newPlacementPolicy(3, rsUnnamed, ssUnnamed, fsUnnamed) + pUnnamed.unique = unique + + vUnnamed, err := nm.ContainerNodes(pUnnamed, []byte{1}) + require.NoError(t, err) + + require.Equal(t, vNamed, vUnnamed) + }) + } +} + +func TestPlacementPolicy_MultiREP(t *testing.T) { + nodes := []NodeInfo{ + nodeInfoFromAttributes("ID", "1", "Country", "Russia", "City", "SPB"), + nodeInfoFromAttributes("ID", "2", "Country", "Germany", "City", "Berlin"), + nodeInfoFromAttributes("ID", "3", "Country", "Russia", "City", "Moscow"), + nodeInfoFromAttributes("ID", "4", "Country", "France", "City", "Paris"), + nodeInfoFromAttributes("ID", "5", "Country", "France", "City", "Lyon"), + nodeInfoFromAttributes("ID", "6", "Country", "Russia", "City", "SPB"), + nodeInfoFromAttributes("ID", "7", "Country", "Russia", "City", "Moscow"), + nodeInfoFromAttributes("ID", "8", "Country", "Germany", "City", "Darmstadt"), + nodeInfoFromAttributes("ID", "9", "Country", "Germany", "City", "Frankfurt"), + nodeInfoFromAttributes("ID", "10", "Country", "Russia", "City", "SPB"), + nodeInfoFromAttributes("ID", "11", "Country", "Russia", "City", "Moscow"), + nodeInfoFromAttributes("ID", "12", "Country", "Germany", "City", "London"), + } + for i := range nodes { + pub := make([]byte, 33) + rand.Read(pub) + nodes[i].SetPublicKey(pub) + } + + var nm NetMap + nm.SetNodes(nodes) + + ss := []Selector{newSelector("SameRU", "City", 2, "FromRU", (*Selector).SelectDistinct)} + fs := []Filter{newFilter("FromRU", "Country", "Russia", netmap.EQ)} + + for _, unique := range []bool{false, true} { + for _, additional := range []int{0, 1, 2} { + t.Run(fmt.Sprintf("unique=%t, additional=%d", unique, additional), func(t *testing.T) { + rs := []ReplicaDescriptor{newReplica(1, "SameRU")} + for i := 0; i < additional; i++ { + rs = append(rs, newReplica(1, "")) + } + + p := newPlacementPolicy(3, rs, ss, fs) + p.unique = unique + + v, err := nm.ContainerNodes(p, []byte{1}) + require.NoError(t, err) + require.Equal(t, 1+additional, len(v)) + require.Equal(t, 6, len(v[0])) + + for i := 1; i < additional; i++ { + require.Equal(t, 3, len(v[i])) + if !unique { + require.Equal(t, v[1], v[i]) + } + } + + if unique { + seen := make(map[string]bool) + for i := range v { + for j := range v[i] { + attr := v[i][j].Attribute("ID") + require.NotEmpty(t, attr) + require.False(t, seen[attr]) + + seen[attr] = true + } + } + } + }) + } + } +} + +func TestPlacementPolicy_ProcessSelectorsExceptForNodes(t *testing.T) { + p := newPlacementPolicy(1, nil, + []Selector{ + newSelector("ExceptRU", "City", 2, "ExceptRU", (*Selector).SelectSame), + }, + []Filter{ + newFilter("ExceptRU", "", "", netmap.NOT, + newFilter("", "", "", netmap.AND, + newFilter("", "City", "Lyon", netmap.EQ), + newFilter("", "Rating", "10", netmap.LE), + ), + ), + }) + nodes := []NodeInfo{ + nodeInfoFromAttributes("Country", "Germany", "Rating", "1", "City", "Berlin"), + nodeInfoFromAttributes("Country", "Germany", "Rating", "5", "City", "Berlin"), + nodeInfoFromAttributes("Country", "Russia", "Rating", "6", "City", "Moscow"), + nodeInfoFromAttributes("Country", "France", "Rating", "4", "City", "Paris"), + nodeInfoFromAttributes("Country", "France", "Rating", "1", "City", "Lyon"), + nodeInfoFromAttributes("Country", "France", "Rating", "5", "City", "Lyon"), + nodeInfoFromAttributes("Country", "Russia", "Rating", "7", "City", "Moscow"), + nodeInfoFromAttributes("Country", "Germany", "Rating", "3", "City", "Darmstadt"), + nodeInfoFromAttributes("Country", "Germany", "Rating", "7", "City", "Frankfurt"), + nodeInfoFromAttributes("Country", "Russia", "Rating", "9", "City", "SPB"), + nodeInfoFromAttributes("Country", "Russia", "Rating", "9", "City", "SPB"), + } + + var nm NetMap + nm.SetNodes(nodes) + c := newContext(nm) + c.setCBF(p.backupFactor) + require.NoError(t, c.processFilters(p)) + require.NoError(t, c.processSelectors(p)) + + for _, s := range p.selectors { + sel := c.selections[s.GetName()] + s := c.processedSelectors[s.GetName()] + bucketCount, nodesInBucket := calcNodesCount(*s) + nodesInBucket *= int(c.cbf) + targ := fmt.Sprintf("selector '%s'", s.GetName()) + require.Equal(t, bucketCount, len(sel), targ) + fName := s.GetFilter() + for _, res := range sel { + require.Equal(t, nodesInBucket, len(res), targ) + for j := range res { + require.True(t, fName == mainFilterName || c.match(c.processedFilters[fName], res[j]), targ) + } + } + } +} + +func TestSelector_SetName(t *testing.T) { + const name = "some name" + var s Selector + + require.Zero(t, s.m.GetName()) + + s.SetName(name) + require.Equal(t, name, s.m.GetName()) +} + +func TestSelector_SetNumberOfNodes(t *testing.T) { + const num = 3 + var s Selector + + require.Zero(t, s.m.GetCount()) + + s.SetNumberOfNodes(num) + + require.EqualValues(t, num, s.m.GetCount()) +} + +func TestSelectorClauses(t *testing.T) { + var s Selector + + require.Equal(t, netmap.UnspecifiedClause, s.m.GetClause()) + + s.SelectDistinct() + require.Equal(t, netmap.Distinct, s.m.GetClause()) + + s.SelectSame() + require.Equal(t, netmap.Same, s.m.GetClause()) +} + +func TestSelector_SelectByBucketAttribute(t *testing.T) { + const attr = "some attribute" + var s Selector + + require.Zero(t, s.m.GetAttribute()) + + s.SelectByBucketAttribute(attr) + require.Equal(t, attr, s.m.GetAttribute()) +} + +func TestSelector_SetFilterName(t *testing.T) { + const fName = "some filter" + var s Selector + + require.Zero(t, s.m.GetFilter()) + + s.SetFilterName(fName) + require.Equal(t, fName, s.m.GetFilter()) +} diff --git a/pkg/sdk/netmap/test/generate.go b/pkg/sdk/netmap/test/generate.go new file mode 100644 index 000000000..6ebce67e4 --- /dev/null +++ b/pkg/sdk/netmap/test/generate.go @@ -0,0 +1,79 @@ +package netmaptest + +import ( + "crypto/rand" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" +) + +func filter(withInner bool) (x netmap.Filter) { + x.SetName("name") + if withInner { + x.LogicalOR(filter(false), filter(false)) + } else { + x.NumericGE("epoch", 13) + } + + return x +} + +// Filter returns random netmap.Filter. +func Filter() netmap.Filter { + return filter(true) +} + +// Replica returns random netmap.ReplicaDescriptor. +func Replica() (x netmap.ReplicaDescriptor) { + x.SetNumberOfObjects(666) + x.SetSelectorName("selector") + + return +} + +// Selector returns random netmap.Selector. +func Selector() (x netmap.Selector) { + x.SetNumberOfNodes(11) + x.SetName("name") + x.SetFilterName("filter") + x.SelectByBucketAttribute("attribute") + x.SelectDistinct() + + return +} + +// PlacementPolicy returns random netmap.PlacementPolicy. +func PlacementPolicy() (p netmap.PlacementPolicy) { + p.SetContainerBackupFactor(9) + p.AddFilters(Filter(), Filter()) + p.AddReplicas(Replica(), Replica()) + p.AddSelectors(Selector(), Selector()) + + return +} + +// NetworkInfo returns random netmap.NetworkInfo. +func NetworkInfo() (x netmap.NetworkInfo) { + x.SetCurrentEpoch(21) + x.SetMagicNumber(32) + x.SetMsPerBlock(43) + x.SetAuditFee(1) + x.SetStoragePrice(2) + x.SetContainerFee(3) + x.SetEpochDuration(6) + x.SetIRCandidateFee(7) + x.SetMaxObjectSize(8) + x.SetWithdrawalFee(9) + + return +} + +// NodeInfo returns random netmap.NodeInfo. +func NodeInfo() (x netmap.NodeInfo) { + key := make([]byte, 33) + _, _ = rand.Read(key) + + x.SetPublicKey(key) + x.SetNetworkEndpoints("1", "2", "3") + + return +} diff --git a/pkg/sdk/netmap/yml_test.go b/pkg/sdk/netmap/yml_test.go new file mode 100644 index 000000000..a744a01a1 --- /dev/null +++ b/pkg/sdk/netmap/yml_test.go @@ -0,0 +1,182 @@ +package netmap + +import ( + "encoding/base64" + "encoding/json" + "fmt" + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/require" + "gopkg.in/yaml.v3" +) + +// TestCase represents collection of placement policy tests for a single node set. +type TestCase struct { + Name string `json:"name" yaml:"name"` + Nodes []NodeInfo `json:"nodes" yaml:"nodes"` + Tests map[string]struct { + Policy PlacementPolicy + Pivot Base64 + Result [][]int `json:"result,omitempty" yaml:"result,omitempty"` + Error string `json:"error,omitempty" yaml:"error,omitempty"` + Placement struct { + Pivot Base64 `json:"pivot" yaml:"pivot"` + Result [][]int `json:"result,omitempty" yaml:"result,omitempty"` + } `json:"placement,omitempty" yaml:"placement,omitempty"` + } +} + +// Base64 is a type that will hold the decoded Base64 data. +type Base64 []byte + +func (b *Base64) UnmarshalYAML(unmarshal func(interface{}) error) error { + var base64Str string + if err := unmarshal(&base64Str); err != nil { + return err + } + decodedBytes, err := base64.StdEncoding.DecodeString(base64Str) + if err != nil { + return err + } + *b = decodedBytes + return nil +} + +var _, _ json.Unmarshaler = new(NodeInfo), new(PlacementPolicy) + +func compareNodes(t testing.TB, expected [][]int, nodes nodes, actual [][]NodeInfo) { + require.Equal(t, len(expected), len(actual)) + for i := range expected { + require.Equal(t, len(expected[i]), len(actual[i])) + for j, index := range expected[i] { + require.Equal(t, nodes[index], actual[i][j]) + } + } +} + +func TestPlacementPolicy_Interopability(t *testing.T) { + const testsDir = "./yml_tests" + + f, err := os.Open(testsDir) + require.NoError(t, err) + + ds, err := f.ReadDir(0) + require.NoError(t, err) + + for i := range ds { + filename := filepath.Join(testsDir, ds[i].Name()) + bs, err := os.ReadFile(filename) + require.NoError(t, err) + + var tc TestCase + require.NoError(t, yaml.Unmarshal(bs, &tc), "cannot unmarshal %s", ds[i].Name()) + + srcNodes := make([]NodeInfo, len(tc.Nodes)) + copy(srcNodes, tc.Nodes) + + t.Run(fmt.Sprintf("%s:%s", filename, tc.Name), func(t *testing.T) { + var nm NetMap + nm.SetNodes(tc.Nodes) + + for name, tt := range tc.Tests { + t.Run(name, func(t *testing.T) { + v, err := nm.ContainerNodes(tt.Policy, tt.Pivot) + if tt.Result == nil { + require.Error(t, err) + require.Contains(t, err.Error(), tt.Error) + } else { + require.NoError(t, err) + require.Equal(t, srcNodes, tc.Nodes) + + compareNodes(t, tt.Result, tc.Nodes, v) + + if tt.Placement.Result != nil { + res, err := nm.PlacementVectors(v, tt.Placement.Pivot) + require.NoError(t, err) + compareNodes(t, tt.Placement.Result, tc.Nodes, res) + require.Equal(t, srcNodes, tc.Nodes) + } + } + }) + } + }) + } +} + +func BenchmarkPlacementPolicyInteropability(b *testing.B) { + const testsDir = "./yml_tests" + + f, err := os.Open(testsDir) + require.NoError(b, err) + + ds, err := f.ReadDir(0) + require.NoError(b, err) + + for i := range ds { + bs, err := os.ReadFile(filepath.Join(testsDir, ds[i].Name())) + require.NoError(b, err) + + var tc TestCase + require.NoError(b, yaml.Unmarshal(bs, &tc), "cannot unmarshal %s", ds[i].Name()) + + b.Run(tc.Name, func(b *testing.B) { + var nm NetMap + nm.SetNodes(tc.Nodes) + require.NoError(b, err) + + for name, tt := range tc.Tests { + b.Run(name, func(b *testing.B) { + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + b.StartTimer() + v, err := nm.ContainerNodes(tt.Policy, tt.Pivot) + b.StopTimer() + if tt.Result == nil { + require.Error(b, err) + require.Contains(b, err.Error(), tt.Error) + } else { + require.NoError(b, err) + + compareNodes(b, tt.Result, tc.Nodes, v) + + if tt.Placement.Result != nil { + b.StartTimer() + res, err := nm.PlacementVectors(v, tt.Placement.Pivot) + b.StopTimer() + require.NoError(b, err) + compareNodes(b, tt.Placement.Result, tc.Nodes, res) + } + } + } + }) + } + }) + } +} + +func BenchmarkManySelects(b *testing.B) { + testsFile := filepath.Join("yml_tests", "many_selects.yml") + bs, err := os.ReadFile(testsFile) + require.NoError(b, err) + + var tc TestCase + require.NoError(b, yaml.Unmarshal(bs, &tc)) + tt, ok := tc.Tests["Select"] + require.True(b, ok) + + var nm NetMap + nm.SetNodes(tc.Nodes) + + b.ResetTimer() + b.ReportAllocs() + + for i := 0; i < b.N; i++ { + _, err = nm.ContainerNodes(tt.Policy, tt.Pivot) + if err != nil { + b.FailNow() + } + } +} diff --git a/pkg/sdk/netmap/yml_tests/cbf_default.yml b/pkg/sdk/netmap/yml_tests/cbf_default.yml new file mode 100644 index 000000000..c43a7032a --- /dev/null +++ b/pkg/sdk/netmap/yml_tests/cbf_default.yml @@ -0,0 +1,48 @@ +name: default CBF is 3 +nodes: + - attributes: + - key: Location + value: Europe + - key: Country + value: RU + - key: City + value: St.Petersburg + - attributes: + - key: Location + value: Europe + - key: Country + value: RU + - key: City + value: Moscow + - attributes: + - key: Location + value: Europe + - key: Country + value: DE + - key: City + value: Berlin + - attributes: + - key: Location + value: Europe + - key: Country + value: FR + - key: City + value: Paris +tests: + set default CBF: + policy: + replicas: + - count: 1 + selector: EU + containerBackupFactor: 0 + selectors: + - name: EU + count: 1 + clause: SAME + attribute: Location + filter: '*' + filters: [] + result: + - - 0 + - 1 + - 2 diff --git a/pkg/sdk/netmap/yml_tests/cbf_minimal.yml b/pkg/sdk/netmap/yml_tests/cbf_minimal.yml new file mode 100644 index 000000000..2fe2642fd --- /dev/null +++ b/pkg/sdk/netmap/yml_tests/cbf_minimal.yml @@ -0,0 +1,52 @@ +name: Real node count multiplier is in range [1, specified CBF] +nodes: + - attributes: + - key: ID + value: '1' + - key: Country + value: DE + - attributes: + - key: ID + value: '2' + - key: Country + value: DE + - attributes: + - key: ID + value: '3' + - key: Country + value: DE +tests: + select 2, CBF is 2: + policy: + replicas: + - count: 1 + selector: X + containerBackupFactor: 2 + selectors: + - name: X + count: 2 + clause: SAME + attribute: Country + filter: '*' + filters: [] + result: + - - 0 + - 1 + - 2 + select 3, CBF is 2: + policy: + replicas: + - count: 1 + selector: X + containerBackupFactor: 2 + selectors: + - name: X + count: 3 + clause: SAME + attribute: Country + filter: '*' + filters: [] + result: + - - 0 + - 1 + - 2 diff --git a/pkg/sdk/netmap/yml_tests/cbf_requirements.yml b/pkg/sdk/netmap/yml_tests/cbf_requirements.yml new file mode 100644 index 000000000..ccd58d474 --- /dev/null +++ b/pkg/sdk/netmap/yml_tests/cbf_requirements.yml @@ -0,0 +1,82 @@ +name: CBF requirements +nodes: + - attributes: + - key: ID + value: '1' + - key: Attr + value: Same + - attributes: + - key: ID + value: '2' + - key: Attr + value: Same + - attributes: + - key: ID + value: '3' + - key: Attr + value: Same + - attributes: + - key: ID + value: '4' + - key: Attr + value: Same +tests: + default CBF, no selector: + policy: + replicas: + - count: 2 + containerBackupFactor: 0 + selectors: [] + filters: [] + result: + - - 0 + - 2 + - 1 + - 3 + explicit CBF, no selector: + policy: + replicas: + - count: 2 + containerBackupFactor: 3 + selectors: [] + filters: [] + result: + - - 0 + - 2 + - 1 + - 3 + select distinct, weak CBF: + policy: + replicas: + - count: 2 + selector: X + containerBackupFactor: 3 + selectors: + - name: X + count: 2 + clause: DISTINCT + filter: '*' + filters: [] + result: + - - 0 + - 2 + - 1 + - 3 + select same, weak CBF: + policy: + replicas: + - count: 2 + selector: X + containerBackupFactor: 3 + selectors: + - name: X + count: 2 + clause: SAME + attribute: Attr + filter: '*' + filters: [] + result: + - - 0 + - 1 + - 2 + - 3 diff --git a/pkg/sdk/netmap/yml_tests/filter_complex.yml b/pkg/sdk/netmap/yml_tests/filter_complex.yml new file mode 100644 index 000000000..a65fa17cc --- /dev/null +++ b/pkg/sdk/netmap/yml_tests/filter_complex.yml @@ -0,0 +1,210 @@ +name: compound filter +nodes: + - attributes: + - key: Storage + value: SSD + - key: Rating + value: '10' + - key: IntField + value: '100' + - key: Param + value: Value1 +tests: + good: + policy: + replicas: + - count: 1 + selector: S + containerBackupFactor: 1 + selectors: + - name: S + count: 1 + clause: DISTINCT + filter: Main + filters: + - name: StorageSSD + key: Storage + op: EQ + value: SSD + filters: [] + - name: GoodRating + key: Rating + op: GE + value: '4' + filters: [] + - name: Main + op: AND + filters: + - name: StorageSSD + op: OPERATION_UNSPECIFIED + filters: [] + - name: '' + key: IntField + op: LT + value: '123' + filters: [] + - name: GoodRating + op: OPERATION_UNSPECIFIED + filters: [] + - op: OR + filters: + - key: Param + op: EQ + value: Value1 + filters: [] + - key: Param + op: EQ + value: Value2 + filters: [] + result: + - - 0 + bad storage type: + policy: + replicas: + - count: 1 + selector: S + containerBackupFactor: 1 + selectors: + - name: S + count: 1 + clause: DISTINCT + filter: Main + filters: + - name: StorageSSD + key: Storage + op: EQ + value: HDD + filters: [] + - name: GoodRating + key: Rating + op: GE + value: '4' + filters: [] + - name: Main + op: AND + filters: + - name: StorageSSD + op: OPERATION_UNSPECIFIED + filters: [] + - name: '' + key: IntField + op: LT + value: '123' + filters: [] + - name: GoodRating + op: OPERATION_UNSPECIFIED + filters: [] + - name: '' + op: OR + filters: + - name: '' + key: Param + op: EQ + value: Value1 + filters: [] + - name: '' + key: Param + op: EQ + value: Value2 + filters: [] + error: not enough nodes + bad rating: + policy: + replicas: + - count: 1 + selector: S + containerBackupFactor: 1 + selectors: + - name: S + count: 1 + clause: DISTINCT + filter: Main + filters: + - name: StorageSSD + key: Storage + op: EQ + value: SSD + filters: [] + - name: GoodRating + key: Rating + op: GE + value: '15' + filters: [] + - name: Main + op: AND + filters: + - name: StorageSSD + op: OPERATION_UNSPECIFIED + filters: [] + - name: '' + key: IntField + op: LT + value: '123' + filters: [] + - name: GoodRating + op: OPERATION_UNSPECIFIED + filters: [] + - name: '' + op: OR + filters: + - name: '' + key: Param + op: EQ + value: Value1 + filters: [] + - name: '' + key: Param + op: EQ + value: Value2 + filters: [] + error: not enough nodes + bad param: + policy: + replicas: + - count: 1 + selector: S + containerBackupFactor: 1 + selectors: + - name: S + count: 1 + clause: DISTINCT + filter: Main + filters: + - name: StorageSSD + key: Storage + op: EQ + value: SSD + filters: [] + - name: GoodRating + key: Rating + op: GE + value: '4' + filters: [] + - name: Main + op: AND + filters: + - name: StorageSSD + op: OPERATION_UNSPECIFIED + filters: [] + - name: '' + key: IntField + op: LT + value: '123' + filters: [] + - name: GoodRating + op: OPERATION_UNSPECIFIED + filters: [] + - name: '' + op: OR + filters: + - name: '' + key: Param + op: EQ + value: Value0 + filters: [] + - name: '' + key: Param + op: EQ + value: Value2 + filters: [] + error: not enough nodes diff --git a/pkg/sdk/netmap/yml_tests/filter_invalid_integer.yml b/pkg/sdk/netmap/yml_tests/filter_invalid_integer.yml new file mode 100644 index 000000000..e65ab24da --- /dev/null +++ b/pkg/sdk/netmap/yml_tests/filter_invalid_integer.yml @@ -0,0 +1,45 @@ +name: invalid integer field +nodes: + - attributes: + - key: IntegerField + value: 'true' + - attributes: + - key: IntegerField + value: str +tests: + empty string is not casted to 0: + policy: + replicas: + - count: 1 + selector: S + containerBackupFactor: 1 + selectors: + - name: S + count: 1 + clause: DISTINCT + filter: Main + filters: + - name: Main + key: IntegerField + op: LE + value: '8' + filters: [] + error: not enough nodes + non-empty string is not casted to a number: + policy: + replicas: + - count: 1 + selector: S + containerBackupFactor: 1 + selectors: + - name: S + count: 1 + clause: DISTINCT + filter: Main + filters: + - name: Main + key: IntegerField + op: GE + value: '0' + filters: [] + error: not enough nodes diff --git a/pkg/sdk/netmap/yml_tests/filter_simple.yml b/pkg/sdk/netmap/yml_tests/filter_simple.yml new file mode 100644 index 000000000..a24814a49 --- /dev/null +++ b/pkg/sdk/netmap/yml_tests/filter_simple.yml @@ -0,0 +1,230 @@ +name: single-op filters +nodes: + - attributes: + - key: Rating + value: '4' + - key: Country + value: Germany +tests: + GE true: + policy: + replicas: + - count: 1 + selector: S + containerBackupFactor: 1 + selectors: + - name: S + count: 1 + clause: DISTINCT + filter: Main + filters: + - name: Main + key: Rating + op: GE + value: '4' + filters: [] + result: + - - 0 + GE false: + policy: + replicas: + - count: 1 + selector: S + containerBackupFactor: 1 + selectors: + - name: S + count: 1 + clause: DISTINCT + filter: Main + filters: + - name: Main + key: Rating + op: GE + value: '5' + filters: [] + error: not enough nodes + GT true: + policy: + replicas: + - count: 1 + selector: S + containerBackupFactor: 1 + selectors: + - name: S + count: 1 + clause: DISTINCT + filter: Main + filters: + - name: Main + key: Rating + op: GT + value: '3' + filters: [] + result: + - - 0 + GT false: + policy: + replicas: + - count: 1 + selector: S + containerBackupFactor: 1 + selectors: + - name: S + count: 1 + clause: DISTINCT + filter: Main + filters: + - name: Main + key: Rating + op: GT + value: '4' + filters: [] + error: not enough nodes + LE true: + policy: + replicas: + - count: 1 + selector: S + containerBackupFactor: 1 + selectors: + - name: S + count: 1 + clause: DISTINCT + filter: Main + filters: + - name: Main + key: Rating + op: LE + value: '4' + filters: [] + result: + - - 0 + LE false: + policy: + replicas: + - count: 1 + selector: S + containerBackupFactor: 1 + selectors: + - name: S + count: 1 + clause: DISTINCT + filter: Main + filters: + - name: Main + key: Rating + op: LE + value: '3' + filters: [] + error: not enough nodes + LT true: + policy: + replicas: + - count: 1 + selector: S + containerBackupFactor: 1 + selectors: + - name: S + count: 1 + clause: DISTINCT + filter: Main + filters: + - name: Main + key: Rating + op: LT + value: '5' + filters: [] + result: + - - 0 + LT false: + policy: + replicas: + - count: 1 + selector: S + containerBackupFactor: 1 + selectors: + - name: S + count: 1 + clause: DISTINCT + filter: Main + filters: + - name: Main + key: Rating + op: LT + value: '4' + filters: [] + error: not enough nodes + EQ true: + policy: + replicas: + - count: 1 + selector: S + containerBackupFactor: 1 + selectors: + - name: S + count: 1 + clause: DISTINCT + filter: Main + filters: + - name: Main + key: Country + op: EQ + value: Germany + filters: [] + result: + - - 0 + EQ false: + policy: + replicas: + - count: 1 + selector: S + containerBackupFactor: 1 + selectors: + - name: S + count: 1 + clause: DISTINCT + filter: Main + filters: + - name: Main + key: Country + op: EQ + value: China + filters: [] + error: not enough nodes + NE true: + policy: + replicas: + - count: 1 + selector: S + containerBackupFactor: 1 + selectors: + - name: S + count: 1 + clause: DISTINCT + filter: Main + filters: + - name: Main + key: Country + op: NE + value: France + filters: [] + result: + - - 0 + NE false: + policy: + replicas: + - count: 1 + selector: S + containerBackupFactor: 1 + selectors: + - name: S + count: 1 + clause: DISTINCT + filter: Main + filters: + - name: Main + key: Country + op: NE + value: Germany + filters: [] + error: not enough nodes diff --git a/pkg/sdk/netmap/yml_tests/hrw_sort.yml b/pkg/sdk/netmap/yml_tests/hrw_sort.yml new file mode 100644 index 000000000..c84f7c948 --- /dev/null +++ b/pkg/sdk/netmap/yml_tests/hrw_sort.yml @@ -0,0 +1,118 @@ +name: HRW ordering +nodes: + - attributes: + - key: Country + value: Germany + - key: Price + value: '2' + - key: Capacity + value: '10000' + - attributes: + - key: Country + value: Germany + - key: Price + value: '4' + - key: Capacity + value: '1' + - attributes: + - key: Country + value: France + - key: Price + value: '3' + - key: Capacity + value: '10' + - attributes: + - key: Country + value: Russia + - key: Price + value: '2' + - key: Capacity + value: '10000' + - attributes: + - key: Country + value: Russia + - key: Price + value: '1' + - key: Capacity + value: '10000' + - attributes: + - key: Country + value: Russia + - key: Capacity + value: '10000' + - attributes: + - key: Country + value: France + - key: Price + value: '100' + - key: Capacity + value: '1' + - attributes: + - key: Country + value: France + - key: Price + value: '7' + - key: Capacity + value: '10000' + - attributes: + - key: Country + value: Russia + - key: Price + value: '2' + - key: Capacity + value: '1' +tests: + select 3 nodes in 3 distinct countries, same placement: + policy: + replicas: + - count: 1 + selector: Main + containerBackupFactor: 1 + selectors: + - name: Main + count: 3 + clause: DISTINCT + attribute: Country + filter: '*' + filters: [] + pivot: Y29udGFpbmVySUQ= + result: + - - 5 + - 0 + - 7 + placement: + pivot: b2JqZWN0SUQ= + result: + - - 5 + - 0 + - 7 + select 6 nodes in 3 distinct countries, different placement: + policy: + replicas: + - count: 1 + selector: Main + containerBackupFactor: 2 + selectors: + - name: Main + count: 3 + clause: DISTINCT + attribute: Country + filter: '*' + filters: [] + pivot: Y29udGFpbmVySUQ= + result: + - - 5 + - 4 + - 0 + - 1 + - 7 + - 2 + placement: + pivot: b2JqZWN0SUQ= + result: + - - 5 + - 4 + - 0 + - 7 + - 2 + - 1 diff --git a/pkg/sdk/netmap/yml_tests/issue213.yml b/pkg/sdk/netmap/yml_tests/issue213.yml new file mode 100644 index 000000000..8e8aea420 --- /dev/null +++ b/pkg/sdk/netmap/yml_tests/issue213.yml @@ -0,0 +1,52 @@ +name: unnamed selector (nspcc-dev/neofs-api-go#213) +nodes: + - attributes: + - key: Location + value: Europe + - key: Country + value: Russia + - key: City + value: Moscow + - attributes: + - key: Location + value: Europe + - key: Country + value: Russia + - key: City + value: Saint-Petersburg + - attributes: + - key: Location + value: Europe + - key: Country + value: Sweden + - key: City + value: Stockholm + - attributes: + - key: Location + value: Europe + - key: Country + value: Finalnd + - key: City + value: Helsinki +tests: + test: + policy: + replicas: + - count: 4 + containerBackupFactor: 1 + selectors: + - name: '' + count: 4 + clause: DISTINCT + filter: LOC_EU + filters: + - name: LOC_EU + key: Location + op: EQ + value: Europe + filters: [] + result: + - - 0 + - 1 + - 2 + - 3 diff --git a/pkg/sdk/netmap/yml_tests/many_selects.yml b/pkg/sdk/netmap/yml_tests/many_selects.yml new file mode 100644 index 000000000..29efd4337 --- /dev/null +++ b/pkg/sdk/netmap/yml_tests/many_selects.yml @@ -0,0 +1,141 @@ +name: single-op filters +nodes: + - attributes: + - key: Country + value: Russia + - key: Rating + value: '1' + - key: City + value: SPB + - attributes: + - key: Country + value: Germany + - key: Rating + value: '5' + - key: City + value: Berlin + - attributes: + - key: Country + value: Russia + - key: Rating + value: '6' + - key: City + value: Moscow + - attributes: + - key: Country + value: France + - key: Rating + value: '4' + - key: City + value: Paris + - attributes: + - key: Country + value: France + - key: Rating + value: '1' + - key: City + value: Lyon + - attributes: + - key: Country + value: Russia + - key: Rating + value: '5' + - key: City + value: SPB + - attributes: + - key: Country + value: Russia + - key: Rating + value: '7' + - key: City + value: Moscow + - attributes: + - key: Country + value: Germany + - key: Rating + value: '3' + - key: City + value: Darmstadt + - attributes: + - key: Country + value: Germany + - key: Rating + value: '7' + - key: City + value: Frankfurt + - attributes: + - key: Country + value: Russia + - key: Rating + value: '9' + - key: City + value: SPB + - attributes: + - key: Country + value: Russia + - key: Rating + value: '9' + - key: City + value: SPB +tests: + Select: + policy: + replicas: + - count: 1 + selector: SameRU + - count: 1 + selector: DistinctRU + - count: 1 + selector: Good + - count: 1 + selector: Main + containerBackupFactor: 2 + selectors: + - name: SameRU + count: 2 + clause: SAME + attribute: City + filter: FromRU + - name: DistinctRU + count: 2 + clause: DISTINCT + attribute: City + filter: FromRU + - name: Good + count: 2 + clause: DISTINCT + attribute: Country + filter: Good + - name: Main + count: 3 + clause: DISTINCT + attribute: Country + filter: '*' + filters: + - name: FromRU + key: Country + op: EQ + value: Russia + - name: Good + key: Rating + op: GE + value: '4' + result: + - - 0 + - 5 + - 9 + - 10 + - - 2 + - 6 + - 0 + - 5 + - - 1 + - 8 + - 2 + - 5 + - - 3 + - 4 + - 1 + - 7 + - 0 + - 2 diff --git a/pkg/sdk/netmap/yml_tests/multiple_rep.yml b/pkg/sdk/netmap/yml_tests/multiple_rep.yml new file mode 100644 index 000000000..448214f55 --- /dev/null +++ b/pkg/sdk/netmap/yml_tests/multiple_rep.yml @@ -0,0 +1,46 @@ +name: multiple replicas (#215) +nodes: + - attributes: + - key: City + value: Saint-Petersburg + - attributes: + - key: City + value: Moscow + - attributes: + - key: City + value: Berlin + - attributes: + - key: City + value: Paris +tests: + test: + policy: + replicas: + - count: 1 + selector: LOC_SPB_PLACE + - count: 1 + selector: LOC_MSK_PLACE + containerBackupFactor: 1 + selectors: + - name: LOC_SPB_PLACE + count: 1 + clause: CLAUSE_UNSPECIFIED + filter: LOC_SPB + - name: LOC_MSK_PLACE + count: 1 + clause: CLAUSE_UNSPECIFIED + filter: LOC_MSK + filters: + - name: LOC_SPB + key: City + op: EQ + value: Saint-Petersburg + filters: [] + - name: LOC_MSK + key: City + op: EQ + value: Moscow + filters: [] + result: + - - 0 + - - 1 diff --git a/pkg/sdk/netmap/yml_tests/multiple_rep_asymmetric.yml b/pkg/sdk/netmap/yml_tests/multiple_rep_asymmetric.yml new file mode 100644 index 000000000..61f8f7624 --- /dev/null +++ b/pkg/sdk/netmap/yml_tests/multiple_rep_asymmetric.yml @@ -0,0 +1,162 @@ +name: multiple REP, asymmetric +nodes: + - attributes: + - key: ID + value: '1' + - key: Country + value: RU + - key: City + value: St.Petersburg + - key: SSD + value: '0' + - attributes: + - key: ID + value: '2' + - key: Country + value: RU + - key: City + value: St.Petersburg + - key: SSD + value: '1' + - attributes: + - key: ID + value: '3' + - key: Country + value: RU + - key: City + value: Moscow + - key: SSD + value: '1' + - attributes: + - key: ID + value: '4' + - key: Country + value: RU + - key: City + value: Moscow + - key: SSD + value: '1' + - attributes: + - key: ID + value: '5' + - key: Country + value: RU + - key: City + value: St.Petersburg + - key: SSD + value: '1' + - attributes: + - key: ID + value: '6' + - key: Continent + value: NA + - key: City + value: NewYork + - attributes: + - key: ID + value: '7' + - key: Continent + value: AF + - key: City + value: Cairo + - attributes: + - key: ID + value: '8' + - key: Continent + value: AF + - key: City + value: Cairo + - attributes: + - key: ID + value: '9' + - key: Continent + value: SA + - key: City + value: Lima + - attributes: + - key: ID + value: '10' + - key: Continent + value: AF + - key: City + value: Cairo + - attributes: + - key: ID + value: '11' + - key: Continent + value: NA + - key: City + value: NewYork + - attributes: + - key: ID + value: '12' + - key: Continent + value: NA + - key: City + value: LosAngeles + - attributes: + - key: ID + value: '13' + - key: Continent + value: SA + - key: City + value: Lima +tests: + test: + policy: + replicas: + - count: 1 + selector: SPB + - count: 2 + selector: Americas + containerBackupFactor: 2 + selectors: + - name: SPB + count: 1 + clause: SAME + attribute: City + filter: SPBSSD + - name: Americas + count: 2 + clause: DISTINCT + attribute: City + filter: Americas + filters: + - name: SPBSSD + op: AND + filters: + - name: '' + key: Country + op: EQ + value: RU + filters: [] + - name: '' + key: City + op: EQ + value: St.Petersburg + filters: [] + - name: '' + key: SSD + op: EQ + value: '1' + filters: [] + - name: Americas + op: OR + filters: + - name: '' + key: Continent + op: EQ + value: NA + filters: [] + - name: '' + key: Continent + op: EQ + value: SA + filters: [] + result: + - - 1 + - 4 + - - 8 + - 12 + - 5 + - 10 diff --git a/pkg/sdk/netmap/yml_tests/non_strict.yml b/pkg/sdk/netmap/yml_tests/non_strict.yml new file mode 100644 index 000000000..a01986d6f --- /dev/null +++ b/pkg/sdk/netmap/yml_tests/non_strict.yml @@ -0,0 +1,52 @@ +name: non-strict selections +comment: These test specify loose selection behaviour, to allow fetching already PUT + objects even when there is not enough nodes to select from. +nodes: + - attributes: + - key: Country + value: Russia + - attributes: + - key: Country + value: Germany + - attributes: [] +tests: + not enough nodes (backup factor): + policy: + replicas: + - count: 1 + selector: MyStore + containerBackupFactor: 2 + selectors: + - name: MyStore + count: 2 + clause: DISTINCT + attribute: Country + filter: FromRU + filters: + - name: FromRU + key: Country + op: EQ + value: Russia + filters: [] + result: + - - 0 + not enough nodes (buckets): + policy: + replicas: + - count: 1 + selector: MyStore + containerBackupFactor: 1 + selectors: + - name: MyStore + count: 2 + clause: DISTINCT + attribute: Country + filter: FromRU + filters: + - name: FromRU + key: Country + op: EQ + value: Russia + filters: [] + result: + - - 0 diff --git a/pkg/sdk/netmap/yml_tests/rep_only.yml b/pkg/sdk/netmap/yml_tests/rep_only.yml new file mode 100644 index 000000000..80bf06b43 --- /dev/null +++ b/pkg/sdk/netmap/yml_tests/rep_only.yml @@ -0,0 +1,66 @@ +name: REP X +nodes: + - publicKey: '' + addresses: [] + attributes: + - key: City + value: Saint-Petersburg + parents: [] + state: UNSPECIFIED + - publicKey: '' + addresses: [] + attributes: + - key: City + value: Moscow + parents: [] + state: UNSPECIFIED + - publicKey: '' + addresses: [] + attributes: + - key: City + value: Berlin + parents: [] + state: UNSPECIFIED + - publicKey: '' + addresses: [] + attributes: + - key: City + value: Paris + parents: [] + state: UNSPECIFIED +tests: + REP 1: + policy: + replicas: + - count: 1 + containerBackupFactor: 0 + selectors: [] + filters: [] + result: + - - 0 + - 1 + - 2 + REP 3: + policy: + replicas: + - count: 3 + containerBackupFactor: 0 + selectors: [] + filters: [] + result: + - - 0 + - 3 + - 1 + - 2 + REP 5: + policy: + replicas: + - count: 5 + containerBackupFactor: 0 + selectors: [] + filters: [] + result: + - - 0 + - 1 + - 2 + - 3 diff --git a/pkg/sdk/netmap/yml_tests/select_no_attribute.yml b/pkg/sdk/netmap/yml_tests/select_no_attribute.yml new file mode 100644 index 000000000..02046f3b4 --- /dev/null +++ b/pkg/sdk/netmap/yml_tests/select_no_attribute.yml @@ -0,0 +1,56 @@ +name: select with unspecified attribute +nodes: + - attributes: + - key: ID + value: '1' + - key: Country + value: RU + - key: City + value: St.Petersburg + - key: SSD + value: '0' + - attributes: + - key: ID + value: '2' + - key: Country + value: RU + - key: City + value: St.Petersburg + - key: SSD + value: '1' + - attributes: + - key: ID + value: '3' + - key: Country + value: RU + - key: City + value: Moscow + - key: SSD + value: '1' + - attributes: + - key: ID + value: '4' + - key: Country + value: RU + - key: City + value: Moscow + - key: SSD + value: '1' +tests: + test: + policy: + replicas: + - count: 1 + selector: X + containerBackupFactor: 1 + selectors: + - name: X + count: 4 + clause: DISTINCT + filter: '*' + filters: [] + result: + - - 0 + - 1 + - 2 + - 3 diff --git a/pkg/sdk/netmap/yml_tests/selector_invalid.yml b/pkg/sdk/netmap/yml_tests/selector_invalid.yml new file mode 100644 index 000000000..d6e3b4e4f --- /dev/null +++ b/pkg/sdk/netmap/yml_tests/selector_invalid.yml @@ -0,0 +1,48 @@ +name: invalid selections +nodes: + - attributes: + - key: Country + value: Russia + - attributes: + - key: Country + value: Germany + - attributes: [] +tests: + missing filter: + policy: + replicas: + - count: 1 + selector: MyStore + containerBackupFactor: 1 + selectors: + - name: MyStore + count: 1 + clause: DISTINCT + attribute: Country + filter: FromNL + filters: + - name: FromRU + key: Country + op: EQ + value: Russia + filters: [] + error: filter not found + not enough nodes (filter results in empty set): + policy: + replicas: + - count: 1 + selector: MyStore + containerBackupFactor: 2 + selectors: + - name: MyStore + count: 2 + clause: DISTINCT + attribute: Country + filter: FromMoon + filters: + - name: FromMoon + key: Country + op: EQ + value: Moon + filters: [] + error: not enough nodes diff --git a/pkg/sdk/netmap/yml_unmarshal.go b/pkg/sdk/netmap/yml_unmarshal.go new file mode 100644 index 000000000..d4e1988bc --- /dev/null +++ b/pkg/sdk/netmap/yml_unmarshal.go @@ -0,0 +1,142 @@ +package netmap + +import ( + "strings" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/netmap" +) + +type tempPlacementPolicy struct { + BackupFactor uint32 `yaml:"containerBackupFactor"` + Filters []tempFilter `yaml:"filters"` + Selectors []tempSelector `yaml:"selectors"` + Replicas []tempReplica `yaml:"replicas"` + Unique bool `yaml:"unique"` +} + +type tempFilter struct { + Name string `yaml:"name"` + Key string `yaml:"key"` + Op string `yaml:"op"` + Value string `yaml:"value"` + Filters []tempFilter `yaml:"filters"` +} + +type tempSelector struct { + Name string `yaml:"name"` + Count uint32 `yaml:"count"` + Clause string `yaml:"clause"` + Attribute string `yaml:"attribute"` + Filter string `yaml:"filter"` +} + +type tempReplica struct { + Count uint32 `yaml:"count"` + Selector string `yaml:"selector"` +} + +func convertNFilters(temp []tempFilter) []netmap.Filter { + var filters []netmap.Filter + for _, tf := range temp { + filters = append(filters, convertNFilter(tf)) + } + return filters +} + +var stringToOperationMap = map[string]netmap.Operation{ + "EQ": netmap.EQ, + "NE": netmap.NE, + "GT": netmap.GT, + "GE": netmap.GE, + "LT": netmap.LT, + "LE": netmap.LE, + "OR": netmap.OR, + "AND": netmap.AND, + "NOT": netmap.NOT, +} + +func convertStringToOperation(opStr string) netmap.Operation { + opStr = strings.ToUpper(opStr) + if op, exists := stringToOperationMap[opStr]; exists { + return op + } + return netmap.UnspecifiedOperation +} + +func convertStringToClause(clauseStr string) netmap.Clause { + switch strings.ToUpper(clauseStr) { + case "DISTINCT": + return netmap.Distinct + default: + return netmap.Same + } +} + +func convertNFilter(temp tempFilter) netmap.Filter { + filter := netmap.Filter{} + filter.SetKey(temp.Key) + filter.SetName(temp.Name) + filter.SetValue(temp.Value) + filter.SetOp(convertStringToOperation(temp.Op)) + + if temp.Filters != nil { + filter.SetFilters(convertNFilters(temp.Filters)) + } + return filter +} + +func (p *PlacementPolicy) UnmarshalYAML(unmarshal func(interface{}) error) error { + var temp tempPlacementPolicy + if err := unmarshal(&temp); err != nil { + return err + } + + for _, ts := range temp.Filters { + netmapFilters := convertNFilter(ts) + p.AddFilters(Filter{m: netmapFilters}) + } + + for _, ts := range temp.Selectors { + selector := Selector{} + selector.SetName(ts.Name) + selector.SetNumberOfNodes(ts.Count) + selector.SetClause(convertStringToClause(ts.Clause)) + selector.SelectByBucketAttribute(ts.Attribute) + selector.SetFilterName(ts.Filter) + p.AddSelectors(selector) + } + + for _, tr := range temp.Replicas { + replica := ReplicaDescriptor{} + replica.SetSelectorName(tr.Selector) + replica.m.SetCount(tr.Count) + p.AddReplicas(replica) + } + + p.SetContainerBackupFactor(temp.BackupFactor) + p.SetUnique(temp.Unique) + + return nil +} + +type Attribute struct { + Key string `yaml:"key"` + Value string `yaml:"value"` +} + +type tempNode struct { + Attributes []Attribute `yaml:"attributes"` +} + +func (x *NodeInfo) UnmarshalYAML(unmarshal func(interface{}) error) error { + var temp tempNode + if err := unmarshal(&temp); err != nil { + return err + } + + for _, atr := range temp.Attributes { + x.SetAttribute(atr.Key, atr.Value) + } + + return nil +} diff --git a/pkg/sdk/ns/dns.go b/pkg/sdk/ns/dns.go new file mode 100644 index 000000000..86f8320fb --- /dev/null +++ b/pkg/sdk/ns/dns.go @@ -0,0 +1,35 @@ +package ns + +import ( + "net" + + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" +) + +// DNS looks up FrostFS names using system DNS. +// +// See also net package. +type DNS struct{} + +// ResolveContainerName looks up for DNS TXT records for the given domain name +// and returns the first one which represents valid container ID in a string format. +// Otherwise, returns an error. +// +// See also net.LookupTXT. +func (x *DNS) ResolveContainerName(name string) (id cid.ID, err error) { + records, err := net.LookupTXT(name) + if err != nil { + return + } + + for i := range records { + err = id.DecodeString(records[i]) + if err == nil { + return + } + } + + err = errNotFound + + return +} diff --git a/pkg/sdk/ns/doc.go b/pkg/sdk/ns/doc.go new file mode 100644 index 000000000..44475bc58 --- /dev/null +++ b/pkg/sdk/ns/doc.go @@ -0,0 +1,26 @@ +/* +Package ns provides functionality of FrostFS name system. + +DNS type is designed to resolve FrostFS-related names using Domain Name System: + + const containerName = "some-container" + + var dns DNS + + containerID, err := dns.ResolveContainerName(containerName) + // ... + +NNS type is designed to resolve FrostFS-related names using Neo Name Service: + + var nns NNS + + err := nns.Dial(nnsServerAddress) + // ... + + var containerDomain container.Domain + containerDomain.SetName(containerName) + + containerID, err := nns.ResolveContainerDomain(containerDomain) + // ... +*/ +package ns diff --git a/pkg/sdk/ns/nns.go b/pkg/sdk/ns/nns.go new file mode 100644 index 000000000..273d2f697 --- /dev/null +++ b/pkg/sdk/ns/nns.go @@ -0,0 +1,169 @@ +package ns + +import ( + "context" + "errors" + "fmt" + "net/url" + + "git.frostfs.info/TrueCloudLab/frostfs-contract/nns" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + "github.com/nspcc-dev/neo-go/pkg/core/state" + "github.com/nspcc-dev/neo-go/pkg/encoding/address" + "github.com/nspcc-dev/neo-go/pkg/neorpc/result" + "github.com/nspcc-dev/neo-go/pkg/rpcclient" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap" + "github.com/nspcc-dev/neo-go/pkg/util" + "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" +) + +// multiSchemeClient unites invoker.RPCInvoke and common interface of +// rpcclient.Client and rpcclient.WSClient. +type multiSchemeClient interface { + invoker.RPCInvoke + // Init turns client to "ready-to-work" state. + Init() error + // Close closes connections. + Close() + // GetContractStateByID returns state of the NNS contract on 1 input. + GetContractStateByID(int32) (*state.Contract, error) +} + +// NNS looks up FrostFS names using Neo Name Service. +// +// Instances are created with a variable declaration. Before work, the connection +// to the NNS server MUST be established using Dial method. +type NNS struct { + nnsContract util.Uint160 + client multiSchemeClient + + invoker interface { + Call(contract util.Uint160, operation string, params ...any) (*result.Invoke, error) + } +} + +// Dial connects to the address of the NNS server. If fails, the instance +// MUST NOT be used. +// +// If URL address scheme is 'ws' or 'wss', then WebSocket protocol is used, +// otherwise HTTP. +func (n *NNS) Dial(address string) error { + var err error + + uri, err := url.Parse(address) + if err == nil && (uri.Scheme == "ws" || uri.Scheme == "wss") { + n.client, err = rpcclient.NewWS(context.Background(), address, rpcclient.WSOptions{}) + if err != nil { + return fmt.Errorf("create Neo WebSocket client: %w", err) + } + } else { + n.client, err = rpcclient.New(context.Background(), address, rpcclient.Options{}) + if err != nil { + return fmt.Errorf("create Neo HTTP client: %w", err) + } + } + + if err = n.client.Init(); err != nil { + return fmt.Errorf("initialize Neo client: %w", err) + } + + nnsContract, err := n.client.GetContractStateByID(1) + if err != nil { + return fmt.Errorf("get NNS contract state: %w", err) + } + + n.invoker = invoker.New(n.client, nil) + n.nnsContract = nnsContract.Hash + + return nil +} + +// Close closes connections of multiSchemeClient. +func (n *NNS) Close() { + n.client.Close() +} + +// ResolveContainerDomain looks up for NNS TXT records for the given container domain +// by calling `resolve` method of NNS contract. Returns the first record which represents +// valid container ID in a string format. Otherwise, returns an error. +// +// ResolveContainerDomain MUST NOT be called before successful Dial. +// +// See also https://docs.neo.org/docs/en-us/reference/nns.html. +func (n *NNS) ResolveContainerDomain(domain container.Domain) (cid.ID, error) { + item, err := unwrap.Item(n.invoker.Call(n.nnsContract, "resolve", + domain.Name()+"."+domain.Zone(), int64(nns.TXT), + )) + if err != nil { + return cid.ID{}, fmt.Errorf("contract invocation: %w", err) + } + + if _, ok := item.(stackitem.Null); !ok { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + // unexpected for types from stackitem package + return cid.ID{}, errors.New("invalid cast to stack item slice") + } + + var id cid.ID + + for i := range arr { + bs, err := arr[i].TryBytes() + if err != nil { + return cid.ID{}, fmt.Errorf("convert array item to byte slice: %w", err) + } + + err = id.DecodeString(string(bs)) + if err == nil { + return id, nil + } + } + } + + return cid.ID{}, errNotFound +} + +// ResolveContractHash looks up for NNS TXT records for the given container domain +// by calling `resolve` method of NNS contract. Returns the first record which represents +// valid contract hash 20 bytes long unsigned integer. Otherwise, returns an error. +// +// ResolveContractHash MUST NOT be called before successful Dial. +// +// See also https://docs.neo.org/docs/en-us/reference/nns.html. +func (n *NNS) ResolveContractHash(domain container.Domain) (util.Uint160, error) { + item, err := unwrap.Item(n.invoker.Call(n.nnsContract, "resolve", + domain.Name()+"."+domain.Zone(), int64(nns.TXT), + )) + if err != nil { + return util.Uint160{}, fmt.Errorf("contract invocation: %w", err) + } + + if _, ok := item.(stackitem.Null); !ok { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + // unexpected for types from stackitem package + return util.Uint160{}, errors.New("invalid cast to stack item slice") + } + + for i := range arr { + recordValue, err := arr[i].TryBytes() + if err != nil { + return util.Uint160{}, fmt.Errorf("convert array item to byte slice: %w", err) + } + + strRecordValue := string(recordValue) + scriptHash, err := address.StringToUint160(strRecordValue) + if err == nil { + return scriptHash, nil + } + scriptHash, err = util.Uint160DecodeStringLE(strRecordValue) + if err == nil { + return scriptHash, nil + } + } + } + + return util.Uint160{}, errNotFound +} diff --git a/pkg/sdk/ns/nns_test.go b/pkg/sdk/ns/nns_test.go new file mode 100644 index 000000000..5fc381e98 --- /dev/null +++ b/pkg/sdk/ns/nns_test.go @@ -0,0 +1,239 @@ +package ns + +import ( + "crypto/rand" + "errors" + "fmt" + "math/big" + "strings" + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + "github.com/nspcc-dev/neo-go/pkg/neorpc/result" + "github.com/nspcc-dev/neo-go/pkg/util" + "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" + "github.com/nspcc-dev/neo-go/pkg/vm/vmstate" + "github.com/stretchr/testify/require" +) + +// testNeoClient represents test Neo client which checks invocation arguments +// and returns predefined result. +type testNeoClient struct { + t *testing.T + + expectedContract util.Uint160 + + res result.Invoke + + err error +} + +func (x *testNeoClient) Call(contract util.Uint160, operation string, params ...any) (*result.Invoke, error) { + var domain string + + require.Equal(x.t, x.expectedContract, contract) + require.Equal(x.t, "resolve", operation) + require.Len(x.t, params, 2) + require.NotPanics(x.t, func() { domain = params[0].(string) }) + require.NotPanics(x.t, func() { _ = params[1].(int64) }) + require.True(x.t, strings.HasSuffix(domain, ".container")) + require.NotEmpty(x.t, strings.TrimSuffix(domain, ".container")) + + return &x.res, x.err +} + +// implements test stackitem.Item which is obviously incorrect: +// it returns itself on Convert(stackitem.ArrayT), but returns integer from Value. +type brokenArrayStackItem struct { + stackitem.Item +} + +func (x brokenArrayStackItem) Value() any { + return 1 +} + +func (x brokenArrayStackItem) Convert(t stackitem.Type) (stackitem.Item, error) { + if t != stackitem.ArrayT { + panic(fmt.Sprintf("unexpected stack item type %s", t)) + } + + return x, nil +} + +func TestNNS_ResolveContainerDomain(t *testing.T) { + var testContainerDomain container.Domain + testContainerDomain.SetName("some_container") + + var nnsContract util.Uint160 + + rand.Read(nnsContract[:]) + + testC := &testNeoClient{ + t: t, + expectedContract: nnsContract, + } + + n := NNS{ + nnsContract: nnsContract, + invoker: testC, + } + + t.Run("invocation failure", func(t *testing.T) { + err1 := errors.New("invoke err") + testC.err = err1 + + _, err2 := n.ResolveContainerDomain(testContainerDomain) + require.ErrorIs(t, err2, err1) + }) + + testC.err = nil + + t.Run("fault exception", func(t *testing.T) { + _, err := n.ResolveContainerDomain(testContainerDomain) + require.Error(t, err) + }) + + testC.res.State = vmstate.Halt.String() + + t.Run("empty stack", func(t *testing.T) { + _, err := n.ResolveContainerDomain(testContainerDomain) + require.Error(t, err) + }) + + testC.res.Stack = make([]stackitem.Item, 1) + + t.Run("non-array last stack item", func(t *testing.T) { + testC.res.Stack[0] = stackitem.NewBigInteger(big.NewInt(11)) + + _, err := n.ResolveContainerDomain(testContainerDomain) + require.Error(t, err) + }) + + t.Run("null array", func(t *testing.T) { + testC.res.Stack[0] = stackitem.Null{} + + _, err := n.ResolveContainerDomain(testContainerDomain) + require.ErrorIs(t, err, errNotFound) + }) + + t.Run("array stack item with non-slice value", func(t *testing.T) { + testC.res.Stack[0] = brokenArrayStackItem{} + + _, err := n.ResolveContainerDomain(testContainerDomain) + require.Error(t, err) + }) + + arr := make([]stackitem.Item, 2) + testC.res.Stack[0] = stackitem.NewArray(arr) + + t.Run("non-bytes array element", func(t *testing.T) { + arr[0] = stackitem.NewArray(nil) + + _, err := n.ResolveContainerDomain(testContainerDomain) + require.Error(t, err) + }) + + arr[0] = stackitem.NewByteArray([]byte("some byte array 1")) + + t.Run("non-container array elements", func(t *testing.T) { + arr[1] = stackitem.NewByteArray([]byte("some byte array 2")) + + _, err := n.ResolveContainerDomain(testContainerDomain) + require.Error(t, err) + }) + + t.Run("with container array element", func(t *testing.T) { + id := cidtest.ID() + + arr[1] = stackitem.NewByteArray([]byte(id.EncodeToString())) + + res, err := n.ResolveContainerDomain(testContainerDomain) + require.NoError(t, err) + + require.Equal(t, id, res) + }) +} + +func TestNNS_ResolveContractHash(t *testing.T) { + var testContainerDomain container.Domain + testContainerDomain.SetName("some_container") + + var nnsContract util.Uint160 + + rand.Read(nnsContract[:]) + + testC := &testNeoClient{ + t: t, + expectedContract: nnsContract, + } + + n := NNS{ + nnsContract: nnsContract, + invoker: testC, + } + + t.Run("invocation failure", func(t *testing.T) { + err1 := errors.New("invoke err") + testC.err = err1 + + _, err2 := n.ResolveContractHash(testContainerDomain) + require.ErrorIs(t, err2, err1) + }) + + testC.err = nil + + t.Run("fault exception", func(t *testing.T) { + _, err := n.ResolveContractHash(testContainerDomain) + require.Error(t, err) + }) + + testC.res.State = vmstate.Halt.String() + + t.Run("empty stack", func(t *testing.T) { + _, err := n.ResolveContractHash(testContainerDomain) + require.Error(t, err) + }) + + testC.res.Stack = make([]stackitem.Item, 1) + + t.Run("non-array last stack item", func(t *testing.T) { + testC.res.Stack[0] = stackitem.NewBigInteger(big.NewInt(11)) + + _, err := n.ResolveContractHash(testContainerDomain) + require.Error(t, err) + }) + + t.Run("null array", func(t *testing.T) { + testC.res.Stack[0] = stackitem.Null{} + + _, err := n.ResolveContractHash(testContainerDomain) + require.ErrorIs(t, err, errNotFound) + }) + + t.Run("array stack item with non-slice value", func(t *testing.T) { + testC.res.Stack[0] = brokenArrayStackItem{} + + _, err := n.ResolveContractHash(testContainerDomain) + require.Error(t, err) + }) + + arr := make([]stackitem.Item, 2) + testC.res.Stack[0] = stackitem.NewArray(arr) + + t.Run("non-bytes array element", func(t *testing.T) { + arr[0] = stackitem.NewArray(nil) + + _, err := n.ResolveContractHash(testContainerDomain) + require.Error(t, err) + }) + + arr[0] = stackitem.NewByteArray([]byte("some byte array 1")) + + t.Run("non-container array elements", func(t *testing.T) { + arr[1] = stackitem.NewByteArray([]byte("some byte array 2")) + + _, err := n.ResolveContractHash(testContainerDomain) + require.Error(t, err) + }) +} diff --git a/pkg/sdk/ns/util.go b/pkg/sdk/ns/util.go new file mode 100644 index 000000000..88dc2464e --- /dev/null +++ b/pkg/sdk/ns/util.go @@ -0,0 +1,5 @@ +package ns + +import "errors" + +var errNotFound = errors.New("record not found") diff --git a/pkg/sdk/object/attribute.go b/pkg/sdk/object/attribute.go new file mode 100644 index 000000000..9f8a2ff69 --- /dev/null +++ b/pkg/sdk/object/attribute.go @@ -0,0 +1,73 @@ +package object + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" +) + +// Attribute represents v2-compatible object attribute. +type Attribute object.Attribute + +// NewAttributeFromV2 wraps v2 Attribute message to Attribute. +// +// Nil object.Attribute converts to nil. +func NewAttributeFromV2(aV2 *object.Attribute) *Attribute { + return (*Attribute)(aV2) +} + +// NewAttribute creates and initializes blank Attribute. +// +// Works similar as NewAttributeFromV2(new(Attribute)). +// +// Defaults: +// - key: ""; +// - value: "". +func NewAttribute() *Attribute { + return NewAttributeFromV2(new(object.Attribute)) +} + +// Key returns key to the object attribute. +func (a *Attribute) Key() string { + return (*object.Attribute)(a).GetKey() +} + +// SetKey sets key to the object attribute. +func (a *Attribute) SetKey(v string) { + (*object.Attribute)(a).SetKey(v) +} + +// Value return value of the object attribute. +func (a *Attribute) Value() string { + return (*object.Attribute)(a).GetValue() +} + +// SetValue sets value of the object attribute. +func (a *Attribute) SetValue(v string) { + (*object.Attribute)(a).SetValue(v) +} + +// ToV2 converts Attribute to v2 Attribute message. +// +// Nil Attribute converts to nil. +func (a *Attribute) ToV2() *object.Attribute { + return (*object.Attribute)(a) +} + +// Marshal marshals Attribute into a protobuf binary form. +func (a *Attribute) Marshal() ([]byte, error) { + return (*object.Attribute)(a).StableMarshal(nil), nil +} + +// Unmarshal unmarshals protobuf binary representation of Attribute. +func (a *Attribute) Unmarshal(data []byte) error { + return (*object.Attribute)(a).Unmarshal(data) +} + +// MarshalJSON encodes Attribute to protobuf JSON format. +func (a *Attribute) MarshalJSON() ([]byte, error) { + return (*object.Attribute)(a).MarshalJSON() +} + +// UnmarshalJSON decodes Attribute from protobuf JSON format. +func (a *Attribute) UnmarshalJSON(data []byte) error { + return (*object.Attribute)(a).UnmarshalJSON(data) +} diff --git a/pkg/sdk/object/attribute_test.go b/pkg/sdk/object/attribute_test.go new file mode 100644 index 000000000..fe1b97e6f --- /dev/null +++ b/pkg/sdk/object/attribute_test.go @@ -0,0 +1,82 @@ +package object + +import ( + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" + "github.com/stretchr/testify/require" +) + +func TestAttribute(t *testing.T) { + key, val := "some key", "some value" + + a := NewAttribute() + a.SetKey(key) + a.SetValue(val) + + require.Equal(t, key, a.Key()) + require.Equal(t, val, a.Value()) + + aV2 := a.ToV2() + + require.Equal(t, key, aV2.GetKey()) + require.Equal(t, val, aV2.GetValue()) +} + +func TestAttributeEncoding(t *testing.T) { + a := NewAttribute() + a.SetKey("key") + a.SetValue("value") + + t.Run("binary", func(t *testing.T) { + data, err := a.Marshal() + require.NoError(t, err) + + a2 := NewAttribute() + require.NoError(t, a2.Unmarshal(data)) + + require.Equal(t, a, a2) + }) + + t.Run("json", func(t *testing.T) { + data, err := a.MarshalJSON() + require.NoError(t, err) + + a2 := NewAttribute() + require.NoError(t, a2.UnmarshalJSON(data)) + + require.Equal(t, a, a2) + }) +} + +func TestNewAttributeFromV2(t *testing.T) { + t.Run("from nil", func(t *testing.T) { + var x *object.Attribute + + require.Nil(t, NewAttributeFromV2(x)) + }) +} + +func TestAttribute_ToV2(t *testing.T) { + t.Run("nil", func(t *testing.T) { + var x *Attribute + + require.Nil(t, x.ToV2()) + }) +} + +func TestNewAttribute(t *testing.T) { + t.Run("default values", func(t *testing.T) { + a := NewAttribute() + + // check initial values + require.Empty(t, a.Key()) + require.Empty(t, a.Value()) + + // convert to v2 message + aV2 := a.ToV2() + + require.Empty(t, aV2.GetKey()) + require.Empty(t, aV2.GetValue()) + }) +} diff --git a/pkg/sdk/object/error.go b/pkg/sdk/object/error.go new file mode 100644 index 000000000..96048c28b --- /dev/null +++ b/pkg/sdk/object/error.go @@ -0,0 +1,19 @@ +package object + +type SplitInfoError struct { + si *SplitInfo +} + +const splitInfoErrorMsg = "object not found, split info has been provided" + +func (s *SplitInfoError) Error() string { + return splitInfoErrorMsg +} + +func (s *SplitInfoError) SplitInfo() *SplitInfo { + return s.si +} + +func NewSplitInfoError(v *SplitInfo) *SplitInfoError { + return &SplitInfoError{si: v} +} diff --git a/pkg/sdk/object/error_test.go b/pkg/sdk/object/error_test.go new file mode 100644 index 000000000..897819676 --- /dev/null +++ b/pkg/sdk/object/error_test.go @@ -0,0 +1,33 @@ +package object_test + +import ( + "errors" + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + "github.com/stretchr/testify/require" +) + +func TestNewSplitInfoError(t *testing.T) { + var ( + si = generateSplitInfo() + + err error = object.NewSplitInfoError(si) + expectedErr *object.SplitInfoError + ) + + require.True(t, errors.As(err, &expectedErr)) + + siErr, ok := err.(*object.SplitInfoError) + require.True(t, ok) + require.Equal(t, si, siErr.SplitInfo()) +} + +func generateSplitInfo() *object.SplitInfo { + si := object.NewSplitInfo() + si.SetSplitID(object.NewSplitID()) + si.SetLastPart(generateID()) + si.SetLink(generateID()) + + return si +} diff --git a/pkg/sdk/object/fmt.go b/pkg/sdk/object/fmt.go new file mode 100644 index 000000000..3d86ca999 --- /dev/null +++ b/pkg/sdk/object/fmt.go @@ -0,0 +1,180 @@ +package object + +import ( + "bytes" + "crypto/ecdsa" + "crypto/sha256" + "errors" + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/checksum" + frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/crypto" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" +) + +var ( + errCheckSumMismatch = errors.New("payload checksum mismatch") + errCheckSumNotSet = errors.New("payload checksum is not set") + errIncorrectID = errors.New("incorrect object identifier") +) + +// CalculatePayloadChecksum calculates and returns checksum of +// object payload bytes. +func CalculatePayloadChecksum(payload []byte) checksum.Checksum { + var res checksum.Checksum + checksum.Calculate(&res, checksum.SHA256, payload) + + return res +} + +// CalculateAndSetPayloadChecksum calculates checksum of current +// object payload and writes it to the object. +func CalculateAndSetPayloadChecksum(obj *Object) { + obj.SetPayloadChecksum( + CalculatePayloadChecksum(obj.Payload()), + ) +} + +// VerifyPayloadChecksum checks if payload checksum in the object +// corresponds to its payload. +func VerifyPayloadChecksum(obj *Object) error { + actual := CalculatePayloadChecksum(obj.Payload()) + + cs, set := obj.PayloadChecksum() + if !set { + return errCheckSumNotSet + } + + if !bytes.Equal(cs.Value(), actual.Value()) { + return errCheckSumMismatch + } + + return nil +} + +// CalculateID calculates identifier for the object. +func CalculateID(obj *Object) (oid.ID, error) { + var id oid.ID + id.SetSHA256(sha256.Sum256(obj.ToV2().GetHeader().StableMarshal(nil))) + + return id, nil +} + +// CalculateAndSetID calculates identifier for the object +// and writes the result to it. +func CalculateAndSetID(obj *Object) error { + id, err := CalculateID(obj) + if err != nil { + return err + } + + obj.SetID(id) + + return nil +} + +// VerifyID checks if identifier in the object corresponds to +// its structure. +func VerifyID(obj *Object) error { + id, err := CalculateID(obj) + if err != nil { + return err + } + + oID, set := obj.ID() + if !set { + return errOIDNotSet + } + + if !id.Equals(oID) { + return errIncorrectID + } + + return nil +} + +// CalculateAndSetSignature signs id with provided key and sets that signature to +// the object. +func CalculateAndSetSignature(key ecdsa.PrivateKey, obj *Object) error { + oID, set := obj.ID() + if !set { + return errOIDNotSet + } + + sig, err := oID.CalculateIDSignature(key) + if err != nil { + return err + } + + obj.SetSignature(&sig) + + return nil +} + +// VerifyIDSignature verifies object ID signature. +func (o *Object) VerifyIDSignature() bool { + m := (*object.Object)(o) + + sigV2 := m.GetSignature() + if sigV2 == nil { + return false + } + + idV2 := m.GetObjectID() + if idV2 == nil { + return false + } + + var sig frostfscrypto.Signature + + return sig.ReadFromV2(*sigV2) == nil && sig.Verify(idV2.StableMarshal(nil)) +} + +// SetIDWithSignature sets object identifier and signature. +func SetIDWithSignature(key ecdsa.PrivateKey, obj *Object) error { + if err := CalculateAndSetID(obj); err != nil { + return fmt.Errorf("could not set identifier: %w", err) + } + + if err := CalculateAndSetSignature(key, obj); err != nil { + return fmt.Errorf("could not set signature: %w", err) + } + + return nil +} + +// SetVerificationFields calculates and sets all verification fields of the object. +func SetVerificationFields(key ecdsa.PrivateKey, obj *Object) error { + CalculateAndSetPayloadChecksum(obj) + + return SetIDWithSignature(key, obj) +} + +// CheckVerificationFields checks all verification fields of the object. +func CheckVerificationFields(obj *Object) error { + if err := CheckHeaderVerificationFields(obj); err != nil { + return fmt.Errorf("invalid header structure: %w", err) + } + + if err := VerifyPayloadChecksum(obj); err != nil { + return fmt.Errorf("invalid payload checksum: %w", err) + } + + return nil +} + +var errInvalidSignature = errors.New("invalid signature") + +// CheckHeaderVerificationFields checks all verification fields except payload. +func CheckHeaderVerificationFields(obj *Object) error { + if !obj.VerifyIDSignature() { + return errInvalidSignature + } + + if err := VerifyID(obj); err != nil { + return fmt.Errorf("invalid identifier: %w", err) + } + + return nil +} diff --git a/pkg/sdk/object/fmt_test.go b/pkg/sdk/object/fmt_test.go new file mode 100644 index 000000000..b74708071 --- /dev/null +++ b/pkg/sdk/object/fmt_test.go @@ -0,0 +1,65 @@ +package object + +import ( + "crypto/rand" + "testing" + + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + "github.com/stretchr/testify/require" +) + +func TestVerificationFields(t *testing.T) { + obj := New() + + payload := make([]byte, 10) + _, _ = rand.Read(payload) + + obj.SetPayload(payload) + obj.SetPayloadSize(uint64(len(payload))) + + p, err := keys.NewPrivateKey() + require.NoError(t, err) + require.NoError(t, SetVerificationFields(p.PrivateKey, obj)) + + require.NoError(t, CheckVerificationFields(obj)) + + items := []struct { + corrupt func() + restore func() + }{ + { + corrupt: func() { + payload[0]++ + }, + restore: func() { + payload[0]-- + }, + }, + { + corrupt: func() { + obj.SetPayloadSize(obj.PayloadSize() + 1) + }, + restore: func() { + obj.SetPayloadSize(obj.PayloadSize() - 1) + }, + }, + { + corrupt: func() { + obj.ToV2().GetObjectID().GetValue()[0]++ + }, + restore: func() { + obj.ToV2().GetObjectID().GetValue()[0]-- + }, + }, + } + + for _, item := range items { + item.corrupt() + + require.Error(t, CheckVerificationFields(obj)) + + item.restore() + + require.NoError(t, CheckVerificationFields(obj)) + } +} diff --git a/pkg/sdk/object/id/address.go b/pkg/sdk/object/id/address.go new file mode 100644 index 000000000..bb632fee0 --- /dev/null +++ b/pkg/sdk/object/id/address.go @@ -0,0 +1,179 @@ +package oid + +import ( + "errors" + "fmt" + "strings" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" +) + +// Address represents global object identifier in FrostFS network. Each object +// belongs to exactly one container and is uniquely addressed within the container. +// +// Address is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs.Address +// message. See ReadFromV2 / WriteToV2 methods. +// +// Instances can be created using built-in var declaration. +type Address struct { + cnr cid.ID + + obj ID +} + +// ReadFromV2 reads Address from the refs.Address message. Returns an error if +// the message is malformed according to the FrostFS API V2 protocol. +// +// See also WriteToV2. +func (x *Address) ReadFromV2(m refs.Address) error { + cnr := m.GetContainerID() + if cnr == nil { + return errors.New("missing container ID") + } + + obj := m.GetObjectID() + if obj == nil { + return errors.New("missing object ID") + } + + err := x.cnr.ReadFromV2(*cnr) + if err != nil { + return fmt.Errorf("invalid container ID: %w", err) + } + + err = x.obj.ReadFromV2(*obj) + if err != nil { + return fmt.Errorf("invalid object ID: %w", err) + } + + return nil +} + +// WriteToV2 writes Address to the refs.Address message. +// The message must not be nil. +// +// See also ReadFromV2. +func (x Address) WriteToV2(m *refs.Address) { + var obj refs.ObjectID + x.obj.WriteToV2(&obj) + + var cnr refs.ContainerID + x.cnr.WriteToV2(&cnr) + + m.SetObjectID(&obj) + m.SetContainerID(&cnr) +} + +// MarshalJSON encodes Address into a JSON format of the FrostFS API protocol +// (Protocol Buffers JSON). +// +// See also UnmarshalJSON. +func (x Address) MarshalJSON() ([]byte, error) { + var m refs.Address + x.WriteToV2(&m) + + return m.MarshalJSON() +} + +// UnmarshalJSON decodes FrostFS API protocol JSON format into the Address +// (Protocol Buffers JSON). Returns an error describing a format violation. +// +// See also MarshalJSON. +func (x *Address) UnmarshalJSON(data []byte) error { + var m refs.Address + + err := m.UnmarshalJSON(data) + if err != nil { + return err + } + + return x.ReadFromV2(m) +} + +// Container returns unique identifier of the FrostFS object container. +// +// Zero Address has zero container ID, which is incorrect according to FrostFS +// API protocol. +// +// See also SetContainer. +func (x Address) Container() cid.ID { + return x.cnr +} + +// SetContainer sets unique identifier of the FrostFS object container. +// +// See also Container. +func (x *Address) SetContainer(id cid.ID) { + x.cnr = id +} + +// Object returns unique identifier of the object in the container +// identified by Container(). +// +// Zero Address has zero object ID, which is incorrect according to FrostFS +// API protocol. +// +// See also SetObject. +func (x Address) Object() ID { + return x.obj +} + +// SetObject sets unique identifier of the object in the container +// identified by Container(). +// +// See also Object. +func (x *Address) SetObject(id ID) { + x.obj = id +} + +// delimiter of container and object IDs in Address protocol string. +const idDelimiter = "/" + +// EncodeToString encodes Address into FrostFS API protocol string: concatenation +// of the string-encoded container and object IDs delimited by a slash. +// +// See also DecodeString. +func (x Address) EncodeToString() string { + return x.cnr.EncodeToString() + "/" + x.obj.EncodeToString() +} + +// DecodeString decodes string into Address according to FrostFS API protocol. Returns +// an error if s is malformed. +// +// See also DecodeString. +func (x *Address) DecodeString(s string) error { + indDelimiter := strings.Index(s, idDelimiter) + if indDelimiter < 0 { + return errors.New("missing delimiter") + } + + err := x.cnr.DecodeString(s[:indDelimiter]) + if err != nil { + return fmt.Errorf("decode container string: %w", err) + } + + err = x.obj.DecodeString(s[indDelimiter+1:]) + if err != nil { + return fmt.Errorf("decode object string: %w", err) + } + + return nil +} + +// String implements fmt.Stringer. +// +// String is designed to be human-readable, and its format MAY differ between +// SDK versions. String MAY return same result as EncodeToString. String MUST NOT +// be used to encode Address into FrostFS protocol string. +func (x Address) String() string { + return x.EncodeToString() +} + +// Equals defines a comparison relation between two Address's instances. +// +// Note that comparison using '==' operator is not recommended since it MAY result +// in loss of compatibility. +func (x Address) Equals(other Address) bool { + return x.obj.Equals(other.obj) && x.cnr.Equals(other.cnr) +} diff --git a/pkg/sdk/object/id/address_test.go b/pkg/sdk/object/id/address_test.go new file mode 100644 index 000000000..73722c46b --- /dev/null +++ b/pkg/sdk/object/id/address_test.go @@ -0,0 +1,109 @@ +package oid_test + +import ( + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + oidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id/test" + "github.com/stretchr/testify/require" +) + +func TestAddress_SetContainer(t *testing.T) { + var x oid.Address + + require.Zero(t, x.Container()) + + cnr := cidtest.ID() + + x.SetContainer(cnr) + require.Equal(t, cnr, x.Container()) +} + +func TestAddress_SetObject(t *testing.T) { + var x oid.Address + + require.Zero(t, x.Object()) + + obj := oidtest.ID() + + x.SetObject(obj) + require.Equal(t, obj, x.Object()) +} + +func TestAddress_ReadFromV2(t *testing.T) { + var x oid.Address + var xV2 refs.Address + + require.Error(t, x.ReadFromV2(xV2)) + + var cnrV2 refs.ContainerID + xV2.SetContainerID(&cnrV2) + + require.Error(t, x.ReadFromV2(xV2)) + + cnr := cidtest.ID() + cnr.WriteToV2(&cnrV2) + + require.Error(t, x.ReadFromV2(xV2)) + + var objV2 refs.ObjectID + xV2.SetObjectID(&objV2) + + require.Error(t, x.ReadFromV2(xV2)) + + obj := oidtest.ID() + obj.WriteToV2(&objV2) + + require.NoError(t, x.ReadFromV2(xV2)) + require.Equal(t, cnr, x.Container()) + require.Equal(t, obj, x.Object()) + + var xV2To refs.Address + x.WriteToV2(&xV2To) + + require.Equal(t, xV2, xV2To) +} + +func TestAddress_DecodeString(t *testing.T) { + var x, x2 oid.Address + + require.NoError(t, x2.DecodeString(x.EncodeToString())) + require.Equal(t, x, x2) + + cnr := cidtest.ID() + obj := oidtest.ID() + + x.SetContainer(cnr) + x.SetObject(obj) + + require.NoError(t, x2.DecodeString(x.EncodeToString())) + require.Equal(t, x, x2) + + strCnr := cnr.EncodeToString() + strObj := obj.EncodeToString() + + require.Error(t, x2.DecodeString("")) + require.Error(t, x2.DecodeString("/")) + require.Error(t, x2.DecodeString(strCnr)) + require.Error(t, x2.DecodeString(strCnr+"/")) + require.Error(t, x2.DecodeString("/"+strCnr)) + require.Error(t, x2.DecodeString(strCnr+strObj)) + require.Error(t, x2.DecodeString(strCnr+"\\"+strObj)) + require.NoError(t, x2.DecodeString(strCnr+"/"+strObj)) +} + +func TestAddressEncoding(t *testing.T) { + v := oidtest.Address() + + t.Run("json", func(t *testing.T) { + data, err := v.MarshalJSON() + require.NoError(t, err) + + var v2 oid.Address + require.NoError(t, v2.UnmarshalJSON(data)) + + require.Equal(t, v, v2) + }) +} diff --git a/pkg/sdk/object/id/doc.go b/pkg/sdk/object/id/doc.go new file mode 100644 index 000000000..6ea7de0de --- /dev/null +++ b/pkg/sdk/object/id/doc.go @@ -0,0 +1,10 @@ +/* +Package oid provides primitives to work with object identification in FrostFS. + +Address type is used for global object identity inside the FrostFS network, +while ID represents identity within a fixed container. + +Using package types in an application is recommended to potentially work with +different protocol versions with which these types are compatible. +*/ +package oid diff --git a/pkg/sdk/object/id/id.go b/pkg/sdk/object/id/id.go new file mode 100644 index 000000000..49b41ff7e --- /dev/null +++ b/pkg/sdk/object/id/id.go @@ -0,0 +1,169 @@ +package oid + +import ( + "crypto/ecdsa" + "crypto/sha256" + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/crypto" + frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/crypto/ecdsa" + "github.com/mr-tron/base58" +) + +// ID represents FrostFS object identifier in a container. +// +// ID is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs.ObjectID +// message. See ReadFromV2 / WriteToV2 methods. +// +// Instances can be created using built-in var declaration. +// +// Note that direct typecast is not safe and may result in loss of compatibility: +// +// _ = ID([32]byte{}) // not recommended +type ID [sha256.Size]byte + +// ReadFromV2 reads ID from the refs.ObjectID message. Returns an error if +// the message is malformed according to the FrostFS API V2 protocol. +// +// See also WriteToV2. +func (id *ID) ReadFromV2(m refs.ObjectID) error { + return id.Decode(m.GetValue()) +} + +// WriteToV2 writes ID to the refs.ObjectID message. +// The message must not be nil. +// +// See also ReadFromV2. +func (id ID) WriteToV2(m *refs.ObjectID) { + m.SetValue(id[:]) +} + +// Encode encodes ID into 32 bytes of dst. Panics if +// dst length is less than 32. +// +// Zero ID is all zeros. +// +// See also Decode. +func (id ID) Encode(dst []byte) { + if l := len(dst); l < sha256.Size { + panic(fmt.Sprintf("destination length is less than %d bytes: %d", sha256.Size, l)) + } + + copy(dst, id[:]) +} + +// Decode decodes src bytes into ID. +// +// Decode expects that src has 32 bytes length. If the input is malformed, +// Decode returns an error describing format violation. In this case ID +// remains unchanged. +// +// Decode doesn't mutate src. +// +// See also Encode. +func (id *ID) Decode(src []byte) error { + if len(src) != 32 { + return fmt.Errorf("invalid length %d", len(src)) + } + + copy(id[:], src) + + return nil +} + +// SetSHA256 sets object identifier value to SHA256 checksum. +func (id *ID) SetSHA256(v [sha256.Size]byte) { + copy(id[:], v[:]) +} + +// Equals defines a comparison relation between two ID instances. +// +// Note that comparison using '==' operator is not recommended since it MAY result +// in loss of compatibility. +func (id ID) Equals(id2 ID) bool { + return id == id2 +} + +// EncodeToString encodes ID into FrostFS API protocol string. +// +// Zero ID is base58 encoding of 32 zeros. +// +// See also DecodeString. +func (id ID) EncodeToString() string { + return base58.Encode(id[:]) +} + +// DecodeString decodes string into ID according to FrostFS API protocol. Returns +// an error if s is malformed. +// +// See also DecodeString. +func (id *ID) DecodeString(s string) error { + data, err := base58.Decode(s) + if err != nil { + return fmt.Errorf("decode base58: %w", err) + } + + return id.Decode(data) +} + +// String implements fmt.Stringer. +// +// String is designed to be human-readable, and its format MAY differ between +// SDK versions. String MAY return same result as EncodeToString. String MUST NOT +// be used to encode ID into FrostFS protocol string. +func (id ID) String() string { + return id.EncodeToString() +} + +// CalculateIDSignature signs object id with provided key. +func (id ID) CalculateIDSignature(key ecdsa.PrivateKey) (frostfscrypto.Signature, error) { + data, err := id.Marshal() + if err != nil { + return frostfscrypto.Signature{}, fmt.Errorf("marshal ID: %w", err) + } + + var sig frostfscrypto.Signature + + return sig, sig.Calculate(frostfsecdsa.Signer(key), data) +} + +// Marshal marshals ID into a protobuf binary form. +func (id ID) Marshal() ([]byte, error) { + var v2 refs.ObjectID + v2.SetValue(id[:]) + + return v2.StableMarshal(nil), nil +} + +// Unmarshal unmarshals protobuf binary representation of ID. +func (id *ID) Unmarshal(data []byte) error { + var v2 refs.ObjectID + if err := v2.Unmarshal(data); err != nil { + return err + } + + copy(id[:], v2.GetValue()) + + return nil +} + +// MarshalJSON encodes ID to protobuf JSON format. +func (id ID) MarshalJSON() ([]byte, error) { + var v2 refs.ObjectID + v2.SetValue(id[:]) + + return v2.MarshalJSON() +} + +// UnmarshalJSON decodes ID from protobuf JSON format. +func (id *ID) UnmarshalJSON(data []byte) error { + var v2 refs.ObjectID + if err := v2.UnmarshalJSON(data); err != nil { + return err + } + + copy(id[:], v2.GetValue()) + + return nil +} diff --git a/pkg/sdk/object/id/id_test.go b/pkg/sdk/object/id/id_test.go new file mode 100644 index 000000000..fefe1a9e2 --- /dev/null +++ b/pkg/sdk/object/id/id_test.go @@ -0,0 +1,182 @@ +package oid + +import ( + "crypto/rand" + "crypto/sha256" + "strconv" + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + "github.com/mr-tron/base58" + "github.com/stretchr/testify/require" +) + +const emptyID = "11111111111111111111111111111111" + +func randID(t *testing.T) ID { + var id ID + id.SetSHA256(randSHA256Checksum(t)) + + return id +} + +func randSHA256Checksum(t *testing.T) (cs [sha256.Size]byte) { + _, err := rand.Read(cs[:]) + require.NoError(t, err) + + return +} + +func TestIDV2(t *testing.T) { + var id ID + + checksum := [sha256.Size]byte{} + + _, err := rand.Read(checksum[:]) + require.NoError(t, err) + + id.SetSHA256(checksum) + + var idV2 refs.ObjectID + id.WriteToV2(&idV2) + + require.Equal(t, checksum[:], idV2.GetValue()) +} + +func TestID_Equal(t *testing.T) { + cs := randSHA256Checksum(t) + + var id1 ID + id1.SetSHA256(cs) + + var id2 ID + id2.SetSHA256(cs) + + var id3 ID + id3.SetSHA256(randSHA256Checksum(t)) + + require.True(t, id1.Equals(id2)) + require.False(t, id1.Equals(id3)) +} + +func TestID_Parse(t *testing.T) { + t.Run("should parse successful", func(t *testing.T) { + for i := 0; i < 10; i++ { + t.Run(strconv.Itoa(i), func(t *testing.T) { + cs := randSHA256Checksum(t) + str := base58.Encode(cs[:]) + var oid ID + + require.NoError(t, oid.DecodeString(str)) + + var oidV2 refs.ObjectID + oid.WriteToV2(&oidV2) + + require.Equal(t, cs[:], oidV2.GetValue()) + }) + } + }) + + t.Run("should failure on parse", func(t *testing.T) { + for i := 0; i < 10; i++ { + j := i + t.Run(strconv.Itoa(j), func(t *testing.T) { + cs := []byte{1, 2, 3, 4, 5, byte(j)} + str := base58.Encode(cs) + var oid ID + + require.Error(t, oid.DecodeString(str)) + }) + } + }) +} + +func TestID_String(t *testing.T) { + t.Run("zero", func(t *testing.T) { + var id ID + require.Equal(t, emptyID, id.EncodeToString()) + }) + + t.Run("should be equal", func(t *testing.T) { + for i := 0; i < 10; i++ { + t.Run(strconv.Itoa(i), func(t *testing.T) { + cs := randSHA256Checksum(t) + str := base58.Encode(cs[:]) + var oid ID + + require.NoError(t, oid.DecodeString(str)) + require.Equal(t, str, oid.EncodeToString()) + }) + } + }) +} + +func TestObjectIDEncoding(t *testing.T) { + id := randID(t) + + t.Run("binary", func(t *testing.T) { + data, err := id.Marshal() + require.NoError(t, err) + + var id2 ID + require.NoError(t, id2.Unmarshal(data)) + + require.Equal(t, id, id2) + }) + + t.Run("json", func(t *testing.T) { + data, err := id.MarshalJSON() + require.NoError(t, err) + + var id2 ID + require.NoError(t, id2.UnmarshalJSON(data)) + + require.Equal(t, id, id2) + }) +} + +func TestNewIDFromV2(t *testing.T) { + t.Run("from zero", func(t *testing.T) { + var ( + x ID + v2 refs.ObjectID + ) + + require.Error(t, x.ReadFromV2(v2)) + }) +} + +func TestID_ToV2(t *testing.T) { + t.Run("zero to v2", func(t *testing.T) { + var ( + x ID + v2 refs.ObjectID + ) + + x.WriteToV2(&v2) + + require.Equal(t, sha256.Size, len(v2.GetValue())) + require.Equal(t, emptyID, base58.Encode(v2.GetValue())) + }) +} + +func TestID_Encode(t *testing.T) { + var id ID + + t.Run("panic", func(t *testing.T) { + dst := make([]byte, sha256.Size-1) + + require.Panics(t, func() { + id.Encode(dst) + }) + }) + + t.Run("correct", func(t *testing.T) { + dst := make([]byte, sha256.Size) + + require.NotPanics(t, func() { + id.Encode(dst) + }) + require.Equal(t, emptyID, id.EncodeToString()) + }) +} diff --git a/pkg/sdk/object/id/test/doc.go b/pkg/sdk/object/id/test/doc.go new file mode 100644 index 000000000..88bb54fcd --- /dev/null +++ b/pkg/sdk/object/id/test/doc.go @@ -0,0 +1,13 @@ +/* +Package oidtest provides functions for convenient testing of oid package API. + +Note that importing the package into source files is highly discouraged. + +Random instance generation functions can be useful when testing expects any value, e.g.: + + import oidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id/test" + + value := oidtest.ID() + // test the value +*/ +package oidtest diff --git a/pkg/sdk/object/id/test/generate.go b/pkg/sdk/object/id/test/generate.go new file mode 100644 index 000000000..38d7ddfbb --- /dev/null +++ b/pkg/sdk/object/id/test/generate.go @@ -0,0 +1,37 @@ +package oidtest + +import ( + "crypto/rand" + "crypto/sha256" + + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" +) + +// ID returns random oid.ID. +func ID() oid.ID { + checksum := [sha256.Size]byte{} + + _, _ = rand.Read(checksum[:]) + + return idWithChecksum(checksum) +} + +// idWithChecksum returns oid.ID initialized +// with specified checksum. +func idWithChecksum(cs [sha256.Size]byte) oid.ID { + var id oid.ID + id.SetSHA256(cs) + + return id +} + +// Address returns random oid.Address. +func Address() oid.Address { + var x oid.Address + + x.SetContainer(cidtest.ID()) + x.SetObject(ID()) + + return x +} diff --git a/pkg/sdk/object/lock.go b/pkg/sdk/object/lock.go new file mode 100644 index 000000000..0784cc0b2 --- /dev/null +++ b/pkg/sdk/object/lock.go @@ -0,0 +1,73 @@ +package object + +import ( + v2object "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" +) + +// Lock represents record with locked objects. It is compatible with +// FrostFS API V2 protocol. +// +// Lock instance can be written to the Object, see WriteLock/ReadLock. +type Lock v2object.Lock + +// WriteLock writes Lock to the Object, and sets its type to TypeLock. +// The object must not be nil. +// +// See also ReadLock. +func WriteLock(obj *Object, l Lock) { + obj.SetType(TypeLock) + obj.SetPayload(l.Marshal()) +} + +// ReadLock reads Lock from the Object. The lock must not be nil. +// Returns an error describing incorrect format. Makes sense only +// if object has TypeLock type. +// +// See also WriteLock. +func ReadLock(l *Lock, obj Object) error { + return l.Unmarshal(obj.Payload()) +} + +// NumberOfMembers returns number of members in lock list. +func (x Lock) NumberOfMembers() int { + return (*v2object.Lock)(&x).NumberOfMembers() +} + +// ReadMembers reads list of locked members. +// +// Buffer length must not be less than NumberOfMembers. +func (x Lock) ReadMembers(buf []oid.ID) { + var i int + + (*v2object.Lock)(&x).IterateMembers(func(idV2 refs.ObjectID) { + _ = buf[i].ReadFromV2(idV2) + i++ + }) +} + +// WriteMembers writes list of locked members. +func (x *Lock) WriteMembers(ids []oid.ID) { + var members []refs.ObjectID + + if ids != nil { + members = make([]refs.ObjectID, len(ids)) + + for i := range ids { + ids[i].WriteToV2(&members[i]) + } + } + + (*v2object.Lock)(x).SetMembers(members) +} + +// Marshal encodes the Lock into a FrostFS protocol binary format. +func (x Lock) Marshal() []byte { + return (*v2object.Lock)(&x).StableMarshal(nil) +} + +// Unmarshal decodes the Lock from its FrostFS protocol binary representation. +func (x *Lock) Unmarshal(data []byte) error { + return (*v2object.Lock)(x).Unmarshal(data) +} diff --git a/pkg/sdk/object/lock_test.go b/pkg/sdk/object/lock_test.go new file mode 100644 index 000000000..eb4a6f23a --- /dev/null +++ b/pkg/sdk/object/lock_test.go @@ -0,0 +1,39 @@ +package object_test + +import ( + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + objecttest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/test" + "github.com/stretchr/testify/require" +) + +func TestLockEncoding(t *testing.T) { + l := *objecttest.Lock() + + t.Run("binary", func(t *testing.T) { + data := l.Marshal() + + var l2 object.Lock + require.NoError(t, l2.Unmarshal(data)) + + require.Equal(t, l, l2) + }) +} + +func TestWriteLock(t *testing.T) { + l := *objecttest.Lock() + var o object.Object + + object.WriteLock(&o, l) + + var l2 object.Lock + + require.NoError(t, object.ReadLock(&l2, o)) + require.Equal(t, l, l2) + + // corrupt payload + o.Payload()[0]++ + + require.Error(t, object.ReadLock(&l2, o)) +} diff --git a/pkg/sdk/object/object.go b/pkg/sdk/object/object.go new file mode 100644 index 000000000..f41087ef0 --- /dev/null +++ b/pkg/sdk/object/object.go @@ -0,0 +1,671 @@ +package object + +import ( + "errors" + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + v2session "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/checksum" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/crypto" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/version" +) + +// Object represents in-memory structure of the FrostFS object. +// Type is compatible with FrostFS API V2 protocol. +// +// Instance can be created depending on scenario: +// - InitCreation (an object to be placed in container); +// - New (blank instance, usually needed for decoding); +// - NewFromV2 (when working under FrostFS API V2 protocol). +type Object object.Object + +// RequiredFields contains the minimum set of object data that must be set +// by the FrostFS user at the stage of creation. +type RequiredFields struct { + // Identifier of the FrostFS container associated with the object. + Container cid.ID + + // Object owner's user ID in the FrostFS system. + Owner user.ID +} + +// InitCreation initializes the object instance with minimum set of required fields. +// Object is expected (but not required) to be blank. Object must not be nil. +func InitCreation(dst *Object, rf RequiredFields) { + dst.SetContainerID(rf.Container) + dst.SetOwnerID(rf.Owner) +} + +// NewFromV2 wraps v2 Object message to Object. +func NewFromV2(oV2 *object.Object) *Object { + return (*Object)(oV2) +} + +// New creates and initializes blank Object. +// +// Works similar as NewFromV2(new(Object)). +func New() *Object { + return NewFromV2(new(object.Object)) +} + +// ToV2 converts Object to v2 Object message. +func (o *Object) ToV2() *object.Object { + return (*object.Object)(o) +} + +// MarshalHeaderJSON marshals object's header +// into JSON format. +func (o *Object) MarshalHeaderJSON() ([]byte, error) { + return (*object.Object)(o).GetHeader().MarshalJSON() +} + +func (o *Object) setHeaderField(setter func(*object.Header)) { + obj := (*object.Object)(o) + h := obj.GetHeader() + + if h == nil { + h = new(object.Header) + obj.SetHeader(h) + } + + setter(h) +} + +func (o *Object) setSplitFields(setter func(*object.SplitHeader)) { + o.setHeaderField(func(h *object.Header) { + split := h.GetSplit() + if split == nil { + split = new(object.SplitHeader) + h.SetSplit(split) + } + + setter(split) + }) +} + +// ID returns object identifier. +func (o *Object) ID() (v oid.ID, isSet bool) { + v2 := (*object.Object)(o) + if id := v2.GetObjectID(); id != nil { + _ = v.ReadFromV2(*v2.GetObjectID()) + isSet = true + } + + return +} + +// SetID sets object identifier. +func (o *Object) SetID(v oid.ID) { + var v2 refs.ObjectID + v.WriteToV2(&v2) + + (*object.Object)(o). + SetObjectID(&v2) +} + +// Signature returns signature of the object identifier. +func (o *Object) Signature() *frostfscrypto.Signature { + sigv2 := (*object.Object)(o).GetSignature() + if sigv2 == nil { + return nil + } + + var sig frostfscrypto.Signature + _ = sig.ReadFromV2(*sigv2) // FIXME(@cthulhu-rider): #226 handle error + + return &sig +} + +// SetSignature sets signature of the object identifier. +func (o *Object) SetSignature(v *frostfscrypto.Signature) { + var sigv2 *refs.Signature + + if v != nil { + sigv2 = new(refs.Signature) + + v.WriteToV2(sigv2) + } + + (*object.Object)(o).SetSignature(sigv2) +} + +// Payload returns payload bytes. +func (o *Object) Payload() []byte { + return (*object.Object)(o).GetPayload() +} + +// SetPayload sets payload bytes. +func (o *Object) SetPayload(v []byte) { + (*object.Object)(o).SetPayload(v) +} + +// Version returns version of the object. +func (o *Object) Version() *version.Version { + var ver version.Version + if verV2 := (*object.Object)(o).GetHeader().GetVersion(); verV2 != nil { + _ = ver.ReadFromV2(*verV2) // FIXME(@cthulhu-rider): #226 handle error + } + return &ver +} + +// SetVersion sets version of the object. +func (o *Object) SetVersion(v *version.Version) { + var verV2 refs.Version + v.WriteToV2(&verV2) + + o.setHeaderField(func(h *object.Header) { + h.SetVersion(&verV2) + }) +} + +// PayloadSize returns payload length of the object. +func (o *Object) PayloadSize() uint64 { + return (*object.Object)(o). + GetHeader(). + GetPayloadLength() +} + +// SetPayloadSize sets payload length of the object. +func (o *Object) SetPayloadSize(v uint64) { + o.setHeaderField(func(h *object.Header) { + h.SetPayloadLength(v) + }) +} + +// ContainerID returns identifier of the related container. +func (o *Object) ContainerID() (v cid.ID, isSet bool) { + v2 := (*object.Object)(o) + + cidV2 := v2.GetHeader().GetContainerID() + if cidV2 != nil { + _ = v.ReadFromV2(*cidV2) + isSet = true + } + + return +} + +// SetContainerID sets identifier of the related container. +func (o *Object) SetContainerID(v cid.ID) { + var cidV2 refs.ContainerID + v.WriteToV2(&cidV2) + + o.setHeaderField(func(h *object.Header) { + h.SetContainerID(&cidV2) + }) +} + +// OwnerID returns identifier of the object owner and True. +func (o *Object) OwnerID() user.ID { + var id user.ID + + m := (*object.Object)(o).GetHeader().GetOwnerID() + if m != nil { + _ = id.ReadFromV2(*m) + } + + return id +} + +// SetOwnerID sets identifier of the object owner. +func (o *Object) SetOwnerID(v user.ID) { + o.setHeaderField(func(h *object.Header) { + var m refs.OwnerID + v.WriteToV2(&m) + + h.SetOwnerID(&m) + }) +} + +// CreationEpoch returns epoch number in which object was created. +func (o *Object) CreationEpoch() uint64 { + return (*object.Object)(o). + GetHeader(). + GetCreationEpoch() +} + +// SetCreationEpoch sets epoch number in which object was created. +func (o *Object) SetCreationEpoch(v uint64) { + o.setHeaderField(func(h *object.Header) { + h.SetCreationEpoch(v) + }) +} + +// PayloadChecksum returns checksum of the object payload and +// bool that indicates checksum presence in the object. +// +// Zero Object does not have payload checksum. +// +// See also SetPayloadChecksum. +func (o *Object) PayloadChecksum() (checksum.Checksum, bool) { + var v checksum.Checksum + v2 := (*object.Object)(o) + + if hash := v2.GetHeader().GetPayloadHash(); hash != nil { + _ = v.ReadFromV2(*hash) // FIXME(@cthulhu-rider): #226 handle error + return v, true + } + + return v, false +} + +// SetPayloadChecksum sets checksum of the object payload. +// +// See also PayloadChecksum. +func (o *Object) SetPayloadChecksum(v checksum.Checksum) { + var v2 refs.Checksum + v.WriteToV2(&v2) + + o.setHeaderField(func(h *object.Header) { + h.SetPayloadHash(&v2) + }) +} + +// PayloadHomomorphicHash returns homomorphic hash of the object +// payload and bool that indicates checksum presence in the object. +// +// Zero Object does not have payload homomorphic checksum. +// +// See also SetPayloadHomomorphicHash. +func (o *Object) PayloadHomomorphicHash() (checksum.Checksum, bool) { + var v checksum.Checksum + v2 := (*object.Object)(o) + + if hash := v2.GetHeader().GetHomomorphicHash(); hash != nil { + _ = v.ReadFromV2(*hash) // FIXME(@cthulhu-rider): #226 handle error + return v, true + } + + return v, false +} + +// SetPayloadHomomorphicHash sets homomorphic hash of the object payload. +// +// See also PayloadHomomorphicHash. +func (o *Object) SetPayloadHomomorphicHash(v checksum.Checksum) { + var v2 refs.Checksum + v.WriteToV2(&v2) + + o.setHeaderField(func(h *object.Header) { + h.SetHomomorphicHash(&v2) + }) +} + +// Attributes returns object attributes. +func (o *Object) Attributes() []Attribute { + attrs := (*object.Object)(o). + GetHeader(). + GetAttributes() + + res := make([]Attribute, len(attrs)) + + for i := range attrs { + res[i] = *NewAttributeFromV2(&attrs[i]) + } + + return res +} + +// SetAttributes sets object attributes. +func (o *Object) SetAttributes(v ...Attribute) { + attrs := make([]object.Attribute, len(v)) + + for i := range v { + attrs[i] = *v[i].ToV2() + } + + o.setHeaderField(func(h *object.Header) { + h.SetAttributes(attrs) + }) +} + +// PreviousID returns identifier of the previous sibling object. +func (o *Object) PreviousID() (v oid.ID, isSet bool) { + v2 := (*object.Object)(o) + + v2Prev := v2.GetHeader().GetSplit().GetPrevious() + if v2Prev != nil { + _ = v.ReadFromV2(*v2Prev) + isSet = true + } + + return +} + +// SetPreviousID sets identifier of the previous sibling object. +func (o *Object) SetPreviousID(v oid.ID) { + var v2 refs.ObjectID + v.WriteToV2(&v2) + + o.setSplitFields(func(split *object.SplitHeader) { + split.SetPrevious(&v2) + }) +} + +// Children return list of the identifiers of the child objects. +func (o *Object) Children() []oid.ID { + v2 := (*object.Object)(o) + ids := v2.GetHeader().GetSplit().GetChildren() + + var ( + id oid.ID + res = make([]oid.ID, len(ids)) + ) + + for i := range ids { + _ = id.ReadFromV2(ids[i]) + res[i] = id + } + + return res +} + +// SetChildren sets list of the identifiers of the child objects. +func (o *Object) SetChildren(v ...oid.ID) { + var ( + v2 refs.ObjectID + ids = make([]refs.ObjectID, len(v)) + ) + + for i := range v { + v[i].WriteToV2(&v2) + ids[i] = v2 + } + + o.setSplitFields(func(split *object.SplitHeader) { + split.SetChildren(ids) + }) +} + +// NotificationInfo groups information about object notification +// that can be written to object. +// +// Topic is an optional field. +type NotificationInfo struct { + ni object.NotificationInfo +} + +// Epoch returns object notification tick +// epoch. +func (n NotificationInfo) Epoch() uint64 { + return n.ni.Epoch() +} + +// SetEpoch sets object notification tick +// epoch. +func (n *NotificationInfo) SetEpoch(epoch uint64) { + n.ni.SetEpoch(epoch) +} + +// Topic return optional object notification +// topic. +func (n NotificationInfo) Topic() string { + return n.ni.Topic() +} + +// SetTopic sets optional object notification +// topic. +func (n *NotificationInfo) SetTopic(topic string) { + n.ni.SetTopic(topic) +} + +// NotificationInfo returns notification info +// read from the object structure. +// Returns any error that appeared during notification +// information parsing. +func (o *Object) NotificationInfo() (*NotificationInfo, error) { + ni, err := object.GetNotificationInfo((*object.Object)(o)) + if err != nil { + return nil, err + } + + return &NotificationInfo{ + ni: *ni, + }, nil +} + +// SetNotification writes NotificationInfo to the object structure. +func (o *Object) SetNotification(ni NotificationInfo) { + object.WriteNotificationInfo((*object.Object)(o), ni.ni) +} + +// SplitID return split identity of split object. If object is not split +// returns nil. +func (o *Object) SplitID() *SplitID { + return NewSplitIDFromV2( + (*object.Object)(o). + GetHeader(). + GetSplit(). + GetSplitID(), + ) +} + +// SetSplitID sets split identifier for the split object. +func (o *Object) SetSplitID(id *SplitID) { + o.setSplitFields(func(split *object.SplitHeader) { + split.SetSplitID(id.ToV2()) + }) +} + +// ParentID returns identifier of the parent object. +func (o *Object) ParentID() (v oid.ID, isSet bool) { + v2 := (*object.Object)(o) + + v2Par := v2.GetHeader().GetSplit().GetParent() + if v2Par != nil { + _ = v.ReadFromV2(*v2Par) + isSet = true + } + + return +} + +// SetParentID sets identifier of the parent object. +func (o *Object) SetParentID(v oid.ID) { + var v2 refs.ObjectID + v.WriteToV2(&v2) + + o.setSplitFields(func(split *object.SplitHeader) { + split.SetParent(&v2) + }) +} + +// Parent returns parent object w/o payload. +func (o *Object) Parent() *Object { + h := (*object.Object)(o). + GetHeader(). + GetSplit() + + parSig := h.GetParentSignature() + parHdr := h.GetParentHeader() + + if parSig == nil && parHdr == nil { + return nil + } + + oV2 := new(object.Object) + oV2.SetObjectID(h.GetParent()) + oV2.SetSignature(parSig) + oV2.SetHeader(parHdr) + + return NewFromV2(oV2) +} + +// SetParent sets parent object w/o payload. +func (o *Object) SetParent(v *Object) { + o.setSplitFields(func(split *object.SplitHeader) { + split.SetParent((*object.Object)(v).GetObjectID()) + split.SetParentSignature((*object.Object)(v).GetSignature()) + split.SetParentHeader((*object.Object)(v).GetHeader()) + }) +} + +func (o *Object) initRelations() { + o.setHeaderField(func(h *object.Header) { + h.SetSplit(new(object.SplitHeader)) + }) +} + +func (o *Object) resetRelations() { + o.setHeaderField(func(h *object.Header) { + h.SetSplit(nil) + }) +} + +// SessionToken returns token of the session +// within which object was created. +func (o *Object) SessionToken() *session.Object { + tokv2 := (*object.Object)(o).GetHeader().GetSessionToken() + if tokv2 == nil { + return nil + } + + var res session.Object + + _ = res.ReadFromV2(*tokv2) + + return &res +} + +// SetSessionToken sets token of the session +// within which object was created. +func (o *Object) SetSessionToken(v *session.Object) { + o.setHeaderField(func(h *object.Header) { + var tokv2 *v2session.Token + + if v != nil { + tokv2 = new(v2session.Token) + v.WriteToV2(tokv2) + } + + h.SetSessionToken(tokv2) + }) +} + +// Type returns type of the object. +func (o *Object) Type() Type { + return TypeFromV2( + (*object.Object)(o). + GetHeader(). + GetObjectType(), + ) +} + +// SetType sets type of the object. +func (o *Object) SetType(v Type) { + o.setHeaderField(func(h *object.Header) { + h.SetObjectType(v.ToV2()) + }) +} + +// CutPayload returns Object w/ empty payload. +// +// Changes of non-payload fields affect source object. +func (o *Object) CutPayload() *Object { + ov2 := new(object.Object) + *ov2 = *(*object.Object)(o) + ov2.SetPayload(nil) + ov2.SetMarshalData(nil) + + return (*Object)(ov2) +} + +func (o *Object) HasParent() bool { + return (*object.Object)(o). + GetHeader(). + GetSplit() != nil +} + +// ResetRelations removes all fields of links with other objects. +func (o *Object) ResetRelations() { + o.resetRelations() +} + +// InitRelations initializes relation field. +func (o *Object) InitRelations() { + o.initRelations() +} + +// Marshal marshals object into a protobuf binary form. +func (o *Object) Marshal() ([]byte, error) { + return (*object.Object)(o).StableMarshal(nil), nil +} + +// Unmarshal unmarshals protobuf binary representation of object. +func (o *Object) Unmarshal(data []byte) error { + err := (*object.Object)(o).Unmarshal(data) + if err != nil { + return err + } + + return formatCheck((*object.Object)(o)) +} + +// MarshalJSON encodes object to protobuf JSON format. +func (o *Object) MarshalJSON() ([]byte, error) { + return (*object.Object)(o).MarshalJSON() +} + +// UnmarshalJSON decodes object from protobuf JSON format. +func (o *Object) UnmarshalJSON(data []byte) error { + err := (*object.Object)(o).UnmarshalJSON(data) + if err != nil { + return err + } + + return formatCheck((*object.Object)(o)) +} + +var ( + errOIDNotSet = errors.New("object ID is not set") + errCIDNotSet = errors.New("container ID is not set") +) + +func formatCheck(v2 *object.Object) error { + var ( + oID oid.ID + cID cid.ID + ) + + oidV2 := v2.GetObjectID() + if oidV2 == nil { + return errOIDNotSet + } + + err := oID.ReadFromV2(*oidV2) + if err != nil { + return fmt.Errorf("could not convert V2 object ID: %w", err) + } + + cidV2 := v2.GetHeader().GetContainerID() + if cidV2 == nil { + return errCIDNotSet + } + + err = cID.ReadFromV2(*cidV2) + if err != nil { + return fmt.Errorf("could not convert V2 container ID: %w", err) + } + + if prev := v2.GetHeader().GetSplit().GetPrevious(); prev != nil { + err = oID.ReadFromV2(*prev) + if err != nil { + return fmt.Errorf("could not convert previous object ID: %w", err) + } + } + + if parent := v2.GetHeader().GetSplit().GetParent(); parent != nil { + err = oID.ReadFromV2(*parent) + if err != nil { + return fmt.Errorf("could not convert parent object ID: %w", err) + } + } + + return nil +} diff --git a/pkg/sdk/object/object_test.go b/pkg/sdk/object/object_test.go new file mode 100644 index 000000000..c027dc825 --- /dev/null +++ b/pkg/sdk/object/object_test.go @@ -0,0 +1,26 @@ +package object_test + +import ( + "testing" + + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + usertest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user/test" + "github.com/stretchr/testify/require" +) + +func TestInitCreation(t *testing.T) { + var o object.Object + cnr := cidtest.ID() + own := usertest.ID() + + object.InitCreation(&o, object.RequiredFields{ + Container: cnr, + Owner: own, + }) + + cID, set := o.ContainerID() + require.True(t, set) + require.Equal(t, cnr, cID) + require.Equal(t, own, o.OwnerID()) +} diff --git a/pkg/sdk/object/range.go b/pkg/sdk/object/range.go new file mode 100644 index 000000000..1560d7d20 --- /dev/null +++ b/pkg/sdk/object/range.go @@ -0,0 +1,51 @@ +package object + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" +) + +// Range represents v2-compatible object payload range. +type Range object.Range + +// NewRangeFromV2 wraps v2 Range message to Range. +// +// Nil object.Range converts to nil. +func NewRangeFromV2(rV2 *object.Range) *Range { + return (*Range)(rV2) +} + +// NewRange creates and initializes blank Range. +// +// Defaults: +// - offset: 0; +// - length: 0. +func NewRange() *Range { + return NewRangeFromV2(new(object.Range)) +} + +// ToV2 converts Range to v2 Range message. +// +// Nil Range converts to nil. +func (r *Range) ToV2() *object.Range { + return (*object.Range)(r) +} + +// GetLength returns payload range size. +func (r *Range) GetLength() uint64 { + return (*object.Range)(r).GetLength() +} + +// SetLength sets payload range size. +func (r *Range) SetLength(v uint64) { + (*object.Range)(r).SetLength(v) +} + +// GetOffset sets payload range offset from start. +func (r *Range) GetOffset() uint64 { + return (*object.Range)(r).GetOffset() +} + +// SetOffset gets payload range offset from start. +func (r *Range) SetOffset(v uint64) { + (*object.Range)(r).SetOffset(v) +} diff --git a/pkg/sdk/object/range_test.go b/pkg/sdk/object/range_test.go new file mode 100644 index 000000000..d12589a81 --- /dev/null +++ b/pkg/sdk/object/range_test.go @@ -0,0 +1,58 @@ +package object + +import ( + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" + "github.com/stretchr/testify/require" +) + +func TestRange_SetOffset(t *testing.T) { + r := NewRange() + + off := uint64(13) + r.SetOffset(off) + + require.Equal(t, off, r.GetOffset()) +} + +func TestRange_SetLength(t *testing.T) { + r := NewRange() + + ln := uint64(7) + r.SetLength(ln) + + require.Equal(t, ln, r.GetLength()) +} + +func TestNewRangeFromV2(t *testing.T) { + t.Run("from nil", func(t *testing.T) { + var x *object.Range + + require.Nil(t, NewRangeFromV2(x)) + }) +} + +func TestRange_ToV2(t *testing.T) { + t.Run("nil", func(t *testing.T) { + var x *Range + + require.Nil(t, x.ToV2()) + }) +} + +func TestNewRange(t *testing.T) { + t.Run("default values", func(t *testing.T) { + r := NewRange() + + // check initial values + require.Zero(t, r.GetLength()) + require.Zero(t, r.GetOffset()) + + // convert to v2 message + rV2 := r.ToV2() + + require.Zero(t, rV2.GetLength()) + require.Zero(t, rV2.GetOffset()) + }) +} diff --git a/pkg/sdk/object/raw.go b/pkg/sdk/object/raw.go new file mode 100644 index 000000000..c7582a9bf --- /dev/null +++ b/pkg/sdk/object/raw.go @@ -0,0 +1,40 @@ +package object + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" +) + +// RawObject represents v2-compatible FrostFS object that provides +// a convenient interface to fill in the fields of +// an object in isolation from its internal structure. +// +// Deprecated: use Object type instead. +type RawObject = Object + +// NewRawFromV2 wraps v2 Object message to Object. +// +// Deprecated: (v1.0.0) use NewFromV2 function instead. +func NewRawFromV2(oV2 *object.Object) *Object { + return NewFromV2(oV2) +} + +// NewRawFrom wraps Object instance to Object. +// +// Deprecated: (v1.0.0) function is no-op. +func NewRawFrom(obj *Object) *Object { + return obj +} + +// NewRaw creates and initializes blank Object. +// +// Deprecated: (v1.0.0) use New instead. +func NewRaw() *Object { + return New() +} + +// Object returns object instance. +// +// Deprecated: (v1.0.0) method is no-op, use arg directly. +func (o *Object) Object() *Object { + return o +} diff --git a/pkg/sdk/object/raw_test.go b/pkg/sdk/object/raw_test.go new file mode 100644 index 000000000..44d01f1b4 --- /dev/null +++ b/pkg/sdk/object/raw_test.go @@ -0,0 +1,308 @@ +package object + +import ( + "crypto/rand" + "crypto/sha256" + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/checksum" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + sessiontest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/session/test" + usertest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user/test" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/version" + "github.com/stretchr/testify/require" +) + +func randID(t *testing.T) oid.ID { + var id oid.ID + id.SetSHA256(randSHA256Checksum(t)) + + return id +} + +func randSHA256Checksum(t *testing.T) (cs [sha256.Size]byte) { + _, err := rand.Read(cs[:]) + require.NoError(t, err) + + return +} + +func randTZChecksum(t *testing.T) (cs [64]byte) { + _, err := rand.Read(cs[:]) + require.NoError(t, err) + + return +} + +func TestObject_SetID(t *testing.T) { + obj := New() + + id := randID(t) + + obj.SetID(id) + + oID, set := obj.ID() + require.True(t, set) + require.Equal(t, id, oID) +} + +func TestObject_SetPayload(t *testing.T) { + obj := New() + + payload := make([]byte, 10) + _, _ = rand.Read(payload) + + obj.SetPayload(payload) + + require.Equal(t, payload, obj.Payload()) +} + +func TestObject_SetVersion(t *testing.T) { + obj := New() + + var ver version.Version + ver.SetMajor(1) + ver.SetMinor(2) + + obj.SetVersion(&ver) + + require.Equal(t, ver, *obj.Version()) +} + +func TestObject_SetPayloadSize(t *testing.T) { + obj := New() + + sz := uint64(133) + obj.SetPayloadSize(sz) + + require.Equal(t, sz, obj.PayloadSize()) +} + +func TestObject_SetContainerID(t *testing.T) { + obj := New() + + cid := cidtest.ID() + + obj.SetContainerID(cid) + + cID, set := obj.ContainerID() + require.True(t, set) + require.Equal(t, cid, cID) +} + +func TestObject_SetOwnerID(t *testing.T) { + obj := New() + + ownerID := usertest.ID() + + obj.SetOwnerID(ownerID) + + require.Equal(t, ownerID, obj.OwnerID()) +} + +func TestObject_SetCreationEpoch(t *testing.T) { + obj := New() + + creat := uint64(228) + obj.SetCreationEpoch(creat) + + require.Equal(t, creat, obj.CreationEpoch()) +} + +func TestObject_SetPayloadChecksum(t *testing.T) { + obj := New() + var cs checksum.Checksum + cs.SetSHA256(randSHA256Checksum(t)) + + obj.SetPayloadChecksum(cs) + cs2, set := obj.PayloadChecksum() + + require.True(t, set) + require.Equal(t, cs, cs2) +} + +func TestObject_SetPayloadHomomorphicHash(t *testing.T) { + obj := New() + + var cs checksum.Checksum + cs.SetTillichZemor(randTZChecksum(t)) + + obj.SetPayloadHomomorphicHash(cs) + cs2, set := obj.PayloadHomomorphicHash() + + require.True(t, set) + require.Equal(t, cs, cs2) +} + +func TestObject_SetAttributes(t *testing.T) { + obj := New() + + a1 := NewAttribute() + a1.SetKey("key1") + a1.SetValue("val1") + + a2 := NewAttribute() + a2.SetKey("key2") + a2.SetValue("val2") + + obj.SetAttributes(*a1, *a2) + + require.Equal(t, []Attribute{*a1, *a2}, obj.Attributes()) +} + +func TestObject_SetPreviousID(t *testing.T) { + obj := New() + + prev := randID(t) + + obj.SetPreviousID(prev) + + oID, set := obj.PreviousID() + + require.True(t, set) + require.Equal(t, prev, oID) +} + +func TestObject_SetChildren(t *testing.T) { + obj := New() + + id1 := randID(t) + id2 := randID(t) + + obj.SetChildren(id1, id2) + + require.Equal(t, []oid.ID{id1, id2}, obj.Children()) +} + +func TestObject_SetSplitID(t *testing.T) { + obj := New() + + require.Nil(t, obj.SplitID()) + + splitID := NewSplitID() + obj.SetSplitID(splitID) + + require.Equal(t, obj.SplitID(), splitID) +} + +func TestObject_SetParent(t *testing.T) { + obj := New() + + require.Nil(t, obj.Parent()) + + par := New() + par.SetID(randID(t)) + par.SetContainerID(cidtest.ID()) + + obj.SetParent(par) + + require.Equal(t, par, obj.Parent()) +} + +func TestObject_ToV2(t *testing.T) { + objV2 := new(object.Object) + objV2.SetPayload([]byte{1, 2, 3}) + + obj := NewFromV2(objV2) + + require.Equal(t, objV2, obj.ToV2()) +} + +func TestObject_SetSessionToken(t *testing.T) { + obj := New() + + tok := sessiontest.ObjectSigned() + + obj.SetSessionToken(tok) + + require.Equal(t, tok, obj.SessionToken()) +} + +func TestObject_CutPayload(t *testing.T) { + o1 := New() + + p1 := []byte{12, 3} + o1.SetPayload(p1) + + sz := uint64(13) + o1.SetPayloadSize(sz) + + o2 := o1.CutPayload() + + require.Equal(t, sz, o2.PayloadSize()) + require.Empty(t, o2.Payload()) + + sz++ + o1.SetPayloadSize(sz) + + require.Equal(t, sz, o1.PayloadSize()) + require.Equal(t, sz, o2.PayloadSize()) + + p2 := []byte{4, 5, 6} + o2.SetPayload(p2) + + require.Equal(t, p2, o2.Payload()) + require.Equal(t, p1, o1.Payload()) +} + +func TestObject_SetParentID(t *testing.T) { + obj := New() + + id := randID(t) + obj.SetParentID(id) + + oID, set := obj.ParentID() + require.True(t, set) + require.Equal(t, id, oID) +} + +func TestObject_ResetRelations(t *testing.T) { + obj := New() + + obj.SetPreviousID(randID(t)) + + obj.ResetRelations() + + _, set := obj.PreviousID() + require.False(t, set) +} + +func TestObject_HasParent(t *testing.T) { + obj := New() + + obj.InitRelations() + + require.True(t, obj.HasParent()) + + obj.ResetRelations() + + require.False(t, obj.HasParent()) +} + +func TestObjectEncoding(t *testing.T) { + o := New() + o.SetID(randID(t)) + o.SetContainerID(cidtest.ID()) + + t.Run("binary", func(t *testing.T) { + data, err := o.Marshal() + require.NoError(t, err) + + o2 := New() + require.NoError(t, o2.Unmarshal(data)) + + require.Equal(t, o, o2) + }) + + t.Run("json", func(t *testing.T) { + data, err := o.MarshalJSON() + require.NoError(t, err) + + o2 := New() + require.NoError(t, o2.UnmarshalJSON(data)) + + require.Equal(t, o, o2) + }) +} diff --git a/pkg/sdk/object/relations/doc.go b/pkg/sdk/object/relations/doc.go new file mode 100644 index 000000000..4dea37261 --- /dev/null +++ b/pkg/sdk/object/relations/doc.go @@ -0,0 +1,7 @@ +/* +Package relations provides feature to process inner object structure. + +Relations is an interface of entity that can receive object header or +the information about the object relations. +*/ +package relations diff --git a/pkg/sdk/object/relations/relations.go b/pkg/sdk/object/relations/relations.go new file mode 100644 index 000000000..37205131c --- /dev/null +++ b/pkg/sdk/object/relations/relations.go @@ -0,0 +1,120 @@ +package relations + +import ( + "context" + "errors" + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/bearer" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/session" +) + +// Tokens contains different tokens to perform requests in Relations implementations. +type Tokens struct { + Session *session.Object + Bearer *bearer.Token +} + +type Relations interface { + // GetSplitInfo tries to get split info by root object id. + // If object isn't virtual it returns ErrNoSplitInfo. + GetSplitInfo(ctx context.Context, cnrID cid.ID, rootID oid.ID, tokens Tokens) (*object.SplitInfo, error) + + // ListChildrenByLinker returns list of children for link object. + // Result doesn't include link object itself. + ListChildrenByLinker(ctx context.Context, cnrID cid.ID, linkerID oid.ID, tokens Tokens) ([]oid.ID, error) + + // GetLeftSibling return previous object id in object chain. + // If no previous object it returns ErrNoLeftSibling. + GetLeftSibling(ctx context.Context, cnrID cid.ID, objID oid.ID, tokens Tokens) (oid.ID, error) + + // FindSiblingBySplitID returns all objects that relates to the provided split id. + FindSiblingBySplitID(ctx context.Context, cnrID cid.ID, splitID *object.SplitID, tokens Tokens) ([]oid.ID, error) + + // FindSiblingByParentID returns all object that relates to the provided parent id. + FindSiblingByParentID(ctx context.Context, cnrID cid.ID, parentID oid.ID, tokens Tokens) ([]oid.ID, error) +} + +var ( + // ErrNoLeftSibling is an error that must be returned if object doesn't have left sibling in objects chain. + ErrNoLeftSibling = errors.New("no left siblings") + + // ErrNoSplitInfo is an error that must be returned if requested object isn't virtual. + ErrNoSplitInfo = errors.New("no split info") +) + +// ListAllRelations return all related phy objects for provided root object ID. +// Result doesn't include root object ID itself. +func ListAllRelations(ctx context.Context, rels Relations, cnrID cid.ID, rootObjID oid.ID, tokens Tokens) ([]oid.ID, error) { + splitInfo, err := rels.GetSplitInfo(ctx, cnrID, rootObjID, tokens) + if err != nil { + if errors.Is(err, ErrNoSplitInfo) { + return []oid.ID{}, nil + } + return nil, err + } + + // collect split chain by the descending ease of operations (ease is evaluated heuristically). + // If any approach fails, we don't try the next since we assume that it will fail too. + if idLinking, ok := splitInfo.Link(); ok { + children, err := rels.ListChildrenByLinker(ctx, cnrID, idLinking, tokens) + if err != nil { + return nil, fmt.Errorf("failed to get linking object's header: %w", err) + } + + // include linking object + return append(children, idLinking), nil + } + + if idSplit := splitInfo.SplitID(); idSplit != nil { + members, err := rels.FindSiblingBySplitID(ctx, cnrID, idSplit, tokens) + if err != nil { + return nil, fmt.Errorf("failed to search objects by split ID: %w", err) + } + return members, nil + } + + idMember, ok := splitInfo.LastPart() + if !ok { + return nil, errors.New("missing any data in received object split information") + } + + chain := []oid.ID{idMember} + chainSet := map[oid.ID]struct{}{idMember: {}} + + // prmHead.SetRawFlag(false) + // split members are almost definitely singular, but don't get hung up on it + + for { + idMember, err = rels.GetLeftSibling(ctx, cnrID, idMember, tokens) + if err != nil { + if errors.Is(err, ErrNoLeftSibling) { + break + } + return nil, fmt.Errorf("failed to read split chain member's header: %w", err) + } + + if _, ok = chainSet[idMember]; ok { + return nil, fmt.Errorf("duplicated member in the split chain %s", idMember) + } + + chain = append(chain, idMember) + chainSet[idMember] = struct{}{} + } + + list, err := rels.FindSiblingByParentID(ctx, cnrID, rootObjID, tokens) + if err != nil { + return nil, fmt.Errorf("failed to find object children: %w", err) + } + + for i := range list { + if _, ok = chainSet[list[i]]; !ok { + chain = append(chain, list[i]) + } + } + + return chain, nil +} diff --git a/pkg/sdk/object/search.go b/pkg/sdk/object/search.go new file mode 100644 index 000000000..95b74b08d --- /dev/null +++ b/pkg/sdk/object/search.go @@ -0,0 +1,301 @@ +package object + +import ( + "encoding/json" + "strconv" + + v2object "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/version" +) + +// SearchMatchType indicates match operation on specified header. +type SearchMatchType uint32 + +const ( + MatchUnknown SearchMatchType = iota + MatchStringEqual + MatchStringNotEqual + MatchNotPresent + MatchCommonPrefix +) + +func (m SearchMatchType) ToV2() v2object.MatchType { + switch m { + case MatchStringEqual: + return v2object.MatchStringEqual + case MatchStringNotEqual: + return v2object.MatchStringNotEqual + case MatchNotPresent: + return v2object.MatchNotPresent + case MatchCommonPrefix: + return v2object.MatchCommonPrefix + default: + return v2object.MatchUnknown + } +} + +func SearchMatchFromV2(t v2object.MatchType) (m SearchMatchType) { + switch t { + case v2object.MatchStringEqual: + m = MatchStringEqual + case v2object.MatchStringNotEqual: + m = MatchStringNotEqual + case v2object.MatchNotPresent: + m = MatchNotPresent + case v2object.MatchCommonPrefix: + m = MatchCommonPrefix + default: + m = MatchUnknown + } + + return m +} + +// String returns string representation of SearchMatchType. +// +// String mapping: +// - MatchStringEqual: STRING_EQUAL; +// - MatchStringNotEqual: STRING_NOT_EQUAL; +// - MatchNotPresent: NOT_PRESENT; +// - MatchCommonPrefix: COMMON_PREFIX; +// - MatchUnknown, default: MATCH_TYPE_UNSPECIFIED. +func (m SearchMatchType) String() string { + return m.ToV2().String() +} + +// FromString parses SearchMatchType from a string representation. +// It is a reverse action to String(). +// +// Returns true if s was parsed successfully. +func (m *SearchMatchType) FromString(s string) bool { + var g v2object.MatchType + + ok := g.FromString(s) + + if ok { + *m = SearchMatchFromV2(g) + } + + return ok +} + +type stringEncoder interface { + EncodeToString() string +} + +type SearchFilter struct { + header filterKey + value stringEncoder + op SearchMatchType +} + +type staticStringer string + +type filterKey struct { + typ filterKeyType + + str string +} + +// enumeration of reserved filter keys. +type filterKeyType int + +type SearchFilters []SearchFilter + +const ( + _ filterKeyType = iota + fKeyVersion + fKeyObjectID + fKeyContainerID + fKeyOwnerID + fKeyCreationEpoch + fKeyPayloadLength + fKeyPayloadHash + fKeyType + fKeyHomomorphicHash + fKeyParent + fKeySplitID + fKeyPropRoot + fKeyPropPhy +) + +func (k filterKey) String() string { + switch k.typ { + default: + return k.str + case fKeyVersion: + return v2object.FilterHeaderVersion + case fKeyObjectID: + return v2object.FilterHeaderObjectID + case fKeyContainerID: + return v2object.FilterHeaderContainerID + case fKeyOwnerID: + return v2object.FilterHeaderOwnerID + case fKeyCreationEpoch: + return v2object.FilterHeaderCreationEpoch + case fKeyPayloadLength: + return v2object.FilterHeaderPayloadLength + case fKeyPayloadHash: + return v2object.FilterHeaderPayloadHash + case fKeyType: + return v2object.FilterHeaderObjectType + case fKeyHomomorphicHash: + return v2object.FilterHeaderHomomorphicHash + case fKeyParent: + return v2object.FilterHeaderParent + case fKeySplitID: + return v2object.FilterHeaderSplitID + case fKeyPropRoot: + return v2object.FilterPropertyRoot + case fKeyPropPhy: + return v2object.FilterPropertyPhy + } +} + +func (s staticStringer) EncodeToString() string { + return string(s) +} + +func (f *SearchFilter) Header() string { + return f.header.String() +} + +func (f *SearchFilter) Value() string { + return f.value.EncodeToString() +} + +func (f *SearchFilter) Operation() SearchMatchType { + return f.op +} + +func NewSearchFilters() SearchFilters { + return SearchFilters{} +} + +func NewSearchFiltersFromV2(v2 []v2object.SearchFilter) SearchFilters { + filters := make(SearchFilters, 0, len(v2)) + + for i := range v2 { + filters.AddFilter( + v2[i].GetKey(), + v2[i].GetValue(), + SearchMatchFromV2(v2[i].GetMatchType()), + ) + } + + return filters +} + +func (f *SearchFilters) addFilter(op SearchMatchType, keyTyp filterKeyType, key string, val stringEncoder) { + if *f == nil { + *f = make(SearchFilters, 0, 1) + } + + *f = append(*f, SearchFilter{ + header: filterKey{ + typ: keyTyp, + str: key, + }, + value: val, + op: op, + }) +} + +func (f *SearchFilters) AddFilter(header, value string, op SearchMatchType) { + f.addFilter(op, 0, header, staticStringer(value)) +} + +func (f *SearchFilters) addReservedFilter(op SearchMatchType, keyTyp filterKeyType, val stringEncoder) { + f.addFilter(op, keyTyp, "", val) +} + +// addFlagFilters adds filters that works like flags: they don't need to have +// specific match type or value. They processed by FrostFS nodes by the fact +// of presence in search query. E.g.: PHY, ROOT. +func (f *SearchFilters) addFlagFilter(keyTyp filterKeyType) { + f.addFilter(MatchUnknown, keyTyp, "", staticStringer("")) +} + +func (f *SearchFilters) AddObjectVersionFilter(op SearchMatchType, v version.Version) { + f.addReservedFilter(op, fKeyVersion, staticStringer(version.EncodeToString(v))) +} + +func (f *SearchFilters) AddObjectContainerIDFilter(m SearchMatchType, id cid.ID) { + f.addReservedFilter(m, fKeyContainerID, id) +} + +func (f *SearchFilters) AddObjectOwnerIDFilter(m SearchMatchType, id user.ID) { + f.addReservedFilter(m, fKeyOwnerID, id) +} + +func (f *SearchFilters) AddNotificationEpochFilter(epoch uint64) { + f.addFilter(MatchStringEqual, 0, v2object.SysAttributeTickEpoch, staticStringer(strconv.FormatUint(epoch, 10))) +} + +func (f SearchFilters) ToV2() []v2object.SearchFilter { + result := make([]v2object.SearchFilter, len(f)) + + for i := range f { + result[i].SetKey(f[i].header.String()) + result[i].SetValue(f[i].value.EncodeToString()) + result[i].SetMatchType(f[i].op.ToV2()) + } + + return result +} + +func (f *SearchFilters) addRootFilter() { + f.addFlagFilter(fKeyPropRoot) +} + +func (f *SearchFilters) AddRootFilter() { + f.addRootFilter() +} + +func (f *SearchFilters) addPhyFilter() { + f.addFlagFilter(fKeyPropPhy) +} + +func (f *SearchFilters) AddPhyFilter() { + f.addPhyFilter() +} + +// AddParentIDFilter adds filter by parent identifier. +func (f *SearchFilters) AddParentIDFilter(m SearchMatchType, id oid.ID) { + f.addReservedFilter(m, fKeyParent, id) +} + +// AddObjectIDFilter adds filter by object identifier. +func (f *SearchFilters) AddObjectIDFilter(m SearchMatchType, id oid.ID) { + f.addReservedFilter(m, fKeyObjectID, id) +} + +func (f *SearchFilters) AddSplitIDFilter(m SearchMatchType, id *SplitID) { + f.addReservedFilter(m, fKeySplitID, staticStringer(id.String())) +} + +// AddTypeFilter adds filter by object type. +func (f *SearchFilters) AddTypeFilter(m SearchMatchType, typ Type) { + f.addReservedFilter(m, fKeyType, staticStringer(typ.String())) +} + +// MarshalJSON encodes SearchFilters to protobuf JSON format. +func (f *SearchFilters) MarshalJSON() ([]byte, error) { + return json.Marshal(f.ToV2()) +} + +// UnmarshalJSON decodes SearchFilters from protobuf JSON format. +func (f *SearchFilters) UnmarshalJSON(data []byte) error { + var fsV2 []v2object.SearchFilter + + if err := json.Unmarshal(data, &fsV2); err != nil { + return err + } + + *f = NewSearchFiltersFromV2(fsV2) + + return nil +} diff --git a/pkg/sdk/object/search_test.go b/pkg/sdk/object/search_test.go new file mode 100644 index 000000000..cfba35b30 --- /dev/null +++ b/pkg/sdk/object/search_test.go @@ -0,0 +1,209 @@ +package object_test + +import ( + "crypto/rand" + "crypto/sha256" + "testing" + + v2object "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + "github.com/stretchr/testify/require" +) + +var eqV2Matches = map[object.SearchMatchType]v2object.MatchType{ + object.MatchUnknown: v2object.MatchUnknown, + object.MatchStringEqual: v2object.MatchStringEqual, + object.MatchStringNotEqual: v2object.MatchStringNotEqual, + object.MatchNotPresent: v2object.MatchNotPresent, + object.MatchCommonPrefix: v2object.MatchCommonPrefix, +} + +func TestMatch(t *testing.T) { + t.Run("known matches", func(t *testing.T) { + for matchType, matchTypeV2 := range eqV2Matches { + require.Equal(t, matchTypeV2, matchType.ToV2()) + require.Equal(t, object.SearchMatchFromV2(matchTypeV2), matchType) + } + }) + + t.Run("unknown matches", func(t *testing.T) { + var unknownMatchType object.SearchMatchType + + for matchType := range eqV2Matches { + unknownMatchType += matchType + } + + unknownMatchType++ + + require.Equal(t, unknownMatchType.ToV2(), v2object.MatchUnknown) + + var unknownMatchTypeV2 v2object.MatchType + + for _, matchTypeV2 := range eqV2Matches { + unknownMatchTypeV2 += matchTypeV2 + } + + unknownMatchTypeV2++ + + require.Equal(t, object.SearchMatchFromV2(unknownMatchTypeV2), object.MatchUnknown) + }) +} + +func TestFilter(t *testing.T) { + inputs := [][]string{ + {"user-header", "user-value"}, + } + + filters := object.NewSearchFilters() + for i := range inputs { + filters.AddFilter(inputs[i][0], inputs[i][1], object.MatchStringEqual) + } + + require.Len(t, filters, len(inputs)) + for i := range inputs { + require.Equal(t, inputs[i][0], filters[i].Header()) + require.Equal(t, inputs[i][1], filters[i].Value()) + require.Equal(t, object.MatchStringEqual, filters[i].Operation()) + } + + v2 := filters.ToV2() + newFilters := object.NewSearchFiltersFromV2(v2) + require.Equal(t, filters, newFilters) +} + +func TestSearchFilters_AddRootFilter(t *testing.T) { + fs := new(object.SearchFilters) + + fs.AddRootFilter() + + require.Len(t, *fs, 1) + + f := (*fs)[0] + + require.Equal(t, object.MatchUnknown, f.Operation()) + require.Equal(t, v2object.FilterPropertyRoot, f.Header()) + require.Equal(t, "", f.Value()) +} + +func TestSearchFilters_AddPhyFilter(t *testing.T) { + fs := new(object.SearchFilters) + + fs.AddPhyFilter() + + require.Len(t, *fs, 1) + + f := (*fs)[0] + + require.Equal(t, object.MatchUnknown, f.Operation()) + require.Equal(t, v2object.FilterPropertyPhy, f.Header()) + require.Equal(t, "", f.Value()) +} + +func testOID() oid.ID { + cs := [sha256.Size]byte{} + + rand.Read(cs[:]) + + var id oid.ID + id.SetSHA256(cs) + + return id +} + +func TestSearchFilters_AddParentIDFilter(t *testing.T) { + par := testOID() + + fs := object.SearchFilters{} + fs.AddParentIDFilter(object.MatchStringEqual, par) + + fsV2 := fs.ToV2() + + require.Len(t, fsV2, 1) + + require.Equal(t, v2object.FilterHeaderParent, fsV2[0].GetKey()) + require.Equal(t, par.EncodeToString(), fsV2[0].GetValue()) + require.Equal(t, v2object.MatchStringEqual, fsV2[0].GetMatchType()) +} + +func TestSearchFilters_AddObjectIDFilter(t *testing.T) { + id := testOID() + + fs := new(object.SearchFilters) + fs.AddObjectIDFilter(object.MatchStringEqual, id) + + t.Run("v2", func(t *testing.T) { + fsV2 := fs.ToV2() + + require.Len(t, fsV2, 1) + + require.Equal(t, v2object.FilterHeaderObjectID, fsV2[0].GetKey()) + require.Equal(t, id.EncodeToString(), fsV2[0].GetValue()) + require.Equal(t, v2object.MatchStringEqual, fsV2[0].GetMatchType()) + }) +} + +func TestSearchFilters_AddSplitIDFilter(t *testing.T) { + id := object.NewSplitID() + + fs := new(object.SearchFilters) + fs.AddSplitIDFilter(object.MatchStringEqual, id) + + t.Run("v2", func(t *testing.T) { + fsV2 := fs.ToV2() + + require.Len(t, fsV2, 1) + + require.Equal(t, v2object.FilterHeaderSplitID, fsV2[0].GetKey()) + require.Equal(t, id.String(), fsV2[0].GetValue()) + require.Equal(t, v2object.MatchStringEqual, fsV2[0].GetMatchType()) + }) +} + +func TestSearchFilters_AddTypeFilter(t *testing.T) { + typ := object.TypeTombstone + + fs := new(object.SearchFilters) + fs.AddTypeFilter(object.MatchStringEqual, typ) + + t.Run("v2", func(t *testing.T) { + fsV2 := fs.ToV2() + + require.Len(t, fsV2, 1) + + require.Equal(t, v2object.FilterHeaderObjectType, fsV2[0].GetKey()) + require.Equal(t, typ.String(), fsV2[0].GetValue()) + require.Equal(t, v2object.MatchStringEqual, fsV2[0].GetMatchType()) + }) +} + +func TestSearchFiltersEncoding(t *testing.T) { + fs := object.NewSearchFilters() + fs.AddFilter("key 1", "value 2", object.MatchStringEqual) + fs.AddFilter("key 2", "value 2", object.MatchStringNotEqual) + fs.AddFilter("key 2", "value 2", object.MatchCommonPrefix) + + t.Run("json", func(t *testing.T) { + data, err := fs.MarshalJSON() + require.NoError(t, err) + + fs2 := object.NewSearchFilters() + require.NoError(t, fs2.UnmarshalJSON(data)) + + require.Equal(t, fs, fs2) + }) +} + +func TestSearchMatchType_String(t *testing.T) { + toPtr := func(v object.SearchMatchType) *object.SearchMatchType { + return &v + } + + testEnumStrings(t, new(object.SearchMatchType), []enumStringItem{ + {val: toPtr(object.MatchCommonPrefix), str: "COMMON_PREFIX"}, + {val: toPtr(object.MatchStringEqual), str: "STRING_EQUAL"}, + {val: toPtr(object.MatchStringNotEqual), str: "STRING_NOT_EQUAL"}, + {val: toPtr(object.MatchNotPresent), str: "NOT_PRESENT"}, + {val: toPtr(object.MatchUnknown), str: "MATCH_TYPE_UNSPECIFIED"}, + }) +} diff --git a/pkg/sdk/object/splitid.go b/pkg/sdk/object/splitid.go new file mode 100644 index 000000000..6b75dafe4 --- /dev/null +++ b/pkg/sdk/object/splitid.go @@ -0,0 +1,80 @@ +package object + +import ( + "github.com/google/uuid" +) + +// SplitID is a UUIDv4 used as attribute in split objects. +type SplitID struct { + uuid uuid.UUID +} + +// NewSplitID returns UUID representation of splitID attribute. +// +// Defaults: +// - id: random UUID. +func NewSplitID() *SplitID { + return &SplitID{ + uuid: uuid.New(), + } +} + +// NewSplitIDFromV2 returns parsed UUID from bytes. +// If v is invalid UUIDv4 byte sequence, then function returns nil. +// +// Nil converts to nil. +func NewSplitIDFromV2(v []byte) *SplitID { + if v == nil { + return nil + } + + id := uuid.New() + + err := id.UnmarshalBinary(v) + if err != nil { + return nil + } + + return &SplitID{ + uuid: id, + } +} + +// Parse converts UUIDv4 string representation into SplitID. +func (id *SplitID) Parse(s string) (err error) { + id.uuid, err = uuid.Parse(s) + if err != nil { + return err + } + + return nil +} + +// String returns UUIDv4 string representation of SplitID. +func (id *SplitID) String() string { + if id == nil { + return "" + } + + return id.uuid.String() +} + +// SetUUID sets pre created UUID structure as SplitID. +func (id *SplitID) SetUUID(v uuid.UUID) { + if id != nil { + id.uuid = v + } +} + +// ToV2 converts SplitID to a representation of SplitID in frostfs-api v2. +// +// Nil SplitID converts to nil. +func (id *SplitID) ToV2() []byte { + if id == nil { + return nil + } + + data, _ := id.uuid.MarshalBinary() // err is always nil + + return data +} diff --git a/pkg/sdk/object/splitid_test.go b/pkg/sdk/object/splitid_test.go new file mode 100644 index 000000000..d9e202278 --- /dev/null +++ b/pkg/sdk/object/splitid_test.go @@ -0,0 +1,63 @@ +package object_test + +import ( + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + "github.com/google/uuid" + "github.com/stretchr/testify/require" +) + +func TestSplitID(t *testing.T) { + id := object.NewSplitID() + + t.Run("toV2/fromV2", func(t *testing.T) { + data := id.ToV2() + + newID := object.NewSplitIDFromV2(data) + require.NotNil(t, newID) + + require.Equal(t, id, newID) + }) + + t.Run("string/parse", func(t *testing.T) { + idStr := id.String() + + newID := object.NewSplitID() + require.NoError(t, newID.Parse(idStr)) + + require.Equal(t, id, newID) + }) + + t.Run("set UUID", func(t *testing.T) { + newUUID := uuid.New() + id.SetUUID(newUUID) + + require.Equal(t, newUUID.String(), id.String()) + }) + + t.Run("nil value", func(t *testing.T) { + var newID *object.SplitID + + require.NotPanics(t, func() { + require.Nil(t, newID.ToV2()) + require.Equal(t, "", newID.String()) + }) + }) +} + +func TestSplitID_ToV2(t *testing.T) { + t.Run("nil", func(t *testing.T) { + var x *object.SplitID + + require.Nil(t, x.ToV2()) + }) +} + +func TestNewIDFromV2(t *testing.T) { + t.Run("from nil", func(t *testing.T) { + var x []byte + + require.Nil(t, object.NewSplitIDFromV2(x)) + }) +} diff --git a/pkg/sdk/object/splitinfo.go b/pkg/sdk/object/splitinfo.go new file mode 100644 index 000000000..39922b6b9 --- /dev/null +++ b/pkg/sdk/object/splitinfo.go @@ -0,0 +1,139 @@ +package object + +import ( + "errors" + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" +) + +type SplitInfo object.SplitInfo + +// NewSplitInfoFromV2 wraps v2 SplitInfo message to SplitInfo. +// +// Nil object.SplitInfo converts to nil. +func NewSplitInfoFromV2(v2 *object.SplitInfo) *SplitInfo { + return (*SplitInfo)(v2) +} + +// NewSplitInfo creates and initializes blank SplitInfo. +// +// Defaults: +// - splitID: nil; +// - lastPart nil; +// - link: nil. +func NewSplitInfo() *SplitInfo { + return NewSplitInfoFromV2(new(object.SplitInfo)) +} + +// ToV2 converts SplitInfo to v2 SplitInfo message. +// +// Nil SplitInfo converts to nil. +func (s *SplitInfo) ToV2() *object.SplitInfo { + return (*object.SplitInfo)(s) +} + +func (s *SplitInfo) SplitID() *SplitID { + return NewSplitIDFromV2( + (*object.SplitInfo)(s).GetSplitID()) +} + +func (s *SplitInfo) SetSplitID(v *SplitID) { + (*object.SplitInfo)(s).SetSplitID(v.ToV2()) +} + +func (s SplitInfo) LastPart() (v oid.ID, isSet bool) { + v2 := (object.SplitInfo)(s) + + lpV2 := v2.GetLastPart() + if lpV2 != nil { + _ = v.ReadFromV2(*lpV2) + isSet = true + } + + return +} + +func (s *SplitInfo) SetLastPart(v oid.ID) { + var idV2 refs.ObjectID + v.WriteToV2(&idV2) + + (*object.SplitInfo)(s).SetLastPart(&idV2) +} + +func (s SplitInfo) Link() (v oid.ID, isSet bool) { + v2 := (object.SplitInfo)(s) + + linkV2 := v2.GetLink() + if linkV2 != nil { + _ = v.ReadFromV2(*linkV2) + isSet = true + } + + return +} + +func (s *SplitInfo) SetLink(v oid.ID) { + var idV2 refs.ObjectID + v.WriteToV2(&idV2) + + (*object.SplitInfo)(s).SetLink(&idV2) +} + +func (s *SplitInfo) Marshal() ([]byte, error) { + return (*object.SplitInfo)(s).StableMarshal(nil), nil +} + +func (s *SplitInfo) Unmarshal(data []byte) error { + err := (*object.SplitInfo)(s).Unmarshal(data) + if err != nil { + return err + } + + return formatCheckSI((*object.SplitInfo)(s)) +} + +// MarshalJSON implements json.Marshaler. +func (s *SplitInfo) MarshalJSON() ([]byte, error) { + return (*object.SplitInfo)(s).MarshalJSON() +} + +// UnmarshalJSON implements json.Unmarshaler. +func (s *SplitInfo) UnmarshalJSON(data []byte) error { + err := (*object.SplitInfo)(s).UnmarshalJSON(data) + if err != nil { + return err + } + + return formatCheckSI((*object.SplitInfo)(s)) +} + +var errSplitInfoMissingFields = errors.New("neither link object ID nor last part object ID is set") + +func formatCheckSI(v2 *object.SplitInfo) error { + link := v2.GetLink() + lastPart := v2.GetLastPart() + if link == nil && lastPart == nil { + return errSplitInfoMissingFields + } + + var oID oid.ID + + if link != nil { + err := oID.ReadFromV2(*link) + if err != nil { + return fmt.Errorf("could not convert link object ID: %w", err) + } + } + + if lastPart != nil { + err := oID.ReadFromV2(*lastPart) + if err != nil { + return fmt.Errorf("could not convert last part object ID: %w", err) + } + } + + return nil +} diff --git a/pkg/sdk/object/splitinfo_test.go b/pkg/sdk/object/splitinfo_test.go new file mode 100644 index 000000000..61c95f375 --- /dev/null +++ b/pkg/sdk/object/splitinfo_test.go @@ -0,0 +1,155 @@ +package object_test + +import ( + "crypto/rand" + "encoding/json" + "testing" + + objv2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + "github.com/stretchr/testify/require" +) + +func TestSplitInfo(t *testing.T) { + s := object.NewSplitInfo() + splitID := object.NewSplitID() + lastPart := generateID() + link := generateID() + + s.SetSplitID(splitID) + require.Equal(t, splitID, s.SplitID()) + + s.SetLastPart(lastPart) + lp, set := s.LastPart() + require.True(t, set) + require.Equal(t, lastPart, lp) + + s.SetLink(link) + l, set := s.Link() + require.True(t, set) + require.Equal(t, link, l) +} + +func TestSplitInfoMarshal(t *testing.T) { + testToV2 := func(t *testing.T, s *object.SplitInfo) { + v2 := s.ToV2() + newS := object.NewSplitInfoFromV2(v2) + + require.Equal(t, s, newS) + } + testMarshal := func(t *testing.T, s *object.SplitInfo) { + data, err := s.Marshal() + require.NoError(t, err) + + newS := object.NewSplitInfo() + + err = newS.Unmarshal(data) + require.NoError(t, err) + require.Equal(t, s, newS) + } + + t.Run("good, both fields are set", func(t *testing.T) { + s := object.NewSplitInfo() + s.SetSplitID(object.NewSplitID()) + s.SetLink(generateID()) + s.SetLastPart(generateID()) + + testToV2(t, s) + testMarshal(t, s) + }) + t.Run("good, only link is set", func(t *testing.T) { + s := object.NewSplitInfo() + s.SetSplitID(object.NewSplitID()) + s.SetLink(generateID()) + + testToV2(t, s) + testMarshal(t, s) + }) + t.Run("good, only last part is set", func(t *testing.T) { + s := object.NewSplitInfo() + s.SetSplitID(object.NewSplitID()) + s.SetLastPart(generateID()) + + testToV2(t, s) + testMarshal(t, s) + }) + t.Run("bad, no fields are set", func(t *testing.T) { + s := object.NewSplitInfo() + s.SetSplitID(object.NewSplitID()) + + data, err := s.Marshal() + require.NoError(t, err) + require.Error(t, object.NewSplitInfo().Unmarshal(data)) + }) +} + +func generateID() oid.ID { + var buf [32]byte + _, _ = rand.Read(buf[:]) + + var id oid.ID + id.SetSHA256(buf) + + return id +} + +func TestNewSplitInfoFromV2(t *testing.T) { + t.Run("from nil", func(t *testing.T) { + var x *objv2.SplitInfo + + require.Nil(t, object.NewSplitInfoFromV2(x)) + }) +} + +func TestSplitInfo_ToV2(t *testing.T) { + t.Run("nil", func(t *testing.T) { + var x *object.SplitInfo + + require.Nil(t, x.ToV2()) + }) +} + +func TestNewSplitInfo(t *testing.T) { + t.Run("default values", func(t *testing.T) { + si := object.NewSplitInfo() + + // check initial values + require.Nil(t, si.SplitID()) + _, set := si.LastPart() + require.False(t, set) + _, set = si.Link() + require.False(t, set) + + // convert to v2 message + siV2 := si.ToV2() + + require.Nil(t, siV2.GetSplitID()) + require.Nil(t, siV2.GetLastPart()) + require.Nil(t, siV2.GetLink()) + }) +} + +func TestSplitInfoMarshalJSON(t *testing.T) { + t.Run("good", func(t *testing.T) { + s := object.NewSplitInfo() + s.SetSplitID(object.NewSplitID()) + s.SetLastPart(generateID()) + s.SetLink(generateID()) + + data, err := s.MarshalJSON() + require.NoError(t, err) + + actual := object.NewSplitInfo() + require.NoError(t, json.Unmarshal(data, actual)) + require.Equal(t, s, actual) + }) + t.Run("bad link", func(t *testing.T) { + data := `{"splitId":"Sn707289RrqDyJOrZMbMoQ==","lastPart":{"value":"Y7baWE0UdUOBr1ELKX3Q5v1LKRubQUbI81Q5UxCVeow="},"link":{"value":"bad"}}` + require.Error(t, json.Unmarshal([]byte(data), object.NewSplitInfo())) + }) + t.Run("bad last part", func(t *testing.T) { + data := `{"splitId":"Sn707289RrqDyJOrZMbMoQ==","lastPart":{"value":"bad"},"link":{"value":"eRyPNCNNxHfxPcjijlv05HEcdoep/b7eHNLRSmDlnts="}}` + require.Error(t, json.Unmarshal([]byte(data), object.NewSplitInfo())) + }) +} diff --git a/pkg/sdk/object/test/generate.go b/pkg/sdk/object/test/generate.go new file mode 100644 index 000000000..035f38ec4 --- /dev/null +++ b/pkg/sdk/object/test/generate.go @@ -0,0 +1,121 @@ +package objecttest + +import ( + checksumtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/checksum/test" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + oidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id/test" + sessiontest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/session/test" + usertest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user/test" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/version" + "github.com/google/uuid" +) + +// Range returns random object.Range. +func Range() *object.Range { + x := object.NewRange() + + x.SetOffset(1024) + x.SetLength(2048) + + return x +} + +// Attribute returns random object.Attribute. +func Attribute() *object.Attribute { + x := object.NewAttribute() + + x.SetKey("key") + x.SetValue("value") + + return x +} + +// SplitID returns random object.SplitID. +func SplitID() *object.SplitID { + x := object.NewSplitID() + + x.SetUUID(uuid.New()) + + return x +} + +func generate(withParent bool) *object.Object { + x := object.New() + ver := version.Current() + + x.SetID(oidtest.ID()) + x.SetSessionToken(sessiontest.Object()) + x.SetPayload([]byte{1, 2, 3}) + x.SetOwnerID(usertest.ID()) + x.SetContainerID(cidtest.ID()) + x.SetType(object.TypeTombstone) + x.SetVersion(&ver) + x.SetPayloadSize(111) + x.SetCreationEpoch(222) + x.SetPreviousID(oidtest.ID()) + x.SetParentID(oidtest.ID()) + x.SetChildren(oidtest.ID(), oidtest.ID()) + x.SetAttributes(*Attribute(), *Attribute()) + x.SetSplitID(SplitID()) + x.SetPayloadChecksum(checksumtest.Checksum()) + x.SetPayloadHomomorphicHash(checksumtest.Checksum()) + + if withParent { + x.SetParent(generate(false)) + } + + return x +} + +// Raw returns random object.Object. +// Deprecated: (v1.0.0) use Object instead. +func Raw() *object.Object { + return Object() +} + +// Object returns random object.Object. +func Object() *object.Object { + return generate(true) +} + +// Tombstone returns random object.Tombstone. +func Tombstone() *object.Tombstone { + x := object.NewTombstone() + + x.SetSplitID(SplitID()) + x.SetExpirationEpoch(13) + x.SetMembers([]oid.ID{oidtest.ID(), oidtest.ID()}) + + return x +} + +// SplitInfo returns random object.SplitInfo. +func SplitInfo() *object.SplitInfo { + x := object.NewSplitInfo() + + x.SetSplitID(SplitID()) + x.SetLink(oidtest.ID()) + x.SetLastPart(oidtest.ID()) + + return x +} + +// SearchFilters returns random object.SearchFilters. +func SearchFilters() object.SearchFilters { + x := object.NewSearchFilters() + + x.AddObjectIDFilter(object.MatchStringEqual, oidtest.ID()) + x.AddObjectContainerIDFilter(object.MatchStringNotEqual, cidtest.ID()) + + return x +} + +// Lock returns random object.Lock. +func Lock() *object.Lock { + var l object.Lock + l.WriteMembers([]oid.ID{oidtest.ID(), oidtest.ID()}) + + return &l +} diff --git a/pkg/sdk/object/tombstone.go b/pkg/sdk/object/tombstone.go new file mode 100644 index 000000000..579dc18d7 --- /dev/null +++ b/pkg/sdk/object/tombstone.go @@ -0,0 +1,128 @@ +package object + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/tombstone" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" +) + +// Tombstone represents v2-compatible tombstone structure. +type Tombstone tombstone.Tombstone + +// NewTombstoneFromV2 wraps v2 Tombstone message to Tombstone. +// +// Nil tombstone.Tombstone converts to nil. +func NewTombstoneFromV2(tV2 *tombstone.Tombstone) *Tombstone { + return (*Tombstone)(tV2) +} + +// NewTombstone creates and initializes blank Tombstone. +// +// Defaults: +// - exp: 0; +// - splitID: nil; +// - members: nil. +func NewTombstone() *Tombstone { + return NewTombstoneFromV2(new(tombstone.Tombstone)) +} + +// ToV2 converts Tombstone to v2 Tombstone message. +// +// Nil Tombstone converts to nil. +func (t *Tombstone) ToV2() *tombstone.Tombstone { + return (*tombstone.Tombstone)(t) +} + +// ExpirationEpoch returns the last FrostFS epoch +// number of the tombstone lifetime. +// +// See also SetExpirationEpoch. +func (t *Tombstone) ExpirationEpoch() uint64 { + return (*tombstone.Tombstone)(t).GetExpirationEpoch() +} + +// SetExpirationEpoch sets the last FrostFS epoch +// number of the tombstone lifetime. +// +// See also ExpirationEpoch. +func (t *Tombstone) SetExpirationEpoch(v uint64) { + (*tombstone.Tombstone)(t).SetExpirationEpoch(v) +} + +// SplitID returns identifier of object split hierarchy. +func (t *Tombstone) SplitID() *SplitID { + return NewSplitIDFromV2( + (*tombstone.Tombstone)(t).GetSplitID()) +} + +// SetSplitID sets identifier of object split hierarchy. +func (t *Tombstone) SetSplitID(v *SplitID) { + (*tombstone.Tombstone)(t).SetSplitID(v.ToV2()) +} + +// Members returns list of objects to be deleted. +func (t *Tombstone) Members() []oid.ID { + v2 := (*tombstone.Tombstone)(t) + msV2 := v2.GetMembers() + + if msV2 == nil { + return nil + } + + var ( + ms = make([]oid.ID, len(msV2)) + id oid.ID + ) + + for i := range msV2 { + _ = id.ReadFromV2(msV2[i]) + ms[i] = id + } + + return ms +} + +// SetMembers sets list of objects to be deleted. +func (t *Tombstone) SetMembers(v []oid.ID) { + var ms []refs.ObjectID + + if v != nil { + ms = (*tombstone.Tombstone)(t). + GetMembers() + + if ln := len(v); cap(ms) >= ln { + ms = ms[:0] + } else { + ms = make([]refs.ObjectID, 0, ln) + } + + var idV2 refs.ObjectID + + for i := range v { + v[i].WriteToV2(&idV2) + ms = append(ms, idV2) + } + } + + (*tombstone.Tombstone)(t).SetMembers(ms) +} + +// Marshal marshals Tombstone into a protobuf binary form. +func (t *Tombstone) Marshal() ([]byte, error) { + return (*tombstone.Tombstone)(t).StableMarshal(nil), nil +} + +// Unmarshal unmarshals protobuf binary representation of Tombstone. +func (t *Tombstone) Unmarshal(data []byte) error { + return (*tombstone.Tombstone)(t).Unmarshal(data) +} + +// MarshalJSON encodes Tombstone to protobuf JSON format. +func (t *Tombstone) MarshalJSON() ([]byte, error) { + return (*tombstone.Tombstone)(t).MarshalJSON() +} + +// UnmarshalJSON decodes Tombstone from protobuf JSON format. +func (t *Tombstone) UnmarshalJSON(data []byte) error { + return (*tombstone.Tombstone)(t).UnmarshalJSON(data) +} diff --git a/pkg/sdk/object/tombstone_test.go b/pkg/sdk/object/tombstone_test.go new file mode 100644 index 000000000..6bd97bcb8 --- /dev/null +++ b/pkg/sdk/object/tombstone_test.go @@ -0,0 +1,95 @@ +package object + +import ( + "crypto/rand" + "crypto/sha256" + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/tombstone" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + "github.com/stretchr/testify/require" +) + +func generateIDList(sz int) []oid.ID { + res := make([]oid.ID, sz) + cs := [sha256.Size]byte{} + + for i := 0; i < sz; i++ { + var oID oid.ID + + res[i] = oID + rand.Read(cs[:]) + res[i].SetSHA256(cs) + } + + return res +} + +func TestTombstone(t *testing.T) { + ts := NewTombstone() + + exp := uint64(13) + ts.SetExpirationEpoch(exp) + require.Equal(t, exp, ts.ExpirationEpoch()) + + splitID := NewSplitID() + ts.SetSplitID(splitID) + require.Equal(t, splitID, ts.SplitID()) + + members := generateIDList(3) + ts.SetMembers(members) + require.Equal(t, members, ts.Members()) +} + +func TestTombstoneEncoding(t *testing.T) { + ts := NewTombstone() + ts.SetExpirationEpoch(13) + ts.SetSplitID(NewSplitID()) + ts.SetMembers(generateIDList(5)) + + t.Run("binary", func(t *testing.T) { + data, err := ts.Marshal() + require.NoError(t, err) + + ts2 := NewTombstone() + require.NoError(t, ts2.Unmarshal(data)) + + require.Equal(t, ts, ts2) + }) + + t.Run("json", func(t *testing.T) { + data, err := ts.MarshalJSON() + require.NoError(t, err) + + ts2 := NewTombstone() + require.NoError(t, ts2.UnmarshalJSON(data)) + + require.Equal(t, ts, ts2) + }) +} + +func TestNewTombstoneFromV2(t *testing.T) { + t.Run("from nil", func(t *testing.T) { + var x *tombstone.Tombstone + + require.Nil(t, NewTombstoneFromV2(x)) + }) +} + +func TestNewTombstone(t *testing.T) { + t.Run("default values", func(t *testing.T) { + ts := NewTombstone() + + // check initial values + require.Nil(t, ts.SplitID()) + require.Nil(t, ts.Members()) + require.Zero(t, ts.ExpirationEpoch()) + + // convert to v2 message + tsV2 := ts.ToV2() + + require.Nil(t, tsV2.GetSplitID()) + require.Nil(t, tsV2.GetMembers()) + require.Zero(t, tsV2.GetExpirationEpoch()) + }) +} diff --git a/pkg/sdk/object/transformer/channel.go b/pkg/sdk/object/transformer/channel.go new file mode 100644 index 000000000..9d5a97b5c --- /dev/null +++ b/pkg/sdk/object/transformer/channel.go @@ -0,0 +1,28 @@ +package transformer + +import ( + "context" + + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" +) + +type chanTarget struct { + ch chan<- *objectSDK.Object +} + +// NewChannelTarget returns ObjectTarget which writes +// object parts to a provided channel. +func NewChannelTarget(ch chan<- *objectSDK.Object) ObjectWriter { + return &chanTarget{ + ch: ch, + } +} + +func (c *chanTarget) WriteObject(ctx context.Context, o *objectSDK.Object) error { + select { + case c.ch <- o: + case <-ctx.Done(): + return ctx.Err() + } + return nil +} diff --git a/pkg/sdk/object/transformer/channel_test.go b/pkg/sdk/object/transformer/channel_test.go new file mode 100644 index 000000000..65dd20b38 --- /dev/null +++ b/pkg/sdk/object/transformer/channel_test.go @@ -0,0 +1,58 @@ +package transformer + +import ( + "context" + "crypto/rand" + "testing" + + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/version" + "github.com/stretchr/testify/require" +) + +func TestChannelTarget(t *testing.T) { + const maxSize = 100 + + ch := make(chan *objectSDK.Object, 10) + tt := new(testTarget) + ct := NewChannelTarget(ch) + + chTarget, _ := newPayloadSizeLimiter(maxSize, 0, func() ObjectWriter { return ct }) + testTarget, _ := newPayloadSizeLimiter(maxSize, 0, func() ObjectWriter { return tt }) + + ver := version.Current() + cnr := cidtest.ID() + hdr := objectSDK.New() + hdr.SetContainerID(cnr) + hdr.SetType(objectSDK.TypeRegular) + hdr.SetVersion(&ver) + + payload := make([]byte, maxSize*2+maxSize/2) + _, _ = rand.Read(payload) + + ctx := context.Background() + expectedIDs := writeObject(t, ctx, testTarget, hdr, payload) + actualIDs := writeObject(t, ctx, chTarget, hdr, payload) + _ = expectedIDs + _ = actualIDs + // require.Equal(t, expectedIDs, actualIDs) + + for i := range tt.objects { + select { + case obj := <-ch: + // Because of the split ID objects can be different. + // However, payload and attributes must be the same. + require.Equal(t, tt.objects[i].Payload(), obj.Payload()) + require.Equal(t, tt.objects[i].Attributes(), obj.Attributes()) + default: + require.FailNow(t, "received less parts than expected") + } + } + + select { + case <-ch: + require.FailNow(t, "received more parts than expected") + default: + } +} diff --git a/pkg/sdk/object/transformer/hasher.go b/pkg/sdk/object/transformer/hasher.go new file mode 100644 index 000000000..02dbc2805 --- /dev/null +++ b/pkg/sdk/object/transformer/hasher.go @@ -0,0 +1,38 @@ +package transformer + +import ( + "crypto/sha256" + "hash" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/checksum" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + "git.frostfs.info/TrueCloudLab/tzhash/tz" +) + +type payloadChecksumHasher struct { + hasher hash.Hash + typ checksum.Type +} + +func (h payloadChecksumHasher) writeChecksum(obj *objectSDK.Object) { + switch h.typ { + case checksum.SHA256: + csSHA := [sha256.Size]byte{} + h.hasher.Sum(csSHA[:0]) + + var cs checksum.Checksum + cs.SetSHA256(csSHA) + + obj.SetPayloadChecksum(cs) + case checksum.TZ: + csTZ := [tz.Size]byte{} + h.hasher.Sum(csTZ[:0]) + + var cs checksum.Checksum + cs.SetTillichZemor(csTZ) + + obj.SetPayloadHomomorphicHash(cs) + default: + panic("unreachable") + } +} diff --git a/pkg/sdk/object/transformer/size_hint_test.go b/pkg/sdk/object/transformer/size_hint_test.go new file mode 100644 index 000000000..73b13c1e9 --- /dev/null +++ b/pkg/sdk/object/transformer/size_hint_test.go @@ -0,0 +1,72 @@ +package transformer + +import ( + "context" + "crypto/rand" + "math" + "testing" + + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + "github.com/stretchr/testify/require" +) + +func TestTransformerSizeHintCorrectness(t *testing.T) { + const ( + maxSize = 100 + payloadSize = maxSize*2 + maxSize/2 + ) + + pk, err := keys.NewPrivateKey() + require.NoError(t, err) + + p := Params{ + Key: &pk.PrivateKey, + NetworkState: dummyEpochSource(123), + MaxSize: maxSize, + WithoutHomomorphicHash: true, + } + + cnr := cidtest.ID() + hdr := newObject(cnr) + + var owner user.ID + user.IDFromKey(&owner, pk.PrivateKey.PublicKey) + hdr.SetOwnerID(owner) + + expected := make([]byte, payloadSize) + _, _ = rand.Read(expected) + + t.Run("default", func(t *testing.T) { + p.SizeHint = 0 + testPayloadEqual(t, p, hdr, expected) + }) + t.Run("size hint is perfect", func(t *testing.T) { + p.SizeHint = payloadSize + testPayloadEqual(t, p, hdr, expected) + }) + t.Run("size hint < payload size", func(t *testing.T) { + p.SizeHint = payloadSize / 2 + testPayloadEqual(t, p, hdr, expected) + }) + t.Run("size hint > payload size", func(t *testing.T) { + p.SizeHint = math.MaxUint64 + testPayloadEqual(t, p, hdr, expected) + }) +} + +func testPayloadEqual(t *testing.T, p Params, hdr *objectSDK.Object, expected []byte) { + tt := new(testTarget) + + p.NextTargetInit = func() ObjectWriter { return tt } + target := NewPayloadSizeLimiter(p) + + writeObject(t, context.Background(), target, hdr, expected) + var actual []byte + for i := range tt.objects { + actual = append(actual, tt.objects[i].Payload()...) + } + require.Equal(t, expected, actual) +} diff --git a/pkg/sdk/object/transformer/transformer.go b/pkg/sdk/object/transformer/transformer.go new file mode 100644 index 000000000..063624a5b --- /dev/null +++ b/pkg/sdk/object/transformer/transformer.go @@ -0,0 +1,321 @@ +package transformer + +import ( + "context" + "crypto/ecdsa" + "crypto/sha256" + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/checksum" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/version" + "git.frostfs.info/TrueCloudLab/tzhash/tz" +) + +type payloadSizeLimiter struct { + Params + + written, writtenCurrent uint64 + + current, parent *object.Object + payload []byte + + currentHashers, parentHashers []payloadChecksumHasher + + previous []oid.ID + + splitID *object.SplitID + + parAttrs []object.Attribute + + nextTarget ObjectWriter +} + +type Params struct { + Key *ecdsa.PrivateKey + NextTargetInit TargetInitializer + SessionToken *session.Object + NetworkState EpochSource + MaxSize uint64 + WithoutHomomorphicHash bool + // SizeHint is a hint for the total payload size to be processed. + // It is used primarily to optimize allocations and doesn't affect + // functionality. Primary usecases are providing file size when putting an object + // with the frostfs-cli or using Content-Length header in gateways. + SizeHint uint64 +} + +// NewPayloadSizeLimiter returns ObjectTarget instance that restricts payload length +// of the writing object and writes generated objects to targets from initializer. +// +// Calculates and adds homomorphic hash to resulting objects only if withoutHomomorphicHash +// is false. +// +// Objects w/ payload size less or equal than max size remain untouched. +func NewPayloadSizeLimiter(p Params) ChunkedObjectWriter { + return &payloadSizeLimiter{ + Params: p, + splitID: object.NewSplitID(), + } +} + +func (s *payloadSizeLimiter) WriteHeader(_ context.Context, hdr *object.Object) error { + s.current = fromObject(hdr) + + s.initialize() + + return nil +} + +func (s *payloadSizeLimiter) Write(ctx context.Context, p []byte) (int, error) { + if err := s.writeChunk(ctx, p); err != nil { + return 0, err + } + + return len(p), nil +} + +func (s *payloadSizeLimiter) Close(ctx context.Context) (*AccessIdentifiers, error) { + return s.release(ctx, true) +} + +func (s *payloadSizeLimiter) initialize() { + s.current = fromObject(s.current) + + // if it is an object after the 1st + if ln := len(s.previous); ln > 0 { + // initialize parent object once (after 1st object) + if ln == 1 { + ver := version.Current() + s.parent = fromObject(s.current) + s.parent.ResetRelations() + s.parent.SetSignature(nil) + s.parent.SetAttributes(s.parAttrs...) + s.parent.SetVersion(&ver) + s.parentHashers = append(s.parentHashers[:0], s.currentHashers...) + } + + // set previous object to the last previous identifier + s.current.SetPreviousID(s.previous[ln-1]) + } + + s.initializeCurrent() +} + +func fromObject(obj *object.Object) *object.Object { + cnr, _ := obj.ContainerID() + + res := object.New() + res.SetContainerID(cnr) + res.SetOwnerID(obj.OwnerID()) + res.SetAttributes(obj.Attributes()...) + res.SetType(obj.Type()) + + // obj.SetSplitID creates splitHeader but we don't need to do it in case + // of small objects, so we should make nil check. + if obj.SplitID() != nil { + res.SetSplitID(obj.SplitID()) + } + + return res +} + +func (s *payloadSizeLimiter) initializeCurrent() { + s.nextTarget = s.NextTargetInit() + s.writtenCurrent = 0 + s.initPayloadHashers() + + var payloadSize uint64 + + // Check whether SizeHint is valid. + if remaining := s.SizeHint - s.written; remaining <= s.SizeHint { + if remaining >= s.MaxSize { + payloadSize = s.MaxSize + } else { + payloadSize = remaining % s.MaxSize + } + } + s.payload = make([]byte, 0, payloadSize) +} + +func (s *payloadSizeLimiter) initPayloadHashers() { + s.currentHashers = append(s.currentHashers[:0], payloadChecksumHasher{ + hasher: sha256.New(), + typ: checksum.SHA256, + }) + + if !s.WithoutHomomorphicHash { + s.currentHashers = append(s.currentHashers, payloadChecksumHasher{ + hasher: tz.New(), + typ: checksum.TZ, + }) + } +} + +func (s *payloadSizeLimiter) release(ctx context.Context, finalize bool) (*AccessIdentifiers, error) { + // Arg finalize is true only when called from Close method. + // We finalize parent and generate linking objects only if it is more + // than 1 object in split-chain. + withParent := finalize && len(s.previous) > 0 + + if withParent { + for i := range s.parentHashers { + s.parentHashers[i].writeChecksum(s.parent) + } + s.parent.SetPayloadSize(s.written) + s.current.SetParent(s.parent) + } + + // release current object + for i := range s.currentHashers { + s.currentHashers[i].writeChecksum(s.current) + } + + ids, err := s.fillHeader() + if err != nil { + return nil, fmt.Errorf("fillHeader: %w", err) + } + + s.current.SetPayload(s.payload) + if err := s.nextTarget.WriteObject(ctx, s.current); err != nil { + return nil, fmt.Errorf("could not write to next target: %w", err) + } + + // save identifier of the released object + s.previous = append(s.previous, ids.SelfID) + + if withParent { + // generate and release linking object + s.initializeLinking(ids.ParentHeader) + s.initializeCurrent() + + if _, err := s.release(ctx, false); err != nil { + return nil, fmt.Errorf("could not release linking object: %w", err) + } + } + + return ids, nil +} + +func (s *payloadSizeLimiter) fillHeader() (*AccessIdentifiers, error) { + curEpoch := s.NetworkState.CurrentEpoch() + ver := version.Current() + + s.current.SetVersion(&ver) + s.current.SetPayloadSize(s.writtenCurrent) + s.current.SetSessionToken(s.SessionToken) + s.current.SetCreationEpoch(curEpoch) + + var ( + parID *oid.ID + parHdr *object.Object + ) + + if par := s.current.Parent(); par != nil && par.Signature() == nil { + rawPar := object.NewFromV2(par.ToV2()) + + rawPar.SetSessionToken(s.SessionToken) + rawPar.SetCreationEpoch(curEpoch) + + if err := object.SetIDWithSignature(*s.Key, rawPar); err != nil { + return nil, fmt.Errorf("could not finalize parent object: %w", err) + } + + id, _ := rawPar.ID() + parID = &id + parHdr = rawPar + + s.current.SetParent(parHdr) + } + + if err := object.SetIDWithSignature(*s.Key, s.current); err != nil { + return nil, fmt.Errorf("could not finalize object: %w", err) + } + + id, _ := s.current.ID() + return &AccessIdentifiers{ + ParentID: parID, + SelfID: id, + ParentHeader: parHdr, + }, nil +} + +func (s *payloadSizeLimiter) initializeLinking(parHdr *object.Object) { + s.current = fromObject(s.current) + s.current.SetParent(parHdr) + s.current.SetChildren(s.previous...) + s.current.SetSplitID(s.splitID) +} + +func (s *payloadSizeLimiter) writeChunk(ctx context.Context, chunk []byte) error { + for { + // statement is true if the previous write of bytes reached exactly the boundary. + if s.written > 0 && s.written%s.MaxSize == 0 { + if s.written == s.MaxSize { + s.prepareFirstChild() + } + + // we need to release current object + if _, err := s.release(ctx, false); err != nil { + return fmt.Errorf("could not release object: %w", err) + } + + // initialize another object + s.initialize() + } + + var ( + ln = uint64(len(chunk)) + cut = ln + leftToEdge = s.MaxSize - s.written%s.MaxSize + ) + + // write bytes no further than the boundary of the current object + if ln > leftToEdge { + cut = leftToEdge + } + + if err := s.writeHashes(chunk[:cut]); err != nil { + return fmt.Errorf("could not write chunk to target: %w", err) + } + + // increase written bytes counter + s.writtenCurrent += cut + s.written += cut + + if cut == ln { + return nil + } + // if there are more bytes in buffer we call method again to start filling another object + chunk = chunk[cut:] + } +} + +func (s *payloadSizeLimiter) writeHashes(chunk []byte) error { + s.payload = append(s.payload, chunk...) + + // The `Write` method of `hash.Hash` never returns an error. + for i := range s.currentHashers { + _, _ = s.currentHashers[i].hasher.Write(chunk) + } + + for i := range s.parentHashers { + _, _ = s.parentHashers[i].hasher.Write(chunk) + } + + return nil +} + +func (s *payloadSizeLimiter) prepareFirstChild() { + // initialize split header with split ID on first object in chain + s.current.InitRelations() + s.current.SetSplitID(s.splitID) + + // cut source attributes + s.parAttrs = s.current.Attributes() + s.current.SetAttributes() + + // attributes will be added to parent in detachParent +} diff --git a/pkg/sdk/object/transformer/transformer_test.go b/pkg/sdk/object/transformer/transformer_test.go new file mode 100644 index 000000000..1bc98ad31 --- /dev/null +++ b/pkg/sdk/object/transformer/transformer_test.go @@ -0,0 +1,216 @@ +package transformer + +import ( + "context" + "crypto/rand" + "crypto/sha256" + "testing" + + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/version" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + "github.com/stretchr/testify/require" +) + +func TestTransformer(t *testing.T) { + const maxSize = 100 + + tt := new(testTarget) + + target, pk := newPayloadSizeLimiter(maxSize, 0, func() ObjectWriter { return tt }) + + cnr := cidtest.ID() + hdr := newObject(cnr) + + var owner user.ID + user.IDFromKey(&owner, pk.PrivateKey.PublicKey) + hdr.SetOwnerID(owner) + + expectedPayload := make([]byte, maxSize*2+maxSize/2) + _, _ = rand.Read(expectedPayload) + + ids := writeObject(t, context.Background(), target, hdr, expectedPayload) + require.Equal(t, 4, len(tt.objects)) // 3 parts + linking object + + var actualPayload []byte + for i := range tt.objects { + childCnr, ok := tt.objects[i].ContainerID() + require.True(t, ok) + require.Equal(t, cnr, childCnr) + require.Equal(t, objectSDK.TypeRegular, tt.objects[i].Type()) + require.Equal(t, owner, tt.objects[i].OwnerID()) + + payload := tt.objects[i].Payload() + require.EqualValues(t, tt.objects[i].PayloadSize(), len(payload)) + actualPayload = append(actualPayload, payload...) + + if len(payload) != 0 { + cs, ok := tt.objects[i].PayloadChecksum() + require.True(t, ok) + + h := sha256.Sum256(payload) + require.Equal(t, h[:], cs.Value()) + } + + require.True(t, tt.objects[i].VerifyIDSignature()) + switch i { + case 0, 1: + require.EqualValues(t, maxSize, len(payload)) + require.Nil(t, tt.objects[i].Parent()) + case 2: + require.EqualValues(t, maxSize/2, len(payload)) + parent := tt.objects[i].Parent() + require.NotNil(t, parent) + require.Nil(t, parent.SplitID()) + require.True(t, parent.VerifyIDSignature()) + case 3: + parID, ok := tt.objects[i].ParentID() + require.True(t, ok) + require.Equal(t, ids.ParentID, &parID) + + children := tt.objects[i].Children() + for j := 0; j < i; j++ { + id, ok := tt.objects[j].ID() + require.True(t, ok) + require.Equal(t, id, children[j]) + } + } + } + require.Equal(t, expectedPayload, actualPayload) + + t.Run("parent checksum", func(t *testing.T) { + cs, ok := ids.ParentHeader.PayloadChecksum() + require.True(t, ok) + + h := sha256.Sum256(expectedPayload) + require.Equal(t, h[:], cs.Value()) + }) +} + +func newObject(cnr cid.ID) *objectSDK.Object { + ver := version.Current() + hdr := objectSDK.New() + hdr.SetContainerID(cnr) + hdr.SetType(objectSDK.TypeRegular) + hdr.SetVersion(&ver) + return hdr +} + +func writeObject(t *testing.T, ctx context.Context, target ChunkedObjectWriter, header *objectSDK.Object, payload []byte) *AccessIdentifiers { + require.NoError(t, target.WriteHeader(ctx, header)) + + _, err := target.Write(ctx, payload) + require.NoError(t, err) + + ids, err := target.Close(ctx) + require.NoError(t, err) + + return ids +} + +func BenchmarkTransformer(b *testing.B) { + hdr := newObject(cidtest.ID()) + + const ( + // bufferSize is taken from https://git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/src/commit/670619d2426fee233a37efe21a0471989b16a4fc/pool/pool.go#L1825 + bufferSize = 3 * 1024 * 1024 + smallSize = 8 * 1024 + bigSize = 64 * 1024 * 1024 * 9 / 2 // 4.5 parts + ) + b.Run("small", func(b *testing.B) { + b.Run("no size hint", func(b *testing.B) { + benchmarkTransformer(b, hdr, smallSize, 0, 0) + }) + b.Run("no size hint, with buffer", func(b *testing.B) { + benchmarkTransformer(b, hdr, smallSize, 0, bufferSize) + }) + b.Run("with size hint, with buffer", func(b *testing.B) { + benchmarkTransformer(b, hdr, smallSize, smallSize, bufferSize) + }) + }) + b.Run("big", func(b *testing.B) { + b.Run("no size hint", func(b *testing.B) { + benchmarkTransformer(b, hdr, bigSize, 0, 0) + }) + b.Run("no size hint, with buffer", func(b *testing.B) { + benchmarkTransformer(b, hdr, bigSize, 0, bufferSize) + }) + b.Run("with size hint, with buffer", func(b *testing.B) { + benchmarkTransformer(b, hdr, bigSize, bigSize, bufferSize) + }) + }) +} + +func benchmarkTransformer(b *testing.B, header *objectSDK.Object, payloadSize, sizeHint, bufferSize int) { + const maxSize = 64 * 1024 * 1024 + + payload := make([]byte, payloadSize) + ctx := context.Background() + + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + f, _ := newPayloadSizeLimiter(maxSize, uint64(sizeHint), func() ObjectWriter { return benchTarget{} }) + if err := f.WriteHeader(ctx, header); err != nil { + b.Fatalf("write header: %v", err) + } + if bufferSize == 0 { + if _, err := f.Write(ctx, payload); err != nil { + b.Fatalf("write: %v", err) + } + } else { + j := 0 + for ; j+bufferSize < payloadSize; j += bufferSize { + if _, err := f.Write(ctx, payload[j:j+bufferSize]); err != nil { + b.Fatalf("write: %v", err) + } + } + if _, err := f.Write(ctx, payload[j:payloadSize]); err != nil { + b.Fatalf("write: %v", err) + } + } + if _, err := f.Close(ctx); err != nil { + b.Fatalf("close: %v", err) + } + } +} + +func newPayloadSizeLimiter(maxSize uint64, sizeHint uint64, nextTarget TargetInitializer) (ChunkedObjectWriter, *keys.PrivateKey) { + p, err := keys.NewPrivateKey() + if err != nil { + panic(err) + } + + return NewPayloadSizeLimiter(Params{ + Key: &p.PrivateKey, + NextTargetInit: nextTarget, + NetworkState: dummyEpochSource(123), + MaxSize: maxSize, + SizeHint: sizeHint, + WithoutHomomorphicHash: true, + }), p +} + +type dummyEpochSource uint64 + +func (s dummyEpochSource) CurrentEpoch() uint64 { + return uint64(s) +} + +type benchTarget struct{} + +func (benchTarget) WriteObject(context.Context, *objectSDK.Object) error { + return nil +} + +type testTarget struct { + objects []*objectSDK.Object +} + +func (tt *testTarget) WriteObject(_ context.Context, o *objectSDK.Object) error { + tt.objects = append(tt.objects, o) + return nil // AccessIdentifiers should not be used. +} diff --git a/pkg/sdk/object/transformer/types.go b/pkg/sdk/object/transformer/types.go new file mode 100644 index 000000000..e06ad043b --- /dev/null +++ b/pkg/sdk/object/transformer/types.go @@ -0,0 +1,62 @@ +package transformer + +import ( + "context" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" +) + +// AccessIdentifiers represents group of the object identifiers +// that are returned after writing the object. +// Consists of the ID of the stored object and the ID of the parent object. +type AccessIdentifiers struct { + ParentID *oid.ID + SelfID oid.ID + ParentHeader *object.Object +} + +// EpochSource is a source for the current epoch. +type EpochSource interface { + CurrentEpoch() uint64 +} + +// ChunkedObjectWriter is an interface of the object writer +// that writes object chunked. +type ChunkedObjectWriter interface { + // WriteHeader writes object header w/ payload part. + // The payload of the object may be incomplete. + // + // Must be called exactly once. Control remains with the caller. + // Missing a call or re-calling can lead to undefined behavior + // that depends on the implementation. + // + // Must not be called after Close call. + WriteHeader(context.Context, *object.Object) error + + // Write writes object payload chunk. + // + // Can be called multiple times. + // + // Must not be called after Close call. + Write(context.Context, []byte) (int, error) + + // Close is used to finish object writing. + // + // Close must return access identifiers of the object + // that has been written. + // + // Must be called no more than once. Control remains with the caller. + // Re-calling can lead to undefined behavior + // that depends on the implementation. + Close(context.Context) (*AccessIdentifiers, error) +} + +// TargetInitializer represents ObjectWriter constructor. +type TargetInitializer func() ObjectWriter + +// ObjectWriter is an interface of the object writer that writes prepared object. +type ObjectWriter interface { + // WriteObject writes prepared object. + WriteObject(context.Context, *object.Object) error +} diff --git a/pkg/sdk/object/type.go b/pkg/sdk/object/type.go new file mode 100644 index 000000000..aaa068f51 --- /dev/null +++ b/pkg/sdk/object/type.go @@ -0,0 +1,48 @@ +package object + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" +) + +type Type object.Type + +const ( + TypeRegular Type = iota + TypeTombstone + _ + TypeLock +) + +func (t Type) ToV2() object.Type { + return object.Type(t) +} + +func TypeFromV2(t object.Type) Type { + return Type(t) +} + +// String returns string representation of Type. +// +// String mapping: +// - TypeTombstone: TOMBSTONE; +// - TypeLock: LOCK; +// - TypeRegular, default: REGULAR. +func (t Type) String() string { + return t.ToV2().String() +} + +// FromString parses Type from a string representation. +// It is a reverse action to String(). +// +// Returns true if s was parsed successfully. +func (t *Type) FromString(s string) bool { + var g object.Type + + ok := g.FromString(s) + + if ok { + *t = TypeFromV2(g) + } + + return ok +} diff --git a/pkg/sdk/object/type_test.go b/pkg/sdk/object/type_test.go new file mode 100644 index 000000000..a25ef1d9c --- /dev/null +++ b/pkg/sdk/object/type_test.go @@ -0,0 +1,79 @@ +package object_test + +import ( + "testing" + + v2object "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + "github.com/stretchr/testify/require" +) + +func TestType_ToV2(t *testing.T) { + typs := []struct { + t object.Type + t2 v2object.Type + }{ + { + t: object.TypeRegular, + t2: v2object.TypeRegular, + }, + { + t: object.TypeTombstone, + t2: v2object.TypeTombstone, + }, + { + t: object.TypeLock, + t2: v2object.TypeLock, + }, + } + + for _, item := range typs { + t2 := item.t.ToV2() + + require.Equal(t, item.t2, t2) + + require.Equal(t, item.t, object.TypeFromV2(item.t2)) + } +} + +func TestType_String(t *testing.T) { + toPtr := func(v object.Type) *object.Type { + return &v + } + + testEnumStrings(t, new(object.Type), []enumStringItem{ + {val: toPtr(object.TypeTombstone), str: "TOMBSTONE"}, + {val: toPtr(object.TypeRegular), str: "REGULAR"}, + {val: toPtr(object.TypeLock), str: "LOCK"}, + }) +} + +type enumIface interface { + FromString(string) bool + String() string +} + +type enumStringItem struct { + val enumIface + str string +} + +func testEnumStrings(t *testing.T, e enumIface, items []enumStringItem) { + for _, item := range items { + require.Equal(t, item.str, item.val.String()) + + s := item.val.String() + + require.True(t, e.FromString(s), s) + + require.EqualValues(t, item.val, e, item.val) + } + + // incorrect strings + for _, str := range []string{ + "some string", + "undefined", + } { + require.False(t, e.FromString(str)) + } +} diff --git a/pkg/sdk/object/wellknown_attributes.go b/pkg/sdk/object/wellknown_attributes.go new file mode 100644 index 000000000..efece3885 --- /dev/null +++ b/pkg/sdk/object/wellknown_attributes.go @@ -0,0 +1,28 @@ +package object + +const ( + // AttributeName is an attribute key that is commonly used to denote + // human-friendly name. + AttributeName = "Name" + + // AttributeFileName is an attribute key that is commonly used to denote + // file name to be associated with the object on saving. + AttributeFileName = "FileName" + + // AttributeFilePath is an attribute key that is commonly used to denote + // full path to be associated with the object on saving. Should start with a + // '/' and use '/' as a delimiting symbol. Trailing '/' should be + // interpreted as a virtual directory marker. If an object has conflicting + // FilePath and FileName, FilePath should have higher priority, because it + // is used to construct the directory tree. FilePath with trailing '/' and + // non-empty FileName attribute should not be used together. + AttributeFilePath = "FilePath" + + // AttributeTimestamp is an attribute key that is commonly used to denote + // user-defined local time of object creation in Unix Timestamp format. + AttributeTimestamp = "Timestamp" + + // AttributeContentType is an attribute key that is commonly used to denote + // MIME Content Type of object's payload. + AttributeContentType = "Content-Type" +) diff --git a/pkg/sdk/pool/cache.go b/pkg/sdk/pool/cache.go new file mode 100644 index 000000000..1f5f30c2b --- /dev/null +++ b/pkg/sdk/pool/cache.go @@ -0,0 +1,75 @@ +package pool + +import ( + "strings" + "sync/atomic" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/session" + lru "github.com/hashicorp/golang-lru/v2" +) + +type sessionCache struct { + cache *lru.Cache[string, *cacheValue] + currentEpoch atomic.Uint64 +} + +type cacheValue struct { + token session.Object +} + +func newCache() (*sessionCache, error) { + cache, err := lru.New[string, *cacheValue](100) + if err != nil { + return nil, err + } + + return &sessionCache{cache: cache}, nil +} + +// Get returns a copy of the session token from the cache without signature +// and context related fields. Returns nil if token is missing in the cache. +// It is safe to modify and re-sign returned session token. +func (c *sessionCache) Get(key string) (session.Object, bool) { + value, ok := c.cache.Get(key) + if !ok { + return session.Object{}, false + } + + if c.expired(value) { + c.cache.Remove(key) + return session.Object{}, false + } + + return value.token, true +} + +func (c *sessionCache) Put(key string, token session.Object) bool { + return c.cache.Add(key, &cacheValue{ + token: token, + }) +} + +func (c *sessionCache) DeleteByPrefix(prefix string) { + for _, key := range c.cache.Keys() { + if strings.HasPrefix(key, prefix) { + c.cache.Remove(key) + } + } +} + +func (c *sessionCache) updateEpoch(newEpoch uint64) { + epoch := c.currentEpoch.Load() + if newEpoch > epoch { + c.currentEpoch.Store(newEpoch) + } +} + +func (c *sessionCache) expired(val *cacheValue) bool { + epoch := c.currentEpoch.Load() + // use epoch+1 (clear cache beforehand) to prevent 'expired session token' error right after epoch tick + return val.token.ExpiredAt(epoch + 1) +} + +func (c *sessionCache) Epoch() uint64 { + return c.currentEpoch.Load() +} diff --git a/pkg/sdk/pool/cache_test.go b/pkg/sdk/pool/cache_test.go new file mode 100644 index 000000000..58fc867df --- /dev/null +++ b/pkg/sdk/pool/cache_test.go @@ -0,0 +1,37 @@ +package pool + +import ( + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/session" + sessiontest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/session/test" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + "github.com/stretchr/testify/require" +) + +func TestSessionCache_GetUnmodifiedToken(t *testing.T) { + const key = "Foo" + target := *sessiontest.Object() + + pk, err := keys.NewPrivateKey() + require.NoError(t, err) + + check := func(t *testing.T, tok session.Object, extra string) { + require.False(t, tok.VerifySignature(), extra) + } + + cache, err := newCache() + require.NoError(t, err) + + cache.Put(key, target) + value, ok := cache.Get(key) + require.True(t, ok) + check(t, value, "before sign") + + err = value.Sign(pk.PrivateKey) + require.NoError(t, err) + + value, ok = cache.Get(key) + require.True(t, ok) + check(t, value, "after sign") +} diff --git a/pkg/sdk/pool/doc.go b/pkg/sdk/pool/doc.go new file mode 100644 index 000000000..ce7acb240 --- /dev/null +++ b/pkg/sdk/pool/doc.go @@ -0,0 +1,53 @@ +/* +Package pool provides a wrapper for several FrostFS API clients. + +The main component is Pool type. It is a virtual connection to the network +and provides methods for executing operations on the server. It also supports +a weighted random selection of the underlying client to make requests. + +Create pool instance with 3 nodes connection. +This InitParameters will make pool use 192.168.130.71 node while it is healthy. Otherwise, it will make the pool use +192.168.130.72 for 90% of requests and 192.168.130.73 for remaining 10%. +: + + var prm pool.InitParameters + prm.SetKey(key) + prm.AddNode(NewNodeParam(1, "192.168.130.71", 1)) + prm.AddNode(NewNodeParam(2, "192.168.130.72", 9)) + prm.AddNode(NewNodeParam(2, "192.168.130.73", 1)) + // ... + + p, err := pool.NewPool(prm) + // ... + +Connect to the FrostFS server: + + err := p.Dial(ctx) + // ... + +Execute FrostFS operation on the server: + + var prm pool.PrmContainerPut + prm.SetContainer(cnr) + // ... + + res, err := p.PutContainer(context.Background(), prm) + // ... + +Execute FrostFS operation on the server and check error: + + var prm pool.PrmObjectHead + prm.SetAddress(addr) + // ... + + res, err := p.HeadObject(context.Background(), prm) + if client.IsErrObjectNotFound(err) { + // ... + } + // ... + +Close the connection: + + p.Close() +*/ +package pool diff --git a/pkg/sdk/pool/mock_test.go b/pkg/sdk/pool/mock_test.go new file mode 100644 index 000000000..6e9558357 --- /dev/null +++ b/pkg/sdk/pool/mock_test.go @@ -0,0 +1,200 @@ +package pool + +import ( + "context" + "crypto/ecdsa" + "errors" + + "go.uber.org/zap" + + sessionv2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/accounting" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/crypto/ecdsa" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/eacl" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/session" + "github.com/google/uuid" +) + +type mockClient struct { + key ecdsa.PrivateKey + clientStatusMonitor + + errorOnDial bool + errorOnCreateSession bool + errorOnEndpointInfo bool + errorOnNetworkInfo bool + stOnGetObject apistatus.Status +} + +func newMockClient(addr string, key ecdsa.PrivateKey) *mockClient { + return &mockClient{ + key: key, + clientStatusMonitor: newClientStatusMonitor(zap.NewExample(), addr, 10), + } +} + +func (m *mockClient) setThreshold(threshold uint32) { + m.errorThreshold = threshold +} + +func (m *mockClient) errOnCreateSession() { + m.errorOnCreateSession = true +} + +func (m *mockClient) errOnEndpointInfo() { + m.errorOnEndpointInfo = true +} + +func (m *mockClient) errOnNetworkInfo() { + m.errorOnEndpointInfo = true +} + +func (m *mockClient) errOnDial() { + m.errorOnDial = true + m.errOnCreateSession() + m.errOnEndpointInfo() + m.errOnNetworkInfo() +} + +func (m *mockClient) statusOnGetObject(st apistatus.Status) { + m.stOnGetObject = st +} + +func newToken(key ecdsa.PrivateKey) *session.Object { + var tok session.Object + tok.SetID(uuid.New()) + pk := frostfsecdsa.PublicKey(key.PublicKey) + tok.SetAuthKey(&pk) + + return &tok +} + +func (m *mockClient) balanceGet(context.Context, PrmBalanceGet) (accounting.Decimal, error) { + return accounting.Decimal{}, nil +} + +func (m *mockClient) containerPut(context.Context, PrmContainerPut) (cid.ID, error) { + return cid.ID{}, nil +} + +func (m *mockClient) containerGet(context.Context, PrmContainerGet) (container.Container, error) { + return container.Container{}, nil +} + +func (m *mockClient) containerList(context.Context, PrmContainerList) ([]cid.ID, error) { + return nil, nil +} + +func (m *mockClient) containerDelete(context.Context, PrmContainerDelete) error { + return nil +} + +func (m *mockClient) containerEACL(context.Context, PrmContainerEACL) (eacl.Table, error) { + return eacl.Table{}, nil +} + +func (m *mockClient) containerSetEACL(context.Context, PrmContainerSetEACL) error { + return nil +} + +func (m *mockClient) endpointInfo(ctx context.Context, _ prmEndpointInfo) (netmap.NodeInfo, error) { + var ni netmap.NodeInfo + + if m.errorOnEndpointInfo { + return ni, m.handleError(ctx, nil, errors.New("error")) + } + + ni.SetNetworkEndpoints(m.addr) + return ni, nil +} + +func (m *mockClient) networkInfo(ctx context.Context, _ prmNetworkInfo) (netmap.NetworkInfo, error) { + var ni netmap.NetworkInfo + + if m.errorOnNetworkInfo { + return ni, m.handleError(ctx, nil, errors.New("error")) + } + + return ni, nil +} + +func (m *mockClient) netMapSnapshot(context.Context, prmNetMapSnapshot) (netmap.NetMap, error) { + var nm netmap.NetMap + return nm, nil +} + +func (m *mockClient) objectPut(context.Context, PrmObjectPut) (oid.ID, error) { + return oid.ID{}, nil +} + +func (m *mockClient) objectDelete(context.Context, PrmObjectDelete) error { + return nil +} + +func (m *mockClient) objectGet(ctx context.Context, _ PrmObjectGet) (ResGetObject, error) { + var res ResGetObject + + if m.stOnGetObject == nil { + return res, nil + } + + status := apistatus.ErrFromStatus(m.stOnGetObject) + return res, m.handleError(ctx, status, nil) +} + +func (m *mockClient) objectHead(context.Context, PrmObjectHead) (object.Object, error) { + return object.Object{}, nil +} + +func (m *mockClient) objectRange(context.Context, PrmObjectRange) (ResObjectRange, error) { + return ResObjectRange{}, nil +} + +func (m *mockClient) objectSearch(context.Context, PrmObjectSearch) (ResObjectSearch, error) { + return ResObjectSearch{}, nil +} + +func (m *mockClient) sessionCreate(ctx context.Context, _ prmCreateSession) (resCreateSession, error) { + if m.errorOnCreateSession { + return resCreateSession{}, m.handleError(ctx, nil, errors.New("error")) + } + + tok := newToken(m.key) + + var v2tok sessionv2.Token + tok.WriteToV2(&v2tok) + + return resCreateSession{ + id: v2tok.GetBody().GetID(), + sessionKey: v2tok.GetBody().GetSessionKey(), + }, nil +} + +func (m *mockClient) dial(context.Context) error { + if m.errorOnDial { + return errors.New("dial error") + } + return nil +} + +func (m *mockClient) restartIfUnhealthy(ctx context.Context) (healthy bool, changed bool) { + _, err := m.endpointInfo(ctx, prmEndpointInfo{}) + healthy = err == nil + changed = healthy != m.isHealthy() + if healthy { + m.setHealthy() + } else { + m.setUnhealthy() + } + return +} + +func (m *mockClient) close() error { + return nil +} diff --git a/pkg/sdk/pool/object_put_pool_transformer.go b/pkg/sdk/pool/object_put_pool_transformer.go new file mode 100644 index 000000000..047b89e27 --- /dev/null +++ b/pkg/sdk/pool/object_put_pool_transformer.go @@ -0,0 +1,164 @@ +package pool + +import ( + "context" + + sdkClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/transformer" + "go.uber.org/zap" + "go.uber.org/zap/zapcore" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +type logger interface { + log(level zapcore.Level, msg string, fields ...zap.Field) +} + +type PrmObjectPutClientCutInit struct { + PrmObjectPut +} + +func (c *clientWrapper) objectPutInitTransformer(prm PrmObjectPutClientCutInit) (*objectWriterTransformer, error) { + cl, err := c.getClient() + if err != nil { + return nil, err + } + var w objectWriterTransformer + + w.it = internalTarget{ + client: cl, + prm: prm, + address: c.address(), + logger: &c.clientStatusMonitor, + } + + key := &c.prm.key + if prm.key != nil { + key = prm.key + } + + w.ot = transformer.NewPayloadSizeLimiter(transformer.Params{ + Key: key, + NextTargetInit: func() transformer.ObjectWriter { return &w.it }, + MaxSize: prm.networkInfo.MaxObjectSize(), + WithoutHomomorphicHash: prm.withoutHomomorphicHash, + NetworkState: prm.networkInfo, + SessionToken: prm.stoken, + }) + return &w, nil +} + +type objectWriterTransformer struct { + ot transformer.ChunkedObjectWriter + it internalTarget + err error +} + +func (x *objectWriterTransformer) WriteHeader(ctx context.Context, hdr object.Object) bool { + x.err = x.ot.WriteHeader(ctx, &hdr) + return x.err == nil +} + +func (x *objectWriterTransformer) WritePayloadChunk(ctx context.Context, chunk []byte) bool { + _, x.err = x.ot.Write(ctx, chunk) + return x.err == nil +} + +// ResObjectPut groups the final result values of ObjectPutInit operation. +type ResObjectPut struct { + Status apistatus.Status + OID oid.ID +} + +// Close return non nil result in any case. If error occurred, the result contains only buffer for further reusing. +func (x *objectWriterTransformer) Close(ctx context.Context) (*ResObjectPut, error) { + ai, err := x.ot.Close(ctx) + if err != nil { + return nil, err + } + + if ai != nil && ai.ParentID != nil { + x.it.res.OID = *ai.ParentID + } + return &x.it.res, nil +} + +type internalTarget struct { + client *sdkClient.Client + res ResObjectPut + prm PrmObjectPutClientCutInit + useStream bool + address string + logger logger + resolveFrostFSErrors bool +} + +func (it *internalTarget) WriteObject(ctx context.Context, o *object.Object) error { + putSingleImplemented, err := it.tryPutSingle(ctx, o) + if putSingleImplemented { + return err + } + + it.logger.log(zapcore.DebugLevel, "putSingle not implemented, trying put as stream", zap.String("address", it.address)) + + it.useStream = true + return it.putAsStream(ctx, o) +} + +func (it *internalTarget) putAsStream(ctx context.Context, o *object.Object) error { + cliPrm := sdkClient.PrmObjectPutInit{ + CopiesNumber: it.prm.copiesNumber, + Session: it.prm.stoken, + Key: it.prm.key, + BearerToken: it.prm.btoken, + } + + wrt, err := it.client.ObjectPutInit(ctx, cliPrm) + if err != nil { + return err + } + if wrt.WriteHeader(ctx, *o) { + wrt.WritePayloadChunk(ctx, o.Payload()) + } + res, err := wrt.Close(ctx) + if res != nil { + it.res.Status = res.Status() + it.res.OID = res.StoredObjectID() + } + return err +} + +func (it *internalTarget) tryPutSingle(ctx context.Context, o *object.Object) (bool, error) { + if it.useStream { + return false, nil + } + cliPrm := sdkClient.PrmObjectPutSingle{ + CopiesNumber: it.prm.copiesNumber, + Key: it.prm.key, + Session: it.prm.stoken, + BearerToken: it.prm.btoken, + Object: o, + } + + res, err := it.client.ObjectPutSingle(ctx, cliPrm) + if err != nil && status.Code(err) == codes.Unimplemented { + return false, err + } + + if err == nil { + id, _ := o.ID() + it.res = ResObjectPut{ + Status: res.Status(), + OID: id, + } + if !it.resolveFrostFSErrors && !apistatus.IsSuccessful(it.res.Status) { + return true, apistatus.ErrFromStatus(it.res.Status) + } + return true, nil + } + return true, err +} diff --git a/pkg/sdk/pool/pool.go b/pkg/sdk/pool/pool.go new file mode 100644 index 000000000..6c30c1554 --- /dev/null +++ b/pkg/sdk/pool/pool.go @@ -0,0 +1,3031 @@ +package pool + +import ( + "bytes" + "context" + "crypto/ecdsa" + "errors" + "fmt" + "io" + "math" + "math/rand" + "sort" + "sync" + "sync/atomic" + "time" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/accounting" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/bearer" + sdkClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/crypto/ecdsa" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/eacl" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/relations" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" + "github.com/google/uuid" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + "go.uber.org/zap" + "go.uber.org/zap/zapcore" + "google.golang.org/grpc" +) + +// client represents virtual connection to the single FrostFS network endpoint from which Pool is formed. +// This interface is expected to have exactly one production implementation - clientWrapper. +// Others are expected to be for test purposes only. +type client interface { + // see clientWrapper.balanceGet. + balanceGet(context.Context, PrmBalanceGet) (accounting.Decimal, error) + // see clientWrapper.containerPut. + containerPut(context.Context, PrmContainerPut) (cid.ID, error) + // see clientWrapper.containerGet. + containerGet(context.Context, PrmContainerGet) (container.Container, error) + // see clientWrapper.containerList. + containerList(context.Context, PrmContainerList) ([]cid.ID, error) + // see clientWrapper.containerDelete. + containerDelete(context.Context, PrmContainerDelete) error + // see clientWrapper.containerEACL. + containerEACL(context.Context, PrmContainerEACL) (eacl.Table, error) + // see clientWrapper.containerSetEACL. + containerSetEACL(context.Context, PrmContainerSetEACL) error + // see clientWrapper.endpointInfo. + endpointInfo(context.Context, prmEndpointInfo) (netmap.NodeInfo, error) + // see clientWrapper.networkInfo. + networkInfo(context.Context, prmNetworkInfo) (netmap.NetworkInfo, error) + // see clientWrapper.netMapSnapshot + netMapSnapshot(context.Context, prmNetMapSnapshot) (netmap.NetMap, error) + // see clientWrapper.objectPut. + objectPut(context.Context, PrmObjectPut) (oid.ID, error) + // see clientWrapper.objectDelete. + objectDelete(context.Context, PrmObjectDelete) error + // see clientWrapper.objectGet. + objectGet(context.Context, PrmObjectGet) (ResGetObject, error) + // see clientWrapper.objectHead. + objectHead(context.Context, PrmObjectHead) (object.Object, error) + // see clientWrapper.objectRange. + objectRange(context.Context, PrmObjectRange) (ResObjectRange, error) + // see clientWrapper.objectSearch. + objectSearch(context.Context, PrmObjectSearch) (ResObjectSearch, error) + // see clientWrapper.sessionCreate. + sessionCreate(context.Context, prmCreateSession) (resCreateSession, error) + + clientStatus + + // see clientWrapper.dial. + dial(ctx context.Context) error + // see clientWrapper.restartIfUnhealthy. + restartIfUnhealthy(ctx context.Context) (bool, bool) + // see clientWrapper.close. + close() error +} + +// clientStatus provide access to some metrics for connection. +type clientStatus interface { + // isHealthy checks if the connection can handle requests. + isHealthy() bool + // isDialed checks if the connection was created. + isDialed() bool + // setUnhealthy marks client as unhealthy. + setUnhealthy() + // address return address of endpoint. + address() string + // currentErrorRate returns current errors rate. + // After specific threshold connection is considered as unhealthy. + // Pool.startRebalance routine can make this connection healthy again. + currentErrorRate() uint32 + // overallErrorRate returns the number of all happened errors. + overallErrorRate() uint64 + // methodsStatus returns statistic for all used methods. + methodsStatus() []statusSnapshot +} + +// errPoolClientUnhealthy is an error to indicate that client in pool is unhealthy. +var errPoolClientUnhealthy = errors.New("pool client unhealthy") + +// clientStatusMonitor count error rate and other statistics for connection. +type clientStatusMonitor struct { + logger *zap.Logger + addr string + healthy *atomic.Uint32 + errorThreshold uint32 + + mu sync.RWMutex // protect counters + currentErrorCount uint32 + overallErrorCount uint64 + methods []*methodStatus +} + +// values for healthy status of clientStatusMonitor. +const ( + // statusUnhealthyOnDial is set when dialing to the endpoint is failed, + // so there is no connection to the endpoint, and pool should not close it + // before re-establishing connection once again. + statusUnhealthyOnDial = iota + + // statusUnhealthyOnRequest is set when communication after dialing to the + // endpoint is failed due to immediate or accumulated errors, connection is + // available and pool should close it before re-establishing connection once again. + statusUnhealthyOnRequest + + // statusHealthy is set when connection is ready to be used by the pool. + statusHealthy +) + +// methodStatus provide statistic for specific method. +type methodStatus struct { + name string + mu sync.RWMutex // protect counters + statusSnapshot +} + +// statusSnapshot is statistic for specific method. +type statusSnapshot struct { + allTime uint64 + allRequests uint64 +} + +// MethodIndex index of method in list of statuses in clientStatusMonitor. +type MethodIndex int + +const ( + methodBalanceGet MethodIndex = iota + methodContainerPut + methodContainerGet + methodContainerList + methodContainerDelete + methodContainerEACL + methodContainerSetEACL + methodEndpointInfo + methodNetworkInfo + methodNetMapSnapshot + methodObjectPut + methodObjectDelete + methodObjectGet + methodObjectHead + methodObjectRange + methodSessionCreate + methodLast +) + +// String implements fmt.Stringer. +func (m MethodIndex) String() string { + switch m { + case methodBalanceGet: + return "balanceGet" + case methodContainerPut: + return "containerPut" + case methodContainerGet: + return "containerGet" + case methodContainerList: + return "containerList" + case methodContainerDelete: + return "containerDelete" + case methodContainerEACL: + return "containerEACL" + case methodContainerSetEACL: + return "containerSetEACL" + case methodEndpointInfo: + return "endpointInfo" + case methodNetworkInfo: + return "networkInfo" + case methodNetMapSnapshot: + return "netMapSnapshot" + case methodObjectPut: + return "objectPut" + case methodObjectDelete: + return "objectDelete" + case methodObjectGet: + return "objectGet" + case methodObjectHead: + return "objectHead" + case methodObjectRange: + return "objectRange" + case methodSessionCreate: + return "sessionCreate" + case methodLast: + return "it's a system name rather than a method" + default: + return "unknown" + } +} + +func newClientStatusMonitor(logger *zap.Logger, addr string, errorThreshold uint32) clientStatusMonitor { + methods := make([]*methodStatus, methodLast) + for i := methodBalanceGet; i < methodLast; i++ { + methods[i] = &methodStatus{name: i.String()} + } + + healthy := new(atomic.Uint32) + healthy.Store(statusHealthy) + + return clientStatusMonitor{ + logger: logger, + addr: addr, + healthy: healthy, + errorThreshold: errorThreshold, + methods: methods, + } +} + +func (m *methodStatus) snapshot() statusSnapshot { + m.mu.RLock() + defer m.mu.RUnlock() + return m.statusSnapshot +} + +func (m *methodStatus) incRequests(elapsed time.Duration) { + m.mu.Lock() + defer m.mu.Unlock() + m.allTime += uint64(elapsed) + m.allRequests++ +} + +// clientWrapper is used by default, alternative implementations are intended for testing purposes only. +type clientWrapper struct { + clientMutex sync.RWMutex + client *sdkClient.Client + prm wrapperPrm + + clientStatusMonitor +} + +// wrapperPrm is params to create clientWrapper. +type wrapperPrm struct { + logger *zap.Logger + address string + key ecdsa.PrivateKey + dialTimeout time.Duration + streamTimeout time.Duration + errorThreshold uint32 + responseInfoCallback func(sdkClient.ResponseMetaInfo) error + poolRequestInfoCallback func(RequestInfo) + dialOptions []grpc.DialOption +} + +// setAddress sets endpoint to connect in FrostFS network. +func (x *wrapperPrm) setAddress(address string) { + x.address = address +} + +// setKey sets sdkClient.Client private key to be used for the protocol communication by default. +func (x *wrapperPrm) setKey(key ecdsa.PrivateKey) { + x.key = key +} + +// setLogger sets sdkClient.Client logger. +func (x *wrapperPrm) setLogger(logger *zap.Logger) { + x.logger = logger +} + +// setDialTimeout sets the timeout for connection to be established. +func (x *wrapperPrm) setDialTimeout(timeout time.Duration) { + x.dialTimeout = timeout +} + +// setStreamTimeout sets the timeout for individual operations in streaming RPC. +func (x *wrapperPrm) setStreamTimeout(timeout time.Duration) { + x.streamTimeout = timeout +} + +// setErrorThreshold sets threshold after reaching which connection is considered unhealthy +// until Pool.startRebalance routing updates its status. +func (x *wrapperPrm) setErrorThreshold(threshold uint32) { + x.errorThreshold = threshold +} + +// setPoolRequestCallback sets callback that will be invoked after every pool response. +func (x *wrapperPrm) setPoolRequestCallback(f func(RequestInfo)) { + x.poolRequestInfoCallback = f +} + +// setResponseInfoCallback sets callback that will be invoked after every response. +func (x *wrapperPrm) setResponseInfoCallback(f func(sdkClient.ResponseMetaInfo) error) { + x.responseInfoCallback = f +} + +// setGRPCDialOptions sets the gRPC dial options for new gRPC client connection. +func (x *wrapperPrm) setGRPCDialOptions(opts []grpc.DialOption) { + x.dialOptions = opts +} + +// newWrapper creates a clientWrapper that implements the client interface. +func newWrapper(prm wrapperPrm) *clientWrapper { + var cl sdkClient.Client + prmInit := sdkClient.PrmInit{ + Key: prm.key, + ResponseInfoCallback: prm.responseInfoCallback, + } + + cl.Init(prmInit) + + res := &clientWrapper{ + client: &cl, + clientStatusMonitor: newClientStatusMonitor(prm.logger, prm.address, prm.errorThreshold), + prm: prm, + } + + return res +} + +// dial establishes a connection to the server from the FrostFS network. +// Returns an error describing failure reason. If failed, the client +// SHOULD NOT be used. +func (c *clientWrapper) dial(ctx context.Context) error { + cl, err := c.getClient() + if err != nil { + return err + } + + prmDial := sdkClient.PrmDial{ + Endpoint: c.prm.address, + DialTimeout: c.prm.dialTimeout, + StreamTimeout: c.prm.streamTimeout, + GRPCDialOptions: c.prm.dialOptions, + } + + if err = cl.Dial(ctx, prmDial); err != nil { + c.setUnhealthyOnDial() + return err + } + + return nil +} + +// restartIfUnhealthy checks healthy status of client and recreate it if status is unhealthy. +// Return current healthy status and indicating if status was changed by this function call. +func (c *clientWrapper) restartIfUnhealthy(ctx context.Context) (healthy, changed bool) { + var wasHealthy bool + if _, err := c.endpointInfo(ctx, prmEndpointInfo{}); err == nil { + return true, false + } else if !errors.Is(err, errPoolClientUnhealthy) { + wasHealthy = true + } + + // if connection is dialed before, to avoid routine / connection leak, + // pool has to close it and then initialize once again. + if c.isDialed() { + _ = c.close() + } + + var cl sdkClient.Client + prmInit := sdkClient.PrmInit{ + Key: c.prm.key, + ResponseInfoCallback: c.prm.responseInfoCallback, + } + + cl.Init(prmInit) + + prmDial := sdkClient.PrmDial{ + Endpoint: c.prm.address, + DialTimeout: c.prm.dialTimeout, + StreamTimeout: c.prm.streamTimeout, + GRPCDialOptions: c.prm.dialOptions, + } + + if err := cl.Dial(ctx, prmDial); err != nil { + c.setUnhealthyOnDial() + return false, wasHealthy + } + + c.clientMutex.Lock() + c.client = &cl + c.clientMutex.Unlock() + + if _, err := cl.EndpointInfo(ctx, sdkClient.PrmEndpointInfo{}); err != nil { + c.setUnhealthy() + return false, wasHealthy + } + + c.setHealthy() + return true, !wasHealthy +} + +func (c *clientWrapper) getClient() (*sdkClient.Client, error) { + c.clientMutex.RLock() + defer c.clientMutex.RUnlock() + if c.isHealthy() { + return c.client, nil + } + return nil, errPoolClientUnhealthy +} + +// balanceGet invokes sdkClient.BalanceGet parse response status to error and return result as is. +func (c *clientWrapper) balanceGet(ctx context.Context, prm PrmBalanceGet) (accounting.Decimal, error) { + cl, err := c.getClient() + if err != nil { + return accounting.Decimal{}, err + } + + cliPrm := sdkClient.PrmBalanceGet{ + Account: prm.account, + } + + start := time.Now() + res, err := cl.BalanceGet(ctx, cliPrm) + c.incRequests(time.Since(start), methodBalanceGet) + var st apistatus.Status + if res != nil { + st = res.Status() + } + if err = c.handleError(ctx, st, err); err != nil { + return accounting.Decimal{}, fmt.Errorf("balance get on client: %w", err) + } + + return res.Amount(), nil +} + +// containerPut invokes sdkClient.ContainerPut parse response status to error and return result as is. +// It also waits for the container to appear on the network. +func (c *clientWrapper) containerPut(ctx context.Context, prm PrmContainerPut) (cid.ID, error) { + cl, err := c.getClient() + if err != nil { + return cid.ID{}, err + } + + start := time.Now() + res, err := cl.ContainerPut(ctx, prm.ClientParams) + c.incRequests(time.Since(start), methodContainerPut) + var st apistatus.Status + if res != nil { + st = res.Status() + } + if err = c.handleError(ctx, st, err); err != nil { + return cid.ID{}, fmt.Errorf("container put on client: %w", err) + } + + if prm.WaitParams == nil { + prm.WaitParams = defaultWaitParams() + } + if err = prm.WaitParams.CheckValidity(); err != nil { + return cid.ID{}, fmt.Errorf("invalid wait parameters: %w", err) + } + + idCnr := res.ID() + + getPrm := PrmContainerGet{ + ContainerID: idCnr, + Session: prm.ClientParams.Session, + } + + err = waitForContainerPresence(ctx, c, getPrm, prm.WaitParams) + if err = c.handleError(ctx, nil, err); err != nil { + return cid.ID{}, fmt.Errorf("wait container presence on client: %w", err) + } + + return idCnr, nil +} + +// containerGet invokes sdkClient.ContainerGet parse response status to error and return result as is. +func (c *clientWrapper) containerGet(ctx context.Context, prm PrmContainerGet) (container.Container, error) { + cl, err := c.getClient() + if err != nil { + return container.Container{}, err + } + + cliPrm := sdkClient.PrmContainerGet{ + ContainerID: &prm.ContainerID, + Session: prm.Session, + } + + start := time.Now() + res, err := cl.ContainerGet(ctx, cliPrm) + c.incRequests(time.Since(start), methodContainerGet) + var st apistatus.Status + if res != nil { + st = res.Status() + } + if err = c.handleError(ctx, st, err); err != nil { + return container.Container{}, fmt.Errorf("container get on client: %w", err) + } + + return res.Container(), nil +} + +// containerList invokes sdkClient.ContainerList parse response status to error and return result as is. +func (c *clientWrapper) containerList(ctx context.Context, prm PrmContainerList) ([]cid.ID, error) { + cl, err := c.getClient() + if err != nil { + return nil, err + } + + cliPrm := sdkClient.PrmContainerList{ + Account: prm.OwnerID, + Session: prm.Session, + } + + start := time.Now() + res, err := cl.ContainerList(ctx, cliPrm) + c.incRequests(time.Since(start), methodContainerList) + var st apistatus.Status + if res != nil { + st = res.Status() + } + if err = c.handleError(ctx, st, err); err != nil { + return nil, fmt.Errorf("container list on client: %w", err) + } + return res.Containers(), nil +} + +// containerDelete invokes sdkClient.ContainerDelete parse response status to error. +// It also waits for the container to be removed from the network. +func (c *clientWrapper) containerDelete(ctx context.Context, prm PrmContainerDelete) error { + cl, err := c.getClient() + if err != nil { + return err + } + + cliPrm := sdkClient.PrmContainerDelete{ + ContainerID: &prm.ContainerID, + Session: prm.Session, + } + + start := time.Now() + res, err := cl.ContainerDelete(ctx, cliPrm) + c.incRequests(time.Since(start), methodContainerDelete) + var st apistatus.Status + if res != nil { + st = res.Status() + } + if err = c.handleError(ctx, st, err); err != nil { + return fmt.Errorf("container delete on client: %w", err) + } + + if prm.WaitParams == nil { + prm.WaitParams = defaultWaitParams() + } + if err := prm.WaitParams.CheckValidity(); err != nil { + return fmt.Errorf("invalid wait parameters: %w", err) + } + + getPrm := PrmContainerGet{ + ContainerID: prm.ContainerID, + Session: prm.Session, + } + + return waitForContainerRemoved(ctx, c, getPrm, prm.WaitParams) +} + +// containerEACL invokes sdkClient.ContainerEACL parse response status to error and return result as is. +func (c *clientWrapper) containerEACL(ctx context.Context, prm PrmContainerEACL) (eacl.Table, error) { + cl, err := c.getClient() + if err != nil { + return eacl.Table{}, err + } + + cliPrm := sdkClient.PrmContainerEACL{ + ContainerID: &prm.ContainerID, + Session: prm.Session, + } + + start := time.Now() + res, err := cl.ContainerEACL(ctx, cliPrm) + c.incRequests(time.Since(start), methodContainerEACL) + var st apistatus.Status + if res != nil { + st = res.Status() + } + if err = c.handleError(ctx, st, err); err != nil { + return eacl.Table{}, fmt.Errorf("get eacl on client: %w", err) + } + + return res.Table(), nil +} + +// containerSetEACL invokes sdkClient.ContainerSetEACL parse response status to error. +// It also waits for the EACL to appear on the network. +func (c *clientWrapper) containerSetEACL(ctx context.Context, prm PrmContainerSetEACL) error { + cl, err := c.getClient() + if err != nil { + return err + } + + cliPrm := sdkClient.PrmContainerSetEACL{ + Table: &prm.Table, + Session: prm.Session, + } + + start := time.Now() + res, err := cl.ContainerSetEACL(ctx, cliPrm) + c.incRequests(time.Since(start), methodContainerSetEACL) + var st apistatus.Status + if res != nil { + st = res.Status() + } + if err = c.handleError(ctx, st, err); err != nil { + return fmt.Errorf("set eacl on client: %w", err) + } + + if prm.WaitParams == nil { + prm.WaitParams = defaultWaitParams() + } + if err := prm.WaitParams.CheckValidity(); err != nil { + return fmt.Errorf("invalid wait parameters: %w", err) + } + + cnrID, _ := prm.Table.CID() + eaclPrm := PrmContainerEACL{ + ContainerID: cnrID, + Session: prm.Session, + } + + err = waitForEACLPresence(ctx, c, eaclPrm, &prm.Table, prm.WaitParams) + if err = c.handleError(ctx, nil, err); err != nil { + return fmt.Errorf("wait eacl presence on client: %w", err) + } + + return nil +} + +// endpointInfo invokes sdkClient.EndpointInfo parse response status to error and return result as is. +func (c *clientWrapper) endpointInfo(ctx context.Context, _ prmEndpointInfo) (netmap.NodeInfo, error) { + cl, err := c.getClient() + if err != nil { + return netmap.NodeInfo{}, err + } + + start := time.Now() + res, err := cl.EndpointInfo(ctx, sdkClient.PrmEndpointInfo{}) + c.incRequests(time.Since(start), methodEndpointInfo) + var st apistatus.Status + if res != nil { + st = res.Status() + } + if err = c.handleError(ctx, st, err); err != nil { + return netmap.NodeInfo{}, fmt.Errorf("endpoint info on client: %w", err) + } + + return res.NodeInfo(), nil +} + +// networkInfo invokes sdkClient.NetworkInfo parse response status to error and return result as is. +func (c *clientWrapper) networkInfo(ctx context.Context, _ prmNetworkInfo) (netmap.NetworkInfo, error) { + cl, err := c.getClient() + if err != nil { + return netmap.NetworkInfo{}, err + } + + start := time.Now() + res, err := cl.NetworkInfo(ctx, sdkClient.PrmNetworkInfo{}) + c.incRequests(time.Since(start), methodNetworkInfo) + var st apistatus.Status + if res != nil { + st = res.Status() + } + if err = c.handleError(ctx, st, err); err != nil { + return netmap.NetworkInfo{}, fmt.Errorf("network info on client: %w", err) + } + + return res.Info(), nil +} + +// networkInfo invokes sdkClient.NetworkInfo parse response status to error and return result as is. +func (c *clientWrapper) netMapSnapshot(ctx context.Context, _ prmNetMapSnapshot) (netmap.NetMap, error) { + cl, err := c.getClient() + if err != nil { + return netmap.NetMap{}, err + } + + start := time.Now() + res, err := cl.NetMapSnapshot(ctx, sdkClient.PrmNetMapSnapshot{}) + c.incRequests(time.Since(start), methodNetMapSnapshot) + var st apistatus.Status + if res != nil { + st = res.Status() + } + if err = c.handleError(ctx, st, err); err != nil { + return netmap.NetMap{}, fmt.Errorf("network map snapshot on client: %w", err) + } + + return res.NetMap(), nil +} + +// objectPut writes object to FrostFS. +func (c *clientWrapper) objectPut(ctx context.Context, prm PrmObjectPut) (oid.ID, error) { + if prm.bufferMaxSize == 0 { + prm.bufferMaxSize = defaultBufferMaxSizeForPut + } + + if prm.clientCut { + return c.objectPutClientCut(ctx, prm) + } + + return c.objectPutServerCut(ctx, prm) +} + +func (c *clientWrapper) objectPutServerCut(ctx context.Context, prm PrmObjectPut) (oid.ID, error) { + cl, err := c.getClient() + if err != nil { + return oid.ID{}, err + } + + cliPrm := sdkClient.PrmObjectPutInit{ + CopiesNumber: prm.copiesNumber, + Session: prm.stoken, + Key: prm.key, + BearerToken: prm.btoken, + } + + start := time.Now() + wObj, err := cl.ObjectPutInit(ctx, cliPrm) + c.incRequests(time.Since(start), methodObjectPut) + if err = c.handleError(ctx, nil, err); err != nil { + return oid.ID{}, fmt.Errorf("init writing on API client: %w", err) + } + + if wObj.WriteHeader(ctx, prm.hdr) { + sz := prm.hdr.PayloadSize() + + if data := prm.hdr.Payload(); len(data) > 0 { + if prm.payload != nil { + prm.payload = io.MultiReader(bytes.NewReader(data), prm.payload) + } else { + prm.payload = bytes.NewReader(data) + sz = uint64(len(data)) + } + } + + if prm.payload != nil { + if sz == 0 || sz > prm.bufferMaxSize { + sz = prm.bufferMaxSize + } + + buf := make([]byte, sz) + + var n int + + for { + n, err = prm.payload.Read(buf) + if n > 0 { + start = time.Now() + successWrite := wObj.WritePayloadChunk(ctx, buf[:n]) + c.incRequests(time.Since(start), methodObjectPut) + if !successWrite { + break + } + + continue + } + + if errors.Is(err, io.EOF) { + break + } + + return oid.ID{}, fmt.Errorf("read payload: %w", c.handleError(ctx, nil, err)) + } + } + } + + res, err := wObj.Close(ctx) + var st apistatus.Status + if res != nil { + st = res.Status() + } + if err = c.handleError(ctx, st, err); err != nil { // here err already carries both status and client errors + return oid.ID{}, fmt.Errorf("client failure: %w", err) + } + + return res.StoredObjectID(), nil +} + +func (c *clientWrapper) objectPutClientCut(ctx context.Context, prm PrmObjectPut) (oid.ID, error) { + putInitPrm := PrmObjectPutClientCutInit{ + PrmObjectPut: prm, + } + + start := time.Now() + wObj, err := c.objectPutInitTransformer(putInitPrm) + c.incRequests(time.Since(start), methodObjectPut) + if err = c.handleError(ctx, nil, err); err != nil { + return oid.ID{}, fmt.Errorf("init writing on API client: %w", err) + } + + if wObj.WriteHeader(ctx, prm.hdr) { + sz := prm.hdr.PayloadSize() + + if data := prm.hdr.Payload(); len(data) > 0 { + if prm.payload != nil { + prm.payload = io.MultiReader(bytes.NewReader(data), prm.payload) + } else { + prm.payload = bytes.NewReader(data) + sz = uint64(len(data)) + } + } + + if prm.payload != nil { + if sz == 0 || sz > prm.bufferMaxSize { + sz = prm.bufferMaxSize + } + + buf := make([]byte, sz) + + var n int + + for { + n, err = prm.payload.Read(buf) + if n > 0 { + start = time.Now() + successWrite := wObj.WritePayloadChunk(ctx, buf[:n]) + c.incRequests(time.Since(start), methodObjectPut) + if !successWrite { + break + } + + continue + } + + if errors.Is(err, io.EOF) { + break + } + + return oid.ID{}, fmt.Errorf("read payload: %w", c.handleError(ctx, nil, err)) + } + } + } + + res, err := wObj.Close(ctx) + var st apistatus.Status + if res != nil { + st = res.Status + } + if err = c.handleError(ctx, st, err); err != nil { // here err already carries both status and client errors + return oid.ID{}, fmt.Errorf("client failure: %w", err) + } + + return res.OID, nil +} + +// objectDelete invokes sdkClient.ObjectDelete parse response status to error. +func (c *clientWrapper) objectDelete(ctx context.Context, prm PrmObjectDelete) error { + cl, err := c.getClient() + if err != nil { + return err + } + + cnr := prm.addr.Container() + obj := prm.addr.Object() + + cliPrm := sdkClient.PrmObjectDelete{ + BearerToken: prm.btoken, + Session: prm.stoken, + ContainerID: &cnr, + ObjectID: &obj, + Key: prm.key, + } + + start := time.Now() + res, err := cl.ObjectDelete(ctx, cliPrm) + c.incRequests(time.Since(start), methodObjectDelete) + var st apistatus.Status + if res != nil { + st = res.Status() + } + if err = c.handleError(ctx, st, err); err != nil { + return fmt.Errorf("delete object on client: %w", err) + } + return nil +} + +// objectGet returns reader for object. +func (c *clientWrapper) objectGet(ctx context.Context, prm PrmObjectGet) (ResGetObject, error) { + cl, err := c.getClient() + if err != nil { + return ResGetObject{}, err + } + + prmCnr := prm.addr.Container() + prmObj := prm.addr.Object() + + cliPrm := sdkClient.PrmObjectGet{ + BearerToken: prm.btoken, + Session: prm.stoken, + ContainerID: &prmCnr, + ObjectID: &prmObj, + Key: prm.key, + } + + var res ResGetObject + + rObj, err := cl.ObjectGetInit(ctx, cliPrm) + if err = c.handleError(ctx, nil, err); err != nil { + return ResGetObject{}, fmt.Errorf("init object reading on client: %w", err) + } + + start := time.Now() + successReadHeader := rObj.ReadHeader(&res.Header) + c.incRequests(time.Since(start), methodObjectGet) + if !successReadHeader { + rObjRes, err := rObj.Close() + var st apistatus.Status + if rObjRes != nil { + st = rObjRes.Status() + } + err = c.handleError(ctx, st, err) + return res, fmt.Errorf("read header: %w", err) + } + + res.Payload = &objectReadCloser{ + reader: rObj, + elapsedTimeCallback: func(elapsed time.Duration) { + c.incRequests(elapsed, methodObjectGet) + }, + } + + return res, nil +} + +// objectHead invokes sdkClient.ObjectHead parse response status to error and return result as is. +func (c *clientWrapper) objectHead(ctx context.Context, prm PrmObjectHead) (object.Object, error) { + cl, err := c.getClient() + if err != nil { + return object.Object{}, err + } + + prmCnr := prm.addr.Container() + prmObj := prm.addr.Object() + + cliPrm := sdkClient.PrmObjectHead{ + BearerToken: prm.btoken, + Session: prm.stoken, + Raw: prm.raw, + ContainerID: &prmCnr, + ObjectID: &prmObj, + Key: prm.key, + } + + var obj object.Object + + start := time.Now() + res, err := cl.ObjectHead(ctx, cliPrm) + c.incRequests(time.Since(start), methodObjectHead) + var st apistatus.Status + if res != nil { + st = res.Status() + } + if err = c.handleError(ctx, st, err); err != nil { + return obj, fmt.Errorf("read object header via client: %w", err) + } + if !res.ReadHeader(&obj) { + return obj, errors.New("missing object header in response") + } + + return obj, nil +} + +// objectRange returns object range reader. +func (c *clientWrapper) objectRange(ctx context.Context, prm PrmObjectRange) (ResObjectRange, error) { + cl, err := c.getClient() + if err != nil { + return ResObjectRange{}, err + } + + prmCnr := prm.addr.Container() + prmObj := prm.addr.Object() + + cliPrm := sdkClient.PrmObjectRange{ + BearerToken: prm.btoken, + Session: prm.stoken, + ContainerID: &prmCnr, + ObjectID: &prmObj, + Offset: prm.off, + Length: prm.ln, + Key: prm.key, + } + + start := time.Now() + res, err := cl.ObjectRangeInit(ctx, cliPrm) + c.incRequests(time.Since(start), methodObjectRange) + if err = c.handleError(ctx, nil, err); err != nil { + return ResObjectRange{}, fmt.Errorf("init payload range reading on client: %w", err) + } + + return ResObjectRange{ + payload: res, + elapsedTimeCallback: func(elapsed time.Duration) { + c.incRequests(elapsed, methodObjectRange) + }, + }, nil +} + +// objectSearch invokes sdkClient.ObjectSearchInit parse response status to error and return result as is. +func (c *clientWrapper) objectSearch(ctx context.Context, prm PrmObjectSearch) (ResObjectSearch, error) { + cl, err := c.getClient() + if err != nil { + return ResObjectSearch{}, err + } + + cliPrm := sdkClient.PrmObjectSearch{ + ContainerID: &prm.cnrID, + Filters: prm.filters, + Session: prm.stoken, + BearerToken: prm.btoken, + Key: prm.key, + } + + res, err := cl.ObjectSearchInit(ctx, cliPrm) + if err = c.handleError(ctx, nil, err); err != nil { + return ResObjectSearch{}, fmt.Errorf("init object searching on client: %w", err) + } + + return ResObjectSearch{r: res}, nil +} + +// sessionCreate invokes sdkClient.SessionCreate parse response status to error and return result as is. +func (c *clientWrapper) sessionCreate(ctx context.Context, prm prmCreateSession) (resCreateSession, error) { + cl, err := c.getClient() + if err != nil { + return resCreateSession{}, err + } + + cliPrm := sdkClient.PrmSessionCreate{ + Expiration: prm.exp, + Key: &prm.key, + } + + start := time.Now() + res, err := cl.SessionCreate(ctx, cliPrm) + c.incRequests(time.Since(start), methodSessionCreate) + var st apistatus.Status + if res != nil { + st = res.Status() + } + if err = c.handleError(ctx, st, err); err != nil { + return resCreateSession{}, fmt.Errorf("session creation on client: %w", err) + } + + return resCreateSession{ + id: res.ID(), + sessionKey: res.PublicKey(), + }, nil +} + +func (c *clientStatusMonitor) isHealthy() bool { + return c.healthy.Load() == statusHealthy +} + +func (c *clientStatusMonitor) isDialed() bool { + return c.healthy.Load() != statusUnhealthyOnDial +} + +func (c *clientStatusMonitor) setHealthy() { + c.healthy.Store(statusHealthy) +} + +func (c *clientStatusMonitor) setUnhealthy() { + c.healthy.Store(statusUnhealthyOnRequest) +} + +func (c *clientStatusMonitor) setUnhealthyOnDial() { + c.healthy.Store(statusUnhealthyOnDial) +} + +func (c *clientStatusMonitor) address() string { + return c.addr +} + +func (c *clientStatusMonitor) incErrorRate() { + c.mu.Lock() + c.currentErrorCount++ + c.overallErrorCount++ + + thresholdReached := c.currentErrorCount >= c.errorThreshold + if thresholdReached { + c.setUnhealthy() + c.currentErrorCount = 0 + } + c.mu.Unlock() + + if thresholdReached { + c.log(zapcore.WarnLevel, "error threshold reached", + zap.String("address", c.addr), zap.Uint32("threshold", c.errorThreshold)) + } +} + +func (c *clientStatusMonitor) log(level zapcore.Level, msg string, fields ...zap.Field) { + if c.logger == nil { + return + } + + c.logger.Log(level, msg, fields...) +} + +func (c *clientStatusMonitor) currentErrorRate() uint32 { + c.mu.RLock() + defer c.mu.RUnlock() + return c.currentErrorCount +} + +func (c *clientStatusMonitor) overallErrorRate() uint64 { + c.mu.RLock() + defer c.mu.RUnlock() + return c.overallErrorCount +} + +func (c *clientStatusMonitor) methodsStatus() []statusSnapshot { + result := make([]statusSnapshot, len(c.methods)) + for i, val := range c.methods { + result[i] = val.snapshot() + } + + return result +} + +func (c *clientWrapper) incRequests(elapsed time.Duration, method MethodIndex) { + methodStat := c.methods[method] + methodStat.incRequests(elapsed) + if c.prm.poolRequestInfoCallback != nil { + c.prm.poolRequestInfoCallback(RequestInfo{ + Address: c.prm.address, + Method: method, + Elapsed: elapsed, + }) + } +} + +func (c *clientWrapper) close() error { + if c.client != nil { + return c.client.Close() + } + return nil +} + +func (c *clientStatusMonitor) handleError(ctx context.Context, st apistatus.Status, err error) error { + if err != nil { + if needCountError(ctx, err) { + c.incErrorRate() + } + + return err + } + + err = apistatus.ErrFromStatus(st) + switch err.(type) { + case *apistatus.ServerInternal, + *apistatus.WrongMagicNumber, + *apistatus.SignatureVerification, + *apistatus.NodeUnderMaintenance: + c.incErrorRate() + } + + return err +} + +func needCountError(ctx context.Context, err error) bool { + // non-status logic error that could be returned + // from the SDK client; should not be considered + // as a connection error + var siErr *object.SplitInfoError + if errors.As(err, &siErr) { + return false + } + + if errors.Is(ctx.Err(), context.Canceled) { + return false + } + + return true +} + +// clientBuilder is a type alias of client constructors which open connection +// to the given endpoint. +type clientBuilder = func(endpoint string) client + +// RequestInfo groups info about pool request. +type RequestInfo struct { + Address string + Method MethodIndex + Elapsed time.Duration +} + +// InitParameters contains values used to initialize connection Pool. +type InitParameters struct { + key *ecdsa.PrivateKey + logger *zap.Logger + nodeDialTimeout time.Duration + nodeStreamTimeout time.Duration + healthcheckTimeout time.Duration + clientRebalanceInterval time.Duration + sessionExpirationDuration uint64 + errorThreshold uint32 + nodeParams []NodeParam + requestCallback func(RequestInfo) + dialOptions []grpc.DialOption + + clientBuilder clientBuilder +} + +// SetKey specifies default key to be used for the protocol communication by default. +func (x *InitParameters) SetKey(key *ecdsa.PrivateKey) { + x.key = key +} + +// SetLogger specifies logger. +func (x *InitParameters) SetLogger(logger *zap.Logger) { + x.logger = logger +} + +// SetNodeDialTimeout specifies the timeout for connection to be established. +func (x *InitParameters) SetNodeDialTimeout(timeout time.Duration) { + x.nodeDialTimeout = timeout +} + +// SetNodeStreamTimeout specifies the timeout for individual operations in streaming RPC. +func (x *InitParameters) SetNodeStreamTimeout(timeout time.Duration) { + x.nodeStreamTimeout = timeout +} + +// SetHealthcheckTimeout specifies the timeout for request to node to decide if it is alive. +// +// See also Pool.Dial. +func (x *InitParameters) SetHealthcheckTimeout(timeout time.Duration) { + x.healthcheckTimeout = timeout +} + +// SetClientRebalanceInterval specifies the interval for updating nodes health status. +// +// See also Pool.Dial. +func (x *InitParameters) SetClientRebalanceInterval(interval time.Duration) { + x.clientRebalanceInterval = interval +} + +// SetSessionExpirationDuration specifies the session token lifetime in epochs. +func (x *InitParameters) SetSessionExpirationDuration(expirationDuration uint64) { + x.sessionExpirationDuration = expirationDuration +} + +// SetErrorThreshold specifies the number of errors on connection after which node is considered as unhealthy. +func (x *InitParameters) SetErrorThreshold(threshold uint32) { + x.errorThreshold = threshold +} + +// SetRequestCallback makes the pool client to pass RequestInfo for each +// request to f. Nil (default) means ignore RequestInfo. +func (x *InitParameters) SetRequestCallback(f func(RequestInfo)) { + x.requestCallback = f +} + +// AddNode append information about the node to which you want to connect. +func (x *InitParameters) AddNode(nodeParam NodeParam) { + x.nodeParams = append(x.nodeParams, nodeParam) +} + +// SetGRPCDialOptions sets the gRPC dial options for new gRPC client connection. +func (x *InitParameters) SetGRPCDialOptions(opts ...grpc.DialOption) { + x.dialOptions = opts +} + +// setClientBuilder sets clientBuilder used for client construction. +// Wraps setClientBuilderContext without a context. +func (x *InitParameters) setClientBuilder(builder clientBuilder) { + x.clientBuilder = builder +} + +// isMissingClientBuilder checks if client constructor was not specified. +func (x *InitParameters) isMissingClientBuilder() bool { + return x.clientBuilder == nil +} + +type rebalanceParameters struct { + nodesParams []*nodesParam + nodeRequestTimeout time.Duration + clientRebalanceInterval time.Duration + sessionExpirationDuration uint64 +} + +type nodesParam struct { + priority int + addresses []string + weights []float64 +} + +// NodeParam groups parameters of remote node. +type NodeParam struct { + priority int + address string + weight float64 +} + +// NewNodeParam creates NodeParam using parameters. +func NewNodeParam(priority int, address string, weight float64) (prm NodeParam) { + prm.SetPriority(priority) + prm.SetAddress(address) + prm.SetWeight(weight) + + return +} + +// SetPriority specifies priority of the node. +// Negative value is allowed. In the result node groups +// with the same priority will be sorted by descent. +func (x *NodeParam) SetPriority(priority int) { + x.priority = priority +} + +// Priority returns priority of the node. +func (x *NodeParam) Priority() int { + return x.priority +} + +// SetAddress specifies address of the node. +func (x *NodeParam) SetAddress(address string) { + x.address = address +} + +// Address returns address of the node. +func (x *NodeParam) Address() string { + return x.address +} + +// SetWeight specifies weight of the node. +func (x *NodeParam) SetWeight(weight float64) { + x.weight = weight +} + +// Weight returns weight of the node. +func (x *NodeParam) Weight() float64 { + return x.weight +} + +// WaitParams contains parameters used in polling is a something applied on FrostFS network. +type WaitParams struct { + Timeout time.Duration + PollInterval time.Duration +} + +// SetTimeout specifies the time to wait for the operation to complete. +// +// Deprecated: Use WaitParams.Timeout instead. +func (x *WaitParams) SetTimeout(timeout time.Duration) { + x.Timeout = timeout +} + +// SetPollInterval specifies the interval, once it will check the completion of the operation. +// +// Deprecated: Use WaitParams.PollInterval instead. +func (x *WaitParams) SetPollInterval(tick time.Duration) { + x.PollInterval = tick +} + +func defaultWaitParams() *WaitParams { + return &WaitParams{ + Timeout: 120 * time.Second, + PollInterval: 5 * time.Second, + } +} + +// checkForPositive panics if any of the wait params isn't positive. +func (x *WaitParams) checkForPositive() { + if x.Timeout <= 0 || x.PollInterval <= 0 { + panic("all wait params must be positive") + } +} + +// CheckForValid checks if all wait params are non-negative. +func (x *WaitParams) CheckValidity() error { + if x.Timeout <= 0 { + return errors.New("timeout cannot be negative") + } + if x.PollInterval <= 0 { + return errors.New("poll interval cannot be negative") + } + return nil +} + +type prmContext struct { + defaultSession bool + verb session.ObjectVerb + cnr cid.ID + + objSet bool + objs []oid.ID +} + +func (x *prmContext) useDefaultSession() { + x.defaultSession = true +} + +func (x *prmContext) useContainer(cnr cid.ID) { + x.cnr = cnr +} + +func (x *prmContext) useObjects(ids []oid.ID) { + x.objs = ids + x.objSet = true +} + +func (x *prmContext) useAddress(addr oid.Address) { + x.cnr = addr.Container() + x.objs = []oid.ID{addr.Object()} + x.objSet = true +} + +func (x *prmContext) useVerb(verb session.ObjectVerb) { + x.verb = verb +} + +type prmCommon struct { + key *ecdsa.PrivateKey + btoken *bearer.Token + stoken *session.Object +} + +// UseKey specifies private key to sign the requests. +// If key is not provided, then Pool default key is used. +func (x *prmCommon) UseKey(key *ecdsa.PrivateKey) { + x.key = key +} + +// UseBearer attaches bearer token to be used for the operation. +func (x *prmCommon) UseBearer(token bearer.Token) { + x.btoken = &token +} + +// UseSession specifies session within which operation should be performed. +func (x *prmCommon) UseSession(token session.Object) { + x.stoken = &token +} + +// PrmObjectPut groups parameters of PutObject operation. +type PrmObjectPut struct { + prmCommon + + hdr object.Object + + payload io.Reader + + copiesNumber []uint32 + + clientCut bool + networkInfo netmap.NetworkInfo + + withoutHomomorphicHash bool + + bufferMaxSize uint64 +} + +// SetHeader specifies header of the object. +func (x *PrmObjectPut) SetHeader(hdr object.Object) { + x.hdr = hdr +} + +// SetPayload specifies payload of the object. +func (x *PrmObjectPut) SetPayload(payload io.Reader) { + x.payload = payload +} + +// SetCopiesNumber sets number of object copies that is enough to consider put successful. +// Zero means using default behavior. +func (x *PrmObjectPut) SetCopiesNumber(copiesNumber uint32) { + x.copiesNumber = []uint32{copiesNumber} +} + +// SetCopiesNumberVector sets number of object copies that is enough to consider put successful, provided as array. +// Nil/empty vector means using default behavior. +func (x *PrmObjectPut) SetCopiesNumberVector(copiesNumber []uint32) { + x.copiesNumber = copiesNumber +} + +// SetClientCut enables client cut for objects. It means that full object is prepared on client side +// and retrying is possible. But this leads to additional memory using for buffering object parts. +// Buffer size for every put is MaxObjectSize value from FrostFS network. +// There is limit for total memory allocation for in-flight request and +// can be set by InitParameters.SetMaxClientCutMemory (default value is 1gb). +// Put requests will fail if this limit be reached. +func (x *PrmObjectPut) SetClientCut(clientCut bool) { + x.clientCut = clientCut +} + +// WithoutHomomorphicHash if set to true do not use Tillich-Zémor hash for payload. +func (x *PrmObjectPut) WithoutHomomorphicHash(v bool) { + x.withoutHomomorphicHash = v +} + +// SetBufferMaxSize sets max buffer size to read payload. +// This value isn't used if object size is set explicitly and less than this value. +// Default value 3MB. +func (x *PrmObjectPut) SetBufferMaxSize(size uint64) { + x.bufferMaxSize = size +} + +func (x *PrmObjectPut) setNetworkInfo(ni netmap.NetworkInfo) { + x.networkInfo = ni +} + +// PrmObjectDelete groups parameters of DeleteObject operation. +type PrmObjectDelete struct { + prmCommon + + addr oid.Address +} + +// SetAddress specifies FrostFS address of the object. +func (x *PrmObjectDelete) SetAddress(addr oid.Address) { + x.addr = addr +} + +// PrmObjectGet groups parameters of GetObject operation. +type PrmObjectGet struct { + prmCommon + + addr oid.Address +} + +// SetAddress specifies FrostFS address of the object. +func (x *PrmObjectGet) SetAddress(addr oid.Address) { + x.addr = addr +} + +// PrmObjectHead groups parameters of HeadObject operation. +type PrmObjectHead struct { + prmCommon + + addr oid.Address + raw bool +} + +// SetAddress specifies FrostFS address of the object. +func (x *PrmObjectHead) SetAddress(addr oid.Address) { + x.addr = addr +} + +// MarkRaw marks an intent to read physically stored object. +func (x *PrmObjectHead) MarkRaw() { + x.raw = true +} + +// PrmObjectRange groups parameters of RangeObject operation. +type PrmObjectRange struct { + prmCommon + + addr oid.Address + off, ln uint64 +} + +// SetAddress specifies FrostFS address of the object. +func (x *PrmObjectRange) SetAddress(addr oid.Address) { + x.addr = addr +} + +// SetOffset sets offset of the payload range to be read. +func (x *PrmObjectRange) SetOffset(offset uint64) { + x.off = offset +} + +// SetLength sets length of the payload range to be read. +func (x *PrmObjectRange) SetLength(length uint64) { + x.ln = length +} + +// PrmObjectSearch groups parameters of SearchObjects operation. +type PrmObjectSearch struct { + prmCommon + + cnrID cid.ID + filters object.SearchFilters +} + +// SetContainerID specifies the container in which to look for objects. +func (x *PrmObjectSearch) SetContainerID(cnrID cid.ID) { + x.cnrID = cnrID +} + +// SetFilters specifies filters by which to select objects. +func (x *PrmObjectSearch) SetFilters(filters object.SearchFilters) { + x.filters = filters +} + +// PrmContainerPut groups parameters of PutContainer operation. +type PrmContainerPut struct { + ClientParams sdkClient.PrmContainerPut + + WaitParams *WaitParams +} + +// SetContainer container structure to be used as a parameter of the base +// client's operation. +// +// See git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client.PrmContainerPut.SetContainer. +// +// Deprecated: Use PrmContainerPut.ClientParams.Container instead. +func (x *PrmContainerPut) SetContainer(cnr container.Container) { + x.ClientParams.SetContainer(cnr) +} + +// WithinSession specifies session to be used as a parameter of the base +// client's operation. +// +// See git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client.PrmContainerPut.WithinSession. +// +// Deprecated: Use PrmContainerPut.ClientParams.Session instead. +func (x *PrmContainerPut) WithinSession(s session.Container) { + x.ClientParams.WithinSession(s) +} + +// SetWaitParams specifies timeout params to complete operation. +// If not provided the default one will be used. +// Panics if any of the wait params isn't positive. +// +// Deprecated: Use PrmContainerPut.ClientParams.WaitParams instead. +func (x *PrmContainerPut) SetWaitParams(waitParams WaitParams) { + waitParams.checkForPositive() + x.WaitParams = &waitParams +} + +// PrmContainerGet groups parameters of GetContainer operation. +type PrmContainerGet struct { + ContainerID cid.ID + + Session *session.Container +} + +// SetContainerID specifies identifier of the container to be read. +// +// Deprecated: Use PrmContainerGet.ContainerID instead. +func (prm *PrmContainerGet) SetContainerID(cnrID cid.ID) { + prm.ContainerID = cnrID +} + +// PrmContainerList groups parameters of ListContainers operation. +type PrmContainerList struct { + OwnerID user.ID + + Session *session.Container +} + +// SetOwnerID specifies identifier of the FrostFS account to list the containers. +// +// Deprecated: Use PrmContainerList.OwnerID instead. +func (x *PrmContainerList) SetOwnerID(ownerID user.ID) { + x.OwnerID = ownerID +} + +// PrmContainerDelete groups parameters of DeleteContainer operation. +type PrmContainerDelete struct { + ContainerID cid.ID + + Session *session.Container + + WaitParams *WaitParams +} + +// SetContainerID specifies identifier of the FrostFS container to be removed. +// +// Deprecated: Use PrmContainerDelete.ContainerID instead. +func (x *PrmContainerDelete) SetContainerID(cnrID cid.ID) { + x.ContainerID = cnrID +} + +// SetSessionToken specifies session within which operation should be performed. +// +// Deprecated: Use PrmContainerDelete.Session instead. +func (x *PrmContainerDelete) SetSessionToken(token session.Container) { + x.Session = &token +} + +// SetWaitParams specifies timeout params to complete operation. +// If not provided the default one will be used. +// Panics if any of the wait params isn't positive. +// +// Deprecated: Use PrmContainerDelete.WaitParams instead. +func (x *PrmContainerDelete) SetWaitParams(waitParams WaitParams) { + waitParams.checkForPositive() + x.WaitParams = &waitParams +} + +// PrmContainerEACL groups parameters of GetEACL operation. +type PrmContainerEACL struct { + ContainerID cid.ID + + Session *session.Container +} + +// SetContainerID specifies identifier of the FrostFS container to read the eACL table. +// +// Deprecated: Use PrmContainerEACL.ContainerID instead. +func (x *PrmContainerEACL) SetContainerID(cnrID cid.ID) { + x.ContainerID = cnrID +} + +// PrmContainerSetEACL groups parameters of SetEACL operation. +type PrmContainerSetEACL struct { + Table eacl.Table + + Session *session.Container + + WaitParams *WaitParams +} + +// SetTable sets structure of container's extended ACL to be used as a +// parameter of the base client's operation. +// +// See git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client.PrmContainerSetEACL.SetTable. +// +// Deprecated: Use PrmContainerSetEACL.Table instead. +func (x *PrmContainerSetEACL) SetTable(table eacl.Table) { + x.Table = table +} + +// WithinSession specifies session to be used as a parameter of the base +// client's operation. +// +// See git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client.PrmContainerSetEACL.WithinSession. +// +// Deprecated: Use PrmContainerSetEACL.Session instead. +func (x *PrmContainerSetEACL) WithinSession(s session.Container) { + x.Session = &s +} + +// SetWaitParams specifies timeout params to complete operation. +// If not provided the default one will be used. +// Panics if any of the wait params isn't positive. +// +// Deprecated: Use PrmContainerSetEACL.WaitParams instead. +func (x *PrmContainerSetEACL) SetWaitParams(waitParams WaitParams) { + waitParams.checkForPositive() + x.WaitParams = &waitParams +} + +// PrmBalanceGet groups parameters of Balance operation. +type PrmBalanceGet struct { + account user.ID +} + +// SetAccount specifies identifier of the FrostFS account for which the balance is requested. +func (x *PrmBalanceGet) SetAccount(id user.ID) { + x.account = id +} + +// prmEndpointInfo groups parameters of sessionCreate operation. +type prmCreateSession struct { + exp uint64 + key ecdsa.PrivateKey +} + +// setExp sets number of the last FrostFS epoch in the lifetime of the session after which it will be expired. +func (x *prmCreateSession) setExp(exp uint64) { + x.exp = exp +} + +// useKey specifies owner private key for session token. +// If key is not provided, then Pool default key is used. +func (x *prmCreateSession) useKey(key ecdsa.PrivateKey) { + x.key = key +} + +// prmEndpointInfo groups parameters of endpointInfo operation. +type prmEndpointInfo struct{} + +// prmNetworkInfo groups parameters of networkInfo operation. +type prmNetworkInfo struct{} + +// prmNetMapSnapshot groups parameters of netMapSnapshot operation. +type prmNetMapSnapshot struct{} + +// resCreateSession groups resulting values of sessionCreate operation. +type resCreateSession struct { + id []byte + + sessionKey []byte +} + +// Pool represents virtual connection to the FrostFS network to communicate +// with multiple FrostFS servers without thinking about switching between servers +// due to load balancing proportions or their unavailability. +// It is designed to provide a convenient abstraction from the multiple sdkClient.client types. +// +// Pool can be created and initialized using NewPool function. +// Before executing the FrostFS operations using the Pool, connection to the +// servers MUST BE correctly established (see Dial method). +// Using the Pool before connecting have been established can lead to a panic. +// After the work, the Pool SHOULD BE closed (see Close method): it frees internal +// and system resources which were allocated for the period of work of the Pool. +// Calling Dial/Close methods during the communication process step strongly discouraged +// as it leads to undefined behavior. +// +// Each method which produces a FrostFS API call may return an error. +// Status of underlying server response is casted to built-in error instance. +// Certain statuses can be checked using `sdkClient` and standard `errors` packages. +// Note that package provides some helper functions to work with status returns +// (e.g. sdkClient.IsErrContainerNotFound, sdkClient.IsErrObjectNotFound). +// +// See pool package overview to get some examples. +type Pool struct { + innerPools []*innerPool + key *ecdsa.PrivateKey + cancel context.CancelFunc + closedCh chan struct{} + cache *sessionCache + stokenDuration uint64 + rebalanceParams rebalanceParameters + clientBuilder clientBuilder + logger *zap.Logger + + maxObjectSize uint64 +} + +type innerPool struct { + lock sync.RWMutex + sampler *sampler + clients []client +} + +const ( + defaultSessionTokenExpirationDuration = 100 // in blocks + defaultErrorThreshold = 100 + + defaultRebalanceInterval = 15 * time.Second + defaultHealthcheckTimeout = 4 * time.Second + defaultDialTimeout = 5 * time.Second + defaultStreamTimeout = 10 * time.Second + + defaultBufferMaxSizeForPut = 3 * 1024 * 1024 // 3 MB +) + +// NewPool creates connection pool using parameters. +func NewPool(options InitParameters) (*Pool, error) { + if options.key == nil { + return nil, fmt.Errorf("missed required parameter 'Key'") + } + + nodesParams, err := adjustNodeParams(options.nodeParams) + if err != nil { + return nil, err + } + + cache, err := newCache() + if err != nil { + return nil, fmt.Errorf("couldn't create cache: %w", err) + } + + fillDefaultInitParams(&options, cache) + + pool := &Pool{ + key: options.key, + cache: cache, + logger: options.logger, + stokenDuration: options.sessionExpirationDuration, + rebalanceParams: rebalanceParameters{ + nodesParams: nodesParams, + nodeRequestTimeout: options.healthcheckTimeout, + clientRebalanceInterval: options.clientRebalanceInterval, + sessionExpirationDuration: options.sessionExpirationDuration, + }, + clientBuilder: options.clientBuilder, + } + + return pool, nil +} + +// Dial establishes a connection to the servers from the FrostFS network. +// It also starts a routine that checks the health of the nodes and +// updates the weights of the nodes for balancing. +// Returns an error describing failure reason. +// +// If failed, the Pool SHOULD NOT be used. +// +// See also InitParameters.SetClientRebalanceInterval. +func (p *Pool) Dial(ctx context.Context) error { + inner := make([]*innerPool, len(p.rebalanceParams.nodesParams)) + var atLeastOneHealthy bool + + for i, params := range p.rebalanceParams.nodesParams { + clients := make([]client, len(params.weights)) + for j, addr := range params.addresses { + clients[j] = p.clientBuilder(addr) + if err := clients[j].dial(ctx); err != nil { + p.log(zap.WarnLevel, "failed to build client", zap.String("address", addr), zap.Error(err)) + continue + } + + var st session.Object + err := initSessionForDuration(ctx, &st, clients[j], p.rebalanceParams.sessionExpirationDuration, *p.key, false) + if err != nil { + clients[j].setUnhealthy() + p.log(zap.WarnLevel, "failed to create frostfs session token for client", + zap.String("address", addr), zap.Error(err)) + continue + } + + _ = p.cache.Put(formCacheKey(addr, p.key, false), st) + atLeastOneHealthy = true + } + source := rand.NewSource(time.Now().UnixNano()) + sampl := newSampler(params.weights, source) + + inner[i] = &innerPool{ + sampler: sampl, + clients: clients, + } + } + + if !atLeastOneHealthy { + return fmt.Errorf("at least one node must be healthy") + } + + ctx, cancel := context.WithCancel(ctx) + p.cancel = cancel + p.closedCh = make(chan struct{}) + p.innerPools = inner + + ni, err := p.NetworkInfo(ctx) + if err != nil { + return fmt.Errorf("get network info for max object size: %w", err) + } + p.maxObjectSize = ni.MaxObjectSize() + + go p.startRebalance(ctx) + return nil +} + +func (p *Pool) log(level zapcore.Level, msg string, fields ...zap.Field) { + if p.logger == nil { + return + } + + p.logger.Log(level, msg, fields...) +} + +func fillDefaultInitParams(params *InitParameters, cache *sessionCache) { + if params.sessionExpirationDuration == 0 { + params.sessionExpirationDuration = defaultSessionTokenExpirationDuration + } + + if params.errorThreshold == 0 { + params.errorThreshold = defaultErrorThreshold + } + + if params.clientRebalanceInterval <= 0 { + params.clientRebalanceInterval = defaultRebalanceInterval + } + + if params.healthcheckTimeout <= 0 { + params.healthcheckTimeout = defaultHealthcheckTimeout + } + + if params.nodeDialTimeout <= 0 { + params.nodeDialTimeout = defaultDialTimeout + } + + if params.nodeStreamTimeout <= 0 { + params.nodeStreamTimeout = defaultStreamTimeout + } + + if params.isMissingClientBuilder() { + params.setClientBuilder(func(addr string) client { + var prm wrapperPrm + prm.setAddress(addr) + prm.setKey(*params.key) + prm.setLogger(params.logger) + prm.setDialTimeout(params.nodeDialTimeout) + prm.setStreamTimeout(params.nodeStreamTimeout) + prm.setErrorThreshold(params.errorThreshold) + prm.setPoolRequestCallback(params.requestCallback) + prm.setGRPCDialOptions(params.dialOptions) + prm.setResponseInfoCallback(func(info sdkClient.ResponseMetaInfo) error { + cache.updateEpoch(info.Epoch()) + return nil + }) + return newWrapper(prm) + }) + } +} + +func adjustNodeParams(nodeParams []NodeParam) ([]*nodesParam, error) { + if len(nodeParams) == 0 { + return nil, errors.New("no FrostFS peers configured") + } + + nodesParamsMap := make(map[int]*nodesParam) + for _, param := range nodeParams { + nodes, ok := nodesParamsMap[param.priority] + if !ok { + nodes = &nodesParam{priority: param.priority} + } + nodes.addresses = append(nodes.addresses, param.address) + nodes.weights = append(nodes.weights, param.weight) + nodesParamsMap[param.priority] = nodes + } + + nodesParams := make([]*nodesParam, 0, len(nodesParamsMap)) + for _, nodes := range nodesParamsMap { + nodes.weights = adjustWeights(nodes.weights) + nodesParams = append(nodesParams, nodes) + } + + sort.Slice(nodesParams, func(i, j int) bool { + return nodesParams[i].priority < nodesParams[j].priority + }) + + return nodesParams, nil +} + +// startRebalance runs loop to monitor connection healthy status. +func (p *Pool) startRebalance(ctx context.Context) { + ticker := time.NewTimer(p.rebalanceParams.clientRebalanceInterval) + buffers := make([][]float64, len(p.rebalanceParams.nodesParams)) + for i, params := range p.rebalanceParams.nodesParams { + buffers[i] = make([]float64, len(params.weights)) + } + + for { + select { + case <-ctx.Done(): + close(p.closedCh) + return + case <-ticker.C: + p.updateNodesHealth(ctx, buffers) + ticker.Reset(p.rebalanceParams.clientRebalanceInterval) + } + } +} + +func (p *Pool) updateNodesHealth(ctx context.Context, buffers [][]float64) { + wg := sync.WaitGroup{} + for i, inner := range p.innerPools { + wg.Add(1) + + bufferWeights := buffers[i] + go func(i int, _ *innerPool) { + defer wg.Done() + p.updateInnerNodesHealth(ctx, i, bufferWeights) + }(i, inner) + } + wg.Wait() +} + +func (p *Pool) updateInnerNodesHealth(ctx context.Context, i int, bufferWeights []float64) { + if i > len(p.innerPools)-1 { + return + } + pool := p.innerPools[i] + options := p.rebalanceParams + + healthyChanged := new(atomic.Bool) + wg := sync.WaitGroup{} + + for j, cli := range pool.clients { + wg.Add(1) + go func(j int, cli client) { + defer wg.Done() + + tctx, c := context.WithTimeout(ctx, options.nodeRequestTimeout) + defer c() + + healthy, changed := cli.restartIfUnhealthy(tctx) + if healthy { + bufferWeights[j] = options.nodesParams[i].weights[j] + } else { + bufferWeights[j] = 0 + p.cache.DeleteByPrefix(cli.address()) + } + + if changed { + p.log(zap.DebugLevel, "health has changed", + zap.String("address", cli.address()), zap.Bool("healthy", healthy)) + healthyChanged.Store(true) + } + }(j, cli) + } + wg.Wait() + + if healthyChanged.Load() { + probabilities := adjustWeights(bufferWeights) + source := rand.NewSource(time.Now().UnixNano()) + pool.lock.Lock() + pool.sampler = newSampler(probabilities, source) + pool.lock.Unlock() + } +} + +func adjustWeights(weights []float64) []float64 { + adjusted := make([]float64, len(weights)) + sum := 0.0 + for _, weight := range weights { + sum += weight + } + if sum > 0 { + for i, weight := range weights { + adjusted[i] = weight / sum + } + } + + return adjusted +} + +func (p *Pool) connection() (client, error) { + for _, inner := range p.innerPools { + cp, err := inner.connection() + if err == nil { + return cp, nil + } + } + + return nil, errors.New("no healthy client") +} + +func (p *innerPool) connection() (client, error) { + p.lock.RLock() // need lock because of using p.sampler + defer p.lock.RUnlock() + if len(p.clients) == 1 { + cp := p.clients[0] + if cp.isHealthy() { + return cp, nil + } + return nil, errors.New("no healthy client") + } + attempts := 3 * len(p.clients) + for k := 0; k < attempts; k++ { + i := p.sampler.Next() + if cp := p.clients[i]; cp.isHealthy() { + return cp, nil + } + } + + return nil, errors.New("no healthy client") +} + +func formCacheKey(address string, key *ecdsa.PrivateKey, clientCut bool) string { + k := keys.PrivateKey{PrivateKey: *key} + + stype := "server" + if clientCut { + stype = "client" + } + + return address + stype + k.String() +} + +func (p *Pool) checkSessionTokenErr(err error, address string) bool { + if err == nil { + return false + } + + if sdkClient.IsErrSessionNotFound(err) || sdkClient.IsErrSessionExpired(err) { + p.cache.DeleteByPrefix(address) + return true + } + + return false +} + +func initSessionForDuration(ctx context.Context, dst *session.Object, c client, dur uint64, ownerKey ecdsa.PrivateKey, clientCut bool) error { + ni, err := c.networkInfo(ctx, prmNetworkInfo{}) + if err != nil { + return err + } + + epoch := ni.CurrentEpoch() + + var exp uint64 + if math.MaxUint64-epoch < dur { + exp = math.MaxUint64 + } else { + exp = epoch + dur + } + var prm prmCreateSession + prm.setExp(exp) + prm.useKey(ownerKey) + + var ( + id uuid.UUID + key frostfsecdsa.PublicKey + ) + + if clientCut { + id = uuid.New() + key = frostfsecdsa.PublicKey(ownerKey.PublicKey) + } else { + res, err := c.sessionCreate(ctx, prm) + if err != nil { + return err + } + if err = id.UnmarshalBinary(res.id); err != nil { + return fmt.Errorf("invalid session token ID: %w", err) + } + if err = key.Decode(res.sessionKey); err != nil { + return fmt.Errorf("invalid public session key: %w", err) + } + } + + dst.SetID(id) + dst.SetAuthKey(&key) + dst.SetExp(exp) + + return nil +} + +type callContext struct { + client client + + // client endpoint + endpoint string + + // request signer + key *ecdsa.PrivateKey + + // flag to open default session if session token is missing + sessionDefault bool + sessionTarget func(session.Object) + sessionVerb session.ObjectVerb + sessionCnr cid.ID + sessionObjSet bool + sessionObjs []oid.ID + + sessionClientCut bool +} + +func (p *Pool) initCallContext(ctx *callContext, cfg prmCommon, prmCtx prmContext) error { + cp, err := p.connection() + if err != nil { + return err + } + + ctx.key = cfg.key + if ctx.key == nil { + // use pool key if caller didn't specify its own + ctx.key = p.key + } + + ctx.endpoint = cp.address() + ctx.client = cp + + if ctx.sessionTarget != nil && cfg.stoken != nil { + ctx.sessionTarget(*cfg.stoken) + } + + // note that we don't override session provided by the caller + ctx.sessionDefault = cfg.stoken == nil && prmCtx.defaultSession + if ctx.sessionDefault { + ctx.sessionVerb = prmCtx.verb + ctx.sessionCnr = prmCtx.cnr + ctx.sessionObjSet = prmCtx.objSet + ctx.sessionObjs = prmCtx.objs + } + + return err +} + +// opens new session or uses cached one. +// Must be called only on initialized callContext with set sessionTarget. +func (p *Pool) openDefaultSession(ctx context.Context, cc *callContext) error { + cacheKey := formCacheKey(cc.endpoint, cc.key, cc.sessionClientCut) + + tok, ok := p.cache.Get(cacheKey) + if !ok { + // init new session + err := initSessionForDuration(ctx, &tok, cc.client, p.stokenDuration, *cc.key, cc.sessionClientCut) + if err != nil { + return fmt.Errorf("session API client: %w", err) + } + + // cache the opened session + p.cache.Put(cacheKey, tok) + } + + tok.ForVerb(cc.sessionVerb) + tok.BindContainer(cc.sessionCnr) + + if cc.sessionObjSet { + tok.LimitByObjects(cc.sessionObjs...) + } + + // sign the token + if err := tok.Sign(*cc.key); err != nil { + return fmt.Errorf("sign token of the opened session: %w", err) + } + + cc.sessionTarget(tok) + + return nil +} + +// opens default session (if sessionDefault is set), and calls f. If f returns +// session-related error then cached token is removed. +func (p *Pool) call(ctx context.Context, cc *callContext, f func() error) error { + var err error + + if cc.sessionDefault { + err = p.openDefaultSession(ctx, cc) + if err != nil { + return fmt.Errorf("open default session: %w", err) + } + } + + err = f() + _ = p.checkSessionTokenErr(err, cc.endpoint) + + return err +} + +// fillAppropriateKey use pool key if caller didn't specify its own. +func (p *Pool) fillAppropriateKey(prm *prmCommon) { + if prm.key == nil { + prm.key = p.key + } +} + +// PutObject writes an object through a remote server using FrostFS API protocol. +// +// Main return value MUST NOT be processed on an erroneous return. +func (p *Pool) PutObject(ctx context.Context, prm PrmObjectPut) (oid.ID, error) { + cnr, _ := prm.hdr.ContainerID() + + var prmCtx prmContext + prmCtx.useDefaultSession() + prmCtx.useVerb(session.VerbObjectPut) + prmCtx.useContainer(cnr) + + p.fillAppropriateKey(&prm.prmCommon) + + var ctxCall callContext + ctxCall.sessionClientCut = prm.clientCut + if err := p.initCallContext(&ctxCall, prm.prmCommon, prmCtx); err != nil { + return oid.ID{}, fmt.Errorf("init call context: %w", err) + } + + if ctxCall.sessionDefault { + ctxCall.sessionTarget = prm.UseSession + if err := p.openDefaultSession(ctx, &ctxCall); err != nil { + return oid.ID{}, fmt.Errorf("open default session: %w", err) + } + } + + if prm.clientCut { + var ni netmap.NetworkInfo + ni.SetCurrentEpoch(p.cache.Epoch()) + ni.SetMaxObjectSize(p.maxObjectSize) // we want to use initial max object size in PayloadSizeLimiter + prm.setNetworkInfo(ni) + } + + id, err := ctxCall.client.objectPut(ctx, prm) + if err != nil { + // removes session token from cache in case of token error + p.checkSessionTokenErr(err, ctxCall.endpoint) + return id, fmt.Errorf("init writing on API client %s: %w", ctxCall.endpoint, err) + } + + return id, nil +} + +// DeleteObject marks an object for deletion from the container using FrostFS API protocol. +// As a marker, a special unit called a tombstone is placed in the container. +// It confirms the user's intent to delete the object, and is itself a container object. +// Explicit deletion is done asynchronously, and is generally not guaranteed. +func (p *Pool) DeleteObject(ctx context.Context, prm PrmObjectDelete) error { + var prmCtx prmContext + prmCtx.useDefaultSession() + prmCtx.useVerb(session.VerbObjectDelete) + prmCtx.useAddress(prm.addr) + + if prm.stoken == nil { // collect phy objects only if we are about to open default session + var tokens relations.Tokens + tokens.Bearer = prm.btoken + + relatives, err := relations.ListAllRelations(ctx, p, prm.addr.Container(), prm.addr.Object(), tokens) + if err != nil { + return fmt.Errorf("failed to collect relatives: %w", err) + } + + if len(relatives) != 0 { + prmCtx.useContainer(prm.addr.Container()) + prmCtx.useObjects(append(relatives, prm.addr.Object())) + } + } + + p.fillAppropriateKey(&prm.prmCommon) + + var cc callContext + cc.sessionTarget = prm.UseSession + + err := p.initCallContext(&cc, prm.prmCommon, prmCtx) + if err != nil { + return err + } + + return p.call(ctx, &cc, func() error { + if err = cc.client.objectDelete(ctx, prm); err != nil { + return fmt.Errorf("remove object via client %s: %w", cc.endpoint, err) + } + + return nil + }) +} + +type objectReadCloser struct { + reader *sdkClient.ObjectReader + elapsedTimeCallback func(time.Duration) +} + +// Read implements io.Reader of the object payload. +func (x *objectReadCloser) Read(p []byte) (int, error) { + start := time.Now() + n, err := x.reader.Read(p) + x.elapsedTimeCallback(time.Since(start)) + return n, err +} + +// Close implements io.Closer of the object payload. +func (x *objectReadCloser) Close() error { + _, err := x.reader.Close() + return err +} + +// ResGetObject is designed to provide object header nad read one object payload from FrostFS system. +type ResGetObject struct { + Header object.Object + + Payload io.ReadCloser +} + +// GetObject reads object header and initiates reading an object payload through a remote server using FrostFS API protocol. +// +// Main return value MUST NOT be processed on an erroneous return. +func (p *Pool) GetObject(ctx context.Context, prm PrmObjectGet) (ResGetObject, error) { + p.fillAppropriateKey(&prm.prmCommon) + + var cc callContext + cc.sessionTarget = prm.UseSession + + var res ResGetObject + + err := p.initCallContext(&cc, prm.prmCommon, prmContext{}) + if err != nil { + return res, err + } + + return res, p.call(ctx, &cc, func() error { + res, err = cc.client.objectGet(ctx, prm) + if err != nil { + return fmt.Errorf("get object via client %s: %w", cc.endpoint, err) + } + return nil + }) +} + +// HeadObject reads object header through a remote server using FrostFS API protocol. +// +// Main return value MUST NOT be processed on an erroneous return. +func (p *Pool) HeadObject(ctx context.Context, prm PrmObjectHead) (object.Object, error) { + p.fillAppropriateKey(&prm.prmCommon) + + var cc callContext + cc.sessionTarget = prm.UseSession + + var obj object.Object + + err := p.initCallContext(&cc, prm.prmCommon, prmContext{}) + if err != nil { + return obj, err + } + + return obj, p.call(ctx, &cc, func() error { + obj, err = cc.client.objectHead(ctx, prm) + if err != nil { + return fmt.Errorf("head object via client %s: %w", cc.endpoint, err) + } + return nil + }) +} + +// ResObjectRange is designed to read payload range of one object +// from FrostFS system. +// +// Must be initialized using Pool.ObjectRange, any other +// usage is unsafe. +type ResObjectRange struct { + payload *sdkClient.ObjectRangeReader + elapsedTimeCallback func(time.Duration) +} + +// Read implements io.Reader of the object payload. +func (x *ResObjectRange) Read(p []byte) (int, error) { + start := time.Now() + n, err := x.payload.Read(p) + x.elapsedTimeCallback(time.Since(start)) + return n, err +} + +// Close ends reading the payload range and returns the result of the operation +// along with the final results. Must be called after using the ResObjectRange. +func (x *ResObjectRange) Close() error { + _, err := x.payload.Close() + return err +} + +// ObjectRange initiates reading an object's payload range through a remote +// server using FrostFS API protocol. +// +// Main return value MUST NOT be processed on an erroneous return. +func (p *Pool) ObjectRange(ctx context.Context, prm PrmObjectRange) (ResObjectRange, error) { + p.fillAppropriateKey(&prm.prmCommon) + + var cc callContext + cc.sessionTarget = prm.UseSession + + var res ResObjectRange + + err := p.initCallContext(&cc, prm.prmCommon, prmContext{}) + if err != nil { + return res, err + } + + return res, p.call(ctx, &cc, func() error { + res, err = cc.client.objectRange(ctx, prm) + if err != nil { + return fmt.Errorf("object range via client %s: %w", cc.endpoint, err) + } + return nil + }) +} + +// ResObjectSearch is designed to read list of object identifiers from FrostFS system. +// +// Must be initialized using Pool.SearchObjects, any other usage is unsafe. +type ResObjectSearch struct { + r *sdkClient.ObjectListReader +} + +// Read reads another list of the object identifiers. +func (x *ResObjectSearch) Read(buf []oid.ID) (int, error) { + n, ok := x.r.Read(buf) + if !ok { + _, err := x.r.Close() + if err == nil { + return n, io.EOF + } + + return n, err + } + + return n, nil +} + +// Iterate iterates over the list of found object identifiers. +// f can return true to stop iteration earlier. +// +// Returns an error if object can't be read. +func (x *ResObjectSearch) Iterate(f func(oid.ID) bool) error { + return x.r.Iterate(f) +} + +// Close ends reading list of the matched objects and returns the result of the operation +// along with the final results. Must be called after using the ResObjectSearch. +func (x *ResObjectSearch) Close() { + _, _ = x.r.Close() +} + +// SearchObjects initiates object selection through a remote server using FrostFS API protocol. +// +// The call only opens the transmission channel, explicit fetching of matched objects +// is done using the ResObjectSearch. Resulting reader must be finally closed. +// +// Main return value MUST NOT be processed on an erroneous return. +func (p *Pool) SearchObjects(ctx context.Context, prm PrmObjectSearch) (ResObjectSearch, error) { + p.fillAppropriateKey(&prm.prmCommon) + + var cc callContext + cc.sessionTarget = prm.UseSession + + var res ResObjectSearch + + err := p.initCallContext(&cc, prm.prmCommon, prmContext{}) + if err != nil { + return res, err + } + + return res, p.call(ctx, &cc, func() error { + res, err = cc.client.objectSearch(ctx, prm) + if err != nil { + return fmt.Errorf("search object via client %s: %w", cc.endpoint, err) + } + return nil + }) +} + +// PutContainer sends request to save container in FrostFS and waits for the operation to complete. +// +// Waiting parameters can be specified using SetWaitParams. If not called, defaults are used: +// +// polling interval: 5s +// waiting timeout: 120s +// +// Success can be verified by reading by identifier (see GetContainer). +// +// Main return value MUST NOT be processed on an erroneous return. +func (p *Pool) PutContainer(ctx context.Context, prm PrmContainerPut) (cid.ID, error) { + cp, err := p.connection() + if err != nil { + return cid.ID{}, err + } + + cnrID, err := cp.containerPut(ctx, prm) + if err != nil { + return cid.ID{}, fmt.Errorf("put container via client '%s': %w", cp.address(), err) + } + + return cnrID, nil +} + +// GetContainer reads FrostFS container by ID. +// +// Main return value MUST NOT be processed on an erroneous return. +func (p *Pool) GetContainer(ctx context.Context, prm PrmContainerGet) (container.Container, error) { + cp, err := p.connection() + if err != nil { + return container.Container{}, err + } + + cnrs, err := cp.containerGet(ctx, prm) + if err != nil { + return container.Container{}, fmt.Errorf("get container via client '%s': %w", cp.address(), err) + } + + return cnrs, nil +} + +// ListContainers requests identifiers of the account-owned containers. +func (p *Pool) ListContainers(ctx context.Context, prm PrmContainerList) ([]cid.ID, error) { + cp, err := p.connection() + if err != nil { + return nil, err + } + + cnrIDs, err := cp.containerList(ctx, prm) + if err != nil { + return []cid.ID{}, fmt.Errorf("list containers via client '%s': %w", cp.address(), err) + } + + return cnrIDs, nil +} + +// DeleteContainer sends request to remove the FrostFS container and waits for the operation to complete. +// +// Waiting parameters can be specified using SetWaitParams. If not called, defaults are used: +// +// polling interval: 5s +// waiting timeout: 120s +// +// Success can be verified by reading by identifier (see GetContainer). +func (p *Pool) DeleteContainer(ctx context.Context, prm PrmContainerDelete) error { + cp, err := p.connection() + if err != nil { + return err + } + + err = cp.containerDelete(ctx, prm) + if err != nil { + return fmt.Errorf("delete container via client '%s': %w", cp.address(), err) + } + + return nil +} + +// GetEACL reads eACL table of the FrostFS container. +// +// Main return value MUST NOT be processed on an erroneous return. +func (p *Pool) GetEACL(ctx context.Context, prm PrmContainerEACL) (eacl.Table, error) { + cp, err := p.connection() + if err != nil { + return eacl.Table{}, err + } + + eaclResult, err := cp.containerEACL(ctx, prm) + if err != nil { + return eacl.Table{}, fmt.Errorf("get EACL via client '%s': %w", cp.address(), err) + } + + return eaclResult, nil +} + +// SetEACL sends request to update eACL table of the FrostFS container and waits for the operation to complete. +// +// Waiting parameters can be specified using SetWaitParams. If not called, defaults are used: +// +// polling interval: 5s +// waiting timeout: 120s +// +// Success can be verified by reading by identifier (see GetEACL). +func (p *Pool) SetEACL(ctx context.Context, prm PrmContainerSetEACL) error { + cp, err := p.connection() + if err != nil { + return err + } + + err = cp.containerSetEACL(ctx, prm) + if err != nil { + return fmt.Errorf("set EACL via client '%s': %w", cp.address(), err) + } + + return nil +} + +// Balance requests current balance of the FrostFS account. +// +// Main return value MUST NOT be processed on an erroneous return. +func (p *Pool) Balance(ctx context.Context, prm PrmBalanceGet) (accounting.Decimal, error) { + cp, err := p.connection() + if err != nil { + return accounting.Decimal{}, err + } + + balance, err := cp.balanceGet(ctx, prm) + if err != nil { + return accounting.Decimal{}, fmt.Errorf("get balance via client '%s': %w", cp.address(), err) + } + + return balance, nil +} + +// Statistic returns connection statistics. +func (p Pool) Statistic() Statistic { + stat := Statistic{} + for _, inner := range p.innerPools { + nodes := make([]string, 0, len(inner.clients)) + inner.lock.RLock() + for _, cl := range inner.clients { + if cl.isHealthy() { + nodes = append(nodes, cl.address()) + } + node := NodeStatistic{ + address: cl.address(), + methods: cl.methodsStatus(), + overallErrors: cl.overallErrorRate(), + currentErrors: cl.currentErrorRate(), + } + stat.nodes = append(stat.nodes, node) + stat.overallErrors += node.overallErrors + } + inner.lock.RUnlock() + if len(stat.currentNodes) == 0 { + stat.currentNodes = nodes + } + } + + return stat +} + +// waitForContainerPresence waits until the container is found on the FrostFS network. +func waitForContainerPresence(ctx context.Context, cli client, prm PrmContainerGet, waitParams *WaitParams) error { + return waitFor(ctx, waitParams, func(ctx context.Context) bool { + _, err := cli.containerGet(ctx, prm) + return err == nil + }) +} + +// waitForEACLPresence waits until the container eacl is applied on the FrostFS network. +func waitForEACLPresence(ctx context.Context, cli client, prm PrmContainerEACL, table *eacl.Table, waitParams *WaitParams) error { + return waitFor(ctx, waitParams, func(ctx context.Context) bool { + eaclTable, err := cli.containerEACL(ctx, prm) + if err == nil { + return eacl.EqualTables(*table, eaclTable) + } + return false + }) +} + +// waitForContainerRemoved waits until the container is removed from the FrostFS network. +func waitForContainerRemoved(ctx context.Context, cli client, prm PrmContainerGet, waitParams *WaitParams) error { + return waitFor(ctx, waitParams, func(ctx context.Context) bool { + _, err := cli.containerGet(ctx, prm) + return sdkClient.IsErrContainerNotFound(err) + }) +} + +// waitFor await that given condition will be met in waitParams time. +func waitFor(ctx context.Context, params *WaitParams, condition func(context.Context) bool) error { + wctx, cancel := context.WithTimeout(ctx, params.Timeout) + defer cancel() + ticker := time.NewTimer(params.PollInterval) + defer ticker.Stop() + wdone := wctx.Done() + done := ctx.Done() + for { + select { + case <-done: + return ctx.Err() + case <-wdone: + return wctx.Err() + case <-ticker.C: + if condition(ctx) { + return nil + } + ticker.Reset(params.PollInterval) + } + } +} + +// NetworkInfo requests information about the FrostFS network of which the remote server is a part. +// +// Main return value MUST NOT be processed on an erroneous return. +func (p *Pool) NetworkInfo(ctx context.Context) (netmap.NetworkInfo, error) { + cp, err := p.connection() + if err != nil { + return netmap.NetworkInfo{}, err + } + + netInfo, err := cp.networkInfo(ctx, prmNetworkInfo{}) + if err != nil { + return netmap.NetworkInfo{}, fmt.Errorf("get network info via client '%s': %w", cp.address(), err) + } + + return netInfo, nil +} + +// NetMapSnapshot requests information about the FrostFS network map. +// +// Main return value MUST NOT be processed on an erroneous return. +func (p *Pool) NetMapSnapshot(ctx context.Context) (netmap.NetMap, error) { + cp, err := p.connection() + if err != nil { + return netmap.NetMap{}, err + } + + netMap, err := cp.netMapSnapshot(ctx, prmNetMapSnapshot{}) + if err != nil { + return netmap.NetMap{}, fmt.Errorf("get network map via client '%s': %w", cp.address(), err) + } + + return netMap, nil +} + +// Close closes the Pool and releases all the associated resources. +func (p *Pool) Close() { + p.cancel() + <-p.closedCh + + // close all clients + for _, pools := range p.innerPools { + for _, cli := range pools.clients { + if cli.isDialed() { + _ = cli.close() + } + } + } +} + +// SyncContainerWithNetwork applies network configuration received via +// the Pool to the container. Changes the container if it does not satisfy +// network configuration. +// +// Pool and container MUST not be nil. +// +// Returns any error that does not allow reading configuration +// from the network. +func SyncContainerWithNetwork(ctx context.Context, cnr *container.Container, p *Pool) error { + ni, err := p.NetworkInfo(ctx) + if err != nil { + return fmt.Errorf("network info: %w", err) + } + + container.ApplyNetworkConfig(cnr, ni) + + return nil +} + +// GetSplitInfo implements relations.Relations. +func (p *Pool) GetSplitInfo(ctx context.Context, cnrID cid.ID, objID oid.ID, tokens relations.Tokens) (*object.SplitInfo, error) { + var addr oid.Address + addr.SetContainer(cnrID) + addr.SetObject(objID) + + var prm PrmObjectHead + prm.SetAddress(addr) + if tokens.Bearer != nil { + prm.UseBearer(*tokens.Bearer) + } + if tokens.Session != nil { + prm.UseSession(*tokens.Session) + } + prm.MarkRaw() + + _, err := p.HeadObject(ctx, prm) + + var errSplit *object.SplitInfoError + + switch { + case errors.As(err, &errSplit): + return errSplit.SplitInfo(), nil + case err == nil: + return nil, relations.ErrNoSplitInfo + default: + return nil, fmt.Errorf("failed to get raw object header: %w", err) + } +} + +// ListChildrenByLinker implements relations.Relations. +func (p *Pool) ListChildrenByLinker(ctx context.Context, cnrID cid.ID, objID oid.ID, tokens relations.Tokens) ([]oid.ID, error) { + var addr oid.Address + addr.SetContainer(cnrID) + addr.SetObject(objID) + + var prm PrmObjectHead + prm.SetAddress(addr) + if tokens.Bearer != nil { + prm.UseBearer(*tokens.Bearer) + } + if tokens.Session != nil { + prm.UseSession(*tokens.Session) + } + + res, err := p.HeadObject(ctx, prm) + if err != nil { + return nil, fmt.Errorf("failed to get linking object's header: %w", err) + } + + return res.Children(), nil +} + +// GetLeftSibling implements relations.Relations. +func (p *Pool) GetLeftSibling(ctx context.Context, cnrID cid.ID, objID oid.ID, tokens relations.Tokens) (oid.ID, error) { + var addr oid.Address + addr.SetContainer(cnrID) + addr.SetObject(objID) + + var prm PrmObjectHead + prm.SetAddress(addr) + if tokens.Bearer != nil { + prm.UseBearer(*tokens.Bearer) + } + if tokens.Session != nil { + prm.UseSession(*tokens.Session) + } + + res, err := p.HeadObject(ctx, prm) + if err != nil { + return oid.ID{}, fmt.Errorf("failed to read split chain member's header: %w", err) + } + + idMember, ok := res.PreviousID() + if !ok { + return oid.ID{}, relations.ErrNoLeftSibling + } + return idMember, nil +} + +// FindSiblingBySplitID implements relations.Relations. +func (p *Pool) FindSiblingBySplitID(ctx context.Context, cnrID cid.ID, splitID *object.SplitID, tokens relations.Tokens) ([]oid.ID, error) { + var query object.SearchFilters + query.AddSplitIDFilter(object.MatchStringEqual, splitID) + + var prm PrmObjectSearch + prm.SetContainerID(cnrID) + prm.SetFilters(query) + if tokens.Bearer != nil { + prm.UseBearer(*tokens.Bearer) + } + if tokens.Session != nil { + prm.UseSession(*tokens.Session) + } + + res, err := p.SearchObjects(ctx, prm) + if err != nil { + return nil, fmt.Errorf("failed to search objects by split ID: %w", err) + } + + var members []oid.ID + err = res.Iterate(func(id oid.ID) bool { + members = append(members, id) + return false + }) + if err != nil { + return nil, fmt.Errorf("failed to iterate found objects: %w", err) + } + + return members, nil +} + +// FindSiblingByParentID implements relations.Relations. +func (p *Pool) FindSiblingByParentID(ctx context.Context, cnrID cid.ID, objID oid.ID, tokens relations.Tokens) ([]oid.ID, error) { + var query object.SearchFilters + query.AddParentIDFilter(object.MatchStringEqual, objID) + + var prm PrmObjectSearch + prm.SetContainerID(cnrID) + prm.SetFilters(query) + if tokens.Bearer != nil { + prm.UseBearer(*tokens.Bearer) + } + if tokens.Session != nil { + prm.UseSession(*tokens.Session) + } + + resSearch, err := p.SearchObjects(ctx, prm) + if err != nil { + return nil, fmt.Errorf("failed to find object children: %w", err) + } + + var res []oid.ID + err = resSearch.Iterate(func(id oid.ID) bool { + res = append(res, id) + return false + }) + if err != nil { + return nil, fmt.Errorf("failed to iterate found objects: %w", err) + } + + return res, nil +} diff --git a/pkg/sdk/pool/pool_test.go b/pkg/sdk/pool/pool_test.go new file mode 100644 index 000000000..41a8b8fe9 --- /dev/null +++ b/pkg/sdk/pool/pool_test.go @@ -0,0 +1,723 @@ +package pool + +import ( + "context" + "crypto/ecdsa" + "errors" + "strconv" + "testing" + "time" + + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/crypto/ecdsa" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + "github.com/stretchr/testify/require" + "go.uber.org/zap" +) + +func TestBuildPoolClientFailed(t *testing.T) { + mockClientBuilder := func(addr string) client { + mockCli := newMockClient(addr, *newPrivateKey(t)) + mockCli.errOnDial() + return mockCli + } + + opts := InitParameters{ + key: newPrivateKey(t), + nodeParams: []NodeParam{{1, "peer0", 1}}, + } + opts.setClientBuilder(mockClientBuilder) + + pool, err := NewPool(opts) + require.NoError(t, err) + err = pool.Dial(context.Background()) + require.Error(t, err) +} + +func TestBuildPoolCreateSessionFailed(t *testing.T) { + clientMockBuilder := func(addr string) client { + mockCli := newMockClient(addr, *newPrivateKey(t)) + mockCli.errOnCreateSession() + return mockCli + } + + opts := InitParameters{ + key: newPrivateKey(t), + nodeParams: []NodeParam{{1, "peer0", 1}}, + } + opts.setClientBuilder(clientMockBuilder) + + pool, err := NewPool(opts) + require.NoError(t, err) + err = pool.Dial(context.Background()) + require.Error(t, err) +} + +func newPrivateKey(t *testing.T) *ecdsa.PrivateKey { + p, err := keys.NewPrivateKey() + require.NoError(t, err) + return &p.PrivateKey +} + +func TestBuildPoolOneNodeFailed(t *testing.T) { + nodes := []NodeParam{ + {1, "peer0", 1}, + {2, "peer1", 1}, + } + + var clientKeys []*ecdsa.PrivateKey + mockClientBuilder := func(addr string) client { + key := newPrivateKey(t) + clientKeys = append(clientKeys, key) + + if addr == nodes[0].address { + mockCli := newMockClient(addr, *key) + mockCli.errOnEndpointInfo() + return mockCli + } + + return newMockClient(addr, *key) + } + + log, err := zap.NewProduction() + require.NoError(t, err) + opts := InitParameters{ + key: newPrivateKey(t), + clientRebalanceInterval: 1000 * time.Millisecond, + logger: log, + nodeParams: nodes, + } + opts.setClientBuilder(mockClientBuilder) + + clientPool, err := NewPool(opts) + require.NoError(t, err) + err = clientPool.Dial(context.Background()) + require.NoError(t, err) + t.Cleanup(clientPool.Close) + + expectedAuthKey := frostfsecdsa.PublicKey(clientKeys[1].PublicKey) + condition := func() bool { + cp, err := clientPool.connection() + if err != nil { + return false + } + st, _ := clientPool.cache.Get(formCacheKey(cp.address(), clientPool.key, false)) + return st.AssertAuthKey(&expectedAuthKey) + } + require.Never(t, condition, 900*time.Millisecond, 100*time.Millisecond) + require.Eventually(t, condition, 3*time.Second, 300*time.Millisecond) +} + +func TestBuildPoolZeroNodes(t *testing.T) { + opts := InitParameters{ + key: newPrivateKey(t), + } + _, err := NewPool(opts) + require.Error(t, err) +} + +func TestOneNode(t *testing.T) { + key1 := newPrivateKey(t) + mockClientBuilder := func(addr string) client { + return newMockClient(addr, *key1) + } + + opts := InitParameters{ + key: newPrivateKey(t), + nodeParams: []NodeParam{{1, "peer0", 1}}, + } + opts.setClientBuilder(mockClientBuilder) + + pool, err := NewPool(opts) + require.NoError(t, err) + err = pool.Dial(context.Background()) + require.NoError(t, err) + t.Cleanup(pool.Close) + + cp, err := pool.connection() + require.NoError(t, err) + st, _ := pool.cache.Get(formCacheKey(cp.address(), pool.key, false)) + expectedAuthKey := frostfsecdsa.PublicKey(key1.PublicKey) + require.True(t, st.AssertAuthKey(&expectedAuthKey)) +} + +func TestTwoNodes(t *testing.T) { + var clientKeys []*ecdsa.PrivateKey + mockClientBuilder := func(addr string) client { + key := newPrivateKey(t) + clientKeys = append(clientKeys, key) + return newMockClient(addr, *key) + } + + opts := InitParameters{ + key: newPrivateKey(t), + nodeParams: []NodeParam{ + {1, "peer0", 1}, + {1, "peer1", 1}, + }, + } + opts.setClientBuilder(mockClientBuilder) + + pool, err := NewPool(opts) + require.NoError(t, err) + err = pool.Dial(context.Background()) + require.NoError(t, err) + t.Cleanup(pool.Close) + + cp, err := pool.connection() + require.NoError(t, err) + st, _ := pool.cache.Get(formCacheKey(cp.address(), pool.key, false)) + require.True(t, assertAuthKeyForAny(st, clientKeys)) +} + +func assertAuthKeyForAny(st session.Object, clientKeys []*ecdsa.PrivateKey) bool { + for _, key := range clientKeys { + expectedAuthKey := frostfsecdsa.PublicKey(key.PublicKey) + if st.AssertAuthKey(&expectedAuthKey) { + return true + } + } + return false +} + +func TestOneOfTwoFailed(t *testing.T) { + nodes := []NodeParam{ + {1, "peer0", 1}, + {9, "peer1", 1}, + } + + var clientKeys []*ecdsa.PrivateKey + mockClientBuilder := func(addr string) client { + key := newPrivateKey(t) + clientKeys = append(clientKeys, key) + + if addr == nodes[0].address { + return newMockClient(addr, *key) + } + + mockCli := newMockClient(addr, *key) + mockCli.errOnEndpointInfo() + mockCli.errOnNetworkInfo() + return mockCli + } + + opts := InitParameters{ + key: newPrivateKey(t), + nodeParams: nodes, + clientRebalanceInterval: 200 * time.Millisecond, + } + opts.setClientBuilder(mockClientBuilder) + + pool, err := NewPool(opts) + require.NoError(t, err) + err = pool.Dial(context.Background()) + require.NoError(t, err) + + require.NoError(t, err) + t.Cleanup(pool.Close) + + time.Sleep(2 * time.Second) + + for i := 0; i < 5; i++ { + cp, err := pool.connection() + require.NoError(t, err) + st, _ := pool.cache.Get(formCacheKey(cp.address(), pool.key, false)) + require.True(t, assertAuthKeyForAny(st, clientKeys)) + } +} + +func TestTwoFailed(t *testing.T) { + var clientKeys []*ecdsa.PrivateKey + mockClientBuilder := func(addr string) client { + key := newPrivateKey(t) + clientKeys = append(clientKeys, key) + mockCli := newMockClient(addr, *key) + mockCli.errOnEndpointInfo() + return mockCli + } + + opts := InitParameters{ + key: newPrivateKey(t), + nodeParams: []NodeParam{ + {1, "peer0", 1}, + {1, "peer1", 1}, + }, + clientRebalanceInterval: 200 * time.Millisecond, + } + opts.setClientBuilder(mockClientBuilder) + + pool, err := NewPool(opts) + require.NoError(t, err) + err = pool.Dial(context.Background()) + require.NoError(t, err) + + t.Cleanup(pool.Close) + + time.Sleep(2 * time.Second) + + _, err = pool.connection() + require.Error(t, err) + require.Contains(t, err.Error(), "no healthy") +} + +func TestSessionCache(t *testing.T) { + key := newPrivateKey(t) + expectedAuthKey := frostfsecdsa.PublicKey(key.PublicKey) + + mockClientBuilder := func(addr string) client { + mockCli := newMockClient(addr, *key) + mockCli.statusOnGetObject(new(apistatus.SessionTokenNotFound)) + return mockCli + } + + opts := InitParameters{ + key: newPrivateKey(t), + nodeParams: []NodeParam{ + {1, "peer0", 1}, + }, + clientRebalanceInterval: 30 * time.Second, + } + opts.setClientBuilder(mockClientBuilder) + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + pool, err := NewPool(opts) + require.NoError(t, err) + err = pool.Dial(ctx) + require.NoError(t, err) + t.Cleanup(pool.Close) + + // cache must contain session token + cp, err := pool.connection() + require.NoError(t, err) + st, _ := pool.cache.Get(formCacheKey(cp.address(), pool.key, false)) + require.True(t, st.AssertAuthKey(&expectedAuthKey)) + + var prm PrmObjectGet + prm.SetAddress(oid.Address{}) + prm.UseSession(session.Object{}) + + _, err = pool.GetObject(ctx, prm) + require.Error(t, err) + + // cache must not contain session token + cp, err = pool.connection() + require.NoError(t, err) + _, ok := pool.cache.Get(formCacheKey(cp.address(), pool.key, false)) + require.False(t, ok) + + var prm2 PrmObjectPut + prm2.SetHeader(object.Object{}) + + _, err = pool.PutObject(ctx, prm2) + require.NoError(t, err) + + // cache must contain session token + cp, err = pool.connection() + require.NoError(t, err) + st, _ = pool.cache.Get(formCacheKey(cp.address(), pool.key, false)) + require.True(t, st.AssertAuthKey(&expectedAuthKey)) +} + +func TestPriority(t *testing.T) { + nodes := []NodeParam{ + {1, "peer0", 1}, + {2, "peer1", 100}, + } + + var clientKeys []*ecdsa.PrivateKey + mockClientBuilder := func(addr string) client { + key := newPrivateKey(t) + clientKeys = append(clientKeys, key) + + if addr == nodes[0].address { + mockCli := newMockClient(addr, *key) + mockCli.errOnEndpointInfo() + return mockCli + } + + return newMockClient(addr, *key) + } + + opts := InitParameters{ + key: newPrivateKey(t), + nodeParams: nodes, + clientRebalanceInterval: 1500 * time.Millisecond, + } + opts.setClientBuilder(mockClientBuilder) + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + pool, err := NewPool(opts) + require.NoError(t, err) + err = pool.Dial(ctx) + require.NoError(t, err) + t.Cleanup(pool.Close) + + expectedAuthKey1 := frostfsecdsa.PublicKey(clientKeys[0].PublicKey) + firstNode := func() bool { + cp, err := pool.connection() + require.NoError(t, err) + st, _ := pool.cache.Get(formCacheKey(cp.address(), pool.key, false)) + return st.AssertAuthKey(&expectedAuthKey1) + } + + expectedAuthKey2 := frostfsecdsa.PublicKey(clientKeys[1].PublicKey) + secondNode := func() bool { + cp, err := pool.connection() + require.NoError(t, err) + st, _ := pool.cache.Get(formCacheKey(cp.address(), pool.key, false)) + return st.AssertAuthKey(&expectedAuthKey2) + } + require.Never(t, secondNode, time.Second, 200*time.Millisecond) + + require.Eventually(t, secondNode, time.Second, 200*time.Millisecond) + require.Never(t, firstNode, time.Second, 200*time.Millisecond) +} + +func TestSessionCacheWithKey(t *testing.T) { + key := newPrivateKey(t) + expectedAuthKey := frostfsecdsa.PublicKey(key.PublicKey) + + mockClientBuilder := func(addr string) client { + return newMockClient(addr, *key) + } + + opts := InitParameters{ + key: newPrivateKey(t), + nodeParams: []NodeParam{ + {1, "peer0", 1}, + }, + clientRebalanceInterval: 30 * time.Second, + } + opts.setClientBuilder(mockClientBuilder) + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + pool, err := NewPool(opts) + require.NoError(t, err) + err = pool.Dial(ctx) + require.NoError(t, err) + + // cache must contain session token + cp, err := pool.connection() + require.NoError(t, err) + st, _ := pool.cache.Get(formCacheKey(cp.address(), pool.key, false)) + require.True(t, st.AssertAuthKey(&expectedAuthKey)) + + var prm PrmObjectDelete + prm.SetAddress(oid.Address{}) + anonKey := newPrivateKey(t) + prm.UseKey(anonKey) + + err = pool.DeleteObject(ctx, prm) + require.NoError(t, err) + st, _ = pool.cache.Get(formCacheKey(cp.address(), anonKey, false)) + require.True(t, st.AssertAuthKey(&expectedAuthKey)) +} + +func TestSessionTokenOwner(t *testing.T) { + mockClientBuilder := func(addr string) client { + key := newPrivateKey(t) + return newMockClient(addr, *key) + } + + opts := InitParameters{ + key: newPrivateKey(t), + nodeParams: []NodeParam{ + {1, "peer0", 1}, + }, + } + opts.setClientBuilder(mockClientBuilder) + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + p, err := NewPool(opts) + require.NoError(t, err) + err = p.Dial(ctx) + require.NoError(t, err) + t.Cleanup(p.Close) + + anonKey := newPrivateKey(t) + var anonOwner user.ID + user.IDFromKey(&anonOwner, anonKey.PublicKey) + + var prm prmCommon + prm.UseKey(anonKey) + var prmCtx prmContext + prmCtx.useDefaultSession() + + var tkn session.Object + var cc callContext + cc.sessionTarget = func(tok session.Object) { + tkn = tok + } + err = p.initCallContext(&cc, prm, prmCtx) + require.NoError(t, err) + + err = p.openDefaultSession(ctx, &cc) + require.NoError(t, err) + require.True(t, tkn.VerifySignature()) + require.True(t, tkn.Issuer().Equals(anonOwner)) +} + +func TestWaitPresence(t *testing.T) { + mockCli := newMockClient("", *newPrivateKey(t)) + + t.Run("context canceled", func(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + go func() { + time.Sleep(500 * time.Millisecond) + cancel() + }() + + err := waitForContainerPresence(ctx, mockCli, PrmContainerGet{}, &WaitParams{ + Timeout: 120 * time.Second, + PollInterval: 5 * time.Second, + }) + require.Error(t, err) + require.Contains(t, err.Error(), "context canceled") + }) + + t.Run("context deadline exceeded", func(t *testing.T) { + ctx := context.Background() + + err := waitForContainerPresence(ctx, mockCli, PrmContainerGet{}, &WaitParams{ + Timeout: 500 * time.Millisecond, + PollInterval: 5 * time.Second, + }) + require.Error(t, err) + require.Contains(t, err.Error(), "context deadline exceeded") + }) + + t.Run("ok", func(t *testing.T) { + ctx := context.Background() + + err := waitForContainerPresence(ctx, mockCli, PrmContainerGet{}, &WaitParams{ + Timeout: 10 * time.Second, + PollInterval: 500 * time.Millisecond, + }) + require.NoError(t, err) + }) +} + +func TestStatusMonitor(t *testing.T) { + monitor := newClientStatusMonitor(zap.NewExample(), "", 10) + monitor.errorThreshold = 3 + + count := 10 + for i := 0; i < count; i++ { + monitor.incErrorRate() + } + + require.Equal(t, uint64(count), monitor.overallErrorRate()) + require.Equal(t, uint32(1), monitor.currentErrorRate()) + + t.Run("healthy status", func(t *testing.T) { + cases := []struct { + action func(*clientStatusMonitor) + status uint32 + isDialed bool + isHealthy bool + description string + }{ + { + action: func(m *clientStatusMonitor) { m.setUnhealthyOnDial() }, + status: statusUnhealthyOnDial, + isDialed: false, + isHealthy: false, + description: "set unhealthy on dial", + }, + { + action: func(m *clientStatusMonitor) { m.setUnhealthy() }, + status: statusUnhealthyOnRequest, + isDialed: true, + isHealthy: false, + description: "set unhealthy on request", + }, + { + action: func(m *clientStatusMonitor) { m.setHealthy() }, + status: statusHealthy, + isDialed: true, + isHealthy: true, + description: "set healthy", + }, + } + for _, tc := range cases { + tc.action(&monitor) + require.Equal(t, tc.status, monitor.healthy.Load()) + require.Equal(t, tc.isDialed, monitor.isDialed()) + require.Equal(t, tc.isHealthy, monitor.isHealthy()) + } + }) +} + +func TestHandleError(t *testing.T) { + ctx := context.Background() + monitor := newClientStatusMonitor(zap.NewExample(), "", 10) + + canceledCtx, cancel := context.WithCancel(context.Background()) + cancel() + + for i, tc := range []struct { + ctx context.Context + status apistatus.Status + err error + expectedError bool + countError bool + }{ + { + ctx: ctx, + status: nil, + err: nil, + expectedError: false, + countError: false, + }, + { + ctx: ctx, + status: new(apistatus.SuccessDefaultV2), + err: nil, + expectedError: false, + countError: false, + }, + { + ctx: ctx, + status: new(apistatus.SuccessDefaultV2), + err: errors.New("error"), + expectedError: true, + countError: true, + }, + { + ctx: ctx, + status: nil, + err: errors.New("error"), + expectedError: true, + countError: true, + }, + { + ctx: ctx, + status: new(apistatus.ObjectNotFound), + err: nil, + expectedError: true, + countError: false, + }, + { + ctx: ctx, + status: new(apistatus.ServerInternal), + err: nil, + expectedError: true, + countError: true, + }, + { + ctx: ctx, + status: new(apistatus.WrongMagicNumber), + err: nil, + expectedError: true, + countError: true, + }, + { + ctx: ctx, + status: new(apistatus.SignatureVerification), + err: nil, + expectedError: true, + countError: true, + }, + { + ctx: ctx, + status: new(apistatus.SignatureVerification), + err: nil, + expectedError: true, + countError: true, + }, + { + ctx: ctx, + status: new(apistatus.NodeUnderMaintenance), + err: nil, + expectedError: true, + countError: true, + }, + { + ctx: canceledCtx, + status: nil, + err: errors.New("error"), + expectedError: true, + countError: false, + }, + } { + t.Run(strconv.Itoa(i), func(t *testing.T) { + errCount := monitor.currentErrorRate() + err := monitor.handleError(tc.ctx, tc.status, tc.err) + if tc.expectedError { + require.Error(t, err) + } else { + require.NoError(t, err) + } + if tc.countError { + errCount++ + } + require.Equal(t, errCount, monitor.currentErrorRate()) + }) + } +} + +func TestSwitchAfterErrorThreshold(t *testing.T) { + nodes := []NodeParam{ + {1, "peer0", 1}, + {2, "peer1", 100}, + } + + errorThreshold := 5 + + var clientKeys []*ecdsa.PrivateKey + mockClientBuilder := func(addr string) client { + key := newPrivateKey(t) + clientKeys = append(clientKeys, key) + + if addr == nodes[0].address { + mockCli := newMockClient(addr, *key) + mockCli.setThreshold(uint32(errorThreshold)) + mockCli.statusOnGetObject(new(apistatus.ServerInternal)) + return mockCli + } + + return newMockClient(addr, *key) + } + + opts := InitParameters{ + key: newPrivateKey(t), + nodeParams: nodes, + clientRebalanceInterval: 30 * time.Second, + } + opts.setClientBuilder(mockClientBuilder) + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + pool, err := NewPool(opts) + require.NoError(t, err) + err = pool.Dial(ctx) + require.NoError(t, err) + t.Cleanup(pool.Close) + + for i := 0; i < errorThreshold; i++ { + conn, err := pool.connection() + require.NoError(t, err) + require.Equal(t, nodes[0].address, conn.address()) + _, err = conn.objectGet(ctx, PrmObjectGet{}) + require.Error(t, err) + } + + conn, err := pool.connection() + require.NoError(t, err) + require.Equal(t, nodes[1].address, conn.address()) + _, err = conn.objectGet(ctx, PrmObjectGet{}) + require.NoError(t, err) +} diff --git a/pkg/sdk/pool/sampler.go b/pkg/sdk/pool/sampler.go new file mode 100644 index 000000000..f5b663549 --- /dev/null +++ b/pkg/sdk/pool/sampler.go @@ -0,0 +1,81 @@ +package pool + +import "math/rand" + +// sampler implements weighted random number generation using Vose's Alias +// Method (https://www.keithschwarz.com/darts-dice-coins/). +type sampler struct { + randomGenerator *rand.Rand + probabilities []float64 + alias []int +} + +// newSampler creates new sampler with a given set of probabilities using +// given source of randomness. Created sampler will produce numbers from +// 0 to len(probabilities). +func newSampler(probabilities []float64, source rand.Source) *sampler { + sampler := &sampler{} + var ( + small workList + large workList + ) + n := len(probabilities) + sampler.randomGenerator = rand.New(source) + sampler.probabilities = make([]float64, n) + sampler.alias = make([]int, n) + // Compute scaled probabilities. + p := make([]float64, n) + for i := 0; i < n; i++ { + p[i] = probabilities[i] * float64(n) + } + for i, pi := range p { + if pi < 1 { + small.add(i) + } else { + large.add(i) + } + } + for len(small) > 0 && len(large) > 0 { + l, g := small.remove(), large.remove() + sampler.probabilities[l] = p[l] + sampler.alias[l] = g + p[g] = p[g] + p[l] - 1 + if p[g] < 1 { + small.add(g) + } else { + large.add(g) + } + } + for len(large) > 0 { + g := large.remove() + sampler.probabilities[g] = 1 + } + for len(small) > 0 { + l := small.remove() + sampler.probabilities[l] = 1 + } + return sampler +} + +// Next returns the next (not so) random number from sampler. +func (g *sampler) Next() int { + n := len(g.alias) + i := g.randomGenerator.Intn(n) + if g.randomGenerator.Float64() < g.probabilities[i] { + return i + } + return g.alias[i] +} + +type workList []int + +func (wl *workList) add(e int) { + *wl = append(*wl, e) +} + +func (wl *workList) remove() int { + l := len(*wl) - 1 + n := (*wl)[l] + *wl = (*wl)[:l] + return n +} diff --git a/pkg/sdk/pool/sampler_test.go b/pkg/sdk/pool/sampler_test.go new file mode 100644 index 000000000..5ea232604 --- /dev/null +++ b/pkg/sdk/pool/sampler_test.go @@ -0,0 +1,121 @@ +package pool + +import ( + "context" + "math/rand" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestSamplerStability(t *testing.T) { + const COUNT = 100000 + + cases := []struct { + probabilities []float64 + expected []int + }{ + { + probabilities: []float64{1, 0}, + expected: []int{COUNT, 0}, + }, + { + probabilities: []float64{0.1, 0.2, 0.7}, + expected: []int{10138, 19813, 70049}, + }, + { + probabilities: []float64{0.2, 0.2, 0.4, 0.1, 0.1, 0}, + expected: []int{19824, 20169, 39900, 10243, 9864, 0}, + }, + } + + for _, tc := range cases { + sampler := newSampler(tc.probabilities, rand.NewSource(0)) + res := make([]int, len(tc.probabilities)) + for i := 0; i < COUNT; i++ { + res[sampler.Next()]++ + } + + require.Equal(t, tc.expected, res, "probabilities: %v", tc.probabilities) + } +} + +func TestHealthyReweight(t *testing.T) { + var ( + weights = []float64{0.9, 0.1} + names = []string{"node0", "node1"} + buffer = make([]float64, len(weights)) + ) + + cache, err := newCache() + require.NoError(t, err) + + client1 := newMockClient(names[0], *newPrivateKey(t)) + client1.errOnDial() + + client2 := newMockClient(names[1], *newPrivateKey(t)) + + inner := &innerPool{ + sampler: newSampler(weights, rand.NewSource(0)), + clients: []client{client1, client2}, + } + p := &Pool{ + innerPools: []*innerPool{inner}, + cache: cache, + key: newPrivateKey(t), + rebalanceParams: rebalanceParameters{nodesParams: []*nodesParam{{weights: weights}}}, + } + + // check getting first node connection before rebalance happened + connection0, err := p.connection() + require.NoError(t, err) + mock0 := connection0.(*mockClient) + require.Equal(t, names[0], mock0.address()) + + p.updateInnerNodesHealth(context.TODO(), 0, buffer) + + connection1, err := p.connection() + require.NoError(t, err) + mock1 := connection1.(*mockClient) + require.Equal(t, names[1], mock1.address()) + + // enabled first node again + inner.lock.Lock() + inner.clients[0] = newMockClient(names[0], *newPrivateKey(t)) + inner.lock.Unlock() + + p.updateInnerNodesHealth(context.TODO(), 0, buffer) + inner.sampler = newSampler(weights, rand.NewSource(0)) + + connection0, err = p.connection() + require.NoError(t, err) + mock0 = connection0.(*mockClient) + require.Equal(t, names[0], mock0.address()) +} + +func TestHealthyNoReweight(t *testing.T) { + var ( + weights = []float64{0.9, 0.1} + names = []string{"node0", "node1"} + buffer = make([]float64, len(weights)) + ) + + sampl := newSampler(weights, rand.NewSource(0)) + inner := &innerPool{ + sampler: sampl, + clients: []client{ + newMockClient(names[0], *newPrivateKey(t)), + newMockClient(names[1], *newPrivateKey(t)), + }, + } + p := &Pool{ + innerPools: []*innerPool{inner}, + rebalanceParams: rebalanceParameters{nodesParams: []*nodesParam{{weights: weights}}}, + } + + p.updateInnerNodesHealth(context.TODO(), 0, buffer) + + inner.lock.RLock() + defer inner.lock.RUnlock() + require.Equal(t, inner.sampler, sampl) +} diff --git a/pkg/sdk/pool/statistic.go b/pkg/sdk/pool/statistic.go new file mode 100644 index 000000000..5f1cfad9e --- /dev/null +++ b/pkg/sdk/pool/statistic.go @@ -0,0 +1,160 @@ +package pool + +import ( + "errors" + "time" +) + +// Statistic is metrics of the pool. +type Statistic struct { + overallErrors uint64 + nodes []NodeStatistic + currentNodes []string +} + +// OverallErrors returns sum of errors on all connections. It doesn't decrease. +func (s Statistic) OverallErrors() uint64 { + return s.overallErrors +} + +// Nodes returns list of nodes statistic. +func (s Statistic) Nodes() []NodeStatistic { + return s.nodes +} + +// CurrentNodes returns list of nodes of inner pool that has at least one healthy node. +// These nodes have the same and the highest priority among the other healthy nodes. +func (s Statistic) CurrentNodes() []string { + return s.currentNodes +} + +// ErrUnknownNode indicate that node with current address is not found in list. +var ErrUnknownNode = errors.New("unknown node") + +// Node returns NodeStatistic by node address. +// If such node doesn't exist ErrUnknownNode error is returned. +func (s Statistic) Node(address string) (*NodeStatistic, error) { + for i := range s.nodes { + if s.nodes[i].address == address { + return &s.nodes[i], nil + } + } + + return nil, ErrUnknownNode +} + +// NodeStatistic is metrics of certain connections. +type NodeStatistic struct { + address string + methods []statusSnapshot + overallErrors uint64 + currentErrors uint32 +} + +// OverallErrors returns all errors on current node. +// This value never decreases. +func (n NodeStatistic) OverallErrors() uint64 { + return n.overallErrors +} + +// CurrentErrors returns errors on current node. +// This value is always less than 'errorThreshold' from InitParameters. +func (n NodeStatistic) CurrentErrors() uint32 { + return n.currentErrors +} + +// Requests returns number of requests. +func (n NodeStatistic) Requests() (requests uint64) { + for _, val := range n.methods { + requests += val.allRequests + } + return requests +} + +// Address returns node endpoint address. +func (n NodeStatistic) Address() string { + return n.address +} + +// AverageGetBalance returns average time to perform BalanceGet request. +func (n NodeStatistic) AverageGetBalance() time.Duration { + return n.averageTime(methodBalanceGet) +} + +// AveragePutContainer returns average time to perform ContainerPut request. +func (n NodeStatistic) AveragePutContainer() time.Duration { + return n.averageTime(methodContainerPut) +} + +// AverageGetContainer returns average time to perform ContainerGet request. +func (n NodeStatistic) AverageGetContainer() time.Duration { + return n.averageTime(methodContainerGet) +} + +// AverageListContainer returns average time to perform ContainerList request. +func (n NodeStatistic) AverageListContainer() time.Duration { + return n.averageTime(methodContainerList) +} + +// AverageDeleteContainer returns average time to perform ContainerDelete request. +func (n NodeStatistic) AverageDeleteContainer() time.Duration { + return n.averageTime(methodContainerDelete) +} + +// AverageGetContainerEACL returns average time to perform ContainerEACL request. +func (n NodeStatistic) AverageGetContainerEACL() time.Duration { + return n.averageTime(methodContainerEACL) +} + +// AverageSetContainerEACL returns average time to perform ContainerSetEACL request. +func (n NodeStatistic) AverageSetContainerEACL() time.Duration { + return n.averageTime(methodContainerSetEACL) +} + +// AverageEndpointInfo returns average time to perform EndpointInfo request. +func (n NodeStatistic) AverageEndpointInfo() time.Duration { + return n.averageTime(methodEndpointInfo) +} + +// AverageNetworkInfo returns average time to perform NetworkInfo request. +func (n NodeStatistic) AverageNetworkInfo() time.Duration { + return n.averageTime(methodNetworkInfo) +} + +// AveragePutObject returns average time to perform ObjectPut request. +func (n NodeStatistic) AveragePutObject() time.Duration { + return n.averageTime(methodObjectPut) +} + +// AverageDeleteObject returns average time to perform ObjectDelete request. +func (n NodeStatistic) AverageDeleteObject() time.Duration { + return n.averageTime(methodObjectDelete) +} + +// AverageGetObject returns average time to perform ObjectGet request. +func (n NodeStatistic) AverageGetObject() time.Duration { + return n.averageTime(methodObjectGet) +} + +// AverageHeadObject returns average time to perform ObjectHead request. +func (n NodeStatistic) AverageHeadObject() time.Duration { + return n.averageTime(methodObjectHead) +} + +// AverageRangeObject returns average time to perform ObjectRange request. +func (n NodeStatistic) AverageRangeObject() time.Duration { + return n.averageTime(methodObjectRange) +} + +// AverageCreateSession returns average time to perform SessionCreate request. +func (n NodeStatistic) AverageCreateSession() time.Duration { + return n.averageTime(methodSessionCreate) +} + +func (n NodeStatistic) averageTime(method MethodIndex) time.Duration { + stat := n.methods[method] + if stat.allRequests == 0 { + return 0 + } + return time.Duration(stat.allTime / stat.allRequests) +} diff --git a/pkg/sdk/pool/tree/client.go b/pkg/sdk/pool/tree/client.go new file mode 100644 index 000000000..82bbc9c38 --- /dev/null +++ b/pkg/sdk/pool/tree/client.go @@ -0,0 +1,140 @@ +package tree + +import ( + "context" + "crypto/tls" + "errors" + "fmt" + "sync" + + apiClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client" + grpcService "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/pool/tree/service" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" + "google.golang.org/grpc/credentials/insecure" +) + +type treeClient struct { + mu sync.RWMutex + address string + opts []grpc.DialOption + conn *grpc.ClientConn + service grpcService.TreeServiceClient + healthy bool +} + +// ErrUnhealthyEndpoint is returned when client in the pool considered unavailable. +var ErrUnhealthyEndpoint = errors.New("unhealthy endpoint") + +// newTreeClient creates new tree client with auto dial. +func newTreeClient(addr string, opts ...grpc.DialOption) *treeClient { + return &treeClient{ + address: addr, + opts: opts, + } +} + +func (c *treeClient) dial(ctx context.Context) error { + c.mu.Lock() + defer c.mu.Unlock() + + if c.conn != nil { + return fmt.Errorf("couldn't dial '%s': connection already established", c.address) + } + + var err error + if c.conn, c.service, err = dialClient(ctx, c.address, c.opts...); err != nil { + return err + } + + if _, err = c.service.Healthcheck(ctx, &grpcService.HealthcheckRequest{}); err != nil { + return fmt.Errorf("healthcheck tree service: %w", err) + } + + c.healthy = true + + return nil +} + +func (c *treeClient) redialIfNecessary(ctx context.Context) (healthHasChanged bool, err error) { + c.mu.Lock() + defer c.mu.Unlock() + + if c.conn == nil { + if c.conn, c.service, err = dialClient(ctx, c.address, c.opts...); err != nil { + return false, err + } + } + + wasHealthy := c.healthy + if _, err = c.service.Healthcheck(ctx, &grpcService.HealthcheckRequest{}); err != nil { + c.healthy = false + return wasHealthy, fmt.Errorf("healthcheck tree service: %w", err) + } + + c.healthy = true + + return !wasHealthy, nil +} + +func dialClient(ctx context.Context, addr string, clientOptions ...grpc.DialOption) (*grpc.ClientConn, grpcService.TreeServiceClient, error) { + host, tlsEnable, err := apiClient.ParseURI(addr) + if err != nil { + return nil, nil, fmt.Errorf("parse address: %w", err) + } + + creds := insecure.NewCredentials() + if tlsEnable { + creds = credentials.NewTLS(&tls.Config{}) + } + + options := []grpc.DialOption{grpc.WithTransportCredentials(creds)} + + // the order is matter, we want client to be able to overwrite options. + opts := append(options, clientOptions...) + + conn, err := grpc.DialContext(ctx, host, opts...) + if err != nil { + return nil, nil, fmt.Errorf("grpc dial node tree service: %w", err) + } + + return conn, grpcService.NewTreeServiceClient(conn), nil +} + +func (c *treeClient) serviceClient() (grpcService.TreeServiceClient, error) { + c.mu.RLock() + defer c.mu.RUnlock() + + if c.conn == nil || !c.healthy { + return nil, fmt.Errorf("%w: '%s'", ErrUnhealthyEndpoint, c.address) + } + + return c.service, nil +} + +func (c *treeClient) endpoint() string { + return c.address +} + +func (c *treeClient) isHealthy() bool { + c.mu.RLock() + defer c.mu.RUnlock() + return c.healthy +} + +func (c *treeClient) setHealthy(val bool) { + c.mu.Lock() + defer c.mu.Unlock() + c.healthy = val +} + +func (c *treeClient) close() error { + c.mu.Lock() + defer c.mu.Unlock() + + if c.conn == nil { + return nil + } + + return c.conn.Close() +} diff --git a/pkg/sdk/pool/tree/pool.go b/pkg/sdk/pool/tree/pool.go new file mode 100644 index 000000000..21c0aa312 --- /dev/null +++ b/pkg/sdk/pool/tree/pool.go @@ -0,0 +1,837 @@ +package tree + +import ( + "context" + "errors" + "fmt" + "io" + "sort" + "strings" + "sync" + "time" + + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/pool" + grpcService "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/pool/tree/service" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + "go.uber.org/zap" + "go.uber.org/zap/zapcore" + "google.golang.org/grpc" +) + +const ( + defaultRebalanceInterval = 15 * time.Second + defaultHealthcheckTimeout = 4 * time.Second + defaultDialTimeout = 5 * time.Second + defaultStreamTimeout = 10 * time.Second +) + +var ( + // ErrNodeNotFound is returned from Tree service in case of not found error. + ErrNodeNotFound = errors.New("not found") + + // ErrNodeAccessDenied is returned from Tree service in case of access denied error. + ErrNodeAccessDenied = errors.New("access denied") + + // errNodeEmpty is used to trigger retry when 'GetNodeByPath' return empty result. + errNodeEmptyResult = errors.New("empty result") +) + +// client represents virtual connection to the single FrostFS tree service from which Pool is formed. +// This interface is expected to have exactly one production implementation - treeClient. +// Others are expected to be for test purposes only. +type client interface { + serviceClient() (grpcService.TreeServiceClient, error) + endpoint() string + isHealthy() bool + setHealthy(bool) + dial(ctx context.Context) error + redialIfNecessary(context.Context) (bool, error) + close() error +} + +// InitParameters contains values used to initialize connection Pool. +type InitParameters struct { + key *keys.PrivateKey + logger *zap.Logger + nodeDialTimeout time.Duration + nodeStreamTimeout time.Duration + healthcheckTimeout time.Duration + clientRebalanceInterval time.Duration + nodeParams []pool.NodeParam + dialOptions []grpc.DialOption + maxRequestAttempts int +} + +// Pool represents virtual connection to the FrostFS tree services network to communicate +// with multiple FrostFS tree services without thinking about switching between servers +// due to their unavailability. +// +// Pool can be created and initialized using NewPool function. +// Before executing the FrostFS tree operations using the Pool, connection to the +// servers MUST BE correctly established (see Dial method). +type Pool struct { + innerPools []*innerPool + key *keys.PrivateKey + cancel context.CancelFunc + closedCh chan struct{} + rebalanceParams rebalanceParameters + dialOptions []grpc.DialOption + logger *zap.Logger + + maxRequestAttempts int + + startIndicesMtx sync.RWMutex + // startIndices points to the client from which the next request will be executed. + // Since clients are stored in innerPool field we have to use two indices. + // These indices being changed during: + // * rebalance procedure (see Pool.startRebalance) + // * retry in case of request failure (see Pool.requestWithRetry) + startIndices [2]int +} + +type innerPool struct { + clients []client +} + +type rebalanceParameters struct { + nodesGroup [][]pool.NodeParam + nodeRequestTimeout time.Duration + clientRebalanceInterval time.Duration +} + +// GetNodesParams groups parameters of Pool.GetNodes operation. +type GetNodesParams struct { + CID cid.ID + TreeID string + Path []string + Meta []string + PathAttribute string + LatestOnly bool + AllAttrs bool + BearerToken []byte +} + +// GetSubTreeParams groups parameters of Pool.GetSubTree operation. +type GetSubTreeParams struct { + CID cid.ID + TreeID string + RootID uint64 + Depth uint32 + BearerToken []byte +} + +// AddNodeParams groups parameters of Pool.AddNode operation. +type AddNodeParams struct { + CID cid.ID + TreeID string + Parent uint64 + Meta map[string]string + BearerToken []byte +} + +// AddNodeByPathParams groups parameters of Pool.AddNodeByPath operation. +type AddNodeByPathParams struct { + CID cid.ID + TreeID string + Path []string + Meta map[string]string + PathAttribute string + BearerToken []byte +} + +// MoveNodeParams groups parameters of Pool.MoveNode operation. +type MoveNodeParams struct { + CID cid.ID + TreeID string + NodeID uint64 + ParentID uint64 + Meta map[string]string + BearerToken []byte +} + +// RemoveNodeParams groups parameters of Pool.RemoveNode operation. +type RemoveNodeParams struct { + CID cid.ID + TreeID string + NodeID uint64 + BearerToken []byte +} + +// NewPool creates connection pool using parameters. +func NewPool(options InitParameters) (*Pool, error) { + if options.key == nil { + return nil, fmt.Errorf("missed required parameter 'Key'") + } + + nodesParams, err := adjustNodeParams(options.nodeParams) + if err != nil { + return nil, err + } + + fillDefaultInitParams(&options) + + p := &Pool{ + key: options.key, + logger: options.logger, + dialOptions: options.dialOptions, + rebalanceParams: rebalanceParameters{ + nodesGroup: nodesParams, + nodeRequestTimeout: options.healthcheckTimeout, + clientRebalanceInterval: options.clientRebalanceInterval, + }, + maxRequestAttempts: options.maxRequestAttempts, + } + + return p, nil +} + +// Dial establishes a connection to the tree servers from the FrostFS network. +// It also starts a routine that checks the health of the nodes and +// updates the weights of the nodes for balancing. +// Returns an error describing failure reason. +// +// If failed, the Pool SHOULD NOT be used. +// +// See also InitParameters.SetClientRebalanceInterval. +func (p *Pool) Dial(ctx context.Context) error { + inner := make([]*innerPool, len(p.rebalanceParams.nodesGroup)) + var atLeastOneHealthy bool + + for i, nodes := range p.rebalanceParams.nodesGroup { + clients := make([]client, len(nodes)) + for j, node := range nodes { + clients[j] = newTreeClient(node.Address(), p.dialOptions...) + if err := clients[j].dial(ctx); err != nil { + p.log(zap.WarnLevel, "failed to dial tree client", zap.String("address", node.Address()), zap.Error(err)) + continue + } + + atLeastOneHealthy = true + } + + inner[i] = &innerPool{ + clients: clients, + } + } + + if !atLeastOneHealthy { + return fmt.Errorf("at least one node must be healthy") + } + + ctx, cancel := context.WithCancel(ctx) + p.cancel = cancel + p.closedCh = make(chan struct{}) + p.innerPools = inner + + go p.startRebalance(ctx) + return nil +} + +// SetKey specifies default key to be used for the protocol communication by default. +func (x *InitParameters) SetKey(key *keys.PrivateKey) { + x.key = key +} + +// SetLogger specifies logger. +func (x *InitParameters) SetLogger(logger *zap.Logger) { + x.logger = logger +} + +// SetNodeDialTimeout specifies the timeout for connection to be established. +func (x *InitParameters) SetNodeDialTimeout(timeout time.Duration) { + x.nodeDialTimeout = timeout +} + +// SetNodeStreamTimeout specifies the timeout for individual operations in streaming RPC. +func (x *InitParameters) SetNodeStreamTimeout(timeout time.Duration) { + x.nodeStreamTimeout = timeout +} + +// SetHealthcheckTimeout specifies the timeout for request to node to decide if it is alive. +// +// See also Pool.Dial. +func (x *InitParameters) SetHealthcheckTimeout(timeout time.Duration) { + x.healthcheckTimeout = timeout +} + +// SetClientRebalanceInterval specifies the interval for updating nodes health status. +// +// See also Pool.Dial. +func (x *InitParameters) SetClientRebalanceInterval(interval time.Duration) { + x.clientRebalanceInterval = interval +} + +// AddNode append information about the node to which you want to connect. +func (x *InitParameters) AddNode(nodeParam pool.NodeParam) { + x.nodeParams = append(x.nodeParams, nodeParam) +} + +// SetGRPCDialOptions sets the gRPC dial options for new gRPC tree client connection. +func (x *InitParameters) SetGRPCDialOptions(opts ...grpc.DialOption) { + x.dialOptions = opts +} + +// SetMaxRequestAttempts sets the max attempt to make successful request. +// Default value is 0 that means the number of attempts equals to number of nodes in pool. +func (x *InitParameters) SetMaxRequestAttempts(maxAttempts int) { + x.maxRequestAttempts = maxAttempts +} + +// GetNodes invokes eponymous method from TreeServiceClient. +// +// Can return predefined errors: +// * ErrNodeNotFound +// * ErrNodeAccessDenied. +func (p *Pool) GetNodes(ctx context.Context, prm GetNodesParams) ([]*grpcService.GetNodeByPathResponse_Info, error) { + request := &grpcService.GetNodeByPathRequest{ + Body: &grpcService.GetNodeByPathRequest_Body{ + ContainerId: prm.CID[:], + TreeId: prm.TreeID, + Path: prm.Path, + Attributes: prm.Meta, + PathAttribute: prm.PathAttribute, + LatestOnly: prm.LatestOnly, + AllAttributes: prm.AllAttrs, + BearerToken: prm.BearerToken, + }, + } + + if err := p.signRequest(request.Body, func(key, sign []byte) { + request.Signature = &grpcService.Signature{ + Key: key, + Sign: sign, + } + }); err != nil { + return nil, err + } + + var resp *grpcService.GetNodeByPathResponse + if err := p.requestWithRetry(ctx, func(client grpcService.TreeServiceClient) (inErr error) { + resp, inErr = client.GetNodeByPath(ctx, request) + // Pool wants to do retry 'GetNodeByPath' request if result is empty. + // Empty result is expected due to delayed tree service sync. + // Return an error there to trigger retry and ignore it after, + // to keep compatibility with 'GetNodeByPath' implementation. + if inErr == nil && len(resp.Body.Nodes) == 0 { + return errNodeEmptyResult + } + return handleError("failed to get node by path", inErr) + }); err != nil && !errors.Is(err, errNodeEmptyResult) { + return nil, err + } + + return resp.GetBody().GetNodes(), nil +} + +// SubTreeReader is designed to read list of subtree nodes FrostFS tree service. +// +// Must be initialized using Pool.GetSubTree, any other usage is unsafe. +type SubTreeReader struct { + cli grpcService.TreeService_GetSubTreeClient +} + +// Read reads another list of the subtree nodes. +func (x *SubTreeReader) Read(buf []*grpcService.GetSubTreeResponse_Body) (int, error) { + for i := 0; i < len(buf); i++ { + resp, err := x.cli.Recv() + if err == io.EOF { + return i, io.EOF + } else if err != nil { + return i, handleError("failed to get sub tree", err) + } + buf[i] = resp.Body + } + + return len(buf), nil +} + +// ReadAll reads all nodes subtree nodes. +func (x *SubTreeReader) ReadAll() ([]*grpcService.GetSubTreeResponse_Body, error) { + var res []*grpcService.GetSubTreeResponse_Body + for { + resp, err := x.cli.Recv() + if err == io.EOF { + break + } else if err != nil { + return nil, handleError("failed to get sub tree", err) + } + res = append(res, resp.Body) + } + + return res, nil +} + +// Next gets the next node from subtree. +func (x *SubTreeReader) Next() (*grpcService.GetSubTreeResponse_Body, error) { + resp, err := x.cli.Recv() + if err == io.EOF { + return nil, io.EOF + } + if err != nil { + return nil, handleError("failed to get sub tree", err) + } + + return resp.Body, nil +} + +// GetSubTree invokes eponymous method from TreeServiceClient. +// +// Can return predefined errors: +// * ErrNodeNotFound +// * ErrNodeAccessDenied. +func (p *Pool) GetSubTree(ctx context.Context, prm GetSubTreeParams) (*SubTreeReader, error) { + request := &grpcService.GetSubTreeRequest{ + Body: &grpcService.GetSubTreeRequest_Body{ + ContainerId: prm.CID[:], + TreeId: prm.TreeID, + RootId: prm.RootID, + Depth: prm.Depth, + BearerToken: prm.BearerToken, + OrderBy: &grpcService.GetSubTreeRequest_Body_Order{ + Direction: grpcService.GetSubTreeRequest_Body_Order_Asc, + }, + }, + } + + if err := p.signRequest(request.Body, func(key, sign []byte) { + request.Signature = &grpcService.Signature{ + Key: key, + Sign: sign, + } + }); err != nil { + return nil, err + } + + var cli grpcService.TreeService_GetSubTreeClient + if err := p.requestWithRetry(ctx, func(client grpcService.TreeServiceClient) (inErr error) { + cli, inErr = client.GetSubTree(ctx, request) + return handleError("failed to get sub tree client", inErr) + }); err != nil { + return nil, err + } + + return &SubTreeReader{cli: cli}, nil +} + +// AddNode invokes eponymous method from TreeServiceClient. +// +// Can return predefined errors: +// * ErrNodeNotFound +// * ErrNodeAccessDenied. +func (p *Pool) AddNode(ctx context.Context, prm AddNodeParams) (uint64, error) { + request := &grpcService.AddRequest{ + Body: &grpcService.AddRequest_Body{ + ContainerId: prm.CID[:], + TreeId: prm.TreeID, + ParentId: prm.Parent, + Meta: metaToKV(prm.Meta), + BearerToken: prm.BearerToken, + }, + } + if err := p.signRequest(request.Body, func(key, sign []byte) { + request.Signature = &grpcService.Signature{ + Key: key, + Sign: sign, + } + }); err != nil { + return 0, err + } + + var resp *grpcService.AddResponse + if err := p.requestWithRetry(ctx, func(client grpcService.TreeServiceClient) (inErr error) { + resp, inErr = client.Add(ctx, request) + return handleError("failed to add node", inErr) + }); err != nil { + return 0, err + } + + return resp.GetBody().GetNodeId(), nil +} + +// AddNodeByPath invokes eponymous method from TreeServiceClient. +// +// Can return predefined errors: +// * ErrNodeNotFound +// * ErrNodeAccessDenied. +func (p *Pool) AddNodeByPath(ctx context.Context, prm AddNodeByPathParams) (uint64, error) { + request := &grpcService.AddByPathRequest{ + Body: &grpcService.AddByPathRequest_Body{ + ContainerId: prm.CID[:], + TreeId: prm.TreeID, + Path: prm.Path, + Meta: metaToKV(prm.Meta), + PathAttribute: prm.PathAttribute, + BearerToken: prm.BearerToken, + }, + } + + if err := p.signRequest(request.Body, func(key, sign []byte) { + request.Signature = &grpcService.Signature{ + Key: key, + Sign: sign, + } + }); err != nil { + return 0, err + } + + var resp *grpcService.AddByPathResponse + if err := p.requestWithRetry(ctx, func(client grpcService.TreeServiceClient) (inErr error) { + resp, inErr = client.AddByPath(ctx, request) + return handleError("failed to add node by path", inErr) + }); err != nil { + return 0, err + } + + body := resp.GetBody() + if body == nil { + return 0, errors.New("nil body in tree service response") + } else if len(body.Nodes) == 0 { + return 0, errors.New("empty list of added nodes in tree service response") + } + + // The first node is the leaf that we add, according to tree service docs. + return body.Nodes[0], nil +} + +// MoveNode invokes eponymous method from TreeServiceClient. +// +// Can return predefined errors: +// * ErrNodeNotFound +// * ErrNodeAccessDenied. +func (p *Pool) MoveNode(ctx context.Context, prm MoveNodeParams) error { + request := &grpcService.MoveRequest{ + Body: &grpcService.MoveRequest_Body{ + ContainerId: prm.CID[:], + TreeId: prm.TreeID, + NodeId: prm.NodeID, + ParentId: prm.ParentID, + Meta: metaToKV(prm.Meta), + BearerToken: prm.BearerToken, + }, + } + + if err := p.signRequest(request.Body, func(key, sign []byte) { + request.Signature = &grpcService.Signature{ + Key: key, + Sign: sign, + } + }); err != nil { + return err + } + + return p.requestWithRetry(ctx, func(client grpcService.TreeServiceClient) error { + if _, err := client.Move(ctx, request); err != nil { + return handleError("failed to move node", err) + } + return nil + }) +} + +// RemoveNode invokes eponymous method from TreeServiceClient. +// +// Can return predefined errors: +// * ErrNodeNotFound +// * ErrNodeAccessDenied. +func (p *Pool) RemoveNode(ctx context.Context, prm RemoveNodeParams) error { + request := &grpcService.RemoveRequest{ + Body: &grpcService.RemoveRequest_Body{ + ContainerId: prm.CID[:], + TreeId: prm.TreeID, + NodeId: prm.NodeID, + BearerToken: prm.BearerToken, + }, + } + if err := p.signRequest(request.Body, func(key, sign []byte) { + request.Signature = &grpcService.Signature{ + Key: key, + Sign: sign, + } + }); err != nil { + return err + } + + return p.requestWithRetry(ctx, func(client grpcService.TreeServiceClient) error { + if _, err := client.Remove(ctx, request); err != nil { + return handleError("failed to remove node", err) + } + return nil + }) +} + +// Close closes the Pool and releases all the associated resources. +func (p *Pool) Close() error { + p.cancel() + <-p.closedCh + + var err error + for _, group := range p.innerPools { + for _, cl := range group.clients { + if closeErr := cl.close(); closeErr != nil { + p.log(zapcore.ErrorLevel, "close client connection", zap.Error(closeErr)) + err = closeErr + } + } + } + + return err +} + +func handleError(msg string, err error) error { + if err == nil { + return nil + } + if strings.Contains(err.Error(), "not found") { + return fmt.Errorf("%w: %s", ErrNodeNotFound, err.Error()) + } else if strings.Contains(err.Error(), "is denied by") { + return fmt.Errorf("%w: %s", ErrNodeAccessDenied, err.Error()) + } + return fmt.Errorf("%s: %w", msg, err) +} + +func metaToKV(meta map[string]string) []*grpcService.KeyValue { + result := make([]*grpcService.KeyValue, 0, len(meta)) + + for key, value := range meta { + result = append(result, &grpcService.KeyValue{Key: key, Value: []byte(value)}) + } + + return result +} + +func adjustNodeParams(nodeParams []pool.NodeParam) ([][]pool.NodeParam, error) { + if len(nodeParams) == 0 { + return nil, errors.New("no FrostFS peers configured") + } + + nodeParamsMap := make(map[int][]pool.NodeParam) + for _, param := range nodeParams { + nodes := nodeParamsMap[param.Priority()] + nodeParamsMap[param.Priority()] = append(nodes, param) + } + + res := make([][]pool.NodeParam, 0, len(nodeParamsMap)) + for _, nodes := range nodeParamsMap { + res = append(res, nodes) + } + + sort.Slice(res, func(i, j int) bool { + return res[i][0].Priority() < res[j][0].Priority() + }) + + return res, nil +} + +func fillDefaultInitParams(params *InitParameters) { + if params.clientRebalanceInterval <= 0 { + params.clientRebalanceInterval = defaultRebalanceInterval + } + + if params.healthcheckTimeout <= 0 { + params.healthcheckTimeout = defaultHealthcheckTimeout + } + + if params.nodeDialTimeout <= 0 { + params.nodeDialTimeout = defaultDialTimeout + } + + if params.nodeStreamTimeout <= 0 { + params.nodeStreamTimeout = defaultStreamTimeout + } + + if params.maxRequestAttempts <= 0 { + params.maxRequestAttempts = len(params.nodeParams) + } +} + +func (p *Pool) log(level zapcore.Level, msg string, fields ...zap.Field) { + if p.logger == nil { + return + } + + p.logger.Log(level, msg, fields...) +} + +// startRebalance runs loop to monitor tree client healthy status. +func (p *Pool) startRebalance(ctx context.Context) { + ticker := time.NewTimer(p.rebalanceParams.clientRebalanceInterval) + buffers := make([][]bool, len(p.rebalanceParams.nodesGroup)) + for i, nodes := range p.rebalanceParams.nodesGroup { + buffers[i] = make([]bool, len(nodes)) + } + + for { + select { + case <-ctx.Done(): + close(p.closedCh) + return + case <-ticker.C: + p.updateNodesHealth(ctx, buffers) + ticker.Reset(p.rebalanceParams.clientRebalanceInterval) + } + } +} + +func (p *Pool) updateNodesHealth(ctx context.Context, buffers [][]bool) { + wg := sync.WaitGroup{} + for i, inner := range p.innerPools { + wg.Add(1) + + go func(i int, _ *innerPool) { + defer wg.Done() + p.updateInnerNodesHealth(ctx, i, buffers[i]) + }(i, inner) + } + wg.Wait() + +LOOP: + for i, buffer := range buffers { + for j, healthy := range buffer { + if healthy { + p.setStartIndices(i, j) + break LOOP + } + } + } +} + +func (p *Pool) updateInnerNodesHealth(ctx context.Context, i int, buffer []bool) { + if i > len(p.innerPools)-1 { + return + } + nodesByPriority := p.innerPools[i] + options := p.rebalanceParams + + var wg sync.WaitGroup + for j, cli := range nodesByPriority.clients { + wg.Add(1) + go func(j int, cli client) { + defer wg.Done() + + tctx, c := context.WithTimeout(ctx, options.nodeRequestTimeout) + defer c() + + changed, err := cli.redialIfNecessary(tctx) + healthy := err == nil + if changed { + fields := []zap.Field{zap.String("address", cli.endpoint()), zap.Bool("healthy", healthy)} + if err != nil { + fields = append(fields, zap.Error(err)) + } + p.log(zap.DebugLevel, "tree health has changed", fields...) + } else if err != nil { + p.log(zap.DebugLevel, "tree redial error", zap.String("address", cli.endpoint()), zap.Error(err)) + } + buffer[j] = healthy + }(j, cli) + } + wg.Wait() +} + +func (p *Pool) getStartIndices() (int, int) { + p.startIndicesMtx.RLock() + defer p.startIndicesMtx.RUnlock() + + return p.startIndices[0], p.startIndices[1] +} + +func (p *Pool) setStartIndices(i, j int) { + p.startIndicesMtx.Lock() + p.startIndices[0] = i + p.startIndices[1] = j + p.startIndicesMtx.Unlock() +} + +func (p *Pool) requestWithRetry(ctx context.Context, fn func(client grpcService.TreeServiceClient) error) error { + var ( + err, finErr error + cl grpcService.TreeServiceClient + ) + + reqID := GetRequestID(ctx) + + startI, startJ := p.getStartIndices() + groupsLen := len(p.innerPools) + attempts := p.maxRequestAttempts + +LOOP: + for i := startI; i < startI+groupsLen; i++ { + indexI := i % groupsLen + clientsLen := len(p.innerPools[indexI].clients) + for j := startJ; j < startJ+clientsLen; j++ { + indexJ := j % clientsLen + + if attempts == 0 { + if startI != indexI || startJ != indexJ { + p.setStartIndices(indexI, indexJ) + } + break LOOP + } + attempts-- + + if cl, err = p.innerPools[indexI].clients[indexJ].serviceClient(); err == nil { + err = fn(cl) + } + if !shouldTryAgain(err) { + if startI != indexI || startJ != indexJ { + p.setStartIndices(indexI, indexJ) + } + return err + } + + finErr = finalError(finErr, err) + p.log(zap.DebugLevel, "tree request error", zap.String("request_id", reqID), zap.Int("remaining attempts", attempts), + zap.String("address", p.innerPools[indexI].clients[indexJ].endpoint()), zap.Error(err)) + } + startJ = 0 + } + + return finErr +} + +func shouldTryAgain(err error) bool { + return !(err == nil || errors.Is(err, ErrNodeAccessDenied)) +} + +func prioErr(err error) int { + switch { + case err == nil: + return -1 + case errors.Is(err, ErrNodeAccessDenied): + return 100 + case errors.Is(err, ErrNodeNotFound) || + errors.Is(err, errNodeEmptyResult): + return 200 + case errors.Is(err, ErrUnhealthyEndpoint): + return 300 + default: + return 500 + } +} + +func finalError(current, candidate error) error { + if current == nil || candidate == nil { + return candidate + } + + // lower priority error is more desirable + if prioErr(candidate) < prioErr(current) { + return candidate + } + + return current +} + +type reqKeyType struct{} + +// SetRequestID sets request identifier to context so when some operations are logged in tree pool +// this identifier also be logged. +func SetRequestID(ctx context.Context, reqID string) context.Context { + return context.WithValue(ctx, reqKeyType{}, reqID) +} + +// GetRequestID fetch tree pool request identifier from context. +func GetRequestID(ctx context.Context) string { + reqID, _ := ctx.Value(reqKeyType{}).(string) + return reqID +} diff --git a/pkg/sdk/pool/tree/pool_signature.go b/pkg/sdk/pool/tree/pool_signature.go new file mode 100644 index 000000000..0b3a2f6d4 --- /dev/null +++ b/pkg/sdk/pool/tree/pool_signature.go @@ -0,0 +1,25 @@ +package tree + +import ( + crypto "git.frostfs.info/TrueCloudLab/frostfs-crypto" + "google.golang.org/protobuf/proto" +) + +func (p *Pool) signData(buf []byte, f func(key, sign []byte)) error { + sign, err := crypto.Sign(&p.key.PrivateKey, buf) + if err != nil { + return err + } + + f(p.key.PublicKey().Bytes(), sign) + return nil +} + +func (p *Pool) signRequest(requestBody proto.Message, f func(key, sign []byte)) error { + buf, err := proto.Marshal(requestBody) + if err != nil { + return err + } + + return p.signData(buf, f) +} diff --git a/pkg/sdk/pool/tree/pool_test.go b/pkg/sdk/pool/tree/pool_test.go new file mode 100644 index 000000000..a3dfaeffc --- /dev/null +++ b/pkg/sdk/pool/tree/pool_test.go @@ -0,0 +1,356 @@ +package tree + +import ( + "context" + "errors" + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/pool" + grpcService "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/pool/tree/service" + "github.com/stretchr/testify/require" + "go.uber.org/zap/zaptest" +) + +type treeClientMock struct { + address string + err bool +} + +func (t *treeClientMock) serviceClient() (grpcService.TreeServiceClient, error) { + if t.err { + return nil, errors.New("serviceClient() mock error") + } + return nil, nil +} + +func (t *treeClientMock) endpoint() string { + return t.address +} + +func (t *treeClientMock) isHealthy() bool { + return true +} + +func (t *treeClientMock) setHealthy(bool) { + return +} + +func (t *treeClientMock) dial(context.Context) error { + return nil +} + +func (t *treeClientMock) redialIfNecessary(context.Context) (bool, error) { + if t.err { + return false, errors.New("redialIfNecessary() mock error") + } + return false, nil +} + +func (t *treeClientMock) close() error { + return nil +} + +func TestHandleError(t *testing.T) { + defaultError := errors.New("default error") + for _, tc := range []struct { + err error + expectedError error + }{ + { + err: defaultError, + expectedError: defaultError, + }, + { + err: errors.New("something not found"), + expectedError: ErrNodeNotFound, + }, + { + err: errors.New("something is denied by some acl rule"), + expectedError: ErrNodeAccessDenied, + }, + } { + t.Run("", func(t *testing.T) { + err := handleError("err message", tc.err) + require.True(t, errors.Is(err, tc.expectedError)) + }) + } +} + +func TestRetry(t *testing.T) { + ctx := context.Background() + nodes := [][]string{ + {"node00", "node01", "node02", "node03"}, + {"node10", "node11", "node12", "node13"}, + } + + var lenNodes int + for i := range nodes { + lenNodes += len(nodes[i]) + } + + p := &Pool{ + logger: zaptest.NewLogger(t), + innerPools: makeInnerPool(nodes), + maxRequestAttempts: lenNodes, + } + + makeFn := func(client grpcService.TreeServiceClient) error { + return nil + } + + t.Run("first ok", func(t *testing.T) { + err := p.requestWithRetry(ctx, makeFn) + require.NoError(t, err) + checkIndicesAndReset(t, p, 0, 0) + }) + + t.Run("first failed", func(t *testing.T) { + setErrors(p, "node00") + err := p.requestWithRetry(ctx, makeFn) + require.NoError(t, err) + checkIndicesAndReset(t, p, 0, 1) + }) + + t.Run("all failed", func(t *testing.T) { + setErrors(p, nodes[0]...) + setErrors(p, nodes[1]...) + err := p.requestWithRetry(ctx, makeFn) + require.Error(t, err) + checkIndicesAndReset(t, p, 0, 0) + }) + + t.Run("round", func(t *testing.T) { + setErrors(p, nodes[0][0], nodes[0][1]) + setErrors(p, nodes[1]...) + err := p.requestWithRetry(ctx, makeFn) + require.NoError(t, err) + checkIndices(t, p, 0, 2) + resetClientsErrors(p) + + setErrors(p, nodes[0][2], nodes[0][3]) + err = p.requestWithRetry(ctx, makeFn) + require.NoError(t, err) + checkIndicesAndReset(t, p, 0, 0) + }) + + t.Run("group switch", func(t *testing.T) { + setErrors(p, nodes[0]...) + setErrors(p, nodes[1][0]) + err := p.requestWithRetry(ctx, makeFn) + require.NoError(t, err) + checkIndicesAndReset(t, p, 1, 1) + }) + + t.Run("group round", func(t *testing.T) { + setErrors(p, nodes[0][1:]...) + err := p.requestWithRetry(ctx, makeFn) + require.NoError(t, err) + checkIndicesAndReset(t, p, 0, 0) + }) + + t.Run("group round switch", func(t *testing.T) { + setErrors(p, nodes[0]...) + p.setStartIndices(0, 1) + err := p.requestWithRetry(ctx, makeFn) + require.NoError(t, err) + checkIndicesAndReset(t, p, 1, 0) + }) + + t.Run("no panic group switch", func(t *testing.T) { + setErrors(p, nodes[1]...) + p.setStartIndices(1, 0) + err := p.requestWithRetry(ctx, makeFn) + require.NoError(t, err) + checkIndicesAndReset(t, p, 0, 0) + }) + + t.Run("error empty result", func(t *testing.T) { + errNodes, index := 2, 0 + err := p.requestWithRetry(ctx, func(client grpcService.TreeServiceClient) error { + if index < errNodes { + index++ + return errNodeEmptyResult + } + return nil + }) + require.NoError(t, err) + checkIndicesAndReset(t, p, 0, errNodes) + }) + + t.Run("error not found", func(t *testing.T) { + errNodes, index := 2, 0 + err := p.requestWithRetry(ctx, func(client grpcService.TreeServiceClient) error { + if index < errNodes { + index++ + return ErrNodeNotFound + } + return nil + }) + require.NoError(t, err) + checkIndicesAndReset(t, p, 0, errNodes) + }) + + t.Run("error access denied", func(t *testing.T) { + var index int + err := p.requestWithRetry(ctx, func(client grpcService.TreeServiceClient) error { + index++ + return ErrNodeAccessDenied + }) + require.ErrorIs(t, err, ErrNodeAccessDenied) + require.Equal(t, 1, index) + checkIndicesAndReset(t, p, 0, 0) + }) + + t.Run("limit attempts", func(t *testing.T) { + oldVal := p.maxRequestAttempts + p.maxRequestAttempts = 2 + setErrors(p, nodes[0]...) + setErrors(p, nodes[1]...) + err := p.requestWithRetry(ctx, makeFn) + require.Error(t, err) + checkIndicesAndReset(t, p, 0, 2) + p.maxRequestAttempts = oldVal + }) +} + +func TestRebalance(t *testing.T) { + nodes := [][]string{ + {"node00", "node01"}, + {"node10", "node11"}, + } + + p := &Pool{ + logger: zaptest.NewLogger(t), + innerPools: makeInnerPool(nodes), + rebalanceParams: rebalanceParameters{ + nodesGroup: makeNodesGroup(nodes), + }, + } + + ctx := context.Background() + buffers := makeBuffer(p) + + t.Run("check dirty buffers", func(t *testing.T) { + p.updateNodesHealth(ctx, buffers) + checkIndices(t, p, 0, 0) + setErrors(p, nodes[0][0]) + p.updateNodesHealth(ctx, buffers) + checkIndices(t, p, 0, 1) + resetClients(p) + }) + + t.Run("don't change healthy status", func(t *testing.T) { + p.updateNodesHealth(ctx, buffers) + checkIndices(t, p, 0, 0) + resetClients(p) + }) + + t.Run("switch to second group", func(t *testing.T) { + setErrors(p, nodes[0][0], nodes[0][1]) + p.updateNodesHealth(ctx, buffers) + checkIndices(t, p, 1, 0) + resetClients(p) + }) + + t.Run("switch back and forth", func(t *testing.T) { + setErrors(p, nodes[0][0], nodes[0][1]) + p.updateNodesHealth(ctx, buffers) + checkIndices(t, p, 1, 0) + + p.updateNodesHealth(ctx, buffers) + checkIndices(t, p, 1, 0) + + setNoErrors(p, nodes[0][0]) + p.updateNodesHealth(ctx, buffers) + checkIndices(t, p, 0, 0) + + resetClients(p) + }) +} + +func makeInnerPool(nodes [][]string) []*innerPool { + res := make([]*innerPool, len(nodes)) + + for i, group := range nodes { + res[i] = &innerPool{clients: make([]client, len(group))} + for j, node := range group { + res[i].clients[j] = &treeClientMock{address: node} + } + } + + return res +} + +func makeNodesGroup(nodes [][]string) [][]pool.NodeParam { + res := make([][]pool.NodeParam, len(nodes)) + + for i, group := range nodes { + res[i] = make([]pool.NodeParam, len(group)) + for j, node := range group { + res[i][j] = pool.NewNodeParam(1, node, 1) + } + } + + return res +} + +func makeBuffer(p *Pool) [][]bool { + buffers := make([][]bool, len(p.rebalanceParams.nodesGroup)) + for i, nodes := range p.rebalanceParams.nodesGroup { + buffers[i] = make([]bool, len(nodes)) + } + return buffers +} + +func checkIndicesAndReset(t *testing.T, p *Pool, iExp, jExp int) { + checkIndices(t, p, iExp, jExp) + resetClients(p) +} + +func checkIndices(t *testing.T, p *Pool, iExp, jExp int) { + i, j := p.getStartIndices() + require.Equal(t, [2]int{iExp, jExp}, [2]int{i, j}) +} + +func resetClients(p *Pool) { + resetClientsErrors(p) + p.setStartIndices(0, 0) +} + +func resetClientsErrors(p *Pool) { + for _, group := range p.innerPools { + for _, cl := range group.clients { + node := cl.(*treeClientMock) + node.err = false + } + } +} + +func setErrors(p *Pool, nodes ...string) { + setErrorsBase(p, true, nodes...) +} + +func setNoErrors(p *Pool, nodes ...string) { + setErrorsBase(p, false, nodes...) +} + +func setErrorsBase(p *Pool, err bool, nodes ...string) { + for _, group := range p.innerPools { + for _, cl := range group.clients { + node := cl.(*treeClientMock) + if containsStr(nodes, node.address) { + node.err = err + } + } + } +} + +func containsStr(list []string, item string) bool { + for i := range list { + if list[i] == item { + return true + } + } + + return false +} diff --git a/pkg/sdk/pool/tree/service/service.pb.go b/pkg/sdk/pool/tree/service/service.pb.go new file mode 100644 index 000000000..63f3e714a --- /dev/null +++ b/pkg/sdk/pool/tree/service/service.pb.go @@ -0,0 +1,3585 @@ +//* +// Service for working with CRDT tree. + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.26.0 +// protoc v3.21.9 +// source: pkg/services/tree/service.proto + +package tree + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type GetSubTreeRequest_Body_Order_Direction int32 + +const ( + GetSubTreeRequest_Body_Order_None GetSubTreeRequest_Body_Order_Direction = 0 + GetSubTreeRequest_Body_Order_Asc GetSubTreeRequest_Body_Order_Direction = 1 +) + +// Enum value maps for GetSubTreeRequest_Body_Order_Direction. +var ( + GetSubTreeRequest_Body_Order_Direction_name = map[int32]string{ + 0: "None", + 1: "Asc", + } + GetSubTreeRequest_Body_Order_Direction_value = map[string]int32{ + "None": 0, + "Asc": 1, + } +) + +func (x GetSubTreeRequest_Body_Order_Direction) Enum() *GetSubTreeRequest_Body_Order_Direction { + p := new(GetSubTreeRequest_Body_Order_Direction) + *p = x + return p +} + +func (x GetSubTreeRequest_Body_Order_Direction) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (GetSubTreeRequest_Body_Order_Direction) Descriptor() protoreflect.EnumDescriptor { + return file_pkg_services_tree_service_proto_enumTypes[0].Descriptor() +} + +func (GetSubTreeRequest_Body_Order_Direction) Type() protoreflect.EnumType { + return &file_pkg_services_tree_service_proto_enumTypes[0] +} + +func (x GetSubTreeRequest_Body_Order_Direction) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use GetSubTreeRequest_Body_Order_Direction.Descriptor instead. +func (GetSubTreeRequest_Body_Order_Direction) EnumDescriptor() ([]byte, []int) { + return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{10, 0, 0, 0} +} + +type AddRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Request body. + Body *AddRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Request signature. + Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` +} + +func (x *AddRequest) Reset() { + *x = AddRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_tree_service_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AddRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddRequest) ProtoMessage() {} + +func (x *AddRequest) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_tree_service_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AddRequest.ProtoReflect.Descriptor instead. +func (*AddRequest) Descriptor() ([]byte, []int) { + return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{0} +} + +func (x *AddRequest) GetBody() *AddRequest_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *AddRequest) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} + +type AddResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Response body. + Body *AddResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Response signature. + Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` +} + +func (x *AddResponse) Reset() { + *x = AddResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_tree_service_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AddResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddResponse) ProtoMessage() {} + +func (x *AddResponse) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_tree_service_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AddResponse.ProtoReflect.Descriptor instead. +func (*AddResponse) Descriptor() ([]byte, []int) { + return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{1} +} + +func (x *AddResponse) GetBody() *AddResponse_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *AddResponse) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} + +type AddByPathRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Request body. + Body *AddByPathRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Request signature. + Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` +} + +func (x *AddByPathRequest) Reset() { + *x = AddByPathRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_tree_service_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AddByPathRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddByPathRequest) ProtoMessage() {} + +func (x *AddByPathRequest) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_tree_service_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AddByPathRequest.ProtoReflect.Descriptor instead. +func (*AddByPathRequest) Descriptor() ([]byte, []int) { + return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{2} +} + +func (x *AddByPathRequest) GetBody() *AddByPathRequest_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *AddByPathRequest) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} + +type AddByPathResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Response body. + Body *AddByPathResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Response signature. + Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` +} + +func (x *AddByPathResponse) Reset() { + *x = AddByPathResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_tree_service_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AddByPathResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddByPathResponse) ProtoMessage() {} + +func (x *AddByPathResponse) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_tree_service_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AddByPathResponse.ProtoReflect.Descriptor instead. +func (*AddByPathResponse) Descriptor() ([]byte, []int) { + return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{3} +} + +func (x *AddByPathResponse) GetBody() *AddByPathResponse_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *AddByPathResponse) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} + +type RemoveRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Request body. + Body *RemoveRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Request signature. + Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` +} + +func (x *RemoveRequest) Reset() { + *x = RemoveRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_tree_service_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RemoveRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RemoveRequest) ProtoMessage() {} + +func (x *RemoveRequest) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_tree_service_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RemoveRequest.ProtoReflect.Descriptor instead. +func (*RemoveRequest) Descriptor() ([]byte, []int) { + return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{4} +} + +func (x *RemoveRequest) GetBody() *RemoveRequest_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *RemoveRequest) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} + +type RemoveResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Response body. + Body *RemoveResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Response signature. + Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` +} + +func (x *RemoveResponse) Reset() { + *x = RemoveResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_tree_service_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RemoveResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RemoveResponse) ProtoMessage() {} + +func (x *RemoveResponse) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_tree_service_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RemoveResponse.ProtoReflect.Descriptor instead. +func (*RemoveResponse) Descriptor() ([]byte, []int) { + return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{5} +} + +func (x *RemoveResponse) GetBody() *RemoveResponse_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *RemoveResponse) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} + +type MoveRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Request body. + Body *MoveRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Request signature. + Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` +} + +func (x *MoveRequest) Reset() { + *x = MoveRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_tree_service_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MoveRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MoveRequest) ProtoMessage() {} + +func (x *MoveRequest) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_tree_service_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MoveRequest.ProtoReflect.Descriptor instead. +func (*MoveRequest) Descriptor() ([]byte, []int) { + return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{6} +} + +func (x *MoveRequest) GetBody() *MoveRequest_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *MoveRequest) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} + +type MoveResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Response body. + Body *MoveResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Response signature. + Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` +} + +func (x *MoveResponse) Reset() { + *x = MoveResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_tree_service_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MoveResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MoveResponse) ProtoMessage() {} + +func (x *MoveResponse) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_tree_service_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MoveResponse.ProtoReflect.Descriptor instead. +func (*MoveResponse) Descriptor() ([]byte, []int) { + return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{7} +} + +func (x *MoveResponse) GetBody() *MoveResponse_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *MoveResponse) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} + +type GetNodeByPathRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Request body. + Body *GetNodeByPathRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Request signature. + Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` +} + +func (x *GetNodeByPathRequest) Reset() { + *x = GetNodeByPathRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_tree_service_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetNodeByPathRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetNodeByPathRequest) ProtoMessage() {} + +func (x *GetNodeByPathRequest) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_tree_service_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetNodeByPathRequest.ProtoReflect.Descriptor instead. +func (*GetNodeByPathRequest) Descriptor() ([]byte, []int) { + return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{8} +} + +func (x *GetNodeByPathRequest) GetBody() *GetNodeByPathRequest_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *GetNodeByPathRequest) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} + +type GetNodeByPathResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Response body. + Body *GetNodeByPathResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Response signature. + Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` +} + +func (x *GetNodeByPathResponse) Reset() { + *x = GetNodeByPathResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_tree_service_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetNodeByPathResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetNodeByPathResponse) ProtoMessage() {} + +func (x *GetNodeByPathResponse) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_tree_service_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetNodeByPathResponse.ProtoReflect.Descriptor instead. +func (*GetNodeByPathResponse) Descriptor() ([]byte, []int) { + return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{9} +} + +func (x *GetNodeByPathResponse) GetBody() *GetNodeByPathResponse_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *GetNodeByPathResponse) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} + +type GetSubTreeRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Request body. + Body *GetSubTreeRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Request signature. + Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` +} + +func (x *GetSubTreeRequest) Reset() { + *x = GetSubTreeRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_tree_service_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetSubTreeRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetSubTreeRequest) ProtoMessage() {} + +func (x *GetSubTreeRequest) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_tree_service_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetSubTreeRequest.ProtoReflect.Descriptor instead. +func (*GetSubTreeRequest) Descriptor() ([]byte, []int) { + return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{10} +} + +func (x *GetSubTreeRequest) GetBody() *GetSubTreeRequest_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *GetSubTreeRequest) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} + +type GetSubTreeResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Response body. + Body *GetSubTreeResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Response signature. + Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` +} + +func (x *GetSubTreeResponse) Reset() { + *x = GetSubTreeResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_tree_service_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetSubTreeResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetSubTreeResponse) ProtoMessage() {} + +func (x *GetSubTreeResponse) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_tree_service_proto_msgTypes[11] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetSubTreeResponse.ProtoReflect.Descriptor instead. +func (*GetSubTreeResponse) Descriptor() ([]byte, []int) { + return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{11} +} + +func (x *GetSubTreeResponse) GetBody() *GetSubTreeResponse_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *GetSubTreeResponse) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} + +type TreeListRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Request body. + Body *TreeListRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Request signature. + Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` +} + +func (x *TreeListRequest) Reset() { + *x = TreeListRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_tree_service_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TreeListRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TreeListRequest) ProtoMessage() {} + +func (x *TreeListRequest) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_tree_service_proto_msgTypes[12] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TreeListRequest.ProtoReflect.Descriptor instead. +func (*TreeListRequest) Descriptor() ([]byte, []int) { + return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{12} +} + +func (x *TreeListRequest) GetBody() *TreeListRequest_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *TreeListRequest) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} + +type TreeListResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Response body. + Body *TreeListResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` +} + +func (x *TreeListResponse) Reset() { + *x = TreeListResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_tree_service_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TreeListResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TreeListResponse) ProtoMessage() {} + +func (x *TreeListResponse) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_tree_service_proto_msgTypes[13] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TreeListResponse.ProtoReflect.Descriptor instead. +func (*TreeListResponse) Descriptor() ([]byte, []int) { + return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{13} +} + +func (x *TreeListResponse) GetBody() *TreeListResponse_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *TreeListResponse) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} + +type ApplyRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Request body. + Body *ApplyRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Request signature. + Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` +} + +func (x *ApplyRequest) Reset() { + *x = ApplyRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_tree_service_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ApplyRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ApplyRequest) ProtoMessage() {} + +func (x *ApplyRequest) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_tree_service_proto_msgTypes[14] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ApplyRequest.ProtoReflect.Descriptor instead. +func (*ApplyRequest) Descriptor() ([]byte, []int) { + return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{14} +} + +func (x *ApplyRequest) GetBody() *ApplyRequest_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *ApplyRequest) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} + +type ApplyResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Response body. + Body *ApplyResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Response signature. + Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` +} + +func (x *ApplyResponse) Reset() { + *x = ApplyResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_tree_service_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ApplyResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ApplyResponse) ProtoMessage() {} + +func (x *ApplyResponse) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_tree_service_proto_msgTypes[15] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ApplyResponse.ProtoReflect.Descriptor instead. +func (*ApplyResponse) Descriptor() ([]byte, []int) { + return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{15} +} + +func (x *ApplyResponse) GetBody() *ApplyResponse_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *ApplyResponse) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} + +type GetOpLogRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Request body. + Body *GetOpLogRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Request signature. + Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` +} + +func (x *GetOpLogRequest) Reset() { + *x = GetOpLogRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_tree_service_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetOpLogRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetOpLogRequest) ProtoMessage() {} + +func (x *GetOpLogRequest) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_tree_service_proto_msgTypes[16] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetOpLogRequest.ProtoReflect.Descriptor instead. +func (*GetOpLogRequest) Descriptor() ([]byte, []int) { + return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{16} +} + +func (x *GetOpLogRequest) GetBody() *GetOpLogRequest_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *GetOpLogRequest) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} + +type GetOpLogResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Response body. + Body *GetOpLogResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Response signature. + Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` +} + +func (x *GetOpLogResponse) Reset() { + *x = GetOpLogResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_tree_service_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetOpLogResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetOpLogResponse) ProtoMessage() {} + +func (x *GetOpLogResponse) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_tree_service_proto_msgTypes[17] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetOpLogResponse.ProtoReflect.Descriptor instead. +func (*GetOpLogResponse) Descriptor() ([]byte, []int) { + return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{17} +} + +func (x *GetOpLogResponse) GetBody() *GetOpLogResponse_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *GetOpLogResponse) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} + +type HealthcheckResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Response body. + Body *HealthcheckResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Response signature. + Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` +} + +func (x *HealthcheckResponse) Reset() { + *x = HealthcheckResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_tree_service_proto_msgTypes[18] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *HealthcheckResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HealthcheckResponse) ProtoMessage() {} + +func (x *HealthcheckResponse) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_tree_service_proto_msgTypes[18] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use HealthcheckResponse.ProtoReflect.Descriptor instead. +func (*HealthcheckResponse) Descriptor() ([]byte, []int) { + return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{18} +} + +func (x *HealthcheckResponse) GetBody() *HealthcheckResponse_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *HealthcheckResponse) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} + +type HealthcheckRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Request body. + Body *HealthcheckRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Request signature. + Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` +} + +func (x *HealthcheckRequest) Reset() { + *x = HealthcheckRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_tree_service_proto_msgTypes[19] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *HealthcheckRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HealthcheckRequest) ProtoMessage() {} + +func (x *HealthcheckRequest) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_tree_service_proto_msgTypes[19] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use HealthcheckRequest.ProtoReflect.Descriptor instead. +func (*HealthcheckRequest) Descriptor() ([]byte, []int) { + return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{19} +} + +func (x *HealthcheckRequest) GetBody() *HealthcheckRequest_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *HealthcheckRequest) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} + +type AddRequest_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Container ID in V2 format. + ContainerId []byte `protobuf:"bytes,1,opt,name=container_id,json=containerId,proto3" json:"container_id,omitempty"` + // The name of the tree. + TreeId string `protobuf:"bytes,2,opt,name=tree_id,json=treeId,proto3" json:"tree_id,omitempty"` + // ID of the parent to attach node to. + ParentId uint64 `protobuf:"varint,3,opt,name=parent_id,json=parentId,proto3" json:"parent_id,omitempty"` + // Key-Value pairs with meta information. + Meta []*KeyValue `protobuf:"bytes,4,rep,name=meta,proto3" json:"meta,omitempty"` + // Bearer token in V2 format. + BearerToken []byte `protobuf:"bytes,5,opt,name=bearer_token,json=bearerToken,proto3" json:"bearer_token,omitempty"` +} + +func (x *AddRequest_Body) Reset() { + *x = AddRequest_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_tree_service_proto_msgTypes[20] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AddRequest_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddRequest_Body) ProtoMessage() {} + +func (x *AddRequest_Body) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_tree_service_proto_msgTypes[20] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AddRequest_Body.ProtoReflect.Descriptor instead. +func (*AddRequest_Body) Descriptor() ([]byte, []int) { + return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{0, 0} +} + +func (x *AddRequest_Body) GetContainerId() []byte { + if x != nil { + return x.ContainerId + } + return nil +} + +func (x *AddRequest_Body) GetTreeId() string { + if x != nil { + return x.TreeId + } + return "" +} + +func (x *AddRequest_Body) GetParentId() uint64 { + if x != nil { + return x.ParentId + } + return 0 +} + +func (x *AddRequest_Body) GetMeta() []*KeyValue { + if x != nil { + return x.Meta + } + return nil +} + +func (x *AddRequest_Body) GetBearerToken() []byte { + if x != nil { + return x.BearerToken + } + return nil +} + +type AddResponse_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // ID of the created node. + NodeId uint64 `protobuf:"varint,1,opt,name=node_id,json=nodeId,proto3" json:"node_id,omitempty"` +} + +func (x *AddResponse_Body) Reset() { + *x = AddResponse_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_tree_service_proto_msgTypes[21] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AddResponse_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddResponse_Body) ProtoMessage() {} + +func (x *AddResponse_Body) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_tree_service_proto_msgTypes[21] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AddResponse_Body.ProtoReflect.Descriptor instead. +func (*AddResponse_Body) Descriptor() ([]byte, []int) { + return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{1, 0} +} + +func (x *AddResponse_Body) GetNodeId() uint64 { + if x != nil { + return x.NodeId + } + return 0 +} + +type AddByPathRequest_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Container ID in V2 format. + ContainerId []byte `protobuf:"bytes,1,opt,name=container_id,json=containerId,proto3" json:"container_id,omitempty"` + // The name of the tree. + TreeId string `protobuf:"bytes,2,opt,name=tree_id,json=treeId,proto3" json:"tree_id,omitempty"` + // Attribute to build path with. Default: "FileName". + PathAttribute string `protobuf:"bytes,3,opt,name=path_attribute,json=pathAttribute,proto3" json:"path_attribute,omitempty"` + // List of path components. + Path []string `protobuf:"bytes,4,rep,name=path,proto3" json:"path,omitempty"` + // Node meta-information. + Meta []*KeyValue `protobuf:"bytes,5,rep,name=meta,proto3" json:"meta,omitempty"` + // Bearer token in V2 format. + BearerToken []byte `protobuf:"bytes,6,opt,name=bearer_token,json=bearerToken,proto3" json:"bearer_token,omitempty"` +} + +func (x *AddByPathRequest_Body) Reset() { + *x = AddByPathRequest_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_tree_service_proto_msgTypes[22] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AddByPathRequest_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddByPathRequest_Body) ProtoMessage() {} + +func (x *AddByPathRequest_Body) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_tree_service_proto_msgTypes[22] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AddByPathRequest_Body.ProtoReflect.Descriptor instead. +func (*AddByPathRequest_Body) Descriptor() ([]byte, []int) { + return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{2, 0} +} + +func (x *AddByPathRequest_Body) GetContainerId() []byte { + if x != nil { + return x.ContainerId + } + return nil +} + +func (x *AddByPathRequest_Body) GetTreeId() string { + if x != nil { + return x.TreeId + } + return "" +} + +func (x *AddByPathRequest_Body) GetPathAttribute() string { + if x != nil { + return x.PathAttribute + } + return "" +} + +func (x *AddByPathRequest_Body) GetPath() []string { + if x != nil { + return x.Path + } + return nil +} + +func (x *AddByPathRequest_Body) GetMeta() []*KeyValue { + if x != nil { + return x.Meta + } + return nil +} + +func (x *AddByPathRequest_Body) GetBearerToken() []byte { + if x != nil { + return x.BearerToken + } + return nil +} + +type AddByPathResponse_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // List of all created nodes. The first one is the leaf. + Nodes []uint64 `protobuf:"varint,1,rep,packed,name=nodes,proto3" json:"nodes,omitempty"` + // ID of the parent node where new nodes were attached. + ParentId uint64 `protobuf:"varint,2,opt,name=parent_id,json=parentId,proto3" json:"parent_id,omitempty"` +} + +func (x *AddByPathResponse_Body) Reset() { + *x = AddByPathResponse_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_tree_service_proto_msgTypes[23] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AddByPathResponse_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddByPathResponse_Body) ProtoMessage() {} + +func (x *AddByPathResponse_Body) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_tree_service_proto_msgTypes[23] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AddByPathResponse_Body.ProtoReflect.Descriptor instead. +func (*AddByPathResponse_Body) Descriptor() ([]byte, []int) { + return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{3, 0} +} + +func (x *AddByPathResponse_Body) GetNodes() []uint64 { + if x != nil { + return x.Nodes + } + return nil +} + +func (x *AddByPathResponse_Body) GetParentId() uint64 { + if x != nil { + return x.ParentId + } + return 0 +} + +type RemoveRequest_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Container ID in V2 format. + ContainerId []byte `protobuf:"bytes,1,opt,name=container_id,json=containerId,proto3" json:"container_id,omitempty"` + // The name of the tree. + TreeId string `protobuf:"bytes,2,opt,name=tree_id,json=treeId,proto3" json:"tree_id,omitempty"` + // ID of the node to remove. + NodeId uint64 `protobuf:"varint,3,opt,name=node_id,json=nodeId,proto3" json:"node_id,omitempty"` + // Bearer token in V2 format. + BearerToken []byte `protobuf:"bytes,4,opt,name=bearer_token,json=bearerToken,proto3" json:"bearer_token,omitempty"` +} + +func (x *RemoveRequest_Body) Reset() { + *x = RemoveRequest_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_tree_service_proto_msgTypes[24] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RemoveRequest_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RemoveRequest_Body) ProtoMessage() {} + +func (x *RemoveRequest_Body) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_tree_service_proto_msgTypes[24] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RemoveRequest_Body.ProtoReflect.Descriptor instead. +func (*RemoveRequest_Body) Descriptor() ([]byte, []int) { + return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{4, 0} +} + +func (x *RemoveRequest_Body) GetContainerId() []byte { + if x != nil { + return x.ContainerId + } + return nil +} + +func (x *RemoveRequest_Body) GetTreeId() string { + if x != nil { + return x.TreeId + } + return "" +} + +func (x *RemoveRequest_Body) GetNodeId() uint64 { + if x != nil { + return x.NodeId + } + return 0 +} + +func (x *RemoveRequest_Body) GetBearerToken() []byte { + if x != nil { + return x.BearerToken + } + return nil +} + +type RemoveResponse_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *RemoveResponse_Body) Reset() { + *x = RemoveResponse_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_tree_service_proto_msgTypes[25] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RemoveResponse_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RemoveResponse_Body) ProtoMessage() {} + +func (x *RemoveResponse_Body) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_tree_service_proto_msgTypes[25] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RemoveResponse_Body.ProtoReflect.Descriptor instead. +func (*RemoveResponse_Body) Descriptor() ([]byte, []int) { + return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{5, 0} +} + +type MoveRequest_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // TODO import neo.fs.v2.refs.ContainerID directly. + // Container ID in V2 format. + ContainerId []byte `protobuf:"bytes,1,opt,name=container_id,json=containerId,proto3" json:"container_id,omitempty"` + // The name of the tree. + TreeId string `protobuf:"bytes,2,opt,name=tree_id,json=treeId,proto3" json:"tree_id,omitempty"` + // ID of the new parent. + ParentId uint64 `protobuf:"varint,3,opt,name=parent_id,json=parentId,proto3" json:"parent_id,omitempty"` + // ID of the node to move. + NodeId uint64 `protobuf:"varint,4,opt,name=node_id,json=nodeId,proto3" json:"node_id,omitempty"` + // Node meta-information. + Meta []*KeyValue `protobuf:"bytes,5,rep,name=meta,proto3" json:"meta,omitempty"` + // Bearer token in V2 format. + BearerToken []byte `protobuf:"bytes,6,opt,name=bearer_token,json=bearerToken,proto3" json:"bearer_token,omitempty"` +} + +func (x *MoveRequest_Body) Reset() { + *x = MoveRequest_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_tree_service_proto_msgTypes[26] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MoveRequest_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MoveRequest_Body) ProtoMessage() {} + +func (x *MoveRequest_Body) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_tree_service_proto_msgTypes[26] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MoveRequest_Body.ProtoReflect.Descriptor instead. +func (*MoveRequest_Body) Descriptor() ([]byte, []int) { + return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{6, 0} +} + +func (x *MoveRequest_Body) GetContainerId() []byte { + if x != nil { + return x.ContainerId + } + return nil +} + +func (x *MoveRequest_Body) GetTreeId() string { + if x != nil { + return x.TreeId + } + return "" +} + +func (x *MoveRequest_Body) GetParentId() uint64 { + if x != nil { + return x.ParentId + } + return 0 +} + +func (x *MoveRequest_Body) GetNodeId() uint64 { + if x != nil { + return x.NodeId + } + return 0 +} + +func (x *MoveRequest_Body) GetMeta() []*KeyValue { + if x != nil { + return x.Meta + } + return nil +} + +func (x *MoveRequest_Body) GetBearerToken() []byte { + if x != nil { + return x.BearerToken + } + return nil +} + +type MoveResponse_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *MoveResponse_Body) Reset() { + *x = MoveResponse_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_tree_service_proto_msgTypes[27] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MoveResponse_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MoveResponse_Body) ProtoMessage() {} + +func (x *MoveResponse_Body) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_tree_service_proto_msgTypes[27] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MoveResponse_Body.ProtoReflect.Descriptor instead. +func (*MoveResponse_Body) Descriptor() ([]byte, []int) { + return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{7, 0} +} + +type GetNodeByPathRequest_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Container ID in V2 format. + ContainerId []byte `protobuf:"bytes,1,opt,name=container_id,json=containerId,proto3" json:"container_id,omitempty"` + // The name of the tree. + TreeId string `protobuf:"bytes,2,opt,name=tree_id,json=treeId,proto3" json:"tree_id,omitempty"` + // Attribute to build path with. Default: "FileName". + PathAttribute string `protobuf:"bytes,3,opt,name=path_attribute,json=pathAttribute,proto3" json:"path_attribute,omitempty"` + // List of path components. + Path []string `protobuf:"bytes,4,rep,name=path,proto3" json:"path,omitempty"` + // List of attributes to include in response. + Attributes []string `protobuf:"bytes,5,rep,name=attributes,proto3" json:"attributes,omitempty"` + // Flag to return only the latest version of node. + LatestOnly bool `protobuf:"varint,6,opt,name=latest_only,json=latestOnly,proto3" json:"latest_only,omitempty"` + // Flag to return all stored attributes. + AllAttributes bool `protobuf:"varint,7,opt,name=all_attributes,json=allAttributes,proto3" json:"all_attributes,omitempty"` + // Bearer token in V2 format. + BearerToken []byte `protobuf:"bytes,8,opt,name=bearer_token,json=bearerToken,proto3" json:"bearer_token,omitempty"` +} + +func (x *GetNodeByPathRequest_Body) Reset() { + *x = GetNodeByPathRequest_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_tree_service_proto_msgTypes[28] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetNodeByPathRequest_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetNodeByPathRequest_Body) ProtoMessage() {} + +func (x *GetNodeByPathRequest_Body) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_tree_service_proto_msgTypes[28] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetNodeByPathRequest_Body.ProtoReflect.Descriptor instead. +func (*GetNodeByPathRequest_Body) Descriptor() ([]byte, []int) { + return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{8, 0} +} + +func (x *GetNodeByPathRequest_Body) GetContainerId() []byte { + if x != nil { + return x.ContainerId + } + return nil +} + +func (x *GetNodeByPathRequest_Body) GetTreeId() string { + if x != nil { + return x.TreeId + } + return "" +} + +func (x *GetNodeByPathRequest_Body) GetPathAttribute() string { + if x != nil { + return x.PathAttribute + } + return "" +} + +func (x *GetNodeByPathRequest_Body) GetPath() []string { + if x != nil { + return x.Path + } + return nil +} + +func (x *GetNodeByPathRequest_Body) GetAttributes() []string { + if x != nil { + return x.Attributes + } + return nil +} + +func (x *GetNodeByPathRequest_Body) GetLatestOnly() bool { + if x != nil { + return x.LatestOnly + } + return false +} + +func (x *GetNodeByPathRequest_Body) GetAllAttributes() bool { + if x != nil { + return x.AllAttributes + } + return false +} + +func (x *GetNodeByPathRequest_Body) GetBearerToken() []byte { + if x != nil { + return x.BearerToken + } + return nil +} + +// Information about a single tree node. +type GetNodeByPathResponse_Info struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Node ID. + NodeId uint64 `protobuf:"varint,1,opt,name=node_id,json=nodeId,proto3" json:"node_id,omitempty"` + // Timestamp of the last operation with the node. + Timestamp uint64 `protobuf:"varint,2,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + // Node meta-information. + Meta []*KeyValue `protobuf:"bytes,3,rep,name=meta,proto3" json:"meta,omitempty"` + // Parent ID. + ParentId uint64 `protobuf:"varint,4,opt,name=parent_id,json=parentId,proto3" json:"parent_id,omitempty"` +} + +func (x *GetNodeByPathResponse_Info) Reset() { + *x = GetNodeByPathResponse_Info{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_tree_service_proto_msgTypes[29] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetNodeByPathResponse_Info) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetNodeByPathResponse_Info) ProtoMessage() {} + +func (x *GetNodeByPathResponse_Info) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_tree_service_proto_msgTypes[29] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetNodeByPathResponse_Info.ProtoReflect.Descriptor instead. +func (*GetNodeByPathResponse_Info) Descriptor() ([]byte, []int) { + return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{9, 0} +} + +func (x *GetNodeByPathResponse_Info) GetNodeId() uint64 { + if x != nil { + return x.NodeId + } + return 0 +} + +func (x *GetNodeByPathResponse_Info) GetTimestamp() uint64 { + if x != nil { + return x.Timestamp + } + return 0 +} + +func (x *GetNodeByPathResponse_Info) GetMeta() []*KeyValue { + if x != nil { + return x.Meta + } + return nil +} + +func (x *GetNodeByPathResponse_Info) GetParentId() uint64 { + if x != nil { + return x.ParentId + } + return 0 +} + +type GetNodeByPathResponse_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // List of nodes stored by path. + Nodes []*GetNodeByPathResponse_Info `protobuf:"bytes,1,rep,name=nodes,proto3" json:"nodes,omitempty"` +} + +func (x *GetNodeByPathResponse_Body) Reset() { + *x = GetNodeByPathResponse_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_tree_service_proto_msgTypes[30] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetNodeByPathResponse_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetNodeByPathResponse_Body) ProtoMessage() {} + +func (x *GetNodeByPathResponse_Body) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_tree_service_proto_msgTypes[30] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetNodeByPathResponse_Body.ProtoReflect.Descriptor instead. +func (*GetNodeByPathResponse_Body) Descriptor() ([]byte, []int) { + return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{9, 1} +} + +func (x *GetNodeByPathResponse_Body) GetNodes() []*GetNodeByPathResponse_Info { + if x != nil { + return x.Nodes + } + return nil +} + +type GetSubTreeRequest_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Container ID in V2 format. + ContainerId []byte `protobuf:"bytes,1,opt,name=container_id,json=containerId,proto3" json:"container_id,omitempty"` + // The name of the tree. + TreeId string `protobuf:"bytes,2,opt,name=tree_id,json=treeId,proto3" json:"tree_id,omitempty"` + // ID of the root node of a subtree. + RootId uint64 `protobuf:"varint,3,opt,name=root_id,json=rootId,proto3" json:"root_id,omitempty"` + // Optional depth of the traversal. Zero means return only root. + // Maximum depth is 10. + Depth uint32 `protobuf:"varint,4,opt,name=depth,proto3" json:"depth,omitempty"` + // Bearer token in V2 format. + BearerToken []byte `protobuf:"bytes,5,opt,name=bearer_token,json=bearerToken,proto3" json:"bearer_token,omitempty"` + // Result ordering. + OrderBy *GetSubTreeRequest_Body_Order `protobuf:"bytes,6,opt,name=order_by,json=orderBy,proto3" json:"order_by,omitempty"` +} + +func (x *GetSubTreeRequest_Body) Reset() { + *x = GetSubTreeRequest_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_tree_service_proto_msgTypes[31] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetSubTreeRequest_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetSubTreeRequest_Body) ProtoMessage() {} + +func (x *GetSubTreeRequest_Body) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_tree_service_proto_msgTypes[31] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetSubTreeRequest_Body.ProtoReflect.Descriptor instead. +func (*GetSubTreeRequest_Body) Descriptor() ([]byte, []int) { + return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{10, 0} +} + +func (x *GetSubTreeRequest_Body) GetContainerId() []byte { + if x != nil { + return x.ContainerId + } + return nil +} + +func (x *GetSubTreeRequest_Body) GetTreeId() string { + if x != nil { + return x.TreeId + } + return "" +} + +func (x *GetSubTreeRequest_Body) GetRootId() uint64 { + if x != nil { + return x.RootId + } + return 0 +} + +func (x *GetSubTreeRequest_Body) GetDepth() uint32 { + if x != nil { + return x.Depth + } + return 0 +} + +func (x *GetSubTreeRequest_Body) GetBearerToken() []byte { + if x != nil { + return x.BearerToken + } + return nil +} + +func (x *GetSubTreeRequest_Body) GetOrderBy() *GetSubTreeRequest_Body_Order { + if x != nil { + return x.OrderBy + } + return nil +} + +type GetSubTreeRequest_Body_Order struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Direction GetSubTreeRequest_Body_Order_Direction `protobuf:"varint,1,opt,name=direction,proto3,enum=tree.GetSubTreeRequest_Body_Order_Direction" json:"direction,omitempty"` +} + +func (x *GetSubTreeRequest_Body_Order) Reset() { + *x = GetSubTreeRequest_Body_Order{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_tree_service_proto_msgTypes[32] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetSubTreeRequest_Body_Order) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetSubTreeRequest_Body_Order) ProtoMessage() {} + +func (x *GetSubTreeRequest_Body_Order) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_tree_service_proto_msgTypes[32] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetSubTreeRequest_Body_Order.ProtoReflect.Descriptor instead. +func (*GetSubTreeRequest_Body_Order) Descriptor() ([]byte, []int) { + return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{10, 0, 0} +} + +func (x *GetSubTreeRequest_Body_Order) GetDirection() GetSubTreeRequest_Body_Order_Direction { + if x != nil { + return x.Direction + } + return GetSubTreeRequest_Body_Order_None +} + +type GetSubTreeResponse_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // ID of the node. + NodeId uint64 `protobuf:"varint,1,opt,name=node_id,json=nodeId,proto3" json:"node_id,omitempty"` + // ID of the parent. + ParentId uint64 `protobuf:"varint,2,opt,name=parent_id,json=parentId,proto3" json:"parent_id,omitempty"` + // Time node was first added to a tree. + Timestamp uint64 `protobuf:"varint,3,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + // Node meta-information. + Meta []*KeyValue `protobuf:"bytes,4,rep,name=meta,proto3" json:"meta,omitempty"` +} + +func (x *GetSubTreeResponse_Body) Reset() { + *x = GetSubTreeResponse_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_tree_service_proto_msgTypes[33] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetSubTreeResponse_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetSubTreeResponse_Body) ProtoMessage() {} + +func (x *GetSubTreeResponse_Body) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_tree_service_proto_msgTypes[33] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetSubTreeResponse_Body.ProtoReflect.Descriptor instead. +func (*GetSubTreeResponse_Body) Descriptor() ([]byte, []int) { + return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{11, 0} +} + +func (x *GetSubTreeResponse_Body) GetNodeId() uint64 { + if x != nil { + return x.NodeId + } + return 0 +} + +func (x *GetSubTreeResponse_Body) GetParentId() uint64 { + if x != nil { + return x.ParentId + } + return 0 +} + +func (x *GetSubTreeResponse_Body) GetTimestamp() uint64 { + if x != nil { + return x.Timestamp + } + return 0 +} + +func (x *GetSubTreeResponse_Body) GetMeta() []*KeyValue { + if x != nil { + return x.Meta + } + return nil +} + +type TreeListRequest_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Container ID in V2 format. + ContainerId []byte `protobuf:"bytes,1,opt,name=container_id,json=containerId,proto3" json:"container_id,omitempty"` +} + +func (x *TreeListRequest_Body) Reset() { + *x = TreeListRequest_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_tree_service_proto_msgTypes[34] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TreeListRequest_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TreeListRequest_Body) ProtoMessage() {} + +func (x *TreeListRequest_Body) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_tree_service_proto_msgTypes[34] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TreeListRequest_Body.ProtoReflect.Descriptor instead. +func (*TreeListRequest_Body) Descriptor() ([]byte, []int) { + return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{12, 0} +} + +func (x *TreeListRequest_Body) GetContainerId() []byte { + if x != nil { + return x.ContainerId + } + return nil +} + +type TreeListResponse_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Tree IDs. + Ids []string `protobuf:"bytes,1,rep,name=ids,proto3" json:"ids,omitempty"` +} + +func (x *TreeListResponse_Body) Reset() { + *x = TreeListResponse_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_tree_service_proto_msgTypes[35] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TreeListResponse_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TreeListResponse_Body) ProtoMessage() {} + +func (x *TreeListResponse_Body) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_tree_service_proto_msgTypes[35] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TreeListResponse_Body.ProtoReflect.Descriptor instead. +func (*TreeListResponse_Body) Descriptor() ([]byte, []int) { + return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{13, 0} +} + +func (x *TreeListResponse_Body) GetIds() []string { + if x != nil { + return x.Ids + } + return nil +} + +type ApplyRequest_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Container ID in V2 format. + ContainerId []byte `protobuf:"bytes,1,opt,name=container_id,json=containerId,proto3" json:"container_id,omitempty"` + // The name of the tree. + TreeId string `protobuf:"bytes,2,opt,name=tree_id,json=treeId,proto3" json:"tree_id,omitempty"` + // Operation to be applied. + Operation *LogMove `protobuf:"bytes,3,opt,name=operation,proto3" json:"operation,omitempty"` +} + +func (x *ApplyRequest_Body) Reset() { + *x = ApplyRequest_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_tree_service_proto_msgTypes[36] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ApplyRequest_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ApplyRequest_Body) ProtoMessage() {} + +func (x *ApplyRequest_Body) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_tree_service_proto_msgTypes[36] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ApplyRequest_Body.ProtoReflect.Descriptor instead. +func (*ApplyRequest_Body) Descriptor() ([]byte, []int) { + return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{14, 0} +} + +func (x *ApplyRequest_Body) GetContainerId() []byte { + if x != nil { + return x.ContainerId + } + return nil +} + +func (x *ApplyRequest_Body) GetTreeId() string { + if x != nil { + return x.TreeId + } + return "" +} + +func (x *ApplyRequest_Body) GetOperation() *LogMove { + if x != nil { + return x.Operation + } + return nil +} + +type ApplyResponse_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *ApplyResponse_Body) Reset() { + *x = ApplyResponse_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_tree_service_proto_msgTypes[37] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ApplyResponse_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ApplyResponse_Body) ProtoMessage() {} + +func (x *ApplyResponse_Body) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_tree_service_proto_msgTypes[37] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ApplyResponse_Body.ProtoReflect.Descriptor instead. +func (*ApplyResponse_Body) Descriptor() ([]byte, []int) { + return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{15, 0} +} + +type GetOpLogRequest_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Container ID in V2 format. + ContainerId []byte `protobuf:"bytes,1,opt,name=container_id,json=containerId,proto3" json:"container_id,omitempty"` + // The name of the tree. + TreeId string `protobuf:"bytes,2,opt,name=tree_id,json=treeId,proto3" json:"tree_id,omitempty"` + // Starting height to return logs from. + Height uint64 `protobuf:"varint,3,opt,name=height,proto3" json:"height,omitempty"` + // Amount of operations to return. + Count uint64 `protobuf:"varint,4,opt,name=count,proto3" json:"count,omitempty"` +} + +func (x *GetOpLogRequest_Body) Reset() { + *x = GetOpLogRequest_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_tree_service_proto_msgTypes[38] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetOpLogRequest_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetOpLogRequest_Body) ProtoMessage() {} + +func (x *GetOpLogRequest_Body) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_tree_service_proto_msgTypes[38] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetOpLogRequest_Body.ProtoReflect.Descriptor instead. +func (*GetOpLogRequest_Body) Descriptor() ([]byte, []int) { + return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{16, 0} +} + +func (x *GetOpLogRequest_Body) GetContainerId() []byte { + if x != nil { + return x.ContainerId + } + return nil +} + +func (x *GetOpLogRequest_Body) GetTreeId() string { + if x != nil { + return x.TreeId + } + return "" +} + +func (x *GetOpLogRequest_Body) GetHeight() uint64 { + if x != nil { + return x.Height + } + return 0 +} + +func (x *GetOpLogRequest_Body) GetCount() uint64 { + if x != nil { + return x.Count + } + return 0 +} + +type GetOpLogResponse_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Operation on a tree. + Operation *LogMove `protobuf:"bytes,1,opt,name=operation,proto3" json:"operation,omitempty"` +} + +func (x *GetOpLogResponse_Body) Reset() { + *x = GetOpLogResponse_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_tree_service_proto_msgTypes[39] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetOpLogResponse_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetOpLogResponse_Body) ProtoMessage() {} + +func (x *GetOpLogResponse_Body) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_tree_service_proto_msgTypes[39] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetOpLogResponse_Body.ProtoReflect.Descriptor instead. +func (*GetOpLogResponse_Body) Descriptor() ([]byte, []int) { + return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{17, 0} +} + +func (x *GetOpLogResponse_Body) GetOperation() *LogMove { + if x != nil { + return x.Operation + } + return nil +} + +type HealthcheckResponse_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *HealthcheckResponse_Body) Reset() { + *x = HealthcheckResponse_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_tree_service_proto_msgTypes[40] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *HealthcheckResponse_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HealthcheckResponse_Body) ProtoMessage() {} + +func (x *HealthcheckResponse_Body) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_tree_service_proto_msgTypes[40] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use HealthcheckResponse_Body.ProtoReflect.Descriptor instead. +func (*HealthcheckResponse_Body) Descriptor() ([]byte, []int) { + return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{18, 0} +} + +type HealthcheckRequest_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *HealthcheckRequest_Body) Reset() { + *x = HealthcheckRequest_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_tree_service_proto_msgTypes[41] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *HealthcheckRequest_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HealthcheckRequest_Body) ProtoMessage() {} + +func (x *HealthcheckRequest_Body) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_tree_service_proto_msgTypes[41] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use HealthcheckRequest_Body.ProtoReflect.Descriptor instead. +func (*HealthcheckRequest_Body) Descriptor() ([]byte, []int) { + return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{19, 0} +} + +var File_pkg_services_tree_service_proto protoreflect.FileDescriptor + +var file_pkg_services_tree_service_proto_rawDesc = []byte{ + 0x0a, 0x1f, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x74, + 0x72, 0x65, 0x65, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x12, 0x04, 0x74, 0x72, 0x65, 0x65, 0x1a, 0x1d, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x74, 0x72, 0x65, 0x65, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x8f, 0x02, 0x0a, 0x0a, 0x41, 0x64, 0x64, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x41, 0x64, 0x64, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, + 0x12, 0x2d, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, + 0xa6, 0x01, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, + 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, + 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x74, + 0x72, 0x65, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x72, + 0x65, 0x65, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x69, + 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x49, + 0x64, 0x12, 0x22, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x0e, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x4b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, + 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x21, 0x0a, 0x0c, 0x62, 0x65, 0x61, 0x72, 0x65, 0x72, 0x5f, + 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x62, 0x65, 0x61, + 0x72, 0x65, 0x72, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x89, 0x01, 0x0a, 0x0b, 0x41, 0x64, 0x64, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2a, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x41, 0x64, + 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, + 0x62, 0x6f, 0x64, 0x79, 0x12, 0x2d, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x53, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x1a, 0x1f, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x17, 0x0a, 0x07, 0x6e, + 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x6e, 0x6f, + 0x64, 0x65, 0x49, 0x64, 0x22, 0xb9, 0x02, 0x0a, 0x10, 0x41, 0x64, 0x64, 0x42, 0x79, 0x50, 0x61, + 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2f, 0x0a, 0x04, 0x62, 0x6f, 0x64, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x41, + 0x64, 0x64, 0x42, 0x79, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, + 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x2d, 0x0a, 0x09, 0x73, 0x69, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, + 0x74, 0x72, 0x65, 0x65, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, + 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0xc4, 0x01, 0x0a, 0x04, 0x42, 0x6f, + 0x64, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, + 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x69, 0x64, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x72, 0x65, 0x65, 0x49, 0x64, 0x12, 0x25, + 0x0a, 0x0e, 0x70, 0x61, 0x74, 0x68, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x61, 0x74, 0x68, 0x41, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x04, 0x20, + 0x03, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x22, 0x0a, 0x04, 0x6d, 0x65, 0x74, + 0x61, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x4b, + 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x21, 0x0a, + 0x0c, 0x62, 0x65, 0x61, 0x72, 0x65, 0x72, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x62, 0x65, 0x61, 0x72, 0x65, 0x72, 0x54, 0x6f, 0x6b, 0x65, 0x6e, + 0x22, 0xaf, 0x01, 0x0a, 0x11, 0x41, 0x64, 0x64, 0x42, 0x79, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x41, 0x64, 0x64, 0x42, + 0x79, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, + 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x2d, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x72, + 0x65, 0x65, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x39, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, + 0x14, 0x0a, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x04, 0x52, 0x05, + 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, + 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, + 0x49, 0x64, 0x22, 0xec, 0x01, 0x0a, 0x0d, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x2c, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, + 0x64, 0x79, 0x12, 0x2d, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x53, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x1a, 0x7e, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, + 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, + 0x74, 0x72, 0x65, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, + 0x72, 0x65, 0x65, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x12, 0x21, + 0x0a, 0x0c, 0x62, 0x65, 0x61, 0x72, 0x65, 0x72, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x62, 0x65, 0x61, 0x72, 0x65, 0x72, 0x54, 0x6f, 0x6b, 0x65, + 0x6e, 0x22, 0x76, 0x0a, 0x0e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x19, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, + 0x64, 0x79, 0x12, 0x2d, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x53, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0xaa, 0x02, 0x0a, 0x0b, 0x4d, 0x6f, + 0x76, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2a, 0x0a, 0x04, 0x62, 0x6f, 0x64, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x4d, + 0x6f, 0x76, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, + 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x2d, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, + 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x1a, 0xbf, 0x01, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x21, 0x0a, + 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x64, + 0x12, 0x17, 0x0a, 0x07, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x06, 0x74, 0x72, 0x65, 0x65, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x72, + 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x70, 0x61, + 0x72, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, + 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x12, + 0x22, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, + 0x74, 0x72, 0x65, 0x65, 0x2e, 0x4b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x04, 0x6d, + 0x65, 0x74, 0x61, 0x12, 0x21, 0x0a, 0x0c, 0x62, 0x65, 0x61, 0x72, 0x65, 0x72, 0x5f, 0x74, 0x6f, + 0x6b, 0x65, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x62, 0x65, 0x61, 0x72, 0x65, + 0x72, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x72, 0x0a, 0x0c, 0x4d, 0x6f, 0x76, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2b, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x4d, 0x6f, 0x76, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, + 0x6f, 0x64, 0x79, 0x12, 0x2d, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x53, 0x69, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0x85, 0x03, 0x0a, 0x14, 0x47, + 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x42, 0x79, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x33, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1f, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, + 0x42, 0x79, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, + 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x2d, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x72, + 0x65, 0x65, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x88, 0x02, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, + 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, + 0x72, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x72, 0x65, 0x65, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, + 0x70, 0x61, 0x74, 0x68, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x61, 0x74, 0x68, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x04, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x1e, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x6c, 0x61, 0x74, 0x65, 0x73, + 0x74, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x6c, 0x61, + 0x74, 0x65, 0x73, 0x74, 0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x25, 0x0a, 0x0e, 0x61, 0x6c, 0x6c, 0x5f, + 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x0d, 0x61, 0x6c, 0x6c, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, + 0x21, 0x0a, 0x0c, 0x62, 0x65, 0x61, 0x72, 0x65, 0x72, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, + 0x08, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x62, 0x65, 0x61, 0x72, 0x65, 0x72, 0x54, 0x6f, 0x6b, + 0x65, 0x6e, 0x22, 0xbc, 0x02, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x42, 0x79, + 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x04, + 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x74, 0x72, 0x65, + 0x65, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x42, 0x79, 0x50, 0x61, 0x74, 0x68, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, + 0x64, 0x79, 0x12, 0x2d, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x53, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x1a, 0x7e, 0x0a, 0x04, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x17, 0x0a, 0x07, 0x6e, 0x6f, 0x64, + 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x6e, 0x6f, 0x64, 0x65, + 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, + 0x12, 0x22, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, + 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x4b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x04, + 0x6d, 0x65, 0x74, 0x61, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x69, + 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x49, + 0x64, 0x1a, 0x3e, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x36, 0x0a, 0x05, 0x6e, 0x6f, 0x64, + 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, + 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x42, 0x79, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x05, 0x6e, 0x6f, 0x64, 0x65, + 0x73, 0x22, 0xbf, 0x03, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x54, 0x72, 0x65, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x30, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x47, 0x65, 0x74, + 0x53, 0x75, 0x62, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, + 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x2d, 0x0a, 0x09, 0x73, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, + 0x72, 0x65, 0x65, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0xc8, 0x02, 0x0a, 0x04, 0x42, 0x6f, 0x64, + 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, + 0x65, 0x72, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x69, 0x64, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x72, 0x65, 0x65, 0x49, 0x64, 0x12, 0x17, 0x0a, + 0x07, 0x72, 0x6f, 0x6f, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, + 0x72, 0x6f, 0x6f, 0x74, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x64, 0x65, 0x70, 0x74, 0x68, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x64, 0x65, 0x70, 0x74, 0x68, 0x12, 0x21, 0x0a, 0x0c, + 0x62, 0x65, 0x61, 0x72, 0x65, 0x72, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x0b, 0x62, 0x65, 0x61, 0x72, 0x65, 0x72, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, + 0x3d, 0x0a, 0x08, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x5f, 0x62, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x22, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x54, + 0x72, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x2e, + 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x07, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x42, 0x79, 0x1a, 0x73, + 0x0a, 0x05, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x4a, 0x0a, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2c, 0x2e, 0x74, 0x72, 0x65, + 0x65, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x2e, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x2e, 0x44, + 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x22, 0x1e, 0x0a, 0x09, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x6f, 0x6e, 0x65, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x41, 0x73, + 0x63, 0x10, 0x01, 0x22, 0xf6, 0x01, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x54, 0x72, + 0x65, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x31, 0x0a, 0x04, 0x62, 0x6f, + 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, + 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x2d, 0x0a, + 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x0f, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x7e, 0x0a, 0x04, + 0x42, 0x6f, 0x64, 0x79, 0x12, 0x17, 0x0a, 0x07, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x12, 0x1b, 0x0a, + 0x09, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, + 0x52, 0x08, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x74, + 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x22, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, + 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x4b, 0x65, + 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x22, 0x9b, 0x01, 0x0a, + 0x0f, 0x54, 0x72, 0x65, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x2e, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, + 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, + 0x12, 0x2d, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, + 0x29, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x61, + 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x63, + 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x22, 0x8c, 0x01, 0x0a, 0x10, 0x54, + 0x72, 0x65, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x2f, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, + 0x74, 0x72, 0x65, 0x65, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, + 0x12, 0x2d, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, + 0x18, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x69, 0x64, 0x73, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x03, 0x69, 0x64, 0x73, 0x22, 0xdb, 0x01, 0x0a, 0x0c, 0x41, 0x70, + 0x70, 0x6c, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2b, 0x0a, 0x04, 0x62, 0x6f, + 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, + 0x41, 0x70, 0x70, 0x6c, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, + 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x2d, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x72, 0x65, + 0x65, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x6f, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x21, + 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, + 0x64, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x06, 0x74, 0x72, 0x65, 0x65, 0x49, 0x64, 0x12, 0x2b, 0x0a, 0x09, 0x6f, 0x70, + 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, + 0x74, 0x72, 0x65, 0x65, 0x2e, 0x4c, 0x6f, 0x67, 0x4d, 0x6f, 0x76, 0x65, 0x52, 0x09, 0x6f, 0x70, + 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x74, 0x0a, 0x0d, 0x41, 0x70, 0x70, 0x6c, 0x79, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x41, 0x70, + 0x70, 0x6c, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, + 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x2d, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x72, 0x65, 0x65, + 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0xe2, 0x01, + 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x4f, 0x70, 0x4c, 0x6f, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1a, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x70, 0x4c, 0x6f, 0x67, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, + 0x79, 0x12, 0x2d, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x53, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x1a, 0x70, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, + 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, + 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x74, + 0x72, 0x65, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x72, + 0x65, 0x65, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x14, 0x0a, 0x05, + 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x63, 0x6f, 0x75, + 0x6e, 0x74, 0x22, 0xa7, 0x01, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x4f, 0x70, 0x4c, 0x6f, 0x67, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x47, 0x65, 0x74, + 0x4f, 0x70, 0x4c, 0x6f, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, + 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x2d, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x72, + 0x65, 0x65, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x33, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, + 0x2b, 0x0a, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x4c, 0x6f, 0x67, 0x4d, 0x6f, 0x76, + 0x65, 0x52, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x80, 0x01, 0x0a, + 0x13, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x32, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, + 0x63, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, + 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x2d, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x72, + 0x65, 0x65, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, + 0x7e, 0x0a, 0x12, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x31, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, + 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, + 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x2d, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x72, + 0x65, 0x65, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x32, + 0xd6, 0x04, 0x0a, 0x0b, 0x54, 0x72, 0x65, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, + 0x2a, 0x0a, 0x03, 0x41, 0x64, 0x64, 0x12, 0x10, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x41, 0x64, + 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, + 0x41, 0x64, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3c, 0x0a, 0x09, 0x41, + 0x64, 0x64, 0x42, 0x79, 0x50, 0x61, 0x74, 0x68, 0x12, 0x16, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, + 0x41, 0x64, 0x64, 0x42, 0x79, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x17, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x41, 0x64, 0x64, 0x42, 0x79, 0x50, 0x61, 0x74, + 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x33, 0x0a, 0x06, 0x52, 0x65, 0x6d, + 0x6f, 0x76, 0x65, 0x12, 0x13, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, + 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2d, + 0x0a, 0x04, 0x4d, 0x6f, 0x76, 0x65, 0x12, 0x11, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x4d, 0x6f, + 0x76, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x74, 0x72, 0x65, 0x65, + 0x2e, 0x4d, 0x6f, 0x76, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x48, 0x0a, + 0x0d, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x42, 0x79, 0x50, 0x61, 0x74, 0x68, 0x12, 0x1a, + 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x42, 0x79, 0x50, + 0x61, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x74, 0x72, 0x65, + 0x65, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x42, 0x79, 0x50, 0x61, 0x74, 0x68, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x53, 0x75, + 0x62, 0x54, 0x72, 0x65, 0x65, 0x12, 0x17, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x47, 0x65, 0x74, + 0x53, 0x75, 0x62, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, + 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x54, 0x72, 0x65, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x39, 0x0a, 0x08, 0x54, 0x72, + 0x65, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x15, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x54, 0x72, + 0x65, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, + 0x74, 0x72, 0x65, 0x65, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x05, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x12, 0x12, + 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x4f, 0x70, + 0x4c, 0x6f, 0x67, 0x12, 0x15, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x70, + 0x4c, 0x6f, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x74, 0x72, 0x65, + 0x65, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x70, 0x4c, 0x6f, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x30, 0x01, 0x12, 0x42, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x63, 0x68, + 0x65, 0x63, 0x6b, 0x12, 0x18, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, + 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, + 0x74, 0x72, 0x65, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x3e, 0x5a, 0x3c, 0x67, 0x69, 0x74, 0x2e, + 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, 0x75, + 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x4c, 0x61, 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, + 0x73, 0x2d, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x73, 0x2f, 0x74, 0x72, 0x65, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_pkg_services_tree_service_proto_rawDescOnce sync.Once + file_pkg_services_tree_service_proto_rawDescData = file_pkg_services_tree_service_proto_rawDesc +) + +func file_pkg_services_tree_service_proto_rawDescGZIP() []byte { + file_pkg_services_tree_service_proto_rawDescOnce.Do(func() { + file_pkg_services_tree_service_proto_rawDescData = protoimpl.X.CompressGZIP(file_pkg_services_tree_service_proto_rawDescData) + }) + return file_pkg_services_tree_service_proto_rawDescData +} + +var file_pkg_services_tree_service_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_pkg_services_tree_service_proto_msgTypes = make([]protoimpl.MessageInfo, 42) +var file_pkg_services_tree_service_proto_goTypes = []interface{}{ + (GetSubTreeRequest_Body_Order_Direction)(0), // 0: tree.GetSubTreeRequest.Body.Order.Direction + (*AddRequest)(nil), // 1: tree.AddRequest + (*AddResponse)(nil), // 2: tree.AddResponse + (*AddByPathRequest)(nil), // 3: tree.AddByPathRequest + (*AddByPathResponse)(nil), // 4: tree.AddByPathResponse + (*RemoveRequest)(nil), // 5: tree.RemoveRequest + (*RemoveResponse)(nil), // 6: tree.RemoveResponse + (*MoveRequest)(nil), // 7: tree.MoveRequest + (*MoveResponse)(nil), // 8: tree.MoveResponse + (*GetNodeByPathRequest)(nil), // 9: tree.GetNodeByPathRequest + (*GetNodeByPathResponse)(nil), // 10: tree.GetNodeByPathResponse + (*GetSubTreeRequest)(nil), // 11: tree.GetSubTreeRequest + (*GetSubTreeResponse)(nil), // 12: tree.GetSubTreeResponse + (*TreeListRequest)(nil), // 13: tree.TreeListRequest + (*TreeListResponse)(nil), // 14: tree.TreeListResponse + (*ApplyRequest)(nil), // 15: tree.ApplyRequest + (*ApplyResponse)(nil), // 16: tree.ApplyResponse + (*GetOpLogRequest)(nil), // 17: tree.GetOpLogRequest + (*GetOpLogResponse)(nil), // 18: tree.GetOpLogResponse + (*HealthcheckResponse)(nil), // 19: tree.HealthcheckResponse + (*HealthcheckRequest)(nil), // 20: tree.HealthcheckRequest + (*AddRequest_Body)(nil), // 21: tree.AddRequest.Body + (*AddResponse_Body)(nil), // 22: tree.AddResponse.Body + (*AddByPathRequest_Body)(nil), // 23: tree.AddByPathRequest.Body + (*AddByPathResponse_Body)(nil), // 24: tree.AddByPathResponse.Body + (*RemoveRequest_Body)(nil), // 25: tree.RemoveRequest.Body + (*RemoveResponse_Body)(nil), // 26: tree.RemoveResponse.Body + (*MoveRequest_Body)(nil), // 27: tree.MoveRequest.Body + (*MoveResponse_Body)(nil), // 28: tree.MoveResponse.Body + (*GetNodeByPathRequest_Body)(nil), // 29: tree.GetNodeByPathRequest.Body + (*GetNodeByPathResponse_Info)(nil), // 30: tree.GetNodeByPathResponse.Info + (*GetNodeByPathResponse_Body)(nil), // 31: tree.GetNodeByPathResponse.Body + (*GetSubTreeRequest_Body)(nil), // 32: tree.GetSubTreeRequest.Body + (*GetSubTreeRequest_Body_Order)(nil), // 33: tree.GetSubTreeRequest.Body.Order + (*GetSubTreeResponse_Body)(nil), // 34: tree.GetSubTreeResponse.Body + (*TreeListRequest_Body)(nil), // 35: tree.TreeListRequest.Body + (*TreeListResponse_Body)(nil), // 36: tree.TreeListResponse.Body + (*ApplyRequest_Body)(nil), // 37: tree.ApplyRequest.Body + (*ApplyResponse_Body)(nil), // 38: tree.ApplyResponse.Body + (*GetOpLogRequest_Body)(nil), // 39: tree.GetOpLogRequest.Body + (*GetOpLogResponse_Body)(nil), // 40: tree.GetOpLogResponse.Body + (*HealthcheckResponse_Body)(nil), // 41: tree.HealthcheckResponse.Body + (*HealthcheckRequest_Body)(nil), // 42: tree.HealthcheckRequest.Body + (*Signature)(nil), // 43: tree.Signature + (*KeyValue)(nil), // 44: tree.KeyValue + (*LogMove)(nil), // 45: tree.LogMove +} +var file_pkg_services_tree_service_proto_depIdxs = []int32{ + 21, // 0: tree.AddRequest.body:type_name -> tree.AddRequest.Body + 43, // 1: tree.AddRequest.signature:type_name -> tree.Signature + 22, // 2: tree.AddResponse.body:type_name -> tree.AddResponse.Body + 43, // 3: tree.AddResponse.signature:type_name -> tree.Signature + 23, // 4: tree.AddByPathRequest.body:type_name -> tree.AddByPathRequest.Body + 43, // 5: tree.AddByPathRequest.signature:type_name -> tree.Signature + 24, // 6: tree.AddByPathResponse.body:type_name -> tree.AddByPathResponse.Body + 43, // 7: tree.AddByPathResponse.signature:type_name -> tree.Signature + 25, // 8: tree.RemoveRequest.body:type_name -> tree.RemoveRequest.Body + 43, // 9: tree.RemoveRequest.signature:type_name -> tree.Signature + 26, // 10: tree.RemoveResponse.body:type_name -> tree.RemoveResponse.Body + 43, // 11: tree.RemoveResponse.signature:type_name -> tree.Signature + 27, // 12: tree.MoveRequest.body:type_name -> tree.MoveRequest.Body + 43, // 13: tree.MoveRequest.signature:type_name -> tree.Signature + 28, // 14: tree.MoveResponse.body:type_name -> tree.MoveResponse.Body + 43, // 15: tree.MoveResponse.signature:type_name -> tree.Signature + 29, // 16: tree.GetNodeByPathRequest.body:type_name -> tree.GetNodeByPathRequest.Body + 43, // 17: tree.GetNodeByPathRequest.signature:type_name -> tree.Signature + 31, // 18: tree.GetNodeByPathResponse.body:type_name -> tree.GetNodeByPathResponse.Body + 43, // 19: tree.GetNodeByPathResponse.signature:type_name -> tree.Signature + 32, // 20: tree.GetSubTreeRequest.body:type_name -> tree.GetSubTreeRequest.Body + 43, // 21: tree.GetSubTreeRequest.signature:type_name -> tree.Signature + 34, // 22: tree.GetSubTreeResponse.body:type_name -> tree.GetSubTreeResponse.Body + 43, // 23: tree.GetSubTreeResponse.signature:type_name -> tree.Signature + 35, // 24: tree.TreeListRequest.body:type_name -> tree.TreeListRequest.Body + 43, // 25: tree.TreeListRequest.signature:type_name -> tree.Signature + 36, // 26: tree.TreeListResponse.body:type_name -> tree.TreeListResponse.Body + 43, // 27: tree.TreeListResponse.signature:type_name -> tree.Signature + 37, // 28: tree.ApplyRequest.body:type_name -> tree.ApplyRequest.Body + 43, // 29: tree.ApplyRequest.signature:type_name -> tree.Signature + 38, // 30: tree.ApplyResponse.body:type_name -> tree.ApplyResponse.Body + 43, // 31: tree.ApplyResponse.signature:type_name -> tree.Signature + 39, // 32: tree.GetOpLogRequest.body:type_name -> tree.GetOpLogRequest.Body + 43, // 33: tree.GetOpLogRequest.signature:type_name -> tree.Signature + 40, // 34: tree.GetOpLogResponse.body:type_name -> tree.GetOpLogResponse.Body + 43, // 35: tree.GetOpLogResponse.signature:type_name -> tree.Signature + 41, // 36: tree.HealthcheckResponse.body:type_name -> tree.HealthcheckResponse.Body + 43, // 37: tree.HealthcheckResponse.signature:type_name -> tree.Signature + 42, // 38: tree.HealthcheckRequest.body:type_name -> tree.HealthcheckRequest.Body + 43, // 39: tree.HealthcheckRequest.signature:type_name -> tree.Signature + 44, // 40: tree.AddRequest.Body.meta:type_name -> tree.KeyValue + 44, // 41: tree.AddByPathRequest.Body.meta:type_name -> tree.KeyValue + 44, // 42: tree.MoveRequest.Body.meta:type_name -> tree.KeyValue + 44, // 43: tree.GetNodeByPathResponse.Info.meta:type_name -> tree.KeyValue + 30, // 44: tree.GetNodeByPathResponse.Body.nodes:type_name -> tree.GetNodeByPathResponse.Info + 33, // 45: tree.GetSubTreeRequest.Body.order_by:type_name -> tree.GetSubTreeRequest.Body.Order + 0, // 46: tree.GetSubTreeRequest.Body.Order.direction:type_name -> tree.GetSubTreeRequest.Body.Order.Direction + 44, // 47: tree.GetSubTreeResponse.Body.meta:type_name -> tree.KeyValue + 45, // 48: tree.ApplyRequest.Body.operation:type_name -> tree.LogMove + 45, // 49: tree.GetOpLogResponse.Body.operation:type_name -> tree.LogMove + 1, // 50: tree.TreeService.Add:input_type -> tree.AddRequest + 3, // 51: tree.TreeService.AddByPath:input_type -> tree.AddByPathRequest + 5, // 52: tree.TreeService.Remove:input_type -> tree.RemoveRequest + 7, // 53: tree.TreeService.Move:input_type -> tree.MoveRequest + 9, // 54: tree.TreeService.GetNodeByPath:input_type -> tree.GetNodeByPathRequest + 11, // 55: tree.TreeService.GetSubTree:input_type -> tree.GetSubTreeRequest + 13, // 56: tree.TreeService.TreeList:input_type -> tree.TreeListRequest + 15, // 57: tree.TreeService.Apply:input_type -> tree.ApplyRequest + 17, // 58: tree.TreeService.GetOpLog:input_type -> tree.GetOpLogRequest + 20, // 59: tree.TreeService.Healthcheck:input_type -> tree.HealthcheckRequest + 2, // 60: tree.TreeService.Add:output_type -> tree.AddResponse + 4, // 61: tree.TreeService.AddByPath:output_type -> tree.AddByPathResponse + 6, // 62: tree.TreeService.Remove:output_type -> tree.RemoveResponse + 8, // 63: tree.TreeService.Move:output_type -> tree.MoveResponse + 10, // 64: tree.TreeService.GetNodeByPath:output_type -> tree.GetNodeByPathResponse + 12, // 65: tree.TreeService.GetSubTree:output_type -> tree.GetSubTreeResponse + 14, // 66: tree.TreeService.TreeList:output_type -> tree.TreeListResponse + 16, // 67: tree.TreeService.Apply:output_type -> tree.ApplyResponse + 18, // 68: tree.TreeService.GetOpLog:output_type -> tree.GetOpLogResponse + 19, // 69: tree.TreeService.Healthcheck:output_type -> tree.HealthcheckResponse + 60, // [60:70] is the sub-list for method output_type + 50, // [50:60] is the sub-list for method input_type + 50, // [50:50] is the sub-list for extension type_name + 50, // [50:50] is the sub-list for extension extendee + 0, // [0:50] is the sub-list for field type_name +} + +func init() { file_pkg_services_tree_service_proto_init() } +func file_pkg_services_tree_service_proto_init() { + if File_pkg_services_tree_service_proto != nil { + return + } + file_pkg_services_tree_types_proto_init() + if !protoimpl.UnsafeEnabled { + file_pkg_services_tree_service_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AddRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_tree_service_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AddResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_tree_service_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AddByPathRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_tree_service_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AddByPathResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_tree_service_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RemoveRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_tree_service_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RemoveResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_tree_service_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MoveRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_tree_service_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MoveResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_tree_service_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetNodeByPathRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_tree_service_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetNodeByPathResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_tree_service_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetSubTreeRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_tree_service_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetSubTreeResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_tree_service_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TreeListRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_tree_service_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TreeListResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_tree_service_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ApplyRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_tree_service_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ApplyResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_tree_service_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetOpLogRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_tree_service_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetOpLogResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_tree_service_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*HealthcheckResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_tree_service_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*HealthcheckRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_tree_service_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AddRequest_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_tree_service_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AddResponse_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_tree_service_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AddByPathRequest_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_tree_service_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AddByPathResponse_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_tree_service_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RemoveRequest_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_tree_service_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RemoveResponse_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_tree_service_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MoveRequest_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_tree_service_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MoveResponse_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_tree_service_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetNodeByPathRequest_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_tree_service_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetNodeByPathResponse_Info); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_tree_service_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetNodeByPathResponse_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_tree_service_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetSubTreeRequest_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_tree_service_proto_msgTypes[32].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetSubTreeRequest_Body_Order); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_tree_service_proto_msgTypes[33].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetSubTreeResponse_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_tree_service_proto_msgTypes[34].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TreeListRequest_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_tree_service_proto_msgTypes[35].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TreeListResponse_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_tree_service_proto_msgTypes[36].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ApplyRequest_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_tree_service_proto_msgTypes[37].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ApplyResponse_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_tree_service_proto_msgTypes[38].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetOpLogRequest_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_tree_service_proto_msgTypes[39].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetOpLogResponse_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_tree_service_proto_msgTypes[40].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*HealthcheckResponse_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_tree_service_proto_msgTypes[41].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*HealthcheckRequest_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_pkg_services_tree_service_proto_rawDesc, + NumEnums: 1, + NumMessages: 42, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_pkg_services_tree_service_proto_goTypes, + DependencyIndexes: file_pkg_services_tree_service_proto_depIdxs, + EnumInfos: file_pkg_services_tree_service_proto_enumTypes, + MessageInfos: file_pkg_services_tree_service_proto_msgTypes, + }.Build() + File_pkg_services_tree_service_proto = out.File + file_pkg_services_tree_service_proto_rawDesc = nil + file_pkg_services_tree_service_proto_goTypes = nil + file_pkg_services_tree_service_proto_depIdxs = nil +} diff --git a/pkg/sdk/pool/tree/service/service_grpc.pb.go b/pkg/sdk/pool/tree/service/service_grpc.pb.go new file mode 100644 index 000000000..2c0828951 --- /dev/null +++ b/pkg/sdk/pool/tree/service/service_grpc.pb.go @@ -0,0 +1,520 @@ +//* +// Service for working with CRDT tree. + +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.3.0 +// - protoc v3.21.9 +// source: pkg/services/tree/service.proto + +package tree + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +const ( + TreeService_Add_FullMethodName = "/tree.TreeService/Add" + TreeService_AddByPath_FullMethodName = "/tree.TreeService/AddByPath" + TreeService_Remove_FullMethodName = "/tree.TreeService/Remove" + TreeService_Move_FullMethodName = "/tree.TreeService/Move" + TreeService_GetNodeByPath_FullMethodName = "/tree.TreeService/GetNodeByPath" + TreeService_GetSubTree_FullMethodName = "/tree.TreeService/GetSubTree" + TreeService_TreeList_FullMethodName = "/tree.TreeService/TreeList" + TreeService_Apply_FullMethodName = "/tree.TreeService/Apply" + TreeService_GetOpLog_FullMethodName = "/tree.TreeService/GetOpLog" + TreeService_Healthcheck_FullMethodName = "/tree.TreeService/Healthcheck" +) + +// TreeServiceClient is the client API for TreeService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type TreeServiceClient interface { + // Add adds new node to the tree. Invoked by a client. + Add(ctx context.Context, in *AddRequest, opts ...grpc.CallOption) (*AddResponse, error) + // AddByPath adds new node to the tree by path. Invoked by a client. + AddByPath(ctx context.Context, in *AddByPathRequest, opts ...grpc.CallOption) (*AddByPathResponse, error) + // Remove removes node from the tree. Invoked by a client. + Remove(ctx context.Context, in *RemoveRequest, opts ...grpc.CallOption) (*RemoveResponse, error) + // Move moves node from one parent to another. Invoked by a client. + Move(ctx context.Context, in *MoveRequest, opts ...grpc.CallOption) (*MoveResponse, error) + // GetNodeByPath returns list of IDs corresponding to a specific filepath. + GetNodeByPath(ctx context.Context, in *GetNodeByPathRequest, opts ...grpc.CallOption) (*GetNodeByPathResponse, error) + // GetSubTree returns tree corresponding to a specific node. + GetSubTree(ctx context.Context, in *GetSubTreeRequest, opts ...grpc.CallOption) (TreeService_GetSubTreeClient, error) + // TreeList return list of the existing trees in the container. + TreeList(ctx context.Context, in *TreeListRequest, opts ...grpc.CallOption) (*TreeListResponse, error) + // Apply pushes log operation from another node to the current. + // The request must be signed by a container node. + Apply(ctx context.Context, in *ApplyRequest, opts ...grpc.CallOption) (*ApplyResponse, error) + // GetOpLog returns a stream of logged operations starting from some height. + GetOpLog(ctx context.Context, in *GetOpLogRequest, opts ...grpc.CallOption) (TreeService_GetOpLogClient, error) + // Healthcheck is a dummy rpc to check service availability + Healthcheck(ctx context.Context, in *HealthcheckRequest, opts ...grpc.CallOption) (*HealthcheckResponse, error) +} + +type treeServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewTreeServiceClient(cc grpc.ClientConnInterface) TreeServiceClient { + return &treeServiceClient{cc} +} + +func (c *treeServiceClient) Add(ctx context.Context, in *AddRequest, opts ...grpc.CallOption) (*AddResponse, error) { + out := new(AddResponse) + err := c.cc.Invoke(ctx, TreeService_Add_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *treeServiceClient) AddByPath(ctx context.Context, in *AddByPathRequest, opts ...grpc.CallOption) (*AddByPathResponse, error) { + out := new(AddByPathResponse) + err := c.cc.Invoke(ctx, TreeService_AddByPath_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *treeServiceClient) Remove(ctx context.Context, in *RemoveRequest, opts ...grpc.CallOption) (*RemoveResponse, error) { + out := new(RemoveResponse) + err := c.cc.Invoke(ctx, TreeService_Remove_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *treeServiceClient) Move(ctx context.Context, in *MoveRequest, opts ...grpc.CallOption) (*MoveResponse, error) { + out := new(MoveResponse) + err := c.cc.Invoke(ctx, TreeService_Move_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *treeServiceClient) GetNodeByPath(ctx context.Context, in *GetNodeByPathRequest, opts ...grpc.CallOption) (*GetNodeByPathResponse, error) { + out := new(GetNodeByPathResponse) + err := c.cc.Invoke(ctx, TreeService_GetNodeByPath_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *treeServiceClient) GetSubTree(ctx context.Context, in *GetSubTreeRequest, opts ...grpc.CallOption) (TreeService_GetSubTreeClient, error) { + stream, err := c.cc.NewStream(ctx, &TreeService_ServiceDesc.Streams[0], TreeService_GetSubTree_FullMethodName, opts...) + if err != nil { + return nil, err + } + x := &treeServiceGetSubTreeClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type TreeService_GetSubTreeClient interface { + Recv() (*GetSubTreeResponse, error) + grpc.ClientStream +} + +type treeServiceGetSubTreeClient struct { + grpc.ClientStream +} + +func (x *treeServiceGetSubTreeClient) Recv() (*GetSubTreeResponse, error) { + m := new(GetSubTreeResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *treeServiceClient) TreeList(ctx context.Context, in *TreeListRequest, opts ...grpc.CallOption) (*TreeListResponse, error) { + out := new(TreeListResponse) + err := c.cc.Invoke(ctx, TreeService_TreeList_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *treeServiceClient) Apply(ctx context.Context, in *ApplyRequest, opts ...grpc.CallOption) (*ApplyResponse, error) { + out := new(ApplyResponse) + err := c.cc.Invoke(ctx, TreeService_Apply_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *treeServiceClient) GetOpLog(ctx context.Context, in *GetOpLogRequest, opts ...grpc.CallOption) (TreeService_GetOpLogClient, error) { + stream, err := c.cc.NewStream(ctx, &TreeService_ServiceDesc.Streams[1], TreeService_GetOpLog_FullMethodName, opts...) + if err != nil { + return nil, err + } + x := &treeServiceGetOpLogClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type TreeService_GetOpLogClient interface { + Recv() (*GetOpLogResponse, error) + grpc.ClientStream +} + +type treeServiceGetOpLogClient struct { + grpc.ClientStream +} + +func (x *treeServiceGetOpLogClient) Recv() (*GetOpLogResponse, error) { + m := new(GetOpLogResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *treeServiceClient) Healthcheck(ctx context.Context, in *HealthcheckRequest, opts ...grpc.CallOption) (*HealthcheckResponse, error) { + out := new(HealthcheckResponse) + err := c.cc.Invoke(ctx, TreeService_Healthcheck_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// TreeServiceServer is the server API for TreeService service. +// All implementations should embed UnimplementedTreeServiceServer +// for forward compatibility +type TreeServiceServer interface { + // Add adds new node to the tree. Invoked by a client. + Add(context.Context, *AddRequest) (*AddResponse, error) + // AddByPath adds new node to the tree by path. Invoked by a client. + AddByPath(context.Context, *AddByPathRequest) (*AddByPathResponse, error) + // Remove removes node from the tree. Invoked by a client. + Remove(context.Context, *RemoveRequest) (*RemoveResponse, error) + // Move moves node from one parent to another. Invoked by a client. + Move(context.Context, *MoveRequest) (*MoveResponse, error) + // GetNodeByPath returns list of IDs corresponding to a specific filepath. + GetNodeByPath(context.Context, *GetNodeByPathRequest) (*GetNodeByPathResponse, error) + // GetSubTree returns tree corresponding to a specific node. + GetSubTree(*GetSubTreeRequest, TreeService_GetSubTreeServer) error + // TreeList return list of the existing trees in the container. + TreeList(context.Context, *TreeListRequest) (*TreeListResponse, error) + // Apply pushes log operation from another node to the current. + // The request must be signed by a container node. + Apply(context.Context, *ApplyRequest) (*ApplyResponse, error) + // GetOpLog returns a stream of logged operations starting from some height. + GetOpLog(*GetOpLogRequest, TreeService_GetOpLogServer) error + // Healthcheck is a dummy rpc to check service availability + Healthcheck(context.Context, *HealthcheckRequest) (*HealthcheckResponse, error) +} + +// UnimplementedTreeServiceServer should be embedded to have forward compatible implementations. +type UnimplementedTreeServiceServer struct { +} + +func (UnimplementedTreeServiceServer) Add(context.Context, *AddRequest) (*AddResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Add not implemented") +} +func (UnimplementedTreeServiceServer) AddByPath(context.Context, *AddByPathRequest) (*AddByPathResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method AddByPath not implemented") +} +func (UnimplementedTreeServiceServer) Remove(context.Context, *RemoveRequest) (*RemoveResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Remove not implemented") +} +func (UnimplementedTreeServiceServer) Move(context.Context, *MoveRequest) (*MoveResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Move not implemented") +} +func (UnimplementedTreeServiceServer) GetNodeByPath(context.Context, *GetNodeByPathRequest) (*GetNodeByPathResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetNodeByPath not implemented") +} +func (UnimplementedTreeServiceServer) GetSubTree(*GetSubTreeRequest, TreeService_GetSubTreeServer) error { + return status.Errorf(codes.Unimplemented, "method GetSubTree not implemented") +} +func (UnimplementedTreeServiceServer) TreeList(context.Context, *TreeListRequest) (*TreeListResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method TreeList not implemented") +} +func (UnimplementedTreeServiceServer) Apply(context.Context, *ApplyRequest) (*ApplyResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Apply not implemented") +} +func (UnimplementedTreeServiceServer) GetOpLog(*GetOpLogRequest, TreeService_GetOpLogServer) error { + return status.Errorf(codes.Unimplemented, "method GetOpLog not implemented") +} +func (UnimplementedTreeServiceServer) Healthcheck(context.Context, *HealthcheckRequest) (*HealthcheckResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Healthcheck not implemented") +} + +// UnsafeTreeServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to TreeServiceServer will +// result in compilation errors. +type UnsafeTreeServiceServer interface { + mustEmbedUnimplementedTreeServiceServer() +} + +func RegisterTreeServiceServer(s grpc.ServiceRegistrar, srv TreeServiceServer) { + s.RegisterService(&TreeService_ServiceDesc, srv) +} + +func _TreeService_Add_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(AddRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(TreeServiceServer).Add(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: TreeService_Add_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(TreeServiceServer).Add(ctx, req.(*AddRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _TreeService_AddByPath_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(AddByPathRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(TreeServiceServer).AddByPath(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: TreeService_AddByPath_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(TreeServiceServer).AddByPath(ctx, req.(*AddByPathRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _TreeService_Remove_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RemoveRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(TreeServiceServer).Remove(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: TreeService_Remove_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(TreeServiceServer).Remove(ctx, req.(*RemoveRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _TreeService_Move_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MoveRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(TreeServiceServer).Move(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: TreeService_Move_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(TreeServiceServer).Move(ctx, req.(*MoveRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _TreeService_GetNodeByPath_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetNodeByPathRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(TreeServiceServer).GetNodeByPath(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: TreeService_GetNodeByPath_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(TreeServiceServer).GetNodeByPath(ctx, req.(*GetNodeByPathRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _TreeService_GetSubTree_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(GetSubTreeRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(TreeServiceServer).GetSubTree(m, &treeServiceGetSubTreeServer{stream}) +} + +type TreeService_GetSubTreeServer interface { + Send(*GetSubTreeResponse) error + grpc.ServerStream +} + +type treeServiceGetSubTreeServer struct { + grpc.ServerStream +} + +func (x *treeServiceGetSubTreeServer) Send(m *GetSubTreeResponse) error { + return x.ServerStream.SendMsg(m) +} + +func _TreeService_TreeList_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(TreeListRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(TreeServiceServer).TreeList(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: TreeService_TreeList_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(TreeServiceServer).TreeList(ctx, req.(*TreeListRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _TreeService_Apply_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ApplyRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(TreeServiceServer).Apply(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: TreeService_Apply_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(TreeServiceServer).Apply(ctx, req.(*ApplyRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _TreeService_GetOpLog_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(GetOpLogRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(TreeServiceServer).GetOpLog(m, &treeServiceGetOpLogServer{stream}) +} + +type TreeService_GetOpLogServer interface { + Send(*GetOpLogResponse) error + grpc.ServerStream +} + +type treeServiceGetOpLogServer struct { + grpc.ServerStream +} + +func (x *treeServiceGetOpLogServer) Send(m *GetOpLogResponse) error { + return x.ServerStream.SendMsg(m) +} + +func _TreeService_Healthcheck_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(HealthcheckRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(TreeServiceServer).Healthcheck(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: TreeService_Healthcheck_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(TreeServiceServer).Healthcheck(ctx, req.(*HealthcheckRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// TreeService_ServiceDesc is the grpc.ServiceDesc for TreeService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var TreeService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "tree.TreeService", + HandlerType: (*TreeServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Add", + Handler: _TreeService_Add_Handler, + }, + { + MethodName: "AddByPath", + Handler: _TreeService_AddByPath_Handler, + }, + { + MethodName: "Remove", + Handler: _TreeService_Remove_Handler, + }, + { + MethodName: "Move", + Handler: _TreeService_Move_Handler, + }, + { + MethodName: "GetNodeByPath", + Handler: _TreeService_GetNodeByPath_Handler, + }, + { + MethodName: "TreeList", + Handler: _TreeService_TreeList_Handler, + }, + { + MethodName: "Apply", + Handler: _TreeService_Apply_Handler, + }, + { + MethodName: "Healthcheck", + Handler: _TreeService_Healthcheck_Handler, + }, + }, + Streams: []grpc.StreamDesc{ + { + StreamName: "GetSubTree", + Handler: _TreeService_GetSubTree_Handler, + ServerStreams: true, + }, + { + StreamName: "GetOpLog", + Handler: _TreeService_GetOpLog_Handler, + ServerStreams: true, + }, + }, + Metadata: "pkg/services/tree/service.proto", +} diff --git a/pkg/sdk/pool/tree/service/types.pb.go b/pkg/sdk/pool/tree/service/types.pb.go new file mode 100644 index 000000000..b4d6981ef --- /dev/null +++ b/pkg/sdk/pool/tree/service/types.pb.go @@ -0,0 +1,320 @@ +//* +// Auxiliary structures to use with tree service. + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.26.0 +// protoc v3.21.9 +// source: pkg/services/tree/types.proto + +package tree + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// KeyValue represents key-value pair attached to an object. +type KeyValue struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Attribute name. + Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` + // Attribute value. + Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` +} + +func (x *KeyValue) Reset() { + *x = KeyValue{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_tree_types_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *KeyValue) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*KeyValue) ProtoMessage() {} + +func (x *KeyValue) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_tree_types_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use KeyValue.ProtoReflect.Descriptor instead. +func (*KeyValue) Descriptor() ([]byte, []int) { + return file_pkg_services_tree_types_proto_rawDescGZIP(), []int{0} +} + +func (x *KeyValue) GetKey() string { + if x != nil { + return x.Key + } + return "" +} + +func (x *KeyValue) GetValue() []byte { + if x != nil { + return x.Value + } + return nil +} + +// LogMove represents log-entry for a single move operation. +type LogMove struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // ID of the parent node. + ParentId uint64 `protobuf:"varint,1,opt,name=parent_id,json=parentID,proto3" json:"parent_id,omitempty"` + // Node meta information, including operation timestamp. + Meta []byte `protobuf:"bytes,2,opt,name=meta,proto3" json:"meta,omitempty"` + // ID of the node to move. + ChildId uint64 `protobuf:"varint,3,opt,name=child_id,json=childID,proto3" json:"child_id,omitempty"` +} + +func (x *LogMove) Reset() { + *x = LogMove{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_tree_types_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LogMove) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LogMove) ProtoMessage() {} + +func (x *LogMove) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_tree_types_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LogMove.ProtoReflect.Descriptor instead. +func (*LogMove) Descriptor() ([]byte, []int) { + return file_pkg_services_tree_types_proto_rawDescGZIP(), []int{1} +} + +func (x *LogMove) GetParentId() uint64 { + if x != nil { + return x.ParentId + } + return 0 +} + +func (x *LogMove) GetMeta() []byte { + if x != nil { + return x.Meta + } + return nil +} + +func (x *LogMove) GetChildId() uint64 { + if x != nil { + return x.ChildId + } + return 0 +} + +// Signature of a message. +type Signature struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Serialized public key as defined in FrostFS API. + Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` + // Signature of a message body. + Sign []byte `protobuf:"bytes,2,opt,name=sign,json=signature,proto3" json:"sign,omitempty"` +} + +func (x *Signature) Reset() { + *x = Signature{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_tree_types_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Signature) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Signature) ProtoMessage() {} + +func (x *Signature) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_tree_types_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Signature.ProtoReflect.Descriptor instead. +func (*Signature) Descriptor() ([]byte, []int) { + return file_pkg_services_tree_types_proto_rawDescGZIP(), []int{2} +} + +func (x *Signature) GetKey() []byte { + if x != nil { + return x.Key + } + return nil +} + +func (x *Signature) GetSign() []byte { + if x != nil { + return x.Sign + } + return nil +} + +var File_pkg_services_tree_types_proto protoreflect.FileDescriptor + +var file_pkg_services_tree_types_proto_rawDesc = []byte{ + 0x0a, 0x1d, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x74, + 0x72, 0x65, 0x65, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, + 0x04, 0x74, 0x72, 0x65, 0x65, 0x22, 0x32, 0x0a, 0x08, 0x4b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, + 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x55, 0x0a, 0x07, 0x4c, 0x6f, 0x67, + 0x4d, 0x6f, 0x76, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x49, + 0x44, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x5f, 0x69, + 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x49, 0x44, + 0x22, 0x36, 0x0a, 0x09, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x10, 0x0a, + 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, + 0x17, 0x0a, 0x04, 0x73, 0x69, 0x67, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x42, 0x3e, 0x5a, 0x3c, 0x67, 0x69, 0x74, 0x2e, + 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, 0x75, + 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x4c, 0x61, 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, + 0x73, 0x2d, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x73, 0x2f, 0x74, 0x72, 0x65, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_pkg_services_tree_types_proto_rawDescOnce sync.Once + file_pkg_services_tree_types_proto_rawDescData = file_pkg_services_tree_types_proto_rawDesc +) + +func file_pkg_services_tree_types_proto_rawDescGZIP() []byte { + file_pkg_services_tree_types_proto_rawDescOnce.Do(func() { + file_pkg_services_tree_types_proto_rawDescData = protoimpl.X.CompressGZIP(file_pkg_services_tree_types_proto_rawDescData) + }) + return file_pkg_services_tree_types_proto_rawDescData +} + +var file_pkg_services_tree_types_proto_msgTypes = make([]protoimpl.MessageInfo, 3) +var file_pkg_services_tree_types_proto_goTypes = []interface{}{ + (*KeyValue)(nil), // 0: tree.KeyValue + (*LogMove)(nil), // 1: tree.LogMove + (*Signature)(nil), // 2: tree.Signature +} +var file_pkg_services_tree_types_proto_depIdxs = []int32{ + 0, // [0:0] is the sub-list for method output_type + 0, // [0:0] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_pkg_services_tree_types_proto_init() } +func file_pkg_services_tree_types_proto_init() { + if File_pkg_services_tree_types_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_pkg_services_tree_types_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*KeyValue); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_tree_types_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LogMove); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_tree_types_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Signature); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_pkg_services_tree_types_proto_rawDesc, + NumEnums: 0, + NumMessages: 3, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_pkg_services_tree_types_proto_goTypes, + DependencyIndexes: file_pkg_services_tree_types_proto_depIdxs, + MessageInfos: file_pkg_services_tree_types_proto_msgTypes, + }.Build() + File_pkg_services_tree_types_proto = out.File + file_pkg_services_tree_types_proto_rawDesc = nil + file_pkg_services_tree_types_proto_goTypes = nil + file_pkg_services_tree_types_proto_depIdxs = nil +} diff --git a/pkg/sdk/session/common.go b/pkg/sdk/session/common.go new file mode 100644 index 000000000..97d9fa5bd --- /dev/null +++ b/pkg/sdk/session/common.go @@ -0,0 +1,334 @@ +package session + +import ( + "bytes" + "crypto/ecdsa" + "errors" + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" + frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/crypto" + frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/crypto/ecdsa" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" + "github.com/google/uuid" +) + +type commonData struct { + idSet bool + id uuid.UUID + + issuerSet bool + issuer user.ID + + lifetimeSet bool + iat, nbf, exp uint64 + + authKey []byte + + sigSet bool + sig refs.Signature +} + +type contextReader func(session.TokenContext, bool) error + +// reads commonData and custom context from the session.Token message. +// If checkFieldPresence is set, returns an error on absence of any protocol-required +// field. Verifies format of any presented field according to FrostFS API V2 protocol. +// Calls contextReader if session context is set. Passes checkFieldPresence into contextReader. +func (x *commonData) readFromV2(m session.Token, checkFieldPresence bool, r contextReader) error { + var err error + + body := m.GetBody() + if checkFieldPresence && body == nil { + return errors.New("missing token body") + } + + binID := body.GetID() + if x.idSet = len(binID) > 0; x.idSet { + err = x.id.UnmarshalBinary(binID) + if err != nil { + return fmt.Errorf("invalid session ID: %w", err) + } else if ver := x.id.Version(); ver != 4 { + return fmt.Errorf("invalid session UUID version %d", ver) + } + } else if checkFieldPresence { + return errors.New("missing session ID") + } + + issuer := body.GetOwnerID() + if x.issuerSet = issuer != nil; x.issuerSet { + err = x.issuer.ReadFromV2(*issuer) + if err != nil { + return fmt.Errorf("invalid session issuer: %w", err) + } + } else if checkFieldPresence { + return errors.New("missing session issuer") + } + + lifetime := body.GetLifetime() + if x.lifetimeSet = lifetime != nil; x.lifetimeSet { + x.iat = lifetime.GetIat() + x.nbf = lifetime.GetNbf() + x.exp = lifetime.GetExp() + } else if checkFieldPresence { + return errors.New("missing token lifetime") + } + + x.authKey = body.GetSessionKey() + if checkFieldPresence && len(x.authKey) == 0 { + return errors.New("missing session public key") + } + + c := body.GetContext() + if c != nil { + err = r(c, checkFieldPresence) + if err != nil { + return fmt.Errorf("invalid context: %w", err) + } + } else if checkFieldPresence { + return errors.New("missing session context") + } + + sig := m.GetSignature() + if x.sigSet = sig != nil; sig != nil { + x.sig = *sig + } else if checkFieldPresence { + return errors.New("missing body signature") + } + + return nil +} + +type contextWriter func() session.TokenContext + +func (x commonData) fillBody(w contextWriter) *session.TokenBody { + var body session.TokenBody + + if x.idSet { + binID, err := x.id.MarshalBinary() + if err != nil { + panic(fmt.Sprintf("unexpected error from UUID.MarshalBinary: %v", err)) + } + + body.SetID(binID) + } + + if x.issuerSet { + var issuer refs.OwnerID + x.issuer.WriteToV2(&issuer) + + body.SetOwnerID(&issuer) + } + + if x.lifetimeSet { + var lifetime session.TokenLifetime + lifetime.SetIat(x.iat) + lifetime.SetNbf(x.nbf) + lifetime.SetExp(x.exp) + + body.SetLifetime(&lifetime) + } + + body.SetSessionKey(x.authKey) + + body.SetContext(w()) + + return &body +} + +func (x commonData) writeToV2(m *session.Token, w contextWriter) { + body := x.fillBody(w) + + m.SetBody(body) + + var sig *refs.Signature + + if x.sigSet { + sig = &x.sig + } + + m.SetSignature(sig) +} + +func (x commonData) signedData(w contextWriter) []byte { + return x.fillBody(w).StableMarshal(nil) +} + +func (x *commonData) sign(key ecdsa.PrivateKey, w contextWriter) error { + user.IDFromKey(&x.issuer, key.PublicKey) + x.issuerSet = true + + var sig frostfscrypto.Signature + + err := sig.Calculate(frostfsecdsa.Signer(key), x.signedData(w)) + if err != nil { + return err + } + + sig.WriteToV2(&x.sig) + x.sigSet = true + + return nil +} + +func (x commonData) verifySignature(w contextWriter) bool { + if !x.sigSet { + return false + } + + var sig frostfscrypto.Signature + + // TODO: (#233) check owner<->key relation + return sig.ReadFromV2(x.sig) == nil && sig.Verify(x.signedData(w)) +} + +func (x commonData) marshal(w contextWriter) []byte { + var m session.Token + x.writeToV2(&m, w) + + return m.StableMarshal(nil) +} + +func (x *commonData) unmarshal(data []byte, r contextReader) error { + var m session.Token + + err := m.Unmarshal(data) + if err != nil { + return err + } + + return x.readFromV2(m, false, r) +} + +func (x commonData) marshalJSON(w contextWriter) ([]byte, error) { + var m session.Token + x.writeToV2(&m, w) + + return m.MarshalJSON() +} + +func (x *commonData) unmarshalJSON(data []byte, r contextReader) error { + var m session.Token + + err := m.UnmarshalJSON(data) + if err != nil { + return err + } + + return x.readFromV2(m, false, r) +} + +// SetExp sets "exp" (expiration time) claim which identifies the expiration +// time (in FrostFS epochs) after which the session MUST NOT be accepted for +// processing. The processing of the "exp" claim requires that the current +// epoch MUST be before or equal to the expiration epoch listed in the "exp" +// claim. +// +// Naming is inspired by https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.4. +// +// See also ExpiredAt. +func (x *commonData) SetExp(exp uint64) { + x.exp = exp + x.lifetimeSet = true +} + +// SetNbf sets "nbf" (not before) claim which identifies the time (in FrostFS +// epochs) before which the session MUST NOT be accepted for processing. +// The processing of the "nbf" claim requires that the current date/time MUST be +// after or equal to the not-before date/time listed in the "nbf" claim. +// +// Naming is inspired by https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.5. +// +// See also InvalidAt. +func (x *commonData) SetNbf(nbf uint64) { + x.nbf = nbf + x.lifetimeSet = true +} + +// SetIat sets "iat" (issued at) claim which identifies the time (in FrostFS +// epochs) at which the session was issued. This claim can be used to +// determine the age of the session. +// +// Naming is inspired by https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.6. +// +// See also InvalidAt. +func (x *commonData) SetIat(iat uint64) { + x.iat = iat + x.lifetimeSet = true +} + +func (x commonData) expiredAt(epoch uint64) bool { + return !x.lifetimeSet || x.exp < epoch +} + +// InvalidAt asserts "exp", "nbf" and "iat" claims. +// +// Zero session is invalid in any epoch. +// +// See also SetExp, SetNbf, SetIat. +func (x commonData) InvalidAt(epoch uint64) bool { + return x.expiredAt(epoch) || x.nbf > epoch || x.iat > epoch +} + +// SetID sets a unique identifier for the session. The identifier value MUST be +// assigned in a manner that ensures that there is a negligible probability +// that the same value will be accidentally assigned to a different session. +// +// ID format MUST be UUID version 4 (random). uuid.New can be used to generate +// a new ID. See https://datatracker.ietf.org/doc/html/rfc4122 and +// github.com/google/uuid package docs for details. +// +// See also ID. +func (x *commonData) SetID(id uuid.UUID) { + x.id = id + x.idSet = true +} + +// ID returns a unique identifier for the session. +// +// Zero session has empty UUID (all zeros, see uuid.Nil) which is legitimate +// but most likely not suitable. +// +// See also SetID. +func (x commonData) ID() uuid.UUID { + if x.idSet { + return x.id + } + + return uuid.Nil +} + +// SetAuthKey public key corresponding to the private key bound to the session. +// +// See also AssertAuthKey. +func (x *commonData) SetAuthKey(key frostfscrypto.PublicKey) { + x.authKey = make([]byte, key.MaxEncodedSize()) + x.authKey = x.authKey[:key.Encode(x.authKey)] +} + +// AssertAuthKey asserts public key bound to the session. +// +// Zero session fails the check. +// +// See also SetAuthKey. +func (x commonData) AssertAuthKey(key frostfscrypto.PublicKey) bool { + bKey := make([]byte, key.MaxEncodedSize()) + bKey = bKey[:key.Encode(bKey)] + + return bytes.Equal(bKey, x.authKey) +} + +// Issuer returns user ID of the session issuer. +// +// Makes sense only for signed session instances. For unsigned instances, +// Issuer returns zero user.ID. +// +// See also Sign. +func (x commonData) Issuer() user.ID { + if x.issuerSet { + return x.issuer + } + + return user.ID{} +} diff --git a/pkg/sdk/session/container.go b/pkg/sdk/session/container.go new file mode 100644 index 000000000..0109e2df1 --- /dev/null +++ b/pkg/sdk/session/container.go @@ -0,0 +1,215 @@ +package session + +import ( + "crypto/ecdsa" + "errors" + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/crypto" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" +) + +// Container represents token of the FrostFS Container session. A session is opened +// between any two sides of the system, and implements a mechanism for transferring +// the power of attorney of actions to another network member. The session has a +// limited validity period, and applies to a strictly defined set of operations. +// See methods for details. +// +// Container is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session.Token +// message. See ReadFromV2 / WriteToV2 methods. +// +// Instances can be created using built-in var declaration. +type Container struct { + commonData + + verb ContainerVerb + + cnrSet bool + cnr cid.ID +} + +// readContext is a contextReader needed for commonData methods. +func (x *Container) readContext(c session.TokenContext, checkFieldPresence bool) error { + cCnr, ok := c.(*session.ContainerSessionContext) + if !ok || cCnr == nil { + return fmt.Errorf("invalid context %T", c) + } + + x.cnrSet = !cCnr.Wildcard() + cnr := cCnr.ContainerID() + + if x.cnrSet { + if cnr != nil { + err := x.cnr.ReadFromV2(*cnr) + if err != nil { + return fmt.Errorf("invalid container ID: %w", err) + } + } else if checkFieldPresence { + return errors.New("missing container or wildcard flag") + } + } else if cnr != nil { + return errors.New("container conflicts with wildcard flag") + } + + x.verb = ContainerVerb(cCnr.Verb()) + + return nil +} + +func (x *Container) readFromV2(m session.Token, checkFieldPresence bool) error { + return x.commonData.readFromV2(m, checkFieldPresence, x.readContext) +} + +// ReadFromV2 reads Container from the session.Token message. Checks if the +// message conforms to FrostFS API V2 protocol. +// +// See also WriteToV2. +func (x *Container) ReadFromV2(m session.Token) error { + return x.readFromV2(m, true) +} + +func (x Container) writeContext() session.TokenContext { + var c session.ContainerSessionContext + c.SetWildcard(!x.cnrSet) + c.SetVerb(session.ContainerSessionVerb(x.verb)) + + if x.cnrSet { + var cnr refs.ContainerID + x.cnr.WriteToV2(&cnr) + + c.SetContainerID(&cnr) + } + + return &c +} + +// WriteToV2 writes Container to the session.Token message. +// The message must not be nil. +// +// See also ReadFromV2. +func (x Container) WriteToV2(m *session.Token) { + x.writeToV2(m, x.writeContext) +} + +// Marshal encodes Container into a binary format of the FrostFS API protocol +// (Protocol Buffers with direct field order). +// +// See also Unmarshal. +func (x Container) Marshal() []byte { + return x.marshal(x.writeContext) +} + +// Unmarshal decodes FrostFS API protocol binary format into the Container +// (Protocol Buffers with direct field order). Returns an error describing +// a format violation. +// +// See also Marshal. +func (x *Container) Unmarshal(data []byte) error { + return x.unmarshal(data, x.readContext) +} + +// MarshalJSON encodes Container into a JSON format of the FrostFS API protocol +// (Protocol Buffers JSON). +// +// See also UnmarshalJSON. +func (x Container) MarshalJSON() ([]byte, error) { + return x.marshalJSON(x.writeContext) +} + +// UnmarshalJSON decodes FrostFS API protocol JSON format into the Container +// (Protocol Buffers JSON). Returns an error describing a format violation. +// +// See also MarshalJSON. +func (x *Container) UnmarshalJSON(data []byte) error { + return x.unmarshalJSON(data, x.readContext) +} + +// Sign calculates and writes signature of the Container data. +// Returns signature calculation errors. +// +// Zero Container is unsigned. +// +// Note that any Container mutation is likely to break the signature, so it is +// expected to be calculated as a final stage of Container formation. +// +// See also VerifySignature. +func (x *Container) Sign(key ecdsa.PrivateKey) error { + return x.sign(key, x.writeContext) +} + +// VerifySignature checks if Container signature is presented and valid. +// +// Zero Container fails the check. +// +// See also Sign. +func (x Container) VerifySignature() bool { + return x.verifySignature(x.writeContext) +} + +// ApplyOnlyTo limits session scope to a given author container. +// +// See also AppliedTo. +func (x *Container) ApplyOnlyTo(cnr cid.ID) { + x.cnr = cnr + x.cnrSet = true +} + +// AppliedTo checks if the session is propagated to the given container. +// +// Zero Container is applied to all author's containers. +// +// See also ApplyOnlyTo. +func (x Container) AppliedTo(cnr cid.ID) bool { + return !x.cnrSet || x.cnr.Equals(cnr) +} + +// ContainerVerb enumerates container operations. +type ContainerVerb int8 + +const ( + _ ContainerVerb = iota + + VerbContainerPut // Put rpc + VerbContainerDelete // Delete rpc + VerbContainerSetEACL // SetExtendedACL rpc +) + +// ForVerb specifies the container operation of the session scope. Each +// Container is related to the single operation. +// +// See also AssertVerb. +func (x *Container) ForVerb(verb ContainerVerb) { + x.verb = verb +} + +// AssertVerb checks if Container relates to the given container operation. +// +// Zero Container relates to zero (unspecified) verb. +// +// See also ForVerb. +func (x Container) AssertVerb(verb ContainerVerb) bool { + return x.verb == verb +} + +// IssuedBy checks if Container session is issued by the given user. +// +// See also Container.Issuer. +func IssuedBy(cnr Container, id user.ID) bool { + return cnr.Issuer().Equals(id) +} + +// VerifySessionDataSignature verifies signature of the session data. In practice, +// the method is used to authenticate an operation with session data. +func (x Container) VerifySessionDataSignature(data, signature []byte) bool { + var sigV2 refs.Signature + sigV2.SetKey(x.authKey) + sigV2.SetScheme(refs.ECDSA_RFC6979_SHA256) + sigV2.SetSign(signature) + + var sig frostfscrypto.Signature + + return sig.ReadFromV2(sigV2) == nil && sig.Verify(data) +} diff --git a/pkg/sdk/session/container_test.go b/pkg/sdk/session/container_test.go new file mode 100644 index 000000000..36cc3d47f --- /dev/null +++ b/pkg/sdk/session/container_test.go @@ -0,0 +1,571 @@ +package session_test + +import ( + "crypto/rand" + "fmt" + "math" + mrand "math/rand" + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + v2session "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/crypto" + frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/crypto/ecdsa" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/session" + sessiontest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/session/test" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" + usertest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user/test" + "github.com/google/uuid" + "github.com/nspcc-dev/neo-go/pkg/util/slice" + "github.com/stretchr/testify/require" +) + +func TestContainerProtocolV2(t *testing.T) { + var validV2 v2session.Token + + var body v2session.TokenBody + validV2.SetBody(&body) + + // ID + id := uuid.New() + binID, err := id.MarshalBinary() + require.NoError(t, err) + restoreID := func() { + body.SetID(binID) + } + restoreID() + + // Owner + usr := usertest.ID() + var usrV2 refs.OwnerID + usr.WriteToV2(&usrV2) + restoreUser := func() { + body.SetOwnerID(&usrV2) + } + restoreUser() + + // Lifetime + var lifetime v2session.TokenLifetime + lifetime.SetIat(1) + lifetime.SetNbf(2) + lifetime.SetExp(3) + restoreLifetime := func() { + body.SetLifetime(&lifetime) + } + restoreLifetime() + + // Session key + signer := randSigner() + authKey := frostfsecdsa.PublicKey(signer.PublicKey) + binAuthKey := make([]byte, authKey.MaxEncodedSize()) + binAuthKey = binAuthKey[:authKey.Encode(binAuthKey)] + restoreAuthKey := func() { + body.SetSessionKey(binAuthKey) + } + restoreAuthKey() + + // Context + cnr := cidtest.ID() + var cnrV2 refs.ContainerID + cnr.WriteToV2(&cnrV2) + var cCnr v2session.ContainerSessionContext + restoreCtx := func() { + cCnr.SetContainerID(&cnrV2) + cCnr.SetWildcard(false) + body.SetContext(&cCnr) + } + restoreCtx() + + // Signature + var sig refs.Signature + restoreSig := func() { + validV2.SetSignature(&sig) + } + restoreSig() + + // TODO(@cthulhu-rider): #260 use functionality for message corruption + + for _, testcase := range []struct { + name string + corrupt []func() + restore func() + assert func(session.Container) + breakSign func(*v2session.Token) + }{ + { + name: "Signature", + corrupt: []func(){ + func() { + validV2.SetSignature(nil) + }, + }, + restore: restoreSig, + }, + { + name: "ID", + corrupt: []func(){ + func() { + body.SetID([]byte{1, 2, 3}) + }, + func() { + id, err := uuid.NewDCEPerson() + require.NoError(t, err) + bindID, err := id.MarshalBinary() + require.NoError(t, err) + body.SetID(bindID) + }, + }, + restore: restoreID, + assert: func(val session.Container) { + require.Equal(t, id, val.ID()) + }, + breakSign: func(m *v2session.Token) { + id := m.GetBody().GetID() + id[len(id)-1]++ + }, + }, + { + name: "User", + corrupt: []func(){ + func() { + var brokenUsrV2 refs.OwnerID + brokenUsrV2.SetValue(append(usrV2.GetValue(), 1)) + body.SetOwnerID(&brokenUsrV2) + }, + }, + restore: restoreUser, + assert: func(val session.Container) { + require.Equal(t, usr, val.Issuer()) + }, + breakSign: func(m *v2session.Token) { + id := m.GetBody().GetOwnerID().GetValue() + copy(id, usertest.ID().WalletBytes()) + }, + }, + { + name: "Lifetime", + corrupt: []func(){ + func() { + body.SetLifetime(nil) + }, + }, + restore: restoreLifetime, + assert: func(val session.Container) { + require.True(t, val.InvalidAt(1)) + require.False(t, val.InvalidAt(2)) + require.False(t, val.InvalidAt(3)) + require.True(t, val.InvalidAt(4)) + }, + breakSign: func(m *v2session.Token) { + lt := m.GetBody().GetLifetime() + lt.SetIat(lt.GetIat() + 1) + }, + }, + { + name: "Auth key", + corrupt: []func(){ + func() { + body.SetSessionKey(nil) + }, + func() { + body.SetSessionKey([]byte{}) + }, + }, + restore: restoreAuthKey, + assert: func(val session.Container) { + require.True(t, val.AssertAuthKey(&authKey)) + }, + breakSign: func(m *v2session.Token) { + body := m.GetBody() + key := body.GetSessionKey() + cp := slice.Copy(key) + cp[len(cp)-1]++ + body.SetSessionKey(cp) + }, + }, + { + name: "Context", + corrupt: []func(){ + func() { + body.SetContext(nil) + }, + func() { + cCnr.SetWildcard(true) + }, + func() { + cCnr.SetContainerID(nil) + }, + func() { + var brokenCnr refs.ContainerID + brokenCnr.SetValue(append(cnrV2.GetValue(), 1)) + cCnr.SetContainerID(&brokenCnr) + }, + }, + restore: restoreCtx, + assert: func(val session.Container) { + require.True(t, val.AppliedTo(cnr)) + require.False(t, val.AppliedTo(cidtest.ID())) + }, + breakSign: func(m *v2session.Token) { + cnr := m.GetBody().GetContext().(*v2session.ContainerSessionContext).ContainerID().GetValue() + cnr[len(cnr)-1]++ + }, + }, + } { + var val session.Container + + for i, corrupt := range testcase.corrupt { + corrupt() + require.Error(t, val.ReadFromV2(validV2), testcase.name, fmt.Sprintf("corrupt #%d", i)) + + testcase.restore() + require.NoError(t, val.ReadFromV2(validV2), testcase.name) + + if testcase.assert != nil { + testcase.assert(val) + } + + if testcase.breakSign != nil { + require.NoError(t, val.Sign(signer), testcase.name) + require.True(t, val.VerifySignature(), testcase.name) + + var signedV2 v2session.Token + val.WriteToV2(&signedV2) + + var restored session.Container + require.NoError(t, restored.ReadFromV2(signedV2), testcase.name) + require.True(t, restored.VerifySignature(), testcase.name) + + testcase.breakSign(&signedV2) + + require.NoError(t, restored.ReadFromV2(signedV2), testcase.name) + require.False(t, restored.VerifySignature(), testcase.name) + } + } + } +} + +func TestContainer_WriteToV2(t *testing.T) { + var val session.Container + + assert := func(baseAssert func(v2session.Token)) { + var m v2session.Token + val.WriteToV2(&m) + baseAssert(m) + } + + // ID + id := uuid.New() + + binID, err := id.MarshalBinary() + require.NoError(t, err) + + val.SetID(id) + assert(func(m v2session.Token) { + require.Equal(t, binID, m.GetBody().GetID()) + }) + + // Owner/Signature + signer := randSigner() + + require.NoError(t, val.Sign(signer)) + + var usr user.ID + user.IDFromKey(&usr, signer.PublicKey) + + var usrV2 refs.OwnerID + usr.WriteToV2(&usrV2) + + assert(func(m v2session.Token) { + require.Equal(t, &usrV2, m.GetBody().GetOwnerID()) + + sig := m.GetSignature() + require.NotZero(t, sig.GetKey()) + require.NotZero(t, sig.GetSign()) + }) + + // Lifetime + const iat, nbf, exp = 1, 2, 3 + val.SetIat(iat) + val.SetNbf(nbf) + val.SetExp(exp) + + assert(func(m v2session.Token) { + lt := m.GetBody().GetLifetime() + require.EqualValues(t, iat, lt.GetIat()) + require.EqualValues(t, nbf, lt.GetNbf()) + require.EqualValues(t, exp, lt.GetExp()) + }) + + // Context + assert(func(m v2session.Token) { + cCnr, ok := m.GetBody().GetContext().(*v2session.ContainerSessionContext) + require.True(t, ok) + require.True(t, cCnr.Wildcard()) + require.Zero(t, cCnr.ContainerID()) + }) + + cnr := cidtest.ID() + + var cnrV2 refs.ContainerID + cnr.WriteToV2(&cnrV2) + + val.ApplyOnlyTo(cnr) + + assert(func(m v2session.Token) { + cCnr, ok := m.GetBody().GetContext().(*v2session.ContainerSessionContext) + require.True(t, ok) + require.False(t, cCnr.Wildcard()) + require.Equal(t, &cnrV2, cCnr.ContainerID()) + }) +} + +func TestContainer_ApplyOnlyTo(t *testing.T) { + var val session.Container + var m v2session.Token + filled := sessiontest.Container() + + assertDefaults := func() { + cCnr, ok := m.GetBody().GetContext().(*v2session.ContainerSessionContext) + require.True(t, ok) + require.True(t, cCnr.Wildcard()) + require.Zero(t, cCnr.ContainerID()) + } + + assertBinary := func(baseAssert func()) { + val2 := filled + + require.NoError(t, val2.Unmarshal(val.Marshal())) + baseAssert() + } + + assertJSON := func(baseAssert func()) { + val2 := filled + + jd, err := val.MarshalJSON() + require.NoError(t, err) + + require.NoError(t, val2.UnmarshalJSON(jd)) + baseAssert() + } + + val.WriteToV2(&m) + + assertDefaults() + assertBinary(assertDefaults) + assertJSON(assertDefaults) + + // set value + + cnr := cidtest.ID() + + var cnrV2 refs.ContainerID + cnr.WriteToV2(&cnrV2) + + val.ApplyOnlyTo(cnr) + + val.WriteToV2(&m) + + assertCnr := func() { + cCnr, ok := m.GetBody().GetContext().(*v2session.ContainerSessionContext) + require.True(t, ok) + require.False(t, cCnr.Wildcard()) + require.Equal(t, &cnrV2, cCnr.ContainerID()) + } + + assertCnr() + assertBinary(assertCnr) + assertJSON(assertCnr) +} + +func TestContainer_AppliedTo(t *testing.T) { + var x session.Container + + cnr1 := cidtest.ID() + cnr2 := cidtest.ID() + + require.True(t, x.AppliedTo(cnr1)) + require.True(t, x.AppliedTo(cnr2)) + + x.ApplyOnlyTo(cnr1) + + require.True(t, x.AppliedTo(cnr1)) + require.False(t, x.AppliedTo(cnr2)) +} + +func TestContainer_InvalidAt(t *testing.T) { + var x session.Container + + nbf := mrand.Uint64() + if nbf == math.MaxUint64 { + nbf-- + } + + iat := nbf + exp := iat + 1 + + x.SetNbf(nbf) + x.SetIat(iat) + x.SetExp(exp) + + require.True(t, x.InvalidAt(nbf-1)) + require.True(t, x.InvalidAt(iat-1)) + require.False(t, x.InvalidAt(iat)) + require.False(t, x.InvalidAt(exp)) + require.True(t, x.InvalidAt(exp+1)) +} + +func TestContainer_ID(t *testing.T) { + var x session.Container + + require.Zero(t, x.ID()) + + id := uuid.New() + + x.SetID(id) + + require.Equal(t, id, x.ID()) +} + +func TestContainer_AssertAuthKey(t *testing.T) { + var x session.Container + + key := randPublicKey() + + require.False(t, x.AssertAuthKey(key)) + + x.SetAuthKey(key) + + require.True(t, x.AssertAuthKey(key)) +} + +func TestContainer_ForVerb(t *testing.T) { + var val session.Container + var m v2session.Token + filled := sessiontest.Container() + + assertDefaults := func() { + cCnr, ok := m.GetBody().GetContext().(*v2session.ContainerSessionContext) + require.True(t, ok) + require.Zero(t, cCnr.Verb()) + } + + assertBinary := func(baseAssert func()) { + val2 := filled + + require.NoError(t, val2.Unmarshal(val.Marshal())) + baseAssert() + } + + assertJSON := func(baseAssert func()) { + val2 := filled + + jd, err := val.MarshalJSON() + require.NoError(t, err) + + require.NoError(t, val2.UnmarshalJSON(jd)) + baseAssert() + } + + val.WriteToV2(&m) + + assertDefaults() + assertBinary(assertDefaults) + assertJSON(assertDefaults) + + // set value + + assertVerb := func(verb v2session.ContainerSessionVerb) { + cCnr, ok := m.GetBody().GetContext().(*v2session.ContainerSessionContext) + require.True(t, ok) + require.Equal(t, verb, cCnr.Verb()) + } + + for from, to := range map[session.ContainerVerb]v2session.ContainerSessionVerb{ + session.VerbContainerPut: v2session.ContainerVerbPut, + session.VerbContainerDelete: v2session.ContainerVerbDelete, + session.VerbContainerSetEACL: v2session.ContainerVerbSetEACL, + } { + val.ForVerb(from) + + val.WriteToV2(&m) + + assertVerb(to) + assertBinary(func() { assertVerb(to) }) + assertJSON(func() { assertVerb(to) }) + } +} + +func TestContainer_AssertVerb(t *testing.T) { + var x session.Container + + const v1, v2 = session.VerbContainerPut, session.VerbContainerDelete + + require.False(t, x.AssertVerb(v1)) + require.False(t, x.AssertVerb(v2)) + + x.ForVerb(v1) + require.True(t, x.AssertVerb(v1)) + require.False(t, x.AssertVerb(v2)) +} + +func TestIssuedBy(t *testing.T) { + var ( + token session.Container + issuer user.ID + signer = randSigner() + ) + + user.IDFromKey(&issuer, signer.PublicKey) + + require.False(t, session.IssuedBy(token, issuer)) + + require.NoError(t, token.Sign(signer)) + require.True(t, session.IssuedBy(token, issuer)) +} + +func TestContainer_Issuer(t *testing.T) { + var token session.Container + signer := randSigner() + + require.Zero(t, token.Issuer()) + + require.NoError(t, token.Sign(signer)) + + var issuer user.ID + + user.IDFromKey(&issuer, signer.PublicKey) + + require.True(t, token.Issuer().Equals(issuer)) +} + +func TestContainer_Sign(t *testing.T) { + val := sessiontest.Container() + + require.NoError(t, val.Sign(randSigner())) + + require.True(t, val.VerifySignature()) +} + +func TestContainer_VerifyDataSignature(t *testing.T) { + signer := randSigner() + + var tok session.Container + + data := make([]byte, 100) + rand.Read(data) + + var sig frostfscrypto.Signature + require.NoError(t, sig.Calculate(frostfsecdsa.SignerRFC6979(signer), data)) + + var sigV2 refs.Signature + sig.WriteToV2(&sigV2) + + require.False(t, tok.VerifySessionDataSignature(data, sigV2.GetSign())) + + tok.SetAuthKey((*frostfsecdsa.PublicKeyRFC6979)(&signer.PublicKey)) + require.True(t, tok.VerifySessionDataSignature(data, sigV2.GetSign())) + require.False(t, tok.VerifySessionDataSignature(append(data, 1), sigV2.GetSign())) + require.False(t, tok.VerifySessionDataSignature(data, append(sigV2.GetSign(), 1))) +} diff --git a/pkg/sdk/session/doc.go b/pkg/sdk/session/doc.go new file mode 100644 index 000000000..9b860f24c --- /dev/null +++ b/pkg/sdk/session/doc.go @@ -0,0 +1,50 @@ +/* +Package session collects functionality of the FrostFS sessions. + +Sessions are used in FrostFS as a mechanism for transferring the power of attorney +of actions to another network member. + +Session tokens represent proof of trust. Each session has a limited lifetime and +scope related to some FrostFS service: Object, Container, etc. + +Both parties agree on a secret (private session key), the possession of which +will be authenticated by a trusted person. The principal confirms his trust by +signing the public part of the secret (public session key). + + var tok Container + tok.ForVerb(VerbContainerDelete) + tok.SetAuthKey(trustedKey) + // ... + + err := tok.Sign(principalKey) + // ... + + // transfer the token to a trusted party + +The trusted member can perform operations on behalf of the trustee. + +Instances can be also used to process FrostFS API V2 protocol messages +(see neo.fs.v2.accounting package in https://git.frostfs.info/TrueCloudLab/frostfs-api). + +On client side: + + import "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" + + var msg session.Token + tok.WriteToV2(&msg) + + // send msg + +On server side: + + // recv msg + + var tok session.Container + tok.ReadFromV2(msg) + + // process cnr + +Using package types in an application is recommended to potentially work with +different protocol versions with which these types are compatible. +*/ +package session diff --git a/pkg/sdk/session/object.go b/pkg/sdk/session/object.go new file mode 100644 index 000000000..ccb7c6deb --- /dev/null +++ b/pkg/sdk/session/object.go @@ -0,0 +1,272 @@ +package session + +import ( + "crypto/ecdsa" + "errors" + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" +) + +// Object represents token of the FrostFS Object session. A session is opened +// between any two sides of the system, and implements a mechanism for transferring +// the power of attorney of actions to another network member. The session has a +// limited validity period, and applies to a strictly defined set of operations. +// See methods for details. +// +// Object is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session.Token +// message. See ReadFromV2 / WriteToV2 methods. +// +// Instances can be created using built-in var declaration. +type Object struct { + commonData + + verb ObjectVerb + + cnrSet bool + cnr cid.ID + + objs []oid.ID +} + +func (x *Object) readContext(c session.TokenContext, checkFieldPresence bool) error { + cObj, ok := c.(*session.ObjectSessionContext) + if !ok || cObj == nil { + return fmt.Errorf("invalid context %T", c) + } + + var err error + + cnr := cObj.GetContainer() + if x.cnrSet = cnr != nil; x.cnrSet { + err := x.cnr.ReadFromV2(*cnr) + if err != nil { + return fmt.Errorf("invalid container ID: %w", err) + } + } else if checkFieldPresence { + return errors.New("missing target container") + } + + objs := cObj.GetObjects() + if objs != nil { + x.objs = make([]oid.ID, len(objs)) + + for i := range objs { + err = x.objs[i].ReadFromV2(objs[i]) + if err != nil { + return fmt.Errorf("invalid target object: %w", err) + } + } + } else { + x.objs = nil + } + + x.verb = ObjectVerb(cObj.GetVerb()) + + return nil +} + +func (x *Object) readFromV2(m session.Token, checkFieldPresence bool) error { + return x.commonData.readFromV2(m, checkFieldPresence, x.readContext) +} + +// ReadFromV2 reads Object from the session.Token message. Checks if the +// message conforms to FrostFS API V2 protocol. +// +// See also WriteToV2. +func (x *Object) ReadFromV2(m session.Token) error { + return x.readFromV2(m, true) +} + +func (x Object) writeContext() session.TokenContext { + var c session.ObjectSessionContext + c.SetVerb(session.ObjectSessionVerb(x.verb)) + + if x.cnrSet || len(x.objs) > 0 { + var cnr *refs.ContainerID + + if x.cnrSet { + cnr = new(refs.ContainerID) + x.cnr.WriteToV2(cnr) + } + + var objs []refs.ObjectID + + if x.objs != nil { + objs = make([]refs.ObjectID, len(x.objs)) + + for i := range x.objs { + x.objs[i].WriteToV2(&objs[i]) + } + } + + c.SetTarget(cnr, objs...) + } + + return &c +} + +// WriteToV2 writes Object to the session.Token message. +// The message must not be nil. +// +// See also ReadFromV2. +func (x Object) WriteToV2(m *session.Token) { + x.writeToV2(m, x.writeContext) +} + +// Marshal encodes Object into a binary format of the FrostFS API protocol +// (Protocol Buffers with direct field order). +// +// See also Unmarshal. +func (x Object) Marshal() []byte { + var m session.Token + x.WriteToV2(&m) + + return x.marshal(x.writeContext) +} + +// Unmarshal decodes FrostFS API protocol binary format into the Object +// (Protocol Buffers with direct field order). Returns an error describing +// a format violation. +// +// See also Marshal. +func (x *Object) Unmarshal(data []byte) error { + return x.unmarshal(data, x.readContext) +} + +// MarshalJSON encodes Object into a JSON format of the FrostFS API protocol +// (Protocol Buffers JSON). +// +// See also UnmarshalJSON. +func (x Object) MarshalJSON() ([]byte, error) { + return x.marshalJSON(x.writeContext) +} + +// UnmarshalJSON decodes FrostFS API protocol JSON format into the Object +// (Protocol Buffers JSON). Returns an error describing a format violation. +// +// See also MarshalJSON. +func (x *Object) UnmarshalJSON(data []byte) error { + return x.unmarshalJSON(data, x.readContext) +} + +// Sign calculates and writes signature of the Object data. +// Returns signature calculation errors. +// +// Zero Object is unsigned. +// +// Note that any Object mutation is likely to break the signature, so it is +// expected to be calculated as a final stage of Object formation. +// +// See also VerifySignature. +func (x *Object) Sign(key ecdsa.PrivateKey) error { + return x.sign(key, x.writeContext) +} + +// VerifySignature checks if Object signature is presented and valid. +// +// Zero Object fails the check. +// +// See also Sign. +func (x Object) VerifySignature() bool { + // TODO: (#233) check owner<->key relation + return x.verifySignature(x.writeContext) +} + +// BindContainer binds the Object session to a given container. Each session +// MUST be bound to exactly one container. +// +// See also AssertContainer. +func (x *Object) BindContainer(cnr cid.ID) { + x.cnr = cnr + x.cnrSet = true +} + +// AssertContainer checks if Object session bound to a given container. +// +// Zero Object isn't bound to any container which is incorrect according to +// FrostFS API protocol. +// +// See also BindContainer. +func (x Object) AssertContainer(cnr cid.ID) bool { + return x.cnr.Equals(cnr) +} + +// LimitByObjects limits session scope to the given objects from the container +// to which Object session is bound. +// +// Argument MUST NOT be mutated, make a copy first. +// +// See also AssertObject. +func (x *Object) LimitByObjects(objs ...oid.ID) { + x.objs = objs +} + +// AssertObject checks if Object session is applied to a given object. +// +// Zero Object is applied to all objects in the container. +// +// See also LimitByObjects. +func (x Object) AssertObject(obj oid.ID) bool { + if len(x.objs) == 0 { + return true + } + + for i := range x.objs { + if x.objs[i].Equals(obj) { + return true + } + } + + return false +} + +// ObjectVerb enumerates object operations. +type ObjectVerb int8 + +const ( + _ ObjectVerb = iota + + VerbObjectPut // Put rpc + VerbObjectGet // Get rpc + VerbObjectHead // Head rpc + VerbObjectSearch // Search rpc + VerbObjectDelete // Delete rpc + VerbObjectRange // GetRange rpc + VerbObjectRangeHash // GetRangeHash rpc +) + +// ForVerb specifies the object operation of the session scope. Each +// Object is related to the single operation. +// +// See also AssertVerb. +func (x *Object) ForVerb(verb ObjectVerb) { + x.verb = verb +} + +// AssertVerb checks if Object relates to one of the given object operations. +// +// Zero Object relates to zero (unspecified) verb. +// +// See also ForVerb. +func (x Object) AssertVerb(verbs ...ObjectVerb) bool { + for i := range verbs { + if verbs[i] == x.verb { + return true + } + } + + return false +} + +// ExpiredAt asserts "exp" claim. +// +// Zero Object is expired in any epoch. +// +// See also SetExp. +func (x Object) ExpiredAt(epoch uint64) bool { + return x.expiredAt(epoch) +} diff --git a/pkg/sdk/session/object_test.go b/pkg/sdk/session/object_test.go new file mode 100644 index 000000000..1dbd35d07 --- /dev/null +++ b/pkg/sdk/session/object_test.go @@ -0,0 +1,648 @@ +package session_test + +import ( + "crypto/ecdsa" + "fmt" + "math" + "math/rand" + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + v2session "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/crypto" + frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/crypto/ecdsa" + oidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id/test" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/session" + sessiontest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/session/test" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" + usertest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user/test" + "github.com/google/uuid" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + "github.com/nspcc-dev/neo-go/pkg/util/slice" + "github.com/stretchr/testify/require" +) + +func randSigner() ecdsa.PrivateKey { + k, err := keys.NewPrivateKey() + if err != nil { + panic(fmt.Sprintf("generate private key: %v", err)) + } + + return k.PrivateKey +} + +func randPublicKey() frostfscrypto.PublicKey { + k := randSigner().PublicKey + return (*frostfsecdsa.PublicKey)(&k) +} + +func TestObjectProtocolV2(t *testing.T) { + var validV2 v2session.Token + + var body v2session.TokenBody + validV2.SetBody(&body) + + // ID + id := uuid.New() + binID, err := id.MarshalBinary() + require.NoError(t, err) + restoreID := func() { + body.SetID(binID) + } + restoreID() + + // Owner + usr := usertest.ID() + var usrV2 refs.OwnerID + usr.WriteToV2(&usrV2) + restoreUser := func() { + body.SetOwnerID(&usrV2) + } + restoreUser() + + // Lifetime + var lifetime v2session.TokenLifetime + lifetime.SetIat(1) + lifetime.SetNbf(2) + lifetime.SetExp(3) + restoreLifetime := func() { + body.SetLifetime(&lifetime) + } + restoreLifetime() + + // Session key + signer := randSigner() + authKey := frostfsecdsa.PublicKey(signer.PublicKey) + binAuthKey := make([]byte, authKey.MaxEncodedSize()) + binAuthKey = binAuthKey[:authKey.Encode(binAuthKey)] + restoreAuthKey := func() { + body.SetSessionKey(binAuthKey) + } + restoreAuthKey() + + // Context + cnr := cidtest.ID() + obj1 := oidtest.ID() + obj2 := oidtest.ID() + var cnrV2 refs.ContainerID + cnr.WriteToV2(&cnrV2) + var obj1V2 refs.ObjectID + obj1.WriteToV2(&obj1V2) + var obj2V2 refs.ObjectID + obj2.WriteToV2(&obj2V2) + var cObj v2session.ObjectSessionContext + restoreCtx := func() { + cObj.SetTarget(&cnrV2, obj1V2, obj2V2) + body.SetContext(&cObj) + } + restoreCtx() + + // Signature + var sig refs.Signature + restoreSig := func() { + validV2.SetSignature(&sig) + } + restoreSig() + + // TODO(@cthulhu-rider): #260 use functionality for message corruption + + for _, testcase := range []struct { + name string + corrupt []func() + restore func() + assert func(session.Object) + breakSign func(*v2session.Token) + }{ + { + name: "Signature", + corrupt: []func(){ + func() { + validV2.SetSignature(nil) + }, + }, + restore: restoreSig, + }, + { + name: "ID", + corrupt: []func(){ + func() { + body.SetID([]byte{1, 2, 3}) + }, + func() { + id, err := uuid.NewDCEPerson() + require.NoError(t, err) + bindID, err := id.MarshalBinary() + require.NoError(t, err) + body.SetID(bindID) + }, + }, + restore: restoreID, + assert: func(val session.Object) { + require.Equal(t, id, val.ID()) + }, + breakSign: func(m *v2session.Token) { + id := m.GetBody().GetID() + id[len(id)-1]++ + }, + }, + { + name: "User", + corrupt: []func(){ + func() { + var brokenUsrV2 refs.OwnerID + brokenUsrV2.SetValue(append(usrV2.GetValue(), 1)) + body.SetOwnerID(&brokenUsrV2) + }, + }, + restore: restoreUser, + assert: func(val session.Object) { + require.Equal(t, usr, val.Issuer()) + }, + breakSign: func(m *v2session.Token) { + id := m.GetBody().GetOwnerID().GetValue() + copy(id, usertest.ID().WalletBytes()) + }, + }, + { + name: "Lifetime", + corrupt: []func(){ + func() { + body.SetLifetime(nil) + }, + }, + restore: restoreLifetime, + assert: func(val session.Object) { + require.True(t, val.InvalidAt(1)) + require.False(t, val.InvalidAt(2)) + require.False(t, val.InvalidAt(3)) + require.True(t, val.InvalidAt(4)) + }, + breakSign: func(m *v2session.Token) { + lt := m.GetBody().GetLifetime() + lt.SetIat(lt.GetIat() + 1) + }, + }, + { + name: "Auth key", + corrupt: []func(){ + func() { + body.SetSessionKey(nil) + }, + func() { + body.SetSessionKey([]byte{}) + }, + }, + restore: restoreAuthKey, + assert: func(val session.Object) { + require.True(t, val.AssertAuthKey(&authKey)) + }, + breakSign: func(m *v2session.Token) { + body := m.GetBody() + key := body.GetSessionKey() + cp := slice.Copy(key) + cp[len(cp)-1]++ + body.SetSessionKey(cp) + }, + }, + { + name: "Context", + corrupt: []func(){ + func() { + body.SetContext(nil) + }, + func() { + cObj.SetTarget(nil) + }, + func() { + var brokenCnr refs.ContainerID + brokenCnr.SetValue(append(cnrV2.GetValue(), 1)) + cObj.SetTarget(&brokenCnr) + }, + func() { + var brokenObj refs.ObjectID + brokenObj.SetValue(append(obj1V2.GetValue(), 1)) + cObj.SetTarget(&cnrV2, brokenObj) + }, + }, + restore: restoreCtx, + assert: func(val session.Object) { + require.True(t, val.AssertContainer(cnr)) + require.False(t, val.AssertContainer(cidtest.ID())) + require.True(t, val.AssertObject(obj1)) + require.True(t, val.AssertObject(obj2)) + require.False(t, val.AssertObject(oidtest.ID())) + }, + breakSign: func(m *v2session.Token) { + cnr := m.GetBody().GetContext().(*v2session.ObjectSessionContext).GetContainer().GetValue() + cnr[len(cnr)-1]++ + }, + }, + } { + var val session.Object + + for i, corrupt := range testcase.corrupt { + corrupt() + require.Error(t, val.ReadFromV2(validV2), testcase.name, fmt.Sprintf("corrupt #%d", i)) + + testcase.restore() + require.NoError(t, val.ReadFromV2(validV2), testcase.name, fmt.Sprintf("corrupt #%d", i)) + + if testcase.assert != nil { + testcase.assert(val) + } + + if testcase.breakSign != nil { + require.NoError(t, val.Sign(signer), testcase.name) + require.True(t, val.VerifySignature(), testcase.name) + + var signedV2 v2session.Token + val.WriteToV2(&signedV2) + + var restored session.Object + require.NoError(t, restored.ReadFromV2(signedV2), testcase.name) + require.True(t, restored.VerifySignature(), testcase.name) + + testcase.breakSign(&signedV2) + + require.NoError(t, restored.ReadFromV2(signedV2), testcase.name) + require.False(t, restored.VerifySignature(), testcase.name) + } + } + } +} + +func TestObject_WriteToV2(t *testing.T) { + var val session.Object + + assert := func(baseAssert func(v2session.Token)) { + var m v2session.Token + val.WriteToV2(&m) + baseAssert(m) + } + + // ID + id := uuid.New() + + binID, err := id.MarshalBinary() + require.NoError(t, err) + + val.SetID(id) + assert(func(m v2session.Token) { + require.Equal(t, binID, m.GetBody().GetID()) + }) + + // Owner/Signature + signer := randSigner() + + require.NoError(t, val.Sign(signer)) + + var usr user.ID + user.IDFromKey(&usr, signer.PublicKey) + + var usrV2 refs.OwnerID + usr.WriteToV2(&usrV2) + + assert(func(m v2session.Token) { + require.Equal(t, &usrV2, m.GetBody().GetOwnerID()) + + sig := m.GetSignature() + require.NotZero(t, sig.GetKey()) + require.NotZero(t, sig.GetSign()) + }) + + // Lifetime + const iat, nbf, exp = 1, 2, 3 + val.SetIat(iat) + val.SetNbf(nbf) + val.SetExp(exp) + + assert(func(m v2session.Token) { + lt := m.GetBody().GetLifetime() + require.EqualValues(t, iat, lt.GetIat()) + require.EqualValues(t, nbf, lt.GetNbf()) + require.EqualValues(t, exp, lt.GetExp()) + }) + + // Context + assert(func(m v2session.Token) { + cCnr, ok := m.GetBody().GetContext().(*v2session.ObjectSessionContext) + require.True(t, ok) + require.Zero(t, cCnr.GetContainer()) + require.Zero(t, cCnr.GetObjects()) + }) + + cnr := cidtest.ID() + + var cnrV2 refs.ContainerID + cnr.WriteToV2(&cnrV2) + + obj1 := oidtest.ID() + obj2 := oidtest.ID() + + var obj1V2 refs.ObjectID + obj1.WriteToV2(&obj1V2) + var obj2V2 refs.ObjectID + obj2.WriteToV2(&obj2V2) + + val.BindContainer(cnr) + val.LimitByObjects(obj1, obj2) + + assert(func(m v2session.Token) { + cCnr, ok := m.GetBody().GetContext().(*v2session.ObjectSessionContext) + require.True(t, ok) + require.Equal(t, &cnrV2, cCnr.GetContainer()) + require.Equal(t, []refs.ObjectID{obj1V2, obj2V2}, cCnr.GetObjects()) + }) +} + +func TestObject_BindContainer(t *testing.T) { + var val session.Object + var m v2session.Token + filled := sessiontest.Object() + + assertDefaults := func() { + cCnr, ok := m.GetBody().GetContext().(*v2session.ObjectSessionContext) + require.True(t, ok) + require.Zero(t, cCnr.GetContainer()) + require.Zero(t, cCnr.GetObjects()) + } + + assertBinary := func(baseAssert func()) { + val2 := filled + + require.NoError(t, val2.Unmarshal(val.Marshal())) + baseAssert() + } + + assertJSON := func(baseAssert func()) { + val2 := filled + + jd, err := val.MarshalJSON() + require.NoError(t, err) + + require.NoError(t, val2.UnmarshalJSON(jd)) + baseAssert() + } + + val.WriteToV2(&m) + + assertDefaults() + assertBinary(assertDefaults) + assertJSON(assertDefaults) + + // set value + + cnr := cidtest.ID() + + var cnrV2 refs.ContainerID + cnr.WriteToV2(&cnrV2) + + val.BindContainer(cnr) + + val.WriteToV2(&m) + + assertCnr := func() { + cObj, ok := m.GetBody().GetContext().(*v2session.ObjectSessionContext) + require.True(t, ok) + require.Equal(t, &cnrV2, cObj.GetContainer()) + } + + assertCnr() + assertBinary(assertCnr) + assertJSON(assertCnr) +} + +func TestObject_AssertContainer(t *testing.T) { + var x session.Object + + cnr := cidtest.ID() + + require.False(t, x.AssertContainer(cnr)) + + x.BindContainer(cnr) + + require.True(t, x.AssertContainer(cnr)) +} + +func TestObject_LimitByObjects(t *testing.T) { + var val session.Object + var m v2session.Token + filled := sessiontest.Object() + + assertDefaults := func() { + cCnr, ok := m.GetBody().GetContext().(*v2session.ObjectSessionContext) + require.True(t, ok) + require.Zero(t, cCnr.GetContainer()) + require.Zero(t, cCnr.GetObjects()) + } + + assertBinary := func(baseAssert func()) { + val2 := filled + + require.NoError(t, val2.Unmarshal(val.Marshal())) + baseAssert() + } + + assertJSON := func(baseAssert func()) { + val2 := filled + + jd, err := val.MarshalJSON() + require.NoError(t, err) + + require.NoError(t, val2.UnmarshalJSON(jd)) + baseAssert() + } + + val.WriteToV2(&m) + + assertDefaults() + assertBinary(assertDefaults) + assertJSON(assertDefaults) + + // set value + + obj1 := oidtest.ID() + obj2 := oidtest.ID() + + var obj1V2 refs.ObjectID + obj1.WriteToV2(&obj1V2) + var obj2V2 refs.ObjectID + obj2.WriteToV2(&obj2V2) + + val.LimitByObjects(obj1, obj2) + + val.WriteToV2(&m) + + assertObj := func() { + cObj, ok := m.GetBody().GetContext().(*v2session.ObjectSessionContext) + require.True(t, ok) + require.Equal(t, []refs.ObjectID{obj1V2, obj2V2}, cObj.GetObjects()) + } + + assertObj() + assertBinary(assertObj) + assertJSON(assertObj) +} + +func TestObject_AssertObject(t *testing.T) { + var x session.Object + + obj1 := oidtest.ID() + obj2 := oidtest.ID() + objOther := oidtest.ID() + + require.True(t, x.AssertObject(obj1)) + require.True(t, x.AssertObject(obj2)) + require.True(t, x.AssertObject(objOther)) + + x.LimitByObjects(obj1, obj2) + + require.True(t, x.AssertObject(obj1)) + require.True(t, x.AssertObject(obj2)) + require.False(t, x.AssertObject(objOther)) +} + +func TestObject_InvalidAt(t *testing.T) { + var x session.Object + + nbf := rand.Uint64() + if nbf == math.MaxUint64 { + nbf-- + } + + iat := nbf + exp := iat + 1 + + x.SetNbf(nbf) + x.SetIat(iat) + x.SetExp(exp) + + require.True(t, x.InvalidAt(nbf-1)) + require.True(t, x.InvalidAt(iat-1)) + require.False(t, x.InvalidAt(iat)) + require.False(t, x.InvalidAt(exp)) + require.True(t, x.InvalidAt(exp+1)) +} + +func TestObject_ID(t *testing.T) { + var x session.Object + + require.Zero(t, x.ID()) + + id := uuid.New() + + x.SetID(id) + + require.Equal(t, id, x.ID()) +} + +func TestObject_AssertAuthKey(t *testing.T) { + var x session.Object + + key := randPublicKey() + + require.False(t, x.AssertAuthKey(key)) + + x.SetAuthKey(key) + + require.True(t, x.AssertAuthKey(key)) +} + +func TestObject_ForVerb(t *testing.T) { + var val session.Object + var m v2session.Token + filled := sessiontest.Object() + + assertDefaults := func() { + cCnr, ok := m.GetBody().GetContext().(*v2session.ObjectSessionContext) + require.True(t, ok) + require.Zero(t, cCnr.GetVerb()) + } + + assertBinary := func(baseAssert func()) { + val2 := filled + + require.NoError(t, val2.Unmarshal(val.Marshal())) + baseAssert() + } + + assertJSON := func(baseAssert func()) { + val2 := filled + + jd, err := val.MarshalJSON() + require.NoError(t, err) + + require.NoError(t, val2.UnmarshalJSON(jd)) + baseAssert() + } + + val.WriteToV2(&m) + + assertDefaults() + assertBinary(assertDefaults) + assertJSON(assertDefaults) + + // set value + + assertVerb := func(verb v2session.ObjectSessionVerb) { + cCnr, ok := m.GetBody().GetContext().(*v2session.ObjectSessionContext) + require.True(t, ok) + require.Equal(t, verb, cCnr.GetVerb()) + } + + for from, to := range map[session.ObjectVerb]v2session.ObjectSessionVerb{ + session.VerbObjectPut: v2session.ObjectVerbPut, + session.VerbObjectGet: v2session.ObjectVerbGet, + session.VerbObjectHead: v2session.ObjectVerbHead, + session.VerbObjectSearch: v2session.ObjectVerbSearch, + session.VerbObjectRangeHash: v2session.ObjectVerbRangeHash, + session.VerbObjectRange: v2session.ObjectVerbRange, + session.VerbObjectDelete: v2session.ObjectVerbDelete, + } { + val.ForVerb(from) + + val.WriteToV2(&m) + + assertVerb(to) + assertBinary(func() { assertVerb(to) }) + assertJSON(func() { assertVerb(to) }) + } +} + +func TestObject_AssertVerb(t *testing.T) { + var x session.Object + + const v1, v2 = session.VerbObjectGet, session.VerbObjectPut + + require.False(t, x.AssertVerb(v1, v2)) + + x.ForVerb(v1) + require.True(t, x.AssertVerb(v1)) + require.False(t, x.AssertVerb(v2)) + require.True(t, x.AssertVerb(v1, v2)) + require.True(t, x.AssertVerb(v2, v1)) +} + +func TestObject_Issuer(t *testing.T) { + var token session.Object + signer := randSigner() + + require.Zero(t, token.Issuer()) + + require.NoError(t, token.Sign(signer)) + + var issuer user.ID + + user.IDFromKey(&issuer, signer.PublicKey) + + require.True(t, token.Issuer().Equals(issuer)) +} + +func TestObject_Sign(t *testing.T) { + val := sessiontest.Object() + + require.NoError(t, val.Sign(randSigner())) + + require.True(t, val.VerifySignature()) +} diff --git a/pkg/sdk/session/test/doc.go b/pkg/sdk/session/test/doc.go new file mode 100644 index 000000000..6c326cfec --- /dev/null +++ b/pkg/sdk/session/test/doc.go @@ -0,0 +1,13 @@ +/* +Package sessiontest provides functions for convenient testing of session package API. + +Note that importing the package into source files is highly discouraged. + +Random instance generation functions can be useful when testing expects any value, e.g.: + + import sessiontest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/session/test" + + val := sessiontest.Container() + // test the value +*/ +package sessiontest diff --git a/pkg/sdk/session/test/session.go b/pkg/sdk/session/test/session.go new file mode 100644 index 000000000..f1ad29ec5 --- /dev/null +++ b/pkg/sdk/session/test/session.go @@ -0,0 +1,98 @@ +package sessiontest + +import ( + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/crypto/ecdsa" + oidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id/test" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/session" + "github.com/google/uuid" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" +) + +var p ecdsa.PrivateKey + +func init() { + k, err := keys.NewPrivateKey() + if err != nil { + panic(err) + } + + p = k.PrivateKey +} + +// Container returns random session.Container. +// +// Resulting token is unsigned. +func Container() *session.Container { + var tok session.Container + + priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + panic(err) + } + + tok.ForVerb(session.VerbContainerPut) + tok.ApplyOnlyTo(cidtest.ID()) + tok.SetID(uuid.New()) + tok.SetAuthKey((*frostfsecdsa.PublicKey)(&priv.PublicKey)) + tok.SetExp(11) + tok.SetNbf(22) + tok.SetIat(33) + + return &tok +} + +// ContainerSigned returns signed random session.Container. +// +// Panics if token could not be signed (actually unexpected). +func ContainerSigned() *session.Container { + tok := Container() + + err := tok.Sign(p) + if err != nil { + panic(err) + } + + return tok +} + +// Object returns random session.Object. +// +// Resulting token is unsigned. +func Object() *session.Object { + var tok session.Object + + priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + panic(err) + } + + tok.ForVerb(session.VerbObjectPut) + tok.BindContainer(cidtest.ID()) + tok.LimitByObjects(oidtest.ID(), oidtest.ID()) + tok.SetID(uuid.New()) + tok.SetAuthKey((*frostfsecdsa.PublicKey)(&priv.PublicKey)) + tok.SetExp(11) + tok.SetNbf(22) + tok.SetIat(33) + + return &tok +} + +// ObjectSigned returns signed random session.Object. +// +// Panics if token could not be signed (actually unexpected). +func ObjectSigned() *session.Object { + tok := Object() + + err := tok.Sign(p) + if err != nil { + panic(err) + } + + return tok +} diff --git a/pkg/sdk/syncTree.sh b/pkg/sdk/syncTree.sh new file mode 100755 index 000000000..90eeba72d --- /dev/null +++ b/pkg/sdk/syncTree.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +REVISION="b3695411d907c3c65485bab04f9ff8479a72906b" + +echo "tree service revision ${REVISION}" + +# regexp below find all link to source code files which end with ".pb.go" and retrieve the file names +# we use `[^.]*` as non greedy workaround for `.*` +FILES=$(curl -s https://git.frostfs.info/TrueCloudLab/frostfs-node/src/commit/${REVISION}/pkg/services/tree | sed -n "s,.*\"/TrueCloudLab/frostfs-node/src/commit/${REVISION}/pkg/services/tree/\([^.]*\.pb\.go\)\".*,\1,p") + +for file in $FILES; do + if [[ $file == *"frostfs"* ]]; then + echo "skip '$file'" + continue + else + echo "sync '$file' in tree service" + fi + curl -s "https://git.frostfs.info/TrueCloudLab/frostfs-node/raw/commit/${REVISION}/pkg/services/tree/${file}" -o "./pool/tree/service/${file}" +done diff --git a/pkg/sdk/user/doc.go b/pkg/sdk/user/doc.go new file mode 100644 index 000000000..5f6b2508c --- /dev/null +++ b/pkg/sdk/user/doc.go @@ -0,0 +1,60 @@ +/* +Package user provides functionality related to FrostFS users. + +User identity is reflected in ID type. Each user has its own unique identifier +within the same network. + +FrostFS user identification is compatible with Neo accounts: + + import "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + import "github.com/nspcc-dev/neo-go/pkg/crypto/hash" + + var id user.ID + + var scriptHash util.Uint160 // user account in FrostFS + id.SetScriptHash(scriptHash) + + var key keys.PublicKey // user's public key + user.IDFromKey(&id, k.PrivateKey.PublicKey) + +ID is compatible with the FrostFS Smart Contract API: + + var id user.ID + // ... + + wallet := id.WalletBytes() + + // use wallet in call + +Encoding/decoding mechanisms are used to transfer identifiers: + + var id user.ID + // ... + + s := id.EncodeToString() // on transmitter + err = id.DecodeString(s) // on receiver + +Instances can be also used to process FrostFS API protocol messages +(see neo.fs.v2.refs package in https://git.frostfs.info/TrueCloudLab/frostfs-api). + +On client side: + + import "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + + var msg refs.OwnerID + id.WriteToV2(&msg) + + // send msg + +On server side: + + // recv msg + + var id user.ID + + err := id.ReadFromV2(msg) + // ... + + // process id +*/ +package user diff --git a/pkg/sdk/user/id.go b/pkg/sdk/user/id.go new file mode 100644 index 000000000..3244491df --- /dev/null +++ b/pkg/sdk/user/id.go @@ -0,0 +1,130 @@ +package user + +import ( + "bytes" + "errors" + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + "github.com/mr-tron/base58" + "github.com/nspcc-dev/neo-go/pkg/crypto/hash" + "github.com/nspcc-dev/neo-go/pkg/encoding/address" + "github.com/nspcc-dev/neo-go/pkg/util" +) + +const idSize = 25 + +var zeroSlice = bytes.Repeat([]byte{0}, idSize) + +// ID identifies users of the FrostFS system. +// +// ID is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs.OwnerID +// message. See ReadFromV2 / WriteToV2 methods. +// +// Instances can be created using built-in var declaration. Zero ID is not valid, +// so it MUST be initialized using some modifying function (e.g. SetScriptHash, +// IDFromKey, etc.). +type ID struct { + w []byte +} + +// ReadFromV2 reads ID from the refs.OwnerID message. Returns an error if +// the message is malformed according to the FrostFS API V2 protocol. +// +// See also WriteToV2. +func (x *ID) ReadFromV2(m refs.OwnerID) error { + w := m.GetValue() + if len(w) != idSize { + return fmt.Errorf("invalid length %d, expected %d", len(w), idSize) + } + + if w[0] != address.NEO3Prefix { + return fmt.Errorf("invalid prefix byte 0x%X, expected 0x%X", w[0], address.NEO3Prefix) + } + + if !bytes.Equal(w[21:], hash.Checksum(w[:21])) { + return errors.New("checksum mismatch") + } + + x.w = w + + return nil +} + +// WriteToV2 writes ID to the refs.OwnerID message. +// The message must not be nil. +// +// See also ReadFromV2. +func (x ID) WriteToV2(m *refs.OwnerID) { + m.SetValue(x.w) +} + +// SetScriptHash forms user ID from wallet address scripthash. +func (x *ID) SetScriptHash(scriptHash util.Uint160) { + if cap(x.w) < idSize { + x.w = make([]byte, idSize) + } else if len(x.w) < idSize { + x.w = x.w[:idSize] + } + + x.w[0] = address.Prefix + copy(x.w[1:], scriptHash.BytesBE()) + copy(x.w[21:], hash.Checksum(x.w[:21])) +} + +// ScriptHash calculates and returns script hash of ID. +func (x *ID) ScriptHash() (util.Uint160, error) { + return util.Uint160DecodeBytesBE(x.w[1:21]) +} + +// WalletBytes returns FrostFS user ID as Neo3 wallet address in a binary format. +// +// Return value MUST NOT be mutated: to do this, first make a copy. +// +// See also Neo3 wallet docs. +func (x ID) WalletBytes() []byte { + return x.w +} + +// EncodeToString encodes ID into FrostFS API V2 protocol string. +// +// See also DecodeString. +func (x ID) EncodeToString() string { + return base58.Encode(x.w) +} + +// DecodeString decodes FrostFS API V2 protocol string. Returns an error +// if s is malformed. +// +// DecodeString always changes the ID. +// +// See also EncodeToString. +func (x *ID) DecodeString(s string) error { + var err error + + x.w, err = base58.Decode(s) + if err != nil { + return fmt.Errorf("decode base58: %w", err) + } + + return nil +} + +// String implements fmt.Stringer. +// +// String is designed to be human-readable, and its format MAY differ between +// SDK versions. String MAY return same result as EncodeToString. String MUST NOT +// be used to encode ID into FrostFS protocol string. +func (x ID) String() string { + return x.EncodeToString() +} + +// Equals defines a comparison relation between two ID instances. +func (x ID) Equals(x2 ID) bool { + return bytes.Equal(x.w, x2.w) +} + +// IsEmpty returns True, if ID is empty value. +func (x ID) IsEmpty() bool { + return bytes.Equal(zeroSlice, x.w) +} diff --git a/pkg/sdk/user/id_test.go b/pkg/sdk/user/id_test.go new file mode 100644 index 000000000..8d1c665fa --- /dev/null +++ b/pkg/sdk/user/id_test.go @@ -0,0 +1,135 @@ +package user_test + +import ( + "crypto/rand" + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + . "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" + usertest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user/test" + "github.com/mr-tron/base58" + "github.com/nspcc-dev/neo-go/pkg/encoding/address" + "github.com/nspcc-dev/neo-go/pkg/util" + "github.com/nspcc-dev/neo-go/pkg/util/slice" + "github.com/stretchr/testify/require" +) + +func TestID_WalletBytes(t *testing.T) { + var scriptHash util.Uint160 + rand.Read(scriptHash[:]) + + var id ID + id.SetScriptHash(scriptHash) + + w := id.WalletBytes() + + var m refs.OwnerID + m.SetValue(w) + + err := id.ReadFromV2(m) + require.NoError(t, err) +} + +func TestID_SetScriptHash(t *testing.T) { + var scriptHash util.Uint160 + rand.Read(scriptHash[:]) + + var id ID + id.SetScriptHash(scriptHash) + + var m refs.OwnerID + id.WriteToV2(&m) + + var id2 ID + + err := id2.ReadFromV2(m) + require.NoError(t, err) + + require.True(t, id2.Equals(id)) +} + +func TestID_ScriptHash(t *testing.T) { + userID := usertest.ID() + + scriptHash, err := userID.ScriptHash() + require.NoError(t, err) + + ownerAddress := userID.EncodeToString() + decodedScriptHash, err := address.StringToUint160(ownerAddress) + require.NoError(t, err) + + require.True(t, scriptHash.Equals(decodedScriptHash)) +} + +func TestV2_ID(t *testing.T) { + id := usertest.ID() + var m refs.OwnerID + var id2 ID + + t.Run("OK", func(t *testing.T) { + id.WriteToV2(&m) + + err := id2.ReadFromV2(m) + require.NoError(t, err) + require.True(t, id2.Equals(id)) + }) + + val := m.GetValue() + + t.Run("invalid size", func(t *testing.T) { + m.SetValue(val[:24]) + + err := id2.ReadFromV2(m) + require.Error(t, err) + }) + + t.Run("invalid prefix", func(t *testing.T) { + val := slice.Copy(val) + val[0]++ + + m.SetValue(val) + + err := id2.ReadFromV2(m) + require.Error(t, err) + }) + + t.Run("invalid checksum", func(t *testing.T) { + val := slice.Copy(val) + val[21]++ + + m.SetValue(val) + + err := id2.ReadFromV2(m) + require.Error(t, err) + }) +} + +func TestID_EncodeToString(t *testing.T) { + id := usertest.ID() + + s := id.EncodeToString() + + _, err := base58.Decode(s) + require.NoError(t, err) + + var id2 ID + + err = id2.DecodeString(s) + require.NoError(t, err) + + require.Equal(t, id, id2) + + err = id2.DecodeString("_") // any invalid bas58 string + require.Error(t, err) +} + +func TestID_Equal(t *testing.T) { + id1 := usertest.ID() + id2 := usertest.ID() + id3 := id1 + + require.True(t, id1.Equals(id1)) // self-equality + require.True(t, id1.Equals(id3)) + require.True(t, id3.Equals(id1)) // commutativity + require.False(t, id1.Equals(id2)) +} diff --git a/pkg/sdk/user/test/doc.go b/pkg/sdk/user/test/doc.go new file mode 100644 index 000000000..e8ddf346b --- /dev/null +++ b/pkg/sdk/user/test/doc.go @@ -0,0 +1,13 @@ +/* +Package usertest provides functions for convenient testing of user package API. + +Note that importing the package into source files is highly discouraged. + +Random instance generation functions can be useful when testing expects any value, e.g.: + + import usertest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user/test" + + id := usertest.ID() + // test the value +*/ +package usertest diff --git a/pkg/sdk/user/test/id.go b/pkg/sdk/user/test/id.go new file mode 100644 index 000000000..cc79e0c4e --- /dev/null +++ b/pkg/sdk/user/test/id.go @@ -0,0 +1,19 @@ +package usertest + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" +) + +// ID returns random user.ID. +func ID() user.ID { + key, err := keys.NewPrivateKey() + if err != nil { + panic(err) + } + + var x user.ID + user.IDFromKey(&x, key.PrivateKey.PublicKey) + + return x +} diff --git a/pkg/sdk/user/util.go b/pkg/sdk/user/util.go new file mode 100644 index 000000000..ddd9657a2 --- /dev/null +++ b/pkg/sdk/user/util.go @@ -0,0 +1,12 @@ +package user + +import ( + "crypto/ecdsa" + + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" +) + +// IDFromKey forms the ID using script hash calculated for the given key. +func IDFromKey(id *ID, key ecdsa.PublicKey) { + id.SetScriptHash((*keys.PublicKey)(&key).GetScriptHash()) +} diff --git a/pkg/sdk/user/util_test.go b/pkg/sdk/user/util_test.go new file mode 100644 index 000000000..74f294383 --- /dev/null +++ b/pkg/sdk/user/util_test.go @@ -0,0 +1,24 @@ +package user_test + +import ( + "crypto/ecdsa" + "crypto/elliptic" + "encoding/hex" + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" + "github.com/stretchr/testify/require" +) + +func TestIDFromKey(t *testing.T) { + // examples are taken from https://docs.neo.org/docs/en-us/basic/concept/wallets.html + rawPub, _ := hex.DecodeString("03cdb067d930fd5adaa6c68545016044aaddec64ba39e548250eaea551172e535c") + x, y := elliptic.UnmarshalCompressed(elliptic.P256(), rawPub) + require.True(t, x != nil && y != nil) + + var id user.ID + + user.IDFromKey(&id, ecdsa.PublicKey{Curve: elliptic.P256(), X: x, Y: y}) + + require.Equal(t, "NNLi44dJNXtDNSBkofB48aTVYtb1zZrNEs", id.EncodeToString()) +} diff --git a/pkg/sdk/version/doc.go b/pkg/sdk/version/doc.go new file mode 100644 index 000000000..8ade1a522 --- /dev/null +++ b/pkg/sdk/version/doc.go @@ -0,0 +1,18 @@ +/* +Package version provides functionality for FrostFS versioning. + +FrostFS uses FrostFS API versioning scheme. It uses major and minor version of +the API. + +In most of the cases it will be enough to use the latest supported FrostFS API +version in SDK: + + ver := version.Current() + +It is possible to specify arbitrary version by setting major and minor numbers: + + var ver version.Version + ver.SetMajor(2) + ver.SetMinor(5) +*/ +package version diff --git a/pkg/sdk/version/test/doc.go b/pkg/sdk/version/test/doc.go new file mode 100644 index 000000000..04266e997 --- /dev/null +++ b/pkg/sdk/version/test/doc.go @@ -0,0 +1,6 @@ +/* +Package versiontest provides functions for testing version package. + +Note that this package intended only for tests. +*/ +package versiontest diff --git a/pkg/sdk/version/test/generate.go b/pkg/sdk/version/test/generate.go new file mode 100644 index 000000000..6094119aa --- /dev/null +++ b/pkg/sdk/version/test/generate.go @@ -0,0 +1,14 @@ +package versiontest + +import ( + "math/rand" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/version" +) + +// Version returns random version.Version. +func Version() (v version.Version) { + v.SetMajor(rand.Uint32()) + v.SetMinor(rand.Uint32()) + return v +} diff --git a/pkg/sdk/version/version.go b/pkg/sdk/version/version.go new file mode 100644 index 000000000..4d7623648 --- /dev/null +++ b/pkg/sdk/version/version.go @@ -0,0 +1,86 @@ +package version + +import ( + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" +) + +// Version represents revision number in SemVer scheme. +// +// Version is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs.Version +// message. See ReadFromV2 / WriteToV2 methods. +// +// Instances can be created using built-in var declaration. +// +// Note that direct typecast is not safe and may result in loss of compatibility: +// +// _ = Version(refs.Version{}) // not recommended +type Version refs.Version + +const sdkMjr, sdkMnr = 2, 13 + +// Current returns Version instance that initialized to the +// latest supported FrostFS API revision number in SDK. +func Current() (v Version) { + v.SetMajor(sdkMjr) + v.SetMinor(sdkMnr) + return v +} + +// Major returns major number of the revision. +func (v *Version) Major() uint32 { + return (*refs.Version)(v).GetMajor() +} + +// SetMajor sets major number of the revision. +func (v *Version) SetMajor(val uint32) { + (*refs.Version)(v).SetMajor(val) +} + +// Minor returns minor number of the revision. +func (v *Version) Minor() uint32 { + return (*refs.Version)(v).GetMinor() +} + +// SetMinor sets minor number of the revision. +func (v *Version) SetMinor(val uint32) { + (*refs.Version)(v).SetMinor(val) +} + +// WriteToV2 writes Version to the refs.Version message. +// The message must not be nil. +// +// See also ReadFromV2. +func (v Version) WriteToV2(m *refs.Version) { + *m = (refs.Version)(v) +} + +// ReadFromV2 reads Version from the refs.Version message. Checks if the message +// conforms to FrostFS API V2 protocol. +// +// See also WriteToV2. +func (v *Version) ReadFromV2(m refs.Version) error { + *v = Version(m) + return nil +} + +// String implements fmt.Stringer. +// +// String is designed to be human-readable, and its format MAY differ between +// SDK versions. +func (v Version) String() string { + return EncodeToString(v) +} + +// EncodeToString encodes version according to format from specification: +// semver formatted value without patch and with v prefix, e.g. 'v2.1'. +func EncodeToString(v Version) string { + return fmt.Sprintf("v%d.%d", v.Major(), v.Minor()) +} + +// Equal returns true if versions are identical. +func (v Version) Equal(v2 Version) bool { + return v.Major() == v2.Major() && + v.Minor() == v2.Minor() +} diff --git a/pkg/sdk/version/version_test.go b/pkg/sdk/version/version_test.go new file mode 100644 index 000000000..b1ba8850c --- /dev/null +++ b/pkg/sdk/version/version_test.go @@ -0,0 +1,50 @@ +package version + +import ( + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + "github.com/stretchr/testify/require" +) + +func TestNewVersion(t *testing.T) { + t.Run("default values", func(t *testing.T) { + var v Version + + // check initial values + require.Zero(t, v.Major()) + require.Zero(t, v.Minor()) + + // convert to v2 message + var vV2 refs.Version + v.WriteToV2(&vV2) + + require.Zero(t, vV2.GetMajor()) + require.Zero(t, vV2.GetMinor()) + }) + + t.Run("setting values", func(t *testing.T) { + var v Version + + var mjr, mnr uint32 = 1, 2 + + v.SetMajor(mjr) + v.SetMinor(mnr) + require.Equal(t, mjr, v.Major()) + require.Equal(t, mnr, v.Minor()) + + // convert to v2 message + var ver refs.Version + v.WriteToV2(&ver) + + require.Equal(t, mjr, ver.GetMajor()) + require.Equal(t, mnr, ver.GetMinor()) + }) +} + +func TestSDKVersion(t *testing.T) { + v := Current() + + require.Equal(t, uint32(sdkMjr), v.Major()) + require.Equal(t, uint32(sdkMnr), v.Minor()) +} diff --git a/pkg/services/accounting/executor.go b/pkg/services/accounting/executor.go index b0722cf8a..217b29d42 100644 --- a/pkg/services/accounting/executor.go +++ b/pkg/services/accounting/executor.go @@ -4,7 +4,7 @@ import ( "context" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/accounting" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/accounting" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util/response" ) diff --git a/pkg/services/accounting/morph/executor.go b/pkg/services/accounting/morph/executor.go index ac836b71d..0b6378ce5 100644 --- a/pkg/services/accounting/morph/executor.go +++ b/pkg/services/accounting/morph/executor.go @@ -5,10 +5,10 @@ import ( "errors" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/accounting" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/accounting" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/balance" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" accountingSvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/accounting" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" ) type morphExecutor struct { diff --git a/pkg/services/accounting/server.go b/pkg/services/accounting/server.go index 72833c46c..c787141a4 100644 --- a/pkg/services/accounting/server.go +++ b/pkg/services/accounting/server.go @@ -3,7 +3,7 @@ package accounting import ( "context" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/accounting" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/accounting" ) // Server is an interface of the FrostFS API Accounting service server. diff --git a/pkg/services/accounting/sign.go b/pkg/services/accounting/sign.go index cd6ff0307..6fc6f08fe 100644 --- a/pkg/services/accounting/sign.go +++ b/pkg/services/accounting/sign.go @@ -4,7 +4,7 @@ import ( "context" "crypto/ecdsa" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/accounting" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/accounting" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util" ) diff --git a/pkg/services/container/ape.go b/pkg/services/container/ape.go index 83361257a..6f4adad16 100644 --- a/pkg/services/container/ape.go +++ b/pkg/services/container/ape.go @@ -11,19 +11,19 @@ import ( "fmt" "strings" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" - session "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" "git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/container" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + session "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" containercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + cnrSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" + sessionSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" - cnrSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" - sessionSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" policyengine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" "git.frostfs.info/TrueCloudLab/policy-engine/pkg/resource" diff --git a/pkg/services/container/ape_test.go b/pkg/services/container/ape_test.go index 1af59d1c6..ac8c5ae60 100644 --- a/pkg/services/container/ape_test.go +++ b/pkg/services/container/ape_test.go @@ -8,21 +8,21 @@ import ( "fmt" "testing" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" - session "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature" "git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/acl" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/container" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + session "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/signature" containercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" - cnrSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" - containertest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/test" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" - sessiontest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session/test" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + cnrSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + containertest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/test" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" + sessiontest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/session/test" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine/inmemory" diff --git a/pkg/services/container/executor.go b/pkg/services/container/executor.go index d4ae11d62..b19199a09 100644 --- a/pkg/services/container/executor.go +++ b/pkg/services/container/executor.go @@ -4,8 +4,8 @@ import ( "context" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/container" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util/response" ) diff --git a/pkg/services/container/morph/executor.go b/pkg/services/container/morph/executor.go index a653fa066..1519b7968 100644 --- a/pkg/services/container/morph/executor.go +++ b/pkg/services/container/morph/executor.go @@ -5,15 +5,15 @@ import ( "errors" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" - sessionV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/container" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + sessionV2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" containercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + eaclSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/eacl" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" containerSvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/container" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - eaclSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" ) var errMissingUserID = errors.New("missing user ID") diff --git a/pkg/services/container/morph/executor_test.go b/pkg/services/container/morph/executor_test.go index 42dd0b77e..e0c1e4033 100644 --- a/pkg/services/container/morph/executor_test.go +++ b/pkg/services/container/morph/executor_test.go @@ -4,18 +4,18 @@ import ( "context" "testing" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/container" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" containerCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + containertest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/test" + frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/crypto" + frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/crypto/ecdsa" + sessiontest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/session/test" containerSvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/container" containerSvcMorph "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/container/morph" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" - containertest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/test" - frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto" - frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto/ecdsa" - sessiontest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session/test" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/stretchr/testify/require" ) diff --git a/pkg/services/container/server.go b/pkg/services/container/server.go index 052a8c945..8f8f22c6a 100644 --- a/pkg/services/container/server.go +++ b/pkg/services/container/server.go @@ -3,7 +3,7 @@ package container import ( "context" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/container" ) // Server is an interface of the FrostFS API Container service server. diff --git a/pkg/services/container/sign.go b/pkg/services/container/sign.go index bba717f60..53b47933a 100644 --- a/pkg/services/container/sign.go +++ b/pkg/services/container/sign.go @@ -4,7 +4,7 @@ import ( "context" "crypto/ecdsa" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util" ) diff --git a/pkg/services/control/convert.go b/pkg/services/control/convert.go index fd6f020d1..02406835e 100644 --- a/pkg/services/control/convert.go +++ b/pkg/services/control/convert.go @@ -1,8 +1,8 @@ package control import ( - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/grpc" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/message" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/message" ) type requestWrapper struct { diff --git a/pkg/services/control/ir/convert.go b/pkg/services/control/ir/convert.go index c892c5b6c..0d970771e 100644 --- a/pkg/services/control/ir/convert.go +++ b/pkg/services/control/ir/convert.go @@ -1,8 +1,8 @@ package control import ( - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/grpc" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/message" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/message" ) type requestWrapper struct { diff --git a/pkg/services/control/ir/rpc.go b/pkg/services/control/ir/rpc.go index 0c9400f6c..5d718a98d 100644 --- a/pkg/services/control/ir/rpc.go +++ b/pkg/services/control/ir/rpc.go @@ -1,9 +1,9 @@ package control import ( - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/common" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/grpc" ) const serviceName = "ircontrol.ControlService" diff --git a/pkg/services/control/ir/server/calls.go b/pkg/services/control/ir/server/calls.go index 2447a8a74..7ad00aacd 100644 --- a/pkg/services/control/ir/server/calls.go +++ b/pkg/services/control/ir/server/calls.go @@ -5,12 +5,12 @@ import ( "context" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" control "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/ir" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) diff --git a/pkg/services/control/ir/server/sign.go b/pkg/services/control/ir/server/sign.go index f72d51f9e..5facf5e59 100644 --- a/pkg/services/control/ir/server/sign.go +++ b/pkg/services/control/ir/server/sign.go @@ -6,10 +6,10 @@ import ( "errors" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/crypto" + frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/crypto/ecdsa" control "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/ir" - frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto" - frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto/ecdsa" ) // SignedMessage is an interface of Control service message. diff --git a/pkg/services/control/ir/service_frostfs.pb.go b/pkg/services/control/ir/service_frostfs.pb.go index e22d0013f..294ad791e 100644 --- a/pkg/services/control/ir/service_frostfs.pb.go +++ b/pkg/services/control/ir/service_frostfs.pb.go @@ -2,7 +2,7 @@ package control -import "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/proto" +import "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/util/proto" // StableSize returns the size of x in protobuf format. // diff --git a/pkg/services/control/ir/types_frostfs.pb.go b/pkg/services/control/ir/types_frostfs.pb.go index ef2fc458e..4689408ac 100644 --- a/pkg/services/control/ir/types_frostfs.pb.go +++ b/pkg/services/control/ir/types_frostfs.pb.go @@ -2,7 +2,7 @@ package control -import "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/proto" +import "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/util/proto" // StableSize returns the size of x in protobuf format. // diff --git a/pkg/services/control/rpc.go b/pkg/services/control/rpc.go index f9397c128..b527bede1 100644 --- a/pkg/services/control/rpc.go +++ b/pkg/services/control/rpc.go @@ -1,8 +1,8 @@ package control import ( - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/common" ) const serviceName = "control.ControlService" diff --git a/pkg/services/control/server/ape/validate.go b/pkg/services/control/server/ape/validate.go index f4aa0399f..56e446061 100644 --- a/pkg/services/control/server/ape/validate.go +++ b/pkg/services/control/server/ape/validate.go @@ -6,8 +6,8 @@ import ( "strings" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/ape" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" ) diff --git a/pkg/services/control/server/evacuate.go b/pkg/services/control/server/evacuate.go index 462ab211e..6747b7ce5 100644 --- a/pkg/services/control/server/evacuate.go +++ b/pkg/services/control/server/evacuate.go @@ -10,14 +10,14 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/replicator" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/tree" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" diff --git a/pkg/services/control/server/gc.go b/pkg/services/control/server/gc.go index d382dd7e5..d00009445 100644 --- a/pkg/services/control/server/gc.go +++ b/pkg/services/control/server/gc.go @@ -5,8 +5,8 @@ import ( "fmt" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) diff --git a/pkg/services/control/server/sign.go b/pkg/services/control/server/sign.go index acc405821..97a19c481 100644 --- a/pkg/services/control/server/sign.go +++ b/pkg/services/control/server/sign.go @@ -6,10 +6,10 @@ import ( "errors" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/crypto" + frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/crypto/ecdsa" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" - frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto" - frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto/ecdsa" ) // SignedMessage is an interface of Control service message. diff --git a/pkg/services/control/server/syncronize_tree.go b/pkg/services/control/server/syncronize_tree.go index 678f87d0a..41d312f34 100644 --- a/pkg/services/control/server/syncronize_tree.go +++ b/pkg/services/control/server/syncronize_tree.go @@ -3,10 +3,10 @@ package control import ( "context" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/tree" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) diff --git a/pkg/services/control/service_frostfs.pb.go b/pkg/services/control/service_frostfs.pb.go index 9d8d6376c..25cd64454 100644 --- a/pkg/services/control/service_frostfs.pb.go +++ b/pkg/services/control/service_frostfs.pb.go @@ -2,7 +2,7 @@ package control -import "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/proto" +import "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/util/proto" // StableSize returns the size of x in protobuf format. // diff --git a/pkg/services/control/types_frostfs.pb.go b/pkg/services/control/types_frostfs.pb.go index 858d85a1c..2cd417e78 100644 --- a/pkg/services/control/types_frostfs.pb.go +++ b/pkg/services/control/types_frostfs.pb.go @@ -2,7 +2,7 @@ package control -import "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/proto" +import "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/util/proto" // StableSize returns the size of x in protobuf format. // diff --git a/pkg/services/netmap/executor.go b/pkg/services/netmap/executor.go index 496b07a98..e25b2fa26 100644 --- a/pkg/services/netmap/executor.go +++ b/pkg/services/netmap/executor.go @@ -5,12 +5,12 @@ import ( "errors" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/version" + netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" + versionsdk "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/version" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util/response" - netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" - versionsdk "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/version" ) type executorSvc struct { diff --git a/pkg/services/netmap/server.go b/pkg/services/netmap/server.go index 0a09c9f44..6bf3d4afb 100644 --- a/pkg/services/netmap/server.go +++ b/pkg/services/netmap/server.go @@ -3,7 +3,7 @@ package netmap import ( "context" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/netmap" ) // Server is an interface of the FrostFS API Netmap service server. diff --git a/pkg/services/netmap/sign.go b/pkg/services/netmap/sign.go index 9a16ad8f1..0a7c48dd0 100644 --- a/pkg/services/netmap/sign.go +++ b/pkg/services/netmap/sign.go @@ -4,7 +4,7 @@ import ( "context" "crypto/ecdsa" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util" ) diff --git a/pkg/services/notificator/deps.go b/pkg/services/notificator/deps.go index d6330f788..983b79f60 100644 --- a/pkg/services/notificator/deps.go +++ b/pkg/services/notificator/deps.go @@ -3,7 +3,7 @@ package notificator import ( "context" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" ) // NotificationSource is a source of object notifications. diff --git a/pkg/services/notificator/nats/service.go b/pkg/services/notificator/nats/service.go index 9de538f2b..59bce68ba 100644 --- a/pkg/services/notificator/nats/service.go +++ b/pkg/services/notificator/nats/service.go @@ -7,8 +7,8 @@ import ( "sync" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "github.com/nats-io/nats.go" "go.uber.org/zap" ) diff --git a/pkg/services/notificator/service.go b/pkg/services/notificator/service.go index bbf4e4823..b8a7a77da 100644 --- a/pkg/services/notificator/service.go +++ b/pkg/services/notificator/service.go @@ -5,8 +5,8 @@ import ( "fmt" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.uber.org/zap" ) diff --git a/pkg/services/object/acl/acl.go b/pkg/services/object/acl/acl.go index 921545c8b..f135bfab0 100644 --- a/pkg/services/object/acl/acl.go +++ b/pkg/services/object/acl/acl.go @@ -11,17 +11,17 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" + bearerSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/bearer" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/acl" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/crypto/ecdsa" + eaclSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/eacl" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" eaclV2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/acl/eacl/v2" v2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/acl/v2" - bearerSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto/ecdsa" - eaclSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" ) diff --git a/pkg/services/object/acl/acl_test.go b/pkg/services/object/acl/acl_test.go index d63cb1285..0ae60cd0f 100644 --- a/pkg/services/object/acl/acl_test.go +++ b/pkg/services/object/acl/acl_test.go @@ -5,12 +5,12 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/acl" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + eaclSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/eacl" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" + usertest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user/test" v2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/acl/v2" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - eaclSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" - usertest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user/test" "github.com/stretchr/testify/require" ) diff --git a/pkg/services/object/acl/eacl/v2/eacl_test.go b/pkg/services/object/acl/eacl/v2/eacl_test.go index 023b99239..25569724a 100644 --- a/pkg/services/object/acl/eacl/v2/eacl_test.go +++ b/pkg/services/object/acl/eacl/v2/eacl_test.go @@ -6,13 +6,13 @@ import ( "errors" "testing" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - eaclSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" + eaclSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/eacl" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + oidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id/test" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/stretchr/testify/require" ) diff --git a/pkg/services/object/acl/eacl/v2/headers.go b/pkg/services/object/acl/eacl/v2/headers.go index 34975e1e6..66e3d4ba4 100644 --- a/pkg/services/object/acl/eacl/v2/headers.go +++ b/pkg/services/object/acl/eacl/v2/headers.go @@ -5,15 +5,15 @@ import ( "errors" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - refsV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - eaclSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/acl" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" + refsV2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + eaclSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/eacl" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" ) type Option func(*cfg) diff --git a/pkg/services/object/acl/eacl/v2/object.go b/pkg/services/object/acl/eacl/v2/object.go index 72bd4c2d2..608948e0d 100644 --- a/pkg/services/object/acl/eacl/v2/object.go +++ b/pkg/services/object/acl/eacl/v2/object.go @@ -3,11 +3,11 @@ package v2 import ( "strconv" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - eaclSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/acl" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + eaclSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/eacl" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" ) type sysObjHdr struct { diff --git a/pkg/services/object/acl/eacl/v2/opts.go b/pkg/services/object/acl/eacl/v2/opts.go index d91a21c75..e166258af 100644 --- a/pkg/services/object/acl/eacl/v2/opts.go +++ b/pkg/services/object/acl/eacl/v2/opts.go @@ -1,7 +1,7 @@ package v2 import ( - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" ) func WithOID(v *oid.ID) Option { diff --git a/pkg/services/object/acl/eacl/v2/xheader.go b/pkg/services/object/acl/eacl/v2/xheader.go index c1fdea9d8..d5731388d 100644 --- a/pkg/services/object/acl/eacl/v2/xheader.go +++ b/pkg/services/object/acl/eacl/v2/xheader.go @@ -1,8 +1,8 @@ package v2 import ( - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - eaclSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" + eaclSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/eacl" ) type XHeaderSource interface { diff --git a/pkg/services/object/acl/v2/errors.go b/pkg/services/object/acl/v2/errors.go index 11b9e6e5f..f7777d39b 100644 --- a/pkg/services/object/acl/v2/errors.go +++ b/pkg/services/object/acl/v2/errors.go @@ -3,7 +3,7 @@ package v2 import ( "fmt" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" ) const invalidRequestMessage = "malformed request" diff --git a/pkg/services/object/acl/v2/errors_test.go b/pkg/services/object/acl/v2/errors_test.go index 2d2b7bc8d..ff96fc874 100644 --- a/pkg/services/object/acl/v2/errors_test.go +++ b/pkg/services/object/acl/v2/errors_test.go @@ -4,7 +4,7 @@ import ( "errors" "testing" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" "github.com/stretchr/testify/require" ) diff --git a/pkg/services/object/acl/v2/request.go b/pkg/services/object/acl/v2/request.go index 74279e453..f42ac94c9 100644 --- a/pkg/services/object/acl/v2/request.go +++ b/pkg/services/object/acl/v2/request.go @@ -4,13 +4,13 @@ import ( "crypto/ecdsa" "fmt" - sessionV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - sessionSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" + sessionV2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/bearer" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/acl" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + sessionSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" ) diff --git a/pkg/services/object/acl/v2/service.go b/pkg/services/object/acl/v2/service.go index 1f1c275cf..4f1b9a02e 100644 --- a/pkg/services/object/acl/v2/service.go +++ b/pkg/services/object/acl/v2/service.go @@ -6,20 +6,20 @@ import ( "fmt" "strings" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" objectCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + cnrSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/acl" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + sessionSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" - cnrSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - sessionSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" "go.uber.org/zap" ) diff --git a/pkg/services/object/acl/v2/types.go b/pkg/services/object/acl/v2/types.go index 061cd26b6..cad47c142 100644 --- a/pkg/services/object/acl/v2/types.go +++ b/pkg/services/object/acl/v2/types.go @@ -1,7 +1,7 @@ package v2 import ( - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" ) // ACLChecker is an interface that must provide diff --git a/pkg/services/object/acl/v2/util.go b/pkg/services/object/acl/v2/util.go index feda6a3cf..ae4f4f74d 100644 --- a/pkg/services/object/acl/v2/util.go +++ b/pkg/services/object/acl/v2/util.go @@ -6,15 +6,15 @@ import ( "errors" "fmt" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - refsV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" - sessionV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - sessionSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" + refsV2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + sessionV2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/bearer" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/acl" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + sessionSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" ) diff --git a/pkg/services/object/acl/v2/util_test.go b/pkg/services/object/acl/v2/util_test.go index 394feef4e..56661845b 100644 --- a/pkg/services/object/acl/v2/util_test.go +++ b/pkg/services/object/acl/v2/util_test.go @@ -6,14 +6,14 @@ import ( "crypto/rand" "testing" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - bearertest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer/test" - aclsdk "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" - cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" - oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" - sessionSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" - sessiontest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session/test" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/acl" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" + bearertest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/bearer/test" + aclsdk "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/acl" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + oidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id/test" + sessionSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/session" + sessiontest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/session/test" "github.com/stretchr/testify/require" ) diff --git a/pkg/services/object/ape/checker.go b/pkg/services/object/ape/checker.go index 45efce5a7..3334996b4 100644 --- a/pkg/services/object/ape/checker.go +++ b/pkg/services/object/ape/checker.go @@ -5,10 +5,10 @@ import ( "errors" "fmt" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" policyengine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" diff --git a/pkg/services/object/ape/checker_test.go b/pkg/services/object/ape/checker_test.go index 443414959..3dd2d189e 100644 --- a/pkg/services/object/ape/checker_test.go +++ b/pkg/services/object/ape/checker_test.go @@ -6,12 +6,12 @@ import ( "fmt" "testing" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/checksum" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/version" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/checksum" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/version" "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" policyengine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine/inmemory" diff --git a/pkg/services/object/ape/errors.go b/pkg/services/object/ape/errors.go index 1b2024ed5..c01a3b3c7 100644 --- a/pkg/services/object/ape/errors.go +++ b/pkg/services/object/ape/errors.go @@ -1,7 +1,7 @@ package ape import ( - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" ) func toStatusErr(err error) error { diff --git a/pkg/services/object/ape/request.go b/pkg/services/object/ape/request.go index 3689bd178..930f6a352 100644 --- a/pkg/services/object/ape/request.go +++ b/pkg/services/object/ape/request.go @@ -5,12 +5,12 @@ import ( "fmt" "strconv" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/acl" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" aperesource "git.frostfs.info/TrueCloudLab/policy-engine/pkg/resource" nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" ) diff --git a/pkg/services/object/ape/request_test.go b/pkg/services/object/ape/request_test.go index c5b43fa8b..003bc9dc3 100644 --- a/pkg/services/object/ape/request_test.go +++ b/pkg/services/object/ape/request_test.go @@ -5,11 +5,11 @@ import ( "fmt" "testing" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - checksumtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/checksum/test" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" - usertest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user/test" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" + checksumtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/checksum/test" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" + usertest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user/test" nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" "github.com/stretchr/testify/require" ) diff --git a/pkg/services/object/ape/service.go b/pkg/services/object/ape/service.go index 0c203209d..74abdaa47 100644 --- a/pkg/services/object/ape/service.go +++ b/pkg/services/object/ape/service.go @@ -6,15 +6,15 @@ import ( "errors" "fmt" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" objectSvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" ) diff --git a/pkg/services/object/common.go b/pkg/services/object/common.go index 73ee9f81b..c5534f61e 100644 --- a/pkg/services/object/common.go +++ b/pkg/services/object/common.go @@ -3,8 +3,8 @@ package object import ( "context" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" ) // NodeState is storage node state processed by Object service. diff --git a/pkg/services/object/delete/exec.go b/pkg/services/object/delete/exec.go index d48f8ab7b..598ff5731 100644 --- a/pkg/services/object/delete/exec.go +++ b/pkg/services/object/delete/exec.go @@ -5,14 +5,14 @@ import ( "fmt" "strconv" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" + apiclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - apiclient "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.uber.org/zap" ) diff --git a/pkg/services/object/delete/local.go b/pkg/services/object/delete/local.go index 55ce4408d..28091773c 100644 --- a/pkg/services/object/delete/local.go +++ b/pkg/services/object/delete/local.go @@ -5,8 +5,8 @@ import ( "fmt" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" ) func (exec *execCtx) executeLocal(ctx context.Context) error { diff --git a/pkg/services/object/delete/prm.go b/pkg/services/object/delete/prm.go index 92eb5dcb6..43898e8f3 100644 --- a/pkg/services/object/delete/prm.go +++ b/pkg/services/object/delete/prm.go @@ -1,8 +1,8 @@ package deletesvc import ( + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" ) // TombstoneAddressWriter is an interface of tombstone address setter. diff --git a/pkg/services/object/delete/service.go b/pkg/services/object/delete/service.go index 0ba4da437..ad979abb5 100644 --- a/pkg/services/object/delete/service.go +++ b/pkg/services/object/delete/service.go @@ -4,14 +4,14 @@ import ( "context" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" getsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/get" putsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/put" searchsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/search" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" "go.uber.org/zap" ) diff --git a/pkg/services/object/delete/util.go b/pkg/services/object/delete/util.go index 439abca2b..2e709ea11 100644 --- a/pkg/services/object/delete/util.go +++ b/pkg/services/object/delete/util.go @@ -4,11 +4,11 @@ import ( "context" "errors" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" getsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/get" putsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/put" searchsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/search" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" ) type headSvcWrapper struct { diff --git a/pkg/services/object/delete/v2/service.go b/pkg/services/object/delete/v2/service.go index 10dcd0e87..6555f7158 100644 --- a/pkg/services/object/delete/v2/service.go +++ b/pkg/services/object/delete/v2/service.go @@ -3,7 +3,7 @@ package deletesvc import ( "context" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" deletesvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/delete" ) diff --git a/pkg/services/object/delete/v2/util.go b/pkg/services/object/delete/v2/util.go index d0db1f543..714521406 100644 --- a/pkg/services/object/delete/v2/util.go +++ b/pkg/services/object/delete/v2/util.go @@ -4,11 +4,11 @@ import ( "errors" "fmt" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" deletesvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/delete" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" ) type tombstoneBodyWriter struct { diff --git a/pkg/services/object/get/assemble.go b/pkg/services/object/get/assemble.go index 6a8c5c818..c17493336 100644 --- a/pkg/services/object/get/assemble.go +++ b/pkg/services/object/get/assemble.go @@ -5,9 +5,9 @@ import ( "errors" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "go.uber.org/zap" ) diff --git a/pkg/services/object/get/assembler.go b/pkg/services/object/get/assembler.go index f10c67e52..85fc707ad 100644 --- a/pkg/services/object/get/assembler.go +++ b/pkg/services/object/get/assembler.go @@ -4,9 +4,9 @@ import ( "context" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" ) type objectGetter interface { diff --git a/pkg/services/object/get/get.go b/pkg/services/object/get/get.go index 3d5547047..48db7793d 100644 --- a/pkg/services/object/get/get.go +++ b/pkg/services/object/get/get.go @@ -4,8 +4,8 @@ import ( "context" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "go.uber.org/zap" ) diff --git a/pkg/services/object/get/get_test.go b/pkg/services/object/get/get_test.go index 64614d8d8..ed03c58f6 100644 --- a/pkg/services/object/get/get_test.go +++ b/pkg/services/object/get/get_test.go @@ -13,18 +13,18 @@ import ( netmapcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" + clientSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" + netmaptest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap/test" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + oidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id/test" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" - clientSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" - netmaptest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap/test" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" "github.com/stretchr/testify/require" ) diff --git a/pkg/services/object/get/local.go b/pkg/services/object/get/local.go index 257465019..1ab6574b5 100644 --- a/pkg/services/object/get/local.go +++ b/pkg/services/object/get/local.go @@ -5,9 +5,9 @@ import ( "errors" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "go.uber.org/zap" ) diff --git a/pkg/services/object/get/prm.go b/pkg/services/object/get/prm.go index cbdb7a3e2..c09a70c04 100644 --- a/pkg/services/object/get/prm.go +++ b/pkg/services/object/get/prm.go @@ -6,9 +6,9 @@ import ( "hash" coreclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" ) // Prm groups parameters of Get service call. diff --git a/pkg/services/object/get/remote.go b/pkg/services/object/get/remote.go index cd94434cf..ec827c4f0 100644 --- a/pkg/services/object/get/remote.go +++ b/pkg/services/object/get/remote.go @@ -7,9 +7,9 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "go.uber.org/zap" ) diff --git a/pkg/services/object/get/request.go b/pkg/services/object/get/request.go index b9223a637..60a032eda 100644 --- a/pkg/services/object/get/request.go +++ b/pkg/services/object/get/request.go @@ -6,12 +6,12 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" clientcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.uber.org/zap" ) diff --git a/pkg/services/object/get/types.go b/pkg/services/object/get/types.go index a866132cc..b570da449 100644 --- a/pkg/services/object/get/types.go +++ b/pkg/services/object/get/types.go @@ -7,15 +7,15 @@ import ( coreclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/bearer" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/session" internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/internal/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" ) type epochSource interface { diff --git a/pkg/services/object/get/v2/errors.go b/pkg/services/object/get/v2/errors.go index 01b57f1f2..f328daf9c 100644 --- a/pkg/services/object/get/v2/errors.go +++ b/pkg/services/object/get/v2/errors.go @@ -4,8 +4,8 @@ import ( "errors" "fmt" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - refs "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" + refs "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" ) var ( diff --git a/pkg/services/object/get/v2/get_forwarder.go b/pkg/services/object/get/v2/get_forwarder.go index 40aa3f62e..3115560ce 100644 --- a/pkg/services/object/get/v2/get_forwarder.go +++ b/pkg/services/object/get/v2/get_forwarder.go @@ -7,17 +7,17 @@ import ( "io" "sync" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc" - rpcclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc" + rpcclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/signature" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/internal" internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/internal/client" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" ) diff --git a/pkg/services/object/get/v2/get_range_forwarder.go b/pkg/services/object/get/v2/get_range_forwarder.go index 8a56c59a6..1d4a59705 100644 --- a/pkg/services/object/get/v2/get_range_forwarder.go +++ b/pkg/services/object/get/v2/get_range_forwarder.go @@ -7,17 +7,17 @@ import ( "io" "sync" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc" - rpcclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc" + rpcclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/signature" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/internal" internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/internal/client" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" ) diff --git a/pkg/services/object/get/v2/get_range_hash.go b/pkg/services/object/get/v2/get_range_hash.go index 0054f0e9f..489771773 100644 --- a/pkg/services/object/get/v2/get_range_hash.go +++ b/pkg/services/object/get/v2/get_range_hash.go @@ -5,18 +5,18 @@ import ( "encoding/hex" "fmt" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc" - rpcclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc" + rpcclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/signature" clientCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" - netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.uber.org/zap" ) diff --git a/pkg/services/object/get/v2/head_forwarder.go b/pkg/services/object/get/v2/head_forwarder.go index a1bce1517..ec04f2d1f 100644 --- a/pkg/services/object/get/v2/head_forwarder.go +++ b/pkg/services/object/get/v2/head_forwarder.go @@ -5,19 +5,19 @@ import ( "crypto/ecdsa" "sync" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc" - rpcclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc" + rpcclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/signature" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" + frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/crypto" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/internal" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" ) diff --git a/pkg/services/object/get/v2/service.go b/pkg/services/object/get/v2/service.go index bcdc4120e..ecf6ad399 100644 --- a/pkg/services/object/get/v2/service.go +++ b/pkg/services/object/get/v2/service.go @@ -4,15 +4,15 @@ import ( "context" "errors" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" clientcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" objectSvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object" getsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/get" objutil "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "go.uber.org/zap" ) diff --git a/pkg/services/object/get/v2/streamer.go b/pkg/services/object/get/v2/streamer.go index ce9a5c767..041f51b5e 100644 --- a/pkg/services/object/get/v2/streamer.go +++ b/pkg/services/object/get/v2/streamer.go @@ -3,9 +3,9 @@ package getsvc import ( "context" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" objectSvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" ) type streamObjectWriter struct { diff --git a/pkg/services/object/get/v2/util.go b/pkg/services/object/get/v2/util.go index 7f7dd7480..0b138f18b 100644 --- a/pkg/services/object/get/v2/util.go +++ b/pkg/services/object/get/v2/util.go @@ -5,20 +5,20 @@ import ( "crypto/sha256" "hash" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/status" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/status" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" + clientSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + versionSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/version" objectSvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object" getsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/get" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" - clientSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - versionSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/version" "git.frostfs.info/TrueCloudLab/tzhash/tz" ) diff --git a/pkg/services/object/get/writer.go b/pkg/services/object/get/writer.go index 3aa4d66ac..3653ee416 100644 --- a/pkg/services/object/get/writer.go +++ b/pkg/services/object/get/writer.go @@ -4,7 +4,7 @@ import ( "context" "io" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" ) // ChunkWriter is an interface of target component diff --git a/pkg/services/object/head/prm.go b/pkg/services/object/head/prm.go index 5566e48fe..bf9321501 100644 --- a/pkg/services/object/head/prm.go +++ b/pkg/services/object/head/prm.go @@ -1,7 +1,7 @@ package headsvc import ( - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" ) type Prm struct { diff --git a/pkg/services/object/head/remote.go b/pkg/services/object/head/remote.go index c9c17d4d8..1b48439e8 100644 --- a/pkg/services/object/head/remote.go +++ b/pkg/services/object/head/remote.go @@ -7,11 +7,11 @@ import ( clientcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" netmapCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/internal/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" ) type ClientConstructor interface { diff --git a/pkg/services/object/internal/client/client.go b/pkg/services/object/internal/client/client.go index dd2de0fd1..4d8d93dd8 100644 --- a/pkg/services/object/internal/client/client.go +++ b/pkg/services/object/internal/client/client.go @@ -9,14 +9,14 @@ import ( "io" coreclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/bearer" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/session" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" ) type commonPrm struct { diff --git a/pkg/services/object/internal/key.go b/pkg/services/object/internal/key.go index eba716976..1a2e9e9d7 100644 --- a/pkg/services/object/internal/key.go +++ b/pkg/services/object/internal/key.go @@ -3,7 +3,7 @@ package internal import ( "bytes" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" ) diff --git a/pkg/services/object/metrics.go b/pkg/services/object/metrics.go index f972f43ae..8963d2e60 100644 --- a/pkg/services/object/metrics.go +++ b/pkg/services/object/metrics.go @@ -4,7 +4,7 @@ import ( "context" "time" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util" ) diff --git a/pkg/services/object/put/common.go b/pkg/services/object/put/common.go index 6696a192b..82b3fa3c0 100644 --- a/pkg/services/object/put/common.go +++ b/pkg/services/object/put/common.go @@ -7,9 +7,9 @@ import ( "sync/atomic" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" svcutil "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "go.uber.org/zap" ) diff --git a/pkg/services/object/put/distributed.go b/pkg/services/object/put/distributed.go index 509f4aee0..c0f7130cd 100644 --- a/pkg/services/object/put/distributed.go +++ b/pkg/services/object/put/distributed.go @@ -5,9 +5,9 @@ import ( "fmt" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/transformer" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/transformer" ) type preparedObjectTarget interface { diff --git a/pkg/services/object/put/local.go b/pkg/services/object/put/local.go index 54649adc7..ad1a83640 100644 --- a/pkg/services/object/put/local.go +++ b/pkg/services/object/put/local.go @@ -5,8 +5,8 @@ import ( "fmt" objectCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" ) // ObjectStorage is an object storage interface. diff --git a/pkg/services/object/put/prm.go b/pkg/services/object/put/prm.go index 52a7c102c..e136b0438 100644 --- a/pkg/services/object/put/prm.go +++ b/pkg/services/object/put/prm.go @@ -4,10 +4,10 @@ import ( "context" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" + containerSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" - containerSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" ) type PutInitPrm struct { diff --git a/pkg/services/object/put/remote.go b/pkg/services/object/put/remote.go index ee8d64e7a..270afff44 100644 --- a/pkg/services/object/put/remote.go +++ b/pkg/services/object/put/remote.go @@ -8,10 +8,10 @@ import ( clientcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" netmapCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" objectcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/internal/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) diff --git a/pkg/services/object/put/res.go b/pkg/services/object/put/res.go index c77e535fd..401d603f9 100644 --- a/pkg/services/object/put/res.go +++ b/pkg/services/object/put/res.go @@ -1,7 +1,7 @@ package putsvc import ( - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" ) type PutResponse struct { diff --git a/pkg/services/object/put/single.go b/pkg/services/object/put/single.go index 09e1eb092..5aeaa1f68 100644 --- a/pkg/services/object/put/single.go +++ b/pkg/services/object/put/single.go @@ -9,23 +9,23 @@ import ( "hash" "sync" - objectAPI "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc" - rawclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" - sessionV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + objectAPI "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc" + rawclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client" + sessionV2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/signature" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/checksum" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/internal" svcutil "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/checksum" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "git.frostfs.info/TrueCloudLab/tzhash/tz" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" diff --git a/pkg/services/object/put/streamer.go b/pkg/services/object/put/streamer.go index 90d580a1c..e522ecc20 100644 --- a/pkg/services/object/put/streamer.go +++ b/pkg/services/object/put/streamer.go @@ -8,13 +8,13 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" + containerSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/transformer" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" pkgutil "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" - containerSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/transformer" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" ) type Streamer struct { diff --git a/pkg/services/object/put/v2/service.go b/pkg/services/object/put/v2/service.go index db902ae59..bc29a3ca4 100644 --- a/pkg/services/object/put/v2/service.go +++ b/pkg/services/object/put/v2/service.go @@ -4,7 +4,7 @@ import ( "context" "fmt" - objectAPI "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + objectAPI "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object" putsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/put" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" diff --git a/pkg/services/object/put/v2/streamer.go b/pkg/services/object/put/v2/streamer.go index 9c6de4ca8..696e39244 100644 --- a/pkg/services/object/put/v2/streamer.go +++ b/pkg/services/object/put/v2/streamer.go @@ -4,11 +4,11 @@ import ( "context" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc" - rawclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" - sessionV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc" + rawclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client" + sessionV2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/signature" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/internal" diff --git a/pkg/services/object/put/v2/util.go b/pkg/services/object/put/v2/util.go index a157a9542..89ce40003 100644 --- a/pkg/services/object/put/v2/util.go +++ b/pkg/services/object/put/v2/util.go @@ -1,11 +1,11 @@ package putsvc import ( - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - refsV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" + refsV2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" putsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/put" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" ) func (s *streamer) toInitPrm(part *objectV2.PutObjectPartInit, req *objectV2.PutRequest) (*putsvc.PutInitPrm, error) { diff --git a/pkg/services/object/put/validation.go b/pkg/services/object/put/validation.go index c2b078ef5..fd2c9f357 100644 --- a/pkg/services/object/put/validation.go +++ b/pkg/services/object/put/validation.go @@ -9,9 +9,9 @@ import ( "hash" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/checksum" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/transformer" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/checksum" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/transformer" "git.frostfs.info/TrueCloudLab/tzhash/tz" ) diff --git a/pkg/services/object/request_context.go b/pkg/services/object/request_context.go index 6a0965b40..112335477 100644 --- a/pkg/services/object/request_context.go +++ b/pkg/services/object/request_context.go @@ -1,8 +1,8 @@ package object import ( - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/acl" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" ) type RequestContextKeyT struct{} diff --git a/pkg/services/object/response.go b/pkg/services/object/response.go index a10f26a34..2ed7031ae 100644 --- a/pkg/services/object/response.go +++ b/pkg/services/object/response.go @@ -4,7 +4,7 @@ import ( "context" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util/response" ) diff --git a/pkg/services/object/search/exec.go b/pkg/services/object/search/exec.go index 2e0d48773..031c1e140 100644 --- a/pkg/services/object/search/exec.go +++ b/pkg/services/object/search/exec.go @@ -1,10 +1,10 @@ package searchsvc import ( + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.uber.org/zap" ) diff --git a/pkg/services/object/search/prm.go b/pkg/services/object/search/prm.go index 95fe82e2f..028efec81 100644 --- a/pkg/services/object/search/prm.go +++ b/pkg/services/object/search/prm.go @@ -4,10 +4,10 @@ import ( "context" coreclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" ) // Prm groups parameters of Get service call. diff --git a/pkg/services/object/search/search_test.go b/pkg/services/object/search/search_test.go index 802fa33ef..153b812d0 100644 --- a/pkg/services/object/search/search_test.go +++ b/pkg/services/object/search/search_test.go @@ -9,21 +9,21 @@ import ( "strconv" "testing" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" clientcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" netmapcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/crypto/ecdsa" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + oidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id/test" + sessionsdk "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/session" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" - frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto/ecdsa" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" - sessionsdk "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" "github.com/google/uuid" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/stretchr/testify/require" diff --git a/pkg/services/object/search/service.go b/pkg/services/object/search/service.go index 0a54f54c5..c1528367e 100644 --- a/pkg/services/object/search/service.go +++ b/pkg/services/object/search/service.go @@ -6,11 +6,11 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.uber.org/zap" ) diff --git a/pkg/services/object/search/util.go b/pkg/services/object/search/util.go index 67b6c0d01..d1c14e5fc 100644 --- a/pkg/services/object/search/util.go +++ b/pkg/services/object/search/util.go @@ -6,9 +6,9 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/internal/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" ) type uniqueIDWriter struct { diff --git a/pkg/services/object/search/v2/request_forwarder.go b/pkg/services/object/search/v2/request_forwarder.go index 5a2e9b936..03d413899 100644 --- a/pkg/services/object/search/v2/request_forwarder.go +++ b/pkg/services/object/search/v2/request_forwarder.go @@ -8,15 +8,15 @@ import ( "io" "sync" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc" - rpcclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc" + rpcclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/rpc/client" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/signature" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/internal" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" ) type requestForwarder struct { diff --git a/pkg/services/object/search/v2/service.go b/pkg/services/object/search/v2/service.go index 78b72ac79..df349f98b 100644 --- a/pkg/services/object/search/v2/service.go +++ b/pkg/services/object/search/v2/service.go @@ -1,7 +1,7 @@ package searchsvc import ( - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" objectSvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object" searchsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/search" objutil "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" diff --git a/pkg/services/object/search/v2/streamer.go b/pkg/services/object/search/v2/streamer.go index 15e2d53d5..9e38aa001 100644 --- a/pkg/services/object/search/v2/streamer.go +++ b/pkg/services/object/search/v2/streamer.go @@ -1,10 +1,10 @@ package searchsvc import ( - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" objectSvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" ) type streamWriter struct { diff --git a/pkg/services/object/search/v2/util.go b/pkg/services/object/search/v2/util.go index e971fa8e5..e91b9dc94 100644 --- a/pkg/services/object/search/v2/util.go +++ b/pkg/services/object/search/v2/util.go @@ -5,15 +5,15 @@ import ( "errors" "fmt" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" objectSvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object" searchsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/search" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" ) func (s *Service) toPrm(req *objectV2.SearchRequest, stream objectSvc.SearchStream) (*searchsvc.Prm, error) { diff --git a/pkg/services/object/server.go b/pkg/services/object/server.go index 73b88f233..7cfd44495 100644 --- a/pkg/services/object/server.go +++ b/pkg/services/object/server.go @@ -3,7 +3,7 @@ package object import ( "context" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util" ) diff --git a/pkg/services/object/sign.go b/pkg/services/object/sign.go index 4bf581b78..52f40583e 100644 --- a/pkg/services/object/sign.go +++ b/pkg/services/object/sign.go @@ -5,7 +5,7 @@ import ( "crypto/ecdsa" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util" ) diff --git a/pkg/services/object/transport_splitter.go b/pkg/services/object/transport_splitter.go index 2d9810cd3..099d4eb98 100644 --- a/pkg/services/object/transport_splitter.go +++ b/pkg/services/object/transport_splitter.go @@ -4,7 +4,7 @@ import ( "bytes" "context" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util" ) diff --git a/pkg/services/object/util/chain.go b/pkg/services/object/util/chain.go index b574d5eb6..b535891cc 100644 --- a/pkg/services/object/util/chain.go +++ b/pkg/services/object/util/chain.go @@ -4,9 +4,9 @@ import ( "errors" "fmt" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" ) // HeadReceiver is an interface of entity that can receive diff --git a/pkg/services/object/util/key.go b/pkg/services/object/util/key.go index 8304bf13a..1e5934680 100644 --- a/pkg/services/object/util/key.go +++ b/pkg/services/object/util/key.go @@ -5,9 +5,9 @@ import ( "fmt" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/session/storage" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" "github.com/google/uuid" ) diff --git a/pkg/services/object/util/key_test.go b/pkg/services/object/util/key_test.go index cb7ddfde5..d22022bf6 100644 --- a/pkg/services/object/util/key_test.go +++ b/pkg/services/object/util/key_test.go @@ -5,14 +5,14 @@ import ( "crypto/elliptic" "testing" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" - sessionV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + sessionV2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" + frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/crypto/ecdsa" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" + usertest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user/test" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" tokenStorage "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/session/storage/temporary" - frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto/ecdsa" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" - usertest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user/test" "github.com/google/uuid" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/stretchr/testify/require" diff --git a/pkg/services/object/util/placement.go b/pkg/services/object/util/placement.go index 6cd3856f4..cfda1f0d5 100644 --- a/pkg/services/object/util/placement.go +++ b/pkg/services/object/util/placement.go @@ -6,10 +6,10 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" ) type localPlacement struct { diff --git a/pkg/services/object/util/prm.go b/pkg/services/object/util/prm.go index 022b9fe5b..8f9411cfb 100644 --- a/pkg/services/object/util/prm.go +++ b/pkg/services/object/util/prm.go @@ -4,9 +4,9 @@ import ( "fmt" "strconv" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" - sessionsdk "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/bearer" + sessionsdk "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/session" ) // maxLocalTTL is maximum TTL for an operation to be considered local. diff --git a/pkg/services/object_manager/placement/netmap.go b/pkg/services/object_manager/placement/netmap.go index 787c04421..004b533bf 100644 --- a/pkg/services/object_manager/placement/netmap.go +++ b/pkg/services/object_manager/placement/netmap.go @@ -6,9 +6,9 @@ import ( "sync" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "github.com/hashicorp/golang-lru/v2/simplelru" ) diff --git a/pkg/services/object_manager/placement/traverser.go b/pkg/services/object_manager/placement/traverser.go index 53da186e8..21eb996f8 100644 --- a/pkg/services/object_manager/placement/traverser.go +++ b/pkg/services/object_manager/placement/traverser.go @@ -6,10 +6,10 @@ import ( "sync" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" ) // Builder is an interface of the diff --git a/pkg/services/object_manager/placement/traverser_test.go b/pkg/services/object_manager/placement/traverser_test.go index f5731c81e..063aa6ad8 100644 --- a/pkg/services/object_manager/placement/traverser_test.go +++ b/pkg/services/object_manager/placement/traverser_test.go @@ -6,10 +6,10 @@ import ( netmapcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "github.com/stretchr/testify/require" ) diff --git a/pkg/services/object_manager/tombstone/checker.go b/pkg/services/object_manager/tombstone/checker.go index c3c810001..503f2d921 100644 --- a/pkg/services/object_manager/tombstone/checker.go +++ b/pkg/services/object_manager/tombstone/checker.go @@ -4,11 +4,11 @@ import ( "context" "strconv" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/object" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" lru "github.com/hashicorp/golang-lru/v2" "go.uber.org/zap" ) diff --git a/pkg/services/object_manager/tombstone/source/source.go b/pkg/services/object_manager/tombstone/source/source.go index 1ff07b05a..f4bc75ff6 100644 --- a/pkg/services/object_manager/tombstone/source/source.go +++ b/pkg/services/object_manager/tombstone/source/source.go @@ -4,11 +4,11 @@ import ( "context" "fmt" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" getsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/get" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" ) // Source represents wrapper over the object service that diff --git a/pkg/services/policer/check.go b/pkg/services/policer/check.go index bb6313d07..c7f7cfba4 100644 --- a/pkg/services/policer/check.go +++ b/pkg/services/policer/check.go @@ -8,12 +8,12 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" containercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" objectcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/replicator" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.uber.org/zap" ) diff --git a/pkg/services/policer/check_test.go b/pkg/services/policer/check_test.go index d4c7ccbf9..21931f64e 100644 --- a/pkg/services/policer/check_test.go +++ b/pkg/services/policer/check_test.go @@ -3,7 +3,7 @@ package policer import ( "testing" - netmaptest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap/test" + netmaptest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap/test" "github.com/stretchr/testify/require" ) diff --git a/pkg/services/policer/nodecache.go b/pkg/services/policer/nodecache.go index cd47cb0fc..34d4a0e3a 100644 --- a/pkg/services/policer/nodecache.go +++ b/pkg/services/policer/nodecache.go @@ -1,6 +1,6 @@ package policer -import "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" +import "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" type nodeProcessStatus int8 diff --git a/pkg/services/policer/option.go b/pkg/services/policer/option.go index 92cf83a84..80584143a 100644 --- a/pkg/services/policer/option.go +++ b/pkg/services/policer/option.go @@ -7,12 +7,12 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" objectcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" + netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/replicator" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "github.com/panjf2000/ants/v2" "go.uber.org/zap" ) diff --git a/pkg/services/policer/policer.go b/pkg/services/policer/policer.go index 363c0b922..cdb4efabc 100644 --- a/pkg/services/policer/policer.go +++ b/pkg/services/policer/policer.go @@ -4,8 +4,8 @@ import ( "sync" "time" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" lru "github.com/hashicorp/golang-lru/v2" "go.uber.org/zap" ) diff --git a/pkg/services/policer/policer_test.go b/pkg/services/policer/policer_test.go index 50f206fd9..ffbefa8ea 100644 --- a/pkg/services/policer/policer_test.go +++ b/pkg/services/policer/policer_test.go @@ -11,14 +11,14 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" objectcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" + oidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id/test" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/replicator" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" "github.com/panjf2000/ants/v2" "github.com/stretchr/testify/require" ) diff --git a/pkg/services/policer/process.go b/pkg/services/policer/process.go index a5ebb0010..fe0747963 100644 --- a/pkg/services/policer/process.go +++ b/pkg/services/policer/process.go @@ -8,7 +8,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" "go.uber.org/zap" ) diff --git a/pkg/services/replicator/process.go b/pkg/services/replicator/process.go index 3a46e5f04..9a3529f18 100644 --- a/pkg/services/replicator/process.go +++ b/pkg/services/replicator/process.go @@ -5,10 +5,10 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" putsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/put" tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" "go.uber.org/zap" diff --git a/pkg/services/replicator/task.go b/pkg/services/replicator/task.go index d2b5b2506..0c2027074 100644 --- a/pkg/services/replicator/task.go +++ b/pkg/services/replicator/task.go @@ -1,9 +1,9 @@ package replicator import ( - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/object/id" ) // Task represents group of Replicator task parameters. diff --git a/pkg/services/session/executor.go b/pkg/services/session/executor.go index 76c220fab..0f96f8c72 100644 --- a/pkg/services/session/executor.go +++ b/pkg/services/session/executor.go @@ -4,8 +4,8 @@ import ( "context" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util/response" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "go.uber.org/zap" diff --git a/pkg/services/session/server.go b/pkg/services/session/server.go index 9e44ae667..2814157d6 100644 --- a/pkg/services/session/server.go +++ b/pkg/services/session/server.go @@ -3,7 +3,7 @@ package session import ( "context" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" ) // Server is an interface of the FrostFS API Session service server. diff --git a/pkg/services/session/sign.go b/pkg/services/session/sign.go index 690fff896..e2d539fa8 100644 --- a/pkg/services/session/sign.go +++ b/pkg/services/session/sign.go @@ -4,7 +4,7 @@ import ( "context" "crypto/ecdsa" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util" ) diff --git a/pkg/services/session/storage/persistent/executor.go b/pkg/services/session/storage/persistent/executor.go index 21f55a7d1..56edf68b8 100644 --- a/pkg/services/session/storage/persistent/executor.go +++ b/pkg/services/session/storage/persistent/executor.go @@ -5,9 +5,9 @@ import ( "errors" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/session/storage" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "go.etcd.io/bbolt" ) diff --git a/pkg/services/session/storage/persistent/executor_test.go b/pkg/services/session/storage/persistent/executor_test.go index 39cb14359..39317cfbd 100644 --- a/pkg/services/session/storage/persistent/executor_test.go +++ b/pkg/services/session/storage/persistent/executor_test.go @@ -8,9 +8,9 @@ import ( "path/filepath" "testing" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - usertest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user/test" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" + usertest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user/test" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/stretchr/testify/require" "go.etcd.io/bbolt" diff --git a/pkg/services/session/storage/persistent/storage.go b/pkg/services/session/storage/persistent/storage.go index 71711e371..429924161 100644 --- a/pkg/services/session/storage/persistent/storage.go +++ b/pkg/services/session/storage/persistent/storage.go @@ -7,9 +7,9 @@ import ( "fmt" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/session/storage" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" "go.etcd.io/bbolt" "go.uber.org/zap" ) diff --git a/pkg/services/session/storage/temporary/executor.go b/pkg/services/session/storage/temporary/executor.go index cd498709c..f9d6d677c 100644 --- a/pkg/services/session/storage/temporary/executor.go +++ b/pkg/services/session/storage/temporary/executor.go @@ -5,9 +5,9 @@ import ( "errors" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/session/storage" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" "github.com/mr-tron/base58" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" ) diff --git a/pkg/services/session/storage/temporary/storage.go b/pkg/services/session/storage/temporary/storage.go index ee93dee71..144113ad7 100644 --- a/pkg/services/session/storage/temporary/storage.go +++ b/pkg/services/session/storage/temporary/storage.go @@ -3,8 +3,8 @@ package temporary import ( "sync" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/session/storage" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" "github.com/mr-tron/base58" ) diff --git a/pkg/services/tree/container.go b/pkg/services/tree/container.go index 435257550..0f1100c89 100644 --- a/pkg/services/tree/container.go +++ b/pkg/services/tree/container.go @@ -7,9 +7,9 @@ import ( "sync" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" + cidSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" - cidSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" "github.com/hashicorp/golang-lru/v2/simplelru" ) diff --git a/pkg/services/tree/drop.go b/pkg/services/tree/drop.go index a9e4e2e71..049058f6d 100644 --- a/pkg/services/tree/drop.go +++ b/pkg/services/tree/drop.go @@ -3,7 +3,7 @@ package tree import ( "context" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" ) // DropTree drops a tree from the database. If treeID is empty, all the trees are dropped. diff --git a/pkg/services/tree/getsubtree_test.go b/pkg/services/tree/getsubtree_test.go index 63cdc73a2..9467e9215 100644 --- a/pkg/services/tree/getsubtree_test.go +++ b/pkg/services/tree/getsubtree_test.go @@ -8,7 +8,7 @@ import ( "testing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" - cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" "github.com/stretchr/testify/require" "google.golang.org/grpc" ) diff --git a/pkg/services/tree/options.go b/pkg/services/tree/options.go index 043e12cb2..af501d269 100644 --- a/pkg/services/tree/options.go +++ b/pkg/services/tree/options.go @@ -7,8 +7,8 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" ) diff --git a/pkg/services/tree/redirect.go b/pkg/services/tree/redirect.go index ec41a60d4..2f8ae6826 100644 --- a/pkg/services/tree/redirect.go +++ b/pkg/services/tree/redirect.go @@ -6,9 +6,9 @@ import ( "errors" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" "go.uber.org/zap" diff --git a/pkg/services/tree/replicator.go b/pkg/services/tree/replicator.go index 346198b3c..d21f97334 100644 --- a/pkg/services/tree/replicator.go +++ b/pkg/services/tree/replicator.go @@ -10,10 +10,10 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" + cidSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - cidSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" "go.uber.org/zap" diff --git a/pkg/services/tree/service.go b/pkg/services/tree/service.go index 59b01796e..4c8660318 100644 --- a/pkg/services/tree/service.go +++ b/pkg/services/tree/service.go @@ -10,10 +10,10 @@ import ( "sync/atomic" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/acl" + cidSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" - cidSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" "github.com/panjf2000/ants/v2" "go.uber.org/zap" ) diff --git a/pkg/services/tree/service_frostfs.pb.go b/pkg/services/tree/service_frostfs.pb.go index 4b50af2aa..0c4dd9964 100644 --- a/pkg/services/tree/service_frostfs.pb.go +++ b/pkg/services/tree/service_frostfs.pb.go @@ -2,7 +2,7 @@ package tree -import "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/proto" +import "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/util/proto" // StableSize returns the size of x in protobuf format. // diff --git a/pkg/services/tree/signature.go b/pkg/services/tree/signature.go index 985e1ad94..ead145372 100644 --- a/pkg/services/tree/signature.go +++ b/pkg/services/tree/signature.go @@ -7,17 +7,17 @@ import ( "errors" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" core "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" - cidSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto" - frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto/ecdsa" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/bearer" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/acl" + cidSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/crypto" + frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/crypto/ecdsa" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/eacl" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "go.uber.org/zap" ) diff --git a/pkg/services/tree/signature_test.go b/pkg/services/tree/signature_test.go index b55f4d4fc..93cb4ab25 100644 --- a/pkg/services/tree/signature_test.go +++ b/pkg/services/tree/signature_test.go @@ -6,18 +6,18 @@ import ( "errors" "testing" - aclV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl" + aclV2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/acl" containercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/bearer" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/acl" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id/test" + eaclSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/eacl" + netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/user" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" - eaclSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" - netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/stretchr/testify/require" ) diff --git a/pkg/services/tree/sync.go b/pkg/services/tree/sync.go index 064ee5900..a484d4229 100644 --- a/pkg/services/tree/sync.go +++ b/pkg/services/tree/sync.go @@ -17,11 +17,11 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" + cid "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/container/id" + netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" metrics "git.frostfs.info/TrueCloudLab/frostfs-observability/metrics/grpc" tracing "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" tracing_grpc "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing/grpc" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" "github.com/panjf2000/ants/v2" "go.uber.org/zap" "golang.org/x/sync/errgroup" diff --git a/pkg/services/tree/types_frostfs.pb.go b/pkg/services/tree/types_frostfs.pb.go index 707fcc3cc..1c02397f5 100644 --- a/pkg/services/tree/types_frostfs.pb.go +++ b/pkg/services/tree/types_frostfs.pb.go @@ -2,7 +2,7 @@ package tree -import "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/proto" +import "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/util/proto" // StableSize returns the size of x in protobuf format. // diff --git a/pkg/services/util/response/service.go b/pkg/services/util/response/service.go index 005a643e5..e085052af 100644 --- a/pkg/services/util/response/service.go +++ b/pkg/services/util/response/service.go @@ -1,11 +1,11 @@ package response import ( - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/refs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/version" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/version" ) // Service represents universal v2 service diff --git a/pkg/services/util/sign.go b/pkg/services/util/sign.go index bce43d6e8..5c7ce906e 100644 --- a/pkg/services/util/sign.go +++ b/pkg/services/util/sign.go @@ -5,9 +5,9 @@ import ( "errors" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/api/signature" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/client/status" ) type RequestMessage interface { diff --git a/pkg/util/attributes/parser.go b/pkg/util/attributes/parser.go index f8cc97189..792858ea3 100644 --- a/pkg/util/attributes/parser.go +++ b/pkg/util/attributes/parser.go @@ -4,7 +4,7 @@ import ( "fmt" "strings" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" ) const keyValueSeparator = ":" diff --git a/pkg/util/attributes/parser_test.go b/pkg/util/attributes/parser_test.go index 547c8d50b..c53443bd9 100644 --- a/pkg/util/attributes/parser_test.go +++ b/pkg/util/attributes/parser_test.go @@ -3,8 +3,8 @@ package attributes_test import ( "testing" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/sdk/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/attributes" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" "github.com/stretchr/testify/require" )