X-Git-Url: http://git.osdn.net/view?p=bytom%2Fvapor.git;a=blobdiff_plain;f=database%2Fstore_test.go;h=3686838d917c1e41caf825dd3ac80905f511d72e;hp=deffc0517ae17aae18eb840269c788736e02fd1e;hb=31f8f7cf1ffbec5365ab6ebf217537809cf714e5;hpb=e34f38162f5d016893e53d6f14d47ed06dafe031 diff --git a/database/store_test.go b/database/store_test.go index deffc051..3686838d 100644 --- a/database/store_test.go +++ b/database/store_test.go @@ -4,7 +4,7 @@ import ( "os" "testing" - "github.com/vapor/config" + "github.com/vapor/consensus" dbm "github.com/vapor/database/leveldb" "github.com/vapor/database/storage" "github.com/vapor/protocol" @@ -14,211 +14,279 @@ import ( "github.com/vapor/testutil" ) -func TestLoadBlockIndex(t *testing.T) { - defer os.RemoveAll("temp") +func TestSaveChainStatus(t *testing.T) { testDB := dbm.NewDB("testdb", "leveldb", "temp") + defer func() { + testDB.Close() + os.RemoveAll("temp") + }() + store := NewStore(testDB) - block := config.GenesisBlock() - txStatus := bc.NewTransactionStatus() + blockHeader := &types.BlockHeader{Height: 100} + blockHash := blockHeader.Hash() //Hash: bc.Hash{V0: 0, V1: 1, V2: 2, V3: 3} + view := &state.UtxoViewpoint{ + Entries: map[bc.Hash]*storage.UtxoEntry{ + bc.Hash{V0: 1, V1: 2, V2: 3, V3: 4}: &storage.UtxoEntry{Type: storage.NormalUTXOType, BlockHeight: 100, Spent: false}, + bc.Hash{V0: 1, V1: 2, V2: 3, V3: 4}: &storage.UtxoEntry{Type: storage.CoinbaseUTXOType, BlockHeight: 100, Spent: true}, + bc.Hash{V0: 1, V1: 1, V2: 3, V3: 4}: &storage.UtxoEntry{Type: storage.NormalUTXOType, BlockHeight: 100, Spent: true}, + bc.Hash{V0: 1, V1: 1, V2: 3, V3: 5}: &storage.UtxoEntry{Type: storage.CrosschainUTXOType, BlockHeight: 100, Spent: false}, + bc.Hash{V0: 1, V1: 1, V2: 3, V3: 6}: &storage.UtxoEntry{Type: storage.CrosschainUTXOType, BlockHeight: 100, Spent: true}, + bc.Hash{V0: 1, V1: 3, V2: 3, V3: 7}: &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 100, Spent: false}, + bc.Hash{V0: 1, V1: 3, V2: 3, V3: 7}: &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 100, Spent: true}, + }, + } - if err := store.SaveBlock(block, txStatus); err != nil { + if err := store.SaveChainStatus(blockHeader, blockHeader, []*types.BlockHeader{blockHeader}, view, []*state.ConsensusResult{}); err != nil { t.Fatal(err) } - for block.Height <= 128 { - preHash := block.Hash() - block.PreviousBlockHash = preHash - block.Height++ - if err := store.SaveBlock(block, txStatus); err != nil { - t.Fatal(err) - } + expectStatus := &protocol.BlockStoreState{Height: blockHeader.Height, Hash: &blockHash, IrreversibleHeight: blockHeader.Height, IrreversibleHash: &blockHash} + if !testutil.DeepEqual(store.GetStoreStatus(), expectStatus) { + t.Errorf("got block status:%v, expect block status:%v", store.GetStoreStatus(), expectStatus) + } - if block.Height%32 != 0 { + for hash, utxo := range view.Entries { + if (utxo.Type == storage.NormalUTXOType) && utxo.Spent { + continue + } + if (utxo.Type == storage.CrosschainUTXOType) && (!utxo.Spent) { + continue + } + if (utxo.Type == storage.VoteUTXOType) && (utxo.Spent) { continue } - for i := uint64(0); i < block.Height/32; i++ { - block.Version++ - if err := store.SaveBlock(block, txStatus); err != nil { - t.Fatal(err) - } + gotUtxo, err := store.GetUtxo(&hash) + if err != nil { + t.Fatal(err) } - } - if _, err := store.LoadBlockIndex(128); err != nil { - t.Fatal(err) + if !testutil.DeepEqual(utxo, gotUtxo) { + t.Errorf("got utxo entry:%v, expect utxo entry:%v", gotUtxo, utxo) + } } } -func TestLoadBlockIndexBestHeight(t *testing.T) { +func TestSaveBlock(t *testing.T) { + testDB := dbm.NewDB("testdb", "leveldb", "temp") + defer func() { + testDB.Close() + os.RemoveAll("temp") + }() + + store := NewStore(testDB) + coinbaseTxData := &types.TxData{ + Version: 1, + Inputs: []*types.TxInput{ + types.NewCoinbaseInput([]byte("Information is power. -- Jan/11/2013. Computing is power. -- Apr/24/2018.")), + }, + Outputs: []*types.TxOutput{ + types.NewVoteOutput(*consensus.BTMAssetID, uint64(10000), []byte{0x51}, []byte{0x51}), + }, + } + coinbaseTx := types.NewTx(*coinbaseTxData) + cases := []struct { - blockBestHeight uint64 - stateBestHeight uint64 + txData []*types.TxData + txStatus *bc.TransactionStatus + blockHeader *types.BlockHeader }{ { - blockBestHeight: 100, - stateBestHeight: 90, + txStatus: &bc.TransactionStatus{ + VerifyStatus: []*bc.TxVerifyResult{ + {StatusFail: true}, + }, + }, + blockHeader: &types.BlockHeader{ + Version: uint64(1), + Height: uint64(1111), + Timestamp: uint64(1528945000), + }, }, { - blockBestHeight: 100, - stateBestHeight: 0, + txStatus: &bc.TransactionStatus{ + VerifyStatus: []*bc.TxVerifyResult{ + {StatusFail: false}, + }, + }, + blockHeader: &types.BlockHeader{ + Version: uint64(1), + Height: uint64(1111), + Timestamp: uint64(1528945000), + }, }, { - blockBestHeight: 100, - stateBestHeight: 100, + txData: []*types.TxData{ + { + Version: 1, + Inputs: []*types.TxInput{ + types.NewSpendInput([][]byte{}, bc.NewHash([32]byte{}), *consensus.BTMAssetID, 100000000, 0, []byte{0x51}), + }, + Outputs: []*types.TxOutput{ + types.NewVoteOutput(*consensus.BTMAssetID, uint64(10000), []byte{0x51}, []byte{0x51}), + }, + }, + }, + txStatus: &bc.TransactionStatus{ + VerifyStatus: []*bc.TxVerifyResult{ + {StatusFail: true}, + }, + }, + blockHeader: &types.BlockHeader{ + Version: uint64(1), + Height: uint64(1111), + Timestamp: uint64(1528945000), + }, + }, + { + txData: []*types.TxData{ + { + Version: 1, + Inputs: []*types.TxInput{ + types.NewSpendInput([][]byte{}, bc.NewHash([32]byte{}), *consensus.BTMAssetID, 100000000, 0, []byte{0x51}), + }, + Outputs: []*types.TxOutput{ + types.NewVoteOutput(*consensus.BTMAssetID, uint64(88888), []byte{0x51}, []byte{0x51}), + }, + }, + }, + txStatus: &bc.TransactionStatus{ + VerifyStatus: []*bc.TxVerifyResult{ + {StatusFail: false}, + }, + }, + blockHeader: &types.BlockHeader{ + Version: uint64(1), + Height: uint64(0), + Timestamp: uint64(152894500000), + }, }, } - defer os.RemoveAll("temp") - testDB := dbm.NewDB("testdb", "leveldb", "temp") - store := NewStore(testDB) - var savedBlocks []types.Block - - for _, c := range cases { - block := config.GenesisBlock() - txStatus := bc.NewTransactionStatus() - - for i := uint64(0); i < c.blockBestHeight; i++ { - if err := store.SaveBlock(block, txStatus); err != nil { - t.Fatal(err) - } + for i, c := range cases { + txs := []*bc.Tx{coinbaseTx.Tx} + for _, tx := range c.txData { + t := types.NewTx(*tx) + txs = append(txs, t.Tx) + } + merkleRoot, _ := types.TxMerkleRoot(txs) + txStatusHash, _ := types.TxStatusMerkleRoot(c.txStatus.VerifyStatus) + block := &types.Block{ + BlockHeader: types.BlockHeader{ + Version: c.blockHeader.Version, + Height: c.blockHeader.Height, + Timestamp: c.blockHeader.Timestamp, + BlockCommitment: types.BlockCommitment{ + TransactionsMerkleRoot: merkleRoot, + TransactionStatusHash: txStatusHash, + }, + }, + } - savedBlocks = append(savedBlocks, *block) - block.PreviousBlockHash = block.Hash() - block.Height++ + if err := store.SaveBlock(block, c.txStatus); err != nil { + t.Fatal(err) } - index, err := store.LoadBlockIndex(c.stateBestHeight) + blockHash := block.Hash() + gotBlock, err := store.GetBlock(&blockHash) if err != nil { t.Fatal(err) } - for _, block := range savedBlocks { - blockHash := block.Hash() - if block.Height <= c.stateBestHeight != index.BlockExist(&blockHash) { - t.Errorf("Error in load block index") - } + if !testutil.DeepEqual(gotBlock, block) { + t.Errorf("case %v: block mismatch: have %x, want %x", i, gotBlock, block) } - } -} - -func TestLoadBlockIndexEquals(t *testing.T) { - defer os.RemoveAll("temp") - testDB := dbm.NewDB("testdb", "leveldb", "temp") - store := NewStore(testDB) - - block := config.GenesisBlock() - txStatus := bc.NewTransactionStatus() - expectBlockIndex := state.NewBlockIndex() - var parent *state.BlockNode - for block.Height <= 100 { - if err := store.SaveBlock(block, txStatus); err != nil { + gotStatus, err := store.GetTransactionStatus(&blockHash) + if err != nil { t.Fatal(err) } - if block.Height != 0 { - parent = expectBlockIndex.GetNode(&block.PreviousBlockHash) + if !testutil.DeepEqual(gotStatus.VerifyStatus, c.txStatus.VerifyStatus) { + t.Errorf("case %v: VerifyStatus mismatch: have %x, want %x", i, gotStatus.VerifyStatus, c.txStatus.VerifyStatus) } - node, err := state.NewBlockNode(&block.BlockHeader, parent) + gotBlockHeader, err := store.GetBlockHeader(&blockHash) if err != nil { t.Fatal(err) } - expectBlockIndex.AddNode(node) - block.PreviousBlockHash = block.Hash() - block.Height++ - } - - index, err := store.LoadBlockIndex(100) - if err != nil { - t.Fatal(err) - } - - if !testutil.DeepEqual(expectBlockIndex, index) { - t.Errorf("got block index:%v, expect block index:%v", index, expectBlockIndex) + if !testutil.DeepEqual(block.BlockHeader, *gotBlockHeader) { + t.Errorf("got block header:%v, expect block header:%v", gotBlockHeader, block.BlockHeader) + } } } -func TestSaveChainStatus(t *testing.T) { - defer os.RemoveAll("temp") + +func TestSaveBlockHeader(t *testing.T) { testDB := dbm.NewDB("testdb", "leveldb", "temp") + defer func() { + testDB.Close() + os.RemoveAll("temp") + }() + store := NewStore(testDB) - node := &state.BlockNode{Height: 100, Hash: bc.Hash{V0: 0, V1: 1, V2: 2, V3: 3}} - view := &state.UtxoViewpoint{ - Entries: map[bc.Hash]*storage.UtxoEntry{ - bc.Hash{V0: 1, V1: 2, V2: 3, V3: 4}: &storage.UtxoEntry{IsCoinBase: false, BlockHeight: 100, Spent: false}, - bc.Hash{V0: 1, V1: 2, V2: 3, V3: 4}: &storage.UtxoEntry{IsCoinBase: true, BlockHeight: 100, Spent: true}, - bc.Hash{V0: 1, V1: 1, V2: 3, V3: 4}: &storage.UtxoEntry{IsCoinBase: false, BlockHeight: 100, Spent: true}, + cases := []struct { + blockHeader *types.BlockHeader + }{ + { + blockHeader: &types.BlockHeader{ + Version: uint64(1), + Height: uint64(1111), + Timestamp: uint64(1528945000), + }, + }, + { + blockHeader: &types.BlockHeader{ + Version: uint64(1), + Height: uint64(0), + 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}), + Timestamp: uint64(1563186936), + BlockCommitment: types.BlockCommitment{ + 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}), + 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}), + }, + BlockWitness: types.BlockWitness{ + Witness: [][]byte{[]byte{0x3e, 0x94, 0x5d, 0x35}, []byte{0x3e, 0x94, 0x5d, 0x35}}, + }, + }, + }, + { + blockHeader: &types.BlockHeader{ + Version: uint64(1), + Height: uint64(8848), + 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}), + Timestamp: uint64(156318693600), + BlockCommitment: types.BlockCommitment{ + 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}), + 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}), + }, + BlockWitness: types.BlockWitness{ + Witness: [][]byte{ + []byte{0x3e, 0x94, 0x5d, 0x35}, + []byte{0xdd, 0x80, 0x67, 0x29}, + []byte{0xff, 0xff, 0xff, 0xff}, + []byte{0x00, 0x01, 0x02, 0x03}, + }, + }, + }, }, } - if err := store.SaveChainStatus(node, node, view, map[uint64]*state.VoteResult{}); err != nil { - t.Fatal(err) - } - - expectStatus := &protocol.BlockStoreState{Height: node.Height, Hash: &node.Hash, IrreversibleHeight: node.Height, IrreversibleHash: &node.Hash} - if !testutil.DeepEqual(store.GetStoreStatus(), expectStatus) { - t.Errorf("got block status:%v, expect block status:%v", store.GetStoreStatus(), expectStatus) - } - - for hash, utxo := range view.Entries { - if utxo.Spent && !utxo.IsCoinBase { - continue + for i, c := range cases { + if err := store.SaveBlockHeader(c.blockHeader); err != nil { + t.Fatal(err) } - gotUtxo, err := store.GetUtxo(&hash) + blockHash := c.blockHeader.Hash() + gotBlockHeader, err := store.GetBlockHeader(&blockHash) if err != nil { t.Fatal(err) } - if !testutil.DeepEqual(utxo, gotUtxo) { - t.Errorf("got utxo entry:%v, expect utxo entry:%v", gotUtxo, utxo) + if !testutil.DeepEqual(gotBlockHeader, c.blockHeader) { + t.Errorf("case %v: block header mismatch: have %x, want %x", i, gotBlockHeader, c.blockHeader) } } } - -func TestSaveBlock(t *testing.T) { - defer os.RemoveAll("temp") - testDB := dbm.NewDB("testdb", "leveldb", "temp") - store := NewStore(testDB) - - block := config.GenesisBlock() - status := &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{{StatusFail: true}}} - if err := store.SaveBlock(block, status); err != nil { - t.Fatal(err) - } - - blockHash := block.Hash() - gotBlock, err := store.GetBlock(&blockHash) - if err != nil { - t.Fatal(err) - } - - gotBlock.Transactions[0].Tx.SerializedSize = 0 - gotBlock.Transactions[0].SerializedSize = 0 - if !testutil.DeepEqual(block, gotBlock) { - t.Errorf("got block:%v, expect block:%v", gotBlock, block) - } - - gotStatus, err := store.GetTransactionStatus(&blockHash) - if err != nil { - t.Fatal(err) - } - - if !testutil.DeepEqual(status, gotStatus) { - t.Errorf("got status:%v, expect status:%v", gotStatus, status) - } - - data := store.db.Get(calcBlockHeaderKey(block.Height, &blockHash)) - gotBlockHeader := types.BlockHeader{} - if err := gotBlockHeader.UnmarshalText(data); err != nil { - t.Fatal(err) - } - - if !testutil.DeepEqual(block.BlockHeader, gotBlockHeader) { - t.Errorf("got block header:%v, expect block header:%v", gotBlockHeader, block.BlockHeader) - } -}