github.com/MetalBlockchain/metalgo@v1.11.9/vms/nftfx/fx_test.go (about) 1 // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. 2 // See the file LICENSE for licensing terms. 3 4 package nftfx 5 6 import ( 7 "testing" 8 "time" 9 10 "github.com/stretchr/testify/require" 11 12 "github.com/MetalBlockchain/metalgo/codec/linearcodec" 13 "github.com/MetalBlockchain/metalgo/ids" 14 "github.com/MetalBlockchain/metalgo/utils/crypto/secp256k1" 15 "github.com/MetalBlockchain/metalgo/utils/hashing" 16 "github.com/MetalBlockchain/metalgo/utils/logging" 17 "github.com/MetalBlockchain/metalgo/vms/secp256k1fx" 18 ) 19 20 var ( 21 txBytes = []byte{0, 1, 2, 3, 4, 5} 22 sigBytes = [secp256k1.SignatureLen]byte{ 23 0x0e, 0x33, 0x4e, 0xbc, 0x67, 0xa7, 0x3f, 0xe8, 24 0x24, 0x33, 0xac, 0xa3, 0x47, 0x88, 0xa6, 0x3d, 25 0x58, 0xe5, 0x8e, 0xf0, 0x3a, 0xd5, 0x84, 0xf1, 26 0xbc, 0xa3, 0xb2, 0xd2, 0x5d, 0x51, 0xd6, 0x9b, 27 0x0f, 0x28, 0x5d, 0xcd, 0x3f, 0x71, 0x17, 0x0a, 28 0xf9, 0xbf, 0x2d, 0xb1, 0x10, 0x26, 0x5c, 0xe9, 29 0xdc, 0xc3, 0x9d, 0x7a, 0x01, 0x50, 0x9d, 0xe8, 30 0x35, 0xbd, 0xcb, 0x29, 0x3a, 0xd1, 0x49, 0x32, 31 0x00, 32 } 33 addr = [hashing.AddrLen]byte{ 34 0x01, 0x5c, 0xce, 0x6c, 0x55, 0xd6, 0xb5, 0x09, 35 0x84, 0x5c, 0x8c, 0x4e, 0x30, 0xbe, 0xd9, 0x8d, 36 0x39, 0x1a, 0xe7, 0xf0, 37 } 38 ) 39 40 func TestFxInitialize(t *testing.T) { 41 vm := secp256k1fx.TestVM{ 42 Codec: linearcodec.NewDefault(), 43 Log: logging.NoLog{}, 44 } 45 fx := Fx{} 46 require.NoError(t, fx.Initialize(&vm)) 47 } 48 49 func TestFxInitializeInvalid(t *testing.T) { 50 fx := Fx{} 51 err := fx.Initialize(nil) 52 require.ErrorIs(t, err, secp256k1fx.ErrWrongVMType) 53 } 54 55 func TestFxVerifyMintOperation(t *testing.T) { 56 require := require.New(t) 57 58 vm := secp256k1fx.TestVM{ 59 Codec: linearcodec.NewDefault(), 60 Log: logging.NoLog{}, 61 } 62 date := time.Date(2019, time.January, 19, 16, 25, 17, 3, time.UTC) 63 vm.Clk.Set(date) 64 65 fx := Fx{} 66 require.NoError(fx.Initialize(&vm)) 67 tx := &secp256k1fx.TestTx{ 68 UnsignedBytes: txBytes, 69 } 70 cred := &Credential{Credential: secp256k1fx.Credential{ 71 Sigs: [][secp256k1.SignatureLen]byte{ 72 sigBytes, 73 }, 74 }} 75 utxo := &MintOutput{OutputOwners: secp256k1fx.OutputOwners{ 76 Threshold: 1, 77 Addrs: []ids.ShortID{ 78 addr, 79 }, 80 }} 81 op := &MintOperation{ 82 MintInput: secp256k1fx.Input{ 83 SigIndices: []uint32{0}, 84 }, 85 } 86 87 utxos := []interface{}{utxo} 88 require.NoError(fx.VerifyOperation(tx, op, cred, utxos)) 89 } 90 91 func TestFxVerifyMintOperationWrongTx(t *testing.T) { 92 require := require.New(t) 93 94 vm := secp256k1fx.TestVM{ 95 Codec: linearcodec.NewDefault(), 96 Log: logging.NoLog{}, 97 } 98 date := time.Date(2019, time.January, 19, 16, 25, 17, 3, time.UTC) 99 vm.Clk.Set(date) 100 101 fx := Fx{} 102 require.NoError(fx.Initialize(&vm)) 103 cred := &Credential{Credential: secp256k1fx.Credential{ 104 Sigs: [][secp256k1.SignatureLen]byte{ 105 sigBytes, 106 }, 107 }} 108 utxo := &MintOutput{OutputOwners: secp256k1fx.OutputOwners{ 109 Threshold: 1, 110 Addrs: []ids.ShortID{ 111 addr, 112 }, 113 }} 114 op := &MintOperation{ 115 MintInput: secp256k1fx.Input{ 116 SigIndices: []uint32{0}, 117 }, 118 } 119 120 utxos := []interface{}{utxo} 121 err := fx.VerifyOperation(nil, op, cred, utxos) 122 require.ErrorIs(err, errWrongTxType) 123 } 124 125 func TestFxVerifyMintOperationWrongNumberUTXOs(t *testing.T) { 126 require := require.New(t) 127 128 vm := secp256k1fx.TestVM{ 129 Codec: linearcodec.NewDefault(), 130 Log: logging.NoLog{}, 131 } 132 date := time.Date(2019, time.January, 19, 16, 25, 17, 3, time.UTC) 133 vm.Clk.Set(date) 134 135 fx := Fx{} 136 require.NoError(fx.Initialize(&vm)) 137 tx := &secp256k1fx.TestTx{ 138 UnsignedBytes: txBytes, 139 } 140 cred := &Credential{Credential: secp256k1fx.Credential{ 141 Sigs: [][secp256k1.SignatureLen]byte{ 142 sigBytes, 143 }, 144 }} 145 op := &MintOperation{ 146 MintInput: secp256k1fx.Input{ 147 SigIndices: []uint32{0}, 148 }, 149 } 150 151 utxos := []interface{}{} 152 err := fx.VerifyOperation(tx, op, cred, utxos) 153 require.ErrorIs(err, errWrongNumberOfUTXOs) 154 } 155 156 func TestFxVerifyMintOperationWrongCredential(t *testing.T) { 157 require := require.New(t) 158 159 vm := secp256k1fx.TestVM{ 160 Codec: linearcodec.NewDefault(), 161 Log: logging.NoLog{}, 162 } 163 date := time.Date(2019, time.January, 19, 16, 25, 17, 3, time.UTC) 164 vm.Clk.Set(date) 165 166 fx := Fx{} 167 require.NoError(fx.Initialize(&vm)) 168 tx := &secp256k1fx.TestTx{ 169 UnsignedBytes: txBytes, 170 } 171 utxo := &MintOutput{OutputOwners: secp256k1fx.OutputOwners{ 172 Threshold: 1, 173 Addrs: []ids.ShortID{ 174 addr, 175 }, 176 }} 177 op := &MintOperation{ 178 MintInput: secp256k1fx.Input{ 179 SigIndices: []uint32{0}, 180 }, 181 } 182 183 utxos := []interface{}{utxo} 184 err := fx.VerifyOperation(tx, op, nil, utxos) 185 require.ErrorIs(err, errWrongCredentialType) 186 } 187 188 func TestFxVerifyMintOperationInvalidUTXO(t *testing.T) { 189 require := require.New(t) 190 191 vm := secp256k1fx.TestVM{ 192 Codec: linearcodec.NewDefault(), 193 Log: logging.NoLog{}, 194 } 195 date := time.Date(2019, time.January, 19, 16, 25, 17, 3, time.UTC) 196 vm.Clk.Set(date) 197 198 fx := Fx{} 199 require.NoError(fx.Initialize(&vm)) 200 tx := &secp256k1fx.TestTx{ 201 UnsignedBytes: txBytes, 202 } 203 cred := &Credential{Credential: secp256k1fx.Credential{ 204 Sigs: [][secp256k1.SignatureLen]byte{ 205 sigBytes, 206 }, 207 }} 208 op := &MintOperation{ 209 MintInput: secp256k1fx.Input{ 210 SigIndices: []uint32{0}, 211 }, 212 } 213 214 utxos := []interface{}{nil} 215 err := fx.VerifyOperation(tx, op, cred, utxos) 216 require.ErrorIs(err, errWrongUTXOType) 217 } 218 219 func TestFxVerifyMintOperationFailingVerification(t *testing.T) { 220 require := require.New(t) 221 222 vm := secp256k1fx.TestVM{ 223 Codec: linearcodec.NewDefault(), 224 Log: logging.NoLog{}, 225 } 226 date := time.Date(2019, time.January, 19, 16, 25, 17, 3, time.UTC) 227 vm.Clk.Set(date) 228 229 fx := Fx{} 230 require.NoError(fx.Initialize(&vm)) 231 tx := &secp256k1fx.TestTx{ 232 UnsignedBytes: txBytes, 233 } 234 cred := &Credential{Credential: secp256k1fx.Credential{ 235 Sigs: [][secp256k1.SignatureLen]byte{ 236 sigBytes, 237 }, 238 }} 239 utxo := &MintOutput{OutputOwners: secp256k1fx.OutputOwners{ 240 Threshold: 1, 241 Addrs: []ids.ShortID{ 242 addr, 243 ids.ShortEmpty, 244 }, 245 }} 246 op := &MintOperation{ 247 MintInput: secp256k1fx.Input{ 248 SigIndices: []uint32{0}, 249 }, 250 } 251 252 utxos := []interface{}{utxo} 253 err := fx.VerifyOperation(tx, op, cred, utxos) 254 require.ErrorIs(err, secp256k1fx.ErrAddrsNotSortedUnique) 255 } 256 257 func TestFxVerifyMintOperationInvalidGroupID(t *testing.T) { 258 require := require.New(t) 259 260 vm := secp256k1fx.TestVM{ 261 Codec: linearcodec.NewDefault(), 262 Log: logging.NoLog{}, 263 } 264 date := time.Date(2019, time.January, 19, 16, 25, 17, 3, time.UTC) 265 vm.Clk.Set(date) 266 267 fx := Fx{} 268 require.NoError(fx.Initialize(&vm)) 269 tx := &secp256k1fx.TestTx{ 270 UnsignedBytes: txBytes, 271 } 272 cred := &Credential{Credential: secp256k1fx.Credential{ 273 Sigs: [][secp256k1.SignatureLen]byte{ 274 sigBytes, 275 }, 276 }} 277 utxo := &MintOutput{OutputOwners: secp256k1fx.OutputOwners{ 278 Threshold: 1, 279 Addrs: []ids.ShortID{ 280 addr, 281 }, 282 }} 283 op := &MintOperation{ 284 MintInput: secp256k1fx.Input{ 285 SigIndices: []uint32{0}, 286 }, 287 GroupID: 1, 288 } 289 290 utxos := []interface{}{utxo} 291 err := fx.VerifyOperation(tx, op, cred, utxos) 292 require.ErrorIs(err, errWrongUniqueID) 293 } 294 295 func TestFxVerifyTransferOperation(t *testing.T) { 296 require := require.New(t) 297 298 vm := secp256k1fx.TestVM{ 299 Codec: linearcodec.NewDefault(), 300 Log: logging.NoLog{}, 301 } 302 date := time.Date(2019, time.January, 19, 16, 25, 17, 3, time.UTC) 303 vm.Clk.Set(date) 304 305 fx := Fx{} 306 require.NoError(fx.Initialize(&vm)) 307 tx := &secp256k1fx.TestTx{ 308 UnsignedBytes: txBytes, 309 } 310 cred := &Credential{Credential: secp256k1fx.Credential{ 311 Sigs: [][secp256k1.SignatureLen]byte{ 312 sigBytes, 313 }, 314 }} 315 utxo := &TransferOutput{ 316 GroupID: 1, 317 Payload: []byte{2}, 318 OutputOwners: secp256k1fx.OutputOwners{ 319 Threshold: 1, 320 Addrs: []ids.ShortID{ 321 addr, 322 }, 323 }, 324 } 325 op := &TransferOperation{ 326 Input: secp256k1fx.Input{ 327 SigIndices: []uint32{0}, 328 }, 329 Output: TransferOutput{ 330 GroupID: 1, 331 Payload: []byte{2}, 332 OutputOwners: secp256k1fx.OutputOwners{ 333 Threshold: 1, 334 Addrs: []ids.ShortID{ 335 ids.ShortEmpty, 336 }, 337 }, 338 }, 339 } 340 341 utxos := []interface{}{utxo} 342 require.NoError(fx.VerifyOperation(tx, op, cred, utxos)) 343 } 344 345 func TestFxVerifyTransferOperationWrongUTXO(t *testing.T) { 346 require := require.New(t) 347 348 vm := secp256k1fx.TestVM{ 349 Codec: linearcodec.NewDefault(), 350 Log: logging.NoLog{}, 351 } 352 date := time.Date(2019, time.January, 19, 16, 25, 17, 3, time.UTC) 353 vm.Clk.Set(date) 354 355 fx := Fx{} 356 require.NoError(fx.Initialize(&vm)) 357 tx := &secp256k1fx.TestTx{ 358 UnsignedBytes: txBytes, 359 } 360 cred := &Credential{Credential: secp256k1fx.Credential{ 361 Sigs: [][secp256k1.SignatureLen]byte{ 362 sigBytes, 363 }, 364 }} 365 op := &TransferOperation{ 366 Input: secp256k1fx.Input{ 367 SigIndices: []uint32{0}, 368 }, 369 Output: TransferOutput{ 370 GroupID: 1, 371 Payload: []byte{2}, 372 OutputOwners: secp256k1fx.OutputOwners{ 373 Threshold: 1, 374 Addrs: []ids.ShortID{ 375 ids.ShortEmpty, 376 }, 377 }, 378 }, 379 } 380 381 utxos := []interface{}{nil} 382 err := fx.VerifyOperation(tx, op, cred, utxos) 383 require.ErrorIs(err, errWrongUTXOType) 384 } 385 386 func TestFxVerifyTransferOperationFailedVerify(t *testing.T) { 387 require := require.New(t) 388 389 vm := secp256k1fx.TestVM{ 390 Codec: linearcodec.NewDefault(), 391 Log: logging.NoLog{}, 392 } 393 date := time.Date(2019, time.January, 19, 16, 25, 17, 3, time.UTC) 394 vm.Clk.Set(date) 395 396 fx := Fx{} 397 require.NoError(fx.Initialize(&vm)) 398 tx := &secp256k1fx.TestTx{ 399 UnsignedBytes: txBytes, 400 } 401 cred := &Credential{Credential: secp256k1fx.Credential{ 402 Sigs: [][secp256k1.SignatureLen]byte{ 403 sigBytes, 404 }, 405 }} 406 utxo := &TransferOutput{ 407 GroupID: 1, 408 Payload: []byte{2}, 409 OutputOwners: secp256k1fx.OutputOwners{ 410 Threshold: 1, 411 }, 412 } 413 op := &TransferOperation{ 414 Input: secp256k1fx.Input{ 415 SigIndices: []uint32{0}, 416 }, 417 Output: TransferOutput{ 418 GroupID: 1, 419 Payload: []byte{2}, 420 OutputOwners: secp256k1fx.OutputOwners{ 421 Threshold: 1, 422 Addrs: []ids.ShortID{ 423 ids.ShortEmpty, 424 }, 425 }, 426 }, 427 } 428 429 utxos := []interface{}{utxo} 430 err := fx.VerifyOperation(tx, op, cred, utxos) 431 require.ErrorIs(err, secp256k1fx.ErrOutputUnspendable) 432 } 433 434 func TestFxVerifyTransferOperationWrongGroupID(t *testing.T) { 435 require := require.New(t) 436 437 vm := secp256k1fx.TestVM{ 438 Codec: linearcodec.NewDefault(), 439 Log: logging.NoLog{}, 440 } 441 date := time.Date(2019, time.January, 19, 16, 25, 17, 3, time.UTC) 442 vm.Clk.Set(date) 443 444 fx := Fx{} 445 require.NoError(fx.Initialize(&vm)) 446 tx := &secp256k1fx.TestTx{ 447 UnsignedBytes: txBytes, 448 } 449 cred := &Credential{Credential: secp256k1fx.Credential{ 450 Sigs: [][secp256k1.SignatureLen]byte{ 451 sigBytes, 452 }, 453 }} 454 utxo := &TransferOutput{ 455 GroupID: 1, 456 Payload: []byte{2}, 457 OutputOwners: secp256k1fx.OutputOwners{ 458 Threshold: 1, 459 Addrs: []ids.ShortID{ 460 addr, 461 }, 462 }, 463 } 464 op := &TransferOperation{ 465 Input: secp256k1fx.Input{ 466 SigIndices: []uint32{0}, 467 }, 468 Output: TransferOutput{ 469 GroupID: 2, 470 Payload: []byte{2}, 471 OutputOwners: secp256k1fx.OutputOwners{ 472 Threshold: 1, 473 Addrs: []ids.ShortID{ 474 ids.ShortEmpty, 475 }, 476 }, 477 }, 478 } 479 480 utxos := []interface{}{utxo} 481 err := fx.VerifyOperation(tx, op, cred, utxos) 482 require.ErrorIs(err, errWrongUniqueID) 483 } 484 485 func TestFxVerifyTransferOperationWrongBytes(t *testing.T) { 486 require := require.New(t) 487 488 vm := secp256k1fx.TestVM{ 489 Codec: linearcodec.NewDefault(), 490 Log: logging.NoLog{}, 491 } 492 date := time.Date(2019, time.January, 19, 16, 25, 17, 3, time.UTC) 493 vm.Clk.Set(date) 494 495 fx := Fx{} 496 require.NoError(fx.Initialize(&vm)) 497 tx := &secp256k1fx.TestTx{ 498 UnsignedBytes: txBytes, 499 } 500 cred := &Credential{Credential: secp256k1fx.Credential{ 501 Sigs: [][secp256k1.SignatureLen]byte{ 502 sigBytes, 503 }, 504 }} 505 utxo := &TransferOutput{ 506 GroupID: 1, 507 Payload: []byte{2}, 508 OutputOwners: secp256k1fx.OutputOwners{ 509 Threshold: 1, 510 Addrs: []ids.ShortID{ 511 addr, 512 }, 513 }, 514 } 515 op := &TransferOperation{ 516 Input: secp256k1fx.Input{ 517 SigIndices: []uint32{0}, 518 }, 519 Output: TransferOutput{ 520 GroupID: 1, 521 Payload: []byte{3}, 522 OutputOwners: secp256k1fx.OutputOwners{ 523 Threshold: 1, 524 Addrs: []ids.ShortID{ 525 ids.ShortEmpty, 526 }, 527 }, 528 }, 529 } 530 531 utxos := []interface{}{utxo} 532 err := fx.VerifyOperation(tx, op, cred, utxos) 533 require.ErrorIs(err, errWrongBytes) 534 } 535 536 func TestFxVerifyTransferOperationTooSoon(t *testing.T) { 537 require := require.New(t) 538 539 vm := secp256k1fx.TestVM{ 540 Codec: linearcodec.NewDefault(), 541 Log: logging.NoLog{}, 542 } 543 date := time.Date(2019, time.January, 19, 16, 25, 17, 3, time.UTC) 544 vm.Clk.Set(date) 545 546 fx := Fx{} 547 require.NoError(fx.Initialize(&vm)) 548 tx := &secp256k1fx.TestTx{ 549 UnsignedBytes: txBytes, 550 } 551 cred := &Credential{Credential: secp256k1fx.Credential{ 552 Sigs: [][secp256k1.SignatureLen]byte{ 553 sigBytes, 554 }, 555 }} 556 utxo := &TransferOutput{ 557 GroupID: 1, 558 Payload: []byte{2}, 559 OutputOwners: secp256k1fx.OutputOwners{ 560 Locktime: vm.Clk.Unix() + 1, 561 Threshold: 1, 562 Addrs: []ids.ShortID{ 563 addr, 564 }, 565 }, 566 } 567 op := &TransferOperation{ 568 Input: secp256k1fx.Input{ 569 SigIndices: []uint32{0}, 570 }, 571 Output: TransferOutput{ 572 GroupID: 1, 573 Payload: []byte{2}, 574 OutputOwners: secp256k1fx.OutputOwners{ 575 Threshold: 1, 576 Addrs: []ids.ShortID{ 577 ids.ShortEmpty, 578 }, 579 }, 580 }, 581 } 582 583 utxos := []interface{}{utxo} 584 err := fx.VerifyOperation(tx, op, cred, utxos) 585 require.ErrorIs(err, secp256k1fx.ErrTimelocked) 586 } 587 588 func TestFxVerifyOperationUnknownOperation(t *testing.T) { 589 require := require.New(t) 590 591 vm := secp256k1fx.TestVM{ 592 Codec: linearcodec.NewDefault(), 593 Log: logging.NoLog{}, 594 } 595 date := time.Date(2019, time.January, 19, 16, 25, 17, 3, time.UTC) 596 vm.Clk.Set(date) 597 598 fx := Fx{} 599 require.NoError(fx.Initialize(&vm)) 600 tx := &secp256k1fx.TestTx{ 601 UnsignedBytes: txBytes, 602 } 603 cred := &Credential{Credential: secp256k1fx.Credential{ 604 Sigs: [][secp256k1.SignatureLen]byte{ 605 sigBytes, 606 }, 607 }} 608 utxo := &TransferOutput{ 609 GroupID: 1, 610 Payload: []byte{2}, 611 OutputOwners: secp256k1fx.OutputOwners{ 612 Threshold: 1, 613 Addrs: []ids.ShortID{ 614 addr, 615 }, 616 }, 617 } 618 619 utxos := []interface{}{utxo} 620 err := fx.VerifyOperation(tx, nil, cred, utxos) 621 require.ErrorIs(err, errWrongOperationType) 622 } 623 624 func TestFxVerifyTransfer(t *testing.T) { 625 require := require.New(t) 626 627 vm := secp256k1fx.TestVM{ 628 Codec: linearcodec.NewDefault(), 629 Log: logging.NoLog{}, 630 } 631 date := time.Date(2019, time.January, 19, 16, 25, 17, 3, time.UTC) 632 vm.Clk.Set(date) 633 634 fx := Fx{} 635 require.NoError(fx.Initialize(&vm)) 636 err := fx.VerifyTransfer(nil, nil, nil, nil) 637 require.ErrorIs(err, errCantTransfer) 638 }