7 "github.com/davecgh/go-spew/spew"
9 "github.com/vapor/consensus"
10 "github.com/vapor/crypto/sha3pool"
11 "github.com/vapor/errors"
12 "github.com/vapor/protocol/bc"
13 "github.com/vapor/protocol/bc/types"
14 "github.com/vapor/protocol/vm"
15 "github.com/vapor/protocol/vm/vmutil"
16 "github.com/vapor/testutil"
20 spew.Config.DisableMethods = true
23 func TestGasStatus(t *testing.T) {
27 f func(*GasState) error
37 GasLeft: 10000 / consensus.VMGasRate,
41 f: func(input *GasState) error {
42 return input.setGas(10000, 0)
57 f: func(input *GasState) error {
58 return input.setGas(-10000, 0)
64 GasLeft: consensus.DefaultGasCredit,
71 BTMValue: 80000000000,
73 f: func(input *GasState) error {
74 return input.setGas(80000000000, 0)
80 GasLeft: consensus.DefaultGasCredit,
87 BTMValue: math.MaxInt64,
89 f: func(input *GasState) error {
90 return input.setGas(math.MaxInt64, 0)
105 f: func(input *GasState) error {
106 return input.updateUsage(-1)
108 err: ErrGasCalculate,
121 f: func(input *GasState) error {
122 return input.updateUsage(9999)
137 f: func(input *GasState) error {
138 return input.updateUsage(math.MaxInt64)
140 err: ErrGasCalculate,
155 f: func(input *GasState) error {
156 return input.setGasValid()
173 f: func(input *GasState) error {
174 return input.setGasValid()
176 err: ErrGasCalculate,
181 GasUsed: math.MaxInt64,
191 f: func(input *GasState) error {
192 return input.setGasValid()
194 err: ErrGasCalculate,
198 GasLeft: math.MinInt64,
209 f: func(input *GasState) error {
210 return input.setGasValid()
212 err: ErrGasCalculate,
216 for i, c := range cases {
219 if rootErr(err) != c.err {
220 t.Errorf("case %d: got error %s, want %s", i, err, c.err)
221 } else if *c.input != *c.output {
222 t.Errorf("case %d: gasStatus %v, want %v;", i, c.input, c.output)
227 func TestOverflow(t *testing.T) {
228 sourceID := &bc.Hash{V0: 9999}
229 ctrlProgram := []byte{byte(vm.OP_TRUE)}
230 newTx := func(inputs []uint64, outputs []uint64) *bc.Tx {
231 txInputs := make([]*types.TxInput, 0, len(inputs))
232 txOutputs := make([]*types.TxOutput, 0, len(outputs))
234 for _, amount := range inputs {
235 txInput := types.NewSpendInput(nil, *sourceID, *consensus.BTMAssetID, amount, 0, ctrlProgram)
236 txInputs = append(txInputs, txInput)
239 for _, amount := range outputs {
240 txOutput := types.NewIntraChainOutput(*consensus.BTMAssetID, amount, ctrlProgram)
241 txOutputs = append(txOutputs, txOutput)
244 txData := &types.TxData{
251 return types.MapTx(txData)
260 inputs: []uint64{math.MaxUint64, 1},
261 outputs: []uint64{0},
265 inputs: []uint64{math.MaxUint64, math.MaxUint64},
266 outputs: []uint64{0},
270 inputs: []uint64{math.MaxUint64, math.MaxUint64 - 1},
271 outputs: []uint64{0},
275 inputs: []uint64{math.MaxInt64, 1},
276 outputs: []uint64{0},
280 inputs: []uint64{math.MaxInt64, math.MaxInt64},
281 outputs: []uint64{0},
285 inputs: []uint64{math.MaxInt64, math.MaxInt64 - 1},
286 outputs: []uint64{0},
291 outputs: []uint64{math.MaxUint64},
296 outputs: []uint64{math.MaxInt64},
297 err: ErrGasCalculate,
300 inputs: []uint64{math.MaxInt64 - 1},
301 outputs: []uint64{math.MaxInt64},
302 err: ErrGasCalculate,
306 for i, c := range cases {
307 tx := newTx(c.inputs, c.outputs)
308 if _, err := ValidateTx(tx, mockBlock()); rootErr(err) != c.err {
309 t.Fatalf("case %d test failed, want %s, have %s", i, c.err, rootErr(err))
314 func TestTxValidation(t *testing.T) {
320 // the mux from tx, pulled out for convenience
324 addCoinbase := func(assetID *bc.AssetID, amount uint64, arbitrary []byte) {
325 coinbase := bc.NewCoinbase(arbitrary)
326 txOutput := types.NewIntraChainOutput(*assetID, amount, []byte{byte(vm.OP_TRUE)})
327 assetAmount := txOutput.AssetAmount()
328 muxID := getMuxID(tx)
329 coinbase.SetDestination(muxID, &assetAmount, uint64(len(mux.Sources)))
330 coinbaseID := bc.EntryID(coinbase)
331 tx.Entries[coinbaseID] = coinbase
333 mux.Sources = append(mux.Sources, &bc.ValueSource{
338 src := &bc.ValueSource{
341 Position: uint64(len(tx.ResultIds)),
343 prog := &bc.Program{txOutput.VMVersion(), txOutput.ControlProgram()}
344 output := bc.NewIntraChainOutput(src, prog, uint64(len(tx.ResultIds)))
345 outputID := bc.EntryID(output)
346 tx.Entries[outputID] = output
348 dest := &bc.ValueDestination{
353 mux.WitnessDestinations = append(mux.WitnessDestinations, dest)
354 tx.ResultIds = append(tx.ResultIds, &outputID)
355 vs.block.Transactions = append(vs.block.Transactions, vs.tx)
359 desc string // description of the test case
360 f func() // function to adjust tx, vs, and/or mux
361 err error // expected error
367 desc: "unbalanced mux amounts",
369 mux.Sources[0].Value.Amount++
370 iss := tx.Entries[*mux.Sources[0].Ref].(*bc.Issuance)
371 iss.WitnessDestination.Value.Amount++
376 desc: "unbalanced mux amounts",
378 mux.WitnessDestinations[0].Value.Amount++
383 desc: "balanced mux amounts",
385 mux.Sources[1].Value.Amount++
386 mux.WitnessDestinations[0].Value.Amount++
391 desc: "overflowing mux source amounts",
393 mux.Sources[0].Value.Amount = math.MaxInt64
394 iss := tx.Entries[*mux.Sources[0].Ref].(*bc.Issuance)
395 iss.WitnessDestination.Value.Amount = math.MaxInt64
400 desc: "underflowing mux destination amounts",
402 mux.WitnessDestinations[0].Value.Amount = math.MaxInt64
403 out := tx.Entries[*mux.WitnessDestinations[0].Ref].(*bc.IntraChainOutput)
404 out.Source.Value.Amount = math.MaxInt64
405 mux.WitnessDestinations[1].Value.Amount = math.MaxInt64
406 out = tx.Entries[*mux.WitnessDestinations[1].Ref].(*bc.IntraChainOutput)
407 out.Source.Value.Amount = math.MaxInt64
412 desc: "unbalanced mux assets",
414 mux.Sources[1].Value.AssetId = newAssetID(255)
415 sp := tx.Entries[*mux.Sources[1].Ref].(*bc.Spend)
416 sp.WitnessDestination.Value.AssetId = newAssetID(255)
421 desc: "mismatched output source / mux dest position",
423 tx.Entries[*tx.ResultIds[0]].(*bc.IntraChainOutput).Source.Position = 1
425 err: ErrMismatchedPosition,
428 desc: "mismatched input dest / mux source position",
430 mux.Sources[0].Position = 1
432 err: ErrMismatchedPosition,
435 desc: "mismatched output source and mux dest",
437 // For this test, it's necessary to construct a mostly
438 // identical second transaction in order to get a similar but
439 // not equal output entry for the mux to falsely point
440 // to. That entry must be added to the first tx's Entries map.
441 fixture2 := sample(t, fixture)
442 tx2 := types.NewTx(*fixture2.tx).Tx
443 out2ID := tx2.ResultIds[0]
444 out2 := tx2.Entries[*out2ID].(*bc.IntraChainOutput)
445 tx.Entries[*out2ID] = out2
446 mux.WitnessDestinations[0].Ref = out2ID
448 err: ErrMismatchedReference,
451 desc: "mismatched input dest and mux source",
453 fixture2 := sample(t, fixture)
454 tx2 := types.NewTx(*fixture2.tx).Tx
455 input2ID := tx2.InputIDs[2]
456 input2 := tx2.Entries[input2ID].(*bc.Spend)
457 dest2Ref := input2.WitnessDestination.Ref
458 dest2 := tx2.Entries[*dest2Ref].(*bc.Mux)
459 tx.Entries[*dest2Ref] = dest2
460 tx.Entries[input2ID] = input2
461 mux.Sources[0].Ref = &input2ID
463 err: ErrMismatchedReference,
466 desc: "invalid mux destination position",
468 mux.WitnessDestinations[0].Position = 1
473 desc: "mismatched mux dest value / output source value",
475 outID := tx.ResultIds[0]
476 out := tx.Entries[*outID].(*bc.IntraChainOutput)
477 mux.WitnessDestinations[0].Value = &bc.AssetAmount{
478 AssetId: out.Source.Value.AssetId,
479 Amount: out.Source.Value.Amount + 1,
481 mux.Sources[0].Value.Amount++ // the mux must still balance
483 err: ErrMismatchedValue,
486 desc: "empty tx results",
490 err: ErrEmptyResults,
493 desc: "empty tx results, but that's OK",
500 desc: "issuance program failure",
502 iss := txIssuance(t, tx, 0)
503 iss.WitnessArguments[0] = []byte{}
505 err: vm.ErrFalseVMResult,
508 desc: "spend control program failure",
510 spend := txSpend(t, tx, 1)
511 spend.WitnessArguments[0] = []byte{}
513 err: vm.ErrFalseVMResult,
516 desc: "mismatched spent source/witness value",
518 spend := txSpend(t, tx, 1)
519 spentOutput := tx.Entries[*spend.SpentOutputId].(*bc.IntraChainOutput)
520 spentOutput.Source.Value = &bc.AssetAmount{
521 AssetId: spend.WitnessDestination.Value.AssetId,
522 Amount: spend.WitnessDestination.Value.Amount + 1,
525 err: ErrMismatchedValue,
528 desc: "gas out of limit",
530 vs.tx.SerializedSize = 10000000
532 err: ErrOverGasCredit,
535 desc: "can't find gas spend input in entries",
537 spendID := mux.Sources[len(mux.Sources)-1].Ref
538 delete(tx.Entries, *spendID)
539 mux.Sources = mux.Sources[:len(mux.Sources)-1]
541 err: bc.ErrMissingEntry,
544 desc: "no gas spend input",
546 spendID := mux.Sources[len(mux.Sources)-1].Ref
547 delete(tx.Entries, *spendID)
548 mux.Sources = mux.Sources[:len(mux.Sources)-1]
550 vs.gasStatus.GasLeft = 0
552 err: vm.ErrRunLimitExceeded,
555 desc: "no gas spend input, but set gas left, so it's ok",
557 spendID := mux.Sources[len(mux.Sources)-1].Ref
558 delete(tx.Entries, *spendID)
559 mux.Sources = mux.Sources[:len(mux.Sources)-1]
565 desc: "mismatched gas spend input destination amount/prevout source amount",
567 spendID := mux.Sources[len(mux.Sources)-1].Ref
568 spend := tx.Entries[*spendID].(*bc.Spend)
569 spend.WitnessDestination.Value = &bc.AssetAmount{
570 AssetId: spend.WitnessDestination.Value.AssetId,
571 Amount: spend.WitnessDestination.Value.Amount + 1,
574 err: ErrMismatchedValue,
577 desc: "mismatched witness asset destination",
579 issuanceID := mux.Sources[0].Ref
580 issuance := tx.Entries[*issuanceID].(*bc.Issuance)
581 issuance.WitnessAssetDefinition.Data = &bc.Hash{V0: 9999}
583 err: ErrMismatchedAssetID,
586 desc: "issuance witness position greater than length of mux sources",
588 issuanceID := mux.Sources[0].Ref
589 issuance := tx.Entries[*issuanceID].(*bc.Issuance)
590 issuance.WitnessDestination.Position = uint64(len(mux.Sources) + 1)
595 desc: "normal coinbase tx",
597 addCoinbase(consensus.BTMAssetID, 100000, nil)
602 desc: "invalid coinbase tx asset id",
604 addCoinbase(&bc.AssetID{V1: 100}, 100000, nil)
606 err: ErrWrongCoinbaseAsset,
609 desc: "coinbase tx is not first tx in block",
611 addCoinbase(consensus.BTMAssetID, 100000, nil)
612 vs.block.Transactions[0] = nil
614 err: ErrWrongCoinbaseTransaction,
617 desc: "coinbase arbitrary size out of limit",
619 arbitrary := make([]byte, consensus.CoinbaseArbitrarySizeLimit+1)
620 addCoinbase(consensus.BTMAssetID, 100000, arbitrary)
622 err: ErrCoinbaseArbitraryOversize,
625 desc: "normal retirement output",
627 outputID := tx.ResultIds[0]
628 output := tx.Entries[*outputID].(*bc.IntraChainOutput)
629 retirement := bc.NewRetirement(output.Source, output.Ordinal)
630 retirementID := bc.EntryID(retirement)
631 tx.Entries[retirementID] = retirement
632 delete(tx.Entries, *outputID)
633 tx.ResultIds[0] = &retirementID
634 mux.WitnessDestinations[0].Ref = &retirementID
639 desc: "ordinal doesn't matter for prevouts",
641 spend := txSpend(t, tx, 1)
642 prevout := tx.Entries[*spend.SpentOutputId].(*bc.IntraChainOutput)
643 newPrevout := bc.NewIntraChainOutput(prevout.Source, prevout.ControlProgram, 10)
644 hash := bc.EntryID(newPrevout)
645 spend.SpentOutputId = &hash
650 desc: "mux witness destination have no source",
652 dest := &bc.ValueDestination{
653 Value: &bc.AssetAmount{
654 AssetId: &bc.AssetID{V2: 1000},
657 Ref: mux.WitnessDestinations[0].Ref,
660 mux.WitnessDestinations = append(mux.WitnessDestinations, dest)
666 for i, c := range cases {
667 t.Run(c.desc, func(t *testing.T) {
668 fixture = sample(t, nil)
669 tx = types.NewTx(*fixture.tx).Tx
670 vs = &validationState{
674 gasStatus: &GasState{
675 GasLeft: int64(80000),
678 cache: make(map[bc.Hash]error),
680 muxID := getMuxID(tx)
681 mux = tx.Entries[*muxID].(*bc.Mux)
686 err := checkValid(vs, tx.TxHeader)
688 if rootErr(err) != c.err {
689 t.Errorf("case #%d (%s) got error %s, want %s; validationState is:\n%s", i, c.desc, err, c.err, spew.Sdump(vs))
695 // TestCoinbase test the coinbase transaction is valid (txtest#1016)
696 func TestCoinbase(t *testing.T) {
697 cp, _ := vmutil.DefaultCoinbaseProgram()
698 retire, _ := vmutil.RetireProgram([]byte{})
699 CbTx := types.MapTx(&types.TxData{
701 Inputs: []*types.TxInput{
702 types.NewCoinbaseInput(nil),
704 Outputs: []*types.TxOutput{
705 types.NewIntraChainOutput(*consensus.BTMAssetID, 888, cp),
717 BlockHeader: &bc.BlockHeader{Height: 666},
718 Transactions: []*bc.Tx{CbTx},
726 BlockHeader: &bc.BlockHeader{Height: 666},
727 Transactions: []*bc.Tx{
729 types.MapTx(&types.TxData{
731 Inputs: []*types.TxInput{
732 types.NewCoinbaseInput(nil),
734 Outputs: []*types.TxOutput{
735 types.NewIntraChainOutput(*consensus.BTMAssetID, 888, cp),
742 err: ErrWrongCoinbaseTransaction,
746 BlockHeader: &bc.BlockHeader{Height: 666},
747 Transactions: []*bc.Tx{
749 types.MapTx(&types.TxData{
751 Inputs: []*types.TxInput{
752 types.NewCoinbaseInput(nil),
753 types.NewSpendInput([][]byte{}, *newHash(8), *consensus.BTMAssetID, 100000000, 0, cp),
755 Outputs: []*types.TxOutput{
756 types.NewIntraChainOutput(*consensus.BTMAssetID, 888, cp),
757 types.NewIntraChainOutput(*consensus.BTMAssetID, 90000000, cp),
764 err: ErrWrongCoinbaseTransaction,
768 BlockHeader: &bc.BlockHeader{Height: 666},
769 Transactions: []*bc.Tx{
771 types.MapTx(&types.TxData{
773 Inputs: []*types.TxInput{
774 types.NewSpendInput([][]byte{}, *newHash(8), *consensus.BTMAssetID, 100000000, 0, cp),
775 types.NewCoinbaseInput(nil),
777 Outputs: []*types.TxOutput{
778 types.NewIntraChainOutput(*consensus.BTMAssetID, 888, cp),
779 types.NewIntraChainOutput(*consensus.BTMAssetID, 90000000, cp),
786 err: ErrWrongCoinbaseTransaction,
790 BlockHeader: &bc.BlockHeader{Height: 666},
791 Transactions: []*bc.Tx{
792 types.MapTx(&types.TxData{
794 Inputs: []*types.TxInput{
795 types.NewCoinbaseInput(nil),
796 types.NewSpendInput([][]byte{}, *newHash(8), *consensus.BTMAssetID, 100000000, 0, cp),
798 Outputs: []*types.TxOutput{
799 types.NewIntraChainOutput(*consensus.BTMAssetID, 888, cp),
800 types.NewIntraChainOutput(*consensus.BTMAssetID, 90000000, cp),
811 BlockHeader: &bc.BlockHeader{Height: 666},
812 Transactions: []*bc.Tx{
813 types.MapTx(&types.TxData{
815 Inputs: []*types.TxInput{
816 types.NewCoinbaseInput(nil),
817 types.NewSpendInput([][]byte{}, *newHash(8), *consensus.BTMAssetID, 100000000, 0, retire),
819 Outputs: []*types.TxOutput{
820 types.NewIntraChainOutput(*consensus.BTMAssetID, 888, cp),
821 types.NewIntraChainOutput(*consensus.BTMAssetID, 90000000, cp),
832 for i, c := range cases {
833 gasStatus, err := ValidateTx(c.block.Transactions[c.txIndex], c.block)
835 if rootErr(err) != c.err {
836 t.Errorf("#%d got error %s, want %s", i, err, c.err)
838 if c.GasValid != gasStatus.GasValid {
839 t.Errorf("#%d got GasValid %t, want %t", i, gasStatus.GasValid, c.GasValid)
844 // TestTimeRange test the checkTimeRange function (txtest#1004)
845 func TestTimeRange(t *testing.T) {
863 timeRange: 1521625824,
869 BlockHeader: &bc.BlockHeader{
871 Timestamp: 1521625823,
875 tx := types.MapTx(&types.TxData{
878 Inputs: []*types.TxInput{
881 Outputs: []*types.TxOutput{
882 types.NewIntraChainOutput(*consensus.BTMAssetID, 1, []byte{0x6a}),
886 for i, c := range cases {
887 tx.TimeRange = c.timeRange
888 if _, err := ValidateTx(tx, block); (err != nil) != c.err {
889 t.Errorf("#%d got error %t, want %t", i, !c.err, c.err)
894 func TestStandardTx(t *testing.T) {
895 fixture := sample(t, nil)
896 tx := types.NewTx(*fixture.tx).Tx
904 desc: "normal standard tx",
908 desc: "not standard tx in spend input",
910 inputID := tx.GasInputIDs[0]
911 spend := tx.Entries[inputID].(*bc.Spend)
912 spentOutput, err := tx.IntraChainOutput(*spend.SpentOutputId)
916 spentOutput.ControlProgram = &bc.Program{Code: []byte{0}}
918 err: ErrNotStandardTx,
921 desc: "not standard tx in output",
923 outputID := tx.ResultIds[0]
924 output := tx.Entries[*outputID].(*bc.IntraChainOutput)
925 output.ControlProgram = &bc.Program{Code: []byte{0}}
927 err: ErrNotStandardTx,
931 for i, c := range cases {
935 if err := checkStandardTx(tx, 0); err != c.err {
936 t.Errorf("case #%d (%s) got error %t, want %t", i, c.desc, err, c.err)
941 func TestValidateTxVersion(t *testing.T) {
948 desc: "tx version greater than 1 (txtest#1001)",
950 BlockHeader: &bc.BlockHeader{Version: 1},
951 Transactions: []*bc.Tx{
952 {TxHeader: &bc.TxHeader{Version: 2}},
958 desc: "tx version equals 0 (txtest#1002)",
960 BlockHeader: &bc.BlockHeader{Version: 1},
961 Transactions: []*bc.Tx{
962 {TxHeader: &bc.TxHeader{Version: 0}},
968 desc: "tx version equals max uint64 (txtest#1003)",
970 BlockHeader: &bc.BlockHeader{Version: 1},
971 Transactions: []*bc.Tx{
972 {TxHeader: &bc.TxHeader{Version: math.MaxUint64}},
979 for i, c := range cases {
980 if _, err := ValidateTx(c.block.Transactions[0], c.block); rootErr(err) != c.err {
981 t.Errorf("case #%d (%s) got error %t, want %t", i, c.desc, err, c.err)
986 // A txFixture is returned by sample (below) to produce a sample
987 // transaction, which takes a separate, optional _input_ txFixture to
988 // affect the transaction that's built. The components of the
989 // transaction are the fields of txFixture.
990 type txFixture struct {
991 initialBlockID bc.Hash
992 issuanceProg bc.Program
993 issuanceArgs [][]byte
997 txInputs []*types.TxInput
998 txOutputs []*types.TxOutput
1002 // Produces a sample transaction in a txFixture object (see above). A
1003 // separate input txFixture can be used to alter the transaction
1006 // The output of this function can be used as the input to a
1007 // subsequent call to make iterative refinements to a test object.
1009 // The default transaction produced is valid and has three inputs:
1010 // - an issuance of 10 units
1011 // - a spend of 20 units
1012 // - a spend of 40 units
1013 // and two outputs, one of 25 units and one of 45 units.
1014 // All amounts are denominated in the same asset.
1016 // The issuance program for the asset requires two numbers as
1017 // arguments that add up to 5. The prevout control programs require
1018 // two numbers each, adding to 9 and 13, respectively.
1020 // The min and max times for the transaction are now +/- one minute.
1021 func sample(tb testing.TB, in *txFixture) *txFixture {
1022 var result txFixture
1027 if result.initialBlockID.IsZero() {
1028 result.initialBlockID = *newHash(1)
1030 if testutil.DeepEqual(result.issuanceProg, bc.Program{}) {
1031 prog, err := vm.Assemble("ADD 5 NUMEQUAL")
1035 result.issuanceProg = bc.Program{VmVersion: 1, Code: prog}
1037 if len(result.issuanceArgs) == 0 {
1038 result.issuanceArgs = [][]byte{{2}, {3}}
1040 if len(result.assetDef) == 0 {
1041 result.assetDef = []byte{2}
1043 if result.assetID.IsZero() {
1044 refdatahash := hashData(result.assetDef)
1045 result.assetID = bc.ComputeAssetID(result.issuanceProg.Code, result.issuanceProg.VmVersion, &refdatahash)
1048 if result.txVersion == 0 {
1049 result.txVersion = 1
1051 if len(result.txInputs) == 0 {
1052 cp1, err := vm.Assemble("ADD 9 NUMEQUAL")
1056 args1 := [][]byte{{4}, {5}}
1058 cp2, err := vm.Assemble("ADD 13 NUMEQUAL")
1062 args2 := [][]byte{{6}, {7}}
1064 result.txInputs = []*types.TxInput{
1065 types.NewIssuanceInput([]byte{3}, 10, result.issuanceProg.Code, result.issuanceArgs, result.assetDef),
1066 types.NewSpendInput(args1, *newHash(5), result.assetID, 20, 0, cp1),
1067 types.NewSpendInput(args2, *newHash(8), result.assetID, 40, 0, cp2),
1071 result.txInputs = append(result.txInputs, mockGasTxInput())
1073 if len(result.txOutputs) == 0 {
1074 cp1, err := vm.Assemble("ADD 17 NUMEQUAL")
1078 cp2, err := vm.Assemble("ADD 21 NUMEQUAL")
1083 result.txOutputs = []*types.TxOutput{
1084 types.NewIntraChainOutput(result.assetID, 25, cp1),
1085 types.NewIntraChainOutput(result.assetID, 45, cp2),
1089 result.tx = &types.TxData{
1090 Version: result.txVersion,
1091 Inputs: result.txInputs,
1092 Outputs: result.txOutputs,
1098 func mockBlock() *bc.Block {
1100 BlockHeader: &bc.BlockHeader{
1106 func mockGasTxInput() *types.TxInput {
1107 cp, _ := vmutil.DefaultCoinbaseProgram()
1108 return types.NewSpendInput([][]byte{}, *newHash(8), *consensus.BTMAssetID, 100000000, 0, cp)
1111 // Like errors.Root, but also unwraps vm.Error objects.
1112 func rootErr(e error) error {
1113 return errors.Root(e)
1116 func hashData(data []byte) bc.Hash {
1118 sha3pool.Sum256(b32[:], data)
1119 return bc.NewHash(b32)
1122 func newHash(n byte) *bc.Hash {
1123 h := bc.NewHash([32]byte{n})
1127 func newAssetID(n byte) *bc.AssetID {
1128 a := bc.NewAssetID([32]byte{n})
1132 func txIssuance(t *testing.T, tx *bc.Tx, index int) *bc.Issuance {
1133 id := tx.InputIDs[index]
1134 res, err := tx.Issuance(id)
1141 func txSpend(t *testing.T, tx *bc.Tx, index int) *bc.Spend {
1142 id := tx.InputIDs[index]
1143 res, err := tx.Spend(id)
1150 func getMuxID(tx *bc.Tx) *bc.Hash {
1151 out := tx.Entries[*tx.ResultIds[0]]
1152 switch result := out.(type) {
1153 case *bc.IntraChainOutput:
1154 return result.Source.Ref
1155 case *bc.Retirement:
1156 return result.Source.Ref