OSDN Git Service

versoin1.1.9 (#594)
[bytom/vapor.git] / database / store_test.go
1 package database
2
3 import (
4         "os"
5         "testing"
6
7         "github.com/stretchr/testify/require"
8
9         "github.com/bytom/vapor/consensus"
10         dbm "github.com/bytom/vapor/database/leveldb"
11         "github.com/bytom/vapor/database/storage"
12         "github.com/bytom/vapor/protocol"
13         "github.com/bytom/vapor/protocol/bc"
14         "github.com/bytom/vapor/protocol/bc/types"
15         "github.com/bytom/vapor/protocol/state"
16         "github.com/bytom/vapor/testutil"
17 )
18
19 func TestSaveChainStatus(t *testing.T) {
20         testDB := dbm.NewDB("testdb", "leveldb", "temp")
21         defer func() {
22                 testDB.Close()
23                 os.RemoveAll("temp")
24         }()
25
26         store := NewStore(testDB)
27
28         blockHeader := &types.BlockHeader{Height: 100}
29         blockHash := blockHeader.Hash() //Hash: bc.Hash{V0: 0, V1: 1, V2: 2, V3: 3}
30         view := &state.UtxoViewpoint{
31                 Entries: map[bc.Hash]*storage.UtxoEntry{
32                         bc.Hash{V0: 1, V1: 2, V2: 3, V3: 4}: &storage.UtxoEntry{Type: storage.NormalUTXOType, BlockHeight: 100, Spent: false},
33                         bc.Hash{V0: 1, V1: 2, V2: 3, V3: 4}: &storage.UtxoEntry{Type: storage.CoinbaseUTXOType, BlockHeight: 100, Spent: true},
34                         bc.Hash{V0: 1, V1: 1, V2: 3, V3: 4}: &storage.UtxoEntry{Type: storage.NormalUTXOType, BlockHeight: 100, Spent: true},
35                         bc.Hash{V0: 1, V1: 1, V2: 3, V3: 5}: &storage.UtxoEntry{Type: storage.CrosschainUTXOType, BlockHeight: 100, Spent: false},
36                         bc.Hash{V0: 1, V1: 1, V2: 3, V3: 6}: &storage.UtxoEntry{Type: storage.CrosschainUTXOType, BlockHeight: 100, Spent: true},
37                         bc.Hash{V0: 1, V1: 3, V2: 3, V3: 7}: &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 100, Spent: false},
38                         bc.Hash{V0: 1, V1: 3, V2: 3, V3: 7}: &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 100, Spent: true},
39                 },
40         }
41
42         if err := store.SaveChainStatus(blockHeader, blockHeader, []*types.BlockHeader{blockHeader}, view, []*state.ConsensusResult{}); err != nil {
43                 t.Fatal(err)
44         }
45
46         expectStatus := &protocol.BlockStoreState{Height: blockHeader.Height, Hash: &blockHash, IrreversibleHeight: blockHeader.Height, IrreversibleHash: &blockHash}
47         if !testutil.DeepEqual(store.GetStoreStatus(), expectStatus) {
48                 t.Errorf("got block status:%v, expect block status:%v", store.GetStoreStatus(), expectStatus)
49         }
50
51         for hash, utxo := range view.Entries {
52                 if (utxo.Type == storage.NormalUTXOType) && utxo.Spent {
53                         continue
54                 }
55                 if (utxo.Type == storage.CrosschainUTXOType) && (!utxo.Spent) {
56                         continue
57                 }
58                 if (utxo.Type == storage.VoteUTXOType) && (utxo.Spent) {
59                         continue
60                 }
61
62                 gotUtxo, err := store.GetUtxo(&hash)
63                 if err != nil {
64                         t.Fatal(err)
65                 }
66
67                 if !testutil.DeepEqual(utxo, gotUtxo) {
68                         t.Errorf("got utxo entry:%v, expect utxo entry:%v", gotUtxo, utxo)
69                 }
70         }
71 }
72
73 func TestSaveBlock(t *testing.T) {
74         testDB := dbm.NewDB("testdb", "leveldb", "temp")
75         defer func() {
76                 testDB.Close()
77                 os.RemoveAll("temp")
78         }()
79
80         store := NewStore(testDB)
81         coinbaseTxData := &types.TxData{
82                 Version: 1,
83                 Inputs: []*types.TxInput{
84                         types.NewCoinbaseInput([]byte("Information is power. -- Jan/11/2013. Computing is power. -- Apr/24/2018.")),
85                 },
86                 Outputs: []*types.TxOutput{
87                         types.NewVoteOutput(*consensus.BTMAssetID, uint64(10000), []byte{0x51}, []byte{0x51}),
88                 },
89         }
90         coinbaseTx := types.NewTx(*coinbaseTxData)
91
92         cases := []struct {
93                 txData      []*types.TxData
94                 txStatus    *bc.TransactionStatus
95                 blockHeader *types.BlockHeader
96         }{
97                 {
98                         txStatus: &bc.TransactionStatus{
99                                 VerifyStatus: []*bc.TxVerifyResult{
100                                         {StatusFail: true},
101                                 },
102                         },
103                         blockHeader: &types.BlockHeader{
104                                 Version:   uint64(1),
105                                 Height:    uint64(1111),
106                                 Timestamp: uint64(1528945000),
107                         },
108                 },
109                 {
110                         txStatus: &bc.TransactionStatus{
111                                 VerifyStatus: []*bc.TxVerifyResult{
112                                         {StatusFail: false},
113                                 },
114                         },
115                         blockHeader: &types.BlockHeader{
116                                 Version:   uint64(1),
117                                 Height:    uint64(1111),
118                                 Timestamp: uint64(1528945000),
119                         },
120                 },
121                 {
122                         txData: []*types.TxData{
123                                 {
124                                         Version: 1,
125                                         Inputs: []*types.TxInput{
126                                                 types.NewSpendInput([][]byte{}, bc.NewHash([32]byte{}), *consensus.BTMAssetID, 100000000, 0, []byte{0x51}),
127                                         },
128                                         Outputs: []*types.TxOutput{
129                                                 types.NewVoteOutput(*consensus.BTMAssetID, uint64(10000), []byte{0x51}, []byte{0x51}),
130                                         },
131                                 },
132                         },
133                         txStatus: &bc.TransactionStatus{
134                                 VerifyStatus: []*bc.TxVerifyResult{
135                                         {StatusFail: true},
136                                 },
137                         },
138                         blockHeader: &types.BlockHeader{
139                                 Version:   uint64(1),
140                                 Height:    uint64(1111),
141                                 Timestamp: uint64(1528945000),
142                         },
143                 },
144                 {
145                         txData: []*types.TxData{
146                                 {
147                                         Version: 1,
148                                         Inputs: []*types.TxInput{
149                                                 types.NewSpendInput([][]byte{}, bc.NewHash([32]byte{}), *consensus.BTMAssetID, 100000000, 0, []byte{0x51}),
150                                         },
151                                         Outputs: []*types.TxOutput{
152                                                 types.NewVoteOutput(*consensus.BTMAssetID, uint64(88888), []byte{0x51}, []byte{0x51}),
153                                         },
154                                 },
155                         },
156                         txStatus: &bc.TransactionStatus{
157                                 VerifyStatus: []*bc.TxVerifyResult{
158                                         {StatusFail: false},
159                                 },
160                         },
161                         blockHeader: &types.BlockHeader{
162                                 Version:   uint64(1),
163                                 Height:    uint64(0),
164                                 Timestamp: uint64(152894500000),
165                         },
166                 },
167         }
168
169         for i, c := range cases {
170                 txs := []*bc.Tx{coinbaseTx.Tx}
171                 for _, tx := range c.txData {
172                         t := types.NewTx(*tx)
173                         txs = append(txs, t.Tx)
174                 }
175                 merkleRoot, _ := types.TxMerkleRoot(txs)
176                 txStatusHash, _ := types.TxStatusMerkleRoot(c.txStatus.VerifyStatus)
177                 block := &types.Block{
178                         BlockHeader: types.BlockHeader{
179                                 Version:   c.blockHeader.Version,
180                                 Height:    c.blockHeader.Height,
181                                 Timestamp: c.blockHeader.Timestamp,
182                                 BlockCommitment: types.BlockCommitment{
183                                         TransactionsMerkleRoot: merkleRoot,
184                                         TransactionStatusHash:  txStatusHash,
185                                 },
186                         },
187                 }
188
189                 if err := store.SaveBlock(block, c.txStatus); err != nil {
190                         t.Fatal(err)
191                 }
192
193                 blockHash := block.Hash()
194                 gotBlock, err := store.GetBlock(&blockHash)
195                 if err != nil {
196                         t.Fatal(err)
197                 }
198
199                 if !testutil.DeepEqual(gotBlock, block) {
200                         t.Errorf("case %v: block mismatch: have %x, want %x", i, gotBlock, block)
201                 }
202
203                 gotStatus, err := store.GetTransactionStatus(&blockHash)
204                 if err != nil {
205                         t.Fatal(err)
206                 }
207
208                 if !testutil.DeepEqual(gotStatus.VerifyStatus, c.txStatus.VerifyStatus) {
209                         t.Errorf("case %v: VerifyStatus mismatch: have %x, want %x", i, gotStatus.VerifyStatus, c.txStatus.VerifyStatus)
210                 }
211
212                 gotBlockHeader, err := store.GetBlockHeader(&blockHash)
213                 if err != nil {
214                         t.Fatal(err)
215                 }
216
217                 if !testutil.DeepEqual(block.BlockHeader, *gotBlockHeader) {
218                         t.Errorf("got block header:%v, expect block header:%v", gotBlockHeader, block.BlockHeader)
219                 }
220         }
221 }
222
223 func TestSaveBlockHeader(t *testing.T) {
224         testDB := dbm.NewDB("testdb", "leveldb", "temp")
225         defer func() {
226                 testDB.Close()
227                 os.RemoveAll("temp")
228         }()
229
230         store := NewStore(testDB)
231
232         cases := []struct {
233                 blockHeader *types.BlockHeader
234         }{
235                 {
236                         blockHeader: &types.BlockHeader{
237                                 Version:   uint64(1),
238                                 Height:    uint64(1111),
239                                 Timestamp: uint64(1528945000),
240                         },
241                 },
242                 {
243                         blockHeader: &types.BlockHeader{
244                                 Version:           uint64(1),
245                                 Height:            uint64(0),
246                                 PreviousBlockHash: bc.NewHash([32]byte{0x3e, 0x94, 0x5d, 0x35, 0x70, 0x30, 0xd4, 0x3b, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c}),
247                                 Timestamp:         uint64(1563186936),
248                                 BlockCommitment: types.BlockCommitment{
249                                         TransactionsMerkleRoot: bc.NewHash([32]byte{0x3e, 0x94, 0x5d, 0x35, 0x70, 0x30, 0xd4, 0x3b, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c}),
250                                         TransactionStatusHash:  bc.NewHash([32]byte{0x3e, 0x94, 0x5d, 0x35, 0x70, 0x30, 0xd4, 0x3b, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c}),
251                                 },
252                                 BlockWitness: types.BlockWitness{
253                                         Witness: [][]byte{[]byte{0x3e, 0x94, 0x5d, 0x35}, []byte{0x3e, 0x94, 0x5d, 0x35}},
254                                 },
255                         },
256                 },
257                 {
258                         blockHeader: &types.BlockHeader{
259                                 Version:           uint64(1),
260                                 Height:            uint64(8848),
261                                 PreviousBlockHash: bc.NewHash([32]byte{0x3e, 0x94, 0x5d, 0x35, 0x70, 0x30, 0xd4, 0x3b, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c}),
262                                 Timestamp:         uint64(156318693600),
263                                 BlockCommitment: types.BlockCommitment{
264                                         TransactionsMerkleRoot: bc.NewHash([32]byte{0x3e, 0x94, 0x5d, 0x35, 0x70, 0x30, 0xd4, 0x3b, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c}),
265                                         TransactionStatusHash:  bc.NewHash([32]byte{0x3e, 0x94, 0x5d, 0x35, 0x70, 0x30, 0xd4, 0x3b, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c}),
266                                 },
267                                 BlockWitness: types.BlockWitness{
268                                         Witness: [][]byte{
269                                                 []byte{0x3e, 0x94, 0x5d, 0x35},
270                                                 []byte{0xdd, 0x80, 0x67, 0x29},
271                                                 []byte{0xff, 0xff, 0xff, 0xff},
272                                                 []byte{0x00, 0x01, 0x02, 0x03},
273                                         },
274                                 },
275                         },
276                 },
277         }
278
279         for i, c := range cases {
280                 if err := store.SaveBlockHeader(c.blockHeader); err != nil {
281                         t.Fatal(err)
282                 }
283
284                 blockHash := c.blockHeader.Hash()
285                 gotBlockHeader, err := store.GetBlockHeader(&blockHash)
286                 if err != nil {
287                         t.Fatal(err)
288                 }
289
290                 if !testutil.DeepEqual(gotBlockHeader, c.blockHeader) {
291                         t.Errorf("case %v: block header mismatch: have %x, want %x", i, gotBlockHeader, c.blockHeader)
292                 }
293         }
294 }
295
296 func TestDeleteBlock(t *testing.T) {
297         cases := []struct {
298                 initBlocks  []*types.BlockHeader
299                 deleteBlock *types.BlockHeader
300                 wantBlocks  []*types.BlockHeader
301         }{
302                 {
303                         initBlocks: []*types.BlockHeader{},
304                         deleteBlock: &types.BlockHeader{
305                                 Version:   uint64(1),
306                                 Height:    uint64(1),
307                                 Timestamp: uint64(1528945000),
308                         },
309                         wantBlocks: []*types.BlockHeader{},
310                 },
311                 {
312                         initBlocks: []*types.BlockHeader{
313                                 {
314                                         Version:   uint64(1),
315                                         Height:    uint64(1),
316                                         Timestamp: uint64(1528945000),
317                                 },
318                                 {
319                                         Version:   uint64(1),
320                                         Height:    uint64(1),
321                                         Timestamp: uint64(1528945005),
322                                 },
323                                 {
324                                         Version:   uint64(1),
325                                         Height:    uint64(1),
326                                         Timestamp: uint64(1528945010),
327                                 },
328                         },
329                         deleteBlock: &types.BlockHeader{
330                                 Version:   uint64(1),
331                                 Height:    uint64(1),
332                                 Timestamp: uint64(1528945000),
333                         },
334                         wantBlocks: []*types.BlockHeader{
335                                 {
336                                         Version:   uint64(1),
337                                         Height:    uint64(1),
338                                         Timestamp: uint64(1528945005),
339                                 },
340                                 {
341                                         Version:   uint64(1),
342                                         Height:    uint64(1),
343                                         Timestamp: uint64(1528945010),
344                                 },
345                         },
346                 },
347                 {
348                         initBlocks: []*types.BlockHeader{
349                                 {
350                                         Version:   uint64(1),
351                                         Height:    uint64(1),
352                                         Timestamp: uint64(1528945000),
353                                 },
354                                 {
355                                         Version:   uint64(1),
356                                         Height:    uint64(1),
357                                         Timestamp: uint64(1528945005),
358                                 },
359                                 {
360                                         Version:   uint64(1),
361                                         Height:    uint64(1),
362                                         Timestamp: uint64(1528945010),
363                                 },
364                         },
365                         deleteBlock: &types.BlockHeader{
366                                 Version:   uint64(1),
367                                 Height:    uint64(1),
368                                 Timestamp: uint64(1528945005),
369                         },
370                         wantBlocks: []*types.BlockHeader{
371                                 {
372                                         Version:   uint64(1),
373                                         Height:    uint64(1),
374                                         Timestamp: uint64(1528945000),
375                                 },
376                                 {
377                                         Version:   uint64(1),
378                                         Height:    uint64(1),
379                                         Timestamp: uint64(1528945010),
380                                 },
381                         },
382                 },
383                 {
384                         initBlocks: []*types.BlockHeader{
385                                 {
386                                         Version:   uint64(1),
387                                         Height:    uint64(1),
388                                         Timestamp: uint64(1528945000),
389                                 },
390                                 {
391                                         Version:   uint64(1),
392                                         Height:    uint64(1),
393                                         Timestamp: uint64(1528945005),
394                                 },
395                                 {
396                                         Version:   uint64(1),
397                                         Height:    uint64(1),
398                                         Timestamp: uint64(1528945010),
399                                 },
400                         },
401                         deleteBlock: &types.BlockHeader{
402                                 Version:   uint64(1),
403                                 Height:    uint64(1),
404                                 Timestamp: uint64(1528945010),
405                         },
406                         wantBlocks: []*types.BlockHeader{
407                                 {
408                                         Version:   uint64(1),
409                                         Height:    uint64(1),
410                                         Timestamp: uint64(1528945000),
411                                 },
412                                 {
413                                         Version:   uint64(1),
414                                         Height:    uint64(1),
415                                         Timestamp: uint64(1528945005),
416                                 },
417                         },
418                 },
419                 {
420                         initBlocks: []*types.BlockHeader{},
421                         deleteBlock: &types.BlockHeader{
422                                 Version:   uint64(1),
423                                 Height:    uint64(1),
424                                 Timestamp: uint64(1528945030),
425                         },
426                         wantBlocks: []*types.BlockHeader{},
427                 },
428                 {
429                         initBlocks: []*types.BlockHeader{
430                                 {
431                                         Version:   uint64(1),
432                                         Height:    uint64(1),
433                                         Timestamp: uint64(1528945000),
434                                 },
435                         },
436                         deleteBlock: &types.BlockHeader{
437                                 Version:   uint64(1),
438                                 Height:    uint64(1),
439                                 Timestamp: uint64(1528945030),
440                         },
441                         wantBlocks: []*types.BlockHeader{
442                                 {
443                                         Version:   uint64(1),
444                                         Height:    uint64(1),
445                                         Timestamp: uint64(1528945000),
446                                 },
447                         },
448                 },
449         }
450
451         for _, c := range cases {
452                 verifyStatus := &bc.TransactionStatus{
453                         VerifyStatus: []*bc.TxVerifyResult{
454                                 {StatusFail: false},
455                         },
456                 }
457                 deleteBlock := &types.Block{
458                         BlockHeader: types.BlockHeader{
459                                 Version:   c.deleteBlock.Version,
460                                 Height:    c.deleteBlock.Height,
461                                 Timestamp: c.deleteBlock.Timestamp,
462                         },
463                 }
464
465                 dbA := dbm.NewDB("dbu", "leveldb", "tempA")
466                 dbB := dbm.NewDB("dbc", "leveldb", "tempB")
467
468                 storeA := NewStore(dbA)
469                 storeB := NewStore(dbB)
470
471                 for i := 0; i < len(c.initBlocks); i++ {
472                         block := &types.Block{
473                                 BlockHeader: types.BlockHeader{
474                                         Version:   c.initBlocks[i].Version,
475                                         Height:    c.initBlocks[i].Height,
476                                         Timestamp: c.initBlocks[i].Timestamp,
477                                 },
478                         }
479                         if err := storeA.SaveBlock(block, verifyStatus); err != nil {
480                                 t.Fatal(err)
481                         }
482                 }
483
484                 if err := storeA.DeleteBlock(deleteBlock); err != nil {
485                         t.Fatal(err)
486                 }
487
488                 for i := 0; i < len(c.wantBlocks); i++ {
489                         block := &types.Block{
490                                 BlockHeader: types.BlockHeader{
491                                         Version:   c.wantBlocks[i].Version,
492                                         Height:    c.wantBlocks[i].Height,
493                                         Timestamp: c.wantBlocks[i].Timestamp,
494                                 },
495                         }
496                         if err := storeB.SaveBlock(block, verifyStatus); err != nil {
497                                 t.Fatal(err)
498                         }
499                 }
500
501                 iterA := dbA.Iterator()
502                 iterB := dbB.Iterator()
503
504                 for iterA.Next() && iterB.Next() {
505                         require.Equal(t, iterA.Key(), iterB.Key())
506                         require.Equal(t, iterA.Value(), iterB.Value())
507                 }
508
509                 if iterA.Next() || iterB.Next() {
510                         t.Fatalf("why iterator is not finished")
511                 }
512
513                 dbA.Close()
514                 os.RemoveAll("tempA")
515                 dbB.Close()
516                 os.RemoveAll("tempB")
517         }
518 }