Unverified Commit 881935c9 authored by Paladz's avatar Paladz Committed by GitHub

Merge pull request #1739 from Bytom/revert-1738-process_block_integra_test

Revert "block integration test"
parents d3cd712c 6767ccf1
......@@ -21,14 +21,14 @@ import (
const logModule = "leveldb"
var (
BlockStoreKey = []byte("blockStore")
BlockPrefix = []byte("B:")
BlockHeaderPrefix = []byte("BH:")
TxStatusPrefix = []byte("BTS:")
blockStoreKey = []byte("blockStore")
blockPrefix = []byte("B:")
blockHeaderPrefix = []byte("BH:")
txStatusPrefix = []byte("BTS:")
)
func loadBlockStoreStateJSON(db dbm.DB) *protocol.BlockStoreState {
bytes := db.Get(BlockStoreKey)
bytes := db.Get(blockStoreKey)
if bytes == nil {
return nil
}
......@@ -47,24 +47,24 @@ type Store struct {
cache blockCache
}
func CalcBlockKey(hash *bc.Hash) []byte {
return append(BlockPrefix, hash.Bytes()...)
func calcBlockKey(hash *bc.Hash) []byte {
return append(blockPrefix, hash.Bytes()...)
}
func CalcBlockHeaderKey(height uint64, hash *bc.Hash) []byte {
func calcBlockHeaderKey(height uint64, hash *bc.Hash) []byte {
buf := [8]byte{}
binary.BigEndian.PutUint64(buf[:], height)
key := append(BlockHeaderPrefix, buf[:]...)
key := append(blockHeaderPrefix, buf[:]...)
return append(key, hash.Bytes()...)
}
func CalcTxStatusKey(hash *bc.Hash) []byte {
return append(TxStatusPrefix, hash.Bytes()...)
func calcTxStatusKey(hash *bc.Hash) []byte {
return append(txStatusPrefix, hash.Bytes()...)
}
// GetBlock return the block by given hash
func GetBlock(db dbm.DB, hash *bc.Hash) (*types.Block, error) {
bytez := db.Get(CalcBlockKey(hash))
bytez := db.Get(calcBlockKey(hash))
if bytez == nil {
return nil, nil
}
......@@ -108,7 +108,7 @@ func (s *Store) GetTransactionsUtxo(view *state.UtxoViewpoint, txs []*bc.Tx) err
// GetTransactionStatus will return the utxo that related to the block hash
func (s *Store) GetTransactionStatus(hash *bc.Hash) (*bc.TransactionStatus, error) {
data := s.db.Get(CalcTxStatusKey(hash))
data := s.db.Get(calcTxStatusKey(hash))
if data == nil {
return nil, errors.New("can't find the transaction status by given hash")
}
......@@ -128,7 +128,7 @@ func (s *Store) GetStoreStatus() *protocol.BlockStoreState {
func (s *Store) LoadBlockIndex(stateBestHeight uint64) (*state.BlockIndex, error) {
startTime := time.Now()
blockIndex := state.NewBlockIndex()
bhIter := s.db.IteratorPrefix(BlockHeaderPrefix)
bhIter := s.db.IteratorPrefix(blockHeaderPrefix)
defer bhIter.Release()
var lastNode *state.BlockNode
......@@ -188,9 +188,9 @@ func (s *Store) SaveBlock(block *types.Block, ts *bc.TransactionStatus) error {
blockHash := block.Hash()
batch := s.db.NewBatch()
batch.Set(CalcBlockKey(&blockHash), binaryBlock)
batch.Set(CalcBlockHeaderKey(block.Height, &blockHash), binaryBlockHeader)
batch.Set(CalcTxStatusKey(&blockHash), binaryTxStatus)
batch.Set(calcBlockKey(&blockHash), binaryBlock)
batch.Set(calcBlockHeaderKey(block.Height, &blockHash), binaryBlockHeader)
batch.Set(calcTxStatusKey(&blockHash), binaryTxStatus)
batch.Write()
log.WithFields(log.Fields{
......@@ -214,7 +214,7 @@ func (s *Store) SaveChainStatus(node *state.BlockNode, view *state.UtxoViewpoint
return err
}
batch.Set(BlockStoreKey, bytes)
batch.Set(blockStoreKey, bytes)
batch.Write()
return nil
}
......@@ -212,7 +212,7 @@ func TestSaveBlock(t *testing.T) {
t.Errorf("got status:%v, expect status:%v", gotStatus, status)
}
data := store.db.Get(CalcBlockHeaderKey(block.Height, &blockHash))
data := store.db.Get(calcBlockHeaderKey(block.Height, &blockHash))
gotBlockHeader := types.BlockHeader{}
if err := gotBlockHeader.UnmarshalText(data); err != nil {
t.Fatal(err)
......
......@@ -9,10 +9,10 @@ import (
dbm "github.com/bytom/database/leveldb"
)
const UtxoPreFix = "UT:"
const utxoPreFix = "UT:"
func CalcUtxoKey(hash *bc.Hash) []byte {
return []byte(UtxoPreFix + hash.String())
func calcUtxoKey(hash *bc.Hash) []byte {
return []byte(utxoPreFix + hash.String())
}
func getTransactionsUtxo(db dbm.DB, view *state.UtxoViewpoint, txs []*bc.Tx) error {
......@@ -22,7 +22,7 @@ func getTransactionsUtxo(db dbm.DB, view *state.UtxoViewpoint, txs []*bc.Tx) err
continue
}
data := db.Get(CalcUtxoKey(&prevout))
data := db.Get(calcUtxoKey(&prevout))
if data == nil {
continue
}
......@@ -41,7 +41,7 @@ func getTransactionsUtxo(db dbm.DB, view *state.UtxoViewpoint, txs []*bc.Tx) err
func getUtxo(db dbm.DB, hash *bc.Hash) (*storage.UtxoEntry, error) {
var utxo storage.UtxoEntry
data := db.Get(CalcUtxoKey(hash))
data := db.Get(calcUtxoKey(hash))
if data == nil {
return nil, errors.New("can't find utxo in db")
}
......@@ -54,7 +54,7 @@ func getUtxo(db dbm.DB, hash *bc.Hash) (*storage.UtxoEntry, error) {
func saveUtxoView(batch dbm.Batch, view *state.UtxoViewpoint) error {
for key, entry := range view.Entries {
if entry.Spent && !entry.IsCoinBase {
batch.Delete(CalcUtxoKey(&key))
batch.Delete(calcUtxoKey(&key))
continue
}
......@@ -62,7 +62,7 @@ func saveUtxoView(batch dbm.Batch, view *state.UtxoViewpoint) error {
if err != nil {
return errors.Wrap(err, "marshaling utxo entry")
}
batch.Set(CalcUtxoKey(&key), b)
batch.Set(calcUtxoKey(&key), b)
}
return nil
}
......
......@@ -8,7 +8,6 @@ import (
"github.com/bytom/protocol/bc"
"github.com/bytom/protocol/bc/types"
"github.com/bytom/testutil"
)
var (
......@@ -92,18 +91,6 @@ func (o *OrphanManage) GetPrevOrphans(hash *bc.Hash) ([]*bc.Hash, bool) {
return prevOrphans, ok
}
func (o *OrphanManage) Equals(o1 *OrphanManage) bool {
if o1 == nil {
return false
}
if !testutil.DeepEqual(o.orphan, o1.orphan) {
return false
}
return testutil.DeepEqual(o.prevOrphans, o1.prevOrphans)
}
func (o *OrphanManage) delete(hash *bc.Hash) {
block, ok := o.orphan[*hash]
if !ok {
......
......@@ -28,12 +28,8 @@ type Chain struct {
// NewChain returns a new Chain using store as the underlying storage.
func NewChain(store Store, txPool *TxPool) (*Chain, error) {
return NewChainWithOrphanManage(store, txPool, NewOrphanManage())
}
func NewChainWithOrphanManage(store Store, txPool *TxPool, manage *OrphanManage) (*Chain, error) {
c := &Chain{
orphanManage: manage,
orphanManage: NewOrphanManage(),
txPool: txPool,
store: store,
processBlockCh: make(chan *processBlockMsg, maxProcessBlockChSize),
......@@ -128,10 +124,6 @@ func (c *Chain) CalcNextBits(preBlock *bc.Hash) (uint64, error) {
return node.CalcNextBits(), nil
}
func (c *Chain) GetBlockIndex() *state.BlockIndex {
return c.index
}
// This function must be called with mu lock in above level
func (c *Chain) setState(node *state.BlockNode, view *state.UtxoViewpoint) error {
if err := c.store.SaveChainStatus(node, view); err != nil {
......
......@@ -11,7 +11,6 @@ import (
"github.com/bytom/consensus/difficulty"
"github.com/bytom/protocol/bc"
"github.com/bytom/protocol/bc/types"
"github.com/bytom/testutil"
)
// approxNodesPerDay is an approximation of the number of new blocks there are
......@@ -134,10 +133,6 @@ func NewBlockIndex() *BlockIndex {
}
}
func NewBlockIndexWithInitData(index map[bc.Hash]*BlockNode, mainChain []*BlockNode) *BlockIndex {
return &BlockIndex{index:index, mainChain:mainChain}
}
// AddNode will add node to the index map
func (bi *BlockIndex) AddNode(node *BlockNode) {
bi.Lock()
......@@ -215,14 +210,3 @@ func (bi *BlockIndex) SetMainChain(node *BlockNode) {
node = node.Parent
}
}
func (bi *BlockIndex) Equals(bi1 *BlockIndex) bool {
if bi1 == nil {
return false
}
if !testutil.DeepEqual(bi.index, bi1.index) {
return false
}
return testutil.DeepEqual(bi.mainChain, bi1.mainChain)
}
package integration
import (
"testing"
"github.com/bytom/config"
"github.com/bytom/database"
"github.com/bytom/database/storage"
"github.com/bytom/protocol"
"github.com/bytom/protocol/bc"
"github.com/bytom/protocol/bc/types"
"github.com/bytom/protocol/state"
)
func TestProcessBlock(t *testing.T) {
gensisBlock := config.GenesisBlock()
genesisBlockHash := gensisBlock.Hash()
fillTransactionSize(gensisBlock)
cases := []*processBlockTestCase{
{
desc: "process a invalid block",
newBlock: &types.Block{
BlockHeader: types.BlockHeader{
Height: 1,
Version: 1,
PreviousBlockHash: genesisBlockHash,
},
},
wantStore: storeItems{
{
key: database.BlockStoreKey,
val: &protocol.BlockStoreState{Height: 0, Hash: &genesisBlockHash},
},
{
key: database.CalcBlockKey(&genesisBlockHash),
val: gensisBlock,
},
{
key: database.CalcTxStatusKey(&genesisBlockHash),
val: &bc.TransactionStatus{Version: 1, VerifyStatus: []*bc.TxVerifyResult{{StatusFail: false}}},
},
{
key: database.CalcBlockHeaderKey(gensisBlock.Height, &genesisBlockHash),
val: gensisBlock.BlockHeader,
},
{
key: database.CalcUtxoKey(gensisBlock.Transactions[0].Tx.ResultIds[0]),
val: &storage.UtxoEntry{IsCoinBase: true, BlockHeight: 0, Spent: false},
},
},
wantBlockIndex: state.NewBlockIndexWithInitData(
map[bc.Hash]*state.BlockNode{
genesisBlockHash: mustNewBlockNode(&gensisBlock.BlockHeader, nil),
},
[]*state.BlockNode{
mustNewBlockNode(&gensisBlock.BlockHeader, nil),
},
),
wantOrphanManage: protocol.NewOrphanManage(),
wantError: true,
},
}
for _, c := range cases {
if err := c.Run(); err != nil {
panic(err)
}
}
}
func mustNewBlockNode(h *types.BlockHeader, parent *state.BlockNode) *state.BlockNode {
node, err := state.NewBlockNode(h, parent)
if err != nil {
panic(err)
}
return node
}
func fillTransactionSize(block *types.Block) {
for _, tx := range block.Transactions {
bytes, err := tx.MarshalText()
if err != nil {
panic(err)
}
tx.TxData.SerializedSize = uint64(len(bytes) / 2)
tx.Tx.SerializedSize = uint64(len(bytes) / 2)
}
}
package integration
import (
"encoding/json"
"fmt"
"os"
"reflect"
"strings"
"github.com/golang/protobuf/proto"
"github.com/bytom/database"
dbm "github.com/bytom/database/leveldb"
"github.com/bytom/database/storage"
"github.com/bytom/event"
"github.com/bytom/protocol"
"github.com/bytom/protocol/bc"
"github.com/bytom/protocol/bc/types"
"github.com/bytom/protocol/state"
"github.com/bytom/testutil"
)
const (
dbDir = "temp"
)
type storeItem struct {
key []byte
val interface{}
}
type serialFun func(obj interface{}) ([]byte, error)
type deserialFun func(data []byte) (interface{}, error)
func getSerialFun(item interface{}) (serialFun, error) {
switch item.(type) {
case *protocol.BlockStoreState:
return json.Marshal, nil
case *types.Block:
return func(obj interface{}) ([]byte, error) {
block := obj.(*types.Block)
return block.MarshalText()
}, nil
case types.BlockHeader:
return func(obj interface{}) ([]byte, error) {
bh := obj.(types.BlockHeader)
return bh.MarshalText()
}, nil
case *bc.TransactionStatus:
return func(obj interface{}) ([]byte, error) {
status := obj.(*bc.TransactionStatus)
return proto.Marshal(status)
}, nil
case *storage.UtxoEntry:
return func(obj interface{}) ([]byte, error) {
utxo := obj.(*storage.UtxoEntry)
return proto.Marshal(utxo)
}, nil
}
typ := reflect.TypeOf(item)
return nil, fmt.Errorf("can not found any serialization function for type:%s", typ.Name())
}
func getDeserailFun(key []byte) (deserialFun, error) {
funMap := map[string]deserialFun{
string(database.BlockStoreKey): func(data []byte) (interface{}, error) {
storeState := &protocol.BlockStoreState{}
err := json.Unmarshal(data, storeState)
return storeState, err
},
string(database.TxStatusPrefix): func(data []byte) (interface{}, error) {
status := &bc.TransactionStatus{}
err := proto.Unmarshal(data, status)
return status, err
},
string(database.BlockPrefix): func(data []byte) (interface{}, error) {
block := &types.Block{}
err := block.UnmarshalText(data)
return block, err
},
string(database.BlockHeaderPrefix): func(data []byte) (interface{}, error) {
bh := types.BlockHeader{}
err := bh.UnmarshalText(data)
return bh, err
},
database.UtxoPreFix: func(data []byte) (interface{}, error) {
utxo := &storage.UtxoEntry{}
err := proto.Unmarshal(data, utxo)
return utxo, err
},
}
for prefix, converter := range funMap {
if strings.HasPrefix(string(key), prefix) {
return converter, nil
}
}
return nil, fmt.Errorf("can not found any deserialization function for key:%s", string(key))
}
type storeItems []*storeItem
func (s1 storeItems) equals(s2 storeItems) bool {
if s2 == nil {
return false
}
itemMap1 := make(map[string]interface{}, len(s1))
for _, item := range s1 {
itemMap1[string(item.key)] = item.val
}
itemMap2 := make(map[string]interface{}, len(s2))
for _, item := range s2 {
itemMap2[string(item.key)] = item.val
}
return testutil.DeepEqual(itemMap1, itemMap2)
}
type processBlockTestCase struct {
desc string
initStore []*storeItem
wantStore []*storeItem
wantBlockIndex *state.BlockIndex
initOrphanManage *protocol.OrphanManage
wantOrphanManage *protocol.OrphanManage
wantIsOrphan bool
wantError bool
newBlock *types.Block
}
func (p *processBlockTestCase) Run() error {
defer os.RemoveAll(dbDir)
if p.initStore == nil {
p.initStore = make([]*storeItem, 0)
}
store, db, err := initStore(p)
if err != nil {
return err
}
orphanManage := p.initOrphanManage
if orphanManage == nil {
orphanManage = protocol.NewOrphanManage()
}
txPool := protocol.NewTxPool(store, event.NewDispatcher())
chain, err := protocol.NewChainWithOrphanManage(store, txPool, orphanManage)
if err != nil {
return err
}
isOrphan, err := chain.ProcessBlock(p.newBlock)
if p.wantError != (err != nil) {
return fmt.Errorf("#case(%s) want error:%t, got error:%t", p.desc, p.wantError, err != nil)
}
if isOrphan != p.wantIsOrphan {
return fmt.Errorf("#case(%s) want orphan:%t, got orphan:%t", p.desc, p.wantIsOrphan, isOrphan)
}
if p.wantStore != nil {
gotStoreItems, err := loadStoreItems(db)
if err != nil {
return err
}
if !storeItems(gotStoreItems).equals(p.wantStore) {
return fmt.Errorf("#case(%s) want store:%v, got store:%v", p.desc, p.wantStore, gotStoreItems)
}
}
if p.wantBlockIndex != nil {
blockIndex := chain.GetBlockIndex()
if !blockIndex.Equals(p.wantBlockIndex) {
return fmt.Errorf("#case(%s) want block index:%v, got block index:%v", p.desc, *p.wantBlockIndex, *blockIndex)
}
}
if p.wantOrphanManage != nil {
if !orphanManage.Equals(p.wantOrphanManage) {
return fmt.Errorf("#case(%s) want orphan manage:%v, got orphan manage:%v", p.desc, *p.wantOrphanManage, *orphanManage)
}
}
return nil
}
func loadStoreItems(db dbm.DB) ([]*storeItem, error) {
iter := db.Iterator()
defer iter.Release()
var items []*storeItem
for iter.Next() {
item := &storeItem{key: iter.Key()}
fun, err := getDeserailFun(iter.Key())
if err != nil {
return nil, err
}
val, err := fun(iter.Value())
if err != nil {
return nil, err
}
item.val = val
items = append(items, item)
}
return items, nil
}
func initStore(c *processBlockTestCase) (protocol.Store, dbm.DB, error) {
testDB := dbm.NewDB("testdb", "leveldb", dbDir)
batch := testDB.NewBatch()
for _, item := range c.initStore {
fun, err := getSerialFun(item.val)
if err != nil {
return nil, nil, err
}
bytes, err := fun(item.val)
if err != nil {
return nil, nil, err
}
batch.Set(item.key, bytes)
}
batch.Write()
return database.NewStore(testDB), testDB, nil
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment