11 "github.com/davecgh/go-spew/spew"
13 "github.com/bytom/errors"
14 "github.com/bytom/protocol/bc"
15 "github.com/bytom/testutil"
18 func TestTransactionTrailingGarbage(t *testing.T) {
19 const validTxHex = `07010000000101270eac870dfde1e0feaa4fac6693dee38da2afe7f5cc83ce2b024f04a2400fd6e20a0104deadbeef027b7d0000`
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)
50 SerializedSize: uint64(7),
55 hex: ("07" + // serflags
56 "01" + // transaction version
58 "00" + // common witness extensible string length
59 "00" + // inputs count
60 "00" + // outputs count
61 "00"), // reference data
62 hash: mustDecodeHash("196ffe40c99e0c25bc2b7347db147e626a13132a8d404b92e270ec6e8df24234"),
67 SerializedSize: uint64(159),
69 NewIssuanceInput([]byte{10, 9, 8}, 1000000000000, []byte("input"), initialBlockHash, issuanceScript, [][]byte{[]byte{1, 2, 3}}, nil),
72 NewTxOutput(bc.AssetID{}, 1000000000000, []byte{1}, []byte("output")),
74 ReferenceData: []byte("issuance"),
76 hex: ("07" + // serflags
77 "01" + // transaction version
79 "00" + // common witness extensible string length
80 "01" + // inputs count
81 "01" + // input 0, asset version
82 "2b" + // input 0, input commitment length prefix
83 "00" + // input 0, input commitment, "issuance" type
84 "03" + // input 0, input commitment, nonce length prefix
85 "0a0908" + // input 0, input commitment, nonce
86 assetID.String() + // input 0, input commitment, asset id
87 "80a094a58d1d" + // input 0, input commitment, amount
88 "05696e707574" + // input 0, reference data
89 "29" + // input 0, issuance input witness length prefix
90 initialBlockHashHex + // input 0, issuance input witness, initial block
91 "00" + // input 0, issuance input witness, asset definition
92 "01" + // input 0, issuance input witness, vm version
93 "01" + // input 0, issuance input witness, issuance program length prefix
94 "01" + // input 0, issuance input witness, issuance program
95 "01" + // input 0, issuance input witness, arguments count
96 "03" + // input 0, issuance input witness, argument 0 length prefix
97 "010203" + // input 0, issuance input witness, argument 0
98 "01" + // outputs count
99 "01" + // output 0, asset version
100 "29" + // output 0, output commitment length
101 "0000000000000000000000000000000000000000000000000000000000000000" + // output 0, output commitment, asset id
102 "80a094a58d1d" + // output 0, output commitment, amount
103 "01" + // output 0, output commitment, vm version
104 "0101" + // output 0, output commitment, control program
105 "066f7574707574" + // output 0, reference data
106 "00" + // output 0, output witness
107 "0869737375616e6365"), // reference data
108 hash: mustDecodeHash("7a9e4f4b87d8af099081d0dfec77fe33ccf288d586308d8a14a640b72ca474f8"),
113 SerializedSize: uint64(227),
115 NewSpendInput(nil, mustDecodeHash("dd385f6fe25d91d8c1bd0fa58951ad56b0c5229dcc01f61d9f9e8b9eb92d3292"), bc.AssetID{}, 1000000000000, 1, []byte{1}, bc.Hash{}, []byte("input")),
117 Outputs: []*TxOutput{
118 NewTxOutput(assetID, 600000000000, []byte{1}, nil),
119 NewTxOutput(assetID, 400000000000, []byte{2}, nil),
121 ReferenceData: []byte("distribution"),
123 hex: ("07" + // serflags
124 "01" + // transaction version
126 "00" + // common witness extensible string length
127 "01" + // inputs count
128 "01" + // input 0, asset version
129 "6c" + // input 0, input commitment length prefix
130 "01" + // input 0, input commitment, "spend" type+
131 "6a" + // input 0, spend input commitment, spend commitment length prefix
132 "dd385f6fe25d91d8c1bd0fa58951ad56b0c5229dcc01f61d9f9e8b9eb92d3292" + // input 0, spend input commitment, spend commitment, source ID
133 "0000000000000000000000000000000000000000000000000000000000000000" + // input 0, spend input commitment, spend commitment, asset id
134 "80a094a58d1d" + // input 0, spend input commitment, spend commitment, amount
135 "01" + // input 0, spend input commitment, spend commitment, source position
136 "01" + // input 0, spend input commitment, spend commitment, vm version
137 "0101" + // input 0, spend input commitment, spend commitment, control program
138 "0000000000000000000000000000000000000000000000000000000000000000" + // input 0, spend input commitment, spend commitment, reference data hash
139 "05696e707574" + // input 0, reference data
140 "01" + // input 0, input witness length prefix
141 "00" + // input 0, input witness, number of args
142 "02" + // outputs count
143 "01" + // output 0, asset version
144 "29" + // output 0, output commitment length
145 "a9b2b6c5394888ab5396f583ae484b8459486b14268e2bef1b637440335eb6c1" + // output 0, output commitment, asset id
146 "80e0a596bb11" + // output 0, output commitment, amount
147 "01" + // output 0, output commitment, vm version
148 "0101" + // output 0, output commitment, control program
149 "00" + // output 0, reference data
150 "00" + // output 0, output witness
151 "01" + // output 1, asset version
152 "29" + // output 1, output commitment length
153 "a9b2b6c5394888ab5396f583ae484b8459486b14268e2bef1b637440335eb6c1" + // output 1, output commitment, asset id
154 "80c0ee8ed20b" + // output 1, output commitment, amount
155 "01" + // output 1, vm version
156 "0102" + // output 1, output commitment, control program
157 "00" + // output 1, reference data
158 "00" + // output 1, output witness
159 "0c646973747269627574696f6e"), // reference data
160 hash: mustDecodeHash("4074fc31692af33defcee32189eaa8cb6219db259883707009b048d7165812ca"),
163 for i, test := range cases {
164 got := serialize(t, test.tx)
165 want, _ := hex.DecodeString(test.hex)
166 if !bytes.Equal(got, want) {
167 t.Errorf("test %d: bytes = %x want %x", i, got, want)
169 if test.tx.ID != test.hash {
170 t.Errorf("test %d: hash = %x want %x", i, test.tx.ID.Bytes(), test.hash.Bytes())
173 txJSON, err := json.Marshal(test.tx)
175 t.Errorf("test %d: error marshaling tx to json: %s", i, err)
178 if err := json.Unmarshal(txJSON, &txFromJSON); err != nil {
179 t.Errorf("test %d: error unmarshaling tx from json: %s", i, err)
181 if !testutil.DeepEqual(test.tx.TxData, txFromJSON.TxData) {
182 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))
186 if err := tx1.UnmarshalText([]byte(test.hex)); err != nil {
187 t.Errorf("test %d: unexpected err %v", i, err)
189 if !testutil.DeepEqual(*tx1, test.tx.TxData) {
190 t.Errorf("test %d: tx1 is:\n%swant:\n%s", i, spew.Sdump(*tx1), spew.Sdump(test.tx.TxData))
195 func TestHasIssuance(t *testing.T) {
201 Inputs: []*TxInput{NewIssuanceInput(nil, 0, nil, bc.Hash{}, nil, nil, nil)},
207 NewSpendInput(nil, bc.Hash{}, bc.AssetID{}, 0, 0, nil, bc.Hash{}, nil),
208 NewIssuanceInput(nil, 0, nil, bc.Hash{}, nil, nil, nil),
215 NewSpendInput(nil, bc.Hash{}, bc.AssetID{}, 0, 0, nil, bc.Hash{}, nil),
224 for _, c := range cases {
225 got := c.tx.HasIssuance()
227 t.Errorf("HasIssuance(%+v) = %v want %v", c.tx, got, c.want)
232 func TestInvalidIssuance(t *testing.T) {
233 hex := ("07" + // serflags
234 "01" + // transaction version
236 "00" + // common witness extensible string length
237 "01" + // inputs count
238 "01" + // input 0, asset version
239 "2b" + // input 0, input commitment length prefix
240 "00" + // input 0, input commitment, "issuance" type
241 "03" + // input 0, input commitment, nonce length prefix
242 "0a0908" + // input 0, input commitment, nonce
243 "0000000000000000000000000000000000000000000000000000000000000000" + // input 0, input commitment, WRONG asset id
244 "80a094a58d1d" + // input 0, input commitment, amount
245 "05696e707574" + // input 0, reference data
246 "29" + // input 0, issuance input witness length prefix
247 "03deff1d4319d67baa10a6d26c1fea9c3e8d30e33474efee1a610a9bb49d758d" + // input 0, issuance input witness, initial block
248 "00" + // input 0, issuance input witness, asset definition
249 "01" + // input 0, issuance input witness, vm version
250 "01" + // input 0, issuance input witness, issuance program length prefix
251 "01" + // input 0, issuance input witness, issuance program
252 "01" + // input 0, issuance input witness, arguments count
253 "03" + // input 0, issuance input witness, argument 0 length prefix
254 "010203" + // input 0, issuance input witness, argument 0
255 "01" + // outputs count
256 "01" + // output 0, asset version
257 "29" + // output 0, output commitment length
258 "0000000000000000000000000000000000000000000000000000000000000000" + // output 0, output commitment, asset id
259 "80a094a58d1d" + // output 0, output commitment, amount
260 "01" + // output 0, output commitment, vm version
261 "0101" + // output 0, output commitment, control program
262 "066f7574707574" + // output 0, reference data
263 "00" + // output 0, output witness
264 "0869737375616e6365")
266 err := tx.UnmarshalText([]byte(hex))
267 if errors.Root(err) != errBadAssetID {
268 t.Errorf("want errBadAssetID, got %v", err)
272 func BenchmarkTxWriteToTrue(b *testing.B) {
274 for i := 0; i < b.N; i++ {
275 tx.writeTo(ioutil.Discard, 0)
279 func BenchmarkTxWriteToFalse(b *testing.B) {
281 for i := 0; i < b.N; i++ {
282 tx.writeTo(ioutil.Discard, serRequired)
286 func BenchmarkTxWriteToTrue200(b *testing.B) {
288 for i := 0; i < 200; i++ {
289 tx.Inputs = append(tx.Inputs, NewSpendInput(nil, bc.Hash{}, bc.AssetID{}, 0, 0, nil, bc.Hash{}, nil))
290 tx.Outputs = append(tx.Outputs, NewTxOutput(bc.AssetID{}, 0, nil, nil))
292 for i := 0; i < b.N; i++ {
293 tx.writeTo(ioutil.Discard, 0)
297 func BenchmarkTxWriteToFalse200(b *testing.B) {
299 for i := 0; i < 200; i++ {
300 tx.Inputs = append(tx.Inputs, NewSpendInput(nil, bc.Hash{}, bc.AssetID{}, 0, 0, nil, bc.Hash{}, nil))
301 tx.Outputs = append(tx.Outputs, NewTxOutput(bc.AssetID{}, 0, nil, nil))
303 for i := 0; i < b.N; i++ {
304 tx.writeTo(ioutil.Discard, serRequired)
308 func BenchmarkTxInputWriteToTrue(b *testing.B) {
309 input := NewSpendInput(nil, bc.Hash{}, bc.AssetID{}, 0, 0, nil, bc.Hash{}, nil)
310 ew := errors.NewWriter(ioutil.Discard)
311 for i := 0; i < b.N; i++ {
316 func BenchmarkTxInputWriteToFalse(b *testing.B) {
317 input := NewSpendInput(nil, bc.Hash{}, bc.AssetID{}, 0, 0, nil, bc.Hash{}, nil)
318 ew := errors.NewWriter(ioutil.Discard)
319 for i := 0; i < b.N; i++ {
320 input.writeTo(ew, serRequired)
324 func BenchmarkTxOutputWriteToTrue(b *testing.B) {
325 output := NewTxOutput(bc.AssetID{}, 0, nil, nil)
326 ew := errors.NewWriter(ioutil.Discard)
327 for i := 0; i < b.N; i++ {
328 output.writeTo(ew, 0)
332 func BenchmarkTxOutputWriteToFalse(b *testing.B) {
333 output := NewTxOutput(bc.AssetID{}, 0, nil, nil)
334 ew := errors.NewWriter(ioutil.Discard)
335 for i := 0; i < b.N; i++ {
336 output.writeTo(ew, serRequired)
340 func BenchmarkAssetAmountWriteTo(b *testing.B) {
341 aa := bc.AssetAmount{}
342 for i := 0; i < b.N; i++ {
343 aa.WriteTo(ioutil.Discard)