"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"
"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)
- }
-}