11 "github.com/davecgh/go-spew/spew"
13 "github.com/blockchain/errors"
14 "github.com/blockchain/protocol/bc"
15 "github.com/blockchain/testutil"
18 func TestTransactionTrailingGarbage(t *testing.T) {
19 const validTxHex = `07010700d0929893b92b00000101270eac870dfde1e0feaa4fac6693dee38da2afe7f5cc83ce2b024f04a2400fd6e20a0104deadbeef027b7d0000`
22 err := validTx.UnmarshalText([]byte(validTxHex))
27 invalidTxHex := validTxHex + strings.Repeat("beef", 10)
29 err = invalidTx.UnmarshalText([]byte(invalidTxHex))
31 t.Fatal("expected error with trailing garbage but got nil")
35 func TestTransaction(t *testing.T) {
36 issuanceScript := []byte{1}
37 initialBlockHashHex := "03deff1d4319d67baa10a6d26c1fea9c3e8d30e33474efee1a610a9bb49d758d"
38 initialBlockHash := mustDecodeHash(initialBlockHashHex)
40 assetID := bc.ComputeAssetID(issuanceScript, &initialBlockHash, 1, &bc.EmptyStringHash)
56 hex: ("07" + // serflags
57 "01" + // transaction version
58 "02" + // common fields extensible string length
59 "00" + // common fields, mintime
60 "00" + // common fields, maxtime
61 "00" + // common witness extensible string length
62 "00" + // inputs count
63 "00" + // outputs count
64 "00"), // reference data
65 hash: mustDecodeHash("7ae6eef6b02fe61d35cc185405aec5f690ccb0ac291ecd6214445a1dff8fc9fd"),
71 NewIssuanceInput([]byte{10, 9, 8}, 1000000000000, []byte("input"), initialBlockHash, issuanceScript, [][]byte{[]byte{1, 2, 3}}, nil),
74 NewTxOutput(bc.AssetID{}, 1000000000000, []byte{1}, []byte("output")),
78 ReferenceData: []byte("issuance"),
80 hex: ("07" + // serflags
81 "01" + // transaction version
82 "02" + // common fields extensible string length
83 "00" + // common fields, mintime
84 "00" + // common fields, maxtime
85 "00" + // common witness extensible string length
86 "01" + // inputs count
87 "01" + // input 0, asset version
88 "2b" + // input 0, input commitment length prefix
89 "00" + // input 0, input commitment, "issuance" type
90 "03" + // input 0, input commitment, nonce length prefix
91 "0a0908" + // input 0, input commitment, nonce
92 assetID.String() + // input 0, input commitment, asset id
93 "80a094a58d1d" + // input 0, input commitment, amount
94 "05696e707574" + // input 0, reference data
95 "29" + // input 0, issuance input witness length prefix
96 initialBlockHashHex + // input 0, issuance input witness, initial block
97 "00" + // input 0, issuance input witness, asset definition
98 "01" + // input 0, issuance input witness, vm version
99 "01" + // input 0, issuance input witness, issuance program length prefix
100 "01" + // input 0, issuance input witness, issuance program
101 "01" + // input 0, issuance input witness, arguments count
102 "03" + // input 0, issuance input witness, argument 0 length prefix
103 "010203" + // input 0, issuance input witness, argument 0
104 "01" + // outputs count
105 "01" + // output 0, asset version
106 "29" + // output 0, output commitment length
107 "0000000000000000000000000000000000000000000000000000000000000000" + // output 0, output commitment, asset id
108 "80a094a58d1d" + // output 0, output commitment, amount
109 "01" + // output 0, output commitment, vm version
110 "0101" + // output 0, output commitment, control program
111 "066f7574707574" + // output 0, reference data
112 "00" + // output 0, output witness
113 "0869737375616e6365"), // reference data
114 hash: mustDecodeHash("cd4669d5363374f8661621273501c23e613fc98b0fab9d5d858f30e16ccd24ce"),
120 NewSpendInput(nil, mustDecodeHash("dd385f6fe25d91d8c1bd0fa58951ad56b0c5229dcc01f61d9f9e8b9eb92d3292"), bc.AssetID{}, 1000000000000, 1, []byte{1}, bc.Hash{}, []byte("input")),
122 Outputs: []*TxOutput{
123 NewTxOutput(assetID, 600000000000, []byte{1}, nil),
124 NewTxOutput(assetID, 400000000000, []byte{2}, nil),
128 ReferenceData: []byte("distribution"),
130 hex: ("07" + // serflags
131 "01" + // transaction version
132 "0a" + // common fields extensible string length
134 "b0bbdcc705" + // common fields, mintime
135 "ffbfdcc705" + // common fields, maxtime
136 "00" + // common witness extensible string length
137 "01" + // inputs count
138 "01" + // input 0, asset version
139 "6c" + // input 0, input commitment length prefix
140 "01" + // input 0, input commitment, "spend" type+
141 "6a" + // input 0, spend input commitment, spend commitment length prefix
142 "dd385f6fe25d91d8c1bd0fa58951ad56b0c5229dcc01f61d9f9e8b9eb92d3292" + // input 0, spend input commitment, spend commitment, source ID
143 "0000000000000000000000000000000000000000000000000000000000000000" + // input 0, spend input commitment, spend commitment, asset id
144 "80a094a58d1d" + // input 0, spend input commitment, spend commitment, amount
145 "01" + // input 0, spend input commitment, spend commitment, source position
146 "01" + // input 0, spend input commitment, spend commitment, vm version
147 "0101" + // input 0, spend input commitment, spend commitment, control program
148 "0000000000000000000000000000000000000000000000000000000000000000" + // input 0, spend input commitment, spend commitment, reference data hash
149 "05696e707574" + // input 0, reference data
150 "01" + // input 0, input witness length prefix
151 "00" + // input 0, input witness, number of args
152 "02" + // outputs count
153 "01" + // output 0, asset version
154 "29" + // output 0, output commitment length
155 "a9b2b6c5394888ab5396f583ae484b8459486b14268e2bef1b637440335eb6c1" + // output 0, output commitment, asset id
156 "80e0a596bb11" + // output 0, output commitment, amount
157 "01" + // output 0, output commitment, vm version
158 "0101" + // output 0, output commitment, control program
159 "00" + // output 0, reference data
160 "00" + // output 0, output witness
161 "01" + // output 1, asset version
162 "29" + // output 1, output commitment length
163 "a9b2b6c5394888ab5396f583ae484b8459486b14268e2bef1b637440335eb6c1" + // output 1, output commitment, asset id
164 "80c0ee8ed20b" + // output 1, output commitment, amount
165 "01" + // output 1, vm version
166 "0102" + // output 1, output commitment, control program
167 "00" + // output 1, reference data
168 "00" + // output 1, output witness
169 "0c646973747269627574696f6e"), // reference data
170 hash: mustDecodeHash("c328ad4278045b4c50e8af7e7d0df198e7d9436d2b5de35df1339f13a1192331"),
183 //dd385f6fe25d91d8c1bd0fa58951ad56b0c5229dcc01f61d9f9e8b9eb92d3292
185 //0000000000000000000000000000000000000000000000000000000000000000
195 //a9b2b6c5394888ab5396f583ae484b8459486b14268e2bef1b637440335eb6c1
203 //a9b2b6c5394888ab5396f583ae484b8459486b14268e2bef1b637440335eb6c1
209 //0c646973747269627574696f6e
212 for i, test := range cases {
213 got := serialize(t, test.tx)
214 want, _ := hex.DecodeString(test.hex)
215 if !bytes.Equal(got, want) {
216 t.Errorf("test %d: bytes = %x want %x", i, got, want)
218 if test.tx.ID != test.hash {
219 t.Errorf("test %d: hash = %x want %x", i, test.tx.ID.Bytes(), test.hash.Bytes())
222 txJSON, err := json.Marshal(test.tx)
224 t.Errorf("test %d: error marshaling tx to json: %s", i, err)
227 if err := json.Unmarshal(txJSON, &txFromJSON); err != nil {
228 t.Errorf("test %d: error unmarshaling tx from json: %s", i, err)
230 if !testutil.DeepEqual(test.tx.TxData, txFromJSON.TxData) {
231 t.Errorf("test %d: legacy.TxData -> json -> legacy.TxData: got:\n%s\nwant:\n%s", i, spew.Sdump(txFromJSON.TxData), spew.Sdump(test.tx.TxData))
235 if err := tx1.UnmarshalText([]byte(test.hex)); err != nil {
236 t.Errorf("test %d: unexpected err %v", i, err)
238 if !testutil.DeepEqual(*tx1, test.tx.TxData) {
239 t.Errorf("test %d: tx1 is:\n%swant:\n%s", i, spew.Sdump(*tx1), spew.Sdump(test.tx.TxData))
244 func TestHasIssuance(t *testing.T) {
250 Inputs: []*TxInput{NewIssuanceInput(nil, 0, nil, bc.Hash{}, nil, nil, nil)},
256 NewSpendInput(nil, bc.Hash{}, bc.AssetID{}, 0, 0, nil, bc.Hash{}, nil),
257 NewIssuanceInput(nil, 0, nil, bc.Hash{}, nil, nil, nil),
264 NewSpendInput(nil, bc.Hash{}, bc.AssetID{}, 0, 0, nil, bc.Hash{}, nil),
273 for _, c := range cases {
274 got := c.tx.HasIssuance()
276 t.Errorf("HasIssuance(%+v) = %v want %v", c.tx, got, c.want)
281 func TestInvalidIssuance(t *testing.T) {
282 hex := ("07" + // serflags
283 "01" + // transaction version
284 "02" + // common fields extensible string length
285 "00" + // common fields, mintime
286 "00" + // common fields, maxtime
287 "00" + // common witness extensible string length
288 "01" + // inputs count
289 "01" + // input 0, asset version
290 "2b" + // input 0, input commitment length prefix
291 "00" + // input 0, input commitment, "issuance" type
292 "03" + // input 0, input commitment, nonce length prefix
293 "0a0908" + // input 0, input commitment, nonce
294 "0000000000000000000000000000000000000000000000000000000000000000" + // input 0, input commitment, WRONG asset id
295 "80a094a58d1d" + // input 0, input commitment, amount
296 "05696e707574" + // input 0, reference data
297 "29" + // input 0, issuance input witness length prefix
298 "03deff1d4319d67baa10a6d26c1fea9c3e8d30e33474efee1a610a9bb49d758d" + // input 0, issuance input witness, initial block
299 "00" + // input 0, issuance input witness, asset definition
300 "01" + // input 0, issuance input witness, vm version
301 "01" + // input 0, issuance input witness, issuance program length prefix
302 "01" + // input 0, issuance input witness, issuance program
303 "01" + // input 0, issuance input witness, arguments count
304 "03" + // input 0, issuance input witness, argument 0 length prefix
305 "010203" + // input 0, issuance input witness, argument 0
306 "01" + // outputs count
307 "01" + // output 0, asset version
308 "29" + // output 0, output commitment length
309 "0000000000000000000000000000000000000000000000000000000000000000" + // output 0, output commitment, asset id
310 "80a094a58d1d" + // output 0, output commitment, amount
311 "01" + // output 0, output commitment, vm version
312 "0101" + // output 0, output commitment, control program
313 "066f7574707574" + // output 0, reference data
314 "00" + // output 0, output witness
315 "0869737375616e6365")
317 err := tx.UnmarshalText([]byte(hex))
318 if errors.Root(err) != errBadAssetID {
319 t.Errorf("want errBadAssetID, got %v", err)
323 func BenchmarkTxWriteToTrue(b *testing.B) {
325 for i := 0; i < b.N; i++ {
326 tx.writeTo(ioutil.Discard, 0)
330 func BenchmarkTxWriteToFalse(b *testing.B) {
332 for i := 0; i < b.N; i++ {
333 tx.writeTo(ioutil.Discard, serRequired)
337 func BenchmarkTxWriteToTrue200(b *testing.B) {
339 for i := 0; i < 200; i++ {
340 tx.Inputs = append(tx.Inputs, NewSpendInput(nil, bc.Hash{}, bc.AssetID{}, 0, 0, nil, bc.Hash{}, nil))
341 tx.Outputs = append(tx.Outputs, NewTxOutput(bc.AssetID{}, 0, nil, nil))
343 for i := 0; i < b.N; i++ {
344 tx.writeTo(ioutil.Discard, 0)
348 func BenchmarkTxWriteToFalse200(b *testing.B) {
350 for i := 0; i < 200; i++ {
351 tx.Inputs = append(tx.Inputs, NewSpendInput(nil, bc.Hash{}, bc.AssetID{}, 0, 0, nil, bc.Hash{}, nil))
352 tx.Outputs = append(tx.Outputs, NewTxOutput(bc.AssetID{}, 0, nil, nil))
354 for i := 0; i < b.N; i++ {
355 tx.writeTo(ioutil.Discard, serRequired)
359 func BenchmarkTxInputWriteToTrue(b *testing.B) {
360 input := NewSpendInput(nil, bc.Hash{}, bc.AssetID{}, 0, 0, nil, bc.Hash{}, nil)
361 ew := errors.NewWriter(ioutil.Discard)
362 for i := 0; i < b.N; i++ {
367 func BenchmarkTxInputWriteToFalse(b *testing.B) {
368 input := NewSpendInput(nil, bc.Hash{}, bc.AssetID{}, 0, 0, nil, bc.Hash{}, nil)
369 ew := errors.NewWriter(ioutil.Discard)
370 for i := 0; i < b.N; i++ {
371 input.writeTo(ew, serRequired)
375 func BenchmarkTxOutputWriteToTrue(b *testing.B) {
376 output := NewTxOutput(bc.AssetID{}, 0, nil, nil)
377 ew := errors.NewWriter(ioutil.Discard)
378 for i := 0; i < b.N; i++ {
379 output.writeTo(ew, 0)
383 func BenchmarkTxOutputWriteToFalse(b *testing.B) {
384 output := NewTxOutput(bc.AssetID{}, 0, nil, nil)
385 ew := errors.NewWriter(ioutil.Discard)
386 for i := 0; i < b.N; i++ {
387 output.writeTo(ew, serRequired)
391 func BenchmarkAssetAmountWriteTo(b *testing.B) {
392 aa := bc.AssetAmount{}
393 for i := 0; i < b.N; i++ {
394 aa.WriteTo(ioutil.Discard)