From 2aba66806c812d62fb34dbb0c1b4113d83236d75 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Fri, 21 Jun 2024 14:33:04 +0300 Subject: [PATCH] [#93] frostfsid: Move struct parsers to separate file Signed-off-by: Alexander Chuprov --- frostfsid/client/client.go | 331 ++----------------------------------- frostfsid/client/utils.go | 312 ++++++++++++++++++++++++++++++++++ 2 files changed, 326 insertions(+), 317 deletions(-) create mode 100644 frostfsid/client/utils.go diff --git a/frostfsid/client/client.go b/frostfsid/client/client.go index d13085d..3db4d83 100644 --- a/frostfsid/client/client.go +++ b/frostfsid/client/client.go @@ -1,21 +1,17 @@ package client import ( - "errors" "fmt" "git.frostfs.info/TrueCloudLab/frostfs-contract/commonclient" "github.com/nspcc-dev/neo-go/pkg/core/state" "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/neorpc/result" "github.com/nspcc-dev/neo-go/pkg/rpcclient/actor" "github.com/nspcc-dev/neo-go/pkg/rpcclient/notary" "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap" "github.com/nspcc-dev/neo-go/pkg/rpcclient/waiter" "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/nspcc-dev/neo-go/pkg/wallet" ) @@ -246,7 +242,7 @@ func (c Client) GetSubject(addr util.Uint160) (*Subject, error) { return nil, err } - return parseSubject(items) + return ParseSubject(items) } // GetSubjectExtended gets extended subject by address. @@ -256,12 +252,12 @@ func (c Client) GetSubjectExtended(addr util.Uint160) (*SubjectExtended, error) return nil, err } - return parseSubjectExtended(items) + return ParseSubjectExtended(items) } // ListSubjects gets all subjects. func (c Client) ListSubjects() ([]util.Uint160, error) { - return unwrapArrayOfUint160(commonclient.ReadIteratorItems(c.act, iteratorBatchSize, c.contract, listSubjectsMethod)) + return UnwrapArrayOfUint160(commonclient.ReadIteratorItems(c.act, iteratorBatchSize, c.contract, listSubjectsMethod)) } // AddSubjectKey adds extra public key to subject. @@ -332,7 +328,7 @@ func (c Client) GetSubjectByKey(key *keys.PublicKey) (*Subject, error) { return nil, err } - return parseSubject(items) + return ParseSubject(items) } // GetSubjectByName gets subject by its name (namespace scope). @@ -342,7 +338,7 @@ func (c Client) GetSubjectByName(namespace, subjectName string) (*Subject, error return nil, err } - return parseSubject(items) + return ParseSubject(items) } // GetSubjectKeyByName gets subject public key by its name (namespace scope). @@ -381,7 +377,7 @@ func (c Client) GetNamespace(namespace string) (*Namespace, error) { return nil, err } - return parseNamespace(items) + return ParseNamespace(items) } // GetNamespaceExtended gets extended namespace. @@ -391,7 +387,7 @@ func (c Client) GetNamespaceExtended(namespace string) (*NamespaceExtended, erro return nil, err } - return parseNamespaceExtended(items) + return ParseNamespaceExtended(items) } // ListNamespaces gets all namespaces. @@ -401,12 +397,12 @@ func (c Client) ListNamespaces() ([]*Namespace, error) { return nil, err } - return parseNamespaces(items) + return ParseNamespaces(items) } // ListNamespaceSubjects gets all subjects from namespace. func (c Client) ListNamespaceSubjects(namespace string) ([]util.Uint160, error) { - return unwrapArrayOfUint160(commonclient.ReadIteratorItems(c.act, iteratorBatchSize, c.contract, listNamespaceSubjectsMethod, namespace)) + return UnwrapArrayOfUint160(commonclient.ReadIteratorItems(c.act, iteratorBatchSize, c.contract, listNamespaceSubjectsMethod, namespace)) } // CreateGroup creates a new group in specific namespace. @@ -428,7 +424,7 @@ func (c Client) GetGroup(namespace string, groupID int64) (*Group, error) { return nil, err } - return parseGroup(items) + return ParseGroup(items) } // GetGroupExtended gets extended group. @@ -438,7 +434,7 @@ func (c Client) GetGroupExtended(namespace string, groupID int64) (*GroupExtende return nil, err } - return parseGroupExtended(items) + return ParseGroupExtended(items) } // SetGroupName updates subject name. @@ -490,7 +486,7 @@ func (c Client) GetGroupByName(namespace, groupName string) (*Group, error) { return nil, err } - return parseGroup(items) + return ParseGroup(items) } // ListGroups gets all groups in specific namespace. @@ -500,7 +496,7 @@ func (c Client) ListGroups(namespace string) ([]*Group, error) { return nil, err } - return parseGroups(items) + return ParseGroups(items) } // AddSubjectToGroup adds a new subject to group. @@ -529,7 +525,7 @@ func (c Client) RemoveSubjectFromGroupCall(addr util.Uint160, groupID int64) (me // ListGroupSubjects gets all subjects in specific group. func (c Client) ListGroupSubjects(namespace string, groupID int64) ([]util.Uint160, error) { - return unwrapArrayOfUint160(commonclient.ReadIteratorItems(c.act, iteratorBatchSize, c.contract, listGroupSubjectsMethod, namespace, groupID)) + return UnwrapArrayOfUint160(commonclient.ReadIteratorItems(c.act, iteratorBatchSize, c.contract, listGroupSubjectsMethod, namespace, groupID)) } // DeleteGroup deletes group. @@ -612,302 +608,3 @@ func (c Client) ListNonEmptyGroups(namespace string) ([]string, error) { return res, nil } - -func unwrapArrayOfUint160(items []stackitem.Item, err error) ([]util.Uint160, error) { - if err != nil { - return nil, err - } - - return unwrap.ArrayOfUint160(makeValidRes(stackitem.NewArray(items))) -} - -func makeValidRes(item stackitem.Item) (*result.Invoke, error) { - return &result.Invoke{ - Stack: []stackitem.Item{item}, - State: vmstate.Halt.String(), - }, nil -} - -func makeResFromAppExec(res *state.AppExecResult) (*result.Invoke, error) { - return &result.Invoke{ - Stack: res.Stack, - State: res.VMState.String(), - }, nil -} - -func parseSubject(structArr []stackitem.Item) (*Subject, error) { - if len(structArr) < 5 { - return nil, errors.New("invalid response subject struct") - } - - var ( - err error - subj Subject - ) - - subj.PrimaryKey, err = unwrap.PublicKey(makeValidRes(structArr[0])) - if err != nil { - return nil, err - } - - if !structArr[1].Equals(stackitem.Null{}) { - subj.AdditionalKeys, err = unwrap.ArrayOfPublicKeys(makeValidRes(structArr[1])) - if err != nil { - return nil, err - } - } - - if !structArr[2].Equals(stackitem.Null{}) { - subj.Namespace, err = unwrap.UTF8String(makeValidRes(structArr[2])) - if err != nil { - return nil, err - } - } - - if !structArr[2].Equals(stackitem.Null{}) { - subj.Name, err = unwrap.UTF8String(makeValidRes(structArr[3])) - if err != nil { - return nil, err - } - } - - subj.KV, err = parseMap(structArr[4]) - if err != nil { - return nil, err - } - - return &subj, nil -} - -func parseSubjectExtended(structArr []stackitem.Item) (*SubjectExtended, error) { - if len(structArr) < 6 { - return nil, errors.New("invalid response subject extended struct") - } - - var ( - err error - subj SubjectExtended - ) - - subj.PrimaryKey, err = unwrap.PublicKey(makeValidRes(structArr[0])) - if err != nil { - return nil, err - } - - if !structArr[1].Equals(stackitem.Null{}) { - subj.AdditionalKeys, err = unwrap.ArrayOfPublicKeys(makeValidRes(structArr[1])) - if err != nil { - return nil, err - } - } - - nsBytes, err := structArr[2].TryBytes() - if err != nil { - return nil, err - } - subj.Namespace = string(nsBytes) - - nameBytes, err := structArr[3].TryBytes() - if err != nil { - return nil, err - } - subj.Name = string(nameBytes) - - subj.KV, err = parseMap(structArr[4]) - if err != nil { - return nil, err - } - - if !structArr[5].Equals(stackitem.Null{}) { - groupItems, ok := structArr[5].Value().([]stackitem.Item) - if !ok { - return nil, fmt.Errorf("invalid groups field") - } - - subj.Groups, err = parseGroups(groupItems) - if err != nil { - return nil, err - } - } - - return &subj, nil -} - -func parseMap(item stackitem.Item) (map[string]string, error) { - if item.Equals(stackitem.Null{}) { - return nil, nil - } - - metaMap, err := unwrap.Map(makeValidRes(item)) - if err != nil { - return nil, err - } - - meta, ok := metaMap.Value().([]stackitem.MapElement) - if !ok { - return nil, errors.New("invalid map type") - } - - res := make(map[string]string, len(meta)) - for _, element := range meta { - key, err := element.Key.TryBytes() - if err != nil { - return nil, err - } - val, err := element.Value.TryBytes() - if err != nil { - return nil, err - } - res[string(key)] = string(val) - } - - return res, nil -} - -func parseNamespace(structArr []stackitem.Item) (*Namespace, error) { - if len(structArr) < 1 { - return nil, errors.New("invalid response namespace struct") - } - - name, err := structArr[0].TryBytes() - if err != nil { - return nil, err - } - - return &Namespace{Name: string(name)}, nil -} - -func parseNamespaceExtended(structArr []stackitem.Item) (*NamespaceExtended, error) { - if len(structArr) < 3 { - return nil, errors.New("invalid response namespace extended struct") - } - - name, err := structArr[0].TryBytes() - if err != nil { - return nil, err - } - - groupCount, err := structArr[1].TryInteger() - if err != nil { - return nil, err - } - - subjectCount, err := structArr[2].TryInteger() - if err != nil { - return nil, err - } - - return &NamespaceExtended{ - Name: string(name), - GroupsCount: groupCount.Int64(), - SubjectsCount: subjectCount.Int64(), - }, nil -} - -func parseNamespaces(items []stackitem.Item) ([]*Namespace, error) { - var err error - res := make([]*Namespace, len(items)) - - for i := 0; i < len(items); i++ { - arr, ok := items[i].Value().([]stackitem.Item) - if !ok { - return nil, fmt.Errorf("invalid namespace type") - } - res[i], err = parseNamespace(arr) - if err != nil { - return nil, err - } - } - - return res, nil -} - -func parseGroup(structArr []stackitem.Item) (*Group, error) { - if len(structArr) < 4 { - return nil, errors.New("invalid response group struct") - } - - groupID, err := structArr[0].TryInteger() - if err != nil { - return nil, err - } - - name, err := structArr[1].TryBytes() - if err != nil { - return nil, err - } - - namespace, err := structArr[2].TryBytes() - if err != nil { - return nil, err - } - - kvs, err := parseMap(structArr[3]) - if err != nil { - return nil, err - } - - return &Group{ - ID: groupID.Int64(), - Name: string(name), - Namespace: string(namespace), - KV: kvs, - }, nil -} - -func parseGroupExtended(structArr []stackitem.Item) (*GroupExtended, error) { - if len(structArr) < 5 { - return nil, errors.New("invalid response group extended struct") - } - - groupID, err := structArr[0].TryInteger() - if err != nil { - return nil, err - } - - name, err := structArr[1].TryBytes() - if err != nil { - return nil, err - } - - namespace, err := structArr[2].TryBytes() - if err != nil { - return nil, err - } - - kvs, err := parseMap(structArr[3]) - if err != nil { - return nil, err - } - - subjectCount, err := structArr[4].TryInteger() - if err != nil { - return nil, err - } - - return &GroupExtended{ - ID: groupID.Int64(), - Name: string(name), - Namespace: string(namespace), - KV: kvs, - SubjectsCount: subjectCount.Int64(), - }, nil -} - -func parseGroups(items []stackitem.Item) ([]*Group, error) { - var err error - res := make([]*Group, len(items)) - - for i := 0; i < len(items); i++ { - arr, ok := items[i].Value().([]stackitem.Item) - if !ok { - return nil, fmt.Errorf("invalid group type") - } - res[i], err = parseGroup(arr) - if err != nil { - return nil, err - } - } - - return res, nil -} diff --git a/frostfsid/client/utils.go b/frostfsid/client/utils.go new file mode 100644 index 0000000..0c7a9fe --- /dev/null +++ b/frostfsid/client/utils.go @@ -0,0 +1,312 @@ +package client + +import ( + "errors" + "fmt" + + "github.com/nspcc-dev/neo-go/pkg/core/state" + "github.com/nspcc-dev/neo-go/pkg/neorpc/result" + "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" + "github.com/nspcc-dev/neo-go/pkg/vm/vmstate" +) + +func UnwrapArrayOfUint160(items []stackitem.Item, err error) ([]util.Uint160, error) { + if err != nil { + return nil, err + } + + return unwrap.ArrayOfUint160(makeValidRes(stackitem.NewArray(items))) +} + +func ParseSubject(structArr []stackitem.Item) (*Subject, error) { + if len(structArr) < 5 { + return nil, errors.New("invalid response subject struct") + } + + var ( + err error + subj Subject + ) + + subj.PrimaryKey, err = unwrap.PublicKey(makeValidRes(structArr[0])) + if err != nil { + return nil, err + } + + if !structArr[1].Equals(stackitem.Null{}) { + subj.AdditionalKeys, err = unwrap.ArrayOfPublicKeys(makeValidRes(structArr[1])) + if err != nil { + return nil, err + } + } + + if !structArr[2].Equals(stackitem.Null{}) { + subj.Namespace, err = unwrap.UTF8String(makeValidRes(structArr[2])) + if err != nil { + return nil, err + } + } + + if !structArr[2].Equals(stackitem.Null{}) { + subj.Name, err = unwrap.UTF8String(makeValidRes(structArr[3])) + if err != nil { + return nil, err + } + } + + subj.KV, err = ParseMap(structArr[4]) + if err != nil { + return nil, err + } + + return &subj, nil +} + +func ParseSubjectExtended(structArr []stackitem.Item) (*SubjectExtended, error) { + if len(structArr) < 6 { + return nil, errors.New("invalid response subject extended struct") + } + + var ( + err error + subj SubjectExtended + ) + + subj.PrimaryKey, err = unwrap.PublicKey(makeValidRes(structArr[0])) + if err != nil { + return nil, err + } + + if !structArr[1].Equals(stackitem.Null{}) { + subj.AdditionalKeys, err = unwrap.ArrayOfPublicKeys(makeValidRes(structArr[1])) + if err != nil { + return nil, err + } + } + + nsBytes, err := structArr[2].TryBytes() + if err != nil { + return nil, err + } + subj.Namespace = string(nsBytes) + + nameBytes, err := structArr[3].TryBytes() + if err != nil { + return nil, err + } + subj.Name = string(nameBytes) + + subj.KV, err = ParseMap(structArr[4]) + if err != nil { + return nil, err + } + + if !structArr[5].Equals(stackitem.Null{}) { + groupItems, ok := structArr[5].Value().([]stackitem.Item) + if !ok { + return nil, fmt.Errorf("invalid groups field") + } + + subj.Groups, err = ParseGroups(groupItems) + if err != nil { + return nil, err + } + } + + return &subj, nil +} + +func ParseMap(item stackitem.Item) (map[string]string, error) { + if item.Equals(stackitem.Null{}) { + return nil, nil + } + + metaMap, err := unwrap.Map(makeValidRes(item)) + if err != nil { + return nil, err + } + + meta, ok := metaMap.Value().([]stackitem.MapElement) + if !ok { + return nil, errors.New("invalid map type") + } + + res := make(map[string]string, len(meta)) + for _, element := range meta { + key, err := element.Key.TryBytes() + if err != nil { + return nil, err + } + val, err := element.Value.TryBytes() + if err != nil { + return nil, err + } + res[string(key)] = string(val) + } + + return res, nil +} + +func ParseNamespace(structArr []stackitem.Item) (*Namespace, error) { + if len(structArr) < 1 { + return nil, errors.New("invalid response namespace struct") + } + + name, err := structArr[0].TryBytes() + if err != nil { + return nil, err + } + + return &Namespace{Name: string(name)}, nil +} + +func ParseNamespaceExtended(structArr []stackitem.Item) (*NamespaceExtended, error) { + if len(structArr) < 3 { + return nil, errors.New("invalid response namespace extended struct") + } + + name, err := structArr[0].TryBytes() + if err != nil { + return nil, err + } + + groupCount, err := structArr[1].TryInteger() + if err != nil { + return nil, err + } + + subjectCount, err := structArr[2].TryInteger() + if err != nil { + return nil, err + } + + return &NamespaceExtended{ + Name: string(name), + GroupsCount: groupCount.Int64(), + SubjectsCount: subjectCount.Int64(), + }, nil +} + +func ParseNamespaces(items []stackitem.Item) ([]*Namespace, error) { + var err error + res := make([]*Namespace, len(items)) + + for i := 0; i < len(items); i++ { + arr, ok := items[i].Value().([]stackitem.Item) + if !ok { + return nil, fmt.Errorf("invalid namespace type") + } + res[i], err = ParseNamespace(arr) + if err != nil { + return nil, err + } + } + + return res, nil +} + +func ParseGroup(structArr []stackitem.Item) (*Group, error) { + if len(structArr) < 4 { + return nil, errors.New("invalid response group struct") + } + + groupID, err := structArr[0].TryInteger() + if err != nil { + return nil, err + } + + name, err := structArr[1].TryBytes() + if err != nil { + return nil, err + } + + namespace, err := structArr[2].TryBytes() + if err != nil { + return nil, err + } + + kvs, err := ParseMap(structArr[3]) + if err != nil { + return nil, err + } + + return &Group{ + ID: groupID.Int64(), + Name: string(name), + Namespace: string(namespace), + KV: kvs, + }, nil +} + +func ParseGroupExtended(structArr []stackitem.Item) (*GroupExtended, error) { + if len(structArr) < 5 { + return nil, errors.New("invalid response group extended struct") + } + + groupID, err := structArr[0].TryInteger() + if err != nil { + return nil, err + } + + name, err := structArr[1].TryBytes() + if err != nil { + return nil, err + } + + namespace, err := structArr[2].TryBytes() + if err != nil { + return nil, err + } + + kvs, err := ParseMap(structArr[3]) + if err != nil { + return nil, err + } + + subjectCount, err := structArr[4].TryInteger() + if err != nil { + return nil, err + } + + return &GroupExtended{ + ID: groupID.Int64(), + Name: string(name), + Namespace: string(namespace), + KV: kvs, + SubjectsCount: subjectCount.Int64(), + }, nil +} + +func ParseGroups(items []stackitem.Item) ([]*Group, error) { + var err error + res := make([]*Group, len(items)) + + for i := 0; i < len(items); i++ { + arr, ok := items[i].Value().([]stackitem.Item) + if !ok { + return nil, fmt.Errorf("invalid group type") + } + res[i], err = ParseGroup(arr) + if err != nil { + return nil, err + } + } + + return res, nil +} + +func makeValidRes(item stackitem.Item) (*result.Invoke, error) { + return &result.Invoke{ + Stack: []stackitem.Item{item}, + State: vmstate.Halt.String(), + }, nil +} + +func makeResFromAppExec(res *state.AppExecResult) (*result.Invoke, error) { + return &result.Invoke{ + Stack: res.Stack, + State: res.VMState.String(), + }, nil +}