OSDN Git Service

add_new_casper_for_chain (#1931)
[bytom/bytom.git] / test / utxo_view / utxo_view_test.go
1 package utxo_view
2
3 import (
4         "os"
5         "testing"
6
7         "github.com/golang/protobuf/proto"
8
9         "github.com/bytom/bytom/database"
10         dbm "github.com/bytom/bytom/database/leveldb"
11         "github.com/bytom/bytom/database/storage"
12         "github.com/bytom/bytom/protocol/bc"
13         "github.com/bytom/bytom/protocol/bc/types"
14         "github.com/bytom/bytom/protocol/state"
15         "github.com/bytom/bytom/testutil"
16 )
17
18 func TestAttachOrDetachBlocks(t *testing.T) {
19         cases := []struct {
20                 desc           string
21                 before         map[bc.Hash]*storage.UtxoEntry
22                 want           map[bc.Hash]*storage.UtxoEntry
23                 attachBlock    []*bc.Block
24                 detachBlock    []*bc.Block
25                 attachTxStatus []*bc.TransactionStatus
26                 detachTxStatus []*bc.TransactionStatus
27         }{
28                 {
29                         desc:   "coinbase tx",
30                         before: make(map[bc.Hash]*storage.UtxoEntry),
31                         want:   map[bc.Hash]*storage.UtxoEntry{*newTx(mockBlocks[0].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(true, mockBlocks[0].Block.Height, false)},
32                         attachBlock: []*bc.Block{
33                                 types.MapBlock(&mockBlocks[0].Block),
34                         },
35                         attachTxStatus: []*bc.TransactionStatus{
36                                 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
37                                         &bc.TxVerifyResult{StatusFail: false},
38                                 }},
39                         },
40                 },
41                 {
42                         desc: "Chain trading 3",
43                         before: map[bc.Hash]*storage.UtxoEntry{
44                                 newTx(mockBlocks[1].Transactions[1]).getSpentOutputID(0): storage.NewUtxoEntry(false, mockBlocks[1].Height-1, false),
45                         },
46                         want: map[bc.Hash]*storage.UtxoEntry{
47                                 *newTx(mockBlocks[1].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(true, mockBlocks[1].Height, false),
48                                 *newTx(mockBlocks[1].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[1].Height, false),
49                                 *newTx(mockBlocks[1].Transactions[2]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[1].Height, false),
50                                 *newTx(mockBlocks[1].Transactions[3]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[1].Height, false),
51                                 *newTx(mockBlocks[1].Transactions[3]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[1].Height, false),
52                         },
53                         attachBlock: []*bc.Block{
54                                 types.MapBlock(&mockBlocks[1].Block),
55                         },
56                         attachTxStatus: []*bc.TransactionStatus{
57                                 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
58                                         &bc.TxVerifyResult{StatusFail: false},
59                                         &bc.TxVerifyResult{StatusFail: false},
60                                         &bc.TxVerifyResult{StatusFail: false},
61                                         &bc.TxVerifyResult{StatusFail: false},
62                                 }},
63                         },
64                 },
65                 {
66                         desc: "detach 1 block, attach 2 block",
67                         before: map[bc.Hash]*storage.UtxoEntry{
68                                 *newTx(mockBlocks[2].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(true, mockBlocks[2].Height, false),
69                                 *newTx(mockBlocks[2].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[2].Height, false),
70                                 *newTx(mockBlocks[2].Transactions[1]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[2].Height, false),
71                         },
72                         want: map[bc.Hash]*storage.UtxoEntry{
73                                 *newTx(mockBlocks[3].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(true, mockBlocks[3].Height, false),
74                                 *newTx(mockBlocks[3].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[3].Height, false),
75
76                                 *newTx(mockBlocks[4].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(true, mockBlocks[4].Height, false),
77                                 *newTx(mockBlocks[4].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[4].Height, false),
78                                 *newTx(mockBlocks[4].Transactions[1]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[4].Height, false),
79                         },
80                         attachBlock: []*bc.Block{
81                                 types.MapBlock(&mockBlocks[3].Block),
82                                 types.MapBlock(&mockBlocks[4].Block),
83                         },
84                         detachBlock: []*bc.Block{
85                                 types.MapBlock(&mockBlocks[2].Block),
86                         },
87                         attachTxStatus: []*bc.TransactionStatus{
88                                 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
89                                         &bc.TxVerifyResult{StatusFail: false},
90                                         &bc.TxVerifyResult{StatusFail: false},
91                                 }},
92                                 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
93                                         &bc.TxVerifyResult{StatusFail: false},
94                                         &bc.TxVerifyResult{StatusFail: false},
95                                 }},
96                         },
97                         detachTxStatus: []*bc.TransactionStatus{
98                                 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
99                                         &bc.TxVerifyResult{StatusFail: false},
100                                         &bc.TxVerifyResult{StatusFail: false},
101                                 }},
102                         },
103                 },
104                 {
105                         desc: "detach block 5, attach block 2",
106                         before: map[bc.Hash]*storage.UtxoEntry{
107                                 *newTx(mockBlocks[5].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(true, mockBlocks[5].Height, false),
108                                 *newTx(mockBlocks[5].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[5].Height, false),
109                                 *newTx(mockBlocks[5].Transactions[1]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[5].Height, false),
110
111                                 *newTx(mockBlocks[6].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(true, mockBlocks[6].Height, false),
112                                 *newTx(mockBlocks[6].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[6].Height, false),
113                                 *newTx(mockBlocks[6].Transactions[1]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[6].Height, false),
114                                 *newTx(mockBlocks[6].Transactions[1]).OutputHash(2): storage.NewUtxoEntry(false, mockBlocks[6].Height, false),
115                                 *newTx(mockBlocks[6].Transactions[1]).OutputHash(3): storage.NewUtxoEntry(false, mockBlocks[6].Height, false),
116                                 *newTx(mockBlocks[6].Transactions[2]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[6].Height, false),
117                                 *newTx(mockBlocks[6].Transactions[2]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[6].Height, false),
118                                 *newTx(mockBlocks[6].Transactions[2]).OutputHash(2): storage.NewUtxoEntry(false, mockBlocks[6].Height, false),
119                                 *newTx(mockBlocks[6].Transactions[2]).OutputHash(3): storage.NewUtxoEntry(false, mockBlocks[6].Height, false),
120
121                                 *newTx(mockBlocks[7].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(true, mockBlocks[7].Height, false),
122                                 *newTx(mockBlocks[7].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[7].Height, false),
123                                 *newTx(mockBlocks[7].Transactions[1]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[7].Height, false),
124                                 *newTx(mockBlocks[7].Transactions[1]).OutputHash(2): storage.NewUtxoEntry(false, mockBlocks[7].Height, false),
125                                 *newTx(mockBlocks[7].Transactions[1]).OutputHash(3): storage.NewUtxoEntry(false, mockBlocks[7].Height, false),
126
127                                 *newTx(mockBlocks[8].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(true, mockBlocks[8].Height, false),
128                                 *newTx(mockBlocks[8].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[8].Height, false),
129                                 *newTx(mockBlocks[8].Transactions[1]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[8].Height, false),
130                                 *newTx(mockBlocks[8].Transactions[1]).OutputHash(2): storage.NewUtxoEntry(false, mockBlocks[8].Height, false),
131                                 *newTx(mockBlocks[8].Transactions[1]).OutputHash(3): storage.NewUtxoEntry(false, mockBlocks[8].Height, false),
132                                 *newTx(mockBlocks[8].Transactions[2]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[8].Height, false),
133                                 *newTx(mockBlocks[8].Transactions[2]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[8].Height, false),
134                                 *newTx(mockBlocks[8].Transactions[3]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[8].Height, false),
135                                 *newTx(mockBlocks[8].Transactions[3]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[8].Height, false),
136
137                                 *newTx(mockBlocks[9].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(true, mockBlocks[9].Height, false),
138                                 *newTx(mockBlocks[9].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[9].Height, false),
139                                 *newTx(mockBlocks[9].Transactions[1]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[9].Height, false),
140                         },
141                         want: map[bc.Hash]*storage.UtxoEntry{
142                                 *newTx(mockBlocks[10].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(true, mockBlocks[10].Height, false),
143                                 *newTx(mockBlocks[10].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[10].Height, false),
144                                 *newTx(mockBlocks[10].Transactions[1]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[10].Height, false),
145                                 *newTx(mockBlocks[10].Transactions[2]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[10].Height, false),
146                                 *newTx(mockBlocks[10].Transactions[2]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[10].Height, false),
147                                 *newTx(mockBlocks[10].Transactions[2]).OutputHash(2): storage.NewUtxoEntry(false, mockBlocks[10].Height, false),
148                                 *newTx(mockBlocks[10].Transactions[2]).OutputHash(3): storage.NewUtxoEntry(false, mockBlocks[10].Height, false),
149                                 *newTx(mockBlocks[10].Transactions[3]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[10].Height, false),
150                                 *newTx(mockBlocks[10].Transactions[3]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[10].Height, false),
151                                 *newTx(mockBlocks[10].Transactions[3]).OutputHash(2): storage.NewUtxoEntry(false, mockBlocks[10].Height, false),
152                                 *newTx(mockBlocks[10].Transactions[3]).OutputHash(3): storage.NewUtxoEntry(false, mockBlocks[10].Height, false),
153                                 *newTx(mockBlocks[10].Transactions[4]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[10].Height, false),
154                                 *newTx(mockBlocks[10].Transactions[4]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[10].Height, false),
155                                 *newTx(mockBlocks[10].Transactions[4]).OutputHash(2): storage.NewUtxoEntry(false, mockBlocks[10].Height, false),
156                                 *newTx(mockBlocks[10].Transactions[4]).OutputHash(3): storage.NewUtxoEntry(false, mockBlocks[10].Height, false),
157                                 *newTx(mockBlocks[10].Transactions[5]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[10].Height, false),
158                                 *newTx(mockBlocks[10].Transactions[5]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[10].Height, false),
159                                 *newTx(mockBlocks[10].Transactions[5]).OutputHash(2): storage.NewUtxoEntry(false, mockBlocks[10].Height, false),
160                                 *newTx(mockBlocks[10].Transactions[5]).OutputHash(3): storage.NewUtxoEntry(false, mockBlocks[10].Height, false),
161
162                                 *newTx(mockBlocks[11].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(true, mockBlocks[11].Height, false),
163                                 *newTx(mockBlocks[11].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[11].Height, false),
164                                 *newTx(mockBlocks[11].Transactions[1]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[11].Height, false),
165                                 *newTx(mockBlocks[11].Transactions[2]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[11].Height, false),
166                                 *newTx(mockBlocks[11].Transactions[2]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[11].Height, false),
167                                 *newTx(mockBlocks[11].Transactions[3]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[11].Height, false),
168                                 *newTx(mockBlocks[11].Transactions[3]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[11].Height, false),
169                         },
170                         attachBlock: []*bc.Block{
171                                 types.MapBlock(&mockBlocks[10].Block),
172                                 types.MapBlock(&mockBlocks[11].Block),
173                         },
174                         detachBlock: []*bc.Block{
175                                 types.MapBlock(&mockBlocks[9].Block),
176                                 types.MapBlock(&mockBlocks[8].Block),
177                                 types.MapBlock(&mockBlocks[7].Block),
178                                 types.MapBlock(&mockBlocks[6].Block),
179                                 types.MapBlock(&mockBlocks[5].Block),
180                         },
181                         attachTxStatus: []*bc.TransactionStatus{
182                                 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
183                                         &bc.TxVerifyResult{StatusFail: false},
184                                         &bc.TxVerifyResult{StatusFail: false},
185                                         &bc.TxVerifyResult{StatusFail: false},
186                                         &bc.TxVerifyResult{StatusFail: false},
187                                         &bc.TxVerifyResult{StatusFail: false},
188                                         &bc.TxVerifyResult{StatusFail: false},
189                                 }},
190                                 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
191                                         &bc.TxVerifyResult{StatusFail: false},
192                                         &bc.TxVerifyResult{StatusFail: false},
193                                         &bc.TxVerifyResult{StatusFail: false},
194                                         &bc.TxVerifyResult{StatusFail: false},
195                                         &bc.TxVerifyResult{StatusFail: false},
196                                 }},
197                         },
198                         detachTxStatus: []*bc.TransactionStatus{
199
200                                 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
201                                         &bc.TxVerifyResult{StatusFail: false},
202                                         &bc.TxVerifyResult{StatusFail: false},
203                                 }},
204                                 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
205                                         &bc.TxVerifyResult{StatusFail: false},
206                                         &bc.TxVerifyResult{StatusFail: false},
207                                         &bc.TxVerifyResult{StatusFail: false},
208                                         &bc.TxVerifyResult{StatusFail: false},
209                                 }},
210                                 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
211                                         &bc.TxVerifyResult{StatusFail: false},
212                                         &bc.TxVerifyResult{StatusFail: false},
213                                 }},
214                                 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
215                                         &bc.TxVerifyResult{StatusFail: false},
216                                         &bc.TxVerifyResult{StatusFail: false},
217                                         &bc.TxVerifyResult{StatusFail: false},
218                                 }},
219                                 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
220                                         &bc.TxVerifyResult{StatusFail: false},
221                                         &bc.TxVerifyResult{StatusFail: false},
222                                 }},
223                         },
224                 },
225                 {
226                         desc: "detach block 2, attach block 1. Chain trading",
227                         before: map[bc.Hash]*storage.UtxoEntry{
228                                 // coinbase tx
229                                 *newTx(mockBlocks[12].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(true, mockBlocks[12].Height, false),
230                                 *newTx(mockBlocks[12].Transactions[1]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[12].Height, false),
231                                 *newTx(mockBlocks[12].Transactions[2]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[12].Height, false),
232                                 *newTx(mockBlocks[12].Transactions[3]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[12].Height, false),
233                                 *newTx(mockBlocks[12].Transactions[4]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[12].Height, false),
234
235                                 *newTx(mockBlocks[13].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(true, mockBlocks[13].Height, false),
236                                 *newTx(mockBlocks[13].Transactions[1]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[13].Height, false),
237                                 *newTx(mockBlocks[13].Transactions[2]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[13].Height, false),
238                                 *newTx(mockBlocks[13].Transactions[2]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[13].Height, false),
239                         },
240                         want: map[bc.Hash]*storage.UtxoEntry{
241                                 newTx(mockBlocks[12].Transactions[1]).getSpentOutputID(0): storage.NewUtxoEntry(false, 0, false),
242                                 *newTx(mockBlocks[14].Transactions[0]).OutputHash(0):      storage.NewUtxoEntry(true, mockBlocks[14].Height, false),
243                         },
244                         attachBlock: []*bc.Block{
245                                 types.MapBlock(&mockBlocks[14].Block),
246                         },
247                         detachBlock: []*bc.Block{
248                                 types.MapBlock(&mockBlocks[13].Block),
249                                 types.MapBlock(&mockBlocks[12].Block),
250                         },
251                         attachTxStatus: []*bc.TransactionStatus{
252                                 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
253                                         &bc.TxVerifyResult{StatusFail: false},
254                                         &bc.TxVerifyResult{StatusFail: false},
255                                         &bc.TxVerifyResult{StatusFail: false},
256                                         &bc.TxVerifyResult{StatusFail: false},
257                                 }},
258                                 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
259                                         &bc.TxVerifyResult{StatusFail: false},
260                                         &bc.TxVerifyResult{StatusFail: false},
261                                 }},
262                                 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
263                                         &bc.TxVerifyResult{StatusFail: false},
264                                         &bc.TxVerifyResult{StatusFail: false},
265                                         &bc.TxVerifyResult{StatusFail: false},
266                                 }},
267                         },
268                         detachTxStatus: []*bc.TransactionStatus{
269                                 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
270                                         &bc.TxVerifyResult{StatusFail: false},
271                                         &bc.TxVerifyResult{StatusFail: false},
272                                         &bc.TxVerifyResult{StatusFail: false},
273                                 }},
274                                 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
275                                         &bc.TxVerifyResult{StatusFail: false},
276                                         &bc.TxVerifyResult{StatusFail: false},
277                                         &bc.TxVerifyResult{StatusFail: false},
278                                         &bc.TxVerifyResult{StatusFail: false},
279                                         &bc.TxVerifyResult{StatusFail: false},
280                                 }},
281                         },
282                 },
283         }
284         node := blockNode(types.MapBlock(&mockBlocks[0].Block).BlockHeader)
285         defer os.RemoveAll("temp")
286
287         for index, c := range cases {
288                 testDB := dbm.NewDB("testdb", "leveldb", "temp")
289                 store := database.NewStore(testDB)
290
291                 utxoViewpoint0 := state.NewUtxoViewpoint()
292                 for k, v := range c.before {
293                         utxoViewpoint0.Entries[k] = v
294                 }
295                 contractView := state.NewContractViewpoint()
296                 if err := store.SaveChainStatus(node, utxoViewpoint0, contractView, 0, &bc.Hash{}); err != nil {
297                         t.Error(err)
298                 }
299
300                 utxoViewpoint := state.NewUtxoViewpoint()
301                 for _, block := range c.detachBlock {
302                         if err := store.GetTransactionsUtxo(utxoViewpoint, block.Transactions); err != nil {
303                                 t.Error(err)
304                         }
305                         if err := utxoViewpoint.DetachBlock(block); err != nil {
306                                 t.Error(err)
307                         }
308                 }
309
310                 for _, block := range c.attachBlock {
311                         if err := store.GetTransactionsUtxo(utxoViewpoint, block.Transactions); err != nil {
312                                 t.Error(err)
313                         }
314                         if err := utxoViewpoint.ApplyBlock(block); err != nil {
315                                 t.Error(err)
316                         }
317                 }
318                 if err := store.SaveChainStatus(node, utxoViewpoint, contractView, 0, &bc.Hash{}); err != nil {
319                         t.Error(err)
320                 }
321
322                 want := map[string]*storage.UtxoEntry{}
323                 result := make(map[string]*storage.UtxoEntry)
324
325                 for k, v := range c.want {
326                         want[string(calcUtxoKey(&k))] = v
327                 }
328
329                 iter := testDB.IteratorPrefix([]byte(utxoPreFix))
330                 defer iter.Release()
331
332                 for iter.Next() {
333                         utxoEntry := &storage.UtxoEntry{}
334                         if err := proto.Unmarshal(iter.Value(), utxoEntry); err != nil {
335                                 t.Error(err)
336                         }
337                         key := string(iter.Key())
338                         result[key] = utxoEntry
339                 }
340
341                 if !testutil.DeepEqual(want, result) {
342                         t.Errorf("case [%d] fail. want: %v, result: %v", index, want, result)
343                 }
344
345                 testDB.Close()
346                 os.RemoveAll("temp")
347         }
348 }