From 7f9e2e504728c47386f04ec0b8569f3104c6d1d8 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Tue, 21 Nov 2023 17:41:34 +0300 Subject: [PATCH 1/6] cli/sc: don't rewrite RPC bindings by default TestAssistedRPCBindings didn't respect rewriteExpectedOutputs setting, with this behavior compiler could produce any result and the test wouldn't notice. Signed-off-by: Roman Khimov --- cli/smartcontract/generate_test.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cli/smartcontract/generate_test.go b/cli/smartcontract/generate_test.go index dffc1892e..4f09544a5 100644 --- a/cli/smartcontract/generate_test.go +++ b/cli/smartcontract/generate_test.go @@ -395,6 +395,7 @@ func TestAssistedRPCBindings(t *testing.T) { } testName += fmt.Sprintf(", predefined hash: %t", hasDefinedHash) t.Run(testName, func(t *testing.T) { + outFile := filepath.Join(tmpDir, "out.go") configFile := filepath.Join(source, "config.yml") expectedFile := filepath.Join(source, "rpcbindings.out") if len(suffix) != 0 { @@ -421,14 +422,14 @@ func TestAssistedRPCBindings(t *testing.T) { cmds := []string{"", "contract", "generate-rpcwrapper", "--config", bindingF, "--manifest", manifestF, - "--out", expectedFile, + "--out", outFile, } if hasDefinedHash { cmds = append(cmds, "--hash", "0x00112233445566778899aabbccddeeff00112233") } require.NoError(t, app.Run(cmds)) - data, err := os.ReadFile(expectedFile) + data, err := os.ReadFile(outFile) require.NoError(t, err) data = bytes.ReplaceAll(data, []byte("\r"), []byte{}) // Windows. if rewriteExpectedOutputs { From a5d041a1ac234fe5f0bb69c06dfe9a65191d83ba Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Tue, 21 Nov 2023 17:48:53 +0300 Subject: [PATCH 2/6] compiler: check range first, analyze funcs then Type data is added while walking through function ins/outs even if we're to throw this function away. But we don't need it, these types are not used, so we can deal with the main part of #3071 by optimizing this out. Signed-off-by: Roman Khimov --- .../rpcbindings/notifications/rpcbindings.out | 626 ------------------ .../notifications/rpcbindings_extended.out | 625 ----------------- .../notifications/rpcbindings_guessed.out | 625 ----------------- .../rpcbindings/structs/rpcbindings.out | 380 ----------- .../structs/rpcbindings_dynamic_hash.out | 380 ----------- pkg/compiler/debug.go | 4 +- 6 files changed, 2 insertions(+), 2638 deletions(-) diff --git a/cli/smartcontract/testdata/rpcbindings/notifications/rpcbindings.out b/cli/smartcontract/testdata/rpcbindings/notifications/rpcbindings.out index fb2c3b20b..957f75b32 100644 --- a/cli/smartcontract/testdata/rpcbindings/notifications/rpcbindings.out +++ b/cli/smartcontract/testdata/rpcbindings/notifications/rpcbindings.out @@ -4,81 +4,18 @@ package structs import ( - "crypto/elliptic" "errors" "fmt" "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/util" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" - "math/big" "unicode/utf8" ) // Hash contains contract hash. var Hash = util.Uint160{0x33, 0x22, 0x11, 0x0, 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x0} -// LedgerBlock is a contract-specific ledger.Block type used by its methods. -type LedgerBlock struct { - Hash util.Uint256 - Version *big.Int - PrevHash util.Uint256 - MerkleRoot util.Uint256 - Timestamp *big.Int - Nonce *big.Int - Index *big.Int - NextConsensus util.Uint160 - TransactionsLength *big.Int -} - -// LedgerBlockSR is a contract-specific ledger.BlockSR type used by its methods. -type LedgerBlockSR struct { - Hash util.Uint256 - Version *big.Int - PrevHash util.Uint256 - MerkleRoot util.Uint256 - Timestamp *big.Int - Nonce *big.Int - Index *big.Int - NextConsensus util.Uint160 - TransactionsLength *big.Int - PrevStateRoot util.Uint256 -} - -// LedgerTransaction is a contract-specific ledger.Transaction type used by its methods. -type LedgerTransaction struct { - Hash util.Uint256 - Version *big.Int - Nonce *big.Int - Sender util.Uint160 - SysFee *big.Int - NetFee *big.Int - ValidUntilBlock *big.Int - Script []byte -} - -// LedgerTransactionSigner is a contract-specific ledger.TransactionSigner type used by its methods. -type LedgerTransactionSigner struct { - Account util.Uint160 - Scopes *big.Int - AllowedContracts []util.Uint160 - AllowedGroups keys.PublicKeys - Rules []*LedgerWitnessRule -} - -// LedgerWitnessCondition is a contract-specific ledger.WitnessCondition type used by its methods. -type LedgerWitnessCondition struct { - Type *big.Int - Value any -} - -// LedgerWitnessRule is a contract-specific ledger.WitnessRule type used by its methods. -type LedgerWitnessRule struct { - Action *big.Int - Condition *LedgerWitnessCondition -} - // ComplicatedNameEvent represents "! complicated name %$#" event emitted by the contract. type ComplicatedNameEvent struct { ComplicatedParam string @@ -236,569 +173,6 @@ func (c *Contract) UnexportedFieldUnsigned() (*transaction.Transaction, error) { return c.actor.MakeUnsignedCall(c.hash, "unexportedField", nil) } -// itemToLedgerBlock converts stack item into *LedgerBlock. -func itemToLedgerBlock(item stackitem.Item, err error) (*LedgerBlock, error) { - if err != nil { - return nil, err - } - var res = new(LedgerBlock) - err = res.FromStackItem(item) - return res, err -} - -// FromStackItem retrieves fields of LedgerBlock from the given -// [stackitem.Item] or returns an error if it's not possible to do to so. -func (res *LedgerBlock) FromStackItem(item stackitem.Item) error { - arr, ok := item.Value().([]stackitem.Item) - if !ok { - return errors.New("not an array") - } - if len(arr) != 9 { - return errors.New("wrong number of structure elements") - } - - var ( - index = -1 - err error - ) - index++ - res.Hash, err = func(item stackitem.Item) (util.Uint256, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint256{}, err - } - u, err := util.Uint256DecodeBytesBE(b) - if err != nil { - return util.Uint256{}, err - } - return u, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field Hash: %w", err) - } - - index++ - res.Version, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Version: %w", err) - } - - index++ - res.PrevHash, err = func(item stackitem.Item) (util.Uint256, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint256{}, err - } - u, err := util.Uint256DecodeBytesBE(b) - if err != nil { - return util.Uint256{}, err - } - return u, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field PrevHash: %w", err) - } - - index++ - res.MerkleRoot, err = func(item stackitem.Item) (util.Uint256, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint256{}, err - } - u, err := util.Uint256DecodeBytesBE(b) - if err != nil { - return util.Uint256{}, err - } - return u, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field MerkleRoot: %w", err) - } - - index++ - res.Timestamp, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Timestamp: %w", err) - } - - index++ - res.Nonce, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Nonce: %w", err) - } - - index++ - res.Index, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Index: %w", err) - } - - index++ - res.NextConsensus, err = func(item stackitem.Item) (util.Uint160, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint160{}, err - } - u, err := util.Uint160DecodeBytesBE(b) - if err != nil { - return util.Uint160{}, err - } - return u, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field NextConsensus: %w", err) - } - - index++ - res.TransactionsLength, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field TransactionsLength: %w", err) - } - - return nil -} - -// itemToLedgerBlockSR converts stack item into *LedgerBlockSR. -func itemToLedgerBlockSR(item stackitem.Item, err error) (*LedgerBlockSR, error) { - if err != nil { - return nil, err - } - var res = new(LedgerBlockSR) - err = res.FromStackItem(item) - return res, err -} - -// FromStackItem retrieves fields of LedgerBlockSR from the given -// [stackitem.Item] or returns an error if it's not possible to do to so. -func (res *LedgerBlockSR) FromStackItem(item stackitem.Item) error { - arr, ok := item.Value().([]stackitem.Item) - if !ok { - return errors.New("not an array") - } - if len(arr) != 10 { - return errors.New("wrong number of structure elements") - } - - var ( - index = -1 - err error - ) - index++ - res.Hash, err = func(item stackitem.Item) (util.Uint256, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint256{}, err - } - u, err := util.Uint256DecodeBytesBE(b) - if err != nil { - return util.Uint256{}, err - } - return u, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field Hash: %w", err) - } - - index++ - res.Version, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Version: %w", err) - } - - index++ - res.PrevHash, err = func(item stackitem.Item) (util.Uint256, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint256{}, err - } - u, err := util.Uint256DecodeBytesBE(b) - if err != nil { - return util.Uint256{}, err - } - return u, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field PrevHash: %w", err) - } - - index++ - res.MerkleRoot, err = func(item stackitem.Item) (util.Uint256, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint256{}, err - } - u, err := util.Uint256DecodeBytesBE(b) - if err != nil { - return util.Uint256{}, err - } - return u, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field MerkleRoot: %w", err) - } - - index++ - res.Timestamp, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Timestamp: %w", err) - } - - index++ - res.Nonce, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Nonce: %w", err) - } - - index++ - res.Index, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Index: %w", err) - } - - index++ - res.NextConsensus, err = func(item stackitem.Item) (util.Uint160, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint160{}, err - } - u, err := util.Uint160DecodeBytesBE(b) - if err != nil { - return util.Uint160{}, err - } - return u, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field NextConsensus: %w", err) - } - - index++ - res.TransactionsLength, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field TransactionsLength: %w", err) - } - - index++ - res.PrevStateRoot, err = func(item stackitem.Item) (util.Uint256, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint256{}, err - } - u, err := util.Uint256DecodeBytesBE(b) - if err != nil { - return util.Uint256{}, err - } - return u, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field PrevStateRoot: %w", err) - } - - return nil -} - -// itemToLedgerTransaction converts stack item into *LedgerTransaction. -func itemToLedgerTransaction(item stackitem.Item, err error) (*LedgerTransaction, error) { - if err != nil { - return nil, err - } - var res = new(LedgerTransaction) - err = res.FromStackItem(item) - return res, err -} - -// FromStackItem retrieves fields of LedgerTransaction from the given -// [stackitem.Item] or returns an error if it's not possible to do to so. -func (res *LedgerTransaction) FromStackItem(item stackitem.Item) error { - arr, ok := item.Value().([]stackitem.Item) - if !ok { - return errors.New("not an array") - } - if len(arr) != 8 { - return errors.New("wrong number of structure elements") - } - - var ( - index = -1 - err error - ) - index++ - res.Hash, err = func(item stackitem.Item) (util.Uint256, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint256{}, err - } - u, err := util.Uint256DecodeBytesBE(b) - if err != nil { - return util.Uint256{}, err - } - return u, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field Hash: %w", err) - } - - index++ - res.Version, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Version: %w", err) - } - - index++ - res.Nonce, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Nonce: %w", err) - } - - index++ - res.Sender, err = func(item stackitem.Item) (util.Uint160, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint160{}, err - } - u, err := util.Uint160DecodeBytesBE(b) - if err != nil { - return util.Uint160{}, err - } - return u, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field Sender: %w", err) - } - - index++ - res.SysFee, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field SysFee: %w", err) - } - - index++ - res.NetFee, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field NetFee: %w", err) - } - - index++ - res.ValidUntilBlock, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field ValidUntilBlock: %w", err) - } - - index++ - res.Script, err = arr[index].TryBytes() - if err != nil { - return fmt.Errorf("field Script: %w", err) - } - - return nil -} - -// itemToLedgerTransactionSigner converts stack item into *LedgerTransactionSigner. -func itemToLedgerTransactionSigner(item stackitem.Item, err error) (*LedgerTransactionSigner, error) { - if err != nil { - return nil, err - } - var res = new(LedgerTransactionSigner) - err = res.FromStackItem(item) - return res, err -} - -// FromStackItem retrieves fields of LedgerTransactionSigner from the given -// [stackitem.Item] or returns an error if it's not possible to do to so. -func (res *LedgerTransactionSigner) FromStackItem(item stackitem.Item) error { - arr, ok := item.Value().([]stackitem.Item) - if !ok { - return errors.New("not an array") - } - if len(arr) != 5 { - return errors.New("wrong number of structure elements") - } - - var ( - index = -1 - err error - ) - index++ - res.Account, err = func(item stackitem.Item) (util.Uint160, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint160{}, err - } - u, err := util.Uint160DecodeBytesBE(b) - if err != nil { - return util.Uint160{}, err - } - return u, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field Account: %w", err) - } - - index++ - res.Scopes, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Scopes: %w", err) - } - - index++ - res.AllowedContracts, err = func(item stackitem.Item) ([]util.Uint160, error) { - arr, ok := item.Value().([]stackitem.Item) - if !ok { - return nil, errors.New("not an array") - } - res := make([]util.Uint160, len(arr)) - for i := range res { - res[i], err = func(item stackitem.Item) (util.Uint160, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint160{}, err - } - u, err := util.Uint160DecodeBytesBE(b) - if err != nil { - return util.Uint160{}, err - } - return u, nil - }(arr[i]) - if err != nil { - return nil, fmt.Errorf("item %d: %w", i, err) - } - } - return res, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field AllowedContracts: %w", err) - } - - index++ - res.AllowedGroups, err = func(item stackitem.Item) (keys.PublicKeys, error) { - arr, ok := item.Value().([]stackitem.Item) - if !ok { - return nil, errors.New("not an array") - } - res := make(keys.PublicKeys, len(arr)) - for i := range res { - res[i], err = func(item stackitem.Item) (*keys.PublicKey, error) { - b, err := item.TryBytes() - if err != nil { - return nil, err - } - k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) - if err != nil { - return nil, err - } - return k, nil - }(arr[i]) - if err != nil { - return nil, fmt.Errorf("item %d: %w", i, err) - } - } - return res, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field AllowedGroups: %w", err) - } - - index++ - res.Rules, err = func(item stackitem.Item) ([]*LedgerWitnessRule, error) { - arr, ok := item.Value().([]stackitem.Item) - if !ok { - return nil, errors.New("not an array") - } - res := make([]*LedgerWitnessRule, len(arr)) - for i := range res { - res[i], err = itemToLedgerWitnessRule(arr[i], nil) - if err != nil { - return nil, fmt.Errorf("item %d: %w", i, err) - } - } - return res, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field Rules: %w", err) - } - - return nil -} - -// itemToLedgerWitnessCondition converts stack item into *LedgerWitnessCondition. -func itemToLedgerWitnessCondition(item stackitem.Item, err error) (*LedgerWitnessCondition, error) { - if err != nil { - return nil, err - } - var res = new(LedgerWitnessCondition) - err = res.FromStackItem(item) - return res, err -} - -// FromStackItem retrieves fields of LedgerWitnessCondition from the given -// [stackitem.Item] or returns an error if it's not possible to do to so. -func (res *LedgerWitnessCondition) FromStackItem(item stackitem.Item) error { - arr, ok := item.Value().([]stackitem.Item) - if !ok { - return errors.New("not an array") - } - if len(arr) != 2 { - return errors.New("wrong number of structure elements") - } - - var ( - index = -1 - err error - ) - index++ - res.Type, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Type: %w", err) - } - - index++ - res.Value, err = arr[index].Value(), error(nil) - if err != nil { - return fmt.Errorf("field Value: %w", err) - } - - return nil -} - -// itemToLedgerWitnessRule converts stack item into *LedgerWitnessRule. -func itemToLedgerWitnessRule(item stackitem.Item, err error) (*LedgerWitnessRule, error) { - if err != nil { - return nil, err - } - var res = new(LedgerWitnessRule) - err = res.FromStackItem(item) - return res, err -} - -// FromStackItem retrieves fields of LedgerWitnessRule from the given -// [stackitem.Item] or returns an error if it's not possible to do to so. -func (res *LedgerWitnessRule) FromStackItem(item stackitem.Item) error { - arr, ok := item.Value().([]stackitem.Item) - if !ok { - return errors.New("not an array") - } - if len(arr) != 2 { - return errors.New("wrong number of structure elements") - } - - var ( - index = -1 - err error - ) - index++ - res.Action, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Action: %w", err) - } - - index++ - res.Condition, err = itemToLedgerWitnessCondition(arr[index], nil) - if err != nil { - return fmt.Errorf("field Condition: %w", err) - } - - return 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_extended.out b/cli/smartcontract/testdata/rpcbindings/notifications/rpcbindings_extended.out index b1b07aa12..ae30f5650 100755 --- a/cli/smartcontract/testdata/rpcbindings/notifications/rpcbindings_extended.out +++ b/cli/smartcontract/testdata/rpcbindings/notifications/rpcbindings_extended.out @@ -4,11 +4,9 @@ package structs import ( - "crypto/elliptic" "errors" "fmt" "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/util" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" @@ -25,66 +23,6 @@ type CrazyStruct struct { B bool } -// LedgerBlock is a contract-specific ledger.Block type used by its methods. -type LedgerBlock struct { - Hash util.Uint256 - Version *big.Int - PrevHash util.Uint256 - MerkleRoot util.Uint256 - Timestamp *big.Int - Nonce *big.Int - Index *big.Int - NextConsensus util.Uint160 - TransactionsLength *big.Int -} - -// LedgerBlockSR is a contract-specific ledger.BlockSR type used by its methods. -type LedgerBlockSR struct { - Hash util.Uint256 - Version *big.Int - PrevHash util.Uint256 - MerkleRoot util.Uint256 - Timestamp *big.Int - Nonce *big.Int - Index *big.Int - NextConsensus util.Uint160 - TransactionsLength *big.Int - PrevStateRoot util.Uint256 -} - -// LedgerTransaction is a contract-specific ledger.Transaction type used by its methods. -type LedgerTransaction struct { - Hash util.Uint256 - Version *big.Int - Nonce *big.Int - Sender util.Uint160 - SysFee *big.Int - NetFee *big.Int - ValidUntilBlock *big.Int - Script []byte -} - -// LedgerTransactionSigner is a contract-specific ledger.TransactionSigner type used by its methods. -type LedgerTransactionSigner struct { - Account util.Uint160 - Scopes *big.Int - AllowedContracts []util.Uint160 - AllowedGroups keys.PublicKeys - Rules []*LedgerWitnessRule -} - -// LedgerWitnessCondition is a contract-specific ledger.WitnessCondition type used by its methods. -type LedgerWitnessCondition struct { - Type *big.Int - Value any -} - -// LedgerWitnessRule is a contract-specific ledger.WitnessRule type used by its methods. -type LedgerWitnessRule struct { - Action *big.Int - Condition *LedgerWitnessCondition -} - // SimpleStruct is a contract-specific simpleStruct type used by its methods. type SimpleStruct struct { I *big.Int @@ -287,569 +225,6 @@ func (res *CrazyStruct) FromStackItem(item stackitem.Item) error { return nil } -// itemToLedgerBlock converts stack item into *LedgerBlock. -func itemToLedgerBlock(item stackitem.Item, err error) (*LedgerBlock, error) { - if err != nil { - return nil, err - } - var res = new(LedgerBlock) - err = res.FromStackItem(item) - return res, err -} - -// FromStackItem retrieves fields of LedgerBlock from the given -// [stackitem.Item] or returns an error if it's not possible to do to so. -func (res *LedgerBlock) FromStackItem(item stackitem.Item) error { - arr, ok := item.Value().([]stackitem.Item) - if !ok { - return errors.New("not an array") - } - if len(arr) != 9 { - return errors.New("wrong number of structure elements") - } - - var ( - index = -1 - err error - ) - index++ - res.Hash, err = func(item stackitem.Item) (util.Uint256, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint256{}, err - } - u, err := util.Uint256DecodeBytesBE(b) - if err != nil { - return util.Uint256{}, err - } - return u, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field Hash: %w", err) - } - - index++ - res.Version, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Version: %w", err) - } - - index++ - res.PrevHash, err = func(item stackitem.Item) (util.Uint256, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint256{}, err - } - u, err := util.Uint256DecodeBytesBE(b) - if err != nil { - return util.Uint256{}, err - } - return u, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field PrevHash: %w", err) - } - - index++ - res.MerkleRoot, err = func(item stackitem.Item) (util.Uint256, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint256{}, err - } - u, err := util.Uint256DecodeBytesBE(b) - if err != nil { - return util.Uint256{}, err - } - return u, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field MerkleRoot: %w", err) - } - - index++ - res.Timestamp, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Timestamp: %w", err) - } - - index++ - res.Nonce, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Nonce: %w", err) - } - - index++ - res.Index, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Index: %w", err) - } - - index++ - res.NextConsensus, err = func(item stackitem.Item) (util.Uint160, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint160{}, err - } - u, err := util.Uint160DecodeBytesBE(b) - if err != nil { - return util.Uint160{}, err - } - return u, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field NextConsensus: %w", err) - } - - index++ - res.TransactionsLength, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field TransactionsLength: %w", err) - } - - return nil -} - -// itemToLedgerBlockSR converts stack item into *LedgerBlockSR. -func itemToLedgerBlockSR(item stackitem.Item, err error) (*LedgerBlockSR, error) { - if err != nil { - return nil, err - } - var res = new(LedgerBlockSR) - err = res.FromStackItem(item) - return res, err -} - -// FromStackItem retrieves fields of LedgerBlockSR from the given -// [stackitem.Item] or returns an error if it's not possible to do to so. -func (res *LedgerBlockSR) FromStackItem(item stackitem.Item) error { - arr, ok := item.Value().([]stackitem.Item) - if !ok { - return errors.New("not an array") - } - if len(arr) != 10 { - return errors.New("wrong number of structure elements") - } - - var ( - index = -1 - err error - ) - index++ - res.Hash, err = func(item stackitem.Item) (util.Uint256, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint256{}, err - } - u, err := util.Uint256DecodeBytesBE(b) - if err != nil { - return util.Uint256{}, err - } - return u, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field Hash: %w", err) - } - - index++ - res.Version, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Version: %w", err) - } - - index++ - res.PrevHash, err = func(item stackitem.Item) (util.Uint256, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint256{}, err - } - u, err := util.Uint256DecodeBytesBE(b) - if err != nil { - return util.Uint256{}, err - } - return u, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field PrevHash: %w", err) - } - - index++ - res.MerkleRoot, err = func(item stackitem.Item) (util.Uint256, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint256{}, err - } - u, err := util.Uint256DecodeBytesBE(b) - if err != nil { - return util.Uint256{}, err - } - return u, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field MerkleRoot: %w", err) - } - - index++ - res.Timestamp, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Timestamp: %w", err) - } - - index++ - res.Nonce, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Nonce: %w", err) - } - - index++ - res.Index, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Index: %w", err) - } - - index++ - res.NextConsensus, err = func(item stackitem.Item) (util.Uint160, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint160{}, err - } - u, err := util.Uint160DecodeBytesBE(b) - if err != nil { - return util.Uint160{}, err - } - return u, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field NextConsensus: %w", err) - } - - index++ - res.TransactionsLength, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field TransactionsLength: %w", err) - } - - index++ - res.PrevStateRoot, err = func(item stackitem.Item) (util.Uint256, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint256{}, err - } - u, err := util.Uint256DecodeBytesBE(b) - if err != nil { - return util.Uint256{}, err - } - return u, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field PrevStateRoot: %w", err) - } - - return nil -} - -// itemToLedgerTransaction converts stack item into *LedgerTransaction. -func itemToLedgerTransaction(item stackitem.Item, err error) (*LedgerTransaction, error) { - if err != nil { - return nil, err - } - var res = new(LedgerTransaction) - err = res.FromStackItem(item) - return res, err -} - -// FromStackItem retrieves fields of LedgerTransaction from the given -// [stackitem.Item] or returns an error if it's not possible to do to so. -func (res *LedgerTransaction) FromStackItem(item stackitem.Item) error { - arr, ok := item.Value().([]stackitem.Item) - if !ok { - return errors.New("not an array") - } - if len(arr) != 8 { - return errors.New("wrong number of structure elements") - } - - var ( - index = -1 - err error - ) - index++ - res.Hash, err = func(item stackitem.Item) (util.Uint256, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint256{}, err - } - u, err := util.Uint256DecodeBytesBE(b) - if err != nil { - return util.Uint256{}, err - } - return u, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field Hash: %w", err) - } - - index++ - res.Version, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Version: %w", err) - } - - index++ - res.Nonce, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Nonce: %w", err) - } - - index++ - res.Sender, err = func(item stackitem.Item) (util.Uint160, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint160{}, err - } - u, err := util.Uint160DecodeBytesBE(b) - if err != nil { - return util.Uint160{}, err - } - return u, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field Sender: %w", err) - } - - index++ - res.SysFee, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field SysFee: %w", err) - } - - index++ - res.NetFee, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field NetFee: %w", err) - } - - index++ - res.ValidUntilBlock, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field ValidUntilBlock: %w", err) - } - - index++ - res.Script, err = arr[index].TryBytes() - if err != nil { - return fmt.Errorf("field Script: %w", err) - } - - return nil -} - -// itemToLedgerTransactionSigner converts stack item into *LedgerTransactionSigner. -func itemToLedgerTransactionSigner(item stackitem.Item, err error) (*LedgerTransactionSigner, error) { - if err != nil { - return nil, err - } - var res = new(LedgerTransactionSigner) - err = res.FromStackItem(item) - return res, err -} - -// FromStackItem retrieves fields of LedgerTransactionSigner from the given -// [stackitem.Item] or returns an error if it's not possible to do to so. -func (res *LedgerTransactionSigner) FromStackItem(item stackitem.Item) error { - arr, ok := item.Value().([]stackitem.Item) - if !ok { - return errors.New("not an array") - } - if len(arr) != 5 { - return errors.New("wrong number of structure elements") - } - - var ( - index = -1 - err error - ) - index++ - res.Account, err = func(item stackitem.Item) (util.Uint160, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint160{}, err - } - u, err := util.Uint160DecodeBytesBE(b) - if err != nil { - return util.Uint160{}, err - } - return u, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field Account: %w", err) - } - - index++ - res.Scopes, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Scopes: %w", err) - } - - index++ - res.AllowedContracts, err = func(item stackitem.Item) ([]util.Uint160, error) { - arr, ok := item.Value().([]stackitem.Item) - if !ok { - return nil, errors.New("not an array") - } - res := make([]util.Uint160, len(arr)) - for i := range res { - res[i], err = func(item stackitem.Item) (util.Uint160, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint160{}, err - } - u, err := util.Uint160DecodeBytesBE(b) - if err != nil { - return util.Uint160{}, err - } - return u, nil - }(arr[i]) - if err != nil { - return nil, fmt.Errorf("item %d: %w", i, err) - } - } - return res, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field AllowedContracts: %w", err) - } - - index++ - res.AllowedGroups, err = func(item stackitem.Item) (keys.PublicKeys, error) { - arr, ok := item.Value().([]stackitem.Item) - if !ok { - return nil, errors.New("not an array") - } - res := make(keys.PublicKeys, len(arr)) - for i := range res { - res[i], err = func(item stackitem.Item) (*keys.PublicKey, error) { - b, err := item.TryBytes() - if err != nil { - return nil, err - } - k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) - if err != nil { - return nil, err - } - return k, nil - }(arr[i]) - if err != nil { - return nil, fmt.Errorf("item %d: %w", i, err) - } - } - return res, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field AllowedGroups: %w", err) - } - - index++ - res.Rules, err = func(item stackitem.Item) ([]*LedgerWitnessRule, error) { - arr, ok := item.Value().([]stackitem.Item) - if !ok { - return nil, errors.New("not an array") - } - res := make([]*LedgerWitnessRule, len(arr)) - for i := range res { - res[i], err = itemToLedgerWitnessRule(arr[i], nil) - if err != nil { - return nil, fmt.Errorf("item %d: %w", i, err) - } - } - return res, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field Rules: %w", err) - } - - return nil -} - -// itemToLedgerWitnessCondition converts stack item into *LedgerWitnessCondition. -func itemToLedgerWitnessCondition(item stackitem.Item, err error) (*LedgerWitnessCondition, error) { - if err != nil { - return nil, err - } - var res = new(LedgerWitnessCondition) - err = res.FromStackItem(item) - return res, err -} - -// FromStackItem retrieves fields of LedgerWitnessCondition from the given -// [stackitem.Item] or returns an error if it's not possible to do to so. -func (res *LedgerWitnessCondition) FromStackItem(item stackitem.Item) error { - arr, ok := item.Value().([]stackitem.Item) - if !ok { - return errors.New("not an array") - } - if len(arr) != 2 { - return errors.New("wrong number of structure elements") - } - - var ( - index = -1 - err error - ) - index++ - res.Type, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Type: %w", err) - } - - index++ - res.Value, err = arr[index].Value(), error(nil) - if err != nil { - return fmt.Errorf("field Value: %w", err) - } - - return nil -} - -// itemToLedgerWitnessRule converts stack item into *LedgerWitnessRule. -func itemToLedgerWitnessRule(item stackitem.Item, err error) (*LedgerWitnessRule, error) { - if err != nil { - return nil, err - } - var res = new(LedgerWitnessRule) - err = res.FromStackItem(item) - return res, err -} - -// FromStackItem retrieves fields of LedgerWitnessRule from the given -// [stackitem.Item] or returns an error if it's not possible to do to so. -func (res *LedgerWitnessRule) FromStackItem(item stackitem.Item) error { - arr, ok := item.Value().([]stackitem.Item) - if !ok { - return errors.New("not an array") - } - if len(arr) != 2 { - return errors.New("wrong number of structure elements") - } - - var ( - index = -1 - err error - ) - index++ - res.Action, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Action: %w", err) - } - - index++ - res.Condition, err = itemToLedgerWitnessCondition(arr[index], nil) - if err != nil { - return fmt.Errorf("field Condition: %w", err) - } - - return nil -} - // itemToSimpleStruct converts stack item into *SimpleStruct. func itemToSimpleStruct(item stackitem.Item, err error) (*SimpleStruct, error) { if err != nil { diff --git a/cli/smartcontract/testdata/rpcbindings/notifications/rpcbindings_guessed.out b/cli/smartcontract/testdata/rpcbindings/notifications/rpcbindings_guessed.out index b71c3d103..6c9128662 100755 --- a/cli/smartcontract/testdata/rpcbindings/notifications/rpcbindings_guessed.out +++ b/cli/smartcontract/testdata/rpcbindings/notifications/rpcbindings_guessed.out @@ -4,11 +4,9 @@ package structs import ( - "crypto/elliptic" "errors" "fmt" "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/util" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" @@ -19,66 +17,6 @@ import ( // Hash contains contract hash. var Hash = util.Uint160{0x33, 0x22, 0x11, 0x0, 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x0} -// LedgerBlock is a contract-specific ledger.Block type used by its methods. -type LedgerBlock struct { - Hash util.Uint256 - Version *big.Int - PrevHash util.Uint256 - MerkleRoot util.Uint256 - Timestamp *big.Int - Nonce *big.Int - Index *big.Int - NextConsensus util.Uint160 - TransactionsLength *big.Int -} - -// LedgerBlockSR is a contract-specific ledger.BlockSR type used by its methods. -type LedgerBlockSR struct { - Hash util.Uint256 - Version *big.Int - PrevHash util.Uint256 - MerkleRoot util.Uint256 - Timestamp *big.Int - Nonce *big.Int - Index *big.Int - NextConsensus util.Uint160 - TransactionsLength *big.Int - PrevStateRoot util.Uint256 -} - -// LedgerTransaction is a contract-specific ledger.Transaction type used by its methods. -type LedgerTransaction struct { - Hash util.Uint256 - Version *big.Int - Nonce *big.Int - Sender util.Uint160 - SysFee *big.Int - NetFee *big.Int - ValidUntilBlock *big.Int - Script []byte -} - -// LedgerTransactionSigner is a contract-specific ledger.TransactionSigner type used by its methods. -type LedgerTransactionSigner struct { - Account util.Uint160 - Scopes *big.Int - AllowedContracts []util.Uint160 - AllowedGroups keys.PublicKeys - Rules []*LedgerWitnessRule -} - -// LedgerWitnessCondition is a contract-specific ledger.WitnessCondition type used by its methods. -type LedgerWitnessCondition struct { - Type *big.Int - Value any -} - -// LedgerWitnessRule is a contract-specific ledger.WitnessRule type used by its methods. -type LedgerWitnessRule struct { - Action *big.Int - Condition *LedgerWitnessCondition -} - // Unnamed is a contract-specific unnamed type used by its methods. type Unnamed struct { I *big.Int @@ -242,569 +180,6 @@ func (c *Contract) UnexportedFieldUnsigned() (*transaction.Transaction, error) { return c.actor.MakeUnsignedCall(c.hash, "unexportedField", nil) } -// itemToLedgerBlock converts stack item into *LedgerBlock. -func itemToLedgerBlock(item stackitem.Item, err error) (*LedgerBlock, error) { - if err != nil { - return nil, err - } - var res = new(LedgerBlock) - err = res.FromStackItem(item) - return res, err -} - -// FromStackItem retrieves fields of LedgerBlock from the given -// [stackitem.Item] or returns an error if it's not possible to do to so. -func (res *LedgerBlock) FromStackItem(item stackitem.Item) error { - arr, ok := item.Value().([]stackitem.Item) - if !ok { - return errors.New("not an array") - } - if len(arr) != 9 { - return errors.New("wrong number of structure elements") - } - - var ( - index = -1 - err error - ) - index++ - res.Hash, err = func(item stackitem.Item) (util.Uint256, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint256{}, err - } - u, err := util.Uint256DecodeBytesBE(b) - if err != nil { - return util.Uint256{}, err - } - return u, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field Hash: %w", err) - } - - index++ - res.Version, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Version: %w", err) - } - - index++ - res.PrevHash, err = func(item stackitem.Item) (util.Uint256, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint256{}, err - } - u, err := util.Uint256DecodeBytesBE(b) - if err != nil { - return util.Uint256{}, err - } - return u, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field PrevHash: %w", err) - } - - index++ - res.MerkleRoot, err = func(item stackitem.Item) (util.Uint256, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint256{}, err - } - u, err := util.Uint256DecodeBytesBE(b) - if err != nil { - return util.Uint256{}, err - } - return u, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field MerkleRoot: %w", err) - } - - index++ - res.Timestamp, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Timestamp: %w", err) - } - - index++ - res.Nonce, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Nonce: %w", err) - } - - index++ - res.Index, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Index: %w", err) - } - - index++ - res.NextConsensus, err = func(item stackitem.Item) (util.Uint160, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint160{}, err - } - u, err := util.Uint160DecodeBytesBE(b) - if err != nil { - return util.Uint160{}, err - } - return u, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field NextConsensus: %w", err) - } - - index++ - res.TransactionsLength, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field TransactionsLength: %w", err) - } - - return nil -} - -// itemToLedgerBlockSR converts stack item into *LedgerBlockSR. -func itemToLedgerBlockSR(item stackitem.Item, err error) (*LedgerBlockSR, error) { - if err != nil { - return nil, err - } - var res = new(LedgerBlockSR) - err = res.FromStackItem(item) - return res, err -} - -// FromStackItem retrieves fields of LedgerBlockSR from the given -// [stackitem.Item] or returns an error if it's not possible to do to so. -func (res *LedgerBlockSR) FromStackItem(item stackitem.Item) error { - arr, ok := item.Value().([]stackitem.Item) - if !ok { - return errors.New("not an array") - } - if len(arr) != 10 { - return errors.New("wrong number of structure elements") - } - - var ( - index = -1 - err error - ) - index++ - res.Hash, err = func(item stackitem.Item) (util.Uint256, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint256{}, err - } - u, err := util.Uint256DecodeBytesBE(b) - if err != nil { - return util.Uint256{}, err - } - return u, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field Hash: %w", err) - } - - index++ - res.Version, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Version: %w", err) - } - - index++ - res.PrevHash, err = func(item stackitem.Item) (util.Uint256, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint256{}, err - } - u, err := util.Uint256DecodeBytesBE(b) - if err != nil { - return util.Uint256{}, err - } - return u, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field PrevHash: %w", err) - } - - index++ - res.MerkleRoot, err = func(item stackitem.Item) (util.Uint256, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint256{}, err - } - u, err := util.Uint256DecodeBytesBE(b) - if err != nil { - return util.Uint256{}, err - } - return u, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field MerkleRoot: %w", err) - } - - index++ - res.Timestamp, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Timestamp: %w", err) - } - - index++ - res.Nonce, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Nonce: %w", err) - } - - index++ - res.Index, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Index: %w", err) - } - - index++ - res.NextConsensus, err = func(item stackitem.Item) (util.Uint160, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint160{}, err - } - u, err := util.Uint160DecodeBytesBE(b) - if err != nil { - return util.Uint160{}, err - } - return u, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field NextConsensus: %w", err) - } - - index++ - res.TransactionsLength, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field TransactionsLength: %w", err) - } - - index++ - res.PrevStateRoot, err = func(item stackitem.Item) (util.Uint256, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint256{}, err - } - u, err := util.Uint256DecodeBytesBE(b) - if err != nil { - return util.Uint256{}, err - } - return u, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field PrevStateRoot: %w", err) - } - - return nil -} - -// itemToLedgerTransaction converts stack item into *LedgerTransaction. -func itemToLedgerTransaction(item stackitem.Item, err error) (*LedgerTransaction, error) { - if err != nil { - return nil, err - } - var res = new(LedgerTransaction) - err = res.FromStackItem(item) - return res, err -} - -// FromStackItem retrieves fields of LedgerTransaction from the given -// [stackitem.Item] or returns an error if it's not possible to do to so. -func (res *LedgerTransaction) FromStackItem(item stackitem.Item) error { - arr, ok := item.Value().([]stackitem.Item) - if !ok { - return errors.New("not an array") - } - if len(arr) != 8 { - return errors.New("wrong number of structure elements") - } - - var ( - index = -1 - err error - ) - index++ - res.Hash, err = func(item stackitem.Item) (util.Uint256, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint256{}, err - } - u, err := util.Uint256DecodeBytesBE(b) - if err != nil { - return util.Uint256{}, err - } - return u, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field Hash: %w", err) - } - - index++ - res.Version, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Version: %w", err) - } - - index++ - res.Nonce, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Nonce: %w", err) - } - - index++ - res.Sender, err = func(item stackitem.Item) (util.Uint160, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint160{}, err - } - u, err := util.Uint160DecodeBytesBE(b) - if err != nil { - return util.Uint160{}, err - } - return u, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field Sender: %w", err) - } - - index++ - res.SysFee, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field SysFee: %w", err) - } - - index++ - res.NetFee, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field NetFee: %w", err) - } - - index++ - res.ValidUntilBlock, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field ValidUntilBlock: %w", err) - } - - index++ - res.Script, err = arr[index].TryBytes() - if err != nil { - return fmt.Errorf("field Script: %w", err) - } - - return nil -} - -// itemToLedgerTransactionSigner converts stack item into *LedgerTransactionSigner. -func itemToLedgerTransactionSigner(item stackitem.Item, err error) (*LedgerTransactionSigner, error) { - if err != nil { - return nil, err - } - var res = new(LedgerTransactionSigner) - err = res.FromStackItem(item) - return res, err -} - -// FromStackItem retrieves fields of LedgerTransactionSigner from the given -// [stackitem.Item] or returns an error if it's not possible to do to so. -func (res *LedgerTransactionSigner) FromStackItem(item stackitem.Item) error { - arr, ok := item.Value().([]stackitem.Item) - if !ok { - return errors.New("not an array") - } - if len(arr) != 5 { - return errors.New("wrong number of structure elements") - } - - var ( - index = -1 - err error - ) - index++ - res.Account, err = func(item stackitem.Item) (util.Uint160, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint160{}, err - } - u, err := util.Uint160DecodeBytesBE(b) - if err != nil { - return util.Uint160{}, err - } - return u, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field Account: %w", err) - } - - index++ - res.Scopes, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Scopes: %w", err) - } - - index++ - res.AllowedContracts, err = func(item stackitem.Item) ([]util.Uint160, error) { - arr, ok := item.Value().([]stackitem.Item) - if !ok { - return nil, errors.New("not an array") - } - res := make([]util.Uint160, len(arr)) - for i := range res { - res[i], err = func(item stackitem.Item) (util.Uint160, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint160{}, err - } - u, err := util.Uint160DecodeBytesBE(b) - if err != nil { - return util.Uint160{}, err - } - return u, nil - }(arr[i]) - if err != nil { - return nil, fmt.Errorf("item %d: %w", i, err) - } - } - return res, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field AllowedContracts: %w", err) - } - - index++ - res.AllowedGroups, err = func(item stackitem.Item) (keys.PublicKeys, error) { - arr, ok := item.Value().([]stackitem.Item) - if !ok { - return nil, errors.New("not an array") - } - res := make(keys.PublicKeys, len(arr)) - for i := range res { - res[i], err = func(item stackitem.Item) (*keys.PublicKey, error) { - b, err := item.TryBytes() - if err != nil { - return nil, err - } - k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) - if err != nil { - return nil, err - } - return k, nil - }(arr[i]) - if err != nil { - return nil, fmt.Errorf("item %d: %w", i, err) - } - } - return res, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field AllowedGroups: %w", err) - } - - index++ - res.Rules, err = func(item stackitem.Item) ([]*LedgerWitnessRule, error) { - arr, ok := item.Value().([]stackitem.Item) - if !ok { - return nil, errors.New("not an array") - } - res := make([]*LedgerWitnessRule, len(arr)) - for i := range res { - res[i], err = itemToLedgerWitnessRule(arr[i], nil) - if err != nil { - return nil, fmt.Errorf("item %d: %w", i, err) - } - } - return res, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field Rules: %w", err) - } - - return nil -} - -// itemToLedgerWitnessCondition converts stack item into *LedgerWitnessCondition. -func itemToLedgerWitnessCondition(item stackitem.Item, err error) (*LedgerWitnessCondition, error) { - if err != nil { - return nil, err - } - var res = new(LedgerWitnessCondition) - err = res.FromStackItem(item) - return res, err -} - -// FromStackItem retrieves fields of LedgerWitnessCondition from the given -// [stackitem.Item] or returns an error if it's not possible to do to so. -func (res *LedgerWitnessCondition) FromStackItem(item stackitem.Item) error { - arr, ok := item.Value().([]stackitem.Item) - if !ok { - return errors.New("not an array") - } - if len(arr) != 2 { - return errors.New("wrong number of structure elements") - } - - var ( - index = -1 - err error - ) - index++ - res.Type, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Type: %w", err) - } - - index++ - res.Value, err = arr[index].Value(), error(nil) - if err != nil { - return fmt.Errorf("field Value: %w", err) - } - - return nil -} - -// itemToLedgerWitnessRule converts stack item into *LedgerWitnessRule. -func itemToLedgerWitnessRule(item stackitem.Item, err error) (*LedgerWitnessRule, error) { - if err != nil { - return nil, err - } - var res = new(LedgerWitnessRule) - err = res.FromStackItem(item) - return res, err -} - -// FromStackItem retrieves fields of LedgerWitnessRule from the given -// [stackitem.Item] or returns an error if it's not possible to do to so. -func (res *LedgerWitnessRule) FromStackItem(item stackitem.Item) error { - arr, ok := item.Value().([]stackitem.Item) - if !ok { - return errors.New("not an array") - } - if len(arr) != 2 { - return errors.New("wrong number of structure elements") - } - - var ( - index = -1 - err error - ) - index++ - res.Action, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Action: %w", err) - } - - index++ - res.Condition, err = itemToLedgerWitnessCondition(arr[index], nil) - if err != nil { - return fmt.Errorf("field Condition: %w", err) - } - - return nil -} - // itemToUnnamed converts stack item into *Unnamed. func itemToUnnamed(item stackitem.Item, err error) (*Unnamed, error) { if err != nil { diff --git a/cli/smartcontract/testdata/rpcbindings/structs/rpcbindings.out b/cli/smartcontract/testdata/rpcbindings/structs/rpcbindings.out index 7a1166ea6..5c7a5476b 100644 --- a/cli/smartcontract/testdata/rpcbindings/structs/rpcbindings.out +++ b/cli/smartcontract/testdata/rpcbindings/structs/rpcbindings.out @@ -32,20 +32,6 @@ type LedgerBlock struct { TransactionsLength *big.Int } -// LedgerBlockSR is a contract-specific ledger.BlockSR type used by its methods. -type LedgerBlockSR struct { - Hash util.Uint256 - Version *big.Int - PrevHash util.Uint256 - MerkleRoot util.Uint256 - Timestamp *big.Int - Nonce *big.Int - Index *big.Int - NextConsensus util.Uint160 - TransactionsLength *big.Int - PrevStateRoot util.Uint256 -} - // LedgerTransaction is a contract-specific ledger.Transaction type used by its methods. type LedgerTransaction struct { Hash util.Uint256 @@ -58,27 +44,6 @@ type LedgerTransaction struct { Script []byte } -// LedgerTransactionSigner is a contract-specific ledger.TransactionSigner type used by its methods. -type LedgerTransactionSigner struct { - Account util.Uint160 - Scopes *big.Int - AllowedContracts []util.Uint160 - AllowedGroups keys.PublicKeys - Rules []*LedgerWitnessRule -} - -// LedgerWitnessCondition is a contract-specific ledger.WitnessCondition type used by its methods. -type LedgerWitnessCondition struct { - Type *big.Int - Value any -} - -// LedgerWitnessRule is a contract-specific ledger.WitnessRule type used by its methods. -type LedgerWitnessRule struct { - Action *big.Int - Condition *LedgerWitnessCondition -} - // ManagementABI is a contract-specific management.ABI type used by its methods. type ManagementABI struct { Methods []*ManagementMethod @@ -316,144 +281,6 @@ func (res *LedgerBlock) FromStackItem(item stackitem.Item) error { return nil } -// itemToLedgerBlockSR converts stack item into *LedgerBlockSR. -func itemToLedgerBlockSR(item stackitem.Item, err error) (*LedgerBlockSR, error) { - if err != nil { - return nil, err - } - var res = new(LedgerBlockSR) - err = res.FromStackItem(item) - return res, err -} - -// FromStackItem retrieves fields of LedgerBlockSR from the given -// [stackitem.Item] or returns an error if it's not possible to do to so. -func (res *LedgerBlockSR) FromStackItem(item stackitem.Item) error { - arr, ok := item.Value().([]stackitem.Item) - if !ok { - return errors.New("not an array") - } - if len(arr) != 10 { - return errors.New("wrong number of structure elements") - } - - var ( - index = -1 - err error - ) - index++ - res.Hash, err = func(item stackitem.Item) (util.Uint256, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint256{}, err - } - u, err := util.Uint256DecodeBytesBE(b) - if err != nil { - return util.Uint256{}, err - } - return u, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field Hash: %w", err) - } - - index++ - res.Version, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Version: %w", err) - } - - index++ - res.PrevHash, err = func(item stackitem.Item) (util.Uint256, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint256{}, err - } - u, err := util.Uint256DecodeBytesBE(b) - if err != nil { - return util.Uint256{}, err - } - return u, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field PrevHash: %w", err) - } - - index++ - res.MerkleRoot, err = func(item stackitem.Item) (util.Uint256, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint256{}, err - } - u, err := util.Uint256DecodeBytesBE(b) - if err != nil { - return util.Uint256{}, err - } - return u, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field MerkleRoot: %w", err) - } - - index++ - res.Timestamp, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Timestamp: %w", err) - } - - index++ - res.Nonce, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Nonce: %w", err) - } - - index++ - res.Index, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Index: %w", err) - } - - index++ - res.NextConsensus, err = func(item stackitem.Item) (util.Uint160, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint160{}, err - } - u, err := util.Uint160DecodeBytesBE(b) - if err != nil { - return util.Uint160{}, err - } - return u, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field NextConsensus: %w", err) - } - - index++ - res.TransactionsLength, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field TransactionsLength: %w", err) - } - - index++ - res.PrevStateRoot, err = func(item stackitem.Item) (util.Uint256, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint256{}, err - } - u, err := util.Uint256DecodeBytesBE(b) - if err != nil { - return util.Uint256{}, err - } - return u, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field PrevStateRoot: %w", err) - } - - return nil -} - // itemToLedgerTransaction converts stack item into *LedgerTransaction. func itemToLedgerTransaction(item stackitem.Item, err error) (*LedgerTransaction, error) { if err != nil { @@ -550,213 +377,6 @@ func (res *LedgerTransaction) FromStackItem(item stackitem.Item) error { return nil } -// itemToLedgerTransactionSigner converts stack item into *LedgerTransactionSigner. -func itemToLedgerTransactionSigner(item stackitem.Item, err error) (*LedgerTransactionSigner, error) { - if err != nil { - return nil, err - } - var res = new(LedgerTransactionSigner) - err = res.FromStackItem(item) - return res, err -} - -// FromStackItem retrieves fields of LedgerTransactionSigner from the given -// [stackitem.Item] or returns an error if it's not possible to do to so. -func (res *LedgerTransactionSigner) FromStackItem(item stackitem.Item) error { - arr, ok := item.Value().([]stackitem.Item) - if !ok { - return errors.New("not an array") - } - if len(arr) != 5 { - return errors.New("wrong number of structure elements") - } - - var ( - index = -1 - err error - ) - index++ - res.Account, err = func(item stackitem.Item) (util.Uint160, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint160{}, err - } - u, err := util.Uint160DecodeBytesBE(b) - if err != nil { - return util.Uint160{}, err - } - return u, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field Account: %w", err) - } - - index++ - res.Scopes, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Scopes: %w", err) - } - - index++ - res.AllowedContracts, err = func(item stackitem.Item) ([]util.Uint160, error) { - arr, ok := item.Value().([]stackitem.Item) - if !ok { - return nil, errors.New("not an array") - } - res := make([]util.Uint160, len(arr)) - for i := range res { - res[i], err = func(item stackitem.Item) (util.Uint160, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint160{}, err - } - u, err := util.Uint160DecodeBytesBE(b) - if err != nil { - return util.Uint160{}, err - } - return u, nil - }(arr[i]) - if err != nil { - return nil, fmt.Errorf("item %d: %w", i, err) - } - } - return res, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field AllowedContracts: %w", err) - } - - index++ - res.AllowedGroups, err = func(item stackitem.Item) (keys.PublicKeys, error) { - arr, ok := item.Value().([]stackitem.Item) - if !ok { - return nil, errors.New("not an array") - } - res := make(keys.PublicKeys, len(arr)) - for i := range res { - res[i], err = func(item stackitem.Item) (*keys.PublicKey, error) { - b, err := item.TryBytes() - if err != nil { - return nil, err - } - k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) - if err != nil { - return nil, err - } - return k, nil - }(arr[i]) - if err != nil { - return nil, fmt.Errorf("item %d: %w", i, err) - } - } - return res, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field AllowedGroups: %w", err) - } - - index++ - res.Rules, err = func(item stackitem.Item) ([]*LedgerWitnessRule, error) { - arr, ok := item.Value().([]stackitem.Item) - if !ok { - return nil, errors.New("not an array") - } - res := make([]*LedgerWitnessRule, len(arr)) - for i := range res { - res[i], err = itemToLedgerWitnessRule(arr[i], nil) - if err != nil { - return nil, fmt.Errorf("item %d: %w", i, err) - } - } - return res, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field Rules: %w", err) - } - - return nil -} - -// itemToLedgerWitnessCondition converts stack item into *LedgerWitnessCondition. -func itemToLedgerWitnessCondition(item stackitem.Item, err error) (*LedgerWitnessCondition, error) { - if err != nil { - return nil, err - } - var res = new(LedgerWitnessCondition) - err = res.FromStackItem(item) - return res, err -} - -// FromStackItem retrieves fields of LedgerWitnessCondition from the given -// [stackitem.Item] or returns an error if it's not possible to do to so. -func (res *LedgerWitnessCondition) FromStackItem(item stackitem.Item) error { - arr, ok := item.Value().([]stackitem.Item) - if !ok { - return errors.New("not an array") - } - if len(arr) != 2 { - return errors.New("wrong number of structure elements") - } - - var ( - index = -1 - err error - ) - index++ - res.Type, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Type: %w", err) - } - - index++ - res.Value, err = arr[index].Value(), error(nil) - if err != nil { - return fmt.Errorf("field Value: %w", err) - } - - return nil -} - -// itemToLedgerWitnessRule converts stack item into *LedgerWitnessRule. -func itemToLedgerWitnessRule(item stackitem.Item, err error) (*LedgerWitnessRule, error) { - if err != nil { - return nil, err - } - var res = new(LedgerWitnessRule) - err = res.FromStackItem(item) - return res, err -} - -// FromStackItem retrieves fields of LedgerWitnessRule from the given -// [stackitem.Item] or returns an error if it's not possible to do to so. -func (res *LedgerWitnessRule) FromStackItem(item stackitem.Item) error { - arr, ok := item.Value().([]stackitem.Item) - if !ok { - return errors.New("not an array") - } - if len(arr) != 2 { - return errors.New("wrong number of structure elements") - } - - var ( - index = -1 - err error - ) - index++ - res.Action, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Action: %w", err) - } - - index++ - res.Condition, err = itemToLedgerWitnessCondition(arr[index], nil) - if err != nil { - return fmt.Errorf("field Condition: %w", err) - } - - return nil -} - // itemToManagementABI converts stack item into *ManagementABI. func itemToManagementABI(item stackitem.Item, err error) (*ManagementABI, error) { if err != nil { diff --git a/cli/smartcontract/testdata/rpcbindings/structs/rpcbindings_dynamic_hash.out b/cli/smartcontract/testdata/rpcbindings/structs/rpcbindings_dynamic_hash.out index e5047b273..3687bb174 100755 --- a/cli/smartcontract/testdata/rpcbindings/structs/rpcbindings_dynamic_hash.out +++ b/cli/smartcontract/testdata/rpcbindings/structs/rpcbindings_dynamic_hash.out @@ -29,20 +29,6 @@ type LedgerBlock struct { TransactionsLength *big.Int } -// LedgerBlockSR is a contract-specific ledger.BlockSR type used by its methods. -type LedgerBlockSR struct { - Hash util.Uint256 - Version *big.Int - PrevHash util.Uint256 - MerkleRoot util.Uint256 - Timestamp *big.Int - Nonce *big.Int - Index *big.Int - NextConsensus util.Uint160 - TransactionsLength *big.Int - PrevStateRoot util.Uint256 -} - // LedgerTransaction is a contract-specific ledger.Transaction type used by its methods. type LedgerTransaction struct { Hash util.Uint256 @@ -55,27 +41,6 @@ type LedgerTransaction struct { Script []byte } -// LedgerTransactionSigner is a contract-specific ledger.TransactionSigner type used by its methods. -type LedgerTransactionSigner struct { - Account util.Uint160 - Scopes *big.Int - AllowedContracts []util.Uint160 - AllowedGroups keys.PublicKeys - Rules []*LedgerWitnessRule -} - -// LedgerWitnessCondition is a contract-specific ledger.WitnessCondition type used by its methods. -type LedgerWitnessCondition struct { - Type *big.Int - Value any -} - -// LedgerWitnessRule is a contract-specific ledger.WitnessRule type used by its methods. -type LedgerWitnessRule struct { - Action *big.Int - Condition *LedgerWitnessCondition -} - // ManagementABI is a contract-specific management.ABI type used by its methods. type ManagementABI struct { Methods []*ManagementMethod @@ -312,144 +277,6 @@ func (res *LedgerBlock) FromStackItem(item stackitem.Item) error { return nil } -// itemToLedgerBlockSR converts stack item into *LedgerBlockSR. -func itemToLedgerBlockSR(item stackitem.Item, err error) (*LedgerBlockSR, error) { - if err != nil { - return nil, err - } - var res = new(LedgerBlockSR) - err = res.FromStackItem(item) - return res, err -} - -// FromStackItem retrieves fields of LedgerBlockSR from the given -// [stackitem.Item] or returns an error if it's not possible to do to so. -func (res *LedgerBlockSR) FromStackItem(item stackitem.Item) error { - arr, ok := item.Value().([]stackitem.Item) - if !ok { - return errors.New("not an array") - } - if len(arr) != 10 { - return errors.New("wrong number of structure elements") - } - - var ( - index = -1 - err error - ) - index++ - res.Hash, err = func(item stackitem.Item) (util.Uint256, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint256{}, err - } - u, err := util.Uint256DecodeBytesBE(b) - if err != nil { - return util.Uint256{}, err - } - return u, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field Hash: %w", err) - } - - index++ - res.Version, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Version: %w", err) - } - - index++ - res.PrevHash, err = func(item stackitem.Item) (util.Uint256, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint256{}, err - } - u, err := util.Uint256DecodeBytesBE(b) - if err != nil { - return util.Uint256{}, err - } - return u, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field PrevHash: %w", err) - } - - index++ - res.MerkleRoot, err = func(item stackitem.Item) (util.Uint256, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint256{}, err - } - u, err := util.Uint256DecodeBytesBE(b) - if err != nil { - return util.Uint256{}, err - } - return u, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field MerkleRoot: %w", err) - } - - index++ - res.Timestamp, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Timestamp: %w", err) - } - - index++ - res.Nonce, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Nonce: %w", err) - } - - index++ - res.Index, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Index: %w", err) - } - - index++ - res.NextConsensus, err = func(item stackitem.Item) (util.Uint160, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint160{}, err - } - u, err := util.Uint160DecodeBytesBE(b) - if err != nil { - return util.Uint160{}, err - } - return u, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field NextConsensus: %w", err) - } - - index++ - res.TransactionsLength, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field TransactionsLength: %w", err) - } - - index++ - res.PrevStateRoot, err = func(item stackitem.Item) (util.Uint256, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint256{}, err - } - u, err := util.Uint256DecodeBytesBE(b) - if err != nil { - return util.Uint256{}, err - } - return u, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field PrevStateRoot: %w", err) - } - - return nil -} - // itemToLedgerTransaction converts stack item into *LedgerTransaction. func itemToLedgerTransaction(item stackitem.Item, err error) (*LedgerTransaction, error) { if err != nil { @@ -546,213 +373,6 @@ func (res *LedgerTransaction) FromStackItem(item stackitem.Item) error { return nil } -// itemToLedgerTransactionSigner converts stack item into *LedgerTransactionSigner. -func itemToLedgerTransactionSigner(item stackitem.Item, err error) (*LedgerTransactionSigner, error) { - if err != nil { - return nil, err - } - var res = new(LedgerTransactionSigner) - err = res.FromStackItem(item) - return res, err -} - -// FromStackItem retrieves fields of LedgerTransactionSigner from the given -// [stackitem.Item] or returns an error if it's not possible to do to so. -func (res *LedgerTransactionSigner) FromStackItem(item stackitem.Item) error { - arr, ok := item.Value().([]stackitem.Item) - if !ok { - return errors.New("not an array") - } - if len(arr) != 5 { - return errors.New("wrong number of structure elements") - } - - var ( - index = -1 - err error - ) - index++ - res.Account, err = func(item stackitem.Item) (util.Uint160, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint160{}, err - } - u, err := util.Uint160DecodeBytesBE(b) - if err != nil { - return util.Uint160{}, err - } - return u, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field Account: %w", err) - } - - index++ - res.Scopes, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Scopes: %w", err) - } - - index++ - res.AllowedContracts, err = func(item stackitem.Item) ([]util.Uint160, error) { - arr, ok := item.Value().([]stackitem.Item) - if !ok { - return nil, errors.New("not an array") - } - res := make([]util.Uint160, len(arr)) - for i := range res { - res[i], err = func(item stackitem.Item) (util.Uint160, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint160{}, err - } - u, err := util.Uint160DecodeBytesBE(b) - if err != nil { - return util.Uint160{}, err - } - return u, nil - }(arr[i]) - if err != nil { - return nil, fmt.Errorf("item %d: %w", i, err) - } - } - return res, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field AllowedContracts: %w", err) - } - - index++ - res.AllowedGroups, err = func(item stackitem.Item) (keys.PublicKeys, error) { - arr, ok := item.Value().([]stackitem.Item) - if !ok { - return nil, errors.New("not an array") - } - res := make(keys.PublicKeys, len(arr)) - for i := range res { - res[i], err = func(item stackitem.Item) (*keys.PublicKey, error) { - b, err := item.TryBytes() - if err != nil { - return nil, err - } - k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) - if err != nil { - return nil, err - } - return k, nil - }(arr[i]) - if err != nil { - return nil, fmt.Errorf("item %d: %w", i, err) - } - } - return res, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field AllowedGroups: %w", err) - } - - index++ - res.Rules, err = func(item stackitem.Item) ([]*LedgerWitnessRule, error) { - arr, ok := item.Value().([]stackitem.Item) - if !ok { - return nil, errors.New("not an array") - } - res := make([]*LedgerWitnessRule, len(arr)) - for i := range res { - res[i], err = itemToLedgerWitnessRule(arr[i], nil) - if err != nil { - return nil, fmt.Errorf("item %d: %w", i, err) - } - } - return res, nil - }(arr[index]) - if err != nil { - return fmt.Errorf("field Rules: %w", err) - } - - return nil -} - -// itemToLedgerWitnessCondition converts stack item into *LedgerWitnessCondition. -func itemToLedgerWitnessCondition(item stackitem.Item, err error) (*LedgerWitnessCondition, error) { - if err != nil { - return nil, err - } - var res = new(LedgerWitnessCondition) - err = res.FromStackItem(item) - return res, err -} - -// FromStackItem retrieves fields of LedgerWitnessCondition from the given -// [stackitem.Item] or returns an error if it's not possible to do to so. -func (res *LedgerWitnessCondition) FromStackItem(item stackitem.Item) error { - arr, ok := item.Value().([]stackitem.Item) - if !ok { - return errors.New("not an array") - } - if len(arr) != 2 { - return errors.New("wrong number of structure elements") - } - - var ( - index = -1 - err error - ) - index++ - res.Type, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Type: %w", err) - } - - index++ - res.Value, err = arr[index].Value(), error(nil) - if err != nil { - return fmt.Errorf("field Value: %w", err) - } - - return nil -} - -// itemToLedgerWitnessRule converts stack item into *LedgerWitnessRule. -func itemToLedgerWitnessRule(item stackitem.Item, err error) (*LedgerWitnessRule, error) { - if err != nil { - return nil, err - } - var res = new(LedgerWitnessRule) - err = res.FromStackItem(item) - return res, err -} - -// FromStackItem retrieves fields of LedgerWitnessRule from the given -// [stackitem.Item] or returns an error if it's not possible to do to so. -func (res *LedgerWitnessRule) FromStackItem(item stackitem.Item) error { - arr, ok := item.Value().([]stackitem.Item) - if !ok { - return errors.New("not an array") - } - if len(arr) != 2 { - return errors.New("wrong number of structure elements") - } - - var ( - index = -1 - err error - ) - index++ - res.Action, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Action: %w", err) - } - - index++ - res.Condition, err = itemToLedgerWitnessCondition(arr[index], nil) - if err != nil { - return fmt.Errorf("field Condition: %w", err) - } - - return nil -} - // itemToManagementABI converts stack item into *ManagementABI. func itemToManagementABI(item stackitem.Item, err error) (*ManagementABI, error) { if err != nil { diff --git a/pkg/compiler/debug.go b/pkg/compiler/debug.go index 03589f9eb..667793ff4 100644 --- a/pkg/compiler/debug.go +++ b/pkg/compiler/debug.go @@ -206,10 +206,10 @@ func (c *codegen) emitDebugInfo(contract []byte) *DebugInfo { start := len(d.Methods) d.NamedTypes = make(map[string]binding.ExtendedType) for name, scope := range c.funcs { - m := c.methodInfoFromScope(name, scope, d.NamedTypes) - if m.Range.Start == m.Range.End { + if scope.rng.Start == scope.rng.End { continue } + m := c.methodInfoFromScope(name, scope, d.NamedTypes) d.Methods = append(d.Methods, *m) } sort.Slice(d.Methods[start:], func(i, j int) bool { From 53700349558c54898c41c701f1cf65128abf183d Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Tue, 21 Nov 2023 18:26:35 +0300 Subject: [PATCH 3/6] compiler: deduplicate autoguessed event names, fix #3088 Make them stable wrt parameter order and use proper names in event structures as well. Signed-off-by: Roman Khimov --- .../notifications/rpcbindings_guessed.out | 43 ++++++++++++++++++- pkg/compiler/compiler.go | 15 ++++--- 2 files changed, 50 insertions(+), 8 deletions(-) diff --git a/cli/smartcontract/testdata/rpcbindings/notifications/rpcbindings_guessed.out b/cli/smartcontract/testdata/rpcbindings/notifications/rpcbindings_guessed.out index 6c9128662..e940fa65e 100755 --- a/cli/smartcontract/testdata/rpcbindings/notifications/rpcbindings_guessed.out +++ b/cli/smartcontract/testdata/rpcbindings/notifications/rpcbindings_guessed.out @@ -20,6 +20,11 @@ var Hash = util.Uint160{0x33, 0x22, 0x11, 0x0, 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xa // Unnamed is a contract-specific unnamed type used by its methods. type Unnamed struct { I *big.Int +} + +// UnnamedX is a contract-specific unnamedX type used by its methods. +type UnnamedX struct { + I *big.Int B bool } @@ -35,7 +40,7 @@ type SomeMapEvent struct { // SomeStructEvent represents "SomeStruct" event emitted by the contract. type SomeStructEvent struct { - S *Unnamed + S *UnnamedX } // SomeArrayEvent represents "SomeArray" event emitted by the contract. @@ -193,6 +198,40 @@ func itemToUnnamed(item stackitem.Item, err error) (*Unnamed, error) { // FromStackItem retrieves fields of Unnamed from the given // [stackitem.Item] or returns an error if it's not possible to do to so. func (res *Unnamed) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 1 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.I, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field I: %w", err) + } + + return nil +} + +// itemToUnnamedX converts stack item into *UnnamedX. +func itemToUnnamedX(item stackitem.Item, err error) (*UnnamedX, error) { + if err != nil { + return nil, err + } + var res = new(UnnamedX) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of UnnamedX from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *UnnamedX) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { return errors.New("not an array") @@ -458,7 +497,7 @@ func (e *SomeStructEvent) FromStackItem(item *stackitem.Array) error { err error ) index++ - e.S, err = itemToUnnamed(arr[index], nil) + e.S, err = itemToUnnamedX(arr[index], nil) if err != nil { return fmt.Errorf("field S: %w", err) } diff --git a/pkg/compiler/compiler.go b/pkg/compiler/compiler.go index a7826a552..d6bba8549 100644 --- a/pkg/compiler/compiler.go +++ b/pkg/compiler/compiler.go @@ -388,12 +388,6 @@ func CompileAndSave(src string, o *Options) ([]byte, error) { } } eBindingName := rpcbinding.ToEventBindingName(eventName) - for typeName, extType := range exampleUsage.ExtTypes { - if _, ok := cfg.NamedTypes[typeName]; !ok { - cfg.NamedTypes[typeName] = extType - } - } - for _, p := range exampleUsage.Params { pBindingName := rpcbinding.ToParameterBindingName(p.Name) pname := eBindingName + "." + pBindingName @@ -403,6 +397,15 @@ func CompileAndSave(src string, o *Options) ([]byte, error) { } } if p.ExtendedType != nil { + typeName := p.ExtendedType.Name + if extType, ok := exampleUsage.ExtTypes[typeName]; ok { + for _, ok := cfg.NamedTypes[typeName]; ok; _, ok = cfg.NamedTypes[typeName] { + typeName = typeName + "X" + } + extType.Name = typeName + p.ExtendedType.Name = typeName + cfg.NamedTypes[typeName] = extType + } if _, ok := cfg.Types[pname]; !ok { cfg.Types[pname] = *p.ExtendedType } From fced6a27ba635d0afb47b32a886aa60a8e9e9423 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Tue, 21 Nov 2023 18:41:58 +0300 Subject: [PATCH 4/6] compiler: iterate over autoguessed events in reproducible way Otherwise it's undertermined which of two unnamed structures will get "Unnamed" and "UnnamedX" which can break the test from time to time. Signed-off-by: Roman Khimov --- .../notifications/rpcbindings_guessed.out | 26 +++++++++---------- pkg/compiler/compiler.go | 13 ++++++++-- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/cli/smartcontract/testdata/rpcbindings/notifications/rpcbindings_guessed.out b/cli/smartcontract/testdata/rpcbindings/notifications/rpcbindings_guessed.out index e940fa65e..f3cf84aee 100755 --- a/cli/smartcontract/testdata/rpcbindings/notifications/rpcbindings_guessed.out +++ b/cli/smartcontract/testdata/rpcbindings/notifications/rpcbindings_guessed.out @@ -20,12 +20,12 @@ var Hash = util.Uint160{0x33, 0x22, 0x11, 0x0, 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xa // Unnamed is a contract-specific unnamed type used by its methods. type Unnamed struct { I *big.Int + B bool } // UnnamedX is a contract-specific unnamedX type used by its methods. type UnnamedX struct { I *big.Int - B bool } // ComplicatedNameEvent represents "! complicated name %$#" event emitted by the contract. @@ -40,7 +40,7 @@ type SomeMapEvent struct { // SomeStructEvent represents "SomeStruct" event emitted by the contract. type SomeStructEvent struct { - S *UnnamedX + S *Unnamed } // SomeArrayEvent represents "SomeArray" event emitted by the contract. @@ -50,7 +50,7 @@ type SomeArrayEvent struct { // SomeUnexportedFieldEvent represents "SomeUnexportedField" event emitted by the contract. type SomeUnexportedFieldEvent struct { - S *Unnamed + S *UnnamedX } // Actor is used by Contract to call state-changing methods. @@ -202,7 +202,7 @@ func (res *Unnamed) FromStackItem(item stackitem.Item) error { if !ok { return errors.New("not an array") } - if len(arr) != 1 { + if len(arr) != 2 { return errors.New("wrong number of structure elements") } @@ -216,6 +216,12 @@ func (res *Unnamed) FromStackItem(item stackitem.Item) error { return fmt.Errorf("field I: %w", err) } + index++ + res.B, err = arr[index].TryBool() + if err != nil { + return fmt.Errorf("field B: %w", err) + } + return nil } @@ -236,7 +242,7 @@ func (res *UnnamedX) FromStackItem(item stackitem.Item) error { if !ok { return errors.New("not an array") } - if len(arr) != 2 { + if len(arr) != 1 { return errors.New("wrong number of structure elements") } @@ -250,12 +256,6 @@ func (res *UnnamedX) FromStackItem(item stackitem.Item) error { return fmt.Errorf("field I: %w", err) } - index++ - res.B, err = arr[index].TryBool() - if err != nil { - return fmt.Errorf("field B: %w", err) - } - return nil } @@ -497,7 +497,7 @@ func (e *SomeStructEvent) FromStackItem(item *stackitem.Array) error { err error ) index++ - e.S, err = itemToUnnamedX(arr[index], nil) + e.S, err = itemToUnnamed(arr[index], nil) if err != nil { return fmt.Errorf("field S: %w", err) } @@ -627,7 +627,7 @@ func (e *SomeUnexportedFieldEvent) FromStackItem(item *stackitem.Array) error { err error ) index++ - e.S, err = itemToUnnamed(arr[index], nil) + e.S, err = itemToUnnamedX(arr[index], nil) if err != nil { return fmt.Errorf("field S: %w", err) } diff --git a/pkg/compiler/compiler.go b/pkg/compiler/compiler.go index d6bba8549..37c9077ec 100644 --- a/pkg/compiler/compiler.go +++ b/pkg/compiler/compiler.go @@ -11,6 +11,7 @@ import ( "io" "os" "path/filepath" + "sort" "strings" "github.com/nspcc-dev/neo-go/pkg/smartcontract" @@ -357,8 +358,16 @@ func CompileAndSave(src string, o *Options) ([]byte, error) { } if o.GuessEventTypes { if len(di.EmittedEvents) > 0 { - for eventName, eventUsages := range di.EmittedEvents { - var manifestEvent HybridEvent + var keys = make([]string, 0, len(di.EmittedEvents)) + for k := range di.EmittedEvents { + keys = append(keys, k) + } + sort.Strings(keys) + for _, eventName := range keys { + var ( + eventUsages = di.EmittedEvents[eventName] + manifestEvent HybridEvent + ) for _, e := range o.ContractEvents { if e.Name == eventName { manifestEvent = e From eade327b9b290e2f1a99076580f6d2d9a5ba4b19 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Tue, 21 Nov 2023 19:31:31 +0300 Subject: [PATCH 5/6] compiler: check for pkg nilness, fix #3202 Unfortunately, when import cycle happens somewhere deep in the import chain we dont't get an error from packages.Load(). But it leaves some imports uninitialized, so at least we can check for them. Signed-off-by: Roman Khimov --- pkg/compiler/analysis.go | 9 +++++- pkg/compiler/codegen.go | 3 ++ pkg/compiler/import_test.go | 28 +++++++++++++++++++ .../testdata/importcycle/pkg1/pkg1.go | 9 ++++++ .../testdata/importcycle/pkg2/pkg2.go | 11 ++++++++ .../testdata/importcycle/pkg3/pkg3.go | 11 ++++++++ 6 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 pkg/compiler/testdata/importcycle/pkg1/pkg1.go create mode 100644 pkg/compiler/testdata/importcycle/pkg2/pkg2.go create mode 100644 pkg/compiler/testdata/importcycle/pkg3/pkg3.go diff --git a/pkg/compiler/analysis.go b/pkg/compiler/analysis.go index b3ca6954a..79827d303 100644 --- a/pkg/compiler/analysis.go +++ b/pkg/compiler/analysis.go @@ -282,7 +282,14 @@ func (c *codegen) visitPkg(pkg *packages.Package, seen map[string]bool) { return } for _, imp := range pkg.Types.Imports() { - c.visitPkg(pkg.Imports[imp.Path()], seen) + var subpkg = pkg.Imports[imp.Path()] + if subpkg == nil { + if c.prog.Err == nil { + c.prog.Err = fmt.Errorf("failed to load %q package from %q, import cycle?", imp.Path(), pkg.PkgPath) + } + return + } + c.visitPkg(subpkg, seen) } seen[pkg.PkgPath] = true c.packages = append(c.packages, pkg.PkgPath) diff --git a/pkg/compiler/codegen.go b/pkg/compiler/codegen.go index 957a508e7..e03866aad 100644 --- a/pkg/compiler/codegen.go +++ b/pkg/compiler/codegen.go @@ -2209,6 +2209,9 @@ func (c *codegen) newLambda(u uint16, lit *ast.FuncLit) { func (c *codegen) compile(info *buildInfo, pkg *packages.Package) error { c.mainPkg = pkg c.analyzePkgOrder() + if c.prog.Err != nil { + return c.prog.Err + } c.fillDocumentInfo() funUsage := c.analyzeFuncAndGlobalVarUsage() if c.prog.Err != nil { diff --git a/pkg/compiler/import_test.go b/pkg/compiler/import_test.go index 9080209f4..967d387b1 100644 --- a/pkg/compiler/import_test.go +++ b/pkg/compiler/import_test.go @@ -2,7 +2,11 @@ package compiler_test import ( "math/big" + "strings" "testing" + + "github.com/nspcc-dev/neo-go/pkg/compiler" + "github.com/stretchr/testify/require" ) func TestImportFunction(t *testing.T) { @@ -61,3 +65,27 @@ func TestImportNameSameAsOwn(t *testing.T) { }` eval(t, src, big.NewInt(3)) } + +func TestImportCycleDirect(t *testing.T) { + src := ` + package some + import "github.com/nspcc-dev/neo-go/pkg/compiler/testdata/importcycle/pkg2" + func Main() int { + return pkg2.A + } + ` + _, _, err := compiler.CompileWithOptions("some.go", strings.NewReader(src), nil) + require.Error(t, err) +} + +func TestImportCycleIndirect(t *testing.T) { + src := ` + package some + import "github.com/nspcc-dev/neo-go/pkg/compiler/testdata/importcycle/pkg1" + func Main() int { + return pkg1.A + } + ` + _, _, err := compiler.CompileWithOptions("some.go", strings.NewReader(src), nil) + require.Error(t, err) +} diff --git a/pkg/compiler/testdata/importcycle/pkg1/pkg1.go b/pkg/compiler/testdata/importcycle/pkg1/pkg1.go new file mode 100644 index 000000000..63bdc4fb7 --- /dev/null +++ b/pkg/compiler/testdata/importcycle/pkg1/pkg1.go @@ -0,0 +1,9 @@ +package pkg1 + +import "github.com/nspcc-dev/neo-go/pkg/compiler/testdata/importcycle/pkg2" + +var A int + +func init() { + pkg2.A = 1 +} diff --git a/pkg/compiler/testdata/importcycle/pkg2/pkg2.go b/pkg/compiler/testdata/importcycle/pkg2/pkg2.go new file mode 100644 index 000000000..f80a896d3 --- /dev/null +++ b/pkg/compiler/testdata/importcycle/pkg2/pkg2.go @@ -0,0 +1,11 @@ +package pkg2 + +import ( + "github.com/nspcc-dev/neo-go/pkg/compiler/testdata/importcycle/pkg3" +) + +var A int + +func init() { + pkg3.A = 2 +} diff --git a/pkg/compiler/testdata/importcycle/pkg3/pkg3.go b/pkg/compiler/testdata/importcycle/pkg3/pkg3.go new file mode 100644 index 000000000..35abab456 --- /dev/null +++ b/pkg/compiler/testdata/importcycle/pkg3/pkg3.go @@ -0,0 +1,11 @@ +package pkg3 + +import ( + "github.com/nspcc-dev/neo-go/pkg/compiler/testdata/importcycle/pkg2" +) + +var A int + +func init() { + pkg2.A = 1 +} From 4c9cd438f8c8f6a9dec95a6ff0787ebfcef38ff7 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Tue, 21 Nov 2023 21:46:21 +0300 Subject: [PATCH 6/6] rpcbinding: sort named types to stabilize output Same input -> same output, otherwise tests fail and @AnnaShaleva is annoyed. Signed-off-by: Roman Khimov --- .../testdata/rpcbindings/types/config.yml | 2 +- .../rpcbindings/types/rpcbindings.out | 95 +++++++++++++++++++ .../types/rpcbindings_dynamic_hash.out | 95 +++++++++++++++++++ .../testdata/rpcbindings/types/types.go | 14 +++ pkg/smartcontract/rpcbinding/binding.go | 36 ++++--- 5 files changed, 226 insertions(+), 16 deletions(-) diff --git a/cli/smartcontract/testdata/rpcbindings/types/config.yml b/cli/smartcontract/testdata/rpcbindings/types/config.yml index 98cb40d18..863043bc3 100644 --- a/cli/smartcontract/testdata/rpcbindings/types/config.yml +++ b/cli/smartcontract/testdata/rpcbindings/types/config.yml @@ -1,3 +1,3 @@ name: "Types" sourceurl: https://github.com/nspcc-dev/neo-go/ -safemethods: ["bool", "int", "bytes", "string", "any", "hash160", "hash256", "publicKey", "signature", "bools", "ints", "bytess", "strings", "hash160s", "hash256s", "publicKeys", "signatures", "aAAStrings", "maps", "crazyMaps", "anyMaps"] +safemethods: ["bool", "int", "bytes", "string", "any", "hash160", "hash256", "publicKey", "signature", "bools", "ints", "bytess", "strings", "hash160s", "hash256s", "publicKeys", "signatures", "aAAStrings", "maps", "crazyMaps", "anyMaps", "unnamedStructs", "unnamedStructsX"] diff --git a/cli/smartcontract/testdata/rpcbindings/types/rpcbindings.out b/cli/smartcontract/testdata/rpcbindings/types/rpcbindings.out index 4a46652ab..2bfab59a5 100644 --- a/cli/smartcontract/testdata/rpcbindings/types/rpcbindings.out +++ b/cli/smartcontract/testdata/rpcbindings/types/rpcbindings.out @@ -18,6 +18,17 @@ import ( // Hash contains contract hash. var Hash = util.Uint160{0x33, 0x22, 0x11, 0x0, 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x0} +// Unnamed is a contract-specific unnamed type used by its methods. +type Unnamed struct { + I *big.Int +} + +// UnnamedX is a contract-specific unnamedX type used by its methods. +type UnnamedX struct { + I *big.Int + B bool +} + // Invoker is used by ContractReader to call various safe methods. type Invoker interface { Call(contract util.Uint160, operation string, params ...any) (*result.Invoke, error) @@ -347,3 +358,87 @@ func (c *ContractReader) String(s string) (string, error) { func (c *ContractReader) Strings(s []string) ([]string, error) { return unwrap.ArrayOfUTF8Strings(c.invoker.Call(c.hash, "strings", s)) } + +// UnnamedStructs invokes `unnamedStructs` method of contract. +func (c *ContractReader) UnnamedStructs() (*Unnamed, error) { + return itemToUnnamed(unwrap.Item(c.invoker.Call(c.hash, "unnamedStructs"))) +} + +// UnnamedStructsX invokes `unnamedStructsX` method of contract. +func (c *ContractReader) UnnamedStructsX() (*UnnamedX, error) { + return itemToUnnamedX(unwrap.Item(c.invoker.Call(c.hash, "unnamedStructsX"))) +} + +// itemToUnnamed converts stack item into *Unnamed. +func itemToUnnamed(item stackitem.Item, err error) (*Unnamed, error) { + if err != nil { + return nil, err + } + var res = new(Unnamed) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of Unnamed from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *Unnamed) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 1 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.I, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field I: %w", err) + } + + return nil +} + +// itemToUnnamedX converts stack item into *UnnamedX. +func itemToUnnamedX(item stackitem.Item, err error) (*UnnamedX, error) { + if err != nil { + return nil, err + } + var res = new(UnnamedX) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of UnnamedX from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *UnnamedX) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.I, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field I: %w", err) + } + + index++ + res.B, err = arr[index].TryBool() + if err != nil { + return fmt.Errorf("field B: %w", err) + } + + return nil +} diff --git a/cli/smartcontract/testdata/rpcbindings/types/rpcbindings_dynamic_hash.out b/cli/smartcontract/testdata/rpcbindings/types/rpcbindings_dynamic_hash.out index fbd348691..749c12b8d 100755 --- a/cli/smartcontract/testdata/rpcbindings/types/rpcbindings_dynamic_hash.out +++ b/cli/smartcontract/testdata/rpcbindings/types/rpcbindings_dynamic_hash.out @@ -15,6 +15,17 @@ import ( "unicode/utf8" ) +// Unnamed is a contract-specific unnamed type used by its methods. +type Unnamed struct { + I *big.Int +} + +// UnnamedX is a contract-specific unnamedX type used by its methods. +type UnnamedX struct { + I *big.Int + B bool +} + // Invoker is used by ContractReader to call various safe methods. type Invoker interface { Call(contract util.Uint160, operation string, params ...any) (*result.Invoke, error) @@ -343,3 +354,87 @@ func (c *ContractReader) String(s string) (string, error) { func (c *ContractReader) Strings(s []string) ([]string, error) { return unwrap.ArrayOfUTF8Strings(c.invoker.Call(c.hash, "strings", s)) } + +// UnnamedStructs invokes `unnamedStructs` method of contract. +func (c *ContractReader) UnnamedStructs() (*Unnamed, error) { + return itemToUnnamed(unwrap.Item(c.invoker.Call(c.hash, "unnamedStructs"))) +} + +// UnnamedStructsX invokes `unnamedStructsX` method of contract. +func (c *ContractReader) UnnamedStructsX() (*UnnamedX, error) { + return itemToUnnamedX(unwrap.Item(c.invoker.Call(c.hash, "unnamedStructsX"))) +} + +// itemToUnnamed converts stack item into *Unnamed. +func itemToUnnamed(item stackitem.Item, err error) (*Unnamed, error) { + if err != nil { + return nil, err + } + var res = new(Unnamed) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of Unnamed from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *Unnamed) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 1 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.I, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field I: %w", err) + } + + return nil +} + +// itemToUnnamedX converts stack item into *UnnamedX. +func itemToUnnamedX(item stackitem.Item, err error) (*UnnamedX, error) { + if err != nil { + return nil, err + } + var res = new(UnnamedX) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of UnnamedX from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *UnnamedX) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.I, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field I: %w", err) + } + + index++ + res.B, err = arr[index].TryBool() + if err != nil { + return fmt.Errorf("field B: %w", err) + } + + return nil +} diff --git a/cli/smartcontract/testdata/rpcbindings/types/types.go b/cli/smartcontract/testdata/rpcbindings/types/types.go index fcf91a0be..fdba19917 100644 --- a/cli/smartcontract/testdata/rpcbindings/types/types.go +++ b/cli/smartcontract/testdata/rpcbindings/types/types.go @@ -87,3 +87,17 @@ func CrazyMaps(m map[int][]map[string][]interop.Hash160) map[int][]map[string][] func AnyMaps(m map[int]any) map[int]any { return m } + +func UnnamedStructs() struct{ I int } { + return struct{ I int }{I: 123} +} + +func UnnamedStructsX() struct { + I int + B bool +} { + return struct { + I int + B bool + }{I: 123, B: true} +} diff --git a/pkg/smartcontract/rpcbinding/binding.go b/pkg/smartcontract/rpcbinding/binding.go index c35d9c179..de801a5de 100644 --- a/pkg/smartcontract/rpcbinding/binding.go +++ b/pkg/smartcontract/rpcbinding/binding.go @@ -124,9 +124,9 @@ import ( // Hash contains contract hash. var Hash = {{ .Hash }} {{end -}} -{{- range $name, $typ := .NamedTypes }} -// {{toTypeName $name}} is a contract-specific {{$name}} type used by its methods. -type {{toTypeName $name}} struct { +{{- range $index, $typ := .NamedTypes }} +// {{toTypeName $typ.Name}} is a contract-specific {{$typ.Name}} type used by its methods. +type {{toTypeName $typ.Name}} struct { {{- range $m := $typ.Fields}} {{ upperFirst .Field}} {{etTypeToStr .ExtendedType}} {{- end}} @@ -236,20 +236,20 @@ func New(actor Actor{{- if not (len .Hash) -}}, hash util.Uint160{{- end -}}) *C {{end -}} {{- range $m := .SafeMethods }}{{template "SAFEMETHOD" $m }}{{ end -}} {{- range $m := .Methods -}}{{template "METHOD" $m }}{{ end -}} -{{- range $name, $typ := .NamedTypes }} -// itemTo{{toTypeName $name}} converts stack item into *{{toTypeName $name}}. -func itemTo{{toTypeName $name}}(item stackitem.Item, err error) (*{{toTypeName $name}}, error) { +{{- range $index, $typ := .NamedTypes }} +// itemTo{{toTypeName $typ.Name}} converts stack item into *{{toTypeName $typ.Name}}. +func itemTo{{toTypeName $typ.Name}}(item stackitem.Item, err error) (*{{toTypeName $typ.Name}}, error) { if err != nil { return nil, err } - var res = new({{toTypeName $name}}) + var res = new({{toTypeName $typ.Name}}) err = res.FromStackItem(item) return res, err } -// FromStackItem retrieves fields of {{toTypeName $name}} from the given +// 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. -func (res *{{toTypeName $name}}) FromStackItem(item stackitem.Item) error { +func (res *{{toTypeName $typ.Name}}) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { return errors.New("not an array") @@ -341,7 +341,7 @@ type ( SafeMethods []SafeMethodTmpl CustomEvents []CustomEventTemplate - NamedTypes map[string]binding.ExtendedType + NamedTypes []binding.ExtendedType IsNep11D bool IsNep11ND bool @@ -430,7 +430,13 @@ func Generate(cfg binding.Config) error { ctr.ContractTmpl = binding.TemplateFromManifest(cfg, scTypeToGo) ctr = scTemplateToRPC(cfg, ctr, imports, scTypeToGo) - ctr.NamedTypes = cfg.NamedTypes + ctr.NamedTypes = make([]binding.ExtendedType, 0, len(cfg.NamedTypes)) + for k := range cfg.NamedTypes { + ctr.NamedTypes = append(ctr.NamedTypes, cfg.NamedTypes[k]) + } + sort.Slice(ctr.NamedTypes, func(i, j int) bool { + return strings.Compare(ctr.NamedTypes[i].Name, ctr.NamedTypes[j].Name) < 0 + }) // Check resulting named types and events don't have duplicating field names. for _, t := range ctr.NamedTypes { @@ -458,7 +464,7 @@ func Generate(cfg binding.Config) error { "addIndent": addIndent, "etTypeConverter": etTypeConverter, "etTypeToStr": func(et binding.ExtendedType) string { - r, _ := extendedTypeToGo(et, ctr.NamedTypes) + r, _ := extendedTypeToGo(et, cfg.NamedTypes) return r }, "toTypeName": toTypeName, @@ -719,7 +725,7 @@ func scTemplateToRPC(cfg binding.Config, ctr ContractTmpl, imports map[string]st } } for _, et := range cfg.NamedTypes { - addETImports(et, ctr.NamedTypes, imports) + addETImports(et, cfg.NamedTypes, imports) } if len(cfg.NamedTypes) > 0 { imports["errors"] = struct{}{} @@ -746,7 +752,7 @@ func scTemplateToRPC(cfg binding.Config, ctr ContractTmpl, imports map[string]st extType = binding.ExtendedType{ Base: abiEvent.Parameters[i].Type, } - addETImports(extType, ctr.NamedTypes, imports) + addETImports(extType, cfg.NamedTypes, imports) } eTmp.Parameters = append(eTmp.Parameters, EventParamTmpl{ ParamTmpl: binding.ParamTmpl{ @@ -817,7 +823,7 @@ func scTemplateToRPC(cfg binding.Config, ctr ContractTmpl, imports map[string]st case "keys.PublicKeys": ctr.SafeMethods[i].Unwrapper = "ArrayOfPublicKeys" default: - addETImports(ctr.SafeMethods[i].ExtendedReturn, ctr.NamedTypes, imports) + addETImports(ctr.SafeMethods[i].ExtendedReturn, cfg.NamedTypes, imports) ctr.SafeMethods[i].Unwrapper = "Item" } }