github.com/nspcc-dev/neo-go@v0.105.2-0.20240517133400-6be757af3eba/pkg/rpcclient/management/management_test.go (about)

     1  package management
     2  
     3  import (
     4  	"errors"
     5  	"math/big"
     6  	"testing"
     7  
     8  	"github.com/google/uuid"
     9  	"github.com/nspcc-dev/neo-go/pkg/core/transaction"
    10  	"github.com/nspcc-dev/neo-go/pkg/neorpc/result"
    11  	"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
    12  	"github.com/nspcc-dev/neo-go/pkg/smartcontract/nef"
    13  	"github.com/nspcc-dev/neo-go/pkg/util"
    14  	"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
    15  	"github.com/stretchr/testify/require"
    16  )
    17  
    18  type testAct struct {
    19  	err error
    20  	res *result.Invoke
    21  	tx  *transaction.Transaction
    22  	txh util.Uint256
    23  	vub uint32
    24  }
    25  
    26  func (t *testAct) Call(contract util.Uint160, operation string, params ...any) (*result.Invoke, error) {
    27  	return t.res, t.err
    28  }
    29  func (t *testAct) MakeCall(contract util.Uint160, method string, params ...any) (*transaction.Transaction, error) {
    30  	return t.tx, t.err
    31  }
    32  func (t *testAct) MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...any) (*transaction.Transaction, error) {
    33  	return t.tx, t.err
    34  }
    35  func (t *testAct) SendCall(contract util.Uint160, method string, params ...any) (util.Uint256, uint32, error) {
    36  	return t.txh, t.vub, t.err
    37  }
    38  func (t *testAct) MakeRun(script []byte) (*transaction.Transaction, error) {
    39  	return t.tx, t.err
    40  }
    41  func (t *testAct) MakeUnsignedRun(script []byte, attrs []transaction.Attribute) (*transaction.Transaction, error) {
    42  	return t.tx, t.err
    43  }
    44  func (t *testAct) SendRun(script []byte) (util.Uint256, uint32, error) {
    45  	return t.txh, t.vub, t.err
    46  }
    47  func (t *testAct) CallAndExpandIterator(contract util.Uint160, method string, maxItems int, params ...any) (*result.Invoke, error) {
    48  	return t.res, t.err
    49  }
    50  func (t *testAct) TerminateSession(sessionID uuid.UUID) error {
    51  	return t.err
    52  }
    53  func (t *testAct) TraverseIterator(sessionID uuid.UUID, iterator *result.Iterator, num int) ([]stackitem.Item, error) {
    54  	return t.res.Stack, t.err
    55  }
    56  
    57  func TestReader(t *testing.T) {
    58  	ta := new(testAct)
    59  	man := NewReader(ta)
    60  
    61  	ta.err = errors.New("")
    62  	_, err := man.GetContract(util.Uint160{1, 2, 3})
    63  	require.Error(t, err)
    64  	_, err = man.GetContractByID(1)
    65  	require.Error(t, err)
    66  	_, err = man.GetMinimumDeploymentFee()
    67  	require.Error(t, err)
    68  	_, err = man.HasMethod(util.Uint160{1, 2, 3}, "method", 0)
    69  	require.Error(t, err)
    70  
    71  	ta.err = nil
    72  	ta.res = &result.Invoke{
    73  		State: "HALT",
    74  		Stack: []stackitem.Item{
    75  			stackitem.Make(42),
    76  		},
    77  	}
    78  	_, err = man.GetContract(util.Uint160{1, 2, 3})
    79  	require.Error(t, err)
    80  	_, err = man.GetContractByID(1)
    81  	require.Error(t, err)
    82  	fee, err := man.GetMinimumDeploymentFee()
    83  	require.NoError(t, err)
    84  	require.Equal(t, big.NewInt(42), fee)
    85  	hm, err := man.HasMethod(util.Uint160{1, 2, 3}, "method", 0)
    86  	require.NoError(t, err)
    87  	require.True(t, hm)
    88  
    89  	ta.res = &result.Invoke{
    90  		State: "HALT",
    91  		Stack: []stackitem.Item{
    92  			stackitem.Make(false),
    93  		},
    94  	}
    95  	_, err = man.GetContract(util.Uint160{1, 2, 3})
    96  	require.Error(t, err)
    97  	_, err = man.GetContractByID(1)
    98  	require.Error(t, err)
    99  	hm, err = man.HasMethod(util.Uint160{1, 2, 3}, "method", 0)
   100  	require.NoError(t, err)
   101  	require.False(t, hm)
   102  
   103  	ta.res = &result.Invoke{
   104  		State: "HALT",
   105  		Stack: []stackitem.Item{
   106  			stackitem.Null{},
   107  		},
   108  	}
   109  
   110  	cs, err := man.GetContract(util.Uint160{1, 2, 3})
   111  	require.NoError(t, err)
   112  	require.Nil(t, cs)
   113  
   114  	ta.res = &result.Invoke{
   115  		State: "HALT",
   116  		Stack: []stackitem.Item{
   117  			stackitem.Make([]stackitem.Item{}),
   118  		},
   119  	}
   120  	_, err = man.GetContract(util.Uint160{1, 2, 3})
   121  	require.Error(t, err)
   122  	_, err = man.GetContractByID(1)
   123  	require.Error(t, err)
   124  
   125  	nefFile, _ := nef.NewFile([]byte{1, 2, 3})
   126  	nefBytes, _ := nefFile.Bytes()
   127  	manif := manifest.DefaultManifest("stack item")
   128  	manifItem, _ := manif.ToStackItem()
   129  	ta.res = &result.Invoke{
   130  		State: "HALT",
   131  		Stack: []stackitem.Item{
   132  			stackitem.Make([]stackitem.Item{
   133  				stackitem.Make(1),
   134  				stackitem.Make(0),
   135  				stackitem.Make(util.Uint160{1, 2, 3}.BytesBE()),
   136  				stackitem.Make(nefBytes),
   137  				manifItem,
   138  			}),
   139  		},
   140  	}
   141  	cs, err = man.GetContract(util.Uint160{1, 2, 3})
   142  	require.NoError(t, err)
   143  	require.Equal(t, int32(1), cs.ID)
   144  	require.Equal(t, uint16(0), cs.UpdateCounter)
   145  	require.Equal(t, util.Uint160{1, 2, 3}, cs.Hash)
   146  	cs2, err := man.GetContractByID(1)
   147  	require.NoError(t, err)
   148  	require.Equal(t, cs, cs2)
   149  }
   150  
   151  func TestGetContractHashes(t *testing.T) {
   152  	ta := &testAct{}
   153  	man := NewReader(ta)
   154  
   155  	ta.err = errors.New("")
   156  	_, err := man.GetContractHashes()
   157  	require.Error(t, err)
   158  	_, err = man.GetContractHashesExpanded(5)
   159  	require.Error(t, err)
   160  
   161  	ta.err = nil
   162  	iid := uuid.New()
   163  	ta.res = &result.Invoke{
   164  		State: "HALT",
   165  		Stack: []stackitem.Item{
   166  			stackitem.NewInterop(result.Iterator{
   167  				ID: &iid,
   168  			}),
   169  		},
   170  	}
   171  	_, err = man.GetContractHashes()
   172  	require.Error(t, err)
   173  
   174  	// Session-based iterator.
   175  	sid := uuid.New()
   176  	ta.res = &result.Invoke{
   177  		Session: sid,
   178  		State:   "HALT",
   179  		Stack: []stackitem.Item{
   180  			stackitem.NewInterop(result.Iterator{
   181  				ID: &iid,
   182  			}),
   183  		},
   184  	}
   185  	iter, err := man.GetContractHashes()
   186  	require.NoError(t, err)
   187  
   188  	ta.res = &result.Invoke{
   189  		Stack: []stackitem.Item{
   190  			stackitem.Make([]stackitem.Item{
   191  				stackitem.Make([]byte{0, 0, 0, 1}),
   192  				stackitem.Make(util.Uint160{1, 2, 3}.BytesBE()),
   193  			}),
   194  		},
   195  	}
   196  	vals, err := iter.Next(10)
   197  	require.NoError(t, err)
   198  	require.Equal(t, 1, len(vals))
   199  	require.Equal(t, IDHash{
   200  		ID:   1,
   201  		Hash: util.Uint160{1, 2, 3},
   202  	}, vals[0])
   203  
   204  	ta.err = errors.New("")
   205  	_, err = iter.Next(1)
   206  	require.Error(t, err)
   207  
   208  	err = iter.Terminate()
   209  	require.Error(t, err)
   210  
   211  	// Value-based iterator.
   212  	ta.err = nil
   213  	ta.res = &result.Invoke{
   214  		State: "HALT",
   215  		Stack: []stackitem.Item{
   216  			stackitem.NewInterop(result.Iterator{
   217  				Values: []stackitem.Item{stackitem.NewStruct([]stackitem.Item{
   218  					stackitem.Make([]byte{0, 0, 0, 1}),
   219  					stackitem.Make(util.Uint160{1, 2, 3}.BytesBE()),
   220  				})},
   221  			}),
   222  		},
   223  	}
   224  	iter, err = man.GetContractHashes()
   225  	require.NoError(t, err)
   226  
   227  	ta.err = errors.New("")
   228  	err = iter.Terminate()
   229  	require.NoError(t, err)
   230  
   231  	// Expanded
   232  	ta.err = nil
   233  	ta.res = &result.Invoke{
   234  		State: "HALT",
   235  		Stack: []stackitem.Item{
   236  			stackitem.Make([]stackitem.Item{stackitem.Make([]stackitem.Item{
   237  				stackitem.Make([]byte{0, 0, 0, 1}),
   238  				stackitem.Make(util.Uint160{1, 2, 3}.BytesBE()),
   239  			})}),
   240  		},
   241  	}
   242  	vals, err = man.GetContractHashesExpanded(5)
   243  	require.NoError(t, err)
   244  	require.Equal(t, 1, len(vals))
   245  	require.Equal(t, IDHash{
   246  		ID:   1,
   247  		Hash: util.Uint160{1, 2, 3},
   248  	}, vals[0])
   249  }
   250  
   251  func TestSetMinimumDeploymentFee(t *testing.T) {
   252  	ta := new(testAct)
   253  	man := New(ta)
   254  
   255  	ta.err = errors.New("")
   256  	_, _, err := man.SetMinimumDeploymentFee(big.NewInt(42))
   257  	require.Error(t, err)
   258  
   259  	for _, m := range []func(*big.Int) (*transaction.Transaction, error){
   260  		man.SetMinimumDeploymentFeeTransaction,
   261  		man.SetMinimumDeploymentFeeUnsigned,
   262  	} {
   263  		_, err = m(big.NewInt(100))
   264  		require.Error(t, err)
   265  	}
   266  
   267  	ta.err = nil
   268  	ta.txh = util.Uint256{1, 2, 3}
   269  	ta.vub = 42
   270  
   271  	h, vub, err := man.SetMinimumDeploymentFee(big.NewInt(42))
   272  	require.NoError(t, err)
   273  	require.Equal(t, ta.txh, h)
   274  	require.Equal(t, ta.vub, vub)
   275  
   276  	ta.tx = transaction.New([]byte{1, 2, 3}, 100500)
   277  	for _, m := range []func(*big.Int) (*transaction.Transaction, error){
   278  		man.SetMinimumDeploymentFeeTransaction,
   279  		man.SetMinimumDeploymentFeeUnsigned,
   280  	} {
   281  		tx, err := m(big.NewInt(100))
   282  		require.NoError(t, err)
   283  		require.Equal(t, ta.tx, tx)
   284  	}
   285  }
   286  
   287  func TestDeploy(t *testing.T) {
   288  	ta := new(testAct)
   289  	man := New(ta)
   290  	nefFile, _ := nef.NewFile([]byte{1, 2, 3})
   291  	manif := manifest.DefaultManifest("stack item")
   292  
   293  	ta.err = errors.New("")
   294  	_, _, err := man.Deploy(nefFile, manif, nil)
   295  	require.Error(t, err)
   296  
   297  	for _, m := range []func(exe *nef.File, manif *manifest.Manifest, data any) (*transaction.Transaction, error){
   298  		man.DeployTransaction,
   299  		man.DeployUnsigned,
   300  	} {
   301  		_, err = m(nefFile, manif, nil)
   302  		require.Error(t, err)
   303  	}
   304  
   305  	ta.err = nil
   306  	ta.txh = util.Uint256{1, 2, 3}
   307  	ta.vub = 42
   308  
   309  	h, vub, err := man.Deploy(nefFile, manif, nil)
   310  	require.NoError(t, err)
   311  	require.Equal(t, ta.txh, h)
   312  	require.Equal(t, ta.vub, vub)
   313  
   314  	ta.tx = transaction.New([]byte{1, 2, 3}, 100500)
   315  	for _, m := range []func(exe *nef.File, manif *manifest.Manifest, data any) (*transaction.Transaction, error){
   316  		man.DeployTransaction,
   317  		man.DeployUnsigned,
   318  	} {
   319  		tx, err := m(nefFile, manif, nil)
   320  		require.NoError(t, err)
   321  		require.Equal(t, ta.tx, tx)
   322  
   323  		_, err = m(nefFile, manif, map[int]int{})
   324  		require.Error(t, err)
   325  	}
   326  
   327  	_, _, err = man.Deploy(nefFile, manif, map[int]int{})
   328  	require.Error(t, err)
   329  
   330  	_, _, err = man.Deploy(nefFile, manif, 100500)
   331  	require.NoError(t, err)
   332  
   333  	nefFile.Compiler = "intentionally very long compiler string that will make NEF code explode on encoding"
   334  	_, _, err = man.Deploy(nefFile, manif, nil)
   335  	require.Error(t, err)
   336  
   337  	// Unfortunately, manifest _always_ marshals successfully (or panics).
   338  }
   339  
   340  func TestItemsToIDHashesErrors(t *testing.T) {
   341  	for name, input := range map[string][]stackitem.Item{
   342  		"not a struct": {stackitem.Make(1)},
   343  		"wrong length": {stackitem.Make([]stackitem.Item{})},
   344  		"wrong id": {stackitem.Make([]stackitem.Item{
   345  			stackitem.Make([]stackitem.Item{}),
   346  			stackitem.Make(util.Uint160{1, 2, 3}.BytesBE()),
   347  		})},
   348  		"lengthy id": {stackitem.Make([]stackitem.Item{
   349  			stackitem.Make(util.Uint160{1, 2, 3}.BytesBE()),
   350  			stackitem.Make(util.Uint160{1, 2, 3}.BytesBE()),
   351  		})},
   352  		"not a good hash": {stackitem.Make([]stackitem.Item{
   353  			stackitem.Make([]byte{0, 0, 0, 1}),
   354  			stackitem.Make([]stackitem.Item{}),
   355  		})},
   356  		"not a good u160 hash": {stackitem.Make([]stackitem.Item{
   357  			stackitem.Make([]byte{0, 0, 0, 1}),
   358  			stackitem.Make(util.Uint256{1, 2, 3}.BytesBE()),
   359  		})},
   360  	} {
   361  		t.Run(name, func(t *testing.T) {
   362  			_, err := itemsToIDHashes(input)
   363  			require.Error(t, err)
   364  		})
   365  	}
   366  }