7 "github.com/stretchr/testify/require"
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"
19 func TestSaveChainStatus(t *testing.T) {
20 testDB := dbm.NewDB("testdb", "leveldb", "temp")
26 store := NewStore(testDB)
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},
42 if err := store.SaveChainStatus(blockHeader, blockHeader, []*types.BlockHeader{blockHeader}, view, []*state.ConsensusResult{}); err != nil {
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)
51 for hash, utxo := range view.Entries {
52 if (utxo.Type == storage.NormalUTXOType) && utxo.Spent {
55 if (utxo.Type == storage.CrosschainUTXOType) && (!utxo.Spent) {
58 if (utxo.Type == storage.VoteUTXOType) && (utxo.Spent) {
62 gotUtxo, err := store.GetUtxo(&hash)
67 if !testutil.DeepEqual(utxo, gotUtxo) {
68 t.Errorf("got utxo entry:%v, expect utxo entry:%v", gotUtxo, utxo)
73 func TestSaveBlock(t *testing.T) {
74 testDB := dbm.NewDB("testdb", "leveldb", "temp")
80 store := NewStore(testDB)
81 coinbaseTxData := &types.TxData{
83 Inputs: []*types.TxInput{
84 types.NewCoinbaseInput([]byte("Information is power. -- Jan/11/2013. Computing is power. -- Apr/24/2018.")),
86 Outputs: []*types.TxOutput{
87 types.NewVoteOutput(*consensus.BTMAssetID, uint64(10000), []byte{0x51}, []byte{0x51}),
90 coinbaseTx := types.NewTx(*coinbaseTxData)
93 txData []*types.TxData
94 txStatus *bc.TransactionStatus
95 blockHeader *types.BlockHeader
98 txStatus: &bc.TransactionStatus{
99 VerifyStatus: []*bc.TxVerifyResult{
103 blockHeader: &types.BlockHeader{
105 Height: uint64(1111),
106 Timestamp: uint64(1528945000),
110 txStatus: &bc.TransactionStatus{
111 VerifyStatus: []*bc.TxVerifyResult{
115 blockHeader: &types.BlockHeader{
117 Height: uint64(1111),
118 Timestamp: uint64(1528945000),
122 txData: []*types.TxData{
125 Inputs: []*types.TxInput{
126 types.NewSpendInput([][]byte{}, bc.NewHash([32]byte{}), *consensus.BTMAssetID, 100000000, 0, []byte{0x51}),
128 Outputs: []*types.TxOutput{
129 types.NewVoteOutput(*consensus.BTMAssetID, uint64(10000), []byte{0x51}, []byte{0x51}),
133 txStatus: &bc.TransactionStatus{
134 VerifyStatus: []*bc.TxVerifyResult{
138 blockHeader: &types.BlockHeader{
140 Height: uint64(1111),
141 Timestamp: uint64(1528945000),
145 txData: []*types.TxData{
148 Inputs: []*types.TxInput{
149 types.NewSpendInput([][]byte{}, bc.NewHash([32]byte{}), *consensus.BTMAssetID, 100000000, 0, []byte{0x51}),
151 Outputs: []*types.TxOutput{
152 types.NewVoteOutput(*consensus.BTMAssetID, uint64(88888), []byte{0x51}, []byte{0x51}),
156 txStatus: &bc.TransactionStatus{
157 VerifyStatus: []*bc.TxVerifyResult{
161 blockHeader: &types.BlockHeader{
164 Timestamp: uint64(152894500000),
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)
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,
189 if err := store.SaveBlock(block, c.txStatus); err != nil {
193 blockHash := block.Hash()
194 gotBlock, err := store.GetBlock(&blockHash)
199 if !testutil.DeepEqual(gotBlock, block) {
200 t.Errorf("case %v: block mismatch: have %x, want %x", i, gotBlock, block)
203 gotStatus, err := store.GetTransactionStatus(&blockHash)
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)
212 gotBlockHeader, err := store.GetBlockHeader(&blockHash)
217 if !testutil.DeepEqual(block.BlockHeader, *gotBlockHeader) {
218 t.Errorf("got block header:%v, expect block header:%v", gotBlockHeader, block.BlockHeader)
223 func TestSaveBlockHeader(t *testing.T) {
224 testDB := dbm.NewDB("testdb", "leveldb", "temp")
230 store := NewStore(testDB)
233 blockHeader *types.BlockHeader
236 blockHeader: &types.BlockHeader{
238 Height: uint64(1111),
239 Timestamp: uint64(1528945000),
243 blockHeader: &types.BlockHeader{
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}),
252 BlockWitness: types.BlockWitness{
253 Witness: [][]byte{[]byte{0x3e, 0x94, 0x5d, 0x35}, []byte{0x3e, 0x94, 0x5d, 0x35}},
258 blockHeader: &types.BlockHeader{
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}),
267 BlockWitness: types.BlockWitness{
269 []byte{0x3e, 0x94, 0x5d, 0x35},
270 []byte{0xdd, 0x80, 0x67, 0x29},
271 []byte{0xff, 0xff, 0xff, 0xff},
272 []byte{0x00, 0x01, 0x02, 0x03},
279 for i, c := range cases {
280 if err := store.SaveBlockHeader(c.blockHeader); err != nil {
284 blockHash := c.blockHeader.Hash()
285 gotBlockHeader, err := store.GetBlockHeader(&blockHash)
290 if !testutil.DeepEqual(gotBlockHeader, c.blockHeader) {
291 t.Errorf("case %v: block header mismatch: have %x, want %x", i, gotBlockHeader, c.blockHeader)
296 func TestDeleteBlock(t *testing.T) {
298 initBlocks []*types.BlockHeader
299 deleteBlock *types.BlockHeader
300 wantBlocks []*types.BlockHeader
303 initBlocks: []*types.BlockHeader{},
304 deleteBlock: &types.BlockHeader{
307 Timestamp: uint64(1528945000),
309 wantBlocks: []*types.BlockHeader{},
312 initBlocks: []*types.BlockHeader{
316 Timestamp: uint64(1528945000),
321 Timestamp: uint64(1528945005),
326 Timestamp: uint64(1528945010),
329 deleteBlock: &types.BlockHeader{
332 Timestamp: uint64(1528945000),
334 wantBlocks: []*types.BlockHeader{
338 Timestamp: uint64(1528945005),
343 Timestamp: uint64(1528945010),
348 initBlocks: []*types.BlockHeader{
352 Timestamp: uint64(1528945000),
357 Timestamp: uint64(1528945005),
362 Timestamp: uint64(1528945010),
365 deleteBlock: &types.BlockHeader{
368 Timestamp: uint64(1528945005),
370 wantBlocks: []*types.BlockHeader{
374 Timestamp: uint64(1528945000),
379 Timestamp: uint64(1528945010),
384 initBlocks: []*types.BlockHeader{
388 Timestamp: uint64(1528945000),
393 Timestamp: uint64(1528945005),
398 Timestamp: uint64(1528945010),
401 deleteBlock: &types.BlockHeader{
404 Timestamp: uint64(1528945010),
406 wantBlocks: []*types.BlockHeader{
410 Timestamp: uint64(1528945000),
415 Timestamp: uint64(1528945005),
420 initBlocks: []*types.BlockHeader{},
421 deleteBlock: &types.BlockHeader{
424 Timestamp: uint64(1528945030),
426 wantBlocks: []*types.BlockHeader{},
429 initBlocks: []*types.BlockHeader{
433 Timestamp: uint64(1528945000),
436 deleteBlock: &types.BlockHeader{
439 Timestamp: uint64(1528945030),
441 wantBlocks: []*types.BlockHeader{
445 Timestamp: uint64(1528945000),
451 for _, c := range cases {
452 verifyStatus := &bc.TransactionStatus{
453 VerifyStatus: []*bc.TxVerifyResult{
457 deleteBlock := &types.Block{
458 BlockHeader: types.BlockHeader{
459 Version: c.deleteBlock.Version,
460 Height: c.deleteBlock.Height,
461 Timestamp: c.deleteBlock.Timestamp,
465 dbA := dbm.NewDB("dbu", "leveldb", "tempA")
466 dbB := dbm.NewDB("dbc", "leveldb", "tempB")
468 storeA := NewStore(dbA)
469 storeB := NewStore(dbB)
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,
479 if err := storeA.SaveBlock(block, verifyStatus); err != nil {
484 if err := storeA.DeleteBlock(deleteBlock); err != nil {
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,
496 if err := storeB.SaveBlock(block, verifyStatus); err != nil {
501 iterA := dbA.Iterator()
502 iterB := dbB.Iterator()
504 for iterA.Next() && iterB.Next() {
505 require.Equal(t, iterA.Key(), iterB.Key())
506 require.Equal(t, iterA.Value(), iterB.Value())
509 if iterA.Next() || iterB.Next() {
510 t.Fatalf("why iterator is not finished")
514 os.RemoveAll("tempA")
516 os.RemoveAll("tempB")