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 }