From b1a8b3a11b6c484eff4200a23dbab823b1dc3d86 Mon Sep 17 00:00:00 2001 From: Leonard Lyubich Date: Tue, 9 Jul 2024 12:31:54 +0400 Subject: [PATCH 1/5] adm/morph: Simplify filtering requested containers Maps are much easier to implement/understand than `sort.Search`. Signed-off-by: Leonard Lyubich --- .../internal/modules/morph/container.go | 52 +++++++------------ 1 file changed, 19 insertions(+), 33 deletions(-) diff --git a/cmd/neofs-adm/internal/modules/morph/container.go b/cmd/neofs-adm/internal/modules/morph/container.go index 06693bb49d..91e9c3d11c 100644 --- a/cmd/neofs-adm/internal/modules/morph/container.go +++ b/cmd/neofs-adm/internal/modules/morph/container.go @@ -5,9 +5,7 @@ import ( "errors" "fmt" "os" - "sort" - "github.com/nspcc-dev/neo-go/pkg/crypto/hash" "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/smartcontract" @@ -71,20 +69,22 @@ func dumpContainers(cmd *cobra.Command, _ []string) error { return fmt.Errorf("unable to get contaract hash: %w", err) } - cids, err := getContainersList(inv, ch) + rawIDs, err := getContainersList(inv, ch) if err != nil { return fmt.Errorf("%w: %w", errInvalidContainerResponse, err) } - isOK, err := getCIDFilterFunc(cmd) + requested, err := getCIDs(cmd) if err != nil { return err } var containers []*Container + var dec cid.ID b := smartcontract.NewBuilder() - for _, id := range cids { - if !isOK(id) { + for _, id := range rawIDs { + copy(dec[:], id) + if _, ok := requested[dec]; !ok { continue } b.Reset() @@ -191,19 +191,20 @@ func restoreContainers(cmd *cobra.Command, _ []string) error { return fmt.Errorf("can't parse dump file: %w", err) } - isOK, err := getCIDFilterFunc(cmd) + requested, err := getCIDs(cmd) if err != nil { return err } + var id cid.ID b := smartcontract.NewBuilder() for _, cnt := range containers { - hv := hash.Sha256(cnt.Value) - if !isOK(hv[:]) { + id.FromBinary(cnt.Value) + if _, ok := requested[id]; !ok { continue } b.Reset() - b.InvokeMethod(ch, "get", hv.BytesBE()) + b.InvokeMethod(ch, "get", id[:]) script, err := b.Script() if err != nil { @@ -223,8 +224,6 @@ func restoreContainers(cmd *cobra.Command, _ []string) error { return fmt.Errorf("%w: %w", errInvalidContainerResponse, err) } if len(old.Value) != 0 { - var id cid.ID - id.SetSHA256(hv) cmd.Printf("Container %s is already deployed.\n", id) continue } @@ -353,33 +352,20 @@ func (c *EACL) FromStackItem(item stackitem.Item) error { return nil } -// getCIDFilterFunc returns filtering function for container IDs. -// Raw byte slices are used because it works with structures returned -// from contract. -func getCIDFilterFunc(cmd *cobra.Command) (func([]byte) bool, error) { +// returns set of cid.ID specified via the 'cid' command flag. Function allows +// duplicates. +func getCIDs(cmd *cobra.Command) (map[cid.ID]struct{}, error) { rawIDs, err := cmd.Flags().GetStringSlice(containerIDsFlag) if err != nil { return nil, err } - if len(rawIDs) == 0 { - return func([]byte) bool { return true }, nil - } - + var id cid.ID + res := make(map[cid.ID]struct{}, len(rawIDs)) for i := range rawIDs { - err := new(cid.ID).DecodeString(rawIDs[i]) - if err != nil { + if err = id.DecodeString(rawIDs[i]); err != nil { return nil, fmt.Errorf("can't parse CID %s: %w", rawIDs[i], err) } + res[id] = struct{}{} } - sort.Strings(rawIDs) - return func(rawID []byte) bool { - var v [32]byte - copy(v[:], rawID) - - var id cid.ID - id.SetSHA256(v) - idStr := id.EncodeToString() - n := sort.Search(len(rawIDs), func(i int) bool { return rawIDs[i] >= idStr }) - return n < len(rawIDs) && rawIDs[n] == idStr - }, nil + return res, nil } From 82983f4b8140840a70e91d6fd97ae2216b8f558b Mon Sep 17 00:00:00 2001 From: Leonard Lyubich Date: Tue, 9 Jul 2024 12:59:56 +0400 Subject: [PATCH 2/5] adm/morph: Improve `dump-containers` command behavior It makes no sense to preliminary request container list from the contract: the list is specified via command flag. Verification of the container IDs is also better to be done before any network access. Signed-off-by: Leonard Lyubich --- .../internal/modules/morph/container.go | 26 ++++++------------- 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/cmd/neofs-adm/internal/modules/morph/container.go b/cmd/neofs-adm/internal/modules/morph/container.go index 91e9c3d11c..f8d485aa07 100644 --- a/cmd/neofs-adm/internal/modules/morph/container.go +++ b/cmd/neofs-adm/internal/modules/morph/container.go @@ -57,6 +57,11 @@ func dumpContainers(cmd *cobra.Command, _ []string) error { return fmt.Errorf("invalid filename: %w", err) } + requestedIDs, err := getCIDs(cmd) + if err != nil { + return err + } + c, err := getN3Client(viper.GetViper()) if err != nil { return fmt.Errorf("can't create N3 client: %w", err) @@ -69,27 +74,12 @@ func dumpContainers(cmd *cobra.Command, _ []string) error { return fmt.Errorf("unable to get contaract hash: %w", err) } - rawIDs, err := getContainersList(inv, ch) - if err != nil { - return fmt.Errorf("%w: %w", errInvalidContainerResponse, err) - } - - requested, err := getCIDs(cmd) - if err != nil { - return err - } - var containers []*Container - var dec cid.ID b := smartcontract.NewBuilder() - for _, id := range rawIDs { - copy(dec[:], id) - if _, ok := requested[dec]; !ok { - continue - } + for id := range requestedIDs { b.Reset() - b.InvokeMethod(ch, "get", id) - b.InvokeMethod(ch, "eACL", id) + b.InvokeMethod(ch, "get", id[:]) + b.InvokeMethod(ch, "eACL", id[:]) script, err := b.Script() if err != nil { From 3656208442d7469b78dfc1d15e8f5cd07d051786 Mon Sep 17 00:00:00 2001 From: Leonard Lyubich Date: Tue, 9 Jul 2024 12:43:23 +0400 Subject: [PATCH 3/5] *: Convert slices to arrays instead of copy where possible Became possible with Go 1.20. Signed-off-by: Leonard Lyubich --- pkg/local_object_storage/metabase/select_test.go | 6 ++---- pkg/services/object_manager/storagegroup/collect.go | 4 +--- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/pkg/local_object_storage/metabase/select_test.go b/pkg/local_object_storage/metabase/select_test.go index cfb03949cc..d8dea30eea 100644 --- a/pkg/local_object_storage/metabase/select_test.go +++ b/pkg/local_object_storage/metabase/select_test.go @@ -374,8 +374,7 @@ func TestDB_SelectPayloadHash(t *testing.T) { require.NoError(t, err) cs, _ := raw1.PayloadChecksum() - var payloadHash [sha256.Size]byte - copy(payloadHash[:], cs.Value()) + payloadHash := [sha256.Size]byte(cs.Value()) fs := objectSDK.SearchFilters{} fs.AddPayloadHashFilter(objectSDK.MatchStringEqual, payloadHash) @@ -444,8 +443,7 @@ func TestDB_SelectWithSlowFilters(t *testing.T) { t.Run("object with TZHash", func(t *testing.T) { cs, _ := raw1.PayloadHomomorphicHash() - var homoHash [tz.Size]byte - copy(homoHash[:], cs.Value()) + homoHash := [tz.Size]byte(cs.Value()) fs := objectSDK.SearchFilters{} fs.AddHomomorphicHashFilter(objectSDK.MatchStringEqual, homoHash) diff --git a/pkg/services/object_manager/storagegroup/collect.go b/pkg/services/object_manager/storagegroup/collect.go index ceda72224f..ae489556a8 100644 --- a/pkg/services/object_manager/storagegroup/collect.go +++ b/pkg/services/object_manager/storagegroup/collect.go @@ -80,9 +80,7 @@ func CollectMembers(r objutil.ObjectSource, cnr cid.ID, members []oid.ID, calcHo } var cs checksum.Checksum - tzHash := [64]byte{} - copy(tzHash[:], sumHash) - cs.SetTillichZemor(tzHash) + cs.SetTillichZemor([tz.Size]byte(sumHash)) sg.SetValidationDataHash(cs) } From 9e8551721a54c04bf112a9d2eba60a1916ae0612 Mon Sep 17 00:00:00 2001 From: Leonard Lyubich Date: Tue, 9 Jul 2024 12:44:31 +0400 Subject: [PATCH 4/5] adm/morph: Do not do no-op slice-to-slice cast Signed-off-by: Leonard Lyubich --- cmd/neofs-adm/internal/modules/morph/config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/neofs-adm/internal/modules/morph/config.go b/cmd/neofs-adm/internal/modules/morph/config.go index 5fdd64f0ff..5f2105dfeb 100644 --- a/cmd/neofs-adm/internal/modules/morph/config.go +++ b/cmd/neofs-adm/internal/modules/morph/config.go @@ -70,7 +70,7 @@ func dumpNetworkConfig(cmd *cobra.Command, _ []string) error { netmapEpochKey, netmapInnerRingCandidateFeeKey, netmapMaxObjectSizeKey, netmapWithdrawFeeKey: nbuf := make([]byte, 8) - copy(nbuf[:], v) + copy(nbuf, v) n := binary.LittleEndian.Uint64(nbuf) _, _ = tw.Write([]byte(fmt.Sprintf("%s:\t%d (int)\n", k, n))) case netmapEigenTrustAlphaKey: From 35ca2f14af1c3118a80158c2fe8fa7456ee3d9d6 Mon Sep 17 00:00:00 2001 From: Leonard Lyubich Date: Tue, 9 Jul 2024 12:45:54 +0400 Subject: [PATCH 5/5] reputation: Clone peer ID bytes instead of copying them into temp array Signed-off-by: Leonard Lyubich --- cmd/neofs-node/reputation/intermediate/contract.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/cmd/neofs-node/reputation/intermediate/contract.go b/cmd/neofs-node/reputation/intermediate/contract.go index 831134d302..a6df61bca7 100644 --- a/cmd/neofs-node/reputation/intermediate/contract.go +++ b/cmd/neofs-node/reputation/intermediate/contract.go @@ -1,6 +1,7 @@ package intermediate import ( + "bytes" "crypto/ecdsa" "fmt" @@ -80,11 +81,8 @@ func (fw FinalWriter) WriteIntermediateTrust(t eigentrust.IterationTrust) error apiTrust.SetValue(t.Value().Float64()) apiTrust.SetPeer(t.Peer()) - var managerPublicKey [33]byte - copy(managerPublicKey[:], fw.pubKey) - var apiMangerPeerID apireputation.PeerID - apiMangerPeerID.SetPublicKey(managerPublicKey[:]) + apiMangerPeerID.SetPublicKey(bytes.Clone(fw.pubKey)) var gTrust apireputation.GlobalTrust gTrust.SetTrust(apiTrust)