github.com/MetalBlockchain/metalgo@v1.11.9/wallet/chain/p/builder_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 p 5 6 import ( 7 "testing" 8 "time" 9 10 "github.com/stretchr/testify/require" 11 12 "github.com/MetalBlockchain/metalgo/ids" 13 "github.com/MetalBlockchain/metalgo/utils/constants" 14 "github.com/MetalBlockchain/metalgo/utils/crypto/bls" 15 "github.com/MetalBlockchain/metalgo/utils/crypto/secp256k1" 16 "github.com/MetalBlockchain/metalgo/utils/set" 17 "github.com/MetalBlockchain/metalgo/utils/units" 18 "github.com/MetalBlockchain/metalgo/vms/components/avax" 19 "github.com/MetalBlockchain/metalgo/vms/platformvm/reward" 20 "github.com/MetalBlockchain/metalgo/vms/platformvm/signer" 21 "github.com/MetalBlockchain/metalgo/vms/platformvm/stakeable" 22 "github.com/MetalBlockchain/metalgo/vms/platformvm/txs" 23 "github.com/MetalBlockchain/metalgo/vms/secp256k1fx" 24 "github.com/MetalBlockchain/metalgo/wallet/chain/p/builder" 25 "github.com/MetalBlockchain/metalgo/wallet/subnet/primary/common" 26 ) 27 28 var ( 29 testKeys = secp256k1.TestKeys() 30 31 // We hard-code [avaxAssetID] and [subnetAssetID] to make 32 // ordering of UTXOs generated by [testUTXOsList] is reproducible 33 avaxAssetID = ids.Empty.Prefix(1789) 34 subnetAssetID = ids.Empty.Prefix(2024) 35 36 testContext = &builder.Context{ 37 NetworkID: constants.UnitTestID, 38 AVAXAssetID: avaxAssetID, 39 BaseTxFee: units.MicroAvax, 40 CreateSubnetTxFee: 19 * units.MicroAvax, 41 TransformSubnetTxFee: 789 * units.MicroAvax, 42 CreateBlockchainTxFee: 1234 * units.MicroAvax, 43 AddPrimaryNetworkValidatorFee: 19 * units.MilliAvax, 44 AddPrimaryNetworkDelegatorFee: 765 * units.MilliAvax, 45 AddSubnetValidatorFee: 1010 * units.MilliAvax, 46 AddSubnetDelegatorFee: 9 * units.Avax, 47 } 48 ) 49 50 // These tests create a tx, then verify that utxos included in the tx are 51 // exactly necessary to pay fees for it. 52 53 func TestBaseTx(t *testing.T) { 54 var ( 55 require = require.New(t) 56 57 // backend 58 utxosKey = testKeys[1] 59 utxos = makeTestUTXOs(utxosKey) 60 chainUTXOs = common.NewDeterministicChainUTXOs(require, map[ids.ID][]*avax.UTXO{ 61 constants.PlatformChainID: utxos, 62 }) 63 backend = NewBackend(testContext, chainUTXOs, nil) 64 65 // builder 66 utxoAddr = utxosKey.Address() 67 builder = builder.New(set.Of(utxoAddr), testContext, backend) 68 69 // data to build the transaction 70 outputsToMove = []*avax.TransferableOutput{{ 71 Asset: avax.Asset{ID: avaxAssetID}, 72 Out: &secp256k1fx.TransferOutput{ 73 Amt: 7 * units.Avax, 74 OutputOwners: secp256k1fx.OutputOwners{ 75 Threshold: 1, 76 Addrs: []ids.ShortID{utxoAddr}, 77 }, 78 }, 79 }} 80 ) 81 82 utx, err := builder.NewBaseTx(outputsToMove) 83 require.NoError(err) 84 85 // check UTXOs selection and fee financing 86 ins := utx.Ins 87 outs := utx.Outs 88 require.Len(ins, 2) 89 require.Len(outs, 2) 90 91 expectedConsumed := testContext.BaseTxFee + outputsToMove[0].Out.Amount() 92 consumed := ins[0].In.Amount() + ins[1].In.Amount() - outs[0].Out.Amount() 93 require.Equal(expectedConsumed, consumed) 94 require.Equal(outputsToMove[0], outs[1]) 95 } 96 97 func TestAddSubnetValidatorTx(t *testing.T) { 98 var ( 99 require = require.New(t) 100 101 // backend 102 utxosKey = testKeys[1] 103 utxos = makeTestUTXOs(utxosKey) 104 chainUTXOs = common.NewDeterministicChainUTXOs(require, map[ids.ID][]*avax.UTXO{ 105 constants.PlatformChainID: utxos, 106 }) 107 108 subnetID = ids.GenerateTestID() 109 subnetAuthKey = testKeys[0] 110 subnetAuthAddr = subnetAuthKey.Address() 111 subnetOwner = &secp256k1fx.OutputOwners{ 112 Threshold: 1, 113 Addrs: []ids.ShortID{subnetAuthAddr}, 114 } 115 subnets = map[ids.ID]*txs.Tx{ 116 subnetID: { 117 Unsigned: &txs.CreateSubnetTx{ 118 Owner: subnetOwner, 119 }, 120 }, 121 } 122 123 backend = NewBackend(testContext, chainUTXOs, subnets) 124 125 // builder 126 utxoAddr = utxosKey.Address() 127 builder = builder.New(set.Of(utxoAddr, subnetAuthAddr), testContext, backend) 128 129 // data to build the transaction 130 subnetValidator = &txs.SubnetValidator{ 131 Validator: txs.Validator{ 132 NodeID: ids.GenerateTestNodeID(), 133 End: uint64(time.Now().Add(time.Hour).Unix()), 134 }, 135 Subnet: subnetID, 136 } 137 ) 138 139 // build the transaction 140 utx, err := builder.NewAddSubnetValidatorTx(subnetValidator) 141 require.NoError(err) 142 143 // check UTXOs selection and fee financing 144 ins := utx.Ins 145 outs := utx.Outs 146 require.Len(ins, 2) 147 require.Len(outs, 1) 148 149 expectedConsumed := testContext.AddSubnetValidatorFee 150 consumed := ins[0].In.Amount() + ins[1].In.Amount() - outs[0].Out.Amount() 151 require.Equal(expectedConsumed, consumed) 152 } 153 154 func TestRemoveSubnetValidatorTx(t *testing.T) { 155 var ( 156 require = require.New(t) 157 158 // backend 159 utxosKey = testKeys[1] 160 utxos = makeTestUTXOs(utxosKey) 161 chainUTXOs = common.NewDeterministicChainUTXOs(require, map[ids.ID][]*avax.UTXO{ 162 constants.PlatformChainID: utxos, 163 }) 164 165 subnetID = ids.GenerateTestID() 166 subnetAuthKey = testKeys[0] 167 subnetAuthAddr = subnetAuthKey.Address() 168 subnetOwner = &secp256k1fx.OutputOwners{ 169 Threshold: 1, 170 Addrs: []ids.ShortID{subnetAuthAddr}, 171 } 172 subnets = map[ids.ID]*txs.Tx{ 173 subnetID: { 174 Unsigned: &txs.CreateSubnetTx{ 175 Owner: subnetOwner, 176 }, 177 }, 178 } 179 180 backend = NewBackend(testContext, chainUTXOs, subnets) 181 182 // builder 183 utxoAddr = utxosKey.Address() 184 builder = builder.New(set.Of(utxoAddr, subnetAuthAddr), testContext, backend) 185 ) 186 187 // build the transaction 188 utx, err := builder.NewRemoveSubnetValidatorTx( 189 ids.GenerateTestNodeID(), 190 subnetID, 191 ) 192 require.NoError(err) 193 194 // check UTXOs selection and fee financing 195 ins := utx.Ins 196 outs := utx.Outs 197 require.Len(ins, 1) 198 require.Len(outs, 1) 199 200 expectedConsumed := testContext.BaseTxFee 201 consumed := ins[0].In.Amount() - outs[0].Out.Amount() 202 require.Equal(expectedConsumed, consumed) 203 } 204 205 func TestCreateChainTx(t *testing.T) { 206 var ( 207 require = require.New(t) 208 209 // backend 210 utxosKey = testKeys[1] 211 utxos = makeTestUTXOs(utxosKey) 212 chainUTXOs = common.NewDeterministicChainUTXOs(require, map[ids.ID][]*avax.UTXO{ 213 constants.PlatformChainID: utxos, 214 }) 215 216 subnetID = ids.GenerateTestID() 217 subnetAuthKey = testKeys[0] 218 subnetAuthAddr = subnetAuthKey.Address() 219 subnetOwner = &secp256k1fx.OutputOwners{ 220 Threshold: 1, 221 Addrs: []ids.ShortID{subnetAuthAddr}, 222 } 223 subnets = map[ids.ID]*txs.Tx{ 224 subnetID: { 225 Unsigned: &txs.CreateSubnetTx{ 226 Owner: subnetOwner, 227 }, 228 }, 229 } 230 231 backend = NewBackend(testContext, chainUTXOs, subnets) 232 233 utxoAddr = utxosKey.Address() 234 builder = builder.New(set.Of(utxoAddr, subnetAuthAddr), testContext, backend) 235 236 // data to build the transaction 237 genesisBytes = []byte{'a', 'b', 'c'} 238 vmID = ids.GenerateTestID() 239 fxIDs = []ids.ID{ids.GenerateTestID()} 240 chainName = "dummyChain" 241 ) 242 243 // build the transaction 244 utx, err := builder.NewCreateChainTx( 245 subnetID, 246 genesisBytes, 247 vmID, 248 fxIDs, 249 chainName, 250 ) 251 require.NoError(err) 252 253 // check UTXOs selection and fee financing 254 ins := utx.Ins 255 outs := utx.Outs 256 require.Len(ins, 1) 257 require.Len(outs, 1) 258 259 expectedConsumed := testContext.CreateBlockchainTxFee 260 consumed := ins[0].In.Amount() - outs[0].Out.Amount() 261 require.Equal(expectedConsumed, consumed) 262 } 263 264 func TestCreateSubnetTx(t *testing.T) { 265 var ( 266 require = require.New(t) 267 268 // backend 269 utxosKey = testKeys[1] 270 utxos = makeTestUTXOs(utxosKey) 271 chainUTXOs = common.NewDeterministicChainUTXOs(require, map[ids.ID][]*avax.UTXO{ 272 constants.PlatformChainID: utxos, 273 }) 274 275 subnetID = ids.GenerateTestID() 276 subnetAuthKey = testKeys[0] 277 subnetAuthAddr = subnetAuthKey.Address() 278 subnetOwner = &secp256k1fx.OutputOwners{ 279 Threshold: 1, 280 Addrs: []ids.ShortID{subnetAuthAddr}, 281 } 282 subnets = map[ids.ID]*txs.Tx{ 283 subnetID: { 284 Unsigned: &txs.CreateSubnetTx{ 285 Owner: subnetOwner, 286 }, 287 }, 288 } 289 290 backend = NewBackend(testContext, chainUTXOs, subnets) 291 292 // builder 293 utxoAddr = utxosKey.Address() 294 builder = builder.New(set.Of(utxoAddr, subnetAuthAddr), testContext, backend) 295 ) 296 297 // build the transaction 298 utx, err := builder.NewCreateSubnetTx(subnetOwner) 299 require.NoError(err) 300 301 // check UTXOs selection and fee financing 302 ins := utx.Ins 303 outs := utx.Outs 304 require.Len(ins, 1) 305 require.Len(outs, 1) 306 307 expectedConsumed := testContext.CreateSubnetTxFee 308 consumed := ins[0].In.Amount() - outs[0].Out.Amount() 309 require.Equal(expectedConsumed, consumed) 310 } 311 312 func TestTransferSubnetOwnershipTx(t *testing.T) { 313 var ( 314 require = require.New(t) 315 316 // backend 317 utxosKey = testKeys[1] 318 utxos = makeTestUTXOs(utxosKey) 319 chainUTXOs = common.NewDeterministicChainUTXOs(require, map[ids.ID][]*avax.UTXO{ 320 constants.PlatformChainID: utxos, 321 }) 322 323 subnetID = ids.GenerateTestID() 324 subnetAuthKey = testKeys[0] 325 subnetAuthAddr = subnetAuthKey.Address() 326 subnetOwner = &secp256k1fx.OutputOwners{ 327 Threshold: 1, 328 Addrs: []ids.ShortID{subnetAuthAddr}, 329 } 330 subnets = map[ids.ID]*txs.Tx{ 331 subnetID: { 332 Unsigned: &txs.CreateSubnetTx{ 333 Owner: subnetOwner, 334 }, 335 }, 336 } 337 338 backend = NewBackend(testContext, chainUTXOs, subnets) 339 340 // builder 341 utxoAddr = utxosKey.Address() 342 builder = builder.New(set.Of(utxoAddr, subnetAuthAddr), testContext, backend) 343 ) 344 345 // build the transaction 346 utx, err := builder.NewTransferSubnetOwnershipTx( 347 subnetID, 348 subnetOwner, 349 ) 350 require.NoError(err) 351 352 // check UTXOs selection and fee financing 353 ins := utx.Ins 354 outs := utx.Outs 355 require.Len(ins, 1) 356 require.Len(outs, 1) 357 358 expectedConsumed := testContext.BaseTxFee 359 consumed := ins[0].In.Amount() - outs[0].Out.Amount() 360 require.Equal(expectedConsumed, consumed) 361 } 362 363 func TestImportTx(t *testing.T) { 364 var ( 365 require = require.New(t) 366 367 // backend 368 utxosKey = testKeys[1] 369 utxos = makeTestUTXOs(utxosKey) 370 sourceChainID = ids.GenerateTestID() 371 importedUTXOs = utxos[:1] 372 chainUTXOs = common.NewDeterministicChainUTXOs(require, map[ids.ID][]*avax.UTXO{ 373 constants.PlatformChainID: utxos, 374 sourceChainID: importedUTXOs, 375 }) 376 377 backend = NewBackend(testContext, chainUTXOs, nil) 378 379 // builder 380 utxoAddr = utxosKey.Address() 381 builder = builder.New(set.Of(utxoAddr), testContext, backend) 382 383 // data to build the transaction 384 importKey = testKeys[0] 385 importTo = &secp256k1fx.OutputOwners{ 386 Threshold: 1, 387 Addrs: []ids.ShortID{ 388 importKey.Address(), 389 }, 390 } 391 ) 392 393 // build the transaction 394 utx, err := builder.NewImportTx( 395 sourceChainID, 396 importTo, 397 ) 398 require.NoError(err) 399 400 // check UTXOs selection and fee financing 401 ins := utx.Ins 402 outs := utx.Outs 403 importedIns := utx.ImportedInputs 404 require.Empty(ins) // we spend the imported input (at least partially) 405 require.Len(importedIns, 1) 406 require.Len(outs, 1) 407 408 expectedConsumed := testContext.BaseTxFee 409 consumed := importedIns[0].In.Amount() - outs[0].Out.Amount() 410 require.Equal(expectedConsumed, consumed) 411 } 412 413 func TestExportTx(t *testing.T) { 414 var ( 415 require = require.New(t) 416 417 // backend 418 utxosKey = testKeys[1] 419 utxos = makeTestUTXOs(utxosKey) 420 chainUTXOs = common.NewDeterministicChainUTXOs(require, map[ids.ID][]*avax.UTXO{ 421 constants.PlatformChainID: utxos, 422 }) 423 backend = NewBackend(testContext, chainUTXOs, nil) 424 425 // builder 426 utxoAddr = utxosKey.Address() 427 builder = builder.New(set.Of(utxoAddr), testContext, backend) 428 429 // data to build the transaction 430 subnetID = ids.GenerateTestID() 431 exportedOutputs = []*avax.TransferableOutput{{ 432 Asset: avax.Asset{ID: avaxAssetID}, 433 Out: &secp256k1fx.TransferOutput{ 434 Amt: 7 * units.Avax, 435 OutputOwners: secp256k1fx.OutputOwners{ 436 Threshold: 1, 437 Addrs: []ids.ShortID{utxoAddr}, 438 }, 439 }, 440 }} 441 ) 442 443 // build the transaction 444 utx, err := builder.NewExportTx( 445 subnetID, 446 exportedOutputs, 447 ) 448 require.NoError(err) 449 450 // check UTXOs selection and fee financing 451 ins := utx.Ins 452 outs := utx.Outs 453 require.Len(ins, 2) 454 require.Len(outs, 1) 455 456 expectedConsumed := testContext.BaseTxFee + exportedOutputs[0].Out.Amount() 457 consumed := ins[0].In.Amount() + ins[1].In.Amount() - outs[0].Out.Amount() 458 require.Equal(expectedConsumed, consumed) 459 require.Equal(utx.ExportedOutputs, exportedOutputs) 460 } 461 462 func TestTransformSubnetTx(t *testing.T) { 463 var ( 464 require = require.New(t) 465 466 // backend 467 utxosKey = testKeys[1] 468 utxos = makeTestUTXOs(utxosKey) 469 chainUTXOs = common.NewDeterministicChainUTXOs(require, map[ids.ID][]*avax.UTXO{ 470 constants.PlatformChainID: utxos, 471 }) 472 473 subnetID = ids.GenerateTestID() 474 subnetAuthKey = testKeys[0] 475 subnetAuthAddr = subnetAuthKey.Address() 476 subnetOwner = &secp256k1fx.OutputOwners{ 477 Threshold: 1, 478 Addrs: []ids.ShortID{subnetAuthAddr}, 479 } 480 subnets = map[ids.ID]*txs.Tx{ 481 subnetID: { 482 Unsigned: &txs.CreateSubnetTx{ 483 Owner: subnetOwner, 484 }, 485 }, 486 } 487 488 backend = NewBackend(testContext, chainUTXOs, subnets) 489 490 // builder 491 utxoAddr = utxosKey.Address() 492 builder = builder.New(set.Of(utxoAddr, subnetAuthAddr), testContext, backend) 493 494 // data to build the transaction 495 initialSupply = 40 * units.MegaAvax 496 maxSupply = 100 * units.MegaAvax 497 ) 498 499 // build the transaction 500 utx, err := builder.NewTransformSubnetTx( 501 subnetID, 502 subnetAssetID, 503 initialSupply, // initial supply 504 maxSupply, // max supply 505 reward.PercentDenominator, // min consumption rate 506 reward.PercentDenominator, // max consumption rate 507 1, // min validator stake 508 100*units.MegaAvax, // max validator stake 509 time.Second, // min stake duration 510 365*24*time.Hour, // max stake duration 511 0, // min delegation fee 512 1, // min delegator stake 513 5, // max validator weight factor 514 .80*reward.PercentDenominator, // uptime requirement 515 ) 516 require.NoError(err) 517 518 // check UTXOs selection and fee financing 519 ins := utx.Ins 520 outs := utx.Outs 521 require.Len(ins, 2) 522 require.Len(outs, 2) 523 524 expectedConsumedSubnetAsset := maxSupply - initialSupply 525 consumedSubnetAsset := ins[0].In.Amount() - outs[1].Out.Amount() 526 require.Equal(expectedConsumedSubnetAsset, consumedSubnetAsset) 527 expectedConsumed := testContext.TransformSubnetTxFee 528 consumed := ins[1].In.Amount() - outs[0].Out.Amount() 529 require.Equal(expectedConsumed, consumed) 530 } 531 532 func TestAddPermissionlessValidatorTx(t *testing.T) { 533 var ( 534 require = require.New(t) 535 536 // backend 537 utxosKey = testKeys[1] 538 utxos = makeTestUTXOs(utxosKey) 539 chainUTXOs = common.NewDeterministicChainUTXOs(require, map[ids.ID][]*avax.UTXO{ 540 constants.PlatformChainID: utxos, 541 }) 542 backend = NewBackend(testContext, chainUTXOs, nil) 543 544 // builder 545 utxoAddr = utxosKey.Address() 546 rewardKey = testKeys[0] 547 rewardAddr = rewardKey.Address() 548 builder = builder.New(set.Of(utxoAddr, rewardAddr), testContext, backend) 549 550 // data to build the transaction 551 validationRewardsOwner = &secp256k1fx.OutputOwners{ 552 Threshold: 1, 553 Addrs: []ids.ShortID{ 554 rewardAddr, 555 }, 556 } 557 delegationRewardsOwner = &secp256k1fx.OutputOwners{ 558 Threshold: 1, 559 Addrs: []ids.ShortID{ 560 rewardAddr, 561 }, 562 } 563 ) 564 565 sk, err := bls.NewSecretKey() 566 require.NoError(err) 567 568 // build the transaction 569 utx, err := builder.NewAddPermissionlessValidatorTx( 570 &txs.SubnetValidator{ 571 Validator: txs.Validator{ 572 NodeID: ids.GenerateTestNodeID(), 573 End: uint64(time.Now().Add(time.Hour).Unix()), 574 Wght: 2 * units.Avax, 575 }, 576 Subnet: constants.PrimaryNetworkID, 577 }, 578 signer.NewProofOfPossession(sk), 579 avaxAssetID, 580 validationRewardsOwner, 581 delegationRewardsOwner, 582 reward.PercentDenominator, 583 ) 584 require.NoError(err) 585 586 // check UTXOs selection and fee financing 587 ins := utx.Ins 588 staked := utx.StakeOuts 589 outs := utx.Outs 590 require.Len(ins, 4) 591 require.Len(staked, 2) 592 require.Len(outs, 2) 593 594 expectedConsumedSubnetAsset := utx.Validator.Weight() 595 consumedSubnetAsset := staked[0].Out.Amount() + staked[1].Out.Amount() 596 require.Equal(expectedConsumedSubnetAsset, consumedSubnetAsset) 597 expectedConsumed := testContext.AddPrimaryNetworkValidatorFee 598 consumed := ins[1].In.Amount() + ins[3].In.Amount() - outs[0].Out.Amount() 599 require.Equal(expectedConsumed, consumed) 600 } 601 602 func TestAddPermissionlessDelegatorTx(t *testing.T) { 603 var ( 604 require = require.New(t) 605 606 // backend 607 utxosKey = testKeys[1] 608 utxos = makeTestUTXOs(utxosKey) 609 chainUTXOs = common.NewDeterministicChainUTXOs(require, map[ids.ID][]*avax.UTXO{ 610 constants.PlatformChainID: utxos, 611 }) 612 backend = NewBackend(testContext, chainUTXOs, nil) 613 614 // builder 615 utxoAddr = utxosKey.Address() 616 rewardKey = testKeys[0] 617 rewardAddr = rewardKey.Address() 618 builder = builder.New(set.Of(utxoAddr, rewardAddr), testContext, backend) 619 620 // data to build the transaction 621 rewardsOwner = &secp256k1fx.OutputOwners{ 622 Threshold: 1, 623 Addrs: []ids.ShortID{ 624 rewardAddr, 625 }, 626 } 627 ) 628 629 // build the transaction 630 utx, err := builder.NewAddPermissionlessDelegatorTx( 631 &txs.SubnetValidator{ 632 Validator: txs.Validator{ 633 NodeID: ids.GenerateTestNodeID(), 634 End: uint64(time.Now().Add(time.Hour).Unix()), 635 Wght: 2 * units.Avax, 636 }, 637 Subnet: constants.PrimaryNetworkID, 638 }, 639 avaxAssetID, 640 rewardsOwner, 641 ) 642 require.NoError(err) 643 644 // check UTXOs selection and fee financing 645 ins := utx.Ins 646 staked := utx.StakeOuts 647 outs := utx.Outs 648 require.Len(ins, 4) 649 require.Len(staked, 2) 650 require.Len(outs, 2) 651 652 expectedConsumedSubnetAsset := utx.Validator.Weight() 653 consumedSubnetAsset := staked[0].Out.Amount() + staked[1].Out.Amount() 654 require.Equal(expectedConsumedSubnetAsset, consumedSubnetAsset) 655 expectedConsumed := testContext.AddPrimaryNetworkDelegatorFee 656 consumed := ins[1].In.Amount() + ins[3].In.Amount() - outs[0].Out.Amount() 657 require.Equal(expectedConsumed, consumed) 658 } 659 660 func makeTestUTXOs(utxosKey *secp256k1.PrivateKey) []*avax.UTXO { 661 // Note: we avoid ids.GenerateTestNodeID here to make sure that UTXO IDs won't change 662 // run by run. This simplifies checking what utxos are included in the built txs. 663 const utxosOffset uint64 = 2024 664 665 utxosAddr := utxosKey.Address() 666 return []*avax.UTXO{ 667 { // a small UTXO first, which should not be enough to pay fees 668 UTXOID: avax.UTXOID{ 669 TxID: ids.Empty.Prefix(utxosOffset), 670 OutputIndex: uint32(utxosOffset), 671 }, 672 Asset: avax.Asset{ID: avaxAssetID}, 673 Out: &secp256k1fx.TransferOutput{ 674 Amt: 2 * units.MilliAvax, 675 OutputOwners: secp256k1fx.OutputOwners{ 676 Locktime: 0, 677 Addrs: []ids.ShortID{utxosAddr}, 678 Threshold: 1, 679 }, 680 }, 681 }, 682 { // a locked, small UTXO 683 UTXOID: avax.UTXOID{ 684 TxID: ids.Empty.Prefix(utxosOffset + 1), 685 OutputIndex: uint32(utxosOffset + 1), 686 }, 687 Asset: avax.Asset{ID: avaxAssetID}, 688 Out: &stakeable.LockOut{ 689 Locktime: uint64(time.Now().Add(time.Hour).Unix()), 690 TransferableOut: &secp256k1fx.TransferOutput{ 691 Amt: 3 * units.MilliAvax, 692 OutputOwners: secp256k1fx.OutputOwners{ 693 Threshold: 1, 694 Addrs: []ids.ShortID{utxosAddr}, 695 }, 696 }, 697 }, 698 }, 699 { // a subnetAssetID denominated UTXO 700 UTXOID: avax.UTXOID{ 701 TxID: ids.Empty.Prefix(utxosOffset + 2), 702 OutputIndex: uint32(utxosOffset + 2), 703 }, 704 Asset: avax.Asset{ID: subnetAssetID}, 705 Out: &secp256k1fx.TransferOutput{ 706 Amt: 99 * units.MegaAvax, 707 OutputOwners: secp256k1fx.OutputOwners{ 708 Locktime: 0, 709 Addrs: []ids.ShortID{utxosAddr}, 710 Threshold: 1, 711 }, 712 }, 713 }, 714 { // a locked, large UTXO 715 UTXOID: avax.UTXOID{ 716 TxID: ids.Empty.Prefix(utxosOffset + 3), 717 OutputIndex: uint32(utxosOffset + 3), 718 }, 719 Asset: avax.Asset{ID: avaxAssetID}, 720 Out: &stakeable.LockOut{ 721 Locktime: uint64(time.Now().Add(time.Hour).Unix()), 722 TransferableOut: &secp256k1fx.TransferOutput{ 723 Amt: 88 * units.Avax, 724 OutputOwners: secp256k1fx.OutputOwners{ 725 Threshold: 1, 726 Addrs: []ids.ShortID{utxosAddr}, 727 }, 728 }, 729 }, 730 }, 731 { // a large UTXO last, which should be enough to pay any fee by itself 732 UTXOID: avax.UTXOID{ 733 TxID: ids.Empty.Prefix(utxosOffset + 4), 734 OutputIndex: uint32(utxosOffset + 4), 735 }, 736 Asset: avax.Asset{ID: avaxAssetID}, 737 Out: &secp256k1fx.TransferOutput{ 738 Amt: 9 * units.Avax, 739 OutputOwners: secp256k1fx.OutputOwners{ 740 Locktime: 0, 741 Addrs: []ids.ShortID{utxosAddr}, 742 Threshold: 1, 743 }, 744 }, 745 }, 746 } 747 }