From 4da753f8221e096805b46f6fc274895d4f5bbcd0 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Thu, 23 Jan 2025 22:42:50 +0300 Subject: [PATCH 1/2] stackitem: split TryMake and Make Sometimes we may need something that doesn't panic. Signed-off-by: Roman Khimov --- pkg/vm/stackitem/item.go | 80 ++++++++++++++++++++++------------------ 1 file changed, 44 insertions(+), 36 deletions(-) diff --git a/pkg/vm/stackitem/item.go b/pkg/vm/stackitem/item.go index 109eb7ae3..c2b8e3804 100644 --- a/pkg/vm/stackitem/item.go +++ b/pkg/vm/stackitem/item.go @@ -93,86 +93,94 @@ func mkInvConversion(from Item, to Type) error { return fmt.Errorf("%w: %s/%s", ErrInvalidConversion, from, to) } -// Make tries to make an appropriate stack item from the provided value. -// It will panic if it's not possible. -func Make(v any) Item { +// TryMake tries to make an appropriate stack item from the provided value. +func TryMake(v any) (Item, error) { switch val := v.(type) { case int: - return (*BigInteger)(big.NewInt(int64(val))) + return (*BigInteger)(big.NewInt(int64(val))), nil case int64: - return (*BigInteger)(big.NewInt(val)) + return (*BigInteger)(big.NewInt(val)), nil case uint8: - return (*BigInteger)(big.NewInt(int64(val))) + return (*BigInteger)(big.NewInt(int64(val))), nil case uint16: - return (*BigInteger)(big.NewInt(int64(val))) + return (*BigInteger)(big.NewInt(int64(val))), nil case uint32: - return (*BigInteger)(big.NewInt(int64(val))) + return (*BigInteger)(big.NewInt(int64(val))), nil case uint64: - return (*BigInteger)(new(big.Int).SetUint64(val)) + return (*BigInteger)(new(big.Int).SetUint64(val)), nil case []byte: - return NewByteArray(val) + return NewByteArray(val), nil case string: - return NewByteArray([]byte(val)) + return NewByteArray([]byte(val)), nil case bool: - return Bool(val) + return Bool(val), nil case []Item: return &Array{ value: val, - } + }, nil case *big.Int: - return NewBigInteger(val) + return NewBigInteger(val), nil case Item: - return val + return val, nil case []int: var res = make([]Item, len(val)) for i := range val { - res[i] = Make(val[i]) + res[i], _ = TryMake(val[i]) // Can't fail for int } - return Make(res) + return TryMake(res) case []string: var res = make([]Item, len(val)) for i := range val { - res[i] = Make(val[i]) + res[i], _ = TryMake(val[i]) // Can't fail for string } - return Make(res) + return TryMake(res) case []any: res := make([]Item, len(val)) for i := range val { - res[i] = Make(val[i]) + var err error + + res[i], err = TryMake(val[i]) + if err != nil { + return nil, err + } } - return Make(res) + return TryMake(res) case util.Uint160: - return Make(val.BytesBE()) + return TryMake(val.BytesBE()) case util.Uint256: - return Make(val.BytesBE()) + return TryMake(val.BytesBE()) case *util.Uint160: if val == nil { - return Null{} + return Null{}, nil } - return Make(*val) + return TryMake(*val) case *util.Uint256: if val == nil { - return Null{} + return Null{}, nil } - return Make(*val) + return TryMake(*val) case nil: - return Null{} + return Null{}, nil default: i64T := reflect.TypeOf(int64(0)) if reflect.TypeOf(val).ConvertibleTo(i64T) { i64Val := reflect.ValueOf(val).Convert(i64T).Interface() - return Make(i64Val) + return TryMake(i64Val) } - panic( - fmt.Sprintf( - "invalid stack item type: %v (%v)", - val, - reflect.TypeOf(val), - ), - ) + return nil, fmt.Errorf("%w: item %v of type %v", + errors.ErrUnsupported, val, reflect.TypeOf(val)) } } +// Make is like TryMake, but panics if conversion isn't possible. +func Make(v any) Item { + itm, err := TryMake(v) + if err != nil { + panic(err) + } + return itm +} + // ToString converts an Item to a string if it is a valid UTF-8. func ToString(item Item) (string, error) { bs, err := item.TryBytes() From 00e22b975179cb548444c11fb5531ed48ca11356 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Thu, 23 Jan 2025 22:25:49 +0300 Subject: [PATCH 2/2] rpcbindings: produce ToStackItem companion method We need it for structs to be usable as function parameters, otherwise they're not implementing stackitam.Convertible and they fail at transaction script creation phase: 2025/01/22 20:31:26 bootstrap error: could not invoke method (addNode): test invocation failed: unsupported operation: *netmap.NetmapNode2 type Related to https://github.com/nspcc-dev/neofs-node/pull/3088. Signed-off-by: Roman Khimov --- .../rpcbindings/nft-nd/rpcbindings.out | 31 + .../nft-nd/rpcbindings_dynamic_hash.out | 31 + .../notifications/rpcbindings_extended.out | 56 ++ .../notifications/rpcbindings_guessed.out | 56 ++ .../rpcbindings/structs/rpcbindings.out | 773 ++++++++++++++++++ .../structs/rpcbindings_dynamic_hash.out | 773 ++++++++++++++++++ .../rpcbindings/types/rpcbindings.out | 56 ++ .../types/rpcbindings_dynamic_hash.out | 56 ++ pkg/smartcontract/rpcbinding/binding.go | 120 ++- 9 files changed, 1949 insertions(+), 3 deletions(-) diff --git a/cli/smartcontract/testdata/rpcbindings/nft-nd/rpcbindings.out b/cli/smartcontract/testdata/rpcbindings/nft-nd/rpcbindings.out index 4f4623e8e..985121a41 100644 --- a/cli/smartcontract/testdata/rpcbindings/nft-nd/rpcbindings.out +++ b/cli/smartcontract/testdata/rpcbindings/nft-nd/rpcbindings.out @@ -208,8 +208,12 @@ func itemToNftRoyaltyRecipientShare(item stackitem.Item, err error) (*NftRoyalty return res, err } +// Ensure *NftRoyaltyRecipientShare is a proper [stackitem.Convertible]. +var _ = stackitem.Convertible(&NftRoyaltyRecipientShare{}) + // FromStackItem retrieves fields of NftRoyaltyRecipientShare from the given // [stackitem.Item] or returns an error if it's not possible to do to so. +// It implements [stackitem.Convertible] interface. func (res *NftRoyaltyRecipientShare) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -247,3 +251,30 @@ func (res *NftRoyaltyRecipientShare) FromStackItem(item stackitem.Item) error { return nil } + +// ToStackItem creates [stackitem.Item] representing NftRoyaltyRecipientShare. +// It implements [stackitem.Convertible] interface. +func (res *NftRoyaltyRecipientShare) ToStackItem() (stackitem.Item, error) { + if res == nil { + return stackitem.Null{}, nil + } + + var ( + err error + itm stackitem.Item + items = make([]stackitem.Item, 0, 2) + ) + itm, err = stackitem.NewByteArray(res.Address.BytesBE()), error(nil) + if err != nil { + return fmt.Errorf("field Address: %w", err) + } + items = append(items, itm) + + itm, err = (*stackitem.BigInteger)(res.Share), error(nil) + if err != nil { + return fmt.Errorf("field Share: %w", err) + } + items = append(items, itm) + + return stackitem.NewStruct(items), nil +} diff --git a/cli/smartcontract/testdata/rpcbindings/nft-nd/rpcbindings_dynamic_hash.out b/cli/smartcontract/testdata/rpcbindings/nft-nd/rpcbindings_dynamic_hash.out index d582ac114..7bc848b40 100644 --- a/cli/smartcontract/testdata/rpcbindings/nft-nd/rpcbindings_dynamic_hash.out +++ b/cli/smartcontract/testdata/rpcbindings/nft-nd/rpcbindings_dynamic_hash.out @@ -203,8 +203,12 @@ func itemToNftRoyaltyRecipientShare(item stackitem.Item, err error) (*NftRoyalty return res, err } +// Ensure *NftRoyaltyRecipientShare is a proper [stackitem.Convertible]. +var _ = stackitem.Convertible(&NftRoyaltyRecipientShare{}) + // FromStackItem retrieves fields of NftRoyaltyRecipientShare from the given // [stackitem.Item] or returns an error if it's not possible to do to so. +// It implements [stackitem.Convertible] interface. func (res *NftRoyaltyRecipientShare) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -242,3 +246,30 @@ func (res *NftRoyaltyRecipientShare) FromStackItem(item stackitem.Item) error { return nil } + +// ToStackItem creates [stackitem.Item] representing NftRoyaltyRecipientShare. +// It implements [stackitem.Convertible] interface. +func (res *NftRoyaltyRecipientShare) ToStackItem() (stackitem.Item, error) { + if res == nil { + return stackitem.Null{}, nil + } + + var ( + err error + itm stackitem.Item + items = make([]stackitem.Item, 0, 2) + ) + itm, err = stackitem.NewByteArray(res.Address.BytesBE()), error(nil) + if err != nil { + return fmt.Errorf("field Address: %w", err) + } + items = append(items, itm) + + itm, err = (*stackitem.BigInteger)(res.Share), error(nil) + if err != nil { + return fmt.Errorf("field Share: %w", err) + } + items = append(items, itm) + + return stackitem.NewStruct(items), nil +} diff --git a/cli/smartcontract/testdata/rpcbindings/notifications/rpcbindings_extended.out b/cli/smartcontract/testdata/rpcbindings/notifications/rpcbindings_extended.out index d6d383310..164fe5b1f 100755 --- a/cli/smartcontract/testdata/rpcbindings/notifications/rpcbindings_extended.out +++ b/cli/smartcontract/testdata/rpcbindings/notifications/rpcbindings_extended.out @@ -200,8 +200,12 @@ func itemToCrazyStruct(item stackitem.Item, err error) (*CrazyStruct, error) { return res, err } +// Ensure *CrazyStruct is a proper [stackitem.Convertible]. +var _ = stackitem.Convertible(&CrazyStruct{}) + // FromStackItem retrieves fields of CrazyStruct from the given // [stackitem.Item] or returns an error if it's not possible to do to so. +// It implements [stackitem.Convertible] interface. func (res *CrazyStruct) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -230,6 +234,33 @@ func (res *CrazyStruct) FromStackItem(item stackitem.Item) error { return nil } +// ToStackItem creates [stackitem.Item] representing CrazyStruct. +// It implements [stackitem.Convertible] interface. +func (res *CrazyStruct) ToStackItem() (stackitem.Item, error) { + if res == nil { + return stackitem.Null{}, nil + } + + var ( + err error + itm stackitem.Item + items = make([]stackitem.Item, 0, 2) + ) + itm, err = (*stackitem.BigInteger)(res.I), error(nil) + if err != nil { + return fmt.Errorf("field I: %w", err) + } + items = append(items, itm) + + itm, err = stackitem.NewBool(res.B), error(nil) + if err != nil { + return fmt.Errorf("field B: %w", err) + } + items = append(items, itm) + + return stackitem.NewStruct(items), nil +} + // itemToSimpleStruct converts stack item into *SimpleStruct. // NULL item is returned as nil pointer without error. func itemToSimpleStruct(item stackitem.Item, err error) (*SimpleStruct, error) { @@ -245,8 +276,12 @@ func itemToSimpleStruct(item stackitem.Item, err error) (*SimpleStruct, error) { return res, err } +// Ensure *SimpleStruct is a proper [stackitem.Convertible]. +var _ = stackitem.Convertible(&SimpleStruct{}) + // FromStackItem retrieves fields of SimpleStruct from the given // [stackitem.Item] or returns an error if it's not possible to do to so. +// It implements [stackitem.Convertible] interface. func (res *SimpleStruct) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -269,6 +304,27 @@ func (res *SimpleStruct) FromStackItem(item stackitem.Item) error { return nil } +// ToStackItem creates [stackitem.Item] representing SimpleStruct. +// It implements [stackitem.Convertible] interface. +func (res *SimpleStruct) ToStackItem() (stackitem.Item, error) { + if res == nil { + return stackitem.Null{}, nil + } + + var ( + err error + itm stackitem.Item + items = make([]stackitem.Item, 0, 1) + ) + itm, err = (*stackitem.BigInteger)(res.I), error(nil) + if err != nil { + return fmt.Errorf("field I: %w", err) + } + items = append(items, itm) + + return stackitem.NewStruct(items), nil +} + // ComplicatedNameEventsFromApplicationLog retrieves a set of all emitted events // with "! complicated name %$#" name from the provided [result.ApplicationLog]. func ComplicatedNameEventsFromApplicationLog(log *result.ApplicationLog) ([]*ComplicatedNameEvent, error) { diff --git a/cli/smartcontract/testdata/rpcbindings/notifications/rpcbindings_guessed.out b/cli/smartcontract/testdata/rpcbindings/notifications/rpcbindings_guessed.out index d10cec334..b285cd2ad 100755 --- a/cli/smartcontract/testdata/rpcbindings/notifications/rpcbindings_guessed.out +++ b/cli/smartcontract/testdata/rpcbindings/notifications/rpcbindings_guessed.out @@ -200,8 +200,12 @@ func itemToUnnamed(item stackitem.Item, err error) (*Unnamed, error) { return res, err } +// Ensure *Unnamed is a proper [stackitem.Convertible]. +var _ = stackitem.Convertible(&Unnamed{}) + // FromStackItem retrieves fields of Unnamed from the given // [stackitem.Item] or returns an error if it's not possible to do to so. +// It implements [stackitem.Convertible] interface. func (res *Unnamed) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -230,6 +234,33 @@ func (res *Unnamed) FromStackItem(item stackitem.Item) error { return nil } +// ToStackItem creates [stackitem.Item] representing Unnamed. +// It implements [stackitem.Convertible] interface. +func (res *Unnamed) ToStackItem() (stackitem.Item, error) { + if res == nil { + return stackitem.Null{}, nil + } + + var ( + err error + itm stackitem.Item + items = make([]stackitem.Item, 0, 2) + ) + itm, err = (*stackitem.BigInteger)(res.I), error(nil) + if err != nil { + return fmt.Errorf("field I: %w", err) + } + items = append(items, itm) + + itm, err = stackitem.NewBool(res.B), error(nil) + if err != nil { + return fmt.Errorf("field B: %w", err) + } + items = append(items, itm) + + return stackitem.NewStruct(items), nil +} + // itemToUnnamedX converts stack item into *UnnamedX. // NULL item is returned as nil pointer without error. func itemToUnnamedX(item stackitem.Item, err error) (*UnnamedX, error) { @@ -245,8 +276,12 @@ func itemToUnnamedX(item stackitem.Item, err error) (*UnnamedX, error) { return res, err } +// Ensure *UnnamedX is a proper [stackitem.Convertible]. +var _ = stackitem.Convertible(&UnnamedX{}) + // FromStackItem retrieves fields of UnnamedX from the given // [stackitem.Item] or returns an error if it's not possible to do to so. +// It implements [stackitem.Convertible] interface. func (res *UnnamedX) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -269,6 +304,27 @@ func (res *UnnamedX) FromStackItem(item stackitem.Item) error { return nil } +// ToStackItem creates [stackitem.Item] representing UnnamedX. +// It implements [stackitem.Convertible] interface. +func (res *UnnamedX) ToStackItem() (stackitem.Item, error) { + if res == nil { + return stackitem.Null{}, nil + } + + var ( + err error + itm stackitem.Item + items = make([]stackitem.Item, 0, 1) + ) + itm, err = (*stackitem.BigInteger)(res.I), error(nil) + if err != nil { + return fmt.Errorf("field I: %w", err) + } + items = append(items, itm) + + return stackitem.NewStruct(items), nil +} + // ComplicatedNameEventsFromApplicationLog retrieves a set of all emitted events // with "! complicated name %$#" name from the provided [result.ApplicationLog]. func ComplicatedNameEventsFromApplicationLog(log *result.ApplicationLog) ([]*ComplicatedNameEvent, error) { diff --git a/cli/smartcontract/testdata/rpcbindings/structs/rpcbindings.out b/cli/smartcontract/testdata/rpcbindings/structs/rpcbindings.out index fd0bcc6ad..b82993f72 100644 --- a/cli/smartcontract/testdata/rpcbindings/structs/rpcbindings.out +++ b/cli/smartcontract/testdata/rpcbindings/structs/rpcbindings.out @@ -175,8 +175,12 @@ func itemToLedgerBlock(item stackitem.Item, err error) (*LedgerBlock, error) { return res, err } +// Ensure *LedgerBlock is a proper [stackitem.Convertible]. +var _ = stackitem.Convertible(&LedgerBlock{}) + // FromStackItem retrieves fields of LedgerBlock from the given // [stackitem.Item] or returns an error if it's not possible to do to so. +// It implements [stackitem.Convertible] interface. func (res *LedgerBlock) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -293,6 +297,81 @@ func (res *LedgerBlock) FromStackItem(item stackitem.Item) error { return nil } +// ToStackItem creates [stackitem.Item] representing LedgerBlock. +// It implements [stackitem.Convertible] interface. +func (res *LedgerBlock) ToStackItem() (stackitem.Item, error) { + if res == nil { + return stackitem.Null{}, nil + } + + var ( + err error + itm stackitem.Item + items = make([]stackitem.Item, 0, 10) + ) + itm, err = stackitem.NewByteArray(res.Hash.BytesBE()), error(nil) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + items = append(items, itm) + + itm, err = (*stackitem.BigInteger)(res.Version), error(nil) + if err != nil { + return fmt.Errorf("field Version: %w", err) + } + items = append(items, itm) + + itm, err = stackitem.NewByteArray(res.PrevHash.BytesBE()), error(nil) + if err != nil { + return fmt.Errorf("field PrevHash: %w", err) + } + items = append(items, itm) + + itm, err = stackitem.NewByteArray(res.MerkleRoot.BytesBE()), error(nil) + if err != nil { + return fmt.Errorf("field MerkleRoot: %w", err) + } + items = append(items, itm) + + itm, err = (*stackitem.BigInteger)(res.Timestamp), error(nil) + if err != nil { + return fmt.Errorf("field Timestamp: %w", err) + } + items = append(items, itm) + + itm, err = (*stackitem.BigInteger)(res.Nonce), error(nil) + if err != nil { + return fmt.Errorf("field Nonce: %w", err) + } + items = append(items, itm) + + itm, err = (*stackitem.BigInteger)(res.Index), error(nil) + if err != nil { + return fmt.Errorf("field Index: %w", err) + } + items = append(items, itm) + + itm, err = (*stackitem.BigInteger)(res.PrimaryIndex), error(nil) + if err != nil { + return fmt.Errorf("field PrimaryIndex: %w", err) + } + items = append(items, itm) + + itm, err = stackitem.NewByteArray(res.NextConsensus.BytesBE()), error(nil) + if err != nil { + return fmt.Errorf("field NextConsensus: %w", err) + } + items = append(items, itm) + + itm, err = (*stackitem.BigInteger)(res.TransactionsLength), error(nil) + if err != nil { + return fmt.Errorf("field TransactionsLength: %w", err) + } + items = append(items, itm) + + return stackitem.NewStruct(items), nil +} + // itemToLedgerTransaction converts stack item into *LedgerTransaction. // NULL item is returned as nil pointer without error. func itemToLedgerTransaction(item stackitem.Item, err error) (*LedgerTransaction, error) { @@ -308,8 +387,12 @@ func itemToLedgerTransaction(item stackitem.Item, err error) (*LedgerTransaction return res, err } +// Ensure *LedgerTransaction is a proper [stackitem.Convertible]. +var _ = stackitem.Convertible(&LedgerTransaction{}) + // FromStackItem retrieves fields of LedgerTransaction from the given // [stackitem.Item] or returns an error if it's not possible to do to so. +// It implements [stackitem.Convertible] interface. func (res *LedgerTransaction) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -394,6 +477,69 @@ func (res *LedgerTransaction) FromStackItem(item stackitem.Item) error { return nil } +// ToStackItem creates [stackitem.Item] representing LedgerTransaction. +// It implements [stackitem.Convertible] interface. +func (res *LedgerTransaction) ToStackItem() (stackitem.Item, error) { + if res == nil { + return stackitem.Null{}, nil + } + + var ( + err error + itm stackitem.Item + items = make([]stackitem.Item, 0, 8) + ) + itm, err = stackitem.NewByteArray(res.Hash.BytesBE()), error(nil) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + items = append(items, itm) + + itm, err = (*stackitem.BigInteger)(res.Version), error(nil) + if err != nil { + return fmt.Errorf("field Version: %w", err) + } + items = append(items, itm) + + itm, err = (*stackitem.BigInteger)(res.Nonce), error(nil) + if err != nil { + return fmt.Errorf("field Nonce: %w", err) + } + items = append(items, itm) + + itm, err = stackitem.NewByteArray(res.Sender.BytesBE()), error(nil) + if err != nil { + return fmt.Errorf("field Sender: %w", err) + } + items = append(items, itm) + + itm, err = (*stackitem.BigInteger)(res.SysFee), error(nil) + if err != nil { + return fmt.Errorf("field SysFee: %w", err) + } + items = append(items, itm) + + itm, err = (*stackitem.BigInteger)(res.NetFee), error(nil) + if err != nil { + return fmt.Errorf("field NetFee: %w", err) + } + items = append(items, itm) + + itm, err = (*stackitem.BigInteger)(res.ValidUntilBlock), error(nil) + if err != nil { + return fmt.Errorf("field ValidUntilBlock: %w", err) + } + items = append(items, itm) + + itm, err = stackitem.NewByteArray(res.Script), error(nil) + if err != nil { + return fmt.Errorf("field Script: %w", err) + } + items = append(items, itm) + + return stackitem.NewStruct(items), nil +} + // itemToManagementABI converts stack item into *ManagementABI. // NULL item is returned as nil pointer without error. func itemToManagementABI(item stackitem.Item, err error) (*ManagementABI, error) { @@ -409,8 +555,12 @@ func itemToManagementABI(item stackitem.Item, err error) (*ManagementABI, error) return res, err } +// Ensure *ManagementABI is a proper [stackitem.Convertible]. +var _ = stackitem.Convertible(&ManagementABI{}) + // FromStackItem retrieves fields of ManagementABI from the given // [stackitem.Item] or returns an error if it's not possible to do to so. +// It implements [stackitem.Convertible] interface. func (res *ManagementABI) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -465,6 +615,61 @@ func (res *ManagementABI) FromStackItem(item stackitem.Item) error { return nil } +// ToStackItem creates [stackitem.Item] representing ManagementABI. +// It implements [stackitem.Convertible] interface. +func (res *ManagementABI) ToStackItem() (stackitem.Item, error) { + if res == nil { + return stackitem.Null{}, nil + } + + var ( + err error + itm stackitem.Item + items = make([]stackitem.Item, 0, 2) + ) + itm, err = func(in []*ManagementMethod) (stackitem.Item, error) { + if in == nil { + return stackitem.Null{}, nil + } + + var items = make([]stackitem.Item, 0, len(in)) + for i, v := range in { + itm, err := v.ToStackItem() + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + items = append(items, itm) + } + return stackitem.NewArray(items), nil + }(res.Methods) + if err != nil { + return fmt.Errorf("field Methods: %w", err) + } + items = append(items, itm) + + itm, err = func(in []*ManagementEvent) (stackitem.Item, error) { + if in == nil { + return stackitem.Null{}, nil + } + + var items = make([]stackitem.Item, 0, len(in)) + for i, v := range in { + itm, err := v.ToStackItem() + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + items = append(items, itm) + } + return stackitem.NewArray(items), nil + }(res.Events) + if err != nil { + return fmt.Errorf("field Events: %w", err) + } + items = append(items, itm) + + return stackitem.NewStruct(items), nil +} + // itemToManagementContract converts stack item into *ManagementContract. // NULL item is returned as nil pointer without error. func itemToManagementContract(item stackitem.Item, err error) (*ManagementContract, error) { @@ -480,8 +685,12 @@ func itemToManagementContract(item stackitem.Item, err error) (*ManagementContra return res, err } +// Ensure *ManagementContract is a proper [stackitem.Convertible]. +var _ = stackitem.Convertible(&ManagementContract{}) + // FromStackItem retrieves fields of ManagementContract from the given // [stackitem.Item] or returns an error if it's not possible to do to so. +// It implements [stackitem.Convertible] interface. func (res *ManagementContract) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -538,6 +747,51 @@ func (res *ManagementContract) FromStackItem(item stackitem.Item) error { return nil } +// ToStackItem creates [stackitem.Item] representing ManagementContract. +// It implements [stackitem.Convertible] interface. +func (res *ManagementContract) ToStackItem() (stackitem.Item, error) { + if res == nil { + return stackitem.Null{}, nil + } + + var ( + err error + itm stackitem.Item + items = make([]stackitem.Item, 0, 5) + ) + itm, err = (*stackitem.BigInteger)(res.ID), error(nil) + if err != nil { + return fmt.Errorf("field ID: %w", err) + } + items = append(items, itm) + + itm, err = (*stackitem.BigInteger)(res.UpdateCounter), error(nil) + if err != nil { + return fmt.Errorf("field UpdateCounter: %w", err) + } + items = append(items, itm) + + itm, err = stackitem.NewByteArray(res.Hash.BytesBE()), error(nil) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + items = append(items, itm) + + itm, err = stackitem.NewByteArray(res.NEF), error(nil) + if err != nil { + return fmt.Errorf("field NEF: %w", err) + } + items = append(items, itm) + + itm, err = res.Manifest.ToStackItem() + if err != nil { + return fmt.Errorf("field Manifest: %w", err) + } + items = append(items, itm) + + return stackitem.NewStruct(items), nil +} + // itemToManagementEvent converts stack item into *ManagementEvent. // NULL item is returned as nil pointer without error. func itemToManagementEvent(item stackitem.Item, err error) (*ManagementEvent, error) { @@ -553,8 +807,12 @@ func itemToManagementEvent(item stackitem.Item, err error) (*ManagementEvent, er return res, err } +// Ensure *ManagementEvent is a proper [stackitem.Convertible]. +var _ = stackitem.Convertible(&ManagementEvent{}) + // FromStackItem retrieves fields of ManagementEvent from the given // [stackitem.Item] or returns an error if it's not possible to do to so. +// It implements [stackitem.Convertible] interface. func (res *ManagementEvent) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -605,6 +863,47 @@ func (res *ManagementEvent) FromStackItem(item stackitem.Item) error { return nil } +// ToStackItem creates [stackitem.Item] representing ManagementEvent. +// It implements [stackitem.Convertible] interface. +func (res *ManagementEvent) ToStackItem() (stackitem.Item, error) { + if res == nil { + return stackitem.Null{}, nil + } + + var ( + err error + itm stackitem.Item + items = make([]stackitem.Item, 0, 2) + ) + itm, err = stackitem.NewByteArray([]byte(res.Name)), error(nil) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + items = append(items, itm) + + itm, err = func(in []*ManagementParameter) (stackitem.Item, error) { + if in == nil { + return stackitem.Null{}, nil + } + + var items = make([]stackitem.Item, 0, len(in)) + for i, v := range in { + itm, err := v.ToStackItem() + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + items = append(items, itm) + } + return stackitem.NewArray(items), nil + }(res.Params) + if err != nil { + return fmt.Errorf("field Params: %w", err) + } + items = append(items, itm) + + return stackitem.NewStruct(items), nil +} + // itemToManagementGroup converts stack item into *ManagementGroup. // NULL item is returned as nil pointer without error. func itemToManagementGroup(item stackitem.Item, err error) (*ManagementGroup, error) { @@ -620,8 +919,12 @@ func itemToManagementGroup(item stackitem.Item, err error) (*ManagementGroup, er return res, err } +// Ensure *ManagementGroup is a proper [stackitem.Convertible]. +var _ = stackitem.Convertible(&ManagementGroup{}) + // FromStackItem retrieves fields of ManagementGroup from the given // [stackitem.Item] or returns an error if it's not possible to do to so. +// It implements [stackitem.Convertible] interface. func (res *ManagementGroup) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -660,6 +963,33 @@ func (res *ManagementGroup) FromStackItem(item stackitem.Item) error { return nil } +// ToStackItem creates [stackitem.Item] representing ManagementGroup. +// It implements [stackitem.Convertible] interface. +func (res *ManagementGroup) ToStackItem() (stackitem.Item, error) { + if res == nil { + return stackitem.Null{}, nil + } + + var ( + err error + itm stackitem.Item + items = make([]stackitem.Item, 0, 2) + ) + itm, err = stackitem.NewByteArray(res.PublicKey.Bytes()), error(nil) + if err != nil { + return fmt.Errorf("field PublicKey: %w", err) + } + items = append(items, itm) + + itm, err = stackitem.NewByteArray(res.Signature), error(nil) + if err != nil { + return fmt.Errorf("field Signature: %w", err) + } + items = append(items, itm) + + return stackitem.NewStruct(items), nil +} + // itemToManagementManifest converts stack item into *ManagementManifest. // NULL item is returned as nil pointer without error. func itemToManagementManifest(item stackitem.Item, err error) (*ManagementManifest, error) { @@ -675,8 +1005,12 @@ func itemToManagementManifest(item stackitem.Item, err error) (*ManagementManife return res, err } +// Ensure *ManagementManifest is a proper [stackitem.Convertible]. +var _ = stackitem.Convertible(&ManagementManifest{}) + // FromStackItem retrieves fields of ManagementManifest from the given // [stackitem.Item] or returns an error if it's not possible to do to so. +// It implements [stackitem.Convertible] interface. func (res *ManagementManifest) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -857,6 +1191,143 @@ func (res *ManagementManifest) FromStackItem(item stackitem.Item) error { return nil } +// ToStackItem creates [stackitem.Item] representing ManagementManifest. +// It implements [stackitem.Convertible] interface. +func (res *ManagementManifest) ToStackItem() (stackitem.Item, error) { + if res == nil { + return stackitem.Null{}, nil + } + + var ( + err error + itm stackitem.Item + items = make([]stackitem.Item, 0, 8) + ) + itm, err = stackitem.NewByteArray([]byte(res.Name)), error(nil) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + items = append(items, itm) + + itm, err = func(in []*ManagementGroup) (stackitem.Item, error) { + if in == nil { + return stackitem.Null{}, nil + } + + var items = make([]stackitem.Item, 0, len(in)) + for i, v := range in { + itm, err := v.ToStackItem() + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + items = append(items, itm) + } + return stackitem.NewArray(items), nil + }(res.Groups) + if err != nil { + return fmt.Errorf("field Groups: %w", err) + } + items = append(items, itm) + + itm, err = func(in map[string]string) (stackitem.Item, error) { + if in == nil { + return stackitem.Null{}, nil + } + + var m = stackitem.NewMap() + for k, v := range in { + iKey, err := stackitem.NewByteArray([]byte(k)), error(nil) + if err != nil { + return nil, fmt.Errorf("key %v: %w", k, err) + } + iVal, err := stackitem.NewByteArray([]byte(v)), error(nil) + if err != nil { + return nil, fmt.Errorf("key %v, wrong value: %w", k, err) + } + m.Add(iKey, iVal) + } + return m, nil + }(res.Features) + if err != nil { + return fmt.Errorf("field Features: %w", err) + } + items = append(items, itm) + + itm, err = func(in []string) (stackitem.Item, error) { + if in == nil { + return stackitem.Null{}, nil + } + + var items = make([]stackitem.Item, 0, len(in)) + for i, v := range in { + itm, err := stackitem.NewByteArray([]byte(v)), error(nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + items = append(items, itm) + } + return stackitem.NewArray(items), nil + }(res.SupportedStandards) + if err != nil { + return fmt.Errorf("field SupportedStandards: %w", err) + } + items = append(items, itm) + + itm, err = res.ABI.ToStackItem() + if err != nil { + return fmt.Errorf("field ABI: %w", err) + } + items = append(items, itm) + + itm, err = func(in []*ManagementPermission) (stackitem.Item, error) { + if in == nil { + return stackitem.Null{}, nil + } + + var items = make([]stackitem.Item, 0, len(in)) + for i, v := range in { + itm, err := v.ToStackItem() + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + items = append(items, itm) + } + return stackitem.NewArray(items), nil + }(res.Permissions) + if err != nil { + return fmt.Errorf("field Permissions: %w", err) + } + items = append(items, itm) + + itm, err = func(in []util.Uint160) (stackitem.Item, error) { + if in == nil { + return stackitem.Null{}, nil + } + + var items = make([]stackitem.Item, 0, len(in)) + for i, v := range in { + itm, err := stackitem.NewByteArray(v.BytesBE()), error(nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + items = append(items, itm) + } + return stackitem.NewArray(items), nil + }(res.Trusts) + if err != nil { + return fmt.Errorf("field Trusts: %w", err) + } + items = append(items, itm) + + itm, err = stackitem.TryMake(res.Extra) + if err != nil { + return fmt.Errorf("field Extra: %w", err) + } + items = append(items, itm) + + return stackitem.NewStruct(items), nil +} + // itemToManagementMethod converts stack item into *ManagementMethod. // NULL item is returned as nil pointer without error. func itemToManagementMethod(item stackitem.Item, err error) (*ManagementMethod, error) { @@ -872,8 +1343,12 @@ func itemToManagementMethod(item stackitem.Item, err error) (*ManagementMethod, return res, err } +// Ensure *ManagementMethod is a proper [stackitem.Convertible]. +var _ = stackitem.Convertible(&ManagementMethod{}) + // FromStackItem retrieves fields of ManagementMethod from the given // [stackitem.Item] or returns an error if it's not possible to do to so. +// It implements [stackitem.Convertible] interface. func (res *ManagementMethod) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -942,6 +1417,65 @@ func (res *ManagementMethod) FromStackItem(item stackitem.Item) error { return nil } +// ToStackItem creates [stackitem.Item] representing ManagementMethod. +// It implements [stackitem.Convertible] interface. +func (res *ManagementMethod) ToStackItem() (stackitem.Item, error) { + if res == nil { + return stackitem.Null{}, nil + } + + var ( + err error + itm stackitem.Item + items = make([]stackitem.Item, 0, 5) + ) + itm, err = stackitem.NewByteArray([]byte(res.Name)), error(nil) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + items = append(items, itm) + + itm, err = func(in []*ManagementParameter) (stackitem.Item, error) { + if in == nil { + return stackitem.Null{}, nil + } + + var items = make([]stackitem.Item, 0, len(in)) + for i, v := range in { + itm, err := v.ToStackItem() + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + items = append(items, itm) + } + return stackitem.NewArray(items), nil + }(res.Params) + if err != nil { + return fmt.Errorf("field Params: %w", err) + } + items = append(items, itm) + + itm, err = (*stackitem.BigInteger)(res.ReturnType), error(nil) + if err != nil { + return fmt.Errorf("field ReturnType: %w", err) + } + items = append(items, itm) + + itm, err = (*stackitem.BigInteger)(res.Offset), error(nil) + if err != nil { + return fmt.Errorf("field Offset: %w", err) + } + items = append(items, itm) + + itm, err = stackitem.NewBool(res.Safe), error(nil) + if err != nil { + return fmt.Errorf("field Safe: %w", err) + } + items = append(items, itm) + + return stackitem.NewStruct(items), nil +} + // itemToManagementParameter converts stack item into *ManagementParameter. // NULL item is returned as nil pointer without error. func itemToManagementParameter(item stackitem.Item, err error) (*ManagementParameter, error) { @@ -957,8 +1491,12 @@ func itemToManagementParameter(item stackitem.Item, err error) (*ManagementParam return res, err } +// Ensure *ManagementParameter is a proper [stackitem.Convertible]. +var _ = stackitem.Convertible(&ManagementParameter{}) + // FromStackItem retrieves fields of ManagementParameter from the given // [stackitem.Item] or returns an error if it's not possible to do to so. +// It implements [stackitem.Convertible] interface. func (res *ManagementParameter) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -996,6 +1534,33 @@ func (res *ManagementParameter) FromStackItem(item stackitem.Item) error { return nil } +// ToStackItem creates [stackitem.Item] representing ManagementParameter. +// It implements [stackitem.Convertible] interface. +func (res *ManagementParameter) ToStackItem() (stackitem.Item, error) { + if res == nil { + return stackitem.Null{}, nil + } + + var ( + err error + itm stackitem.Item + items = make([]stackitem.Item, 0, 2) + ) + itm, err = stackitem.NewByteArray([]byte(res.Name)), error(nil) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + items = append(items, itm) + + itm, err = (*stackitem.BigInteger)(res.Type), error(nil) + if err != nil { + return fmt.Errorf("field Type: %w", err) + } + items = append(items, itm) + + return stackitem.NewStruct(items), nil +} + // itemToManagementPermission converts stack item into *ManagementPermission. // NULL item is returned as nil pointer without error. func itemToManagementPermission(item stackitem.Item, err error) (*ManagementPermission, error) { @@ -1011,8 +1576,12 @@ func itemToManagementPermission(item stackitem.Item, err error) (*ManagementPerm return res, err } +// Ensure *ManagementPermission is a proper [stackitem.Convertible]. +var _ = stackitem.Convertible(&ManagementPermission{}) + // FromStackItem retrieves fields of ManagementPermission from the given // [stackitem.Item] or returns an error if it's not possible to do to so. +// It implements [stackitem.Convertible] interface. func (res *ManagementPermission) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -1073,6 +1642,47 @@ func (res *ManagementPermission) FromStackItem(item stackitem.Item) error { return nil } +// ToStackItem creates [stackitem.Item] representing ManagementPermission. +// It implements [stackitem.Convertible] interface. +func (res *ManagementPermission) ToStackItem() (stackitem.Item, error) { + if res == nil { + return stackitem.Null{}, nil + } + + var ( + err error + itm stackitem.Item + items = make([]stackitem.Item, 0, 2) + ) + itm, err = stackitem.NewByteArray(res.Contract.BytesBE()), error(nil) + if err != nil { + return fmt.Errorf("field Contract: %w", err) + } + items = append(items, itm) + + itm, err = func(in []string) (stackitem.Item, error) { + if in == nil { + return stackitem.Null{}, nil + } + + var items = make([]stackitem.Item, 0, len(in)) + for i, v := range in { + itm, err := stackitem.NewByteArray([]byte(v)), error(nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + items = append(items, itm) + } + return stackitem.NewArray(items), nil + }(res.Methods) + if err != nil { + return fmt.Errorf("field Methods: %w", err) + } + items = append(items, itm) + + return stackitem.NewStruct(items), nil +} + // itemToStructsInternal converts stack item into *StructsInternal. // NULL item is returned as nil pointer without error. func itemToStructsInternal(item stackitem.Item, err error) (*StructsInternal, error) { @@ -1088,8 +1698,12 @@ func itemToStructsInternal(item stackitem.Item, err error) (*StructsInternal, er return res, err } +// Ensure *StructsInternal is a proper [stackitem.Convertible]. +var _ = stackitem.Convertible(&StructsInternal{}) + // FromStackItem retrieves fields of StructsInternal from the given // [stackitem.Item] or returns an error if it's not possible to do to so. +// It implements [stackitem.Convertible] interface. func (res *StructsInternal) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -1315,3 +1929,162 @@ func (res *StructsInternal) FromStackItem(item stackitem.Item) error { return nil } + +// ToStackItem creates [stackitem.Item] representing StructsInternal. +// It implements [stackitem.Convertible] interface. +func (res *StructsInternal) ToStackItem() (stackitem.Item, error) { + if res == nil { + return stackitem.Null{}, nil + } + + var ( + err error + itm stackitem.Item + items = make([]stackitem.Item, 0, 14) + ) + itm, err = stackitem.NewBool(res.Bool), error(nil) + if err != nil { + return fmt.Errorf("field Bool: %w", err) + } + items = append(items, itm) + + itm, err = (*stackitem.BigInteger)(res.Int), error(nil) + if err != nil { + return fmt.Errorf("field Int: %w", err) + } + items = append(items, itm) + + itm, err = stackitem.NewByteArray(res.Bytes), error(nil) + if err != nil { + return fmt.Errorf("field Bytes: %w", err) + } + items = append(items, itm) + + itm, err = stackitem.NewByteArray([]byte(res.String)), error(nil) + if err != nil { + return fmt.Errorf("field String: %w", err) + } + items = append(items, itm) + + itm, err = stackitem.NewByteArray(res.H160.BytesBE()), error(nil) + if err != nil { + return fmt.Errorf("field H160: %w", err) + } + items = append(items, itm) + + itm, err = stackitem.NewByteArray(res.H256.BytesBE()), error(nil) + if err != nil { + return fmt.Errorf("field H256: %w", err) + } + items = append(items, itm) + + itm, err = stackitem.NewByteArray(res.PK.Bytes()), error(nil) + if err != nil { + return fmt.Errorf("field PK: %w", err) + } + items = append(items, itm) + + itm, err = stackitem.NewByteArray(res.PubKey.Bytes()), error(nil) + if err != nil { + return fmt.Errorf("field PubKey: %w", err) + } + items = append(items, itm) + + itm, err = stackitem.NewByteArray(res.Sign), error(nil) + if err != nil { + return fmt.Errorf("field Sign: %w", err) + } + items = append(items, itm) + + itm, err = func(in [][]byte) (stackitem.Item, error) { + if in == nil { + return stackitem.Null{}, nil + } + + var items = make([]stackitem.Item, 0, len(in)) + for i, v := range in { + itm, err := stackitem.NewByteArray(v), error(nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + items = append(items, itm) + } + return stackitem.NewArray(items), nil + }(res.ArrOfBytes) + if err != nil { + return fmt.Errorf("field ArrOfBytes: %w", err) + } + items = append(items, itm) + + itm, err = func(in []util.Uint160) (stackitem.Item, error) { + if in == nil { + return stackitem.Null{}, nil + } + + var items = make([]stackitem.Item, 0, len(in)) + for i, v := range in { + itm, err := stackitem.NewByteArray(v.BytesBE()), error(nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + items = append(items, itm) + } + return stackitem.NewArray(items), nil + }(res.ArrOfH160) + if err != nil { + return fmt.Errorf("field ArrOfH160: %w", err) + } + items = append(items, itm) + + itm, err = func(in map[*big.Int]keys.PublicKeys) (stackitem.Item, error) { + if in == nil { + return stackitem.Null{}, nil + } + + var m = stackitem.NewMap() + for k, v := range in { + iKey, err := (*stackitem.BigInteger)(k), error(nil) + if err != nil { + return nil, fmt.Errorf("key %v: %w", k, err) + } + iVal, err := func(in keys.PublicKeys) (stackitem.Item, error) { + if in == nil { + return stackitem.Null{}, nil + } + + var items = make([]stackitem.Item, 0, len(in)) + for i, v := range in { + itm, err := stackitem.NewByteArray(v.Bytes()), error(nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + items = append(items, itm) + } + return stackitem.NewArray(items), nil + }(v) + if err != nil { + return nil, fmt.Errorf("key %v, wrong value: %w", k, err) + } + m.Add(iKey, iVal) + } + return m, nil + }(res.Map) + if err != nil { + return fmt.Errorf("field Map: %w", err) + } + items = append(items, itm) + + itm, err = res.Struct.ToStackItem() + if err != nil { + return fmt.Errorf("field Struct: %w", err) + } + items = append(items, itm) + + itm, err = (*stackitem.BigInteger)(res.UnexportedField), error(nil) + if err != nil { + return fmt.Errorf("field UnexportedField: %w", err) + } + items = append(items, itm) + + return stackitem.NewStruct(items), nil +} diff --git a/cli/smartcontract/testdata/rpcbindings/structs/rpcbindings_dynamic_hash.out b/cli/smartcontract/testdata/rpcbindings/structs/rpcbindings_dynamic_hash.out index 56814fff4..627fce5e9 100755 --- a/cli/smartcontract/testdata/rpcbindings/structs/rpcbindings_dynamic_hash.out +++ b/cli/smartcontract/testdata/rpcbindings/structs/rpcbindings_dynamic_hash.out @@ -171,8 +171,12 @@ func itemToLedgerBlock(item stackitem.Item, err error) (*LedgerBlock, error) { return res, err } +// Ensure *LedgerBlock is a proper [stackitem.Convertible]. +var _ = stackitem.Convertible(&LedgerBlock{}) + // FromStackItem retrieves fields of LedgerBlock from the given // [stackitem.Item] or returns an error if it's not possible to do to so. +// It implements [stackitem.Convertible] interface. func (res *LedgerBlock) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -289,6 +293,81 @@ func (res *LedgerBlock) FromStackItem(item stackitem.Item) error { return nil } +// ToStackItem creates [stackitem.Item] representing LedgerBlock. +// It implements [stackitem.Convertible] interface. +func (res *LedgerBlock) ToStackItem() (stackitem.Item, error) { + if res == nil { + return stackitem.Null{}, nil + } + + var ( + err error + itm stackitem.Item + items = make([]stackitem.Item, 0, 10) + ) + itm, err = stackitem.NewByteArray(res.Hash.BytesBE()), error(nil) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + items = append(items, itm) + + itm, err = (*stackitem.BigInteger)(res.Version), error(nil) + if err != nil { + return fmt.Errorf("field Version: %w", err) + } + items = append(items, itm) + + itm, err = stackitem.NewByteArray(res.PrevHash.BytesBE()), error(nil) + if err != nil { + return fmt.Errorf("field PrevHash: %w", err) + } + items = append(items, itm) + + itm, err = stackitem.NewByteArray(res.MerkleRoot.BytesBE()), error(nil) + if err != nil { + return fmt.Errorf("field MerkleRoot: %w", err) + } + items = append(items, itm) + + itm, err = (*stackitem.BigInteger)(res.Timestamp), error(nil) + if err != nil { + return fmt.Errorf("field Timestamp: %w", err) + } + items = append(items, itm) + + itm, err = (*stackitem.BigInteger)(res.Nonce), error(nil) + if err != nil { + return fmt.Errorf("field Nonce: %w", err) + } + items = append(items, itm) + + itm, err = (*stackitem.BigInteger)(res.Index), error(nil) + if err != nil { + return fmt.Errorf("field Index: %w", err) + } + items = append(items, itm) + + itm, err = (*stackitem.BigInteger)(res.PrimaryIndex), error(nil) + if err != nil { + return fmt.Errorf("field PrimaryIndex: %w", err) + } + items = append(items, itm) + + itm, err = stackitem.NewByteArray(res.NextConsensus.BytesBE()), error(nil) + if err != nil { + return fmt.Errorf("field NextConsensus: %w", err) + } + items = append(items, itm) + + itm, err = (*stackitem.BigInteger)(res.TransactionsLength), error(nil) + if err != nil { + return fmt.Errorf("field TransactionsLength: %w", err) + } + items = append(items, itm) + + return stackitem.NewStruct(items), nil +} + // itemToLedgerTransaction converts stack item into *LedgerTransaction. // NULL item is returned as nil pointer without error. func itemToLedgerTransaction(item stackitem.Item, err error) (*LedgerTransaction, error) { @@ -304,8 +383,12 @@ func itemToLedgerTransaction(item stackitem.Item, err error) (*LedgerTransaction return res, err } +// Ensure *LedgerTransaction is a proper [stackitem.Convertible]. +var _ = stackitem.Convertible(&LedgerTransaction{}) + // FromStackItem retrieves fields of LedgerTransaction from the given // [stackitem.Item] or returns an error if it's not possible to do to so. +// It implements [stackitem.Convertible] interface. func (res *LedgerTransaction) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -390,6 +473,69 @@ func (res *LedgerTransaction) FromStackItem(item stackitem.Item) error { return nil } +// ToStackItem creates [stackitem.Item] representing LedgerTransaction. +// It implements [stackitem.Convertible] interface. +func (res *LedgerTransaction) ToStackItem() (stackitem.Item, error) { + if res == nil { + return stackitem.Null{}, nil + } + + var ( + err error + itm stackitem.Item + items = make([]stackitem.Item, 0, 8) + ) + itm, err = stackitem.NewByteArray(res.Hash.BytesBE()), error(nil) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + items = append(items, itm) + + itm, err = (*stackitem.BigInteger)(res.Version), error(nil) + if err != nil { + return fmt.Errorf("field Version: %w", err) + } + items = append(items, itm) + + itm, err = (*stackitem.BigInteger)(res.Nonce), error(nil) + if err != nil { + return fmt.Errorf("field Nonce: %w", err) + } + items = append(items, itm) + + itm, err = stackitem.NewByteArray(res.Sender.BytesBE()), error(nil) + if err != nil { + return fmt.Errorf("field Sender: %w", err) + } + items = append(items, itm) + + itm, err = (*stackitem.BigInteger)(res.SysFee), error(nil) + if err != nil { + return fmt.Errorf("field SysFee: %w", err) + } + items = append(items, itm) + + itm, err = (*stackitem.BigInteger)(res.NetFee), error(nil) + if err != nil { + return fmt.Errorf("field NetFee: %w", err) + } + items = append(items, itm) + + itm, err = (*stackitem.BigInteger)(res.ValidUntilBlock), error(nil) + if err != nil { + return fmt.Errorf("field ValidUntilBlock: %w", err) + } + items = append(items, itm) + + itm, err = stackitem.NewByteArray(res.Script), error(nil) + if err != nil { + return fmt.Errorf("field Script: %w", err) + } + items = append(items, itm) + + return stackitem.NewStruct(items), nil +} + // itemToManagementABI converts stack item into *ManagementABI. // NULL item is returned as nil pointer without error. func itemToManagementABI(item stackitem.Item, err error) (*ManagementABI, error) { @@ -405,8 +551,12 @@ func itemToManagementABI(item stackitem.Item, err error) (*ManagementABI, error) return res, err } +// Ensure *ManagementABI is a proper [stackitem.Convertible]. +var _ = stackitem.Convertible(&ManagementABI{}) + // FromStackItem retrieves fields of ManagementABI from the given // [stackitem.Item] or returns an error if it's not possible to do to so. +// It implements [stackitem.Convertible] interface. func (res *ManagementABI) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -461,6 +611,61 @@ func (res *ManagementABI) FromStackItem(item stackitem.Item) error { return nil } +// ToStackItem creates [stackitem.Item] representing ManagementABI. +// It implements [stackitem.Convertible] interface. +func (res *ManagementABI) ToStackItem() (stackitem.Item, error) { + if res == nil { + return stackitem.Null{}, nil + } + + var ( + err error + itm stackitem.Item + items = make([]stackitem.Item, 0, 2) + ) + itm, err = func(in []*ManagementMethod) (stackitem.Item, error) { + if in == nil { + return stackitem.Null{}, nil + } + + var items = make([]stackitem.Item, 0, len(in)) + for i, v := range in { + itm, err := v.ToStackItem() + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + items = append(items, itm) + } + return stackitem.NewArray(items), nil + }(res.Methods) + if err != nil { + return fmt.Errorf("field Methods: %w", err) + } + items = append(items, itm) + + itm, err = func(in []*ManagementEvent) (stackitem.Item, error) { + if in == nil { + return stackitem.Null{}, nil + } + + var items = make([]stackitem.Item, 0, len(in)) + for i, v := range in { + itm, err := v.ToStackItem() + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + items = append(items, itm) + } + return stackitem.NewArray(items), nil + }(res.Events) + if err != nil { + return fmt.Errorf("field Events: %w", err) + } + items = append(items, itm) + + return stackitem.NewStruct(items), nil +} + // itemToManagementContract converts stack item into *ManagementContract. // NULL item is returned as nil pointer without error. func itemToManagementContract(item stackitem.Item, err error) (*ManagementContract, error) { @@ -476,8 +681,12 @@ func itemToManagementContract(item stackitem.Item, err error) (*ManagementContra return res, err } +// Ensure *ManagementContract is a proper [stackitem.Convertible]. +var _ = stackitem.Convertible(&ManagementContract{}) + // FromStackItem retrieves fields of ManagementContract from the given // [stackitem.Item] or returns an error if it's not possible to do to so. +// It implements [stackitem.Convertible] interface. func (res *ManagementContract) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -534,6 +743,51 @@ func (res *ManagementContract) FromStackItem(item stackitem.Item) error { return nil } +// ToStackItem creates [stackitem.Item] representing ManagementContract. +// It implements [stackitem.Convertible] interface. +func (res *ManagementContract) ToStackItem() (stackitem.Item, error) { + if res == nil { + return stackitem.Null{}, nil + } + + var ( + err error + itm stackitem.Item + items = make([]stackitem.Item, 0, 5) + ) + itm, err = (*stackitem.BigInteger)(res.ID), error(nil) + if err != nil { + return fmt.Errorf("field ID: %w", err) + } + items = append(items, itm) + + itm, err = (*stackitem.BigInteger)(res.UpdateCounter), error(nil) + if err != nil { + return fmt.Errorf("field UpdateCounter: %w", err) + } + items = append(items, itm) + + itm, err = stackitem.NewByteArray(res.Hash.BytesBE()), error(nil) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + items = append(items, itm) + + itm, err = stackitem.NewByteArray(res.NEF), error(nil) + if err != nil { + return fmt.Errorf("field NEF: %w", err) + } + items = append(items, itm) + + itm, err = res.Manifest.ToStackItem() + if err != nil { + return fmt.Errorf("field Manifest: %w", err) + } + items = append(items, itm) + + return stackitem.NewStruct(items), nil +} + // itemToManagementEvent converts stack item into *ManagementEvent. // NULL item is returned as nil pointer without error. func itemToManagementEvent(item stackitem.Item, err error) (*ManagementEvent, error) { @@ -549,8 +803,12 @@ func itemToManagementEvent(item stackitem.Item, err error) (*ManagementEvent, er return res, err } +// Ensure *ManagementEvent is a proper [stackitem.Convertible]. +var _ = stackitem.Convertible(&ManagementEvent{}) + // FromStackItem retrieves fields of ManagementEvent from the given // [stackitem.Item] or returns an error if it's not possible to do to so. +// It implements [stackitem.Convertible] interface. func (res *ManagementEvent) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -601,6 +859,47 @@ func (res *ManagementEvent) FromStackItem(item stackitem.Item) error { return nil } +// ToStackItem creates [stackitem.Item] representing ManagementEvent. +// It implements [stackitem.Convertible] interface. +func (res *ManagementEvent) ToStackItem() (stackitem.Item, error) { + if res == nil { + return stackitem.Null{}, nil + } + + var ( + err error + itm stackitem.Item + items = make([]stackitem.Item, 0, 2) + ) + itm, err = stackitem.NewByteArray([]byte(res.Name)), error(nil) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + items = append(items, itm) + + itm, err = func(in []*ManagementParameter) (stackitem.Item, error) { + if in == nil { + return stackitem.Null{}, nil + } + + var items = make([]stackitem.Item, 0, len(in)) + for i, v := range in { + itm, err := v.ToStackItem() + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + items = append(items, itm) + } + return stackitem.NewArray(items), nil + }(res.Params) + if err != nil { + return fmt.Errorf("field Params: %w", err) + } + items = append(items, itm) + + return stackitem.NewStruct(items), nil +} + // itemToManagementGroup converts stack item into *ManagementGroup. // NULL item is returned as nil pointer without error. func itemToManagementGroup(item stackitem.Item, err error) (*ManagementGroup, error) { @@ -616,8 +915,12 @@ func itemToManagementGroup(item stackitem.Item, err error) (*ManagementGroup, er return res, err } +// Ensure *ManagementGroup is a proper [stackitem.Convertible]. +var _ = stackitem.Convertible(&ManagementGroup{}) + // FromStackItem retrieves fields of ManagementGroup from the given // [stackitem.Item] or returns an error if it's not possible to do to so. +// It implements [stackitem.Convertible] interface. func (res *ManagementGroup) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -656,6 +959,33 @@ func (res *ManagementGroup) FromStackItem(item stackitem.Item) error { return nil } +// ToStackItem creates [stackitem.Item] representing ManagementGroup. +// It implements [stackitem.Convertible] interface. +func (res *ManagementGroup) ToStackItem() (stackitem.Item, error) { + if res == nil { + return stackitem.Null{}, nil + } + + var ( + err error + itm stackitem.Item + items = make([]stackitem.Item, 0, 2) + ) + itm, err = stackitem.NewByteArray(res.PublicKey.Bytes()), error(nil) + if err != nil { + return fmt.Errorf("field PublicKey: %w", err) + } + items = append(items, itm) + + itm, err = stackitem.NewByteArray(res.Signature), error(nil) + if err != nil { + return fmt.Errorf("field Signature: %w", err) + } + items = append(items, itm) + + return stackitem.NewStruct(items), nil +} + // itemToManagementManifest converts stack item into *ManagementManifest. // NULL item is returned as nil pointer without error. func itemToManagementManifest(item stackitem.Item, err error) (*ManagementManifest, error) { @@ -671,8 +1001,12 @@ func itemToManagementManifest(item stackitem.Item, err error) (*ManagementManife return res, err } +// Ensure *ManagementManifest is a proper [stackitem.Convertible]. +var _ = stackitem.Convertible(&ManagementManifest{}) + // FromStackItem retrieves fields of ManagementManifest from the given // [stackitem.Item] or returns an error if it's not possible to do to so. +// It implements [stackitem.Convertible] interface. func (res *ManagementManifest) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -853,6 +1187,143 @@ func (res *ManagementManifest) FromStackItem(item stackitem.Item) error { return nil } +// ToStackItem creates [stackitem.Item] representing ManagementManifest. +// It implements [stackitem.Convertible] interface. +func (res *ManagementManifest) ToStackItem() (stackitem.Item, error) { + if res == nil { + return stackitem.Null{}, nil + } + + var ( + err error + itm stackitem.Item + items = make([]stackitem.Item, 0, 8) + ) + itm, err = stackitem.NewByteArray([]byte(res.Name)), error(nil) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + items = append(items, itm) + + itm, err = func(in []*ManagementGroup) (stackitem.Item, error) { + if in == nil { + return stackitem.Null{}, nil + } + + var items = make([]stackitem.Item, 0, len(in)) + for i, v := range in { + itm, err := v.ToStackItem() + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + items = append(items, itm) + } + return stackitem.NewArray(items), nil + }(res.Groups) + if err != nil { + return fmt.Errorf("field Groups: %w", err) + } + items = append(items, itm) + + itm, err = func(in map[string]string) (stackitem.Item, error) { + if in == nil { + return stackitem.Null{}, nil + } + + var m = stackitem.NewMap() + for k, v := range in { + iKey, err := stackitem.NewByteArray([]byte(k)), error(nil) + if err != nil { + return nil, fmt.Errorf("key %v: %w", k, err) + } + iVal, err := stackitem.NewByteArray([]byte(v)), error(nil) + if err != nil { + return nil, fmt.Errorf("key %v, wrong value: %w", k, err) + } + m.Add(iKey, iVal) + } + return m, nil + }(res.Features) + if err != nil { + return fmt.Errorf("field Features: %w", err) + } + items = append(items, itm) + + itm, err = func(in []string) (stackitem.Item, error) { + if in == nil { + return stackitem.Null{}, nil + } + + var items = make([]stackitem.Item, 0, len(in)) + for i, v := range in { + itm, err := stackitem.NewByteArray([]byte(v)), error(nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + items = append(items, itm) + } + return stackitem.NewArray(items), nil + }(res.SupportedStandards) + if err != nil { + return fmt.Errorf("field SupportedStandards: %w", err) + } + items = append(items, itm) + + itm, err = res.ABI.ToStackItem() + if err != nil { + return fmt.Errorf("field ABI: %w", err) + } + items = append(items, itm) + + itm, err = func(in []*ManagementPermission) (stackitem.Item, error) { + if in == nil { + return stackitem.Null{}, nil + } + + var items = make([]stackitem.Item, 0, len(in)) + for i, v := range in { + itm, err := v.ToStackItem() + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + items = append(items, itm) + } + return stackitem.NewArray(items), nil + }(res.Permissions) + if err != nil { + return fmt.Errorf("field Permissions: %w", err) + } + items = append(items, itm) + + itm, err = func(in []util.Uint160) (stackitem.Item, error) { + if in == nil { + return stackitem.Null{}, nil + } + + var items = make([]stackitem.Item, 0, len(in)) + for i, v := range in { + itm, err := stackitem.NewByteArray(v.BytesBE()), error(nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + items = append(items, itm) + } + return stackitem.NewArray(items), nil + }(res.Trusts) + if err != nil { + return fmt.Errorf("field Trusts: %w", err) + } + items = append(items, itm) + + itm, err = stackitem.TryMake(res.Extra) + if err != nil { + return fmt.Errorf("field Extra: %w", err) + } + items = append(items, itm) + + return stackitem.NewStruct(items), nil +} + // itemToManagementMethod converts stack item into *ManagementMethod. // NULL item is returned as nil pointer without error. func itemToManagementMethod(item stackitem.Item, err error) (*ManagementMethod, error) { @@ -868,8 +1339,12 @@ func itemToManagementMethod(item stackitem.Item, err error) (*ManagementMethod, return res, err } +// Ensure *ManagementMethod is a proper [stackitem.Convertible]. +var _ = stackitem.Convertible(&ManagementMethod{}) + // FromStackItem retrieves fields of ManagementMethod from the given // [stackitem.Item] or returns an error if it's not possible to do to so. +// It implements [stackitem.Convertible] interface. func (res *ManagementMethod) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -938,6 +1413,65 @@ func (res *ManagementMethod) FromStackItem(item stackitem.Item) error { return nil } +// ToStackItem creates [stackitem.Item] representing ManagementMethod. +// It implements [stackitem.Convertible] interface. +func (res *ManagementMethod) ToStackItem() (stackitem.Item, error) { + if res == nil { + return stackitem.Null{}, nil + } + + var ( + err error + itm stackitem.Item + items = make([]stackitem.Item, 0, 5) + ) + itm, err = stackitem.NewByteArray([]byte(res.Name)), error(nil) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + items = append(items, itm) + + itm, err = func(in []*ManagementParameter) (stackitem.Item, error) { + if in == nil { + return stackitem.Null{}, nil + } + + var items = make([]stackitem.Item, 0, len(in)) + for i, v := range in { + itm, err := v.ToStackItem() + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + items = append(items, itm) + } + return stackitem.NewArray(items), nil + }(res.Params) + if err != nil { + return fmt.Errorf("field Params: %w", err) + } + items = append(items, itm) + + itm, err = (*stackitem.BigInteger)(res.ReturnType), error(nil) + if err != nil { + return fmt.Errorf("field ReturnType: %w", err) + } + items = append(items, itm) + + itm, err = (*stackitem.BigInteger)(res.Offset), error(nil) + if err != nil { + return fmt.Errorf("field Offset: %w", err) + } + items = append(items, itm) + + itm, err = stackitem.NewBool(res.Safe), error(nil) + if err != nil { + return fmt.Errorf("field Safe: %w", err) + } + items = append(items, itm) + + return stackitem.NewStruct(items), nil +} + // itemToManagementParameter converts stack item into *ManagementParameter. // NULL item is returned as nil pointer without error. func itemToManagementParameter(item stackitem.Item, err error) (*ManagementParameter, error) { @@ -953,8 +1487,12 @@ func itemToManagementParameter(item stackitem.Item, err error) (*ManagementParam return res, err } +// Ensure *ManagementParameter is a proper [stackitem.Convertible]. +var _ = stackitem.Convertible(&ManagementParameter{}) + // FromStackItem retrieves fields of ManagementParameter from the given // [stackitem.Item] or returns an error if it's not possible to do to so. +// It implements [stackitem.Convertible] interface. func (res *ManagementParameter) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -992,6 +1530,33 @@ func (res *ManagementParameter) FromStackItem(item stackitem.Item) error { return nil } +// ToStackItem creates [stackitem.Item] representing ManagementParameter. +// It implements [stackitem.Convertible] interface. +func (res *ManagementParameter) ToStackItem() (stackitem.Item, error) { + if res == nil { + return stackitem.Null{}, nil + } + + var ( + err error + itm stackitem.Item + items = make([]stackitem.Item, 0, 2) + ) + itm, err = stackitem.NewByteArray([]byte(res.Name)), error(nil) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + items = append(items, itm) + + itm, err = (*stackitem.BigInteger)(res.Type), error(nil) + if err != nil { + return fmt.Errorf("field Type: %w", err) + } + items = append(items, itm) + + return stackitem.NewStruct(items), nil +} + // itemToManagementPermission converts stack item into *ManagementPermission. // NULL item is returned as nil pointer without error. func itemToManagementPermission(item stackitem.Item, err error) (*ManagementPermission, error) { @@ -1007,8 +1572,12 @@ func itemToManagementPermission(item stackitem.Item, err error) (*ManagementPerm return res, err } +// Ensure *ManagementPermission is a proper [stackitem.Convertible]. +var _ = stackitem.Convertible(&ManagementPermission{}) + // FromStackItem retrieves fields of ManagementPermission from the given // [stackitem.Item] or returns an error if it's not possible to do to so. +// It implements [stackitem.Convertible] interface. func (res *ManagementPermission) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -1069,6 +1638,47 @@ func (res *ManagementPermission) FromStackItem(item stackitem.Item) error { return nil } +// ToStackItem creates [stackitem.Item] representing ManagementPermission. +// It implements [stackitem.Convertible] interface. +func (res *ManagementPermission) ToStackItem() (stackitem.Item, error) { + if res == nil { + return stackitem.Null{}, nil + } + + var ( + err error + itm stackitem.Item + items = make([]stackitem.Item, 0, 2) + ) + itm, err = stackitem.NewByteArray(res.Contract.BytesBE()), error(nil) + if err != nil { + return fmt.Errorf("field Contract: %w", err) + } + items = append(items, itm) + + itm, err = func(in []string) (stackitem.Item, error) { + if in == nil { + return stackitem.Null{}, nil + } + + var items = make([]stackitem.Item, 0, len(in)) + for i, v := range in { + itm, err := stackitem.NewByteArray([]byte(v)), error(nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + items = append(items, itm) + } + return stackitem.NewArray(items), nil + }(res.Methods) + if err != nil { + return fmt.Errorf("field Methods: %w", err) + } + items = append(items, itm) + + return stackitem.NewStruct(items), nil +} + // itemToStructsInternal converts stack item into *StructsInternal. // NULL item is returned as nil pointer without error. func itemToStructsInternal(item stackitem.Item, err error) (*StructsInternal, error) { @@ -1084,8 +1694,12 @@ func itemToStructsInternal(item stackitem.Item, err error) (*StructsInternal, er return res, err } +// Ensure *StructsInternal is a proper [stackitem.Convertible]. +var _ = stackitem.Convertible(&StructsInternal{}) + // FromStackItem retrieves fields of StructsInternal from the given // [stackitem.Item] or returns an error if it's not possible to do to so. +// It implements [stackitem.Convertible] interface. func (res *StructsInternal) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -1311,3 +1925,162 @@ func (res *StructsInternal) FromStackItem(item stackitem.Item) error { return nil } + +// ToStackItem creates [stackitem.Item] representing StructsInternal. +// It implements [stackitem.Convertible] interface. +func (res *StructsInternal) ToStackItem() (stackitem.Item, error) { + if res == nil { + return stackitem.Null{}, nil + } + + var ( + err error + itm stackitem.Item + items = make([]stackitem.Item, 0, 14) + ) + itm, err = stackitem.NewBool(res.Bool), error(nil) + if err != nil { + return fmt.Errorf("field Bool: %w", err) + } + items = append(items, itm) + + itm, err = (*stackitem.BigInteger)(res.Int), error(nil) + if err != nil { + return fmt.Errorf("field Int: %w", err) + } + items = append(items, itm) + + itm, err = stackitem.NewByteArray(res.Bytes), error(nil) + if err != nil { + return fmt.Errorf("field Bytes: %w", err) + } + items = append(items, itm) + + itm, err = stackitem.NewByteArray([]byte(res.String)), error(nil) + if err != nil { + return fmt.Errorf("field String: %w", err) + } + items = append(items, itm) + + itm, err = stackitem.NewByteArray(res.H160.BytesBE()), error(nil) + if err != nil { + return fmt.Errorf("field H160: %w", err) + } + items = append(items, itm) + + itm, err = stackitem.NewByteArray(res.H256.BytesBE()), error(nil) + if err != nil { + return fmt.Errorf("field H256: %w", err) + } + items = append(items, itm) + + itm, err = stackitem.NewByteArray(res.PK.Bytes()), error(nil) + if err != nil { + return fmt.Errorf("field PK: %w", err) + } + items = append(items, itm) + + itm, err = stackitem.NewByteArray(res.PubKey.Bytes()), error(nil) + if err != nil { + return fmt.Errorf("field PubKey: %w", err) + } + items = append(items, itm) + + itm, err = stackitem.NewByteArray(res.Sign), error(nil) + if err != nil { + return fmt.Errorf("field Sign: %w", err) + } + items = append(items, itm) + + itm, err = func(in [][]byte) (stackitem.Item, error) { + if in == nil { + return stackitem.Null{}, nil + } + + var items = make([]stackitem.Item, 0, len(in)) + for i, v := range in { + itm, err := stackitem.NewByteArray(v), error(nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + items = append(items, itm) + } + return stackitem.NewArray(items), nil + }(res.ArrOfBytes) + if err != nil { + return fmt.Errorf("field ArrOfBytes: %w", err) + } + items = append(items, itm) + + itm, err = func(in []util.Uint160) (stackitem.Item, error) { + if in == nil { + return stackitem.Null{}, nil + } + + var items = make([]stackitem.Item, 0, len(in)) + for i, v := range in { + itm, err := stackitem.NewByteArray(v.BytesBE()), error(nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + items = append(items, itm) + } + return stackitem.NewArray(items), nil + }(res.ArrOfH160) + if err != nil { + return fmt.Errorf("field ArrOfH160: %w", err) + } + items = append(items, itm) + + itm, err = func(in map[*big.Int]keys.PublicKeys) (stackitem.Item, error) { + if in == nil { + return stackitem.Null{}, nil + } + + var m = stackitem.NewMap() + for k, v := range in { + iKey, err := (*stackitem.BigInteger)(k), error(nil) + if err != nil { + return nil, fmt.Errorf("key %v: %w", k, err) + } + iVal, err := func(in keys.PublicKeys) (stackitem.Item, error) { + if in == nil { + return stackitem.Null{}, nil + } + + var items = make([]stackitem.Item, 0, len(in)) + for i, v := range in { + itm, err := stackitem.NewByteArray(v.Bytes()), error(nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + items = append(items, itm) + } + return stackitem.NewArray(items), nil + }(v) + if err != nil { + return nil, fmt.Errorf("key %v, wrong value: %w", k, err) + } + m.Add(iKey, iVal) + } + return m, nil + }(res.Map) + if err != nil { + return fmt.Errorf("field Map: %w", err) + } + items = append(items, itm) + + itm, err = res.Struct.ToStackItem() + if err != nil { + return fmt.Errorf("field Struct: %w", err) + } + items = append(items, itm) + + itm, err = (*stackitem.BigInteger)(res.UnexportedField), error(nil) + if err != nil { + return fmt.Errorf("field UnexportedField: %w", err) + } + items = append(items, itm) + + return stackitem.NewStruct(items), nil +} diff --git a/cli/smartcontract/testdata/rpcbindings/types/rpcbindings.out b/cli/smartcontract/testdata/rpcbindings/types/rpcbindings.out index 7ef32de13..9b872b653 100644 --- a/cli/smartcontract/testdata/rpcbindings/types/rpcbindings.out +++ b/cli/smartcontract/testdata/rpcbindings/types/rpcbindings.out @@ -384,8 +384,12 @@ func itemToUnnamed(item stackitem.Item, err error) (*Unnamed, error) { return res, err } +// Ensure *Unnamed is a proper [stackitem.Convertible]. +var _ = stackitem.Convertible(&Unnamed{}) + // FromStackItem retrieves fields of Unnamed from the given // [stackitem.Item] or returns an error if it's not possible to do to so. +// It implements [stackitem.Convertible] interface. func (res *Unnamed) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -408,6 +412,27 @@ func (res *Unnamed) FromStackItem(item stackitem.Item) error { return nil } +// ToStackItem creates [stackitem.Item] representing Unnamed. +// It implements [stackitem.Convertible] interface. +func (res *Unnamed) ToStackItem() (stackitem.Item, error) { + if res == nil { + return stackitem.Null{}, nil + } + + var ( + err error + itm stackitem.Item + items = make([]stackitem.Item, 0, 1) + ) + itm, err = (*stackitem.BigInteger)(res.I), error(nil) + if err != nil { + return fmt.Errorf("field I: %w", err) + } + items = append(items, itm) + + return stackitem.NewStruct(items), nil +} + // itemToUnnamedX converts stack item into *UnnamedX. // NULL item is returned as nil pointer without error. func itemToUnnamedX(item stackitem.Item, err error) (*UnnamedX, error) { @@ -423,8 +448,12 @@ func itemToUnnamedX(item stackitem.Item, err error) (*UnnamedX, error) { return res, err } +// Ensure *UnnamedX is a proper [stackitem.Convertible]. +var _ = stackitem.Convertible(&UnnamedX{}) + // FromStackItem retrieves fields of UnnamedX from the given // [stackitem.Item] or returns an error if it's not possible to do to so. +// It implements [stackitem.Convertible] interface. func (res *UnnamedX) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -452,3 +481,30 @@ func (res *UnnamedX) FromStackItem(item stackitem.Item) error { return nil } + +// ToStackItem creates [stackitem.Item] representing UnnamedX. +// It implements [stackitem.Convertible] interface. +func (res *UnnamedX) ToStackItem() (stackitem.Item, error) { + if res == nil { + return stackitem.Null{}, nil + } + + var ( + err error + itm stackitem.Item + items = make([]stackitem.Item, 0, 2) + ) + itm, err = (*stackitem.BigInteger)(res.I), error(nil) + if err != nil { + return fmt.Errorf("field I: %w", err) + } + items = append(items, itm) + + itm, err = stackitem.NewBool(res.B), error(nil) + if err != nil { + return fmt.Errorf("field B: %w", err) + } + items = append(items, itm) + + return stackitem.NewStruct(items), nil +} diff --git a/cli/smartcontract/testdata/rpcbindings/types/rpcbindings_dynamic_hash.out b/cli/smartcontract/testdata/rpcbindings/types/rpcbindings_dynamic_hash.out index cdd066287..fe34c4272 100755 --- a/cli/smartcontract/testdata/rpcbindings/types/rpcbindings_dynamic_hash.out +++ b/cli/smartcontract/testdata/rpcbindings/types/rpcbindings_dynamic_hash.out @@ -380,8 +380,12 @@ func itemToUnnamed(item stackitem.Item, err error) (*Unnamed, error) { return res, err } +// Ensure *Unnamed is a proper [stackitem.Convertible]. +var _ = stackitem.Convertible(&Unnamed{}) + // FromStackItem retrieves fields of Unnamed from the given // [stackitem.Item] or returns an error if it's not possible to do to so. +// It implements [stackitem.Convertible] interface. func (res *Unnamed) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -404,6 +408,27 @@ func (res *Unnamed) FromStackItem(item stackitem.Item) error { return nil } +// ToStackItem creates [stackitem.Item] representing Unnamed. +// It implements [stackitem.Convertible] interface. +func (res *Unnamed) ToStackItem() (stackitem.Item, error) { + if res == nil { + return stackitem.Null{}, nil + } + + var ( + err error + itm stackitem.Item + items = make([]stackitem.Item, 0, 1) + ) + itm, err = (*stackitem.BigInteger)(res.I), error(nil) + if err != nil { + return fmt.Errorf("field I: %w", err) + } + items = append(items, itm) + + return stackitem.NewStruct(items), nil +} + // itemToUnnamedX converts stack item into *UnnamedX. // NULL item is returned as nil pointer without error. func itemToUnnamedX(item stackitem.Item, err error) (*UnnamedX, error) { @@ -419,8 +444,12 @@ func itemToUnnamedX(item stackitem.Item, err error) (*UnnamedX, error) { return res, err } +// Ensure *UnnamedX is a proper [stackitem.Convertible]. +var _ = stackitem.Convertible(&UnnamedX{}) + // FromStackItem retrieves fields of UnnamedX from the given // [stackitem.Item] or returns an error if it's not possible to do to so. +// It implements [stackitem.Convertible] interface. func (res *UnnamedX) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -448,3 +477,30 @@ func (res *UnnamedX) FromStackItem(item stackitem.Item) error { return nil } + +// ToStackItem creates [stackitem.Item] representing UnnamedX. +// It implements [stackitem.Convertible] interface. +func (res *UnnamedX) ToStackItem() (stackitem.Item, error) { + if res == nil { + return stackitem.Null{}, nil + } + + var ( + err error + itm stackitem.Item + items = make([]stackitem.Item, 0, 2) + ) + itm, err = (*stackitem.BigInteger)(res.I), error(nil) + if err != nil { + return fmt.Errorf("field I: %w", err) + } + items = append(items, itm) + + itm, err = stackitem.NewBool(res.B), error(nil) + if err != nil { + return fmt.Errorf("field B: %w", err) + } + items = append(items, itm) + + return stackitem.NewStruct(items), nil +} diff --git a/pkg/smartcontract/rpcbinding/binding.go b/pkg/smartcontract/rpcbinding/binding.go index 729893b7b..63b8c0fdf 100644 --- a/pkg/smartcontract/rpcbinding/binding.go +++ b/pkg/smartcontract/rpcbinding/binding.go @@ -259,8 +259,12 @@ func itemTo{{toTypeName $typ.Name}}(item stackitem.Item, err error) (*{{toTypeNa return res, err } +// Ensure *{{toTypeName $typ.Name}} is a proper [stackitem.Convertible]. +var _ = stackitem.Convertible(&{{toTypeName $typ.Name}}{}) + // FromStackItem retrieves fields of {{toTypeName $typ.Name}} from the given // [stackitem.Item] or returns an error if it's not possible to do to so. +// It implements [stackitem.Convertible] interface. func (res *{{toTypeName $typ.Name}}) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -284,6 +288,29 @@ func (res *{{toTypeName $typ.Name}}) FromStackItem(item stackitem.Item) error { {{- end}} return nil } + +// ToStackItem creates [stackitem.Item] representing {{toTypeName $typ.Name}}. +// It implements [stackitem.Convertible] interface. +func (res *{{toTypeName $typ.Name}}) ToStackItem() (stackitem.Item, error) { + if res == nil { + return stackitem.Null{}, nil + } + + var ( + err error + itm stackitem.Item + items = make([]stackitem.Item, 0, {{len .Fields}}) + ) + +{{- range $m := $typ.Fields}} + itm, err = {{goTypeConverter .ExtendedType (print "res." (upperFirst .Field))}} + if err != nil { + return fmt.Errorf("field {{ upperFirst .Field}}: %w", err) + } + items = append(items, itm) +{{end}} + return stackitem.NewStruct(items), nil +} {{ end -}} {{- range $e := .CustomEvents }} // {{$e.Name}}sFromApplicationLog retrieves a set of all emitted events @@ -503,9 +530,10 @@ func Generate(cfg binding.Config) error { r, _ := extendedTypeToGo(et, cfg.NamedTypes) return r }, - "toTypeName": toTypeName, - "cutPointer": cutPointer, - "upperFirst": upperFirst, + "goTypeConverter": goTypeConverter, + "toTypeName": toTypeName, + "cutPointer": cutPointer, + "upperFirst": upperFirst, }).Parse(srcTmpl)) return binding.FExecute(srcTemplate, cfg.Output, ctr) @@ -757,6 +785,92 @@ func etTypeConverter(et binding.ExtendedType, v string) string { } } +func goTypeConverter(et binding.ExtendedType, v string) string { + switch et.Base { + case smartcontract.AnyType: + return "stackitem.TryMake(" + v + ")" + case smartcontract.BoolType: + return "stackitem.NewBool(" + v + "), error(nil)" + case smartcontract.IntegerType: + return "(*stackitem.BigInteger)(" + v + "), error(nil)" + case smartcontract.ByteArrayType, smartcontract.SignatureType: + return "stackitem.NewByteArray(" + v + "), error(nil)" + case smartcontract.StringType: + return "stackitem.NewByteArray([]byte(" + v + ")), error(nil)" + case smartcontract.Hash160Type: + return "stackitem.NewByteArray(" + v + ".BytesBE()), error(nil)" + case smartcontract.Hash256Type: + return "stackitem.NewByteArray(" + v + ".BytesBE()), error(nil)" + case smartcontract.PublicKeyType: + return "stackitem.NewByteArray(" + v + ".Bytes()), error(nil)" + case smartcontract.ArrayType: + if len(et.Name) > 0 { + return v + ".ToStackItem()" + } else if et.Value != nil { + at, _ := extendedTypeToGo(et, nil) + return `func(in ` + at + `) (stackitem.Item, error) { + if in == nil { + return stackitem.Null{}, nil + } + + var items = make([]stackitem.Item, 0, len(in)) + for i, v := range in { + itm, err := ` + goTypeConverter(*et.Value, "v") + ` + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + items = append(items, itm) + } + return stackitem.NewArray(items), nil + }(` + v + `)` + } + return goTypeConverter(binding.ExtendedType{ + Base: smartcontract.ArrayType, + Value: &binding.ExtendedType{ + Base: smartcontract.AnyType, + }, + }, v) + + case smartcontract.MapType: + if et.Value != nil { + at, _ := extendedTypeToGo(et, nil) + return `func(in ` + at + `) (stackitem.Item, error) { + if in == nil { + return stackitem.Null{}, nil + } + + var m = stackitem.NewMap() + for k, v := range in { + iKey, err := ` + goTypeConverter(binding.ExtendedType{Base: et.Key}, "k") + ` + if err != nil { + return nil, fmt.Errorf("key %v: %w", k, err) + } + iVal, err := ` + goTypeConverter(*et.Value, "v") + ` + if err != nil { + return nil, fmt.Errorf("key %v, wrong value: %w", k, err) + } + m.Add(iKey, iVal) + } + return m, nil + }(` + v + `)` + } + + return goTypeConverter(binding.ExtendedType{ + Base: smartcontract.MapType, + Key: et.Key, + Value: &binding.ExtendedType{ + Base: smartcontract.AnyType, + }, + }, v) + case smartcontract.InteropInterfaceType: + return "stackitem.TryMake(" + v + ")" + case smartcontract.VoidType: + return "stackitem.TryMake(" + v + ")" + default: + panic("unreachable") + } +} + func scTypeToGo(name string, typ smartcontract.ParamType, cfg *binding.Config) (string, string) { et, ok := cfg.Types[name] if !ok {