OSDN Git Service

Merge pull request #201 from Bytom/v0.1
[bytom/vapor.git] / vendor / github.com / bytom / protocol / bc / types / transaction_test.go
diff --git a/vendor/github.com/bytom/protocol/bc/types/transaction_test.go b/vendor/github.com/bytom/protocol/bc/types/transaction_test.go
new file mode 100644 (file)
index 0000000..c3a7d4c
--- /dev/null
@@ -0,0 +1,335 @@
+package types
+
+import (
+       "bytes"
+       "encoding/hex"
+       "encoding/json"
+       "io/ioutil"
+       "strings"
+       "testing"
+
+       "github.com/davecgh/go-spew/spew"
+
+       "github.com/bytom/consensus"
+       "github.com/bytom/errors"
+       "github.com/bytom/protocol/bc"
+       "github.com/bytom/testutil"
+)
+
+func TestTransaction(t *testing.T) {
+       cases := []struct {
+               tx   *Tx
+               hex  string
+               hash bc.Hash
+       }{
+               {
+                       tx: NewTx(TxData{
+                               Version:        1,
+                               SerializedSize: uint64(5),
+                               Inputs:         nil,
+                               Outputs:        nil,
+                       }),
+                       hex: strings.Join([]string{
+                               "07", // serflags
+                               "01", // transaction version
+                               "00", // tx time range
+                               "00", // inputs count
+                               "00", // outputs count
+                       }, ""),
+                       hash: testutil.MustDecodeHash("8e88b9cb4615128c7209dff695f68b8de5b38648bf3d44d2d0e6a674848539c9"),
+               },
+               {
+                       tx: NewTx(TxData{
+                               Version:        1,
+                               SerializedSize: uint64(261),
+                               TimeRange:      654,
+                               Inputs: []*TxInput{
+                                       NewIssuanceInput([]byte("nonce"), 254354, []byte("issuanceProgram"), [][]byte{[]byte("arguments1"), []byte("arguments2")}, []byte("assetDefinition")),
+                                       NewSpendInput([][]byte{[]byte("arguments3"), []byte("arguments4")}, testutil.MustDecodeHash("fad5195a0c8e3b590b86a3c0a95e7529565888508aecca96e9aeda633002f409"), *consensus.BTMAssetID, 254354, 3, []byte("spendProgram")),
+                               },
+                               Outputs: []*TxOutput{
+                                       NewTxOutput(testutil.MustDecodeAsset("a69849e11add96ac7053aad22ba2349a4abf5feb0475a0afcadff4e128be76cf"), 254354, []byte("true")),
+                               },
+                       }),
+                       hex: strings.Join([]string{
+                               "07",         // serflags
+                               "01",         // transaction version
+                               "8e05",       // tx time range
+                               "02",         // inputs count
+                               "01",         // input 0: asset version
+                               "2a",         // input 0: serialization length
+                               "00",         // input 0: issuance type flag
+                               "05",         // input 0: nonce length
+                               "6e6f6e6365", // input 0: nonce
+                               "a69849e11add96ac7053aad22ba2349a4abf5feb0475a0afcadff4e128be76cf", // input 0: assetID
+                               "92c30f", // input 0: amount
+                               "38",     // input 0: input witness length
+                               "0f",     // input 0: asset definition length
+                               "6173736574446566696e6974696f6e", // input 0: asset definition
+                               "01", // input 0: vm version
+                               "0f", // input 0: issuanceProgram length
+                               "69737375616e636550726f6772616d", // input 0: issuance program
+                               "02", // input 0: argument array length
+                               "0a", // input 0: first argument length
+                               "617267756d656e747331", // input 0: first argument data
+                               "0a", // input 0: second argument length
+                               "617267756d656e747332", // input 0: second argument data
+                               "01", // input 1: asset version
+                               "54", // input 1: input commitment length
+                               "01", // input 1: spend type flag
+                               "52", // input 1: spend commitment length
+                               "fad5195a0c8e3b590b86a3c0a95e7529565888508aecca96e9aeda633002f409", // input 1: source id
+                               "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", // input 1: assetID
+                               "92c30f", // input 1: amount
+                               "03",     // input 1: source position
+                               "01",     // input 1: vm version
+                               "0c",     // input 1: spend program length
+                               "7370656e6450726f6772616d", // input 1: spend program
+                               "17", // input 1: witness length
+                               "02", // input 1: argument array length
+                               "0a", // input 1: first argument length
+                               "617267756d656e747333", // input 1: first argument data
+                               "0a", // input 1: second argument length
+                               "617267756d656e747334", // input 1: second argument data
+                               "01", // outputs count
+                               "01", // output 0: asset version
+                               "29", // output 0: serialization length
+                               "a69849e11add96ac7053aad22ba2349a4abf5feb0475a0afcadff4e128be76cf", // output 0: assetID
+                               "92c30f",   // output 0: amount
+                               "01",       // output 0: version
+                               "04",       // output 0: control program length
+                               "74727565", // output 0: control program
+                               "00",       // output 0: witness length
+                       }, ""),
+                       hash: testutil.MustDecodeHash("a0ece5ca48dca27708394852599cb4d04af22c36538c03cb72663f3091406c17"),
+               },
+               {
+                       tx: NewTx(TxData{
+                               Version:        1,
+                               SerializedSize: uint64(108),
+                               Inputs: []*TxInput{
+                                       NewCoinbaseInput([]byte("arbitrary")),
+                               },
+                               Outputs: []*TxOutput{
+                                       NewTxOutput(*consensus.BTMAssetID, 254354, []byte("true")),
+                                       NewTxOutput(*consensus.BTMAssetID, 254354, []byte("false")),
+                               },
+                       }),
+                       hex: strings.Join([]string{
+                               "07",                 // serflags
+                               "01",                 // transaction version
+                               "00",                 // tx time range
+                               "01",                 // inputs count
+                               "01",                 // input 0: asset version
+                               "0b",                 // input 0: input commitment length
+                               "02",                 // input 0: coinbase type flag
+                               "09",                 // input 0: arbitrary length
+                               "617262697472617279", // input 0: arbitrary data
+                               "00",                 // input 0: witness length
+                               "02",                 // outputs count
+                               "01",                 // output 0: asset version
+                               "29",                 // output 0: serialization length
+                               "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", // output 0: assetID
+                               "92c30f",   // output 0: amount
+                               "01",       // output 0: version
+                               "04",       // output 0: control program length
+                               "74727565", // output 0: control program
+                               "00",       // output 0: witness length
+                               "01",       // output 1: asset version
+                               "2a",       // output 1: serialization length
+                               "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", // output 1: assetID
+                               "92c30f",     // output 1: amount
+                               "01",         // output 1: version
+                               "05",         // output 1: control program length
+                               "66616c7365", // output 1: control program
+                               "00",         // output 1: witness length
+                       }, ""),
+                       hash: testutil.MustDecodeHash("c2e2f388706fc06cca6aba5e85e0e85029f772872e1b6e6c32a70da22d0309dc"),
+               },
+       }
+       for i, test := range cases {
+               got := testutil.Serialize(t, test.tx)
+               want, err := hex.DecodeString(test.hex)
+               if err != nil {
+                       t.Fatal(err)
+               }
+
+               if !bytes.Equal(got, want) {
+                       t.Errorf("test %d: bytes = %x want %x", i, got, want)
+               }
+               if test.tx.ID != test.hash {
+                       t.Errorf("test %d: hash = %x want %x", i, test.tx.ID.Bytes(), test.hash.Bytes())
+               }
+
+               txJSON, err := json.Marshal(test.tx)
+               if err != nil {
+                       t.Errorf("test %d: error marshaling tx to json: %s", i, err)
+               }
+               txFromJSON := Tx{}
+               if err := json.Unmarshal(txJSON, &txFromJSON); err != nil {
+                       t.Errorf("test %d: error unmarshaling tx from json: %s", i, err)
+               }
+               if !testutil.DeepEqual(test.tx.TxData, txFromJSON.TxData) {
+                       t.Errorf("test %d: types.TxData -> json -> types.TxData: got:\n%s\nwant:\n%s", i, spew.Sdump(txFromJSON.TxData), spew.Sdump(test.tx.TxData))
+               }
+
+               tx1 := new(TxData)
+               if err := tx1.UnmarshalText([]byte(test.hex)); err != nil {
+                       t.Errorf("test %d: unexpected err %v", i, err)
+               }
+               if !testutil.DeepEqual(*tx1, test.tx.TxData) {
+                       t.Errorf("test %d: tx1 is:\n%swant:\n%s", i, spew.Sdump(*tx1), spew.Sdump(test.tx.TxData))
+               }
+       }
+}
+
+func TestTransactionTrailingGarbage(t *testing.T) {
+       // validTxHex is a valid tx, we don't care what's inside as long as it's valid
+       validTxHex := `07010001012b00030a0908916133a0d64d1d973b631e226ef95338ad4a536b95635f32f0d04708a6f2a26380a094a58d1d09000101010103010203010129000000000000000000000000000000000000000000000000000000000000000080a094a58d1d01010100`
+       validTx := Tx{}
+       if err := validTx.UnmarshalText([]byte(validTxHex)); err != nil {
+               t.Fatal(err)
+       }
+
+       invalidTxHex := validTxHex + strings.Repeat("00", 10)
+       invalidTx := Tx{}
+       if err := invalidTx.UnmarshalText([]byte(invalidTxHex)); err == nil {
+               t.Fatal("expected error with trailing garbage but got nil")
+       }
+}
+
+func TestInvalidIssuance(t *testing.T) {
+       hex := strings.Join([]string{
+               "07",     // serflags
+               "01",     // transaction version
+               "00",     // tx maxtime
+               "01",     // inputs count
+               "01",     // input 0, asset version
+               "2b",     // input 0, input commitment length prefix
+               "00",     // input 0, input commitment, "issuance" type
+               "03",     // input 0, input commitment, nonce length prefix
+               "0a0908", // input 0, input commitment, nonce
+               "0000000000000000000000000000000000000000000000000000000000000000", // input 0, input commitment, WRONG asset id
+               "80a094a58d1d", // input 0, input commitment, amount
+               "29",           // input 0, issuance input witness length prefix
+               "03deff1d4319d67baa10a6d26c1fea9c3e8d30e33474efee1a610a9bb49d758d", // input 0, issuance input witness, initial block
+               "00",     // input 0, issuance input witness, asset definition
+               "01",     // input 0, issuance input witness, vm version
+               "01",     // input 0, issuance input witness, issuance program length prefix
+               "01",     // input 0, issuance input witness, issuance program
+               "01",     // input 0, issuance input witness, arguments count
+               "03",     // input 0, issuance input witness, argument 0 length prefix
+               "010203", // input 0, issuance input witness, argument 0
+               "01",     // outputs count
+               "01",     // output 0, asset version
+               "29",     // output 0, output commitment length
+               "0000000000000000000000000000000000000000000000000000000000000000", // output 0, output commitment, asset id
+               "80a094a58d1d",   // output 0, output commitment, amount
+               "01",             // output 0, output commitment, vm version
+               "0101",           // output 0, output commitment, control program
+               "066f7574707574", // output 0, reference data
+               "00",             // output 0, output witness
+               "0869737375616e6365",
+       }, "")
+
+       tx := new(TxData)
+       if err := tx.UnmarshalText([]byte(hex)); errors.Root(err) != errBadAssetID {
+               t.Errorf("want errBadAssetID, got %v", err)
+       }
+}
+
+func TestFuzzUnknownAssetVersion(t *testing.T) {
+       rawTx := `07010001012b00030a0908916133a0d64d1d973b631e226ef95338ad4a536b95635f32f0d04708a6f2a26380a094a58d1d09000101010103010203010129000000000000000000000000000000000000000000000000000000000000000080a094a58d1d01010100`
+       want := Tx{}
+       if err := want.UnmarshalText([]byte(rawTx)); err != nil {
+               t.Fatal(err)
+       }
+
+       b, err := want.MarshalText()
+       if err != nil {
+               t.Fatal(err)
+       }
+
+       got := Tx{}
+       if err = got.UnmarshalText(b); err != nil {
+               t.Fatal(err)
+       }
+       if got.ID.String() != want.ID.String() {
+               t.Errorf("tx id changed to %s", got.ID.String())
+       }
+}
+
+func BenchmarkTxWriteToTrue(b *testing.B) {
+       tx := &Tx{}
+       for i := 0; i < b.N; i++ {
+               tx.writeTo(ioutil.Discard, 0)
+       }
+}
+
+func BenchmarkTxWriteToFalse(b *testing.B) {
+       tx := &Tx{}
+       for i := 0; i < b.N; i++ {
+               tx.writeTo(ioutil.Discard, serRequired)
+       }
+}
+
+func BenchmarkTxWriteToTrue200(b *testing.B) {
+       tx := &Tx{}
+       for i := 0; i < 200; i++ {
+               tx.Inputs = append(tx.Inputs, NewSpendInput(nil, bc.Hash{}, bc.AssetID{}, 0, 0, nil))
+               tx.Outputs = append(tx.Outputs, NewTxOutput(bc.AssetID{}, 0, nil))
+       }
+       for i := 0; i < b.N; i++ {
+               tx.writeTo(ioutil.Discard, 0)
+       }
+}
+
+func BenchmarkTxWriteToFalse200(b *testing.B) {
+       tx := &Tx{}
+       for i := 0; i < 200; i++ {
+               tx.Inputs = append(tx.Inputs, NewSpendInput(nil, bc.Hash{}, bc.AssetID{}, 0, 0, nil))
+               tx.Outputs = append(tx.Outputs, NewTxOutput(bc.AssetID{}, 0, nil))
+       }
+       for i := 0; i < b.N; i++ {
+               tx.writeTo(ioutil.Discard, serRequired)
+       }
+}
+
+func BenchmarkTxInputWriteToTrue(b *testing.B) {
+       input := NewSpendInput(nil, bc.Hash{}, bc.AssetID{}, 0, 0, nil)
+       ew := errors.NewWriter(ioutil.Discard)
+       for i := 0; i < b.N; i++ {
+               input.writeTo(ew)
+       }
+}
+
+func BenchmarkTxInputWriteToFalse(b *testing.B) {
+       input := NewSpendInput(nil, bc.Hash{}, bc.AssetID{}, 0, 0, nil)
+       ew := errors.NewWriter(ioutil.Discard)
+       for i := 0; i < b.N; i++ {
+               input.writeTo(ew)
+       }
+}
+
+func BenchmarkTxOutputWriteToTrue(b *testing.B) {
+       output := NewTxOutput(bc.AssetID{}, 0, nil)
+       ew := errors.NewWriter(ioutil.Discard)
+       for i := 0; i < b.N; i++ {
+               output.writeTo(ew)
+       }
+}
+
+func BenchmarkTxOutputWriteToFalse(b *testing.B) {
+       output := NewTxOutput(bc.AssetID{}, 0, nil)
+       ew := errors.NewWriter(ioutil.Discard)
+       for i := 0; i < b.N; i++ {
+               output.writeTo(ew)
+       }
+}
+
+func BenchmarkAssetAmountWriteTo(b *testing.B) {
+       aa := bc.AssetAmount{}
+       for i := 0; i < b.N; i++ {
+               aa.WriteTo(ioutil.Discard)
+       }
+}