11 "github.com/davecgh/go-spew/spew"
13 "github.com/bytom/consensus"
14 "github.com/bytom/errors"
15 "github.com/bytom/protocol/bc"
16 "github.com/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(261),
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")),
51 NewTxOutput(testutil.MustDecodeAsset("a69849e11add96ac7053aad22ba2349a4abf5feb0475a0afcadff4e128be76cf"), 254354, []byte("true")),
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 "54", // input 1: input commitment length
79 "01", // input 1: spend type flag
80 "52", // 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 "17", // input 1: witness length
89 "02", // input 1: argument array length
90 "0a", // input 1: first argument length
91 "617267756d656e747333", // input 1: first argument data
92 "0a", // input 1: second argument length
93 "617267756d656e747334", // input 1: second argument data
94 "01", // outputs count
95 "01", // output 0: asset version
96 "29", // output 0: serialization length
97 "a69849e11add96ac7053aad22ba2349a4abf5feb0475a0afcadff4e128be76cf", // output 0: assetID
98 "92c30f", // output 0: amount
99 "01", // output 0: version
100 "04", // output 0: control program length
101 "74727565", // output 0: control program
102 "00", // output 0: witness length
104 hash: testutil.MustDecodeHash("a0ece5ca48dca27708394852599cb4d04af22c36538c03cb72663f3091406c17"),
109 SerializedSize: uint64(108),
111 NewCoinbaseInput([]byte("arbitrary")),
113 Outputs: []*TxOutput{
114 NewTxOutput(*consensus.BTMAssetID, 254354, []byte("true")),
115 NewTxOutput(*consensus.BTMAssetID, 254354, []byte("false")),
118 hex: strings.Join([]string{
120 "01", // transaction version
121 "00", // tx time range
122 "01", // inputs count
123 "01", // input 0: asset version
124 "0b", // input 0: input commitment length
125 "02", // input 0: coinbase type flag
126 "09", // input 0: arbitrary length
127 "617262697472617279", // input 0: arbitrary data
128 "00", // input 0: witness length
129 "02", // outputs count
130 "01", // output 0: asset version
131 "29", // output 0: serialization length
132 "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", // output 0: assetID
133 "92c30f", // output 0: amount
134 "01", // output 0: version
135 "04", // output 0: control program length
136 "74727565", // output 0: control program
137 "00", // output 0: witness length
138 "01", // output 1: asset version
139 "2a", // output 1: serialization length
140 "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", // output 1: assetID
141 "92c30f", // output 1: amount
142 "01", // output 1: version
143 "05", // output 1: control program length
144 "66616c7365", // output 1: control program
145 "00", // output 1: witness length
147 hash: testutil.MustDecodeHash("c2e2f388706fc06cca6aba5e85e0e85029f772872e1b6e6c32a70da22d0309dc"),
150 for i, test := range cases {
151 got := testutil.Serialize(t, test.tx)
152 want, err := hex.DecodeString(test.hex)
157 if !bytes.Equal(got, want) {
158 t.Errorf("test %d: bytes = %x want %x", i, got, want)
160 if test.tx.ID != test.hash {
161 t.Errorf("test %d: hash = %x want %x", i, test.tx.ID.Bytes(), test.hash.Bytes())
164 txJSON, err := json.Marshal(test.tx)
166 t.Errorf("test %d: error marshaling tx to json: %s", i, err)
169 if err := json.Unmarshal(txJSON, &txFromJSON); err != nil {
170 t.Errorf("test %d: error unmarshaling tx from json: %s", i, err)
172 if !testutil.DeepEqual(test.tx.TxData, txFromJSON.TxData) {
173 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))
177 if err := tx1.UnmarshalText([]byte(test.hex)); err != nil {
178 t.Errorf("test %d: unexpected err %v", i, err)
180 if !testutil.DeepEqual(*tx1, test.tx.TxData) {
181 t.Errorf("test %d: tx1 is:\n%swant:\n%s", i, spew.Sdump(*tx1), spew.Sdump(test.tx.TxData))
186 func TestTransactionTrailingGarbage(t *testing.T) {
187 // validTxHex is a valid tx, we don't care what's inside as long as it's valid
188 validTxHex := `07010001012b00030a0908916133a0d64d1d973b631e226ef95338ad4a536b95635f32f0d04708a6f2a26380a094a58d1d09000101010103010203010129000000000000000000000000000000000000000000000000000000000000000080a094a58d1d01010100`
190 if err := validTx.UnmarshalText([]byte(validTxHex)); err != nil {
194 invalidTxHex := validTxHex + strings.Repeat("00", 10)
196 if err := invalidTx.UnmarshalText([]byte(invalidTxHex)); err == nil {
197 t.Fatal("expected error with trailing garbage but got nil")
201 func TestInvalidIssuance(t *testing.T) {
202 hex := strings.Join([]string{
204 "01", // transaction version
206 "01", // inputs count
207 "01", // input 0, asset version
208 "2b", // input 0, input commitment length prefix
209 "00", // input 0, input commitment, "issuance" type
210 "03", // input 0, input commitment, nonce length prefix
211 "0a0908", // input 0, input commitment, nonce
212 "0000000000000000000000000000000000000000000000000000000000000000", // input 0, input commitment, WRONG asset id
213 "80a094a58d1d", // input 0, input commitment, amount
214 "29", // input 0, issuance input witness length prefix
215 "03deff1d4319d67baa10a6d26c1fea9c3e8d30e33474efee1a610a9bb49d758d", // input 0, issuance input witness, initial block
216 "00", // input 0, issuance input witness, asset definition
217 "01", // input 0, issuance input witness, vm version
218 "01", // input 0, issuance input witness, issuance program length prefix
219 "01", // input 0, issuance input witness, issuance program
220 "01", // input 0, issuance input witness, arguments count
221 "03", // input 0, issuance input witness, argument 0 length prefix
222 "010203", // input 0, issuance input witness, argument 0
223 "01", // outputs count
224 "01", // output 0, asset version
225 "29", // output 0, output commitment length
226 "0000000000000000000000000000000000000000000000000000000000000000", // output 0, output commitment, asset id
227 "80a094a58d1d", // output 0, output commitment, amount
228 "01", // output 0, output commitment, vm version
229 "0101", // output 0, output commitment, control program
230 "066f7574707574", // output 0, reference data
231 "00", // output 0, output witness
232 "0869737375616e6365",
236 if err := tx.UnmarshalText([]byte(hex)); errors.Root(err) != errBadAssetID {
237 t.Errorf("want errBadAssetID, got %v", err)
241 func TestFuzzUnknownAssetVersion(t *testing.T) {
242 rawTx := `07010001012b00030a0908916133a0d64d1d973b631e226ef95338ad4a536b95635f32f0d04708a6f2a26380a094a58d1d09000101010103010203010129000000000000000000000000000000000000000000000000000000000000000080a094a58d1d01010100`
244 if err := want.UnmarshalText([]byte(rawTx)); err != nil {
248 b, err := want.MarshalText()
254 if err = got.UnmarshalText(b); err != nil {
257 if got.ID.String() != want.ID.String() {
258 t.Errorf("tx id changed to %s", got.ID.String())
262 func BenchmarkTxWriteToTrue(b *testing.B) {
264 for i := 0; i < b.N; i++ {
265 tx.writeTo(ioutil.Discard, 0)
269 func BenchmarkTxWriteToFalse(b *testing.B) {
271 for i := 0; i < b.N; i++ {
272 tx.writeTo(ioutil.Discard, serRequired)
276 func BenchmarkTxWriteToTrue200(b *testing.B) {
278 for i := 0; i < 200; i++ {
279 tx.Inputs = append(tx.Inputs, NewSpendInput(nil, bc.Hash{}, bc.AssetID{}, 0, 0, nil))
280 tx.Outputs = append(tx.Outputs, NewTxOutput(bc.AssetID{}, 0, nil))
282 for i := 0; i < b.N; i++ {
283 tx.writeTo(ioutil.Discard, 0)
287 func BenchmarkTxWriteToFalse200(b *testing.B) {
289 for i := 0; i < 200; i++ {
290 tx.Inputs = append(tx.Inputs, NewSpendInput(nil, bc.Hash{}, bc.AssetID{}, 0, 0, nil))
291 tx.Outputs = append(tx.Outputs, NewTxOutput(bc.AssetID{}, 0, nil))
293 for i := 0; i < b.N; i++ {
294 tx.writeTo(ioutil.Discard, serRequired)
298 func BenchmarkTxInputWriteToTrue(b *testing.B) {
299 input := NewSpendInput(nil, bc.Hash{}, bc.AssetID{}, 0, 0, nil)
300 ew := errors.NewWriter(ioutil.Discard)
301 for i := 0; i < b.N; i++ {
306 func BenchmarkTxInputWriteToFalse(b *testing.B) {
307 input := NewSpendInput(nil, bc.Hash{}, bc.AssetID{}, 0, 0, nil)
308 ew := errors.NewWriter(ioutil.Discard)
309 for i := 0; i < b.N; i++ {
314 func BenchmarkTxOutputWriteToTrue(b *testing.B) {
315 output := NewTxOutput(bc.AssetID{}, 0, nil)
316 ew := errors.NewWriter(ioutil.Discard)
317 for i := 0; i < b.N; i++ {
322 func BenchmarkTxOutputWriteToFalse(b *testing.B) {
323 output := NewTxOutput(bc.AssetID{}, 0, nil)
324 ew := errors.NewWriter(ioutil.Discard)
325 for i := 0; i < b.N; i++ {
330 func BenchmarkAssetAmountWriteTo(b *testing.B) {
331 aa := bc.AssetAmount{}
332 for i := 0; i < b.N; i++ {
333 aa.WriteTo(ioutil.Discard)