OSDN Git Service

rename (#465)
[bytom/vapor.git] / test / utxo_view / utxo_view_test.go
1 package utxo_view
2
3 import (
4         "os"
5         "testing"
6
7         "github.com/bytom/vapor/testutil"
8
9         "github.com/golang/protobuf/proto"
10
11         "github.com/bytom/vapor/database"
12         dbm "github.com/bytom/vapor/database/leveldb"
13         "github.com/bytom/vapor/database/storage"
14         "github.com/bytom/vapor/protocol/bc"
15         "github.com/bytom/vapor/protocol/bc/types"
16         "github.com/bytom/vapor/protocol/state"
17 )
18
19 func TestAttachOrDetachBlocks(t *testing.T) {
20         cases := []struct {
21                 desc           string
22                 before         map[bc.Hash]*storage.UtxoEntry
23                 want           map[bc.Hash]*storage.UtxoEntry
24                 attachBlock    []*bc.Block
25                 detachBlock    []*bc.Block
26                 attachTxStatus []*bc.TransactionStatus
27                 detachTxStatus []*bc.TransactionStatus
28         }{
29                 {
30                         desc:   "coinbase tx",
31                         before: make(map[bc.Hash]*storage.UtxoEntry),
32                         want:   map[bc.Hash]*storage.UtxoEntry{*newTx(mockBlocks[0].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(storage.CoinbaseUTXOType, mockBlocks[0].Block.Height, false)},
33                         attachBlock: []*bc.Block{
34                                 types.MapBlock(&mockBlocks[0].Block),
35                         },
36                         attachTxStatus: []*bc.TransactionStatus{
37                                 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
38                                         &bc.TxVerifyResult{StatusFail: false},
39                                 }},
40                         },
41                 },
42                 {
43                         desc: "Chain trading 3",
44                         before: map[bc.Hash]*storage.UtxoEntry{
45                                 newTx(mockBlocks[1].Transactions[1]).getSpentOutputID(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[1].Height-1, false),
46                         },
47                         want: map[bc.Hash]*storage.UtxoEntry{
48                                 *newTx(mockBlocks[1].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(storage.CoinbaseUTXOType, mockBlocks[1].Height, false),
49                                 *newTx(mockBlocks[1].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[1].Height, false),
50                                 *newTx(mockBlocks[1].Transactions[2]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[1].Height, false),
51                                 *newTx(mockBlocks[1].Transactions[3]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[1].Height, false),
52                                 *newTx(mockBlocks[1].Transactions[3]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[1].Height, false),
53                         },
54                         attachBlock: []*bc.Block{
55                                 types.MapBlock(&mockBlocks[1].Block),
56                         },
57                         attachTxStatus: []*bc.TransactionStatus{
58                                 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
59                                         &bc.TxVerifyResult{StatusFail: false},
60                                         &bc.TxVerifyResult{StatusFail: false},
61                                         &bc.TxVerifyResult{StatusFail: false},
62                                         &bc.TxVerifyResult{StatusFail: false},
63                                 }},
64                         },
65                 },
66                 {
67                         desc: "detach 1 block, attach 2 block",
68                         before: map[bc.Hash]*storage.UtxoEntry{
69                                 *newTx(mockBlocks[2].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(storage.CoinbaseUTXOType, mockBlocks[2].Height, false),
70                                 *newTx(mockBlocks[2].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[2].Height, false),
71                                 *newTx(mockBlocks[2].Transactions[1]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[2].Height, false),
72                         },
73                         want: map[bc.Hash]*storage.UtxoEntry{
74                                 *newTx(mockBlocks[3].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(storage.CoinbaseUTXOType, mockBlocks[3].Height, false),
75                                 *newTx(mockBlocks[3].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[3].Height, false),
76
77                                 *newTx(mockBlocks[4].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(storage.CoinbaseUTXOType, mockBlocks[4].Height, false),
78                                 *newTx(mockBlocks[4].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[4].Height, false),
79                                 *newTx(mockBlocks[4].Transactions[1]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[4].Height, false),
80                         },
81                         attachBlock: []*bc.Block{
82                                 types.MapBlock(&mockBlocks[3].Block),
83                                 types.MapBlock(&mockBlocks[4].Block),
84                         },
85                         detachBlock: []*bc.Block{
86                                 types.MapBlock(&mockBlocks[2].Block),
87                         },
88                         attachTxStatus: []*bc.TransactionStatus{
89                                 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
90                                         &bc.TxVerifyResult{StatusFail: false},
91                                         &bc.TxVerifyResult{StatusFail: false},
92                                 }},
93                                 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
94                                         &bc.TxVerifyResult{StatusFail: false},
95                                         &bc.TxVerifyResult{StatusFail: false},
96                                 }},
97                         },
98                         detachTxStatus: []*bc.TransactionStatus{
99                                 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
100                                         &bc.TxVerifyResult{StatusFail: false},
101                                         &bc.TxVerifyResult{StatusFail: false},
102                                 }},
103                         },
104                 },
105                 {
106                         desc: "detach block 5, attach block 2",
107                         before: map[bc.Hash]*storage.UtxoEntry{
108                                 *newTx(mockBlocks[5].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(storage.CoinbaseUTXOType, mockBlocks[5].Height, false),
109                                 *newTx(mockBlocks[5].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[5].Height, false),
110                                 *newTx(mockBlocks[5].Transactions[1]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[5].Height, false),
111
112                                 *newTx(mockBlocks[6].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(storage.CoinbaseUTXOType, mockBlocks[6].Height, false),
113                                 *newTx(mockBlocks[6].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[6].Height, false),
114                                 *newTx(mockBlocks[6].Transactions[1]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[6].Height, false),
115                                 *newTx(mockBlocks[6].Transactions[1]).OutputHash(2): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[6].Height, false),
116                                 *newTx(mockBlocks[6].Transactions[1]).OutputHash(3): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[6].Height, false),
117                                 *newTx(mockBlocks[6].Transactions[2]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[6].Height, false),
118                                 *newTx(mockBlocks[6].Transactions[2]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[6].Height, false),
119                                 *newTx(mockBlocks[6].Transactions[2]).OutputHash(2): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[6].Height, false),
120                                 *newTx(mockBlocks[6].Transactions[2]).OutputHash(3): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[6].Height, false),
121
122                                 *newTx(mockBlocks[7].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(storage.CoinbaseUTXOType, mockBlocks[7].Height, false),
123                                 *newTx(mockBlocks[7].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[7].Height, false),
124                                 *newTx(mockBlocks[7].Transactions[1]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[7].Height, false),
125                                 *newTx(mockBlocks[7].Transactions[1]).OutputHash(2): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[7].Height, false),
126                                 *newTx(mockBlocks[7].Transactions[1]).OutputHash(3): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[7].Height, false),
127
128                                 *newTx(mockBlocks[8].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(storage.CoinbaseUTXOType, mockBlocks[8].Height, false),
129                                 *newTx(mockBlocks[8].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[8].Height, false),
130                                 *newTx(mockBlocks[8].Transactions[1]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[8].Height, false),
131                                 *newTx(mockBlocks[8].Transactions[1]).OutputHash(2): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[8].Height, false),
132                                 *newTx(mockBlocks[8].Transactions[1]).OutputHash(3): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[8].Height, false),
133                                 *newTx(mockBlocks[8].Transactions[2]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[8].Height, false),
134                                 *newTx(mockBlocks[8].Transactions[2]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[8].Height, false),
135                                 *newTx(mockBlocks[8].Transactions[3]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[8].Height, false),
136                                 *newTx(mockBlocks[8].Transactions[3]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[8].Height, false),
137
138                                 *newTx(mockBlocks[9].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(storage.CoinbaseUTXOType, mockBlocks[9].Height, false),
139                                 *newTx(mockBlocks[9].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[9].Height, false),
140                                 *newTx(mockBlocks[9].Transactions[1]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[9].Height, false),
141                         },
142                         want: map[bc.Hash]*storage.UtxoEntry{
143                                 *newTx(mockBlocks[10].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(storage.CoinbaseUTXOType, mockBlocks[10].Height, false),
144                                 *newTx(mockBlocks[10].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
145                                 *newTx(mockBlocks[10].Transactions[1]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
146                                 *newTx(mockBlocks[10].Transactions[2]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
147                                 *newTx(mockBlocks[10].Transactions[2]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
148                                 *newTx(mockBlocks[10].Transactions[2]).OutputHash(2): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
149                                 *newTx(mockBlocks[10].Transactions[2]).OutputHash(3): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
150                                 *newTx(mockBlocks[10].Transactions[3]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
151                                 *newTx(mockBlocks[10].Transactions[3]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
152                                 *newTx(mockBlocks[10].Transactions[3]).OutputHash(2): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
153                                 *newTx(mockBlocks[10].Transactions[3]).OutputHash(3): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
154                                 *newTx(mockBlocks[10].Transactions[4]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
155                                 *newTx(mockBlocks[10].Transactions[4]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
156                                 *newTx(mockBlocks[10].Transactions[4]).OutputHash(2): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
157                                 *newTx(mockBlocks[10].Transactions[4]).OutputHash(3): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
158                                 *newTx(mockBlocks[10].Transactions[5]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
159                                 *newTx(mockBlocks[10].Transactions[5]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
160                                 *newTx(mockBlocks[10].Transactions[5]).OutputHash(2): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
161                                 *newTx(mockBlocks[10].Transactions[5]).OutputHash(3): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
162
163                                 *newTx(mockBlocks[11].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(storage.CoinbaseUTXOType, mockBlocks[11].Height, false),
164                                 *newTx(mockBlocks[11].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[11].Height, false),
165                                 *newTx(mockBlocks[11].Transactions[1]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[11].Height, false),
166                                 *newTx(mockBlocks[11].Transactions[2]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[11].Height, false),
167                                 *newTx(mockBlocks[11].Transactions[2]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[11].Height, false),
168                                 *newTx(mockBlocks[11].Transactions[3]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[11].Height, false),
169                                 *newTx(mockBlocks[11].Transactions[3]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[11].Height, false),
170                         },
171                         attachBlock: []*bc.Block{
172                                 types.MapBlock(&mockBlocks[10].Block),
173                                 types.MapBlock(&mockBlocks[11].Block),
174                         },
175                         detachBlock: []*bc.Block{
176                                 types.MapBlock(&mockBlocks[9].Block),
177                                 types.MapBlock(&mockBlocks[8].Block),
178                                 types.MapBlock(&mockBlocks[7].Block),
179                                 types.MapBlock(&mockBlocks[6].Block),
180                                 types.MapBlock(&mockBlocks[5].Block),
181                         },
182                         attachTxStatus: []*bc.TransactionStatus{
183                                 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
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                                         &bc.TxVerifyResult{StatusFail: false},
190                                 }},
191                                 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
192                                         &bc.TxVerifyResult{StatusFail: false},
193                                         &bc.TxVerifyResult{StatusFail: false},
194                                         &bc.TxVerifyResult{StatusFail: false},
195                                         &bc.TxVerifyResult{StatusFail: false},
196                                         &bc.TxVerifyResult{StatusFail: false},
197                                 }},
198                         },
199                         detachTxStatus: []*bc.TransactionStatus{
200
201                                 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
202                                         &bc.TxVerifyResult{StatusFail: false},
203                                         &bc.TxVerifyResult{StatusFail: false},
204                                 }},
205                                 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
206                                         &bc.TxVerifyResult{StatusFail: false},
207                                         &bc.TxVerifyResult{StatusFail: false},
208                                         &bc.TxVerifyResult{StatusFail: false},
209                                         &bc.TxVerifyResult{StatusFail: false},
210                                 }},
211                                 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
212                                         &bc.TxVerifyResult{StatusFail: false},
213                                         &bc.TxVerifyResult{StatusFail: false},
214                                 }},
215                                 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
216                                         &bc.TxVerifyResult{StatusFail: false},
217                                         &bc.TxVerifyResult{StatusFail: false},
218                                         &bc.TxVerifyResult{StatusFail: false},
219                                 }},
220                                 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
221                                         &bc.TxVerifyResult{StatusFail: false},
222                                         &bc.TxVerifyResult{StatusFail: false},
223                                 }},
224                         },
225                 },
226                 {
227                         desc: "detach block 5, attach block 2. Other asset deals failed.",
228                         before: map[bc.Hash]*storage.UtxoEntry{
229                                 *newTx(mockBlocks[5].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(storage.CoinbaseUTXOType, mockBlocks[5].Height, false),
230                                 *newTx(mockBlocks[5].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[5].Height, false),
231                                 *newTx(mockBlocks[5].Transactions[1]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[5].Height, false),
232
233                                 *newTx(mockBlocks[6].Transactions[0]).OutputHash(0):      storage.NewUtxoEntry(storage.CoinbaseUTXOType, mockBlocks[6].Height, false),
234                                 *newTx(mockBlocks[6].Transactions[1]).OutputHash(0):      storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[6].Height, false),
235                                 *newTx(mockBlocks[6].Transactions[1]).OutputHash(1):      storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[6].Height, false),
236                                 newTx(mockBlocks[6].Transactions[1]).getSpentOutputID(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[6].Height-1, false),
237
238                                 *newTx(mockBlocks[6].Transactions[2]).OutputHash(0):      storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[6].Height, false),
239                                 *newTx(mockBlocks[6].Transactions[2]).OutputHash(1):      storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[6].Height, false),
240                                 newTx(mockBlocks[6].Transactions[2]).getSpentOutputID(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[6].Height-1, false),
241
242                                 *newTx(mockBlocks[7].Transactions[0]).OutputHash(0):      storage.NewUtxoEntry(storage.CoinbaseUTXOType, mockBlocks[7].Height, false),
243                                 *newTx(mockBlocks[7].Transactions[1]).OutputHash(0):      storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[7].Height, false),
244                                 *newTx(mockBlocks[7].Transactions[1]).OutputHash(1):      storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[7].Height, false),
245                                 newTx(mockBlocks[7].Transactions[1]).getSpentOutputID(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[7].Height-1, false),
246
247                                 *newTx(mockBlocks[8].Transactions[0]).OutputHash(0):      storage.NewUtxoEntry(storage.CoinbaseUTXOType, mockBlocks[8].Height, false),
248                                 *newTx(mockBlocks[8].Transactions[1]).OutputHash(0):      storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[8].Height, false),
249                                 *newTx(mockBlocks[8].Transactions[1]).OutputHash(1):      storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[8].Height, false),
250                                 newTx(mockBlocks[8].Transactions[1]).getSpentOutputID(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[8].Height-1, false),
251
252                                 *newTx(mockBlocks[8].Transactions[2]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[8].Height, false),
253                                 *newTx(mockBlocks[8].Transactions[2]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[8].Height, false),
254                                 *newTx(mockBlocks[8].Transactions[3]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[8].Height, false),
255                                 *newTx(mockBlocks[8].Transactions[3]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[8].Height, false),
256
257                                 *newTx(mockBlocks[9].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(storage.CoinbaseUTXOType, mockBlocks[9].Height, false),
258                                 *newTx(mockBlocks[9].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[9].Height, false),
259                                 *newTx(mockBlocks[9].Transactions[1]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[9].Height, false),
260                         },
261                         want: map[bc.Hash]*storage.UtxoEntry{
262
263                                 *newTx(mockBlocks[10].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(storage.CoinbaseUTXOType, mockBlocks[10].Height, false),
264                                 *newTx(mockBlocks[10].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
265                                 *newTx(mockBlocks[10].Transactions[1]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
266
267                                 *newTx(mockBlocks[10].Transactions[2]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
268                                 *newTx(mockBlocks[10].Transactions[2]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
269                                 *newTx(mockBlocks[10].Transactions[2]).OutputHash(2): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
270                                 *newTx(mockBlocks[10].Transactions[2]).OutputHash(3): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
271
272                                 *newTx(mockBlocks[10].Transactions[3]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
273                                 *newTx(mockBlocks[10].Transactions[3]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
274                                 *newTx(mockBlocks[10].Transactions[3]).OutputHash(2): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
275                                 *newTx(mockBlocks[10].Transactions[3]).OutputHash(3): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
276
277                                 *newTx(mockBlocks[10].Transactions[4]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
278                                 *newTx(mockBlocks[10].Transactions[4]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
279                                 *newTx(mockBlocks[10].Transactions[4]).OutputHash(2): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
280                                 *newTx(mockBlocks[10].Transactions[4]).OutputHash(3): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
281                                 *newTx(mockBlocks[10].Transactions[5]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
282                                 *newTx(mockBlocks[10].Transactions[5]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
283                                 *newTx(mockBlocks[10].Transactions[5]).OutputHash(2): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
284                                 *newTx(mockBlocks[10].Transactions[5]).OutputHash(3): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[10].Height, false),
285
286                                 *newTx(mockBlocks[11].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(storage.CoinbaseUTXOType, mockBlocks[11].Height, false),
287                                 *newTx(mockBlocks[11].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[11].Height, false),
288                                 *newTx(mockBlocks[11].Transactions[1]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[11].Height, false),
289                                 *newTx(mockBlocks[11].Transactions[2]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[11].Height, false),
290                                 *newTx(mockBlocks[11].Transactions[2]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[11].Height, false),
291                                 *newTx(mockBlocks[11].Transactions[3]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[11].Height, false),
292                                 *newTx(mockBlocks[11].Transactions[3]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[11].Height, false),
293                         },
294                         attachBlock: []*bc.Block{
295                                 types.MapBlock(&mockBlocks[10].Block),
296                                 types.MapBlock(&mockBlocks[11].Block),
297                         },
298                         detachBlock: []*bc.Block{
299                                 types.MapBlock(&mockBlocks[9].Block),
300                                 types.MapBlock(&mockBlocks[8].Block),
301                                 types.MapBlock(&mockBlocks[7].Block),
302                                 types.MapBlock(&mockBlocks[6].Block),
303                                 types.MapBlock(&mockBlocks[5].Block),
304                         },
305                         attachTxStatus: []*bc.TransactionStatus{
306                                 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
307                                         &bc.TxVerifyResult{StatusFail: false},
308                                         &bc.TxVerifyResult{StatusFail: false},
309                                         &bc.TxVerifyResult{StatusFail: false},
310                                         &bc.TxVerifyResult{StatusFail: false},
311                                         &bc.TxVerifyResult{StatusFail: false},
312                                         &bc.TxVerifyResult{StatusFail: false},
313                                 }},
314                                 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
315                                         &bc.TxVerifyResult{StatusFail: false},
316                                         &bc.TxVerifyResult{StatusFail: false},
317                                         &bc.TxVerifyResult{StatusFail: false},
318                                         &bc.TxVerifyResult{StatusFail: false},
319                                         &bc.TxVerifyResult{StatusFail: false},
320                                 }},
321                         },
322                         detachTxStatus: []*bc.TransactionStatus{
323                                 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
324                                         &bc.TxVerifyResult{StatusFail: false},
325                                         &bc.TxVerifyResult{StatusFail: false},
326                                 }},
327                                 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
328                                         &bc.TxVerifyResult{StatusFail: false},
329                                         &bc.TxVerifyResult{StatusFail: true},
330                                         &bc.TxVerifyResult{StatusFail: false},
331                                         &bc.TxVerifyResult{StatusFail: false},
332                                 }},
333                                 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
334                                         &bc.TxVerifyResult{StatusFail: false},
335                                         &bc.TxVerifyResult{StatusFail: true},
336                                 }},
337                                 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
338                                         &bc.TxVerifyResult{StatusFail: false},
339                                         &bc.TxVerifyResult{StatusFail: true},
340                                         &bc.TxVerifyResult{StatusFail: true},
341                                 }},
342                                 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
343                                         &bc.TxVerifyResult{StatusFail: false},
344                                         &bc.TxVerifyResult{StatusFail: false},
345                                 }},
346                         },
347                 },
348                 {
349                         desc: "detach block 2, attach block 1. Chain trading",
350                         before: map[bc.Hash]*storage.UtxoEntry{
351                                 // coinbase tx
352                                 *newTx(mockBlocks[12].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(storage.CoinbaseUTXOType, mockBlocks[12].Height, false),
353                                 *newTx(mockBlocks[12].Transactions[1]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[12].Height, false),
354                                 *newTx(mockBlocks[12].Transactions[2]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[12].Height, false),
355                                 *newTx(mockBlocks[12].Transactions[3]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[12].Height, false),
356                                 *newTx(mockBlocks[12].Transactions[4]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[12].Height, false),
357
358                                 *newTx(mockBlocks[13].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(storage.CoinbaseUTXOType, mockBlocks[13].Height, false),
359                                 *newTx(mockBlocks[13].Transactions[1]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[13].Height, false),
360                                 *newTx(mockBlocks[13].Transactions[2]).OutputHash(0): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[13].Height, false),
361                                 *newTx(mockBlocks[13].Transactions[2]).OutputHash(1): storage.NewUtxoEntry(storage.NormalUTXOType, mockBlocks[13].Height, false),
362                         },
363                         want: map[bc.Hash]*storage.UtxoEntry{
364                                 newTx(mockBlocks[12].Transactions[1]).getSpentOutputID(0): storage.NewUtxoEntry(storage.NormalUTXOType, 0, false),
365                                 *newTx(mockBlocks[14].Transactions[0]).OutputHash(0):      storage.NewUtxoEntry(storage.CoinbaseUTXOType, mockBlocks[14].Height, false),
366                         },
367                         attachBlock: []*bc.Block{
368                                 types.MapBlock(&mockBlocks[14].Block),
369                         },
370                         detachBlock: []*bc.Block{
371                                 types.MapBlock(&mockBlocks[13].Block),
372                                 types.MapBlock(&mockBlocks[12].Block),
373                         },
374                         attachTxStatus: []*bc.TransactionStatus{
375                                 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
376                                         &bc.TxVerifyResult{StatusFail: false},
377                                         &bc.TxVerifyResult{StatusFail: false},
378                                         &bc.TxVerifyResult{StatusFail: false},
379                                         &bc.TxVerifyResult{StatusFail: false},
380                                 }},
381                                 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
382                                         &bc.TxVerifyResult{StatusFail: false},
383                                         &bc.TxVerifyResult{StatusFail: false},
384                                 }},
385                                 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
386                                         &bc.TxVerifyResult{StatusFail: false},
387                                         &bc.TxVerifyResult{StatusFail: false},
388                                         &bc.TxVerifyResult{StatusFail: false},
389                                 }},
390                         },
391                         detachTxStatus: []*bc.TransactionStatus{
392                                 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
393                                         &bc.TxVerifyResult{StatusFail: false},
394                                         &bc.TxVerifyResult{StatusFail: false},
395                                         &bc.TxVerifyResult{StatusFail: false},
396                                 }},
397                                 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
398                                         &bc.TxVerifyResult{StatusFail: false},
399                                         &bc.TxVerifyResult{StatusFail: false},
400                                         &bc.TxVerifyResult{StatusFail: false},
401                                         &bc.TxVerifyResult{StatusFail: false},
402                                         &bc.TxVerifyResult{StatusFail: false},
403                                 }},
404                         },
405                 },
406         }
407
408         mockBlockHeader := &mockBlocks[0].Block.BlockHeader
409         defer os.RemoveAll("temp")
410         for index, c := range cases {
411                 testDB := dbm.NewDB("testdb", "leveldb", "temp")
412                 store := database.NewStore(testDB)
413
414                 utxoViewpoint := state.NewUtxoViewpoint()
415                 for k, v := range c.before {
416                         utxoViewpoint.Entries[k] = v
417                 }
418                 if err := store.SaveChainStatus(mockBlockHeader, mockBlockHeader, []*types.BlockHeader{mockBlockHeader}, utxoViewpoint, []*state.ConsensusResult{}); err != nil {
419                         t.Error(err)
420                 }
421
422                 utxoViewpoint = state.NewUtxoViewpoint()
423                 for index, block := range c.detachBlock {
424                         if err := store.GetTransactionsUtxo(utxoViewpoint, block.Transactions); err != nil {
425                                 t.Error(err)
426                         }
427                         if err := utxoViewpoint.DetachBlock(block, c.detachTxStatus[index]); err != nil {
428                                 t.Error(err)
429                         }
430                 }
431
432                 for index, block := range c.attachBlock {
433                         if err := store.GetTransactionsUtxo(utxoViewpoint, block.Transactions); err != nil {
434                                 t.Error(err)
435                         }
436                         if err := utxoViewpoint.ApplyBlock(block, c.attachTxStatus[index]); err != nil {
437                                 t.Error(err)
438                         }
439                 }
440                 if err := store.SaveChainStatus(mockBlockHeader, mockBlockHeader, []*types.BlockHeader{mockBlockHeader}, utxoViewpoint, []*state.ConsensusResult{}); err != nil {
441                         t.Error(err)
442                 }
443
444                 want := map[string]*storage.UtxoEntry{}
445                 result := make(map[string]*storage.UtxoEntry)
446
447                 for k, v := range c.want {
448                         want[string(calcUtxoKey(&k))] = v
449                 }
450
451                 iter := testDB.IteratorPrefix([]byte(utxoPreFix))
452                 defer iter.Release()
453
454                 for iter.Next() {
455                         utxoEntry := &storage.UtxoEntry{}
456                         if err := proto.Unmarshal(iter.Value(), utxoEntry); err != nil {
457                                 t.Error(err)
458                         }
459                         key := string(iter.Key())
460                         result[key] = utxoEntry
461                 }
462
463                 if !testutil.DeepEqual(want, result) {
464                         t.Errorf("case [%d] fail. want: %v, result: %v", index, want, result)
465                 }
466                 testDB.Close()
467                 os.RemoveAll("temp")
468         }
469 }