github.com/nspcc-dev/neo-go@v0.105.2-0.20240517133400-6be757af3eba/pkg/smartcontract/parameter_test.go (about) 1 package smartcontract 2 3 import ( 4 "encoding/base64" 5 "encoding/hex" 6 "encoding/json" 7 "errors" 8 "math" 9 "math/big" 10 "strings" 11 "testing" 12 13 "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" 14 15 "github.com/nspcc-dev/neo-go/pkg/crypto/keys" 16 "github.com/nspcc-dev/neo-go/pkg/io" 17 "github.com/nspcc-dev/neo-go/pkg/util" 18 "github.com/nspcc-dev/neo-go/pkg/vm/emit" 19 "github.com/stretchr/testify/assert" 20 "github.com/stretchr/testify/require" 21 ) 22 23 var marshalJSONTestCases = []struct { 24 input Parameter 25 result string 26 }{ 27 { 28 input: Parameter{Type: IntegerType, Value: big.NewInt(12345)}, 29 result: `{"type":"Integer","value":12345}`, 30 }, 31 { 32 input: Parameter{Type: IntegerType, Value: new(big.Int).Lsh(big.NewInt(1), 254)}, 33 result: `{"type":"Integer","value":"` + new(big.Int).Lsh(big.NewInt(1), 254).String() + `"}`, 34 }, 35 { 36 input: Parameter{Type: StringType, Value: "Some string"}, 37 result: `{"type":"String","value":"Some string"}`, 38 }, 39 { 40 input: Parameter{Type: BoolType, Value: true}, 41 result: `{"type":"Boolean","value":true}`, 42 }, 43 { 44 input: Parameter{Type: ByteArrayType, Value: []byte{0x01, 0x02, 0x03}}, 45 result: `{"type":"ByteString","value":"` + hexToBase64("010203") + `"}`, 46 }, 47 { 48 input: Parameter{Type: ByteArrayType}, 49 result: `{"type":"ByteString","value":null}`, 50 }, 51 { 52 input: Parameter{Type: SignatureType}, 53 result: `{"type":"Signature"}`, 54 }, 55 { 56 input: Parameter{ 57 Type: PublicKeyType, 58 Value: []byte{0x03, 0xb3, 0xbf, 0x15, 0x02, 0xfb, 0xdc, 0x05, 0x44, 0x9b, 0x50, 0x6a, 0xaf, 0x04, 0x57, 0x97, 0x24, 0x02, 0x4b, 0x06, 0x54, 0x2e, 0x49, 0x26, 0x2b, 0xfa, 0xa3, 0xf7, 0x0e, 0x20, 0x00, 0x40, 0xa9}, 59 }, 60 result: `{"type":"PublicKey","value":"03b3bf1502fbdc05449b506aaf04579724024b06542e49262bfaa3f70e200040a9"}`, 61 }, 62 { 63 input: Parameter{ 64 Type: ArrayType, 65 Value: []Parameter{ 66 {Type: StringType, Value: "str 1"}, 67 {Type: IntegerType, Value: big.NewInt(2)}, 68 }, 69 }, 70 result: `{"type":"Array","value":[{"type":"String","value":"str 1"},{"type":"Integer","value":2}]}`, 71 }, 72 { 73 input: Parameter{ 74 Type: ArrayType, 75 Value: []Parameter{ 76 {Type: ByteArrayType, Value: []byte{1, 2}}, 77 { 78 Type: ArrayType, 79 Value: []Parameter{ 80 {Type: ByteArrayType, Value: []byte{3, 2, 1}}, 81 {Type: ByteArrayType, Value: []byte{7, 8, 9}}, 82 }}, 83 }, 84 }, 85 result: `{"type":"Array","value":[{"type":"ByteString","value":"` + hexToBase64("0102") + `"},{"type":"Array","value":[` + 86 `{"type":"ByteString","value":"` + hexToBase64("030201") + `"},{"type":"ByteString","value":"` + hexToBase64("070809") + `"}]}]}`, 87 }, 88 { 89 input: Parameter{ 90 Type: MapType, 91 Value: []ParameterPair{ 92 { 93 Key: Parameter{Type: StringType, Value: "key1"}, 94 Value: Parameter{Type: IntegerType, Value: big.NewInt(1)}, 95 }, 96 { 97 Key: Parameter{Type: StringType, Value: "key2"}, 98 Value: Parameter{Type: StringType, Value: "two"}, 99 }, 100 }, 101 }, 102 result: `{"type":"Map","value":[{"key":{"type":"String","value":"key1"},"value":{"type":"Integer","value":1}},{"key":{"type":"String","value":"key2"},"value":{"type":"String","value":"two"}}]}`, 103 }, 104 { 105 input: Parameter{ 106 Type: MapType, 107 Value: []ParameterPair{ 108 { 109 Key: Parameter{Type: StringType, Value: "key1"}, 110 Value: Parameter{Type: ArrayType, Value: []Parameter{ 111 {Type: StringType, Value: "str 1"}, 112 {Type: IntegerType, Value: big.NewInt(2)}, 113 }}, 114 }, 115 }, 116 }, 117 result: `{"type":"Map","value":[{"key":{"type":"String","value":"key1"},"value":{"type":"Array","value":[{"type":"String","value":"str 1"},{"type":"Integer","value":2}]}}]}`, 118 }, 119 { 120 input: Parameter{ 121 Type: Hash160Type, 122 Value: util.Uint160{ 123 0xd6, 0x24, 0x87, 0x12, 0xff, 0x97, 0x22, 0x80, 0xa0, 0xae, 124 0xf5, 0x24, 0x1c, 0x96, 0x4d, 0x63, 0x78, 0x29, 0xcd, 0xb, 125 }, 126 }, 127 result: `{"type":"Hash160","value":"0x0bcd2978634d961c24f5aea0802297ff128724d6"}`, 128 }, 129 { 130 input: Parameter{ 131 Type: Hash256Type, 132 Value: util.Uint256{ 133 0x2d, 0xf3, 0x45, 0xf2, 0x45, 0xc5, 0x98, 0x9e, 134 0x69, 0x95, 0x45, 0x06, 0xa5, 0x9e, 0x40, 0x12, 135 0xc1, 0x68, 0x54, 0x48, 0x08, 0xfc, 0xcc, 0x5b, 136 0x15, 0x18, 0xab, 0xa0, 0x8f, 0x30, 0x37, 0xf0, 137 }, 138 }, 139 result: `{"type":"Hash256","value":"0xf037308fa0ab18155bccfc08485468c112409ea5064595699e98c545f245f32d"}`, 140 }, 141 { 142 input: Parameter{ 143 Type: InteropInterfaceType, 144 Value: nil, 145 }, 146 result: `{"type":"InteropInterface","value":null}`, 147 }, 148 { 149 input: Parameter{ 150 Type: ArrayType, 151 Value: []Parameter{}, 152 }, 153 result: `{"type":"Array","value":[]}`, 154 }, 155 } 156 157 var marshalJSONErrorCases = []Parameter{ 158 { 159 Type: UnknownType, 160 Value: nil, 161 }, 162 { 163 Type: IntegerType, 164 Value: math.Inf(1), 165 }, 166 } 167 168 func TestParam_MarshalJSON(t *testing.T) { 169 for _, tc := range marshalJSONTestCases { 170 res, err := json.Marshal(tc.input) 171 assert.NoError(t, err) 172 var actual, expected Parameter 173 assert.NoError(t, json.Unmarshal(res, &actual)) 174 assert.NoError(t, json.Unmarshal([]byte(tc.result), &expected)) 175 176 assert.Equal(t, expected, actual) 177 } 178 179 for _, input := range marshalJSONErrorCases { 180 _, err := json.Marshal(&input) 181 assert.Error(t, err) 182 } 183 } 184 185 var unmarshalJSONTestCases = []struct { 186 input string 187 result Parameter 188 }{ 189 { 190 input: `{"type":"Bool","value":true}`, 191 result: Parameter{Type: BoolType, Value: true}, 192 }, 193 { 194 input: `{"type":"Integer","value":12345}`, 195 result: Parameter{Type: IntegerType, Value: big.NewInt(12345)}, 196 }, 197 { 198 input: `{"type":"Integer","value":"12345"}`, 199 result: Parameter{Type: IntegerType, Value: big.NewInt(12345)}, 200 }, 201 { 202 input: `{"type":"ByteString","value":"` + hexToBase64("010203") + `"}`, 203 result: Parameter{Type: ByteArrayType, Value: []byte{0x01, 0x02, 0x03}}, 204 }, 205 { 206 input: `{"type":"String","value":"Some string"}`, 207 result: Parameter{Type: StringType, Value: "Some string"}, 208 }, 209 { 210 input: `{"type":"Signature"}`, 211 result: Parameter{Type: SignatureType}, 212 }, 213 { 214 input: `{"type":"Signature","value":null }`, 215 result: Parameter{Type: SignatureType}, 216 }, 217 { 218 input: `{"type":"Array","value":[ 219 {"type": "String", "value": "str 1"}, 220 {"type": "Integer", "value": 2}]}`, 221 result: Parameter{ 222 Type: ArrayType, 223 Value: []Parameter{ 224 {Type: StringType, Value: "str 1"}, 225 {Type: IntegerType, Value: big.NewInt(2)}, 226 }, 227 }, 228 }, 229 { 230 input: `{"type": "Hash160", "value": "0bcd2978634d961c24f5aea0802297ff128724d6"}`, 231 result: Parameter{ 232 Type: Hash160Type, 233 Value: util.Uint160{ 234 0xd6, 0x24, 0x87, 0x12, 0xff, 0x97, 0x22, 0x80, 0xa0, 0xae, 235 0xf5, 0x24, 0x1c, 0x96, 0x4d, 0x63, 0x78, 0x29, 0xcd, 0xb, 236 }, 237 }, 238 }, 239 { 240 input: `{"type": "Hash256", "value": "f037308fa0ab18155bccfc08485468c112409ea5064595699e98c545f245f32d"}`, 241 result: Parameter{ 242 Type: Hash256Type, 243 Value: util.Uint256{ 244 0x2d, 0xf3, 0x45, 0xf2, 0x45, 0xc5, 0x98, 0x9e, 245 0x69, 0x95, 0x45, 0x06, 0xa5, 0x9e, 0x40, 0x12, 246 0xc1, 0x68, 0x54, 0x48, 0x08, 0xfc, 0xcc, 0x5b, 247 0x15, 0x18, 0xab, 0xa0, 0x8f, 0x30, 0x37, 0xf0, 248 }, 249 }, 250 }, 251 { 252 input: `{"type":"Map","value":[{"key":{"type":"String","value":"key1"},"value":{"type":"Integer","value":1}},{"key":{"type":"String","value":"key2"},"value":{"type":"String","value":"two"}}]}`, 253 result: Parameter{ 254 Type: MapType, 255 Value: []ParameterPair{ 256 { 257 Key: Parameter{Type: StringType, Value: "key1"}, 258 Value: Parameter{Type: IntegerType, Value: big.NewInt(1)}, 259 }, 260 { 261 Key: Parameter{Type: StringType, Value: "key2"}, 262 Value: Parameter{Type: StringType, Value: "two"}, 263 }, 264 }, 265 }, 266 }, 267 { 268 input: `{"type":"Map","value":[{"key":{"type":"String","value":"key1"},"value":{"type":"Array","value":[{"type":"String","value":"str 1"},{"type":"Integer","value":2}]}}]}`, 269 result: Parameter{ 270 Type: MapType, 271 Value: []ParameterPair{ 272 { 273 Key: Parameter{Type: StringType, Value: "key1"}, 274 Value: Parameter{Type: ArrayType, Value: []Parameter{ 275 {Type: StringType, Value: "str 1"}, 276 {Type: IntegerType, Value: big.NewInt(2)}, 277 }}, 278 }, 279 }, 280 }, 281 }, 282 { 283 result: Parameter{ 284 Type: PublicKeyType, 285 Value: []byte{0x03, 0xb3, 0xbf, 0x15, 0x02, 0xfb, 0xdc, 0x05, 0x44, 0x9b, 0x50, 0x6a, 0xaf, 0x04, 0x57, 0x97, 0x24, 0x02, 0x4b, 0x06, 0x54, 0x2e, 0x49, 0x26, 0x2b, 0xfa, 0xa3, 0xf7, 0x0e, 0x20, 0x00, 0x40, 0xa9}, 286 }, 287 input: `{"type":"PublicKey","value":"03b3bf1502fbdc05449b506aaf04579724024b06542e49262bfaa3f70e200040a9"}`, 288 }, 289 { 290 input: `{"type":"InteropInterface","value":null}`, 291 result: Parameter{ 292 Type: InteropInterfaceType, 293 Value: nil, 294 }, 295 }, 296 { 297 input: `{"type":"InteropInterface","value":""}`, 298 result: Parameter{ 299 Type: InteropInterfaceType, 300 Value: nil, 301 }, 302 }, 303 { 304 input: `{"type":"InteropInterface","value":"Hundertwasser"}`, 305 result: Parameter{ 306 Type: InteropInterfaceType, 307 Value: nil, 308 }, 309 }, 310 } 311 312 var unmarshalJSONErrorCases = []string{ 313 `{"type": "ByteString","value":`, // incorrect JSON 314 `{"type": "ByteString","value":1}`, // incorrect Value 315 `{"type": "ByteString","value":"12^"}`, // incorrect ByteArray value 316 `{"type": "String","value":`, // incorrect JSON 317 `{"type": "String","value":1}`, // incorrect Value 318 `{"type": "Integer","value": "nn"}`, // incorrect Integer value 319 `{"type": "Integer","value": []}`, // incorrect Integer value 320 `{"type": "Integer","value":"` + 321 strings.Repeat("9", 100) + `"}`, // too big Integer 322 `{"type": "Array","value": 123}`, // incorrect Array value 323 `{"type": "Hash160","value": "0bcd"}`, // incorrect Uint160 value 324 `{"type": "Hash256","value": "0bcd"}`, // incorrect Uint256 value 325 `{"type": "Stringg","value": ""}`, // incorrect type 326 `{"type": {},"value": ""}`, // incorrect value 327 `{"type": "Boolean","value": qwerty}`, // incorrect Bool value 328 `{"type": "Boolean","value": ""}`, // incorrect Bool value 329 `{"type": "Map","value": ["key": {}]}`, // incorrect Map value 330 `{"type": "Map","value": ["key": {"type":"String", "value":"qwer"}, "value": {"type":"Boolean"}]}`, // incorrect Map Value value 331 `{"type": "Map","value": ["key": {"type":"String"}, "value": {"type":"Boolean", "value":true}]}`, // incorrect Map Key value 332 } 333 334 func TestParam_UnmarshalJSON(t *testing.T) { 335 var s Parameter 336 for _, tc := range unmarshalJSONTestCases { 337 assert.NoError(t, json.Unmarshal([]byte(tc.input), &s)) 338 assert.Equal(t, s, tc.result) 339 } 340 341 for _, input := range unmarshalJSONErrorCases { 342 assert.Error(t, json.Unmarshal([]byte(input), &s), input) 343 } 344 } 345 346 func TestParamType_String(t *testing.T) { 347 types := []ParamType{ 348 SignatureType, 349 BoolType, 350 IntegerType, 351 Hash160Type, 352 Hash256Type, 353 ByteArrayType, 354 PublicKeyType, 355 StringType, 356 ArrayType, 357 InteropInterfaceType, 358 MapType, 359 VoidType, 360 } 361 362 for _, exp := range types { 363 actual, err := ParseParamType(exp.String()) 364 assert.NoError(t, err) 365 assert.Equal(t, exp, actual) 366 } 367 368 actual, err := ParseParamType(UnknownType.String()) 369 assert.Error(t, err) 370 assert.Equal(t, UnknownType, actual) 371 } 372 373 func TestNewParameterFromString(t *testing.T) { 374 var inouts = []struct { 375 in string 376 out Parameter 377 err bool 378 }{{ 379 in: "qwerty", 380 out: Parameter{StringType, "qwerty"}, 381 }, { 382 in: "42", 383 out: Parameter{IntegerType, big.NewInt(42)}, 384 }, { 385 in: "Hello, 世界", 386 out: Parameter{StringType, "Hello, 世界"}, 387 }, { 388 in: `\4\2`, 389 out: Parameter{IntegerType, big.NewInt(42)}, 390 }, { 391 in: `\\4\2`, 392 out: Parameter{StringType, `\42`}, 393 }, { 394 in: `\\\4\2`, 395 out: Parameter{StringType, `\42`}, 396 }, { 397 in: "int:42", 398 out: Parameter{IntegerType, big.NewInt(42)}, 399 }, { 400 in: "true", 401 out: Parameter{BoolType, true}, 402 }, { 403 in: "string:true", 404 out: Parameter{StringType, "true"}, 405 }, { 406 in: "\xfe\xff", 407 err: true, 408 }, { 409 in: `string\:true`, 410 out: Parameter{StringType, "string:true"}, 411 }, { 412 in: "string:true:true", 413 out: Parameter{StringType, "true:true"}, 414 }, { 415 in: `string\\:true`, 416 err: true, 417 }, { 418 in: `qwerty:asdf`, 419 err: true, 420 }, { 421 in: `bool:asdf`, 422 err: true, 423 }, { 424 in: `InteropInterface:123`, 425 err: true, 426 }, { 427 in: `Map:[]`, 428 err: true, 429 }, { 430 in: "filebytes:./testdata/adjustValToType_filebytes_good.txt", 431 out: Parameter{Type: ByteArrayType, Value: []byte{0x30, 0x31, 0x30, 0x32, 0x30, 0x33, 0x65, 0x66}}, 432 }, { 433 in: "filebytes:./testdata/does_not_exists.txt", 434 err: true, 435 }} 436 for _, inout := range inouts { 437 out, err := NewParameterFromString(inout.in) 438 if inout.err { 439 assert.NotNil(t, err, "should error on '%s' input", inout.in) 440 } else { 441 assert.Nil(t, err, "shouldn't error on '%s' input", inout.in) 442 assert.Equal(t, inout.out, *out, "bad output for '%s' input", inout.in) 443 } 444 } 445 } 446 447 func hexToBase64(s string) string { 448 b, _ := hex.DecodeString(s) 449 return base64.StdEncoding.EncodeToString(b) 450 } 451 452 func TestExpandParameterToEmitableToStackitem(t *testing.T) { 453 pk, _ := keys.NewPrivateKey() 454 testCases := []struct { 455 In Parameter 456 Expected any 457 ExpectedStackitem stackitem.Item 458 }{ 459 { 460 In: Parameter{Type: BoolType, Value: true}, 461 Expected: true, 462 ExpectedStackitem: stackitem.NewBool(true), 463 }, 464 { 465 In: Parameter{Type: IntegerType, Value: big.NewInt(123)}, 466 Expected: big.NewInt(123), 467 ExpectedStackitem: stackitem.NewBigInteger(big.NewInt(123)), 468 }, 469 { 470 In: Parameter{Type: ByteArrayType, Value: []byte{1, 2, 3}}, 471 Expected: []byte{1, 2, 3}, 472 ExpectedStackitem: stackitem.NewByteArray([]byte{1, 2, 3}), 473 }, 474 { 475 In: Parameter{Type: StringType, Value: "writing's on the wall"}, 476 Expected: "writing's on the wall", 477 ExpectedStackitem: stackitem.NewByteArray([]byte("writing's on the wall")), 478 }, 479 { 480 In: Parameter{Type: Hash160Type, Value: util.Uint160{1, 2, 3}}, 481 Expected: util.Uint160{1, 2, 3}, 482 ExpectedStackitem: stackitem.NewByteArray(util.Uint160{1, 2, 3}.BytesBE()), 483 }, 484 { 485 In: Parameter{Type: Hash256Type, Value: util.Uint256{1, 2, 3}}, 486 Expected: util.Uint256{1, 2, 3}, 487 ExpectedStackitem: stackitem.NewByteArray(util.Uint256{1, 2, 3}.BytesBE()), 488 }, 489 { 490 In: Parameter{Type: PublicKeyType, Value: pk.PublicKey().Bytes()}, 491 Expected: pk.PublicKey().Bytes(), 492 ExpectedStackitem: stackitem.NewByteArray(pk.PublicKey().Bytes()), 493 }, 494 { 495 In: Parameter{Type: SignatureType, Value: []byte{1, 2, 3}}, 496 Expected: []byte{1, 2, 3}, 497 ExpectedStackitem: stackitem.NewByteArray([]byte{1, 2, 3}), 498 }, 499 { 500 In: Parameter{Type: AnyType}, 501 Expected: nil, 502 ExpectedStackitem: stackitem.Null{}, 503 }, 504 { 505 In: Parameter{Type: ArrayType, Value: []Parameter{ 506 { 507 Type: IntegerType, 508 Value: big.NewInt(123), 509 }, 510 { 511 Type: ByteArrayType, 512 Value: []byte{1, 2, 3}, 513 }, 514 { 515 Type: ArrayType, 516 Value: []Parameter{ 517 { 518 Type: BoolType, 519 Value: true, 520 }, 521 }, 522 }, 523 }}, 524 Expected: []any{big.NewInt(123), []byte{1, 2, 3}, []any{true}}, 525 ExpectedStackitem: stackitem.NewArray([]stackitem.Item{ 526 stackitem.NewBigInteger(big.NewInt(123)), 527 stackitem.NewByteArray([]byte{1, 2, 3}), 528 stackitem.NewArray([]stackitem.Item{ 529 stackitem.NewBool(true), 530 }), 531 }), 532 }, 533 } 534 bw := io.NewBufBinWriter() 535 for _, testCase := range testCases { 536 actual, err := ExpandParameterToEmitable(testCase.In) 537 require.NoError(t, err) 538 require.Equal(t, testCase.Expected, actual) 539 540 emit.Array(bw.BinWriter, actual) 541 require.NoError(t, bw.Err) 542 543 actualSI, err := testCase.In.ToStackItem() 544 require.NoError(t, err) 545 require.Equal(t, testCase.ExpectedStackitem, actualSI) 546 } 547 errCases := []Parameter{ 548 {Type: UnknownType}, 549 {Type: MapType}, 550 {Type: InteropInterfaceType}, 551 } 552 for _, errCase := range errCases { 553 _, err := ExpandParameterToEmitable(errCase) 554 require.Error(t, err) 555 } 556 } 557 558 // testConvertible implements Convertible interface and needed for NewParameterFromValue 559 // test. 560 type testConvertible struct { 561 i int 562 err string 563 } 564 565 var _ = Convertible(testConvertible{}) 566 567 func (c testConvertible) ToSCParameter() (Parameter, error) { 568 if c.err != "" { 569 return Parameter{}, errors.New(c.err) 570 } 571 return Parameter{ 572 Type: IntegerType, 573 Value: c.i, 574 }, nil 575 } 576 577 func TestParameterFromValue(t *testing.T) { 578 pk1, _ := keys.NewPrivateKey() 579 pk2, _ := keys.NewPrivateKey() 580 items := []struct { 581 value any 582 expType ParamType 583 expVal any 584 err string // expected error substring 585 }{ 586 { 587 value: []byte{1, 2, 3}, 588 expType: ByteArrayType, 589 expVal: []byte{1, 2, 3}, 590 }, 591 { 592 value: "hello world", 593 expType: StringType, 594 expVal: "hello world", 595 }, 596 { 597 value: false, 598 expType: BoolType, 599 expVal: false, 600 }, 601 { 602 value: true, 603 expType: BoolType, 604 expVal: true, 605 }, 606 { 607 value: big.NewInt(100), 608 expType: IntegerType, 609 expVal: big.NewInt(100), 610 }, 611 { 612 value: byte(100), 613 expType: IntegerType, 614 expVal: big.NewInt(100), 615 }, 616 { 617 value: int8(100), 618 expType: IntegerType, 619 expVal: big.NewInt(100), 620 }, 621 { 622 value: uint8(100), 623 expType: IntegerType, 624 expVal: big.NewInt(100), 625 }, 626 { 627 value: int16(100), 628 expType: IntegerType, 629 expVal: big.NewInt(100), 630 }, 631 { 632 value: uint16(100), 633 expType: IntegerType, 634 expVal: big.NewInt(100), 635 }, 636 { 637 value: int32(100), 638 expType: IntegerType, 639 expVal: big.NewInt(100), 640 }, 641 { 642 value: uint32(100), 643 expType: IntegerType, 644 expVal: big.NewInt(100), 645 }, 646 { 647 value: 100, 648 expType: IntegerType, 649 expVal: big.NewInt(100), 650 }, 651 { 652 value: uint(100), 653 expType: IntegerType, 654 expVal: big.NewInt(100), 655 }, 656 { 657 value: int64(100), 658 expType: IntegerType, 659 expVal: big.NewInt(100), 660 }, 661 { 662 value: uint64(100), 663 expType: IntegerType, 664 expVal: big.NewInt(100), 665 }, 666 { 667 value: Parameter{ByteArrayType, []byte{1, 2, 3}}, 668 expType: ByteArrayType, 669 expVal: []byte{1, 2, 3}, 670 }, 671 { 672 value: &Parameter{ByteArrayType, []byte{1, 2, 3}}, 673 expType: ByteArrayType, 674 expVal: []byte{1, 2, 3}, 675 }, 676 { 677 value: util.Uint160{1, 2, 3}, 678 expType: Hash160Type, 679 expVal: util.Uint160{1, 2, 3}, 680 }, 681 { 682 value: util.Uint256{3, 2, 1}, 683 expType: Hash256Type, 684 expVal: util.Uint256{3, 2, 1}, 685 }, 686 { 687 value: (*util.Uint160)(nil), 688 expType: AnyType, 689 }, 690 { 691 value: &util.Uint160{1, 2, 3}, 692 expType: Hash160Type, 693 expVal: util.Uint160{1, 2, 3}, 694 }, 695 { 696 value: (*util.Uint256)(nil), 697 expType: AnyType, 698 }, 699 { 700 value: &util.Uint256{3, 2, 1}, 701 expType: Hash256Type, 702 expVal: util.Uint256{3, 2, 1}, 703 }, 704 { 705 value: pk1.PublicKey(), 706 expType: PublicKeyType, 707 expVal: pk1.PublicKey().Bytes(), 708 }, 709 { 710 value: *pk2.PublicKey(), 711 expType: PublicKeyType, 712 expVal: pk2.PublicKey().Bytes(), 713 }, 714 { 715 value: nil, 716 expType: AnyType, 717 expVal: nil, 718 }, 719 { 720 value: [][]byte{{1, 2, 3}, {3, 2, 1}}, 721 expType: ArrayType, 722 expVal: []Parameter{{ByteArrayType, []byte{1, 2, 3}}, {ByteArrayType, []byte{3, 2, 1}}}, 723 }, 724 { 725 value: []Parameter{{ByteArrayType, []byte{1, 2, 3}}, {ByteArrayType, []byte{3, 2, 1}}}, 726 expType: ArrayType, 727 expVal: []Parameter{{ByteArrayType, []byte{1, 2, 3}}, {ByteArrayType, []byte{3, 2, 1}}}, 728 }, 729 { 730 value: []*keys.PublicKey{pk1.PublicKey(), pk2.PublicKey()}, 731 expType: ArrayType, 732 expVal: []Parameter{{ 733 Type: PublicKeyType, 734 Value: pk1.PublicKey().Bytes(), 735 }, { 736 Type: PublicKeyType, 737 Value: pk2.PublicKey().Bytes(), 738 }}, 739 }, 740 { 741 value: keys.PublicKeys{pk1.PublicKey(), pk2.PublicKey()}, 742 expType: ArrayType, 743 expVal: []Parameter{{ 744 Type: PublicKeyType, 745 Value: pk1.PublicKey().Bytes(), 746 }, { 747 Type: PublicKeyType, 748 Value: pk2.PublicKey().Bytes(), 749 }}, 750 }, 751 { 752 value: []any{-42, "random", []byte{1, 2, 3}}, 753 expType: ArrayType, 754 expVal: []Parameter{{ 755 Type: IntegerType, 756 Value: big.NewInt(-42), 757 }, { 758 Type: StringType, 759 Value: "random", 760 }, { 761 Type: ByteArrayType, 762 Value: []byte{1, 2, 3}, 763 }}, 764 }, 765 { 766 value: testConvertible{i: 123}, 767 expType: IntegerType, 768 expVal: 123, 769 }, 770 { 771 value: []any{1, testConvertible{i: 123}}, 772 expType: ArrayType, 773 expVal: []Parameter{ 774 { 775 Type: IntegerType, 776 Value: big.NewInt(1), 777 }, 778 { 779 Type: IntegerType, 780 Value: 123, 781 }, 782 }, 783 }, 784 { 785 value: testConvertible{err: "invalid i value"}, 786 err: "invalid i value", 787 }, 788 { 789 value: make(map[string]int), 790 err: "unsupported parameter map[string]int", 791 }, 792 { 793 value: []any{1, 2, make(map[string]int)}, 794 err: "unsupported parameter map[string]int", 795 }, 796 } 797 798 for _, item := range items { 799 t.Run(item.expType.String()+" to stack parameter", func(t *testing.T) { 800 res, err := NewParameterFromValue(item.value) 801 if item.err != "" { 802 require.Error(t, err) 803 require.Contains(t, err.Error(), item.err) 804 } else { 805 require.NoError(t, err) 806 require.Equal(t, item.expType, res.Type) 807 require.Equal(t, item.expVal, res.Value) 808 } 809 }) 810 } 811 } 812 813 func TestParametersFromValues(t *testing.T) { 814 res, err := NewParametersFromValues(42, "some", []byte{3, 2, 1}) 815 require.NoError(t, err) 816 require.Equal(t, []Parameter{{ 817 Type: IntegerType, 818 Value: big.NewInt(42), 819 }, { 820 Type: StringType, 821 Value: "some", 822 }, { 823 Type: ByteArrayType, 824 Value: []byte{3, 2, 1}, 825 }}, res) 826 _, err = NewParametersFromValues(42, make(map[int]int), []byte{3, 2, 1}) 827 require.Error(t, err) 828 }