OSDN Git Service

edht tx txoutput (#1966)
[bytom/bytom.git] / protocol / state / utxo_view_test.go
1 package state
2
3 import (
4         "fmt"
5         "testing"
6
7         "github.com/bytom/bytom/consensus"
8         "github.com/bytom/bytom/database/storage"
9         "github.com/bytom/bytom/protocol/bc"
10         "github.com/bytom/bytom/testutil"
11 )
12
13 var defaultEntry = map[bc.Hash]bc.Entry{
14         bc.Hash{V0: 0}: &bc.OriginalOutput{
15                 Source: &bc.ValueSource{
16                         Value: &bc.AssetAmount{
17                                 AssetId: &bc.AssetID{V0: 0},
18                         },
19                 },
20         },
21 }
22
23 var gasOnlyTxEntry = map[bc.Hash]bc.Entry{
24         bc.Hash{V1: 0}: &bc.OriginalOutput{
25                 Source: &bc.ValueSource{
26                         Value: &bc.AssetAmount{
27                                 AssetId: consensus.BTMAssetID,
28                         },
29                 },
30         },
31         bc.Hash{V1: 1}: &bc.OriginalOutput{
32                 Source: &bc.ValueSource{
33                         Value: &bc.AssetAmount{
34                                 AssetId: &bc.AssetID{V0: 999},
35                         },
36                 },
37         },
38 }
39
40 func TestApplyBlock(t *testing.T) {
41         cases := []struct {
42                 block     *bc.Block
43                 inputView *UtxoViewpoint
44                 fetchView *UtxoViewpoint
45                 gasOnlyTx bool
46                 err       bool
47         }{
48                 {
49                         // can't find prevout in tx entries
50                         block: &bc.Block{
51                                 BlockHeader: &bc.BlockHeader{},
52                                 Transactions: []*bc.Tx{
53                                         &bc.Tx{
54                                                 SpentOutputIDs: []bc.Hash{
55                                                         bc.Hash{V0: 1},
56                                                 },
57                                                 Entries: defaultEntry,
58                                         },
59                                 },
60                         },
61                         inputView: &UtxoViewpoint{
62                                 Entries: map[bc.Hash]*storage.UtxoEntry{
63                                         bc.Hash{V0: 0}: storage.NewUtxoEntry(false, 0, false),
64                                 },
65                         },
66                         fetchView: NewUtxoViewpoint(),
67                         err:       true,
68                 },
69                 {
70                         block: &bc.Block{
71                                 BlockHeader: &bc.BlockHeader{},
72                                 Transactions: []*bc.Tx{
73                                         &bc.Tx{
74                                                 SpentOutputIDs: []bc.Hash{
75                                                         bc.Hash{V0: 0},
76                                                 },
77                                                 Entries: defaultEntry,
78                                         },
79                                 },
80                         },
81                         inputView: NewUtxoViewpoint(),
82                         fetchView: NewUtxoViewpoint(),
83                         err:       true,
84                 },
85                 {
86                         block: &bc.Block{
87                                 BlockHeader: &bc.BlockHeader{},
88                                 Transactions: []*bc.Tx{
89                                         &bc.Tx{
90                                                 SpentOutputIDs: []bc.Hash{
91                                                         bc.Hash{V0: 0},
92                                                 },
93                                                 Entries: defaultEntry,
94                                         },
95                                 },
96                         },
97                         inputView: &UtxoViewpoint{
98                                 Entries: map[bc.Hash]*storage.UtxoEntry{
99                                         bc.Hash{V0: 0}: storage.NewUtxoEntry(false, 0, true),
100                                 },
101                         },
102                         err: true,
103                 },
104                 {
105                         block: &bc.Block{
106                                 BlockHeader: &bc.BlockHeader{},
107                                 Transactions: []*bc.Tx{
108                                         &bc.Tx{
109                                                 TxHeader: &bc.TxHeader{
110                                                         ResultIds: []*bc.Hash{},
111                                                 },
112                                                 SpentOutputIDs: []bc.Hash{
113                                                         bc.Hash{V0: 0},
114                                                 },
115                                                 Entries: defaultEntry,
116                                         },
117                                 },
118                         },
119                         inputView: &UtxoViewpoint{
120                                 Entries: map[bc.Hash]*storage.UtxoEntry{
121                                         bc.Hash{V0: 0}: storage.NewUtxoEntry(false, 0, false),
122                                 },
123                         },
124                         fetchView: &UtxoViewpoint{
125                                 Entries: map[bc.Hash]*storage.UtxoEntry{
126                                         bc.Hash{V0: 0}: storage.NewUtxoEntry(false, 0, true),
127                                 },
128                         },
129                         err: false,
130                 },
131                 {
132                         block: &bc.Block{
133                                 BlockHeader: &bc.BlockHeader{
134                                         Height: 101,
135                                 },
136                                 Transactions: []*bc.Tx{
137                                         &bc.Tx{
138                                                 TxHeader: &bc.TxHeader{
139                                                         ResultIds: []*bc.Hash{},
140                                                 },
141                                                 SpentOutputIDs: []bc.Hash{
142                                                         bc.Hash{V0: 0},
143                                                 },
144                                                 Entries: defaultEntry,
145                                         },
146                                 },
147                         },
148                         inputView: &UtxoViewpoint{
149                                 Entries: map[bc.Hash]*storage.UtxoEntry{
150                                         bc.Hash{V0: 0}: storage.NewUtxoEntry(true, 0, false),
151                                 },
152                         },
153                         fetchView: &UtxoViewpoint{
154                                 Entries: map[bc.Hash]*storage.UtxoEntry{
155                                         bc.Hash{V0: 0}: storage.NewUtxoEntry(true, 0, true),
156                                 },
157                         },
158                         err: false,
159                 },
160                 {
161                         block: &bc.Block{
162                                 BlockHeader: &bc.BlockHeader{
163                                         Height: 0,
164                                 },
165                                 Transactions: []*bc.Tx{
166                                         &bc.Tx{
167                                                 TxHeader: &bc.TxHeader{
168                                                         ResultIds: []*bc.Hash{},
169                                                 },
170                                                 SpentOutputIDs: []bc.Hash{
171                                                         bc.Hash{V0: 0},
172                                                 },
173                                                 Entries: defaultEntry,
174                                         },
175                                 },
176                         },
177                         inputView: &UtxoViewpoint{
178                                 Entries: map[bc.Hash]*storage.UtxoEntry{
179                                         bc.Hash{V0: 0}: storage.NewUtxoEntry(true, 0, false),
180                                 },
181                         },
182                         fetchView: &UtxoViewpoint{
183                                 Entries: map[bc.Hash]*storage.UtxoEntry{
184                                         bc.Hash{V0: 0}: storage.NewUtxoEntry(true, 0, true),
185                                 },
186                         },
187                         err: true,
188                 },
189                 {
190                         // output will be store
191                         block: &bc.Block{
192                                 BlockHeader: &bc.BlockHeader{},
193                                 Transactions: []*bc.Tx{
194                                         &bc.Tx{
195                                                 TxHeader: &bc.TxHeader{
196                                                         ResultIds: []*bc.Hash{
197                                                                 &bc.Hash{V0: 0},
198                                                         },
199                                                 },
200                                                 SpentOutputIDs: []bc.Hash{},
201                                                 Entries:        defaultEntry,
202                                         },
203                                 },
204                         },
205                         inputView: NewUtxoViewpoint(),
206                         fetchView: &UtxoViewpoint{
207                                 Entries: map[bc.Hash]*storage.UtxoEntry{
208                                         bc.Hash{V0: 0}: storage.NewUtxoEntry(true, 0, false),
209                                 },
210                         },
211                         err: false,
212                 },
213                 {
214                         // non-btm asset spent input will be spent
215                         block: &bc.Block{
216                                 BlockHeader: &bc.BlockHeader{},
217                                 Transactions: []*bc.Tx{
218                                         &bc.Tx{
219                                                 TxHeader: &bc.TxHeader{
220                                                         ResultIds: []*bc.Hash{},
221                                                 },
222                                                 SpentOutputIDs: []bc.Hash{
223                                                         bc.Hash{V1: 0},
224                                                         bc.Hash{V1: 1},
225                                                 },
226                                                 Entries: gasOnlyTxEntry,
227                                         },
228                                 },
229                         },
230                         inputView: &UtxoViewpoint{
231                                 Entries: map[bc.Hash]*storage.UtxoEntry{
232                                         bc.Hash{V1: 0}: storage.NewUtxoEntry(false, 0, false),
233                                         bc.Hash{V1: 1}: storage.NewUtxoEntry(false, 0, false),
234                                 },
235                         },
236                         fetchView: &UtxoViewpoint{
237                                 Entries: map[bc.Hash]*storage.UtxoEntry{
238                                         bc.Hash{V1: 0}: storage.NewUtxoEntry(false, 0, true),
239                                         bc.Hash{V1: 1}: storage.NewUtxoEntry(false, 0, true),
240                                 },
241                         },
242                         err: false,
243                 },
244                 {
245                         // apply gas only tx, non-btm asset spent output will not be store
246                         block: &bc.Block{
247                                 BlockHeader: &bc.BlockHeader{},
248                                 Transactions: []*bc.Tx{
249                                         &bc.Tx{
250                                                 TxHeader: &bc.TxHeader{
251                                                         ResultIds: []*bc.Hash{
252                                                                 &bc.Hash{V1: 0},
253                                                                 &bc.Hash{V1: 1},
254                                                         },
255                                                 },
256                                                 SpentOutputIDs: []bc.Hash{},
257                                                 Entries:        gasOnlyTxEntry,
258                                         },
259                                 },
260                         },
261                         inputView: NewUtxoViewpoint(),
262                         fetchView: &UtxoViewpoint{
263                                 Entries: map[bc.Hash]*storage.UtxoEntry{
264                                         bc.Hash{V1: 0}: storage.NewUtxoEntry(true, 0, false),
265                                         bc.Hash{V1: 1}: storage.NewUtxoEntry(true, 0, false),
266                                 },
267                         },
268                         err: false,
269                 },
270         }
271
272         for i, c := range cases {
273                 if err := c.inputView.ApplyBlock(c.block); c.err != (err != nil) {
274                         t.Errorf("case #%d want err = %v, get err = %v", i, c.err, err)
275                 }
276                 if c.err {
277                         continue
278                 }
279                 if !testutil.DeepEqual(c.inputView, c.fetchView) {
280                         t.Errorf("test case %d, want %v, get %v", i, c.fetchView, c.inputView)
281                 }
282         }
283 }
284
285 func TestDetachBlock(t *testing.T) {
286         cases := []struct {
287                 block     *bc.Block
288                 inputView *UtxoViewpoint
289                 fetchView *UtxoViewpoint
290                 gasOnlyTx bool
291                 err       bool
292         }{
293                 {
294                         block: &bc.Block{
295                                 BlockHeader: &bc.BlockHeader{},
296                                 Transactions: []*bc.Tx{
297                                         &bc.Tx{
298                                                 TxHeader: &bc.TxHeader{
299                                                         ResultIds: []*bc.Hash{},
300                                                 },
301                                                 SpentOutputIDs: []bc.Hash{
302                                                         bc.Hash{V0: 0},
303                                                 },
304                                                 Entries: defaultEntry,
305                                         },
306                                 },
307                         },
308                         inputView: NewUtxoViewpoint(),
309                         fetchView: &UtxoViewpoint{
310                                 Entries: map[bc.Hash]*storage.UtxoEntry{
311                                         bc.Hash{V0: 0}: storage.NewUtxoEntry(false, 0, false),
312                                 },
313                         },
314                         err: false,
315                 },
316                 {
317                         block: &bc.Block{
318                                 BlockHeader: &bc.BlockHeader{},
319                                 Transactions: []*bc.Tx{
320                                         &bc.Tx{
321                                                 TxHeader: &bc.TxHeader{
322                                                         ResultIds: []*bc.Hash{
323                                                                 &bc.Hash{V0: 0},
324                                                         },
325                                                 },
326                                                 SpentOutputIDs: []bc.Hash{},
327                                                 Entries:        defaultEntry,
328                                         },
329                                 },
330                         },
331                         inputView: NewUtxoViewpoint(),
332                         fetchView: &UtxoViewpoint{
333                                 Entries: map[bc.Hash]*storage.UtxoEntry{
334                                         bc.Hash{V0: 0}: storage.NewUtxoEntry(false, 0, true),
335                                 },
336                         },
337                         err: false,
338                 },
339                 {
340                         block: &bc.Block{
341                                 BlockHeader: &bc.BlockHeader{},
342                                 Transactions: []*bc.Tx{
343                                         &bc.Tx{
344                                                 TxHeader: &bc.TxHeader{
345                                                         ResultIds: []*bc.Hash{},
346                                                 },
347                                                 SpentOutputIDs: []bc.Hash{
348                                                         bc.Hash{V0: 0},
349                                                 },
350                                                 Entries: defaultEntry,
351                                         },
352                                 },
353                         },
354                         inputView: &UtxoViewpoint{
355                                 Entries: map[bc.Hash]*storage.UtxoEntry{
356                                         bc.Hash{V0: 0}: storage.NewUtxoEntry(false, 0, false),
357                                 },
358                         },
359                         err: true,
360                 },
361                 {
362                         block: &bc.Block{
363                                 BlockHeader: &bc.BlockHeader{},
364                                 Transactions: []*bc.Tx{
365                                         &bc.Tx{
366                                                 TxHeader: &bc.TxHeader{
367                                                         ResultIds: []*bc.Hash{},
368                                                 },
369                                                 SpentOutputIDs: []bc.Hash{
370                                                         bc.Hash{V0: 0},
371                                                 },
372                                                 Entries: defaultEntry,
373                                         },
374                                 },
375                         },
376                         inputView: &UtxoViewpoint{
377                                 Entries: map[bc.Hash]*storage.UtxoEntry{
378                                         bc.Hash{V0: 0}: storage.NewUtxoEntry(false, 0, true),
379                                 },
380                         },
381                         fetchView: &UtxoViewpoint{
382                                 Entries: map[bc.Hash]*storage.UtxoEntry{
383                                         bc.Hash{V0: 0}: storage.NewUtxoEntry(false, 0, false),
384                                 },
385                         },
386                         err: false,
387                 },
388         }
389
390         for i, c := range cases {
391                 if err := c.inputView.DetachBlock(c.block); c.err != (err != nil) {
392                         t.Errorf("case %d want err = %v, get err = %v", i, c.err, err)
393                 }
394                 if c.err {
395                         continue
396                 }
397                 if !testutil.DeepEqual(c.inputView, c.fetchView) {
398                         for hash, entry := range c.inputView.Entries {
399                                 fmt.Println(hash.String(), ":", entry.String())
400                         }
401
402                         for hash, entry := range c.fetchView.Entries {
403                                 fmt.Println(hash.String(), ":", entry.String())
404                         }
405
406                         t.Errorf("test case %d, want %v, get %v", i, c.fetchView, c.inputView)
407                 }
408         }
409 }