11 "github.com/davecgh/go-spew/spew"
13 "github.com/bytom/bytom/consensus"
14 "github.com/bytom/bytom/errors"
15 "github.com/bytom/bytom/protocol/bc"
16 "github.com/bytom/bytom/testutil"
19 func TestTransaction(t *testing.T) {
28 SerializedSize: uint64(5),
32 hex: strings.Join([]string{
34 "01", // transaction version
35 "00", // tx time range
37 "00", // outputs count
39 hash: testutil.MustDecodeHash("8e88b9cb4615128c7209dff695f68b8de5b38648bf3d44d2d0e6a674848539c9"),
44 SerializedSize: uint64(284),
47 NewIssuanceInput([]byte("nonce"), 254354, []byte("issuanceProgram"), [][]byte{[]byte("arguments1"), []byte("arguments2")}, []byte("assetDefinition")),
48 NewSpendInput([][]byte{[]byte("arguments3"), []byte("arguments4")}, testutil.MustDecodeHash("fad5195a0c8e3b590b86a3c0a95e7529565888508aecca96e9aeda633002f409"), *consensus.BTMAssetID, 254354, 3, []byte("spendProgram"), [][]byte{[]byte("stateData")}),
51 NewOriginalTxOutput(testutil.MustDecodeAsset("a69849e11add96ac7053aad22ba2349a4abf5feb0475a0afcadff4e128be76cf"), 254354, []byte("true"), [][]byte{[]byte("stateData")}),
54 hex: strings.Join([]string{
56 "01", // transaction version
57 "8e05", // tx time range
59 "01", // input 0: asset version
60 "2a", // input 0: serialization length
61 "00", // input 0: issuance type flag
62 "05", // input 0: nonce length
63 "6e6f6e6365", // input 0: nonce
64 "a69849e11add96ac7053aad22ba2349a4abf5feb0475a0afcadff4e128be76cf", // input 0: assetID
65 "92c30f", // input 0: amount
66 "38", // input 0: input witness length
67 "0f", // input 0: asset definition length
68 "6173736574446566696e6974696f6e", // input 0: asset definition
69 "01", // input 0: vm version
70 "0f", // input 0: issuanceProgram length
71 "69737375616e636550726f6772616d", // input 0: issuance program
72 "02", // input 0: argument array length
73 "0a", // input 0: first argument length
74 "617267756d656e747331", // input 0: first argument data
75 "0a", // input 0: second argument length
76 "617267756d656e747332", // input 0: second argument data
77 "01", // input 1: asset version
78 "5f", // input 1: input commitment length
79 "01", // input 1: spend type flag
80 "5d", // input 1: spend commitment length
81 "fad5195a0c8e3b590b86a3c0a95e7529565888508aecca96e9aeda633002f409", // input 1: source id
82 "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", // input 1: assetID
83 "92c30f", // input 1: amount
84 "03", // input 1: source position
85 "01", // input 1: vm version
86 "0c", // input 1: spend program length
87 "7370656e6450726f6772616d", // input 1: spend program
88 "0109", // input 1: state data length
89 "737461746544617461", // input 1: state data
90 "17", // input 1: witness length
91 "02", // input 1: argument array length
92 "0a", // input 1: first argument length
93 "617267756d656e747333", // input 1: first argument data
94 "0a", // input 1: second argument length
95 "617267756d656e747334", // input 1: second argument data
96 "01", // outputs count
97 "01", // output 0: asset version
99 "34", // output 0: serialization length
100 "a69849e11add96ac7053aad22ba2349a4abf5feb0475a0afcadff4e128be76cf", // output 0: assetID
101 "92c30f", // output 0: amount
102 "01", // output 0: version
103 "04", // output 0: control program length
104 "74727565", // output 0: control program
105 "0109", // output 0: state data length
106 "737461746544617461", // output 0: state data
107 "00", // output 0: witness length
109 hash: testutil.MustDecodeHash("509632e139a418be372cd4b73c8de7b8aa5215c47848bf76ed2488d0a5c0c55e"),
114 SerializedSize: uint64(132),
116 NewCoinbaseInput([]byte("arbitrary")),
118 Outputs: []*TxOutput{
119 NewOriginalTxOutput(*consensus.BTMAssetID, 254354, []byte("true"), [][]byte{[]byte("stateData")}),
120 NewOriginalTxOutput(*consensus.BTMAssetID, 254354, []byte("false"), [][]byte{[]byte("stateData")}),
123 hex: strings.Join([]string{
125 "01", // transaction version
126 "00", // tx time range
127 "01", // inputs count
128 "01", // input 0: asset version
129 "0b", // input 0: input commitment length
130 "02", // input 0: coinbase type flag
131 "09", // input 0: arbitrary length
132 "617262697472617279", // input 0: arbitrary data
133 "00", // input 0: witness length
134 "02", // outputs count
135 "01", // output 0: asset version
137 "34", // output 0: serialization length
138 "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", // output 0: assetID
139 "92c30f", // output 0: amount
140 "01", // output 0: version
141 "04", // output 0: control program length
142 "74727565", // output 0: control program
143 "0109", // output 0: state data length
144 "737461746544617461", // output 0: state data
145 "00", // output 0: witness length
146 "01", // output 1: asset version
148 "35", // output 1: serialization length
149 "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", // output 1: assetID
150 "92c30f", // output 1: amount
151 "01", // output 1: version
152 "05", // output 1: control program length
153 "66616c7365", // output 1: control program
154 "0109", // output 0: state data length
155 "737461746544617461", // output 0: state data
156 "00", // output 1: witness length
158 hash: testutil.MustDecodeHash("4243fc12f6e8704c5e4318a2addc648d29fd1c03a8fe1246badafa5efd8b5339"),
161 for i, test := range cases {
162 got := testutil.Serialize(t, test.tx)
163 want, err := hex.DecodeString(test.hex)
168 if !bytes.Equal(got, want) {
169 t.Errorf("test %d: bytes = %x want %x", i, got, want)
171 if test.tx.ID != test.hash {
172 t.Errorf("test %d: hash = %x want %x", i, test.tx.ID.Bytes(), test.hash.Bytes())
175 txJSON, err := json.Marshal(test.tx)
177 t.Errorf("test %d: error marshaling tx to json: %s", i, err)
180 if err := json.Unmarshal(txJSON, &txFromJSON); err != nil {
181 t.Errorf("test %d: error unmarshaling tx from json: %s", i, err)
183 if !testutil.DeepEqual(test.tx.TxData, txFromJSON.TxData) {
184 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))
188 if err := tx1.UnmarshalText([]byte(test.hex)); err != nil {
189 t.Errorf("test %d: unexpected err %v", i, err)
191 if !testutil.DeepEqual(*tx1, test.tx.TxData) {
192 t.Errorf("test %d: tx1 is:\n%swant:\n%s", i, spew.Sdump(*tx1), spew.Sdump(test.tx.TxData))
197 func TestTransactionTrailingGarbage(t *testing.T) {
198 // validTxHex is a valid tx, we don't care what's inside as long as it's valid
199 validTxHex := `07010001012b00030a0908916133a0d64d1d973b631e226ef95338ad4a536b95635f32f0d04708a6f2a26380a094a58d1d090001010101030102030101002a000000000000000000000000000000000000000000000000000000000000000080a094a58d1d0101010000`
201 if err := validTx.UnmarshalText([]byte(validTxHex)); err != nil {
205 invalidTxHex := validTxHex + strings.Repeat("00", 10)
207 if err := invalidTx.UnmarshalText([]byte(invalidTxHex)); err == nil {
208 t.Fatal("expected error with trailing garbage but got nil")
212 func TestInvalidIssuance(t *testing.T) {
213 hex := strings.Join([]string{
215 "01", // transaction version
217 "01", // inputs count
218 "01", // input 0, asset version
219 "2b", // input 0, input commitment length prefix
220 "00", // input 0, input commitment, "issuance" type
221 "03", // input 0, input commitment, nonce length prefix
222 "0a0908", // input 0, input commitment, nonce
223 "0000000000000000000000000000000000000000000000000000000000000000", // input 0, input commitment, WRONG asset id
224 "80a094a58d1d", // input 0, input commitment, amount
225 "29", // input 0, issuance input witness length prefix
226 "03deff1d4319d67baa10a6d26c1fea9c3e8d30e33474efee1a610a9bb49d758d", // input 0, issuance input witness, initial block
227 "00", // input 0, issuance input witness, asset definition
228 "01", // input 0, issuance input witness, vm version
229 "01", // input 0, issuance input witness, issuance program length prefix
230 "01", // input 0, issuance input witness, issuance program
231 "01", // input 0, issuance input witness, arguments count
232 "03", // input 0, issuance input witness, argument 0 length prefix
233 "010203", // input 0, issuance input witness, argument 0
234 "01", // outputs count
235 "01", // output 0, asset version
236 "29", // output 0, output commitment length
237 "0000000000000000000000000000000000000000000000000000000000000000", // output 0, output commitment, asset id
238 "80a094a58d1d", // output 0, output commitment, amount
239 "01", // output 0, output commitment, vm version
240 "0101", // output 0, output commitment, control program
241 "066f7574707574", // output 0, reference data
242 "00", // output 0, output witness
243 "0869737375616e6365",
247 if err := tx.UnmarshalText([]byte(hex)); errors.Root(err) != errBadAssetID {
248 t.Errorf("want errBadAssetID, got %v", err)
252 func TestFuzzUnknownAssetVersion(t *testing.T) {
253 rawTx := `07010001012b00030a0908916133a0d64d1d973b631e226ef95338ad4a536b95635f32f0d04708a6f2a26380a094a58d1d090001010101030102030101002a000000000000000000000000000000000000000000000000000000000000000080a094a58d1d0101010000`
264 916133a0d64d1d973b631e226ef95338ad4a536b95635f32f0d04708a6f2a263
266 0101010103010203010100
268 0000000000000000000000000000000000000000000000000000000000000000
276 if err := want.UnmarshalText([]byte(rawTx)); err != nil {
280 b, err := want.MarshalText()
286 if err = got.UnmarshalText(b); err != nil {
289 if got.ID.String() != want.ID.String() {
290 t.Errorf("tx id changed to %s", got.ID.String())
294 func BenchmarkTxWriteToTrue(b *testing.B) {
296 for i := 0; i < b.N; i++ {
297 tx.writeTo(ioutil.Discard, 0)
301 func BenchmarkTxWriteToFalse(b *testing.B) {
303 for i := 0; i < b.N; i++ {
304 tx.writeTo(ioutil.Discard, serRequired)
308 func BenchmarkTxWriteToTrue200(b *testing.B) {
310 for i := 0; i < 200; i++ {
311 tx.Inputs = append(tx.Inputs, NewSpendInput(nil, bc.Hash{}, bc.AssetID{}, 0, 0, nil, nil))
312 tx.Outputs = append(tx.Outputs, NewOriginalTxOutput(bc.AssetID{}, 0, nil, nil))
314 for i := 0; i < b.N; i++ {
315 tx.writeTo(ioutil.Discard, 0)
319 func BenchmarkTxWriteToFalse200(b *testing.B) {
321 for i := 0; i < 200; i++ {
322 tx.Inputs = append(tx.Inputs, NewSpendInput(nil, bc.Hash{}, bc.AssetID{}, 0, 0, nil, nil))
323 tx.Outputs = append(tx.Outputs, NewOriginalTxOutput(bc.AssetID{}, 0, nil, nil))
325 for i := 0; i < b.N; i++ {
326 tx.writeTo(ioutil.Discard, serRequired)
330 func BenchmarkTxInputWriteToTrue(b *testing.B) {
331 input := NewSpendInput(nil, bc.Hash{}, bc.AssetID{}, 0, 0, nil, nil)
332 ew := errors.NewWriter(ioutil.Discard)
333 for i := 0; i < b.N; i++ {
338 func BenchmarkTxInputWriteToFalse(b *testing.B) {
339 input := NewSpendInput(nil, bc.Hash{}, bc.AssetID{}, 0, 0, nil, nil)
340 ew := errors.NewWriter(ioutil.Discard)
341 for i := 0; i < b.N; i++ {
346 func BenchmarkTxOutputWriteToTrue(b *testing.B) {
347 output := NewOriginalTxOutput(bc.AssetID{}, 0, nil, nil)
348 ew := errors.NewWriter(ioutil.Discard)
349 for i := 0; i < b.N; i++ {
354 func BenchmarkTxOutputWriteToFalse(b *testing.B) {
355 output := NewOriginalTxOutput(bc.AssetID{}, 0, nil, nil)
356 ew := errors.NewWriter(ioutil.Discard)
357 for i := 0; i < b.N; i++ {
362 func BenchmarkAssetAmountWriteTo(b *testing.B) {
363 aa := bc.AssetAmount{}
364 for i := 0; i < b.N; i++ {
365 aa.WriteTo(ioutil.Discard)