github.com/turingchain2020/turingchain@v1.1.21/blockchain/blockstore_test.go (about)

     1  package blockchain
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"os"
     7  	"testing"
     8  
     9  	"github.com/stretchr/testify/mock"
    10  
    11  	"github.com/turingchain2020/turingchain/util"
    12  
    13  	"github.com/turingchain2020/turingchain/common"
    14  	dbm "github.com/turingchain2020/turingchain/common/db"
    15  	"github.com/turingchain2020/turingchain/queue"
    16  	qmocks "github.com/turingchain2020/turingchain/queue/mocks"
    17  	"github.com/turingchain2020/turingchain/types"
    18  	"github.com/stretchr/testify/assert"
    19  	"github.com/stretchr/testify/require"
    20  )
    21  
    22  func InitEnv() *BlockChain {
    23  	cfg := types.NewTuringchainConfig(types.GetDefaultCfgstring())
    24  	q := queue.New("channel")
    25  	q.SetConfig(cfg)
    26  	chain := New(cfg)
    27  	chain.client = q.Client()
    28  	return chain
    29  }
    30  
    31  func TestGetStoreUpgradeMeta(t *testing.T) {
    32  	dir, err := ioutil.TempDir("", "example")
    33  	assert.Nil(t, err)
    34  	defer os.RemoveAll(dir) // clean up
    35  	os.RemoveAll(dir)       //删除已存在目录
    36  
    37  	blockStoreDB := dbm.NewDB("blockchain", "leveldb", dir, 100)
    38  
    39  	chain := InitEnv()
    40  	blockStore := NewBlockStore(chain, blockStoreDB, nil)
    41  	require.NotNil(t, blockStore)
    42  
    43  	meta, err := blockStore.GetStoreUpgradeMeta()
    44  	require.NoError(t, err)
    45  	require.Equal(t, meta.Version, "0.0.0")
    46  
    47  	meta.Version = "1.0.0"
    48  	err = blockStore.SetStoreUpgradeMeta(meta)
    49  	require.NoError(t, err)
    50  	meta, err = blockStore.GetStoreUpgradeMeta()
    51  	require.NoError(t, err)
    52  	require.Equal(t, meta.Version, "1.0.0")
    53  }
    54  
    55  func TestSeqSaveAndGet(t *testing.T) {
    56  	dir, err := ioutil.TempDir("", "example")
    57  	assert.Nil(t, err)
    58  	defer os.RemoveAll(dir) // clean up
    59  	os.RemoveAll(dir)       //删除已存在目录
    60  
    61  	blockStoreDB := dbm.NewDB("blockchain", "leveldb", dir, 100)
    62  
    63  	chain := InitEnv()
    64  	blockStore := NewBlockStore(chain, blockStoreDB, nil)
    65  	assert.NotNil(t, blockStore)
    66  	blockStore.saveSequence = true
    67  	blockStore.isParaChain = false
    68  
    69  	newBatch := blockStore.NewBatch(true)
    70  	seq, err := blockStore.saveBlockSequence(newBatch, []byte("s0"), 0, 1, 0)
    71  	assert.Nil(t, err)
    72  	assert.Equal(t, int64(0), seq)
    73  	err = newBatch.Write()
    74  	assert.Nil(t, err)
    75  
    76  	newBatch = blockStore.NewBatch(true)
    77  	seq, err = blockStore.saveBlockSequence(newBatch, []byte("s1"), 1, 1, 0)
    78  	assert.Nil(t, err)
    79  	assert.Equal(t, int64(1), seq)
    80  	err = newBatch.Write()
    81  	assert.Nil(t, err)
    82  
    83  	s, err := blockStore.LoadBlockLastSequence()
    84  	assert.Nil(t, err)
    85  	assert.Equal(t, int64(1), s)
    86  
    87  	s2, err := blockStore.GetBlockSequence(s)
    88  	assert.Nil(t, err)
    89  	assert.Equal(t, []byte("s1"), s2.Hash)
    90  
    91  	s3, err := blockStore.GetSequenceByHash([]byte("s1"))
    92  	assert.Nil(t, err)
    93  	assert.Equal(t, int64(1), s3)
    94  }
    95  
    96  func TestParaSeqSaveAndGet(t *testing.T) {
    97  	dir, err := ioutil.TempDir("", "example")
    98  	assert.Nil(t, err)
    99  	defer os.RemoveAll(dir) // clean up
   100  	os.RemoveAll(dir)       //删除已存在目录
   101  
   102  	blockStoreDB := dbm.NewDB("blockchain", "leveldb", dir, 100)
   103  
   104  	bchain := InitEnv()
   105  	blockStore := NewBlockStore(bchain, blockStoreDB, nil)
   106  	assert.NotNil(t, blockStore)
   107  	blockStore.saveSequence = true
   108  	blockStore.isParaChain = true
   109  
   110  	newBatch := blockStore.NewBatch(true)
   111  	seq, err := blockStore.saveBlockSequence(newBatch, []byte("s0"), 0, 1, 1)
   112  	assert.Nil(t, err)
   113  	assert.Equal(t, int64(0), seq)
   114  	err = newBatch.Write()
   115  	assert.Nil(t, err)
   116  
   117  	newBatch = blockStore.NewBatch(true)
   118  	seq, err = blockStore.saveBlockSequence(newBatch, []byte("s1"), 1, 1, 10)
   119  	assert.Nil(t, err)
   120  	assert.Equal(t, int64(1), seq)
   121  	err = newBatch.Write()
   122  	assert.Nil(t, err)
   123  
   124  	s, err := blockStore.LoadBlockLastSequence()
   125  	assert.Nil(t, err)
   126  	assert.Equal(t, int64(1), s)
   127  
   128  	s2, err := blockStore.GetBlockSequence(s)
   129  	assert.Nil(t, err)
   130  	assert.Equal(t, []byte("s1"), s2.Hash)
   131  
   132  	s3, err := blockStore.GetSequenceByHash([]byte("s1"))
   133  	assert.Nil(t, err)
   134  	assert.Equal(t, int64(1), s3)
   135  
   136  	s4, err := blockStore.GetMainSequenceByHash([]byte("s1"))
   137  	assert.Nil(t, err)
   138  	assert.Equal(t, int64(10), s4)
   139  
   140  	s5, err := blockStore.LoadBlockLastMainSequence()
   141  	assert.Nil(t, err)
   142  	assert.Equal(t, int64(10), s5)
   143  
   144  	s6, err := blockStore.GetBlockByMainSequence(1)
   145  	assert.Nil(t, err)
   146  	assert.Equal(t, []byte("s0"), s6.Hash)
   147  
   148  	chain := &BlockChain{
   149  		blockStore: blockStore,
   150  	}
   151  	s7, err := chain.ProcGetMainSeqByHash([]byte("s0"))
   152  	assert.Nil(t, err)
   153  	assert.Equal(t, int64(1), s7)
   154  
   155  	_, err = chain.ProcGetMainSeqByHash([]byte("s0-not-exist"))
   156  	assert.NotNil(t, err)
   157  }
   158  
   159  func TestSeqCreateAndDelete(t *testing.T) {
   160  	dir, err := ioutil.TempDir("", "example")
   161  	assert.Nil(t, err)
   162  	defer os.RemoveAll(dir) // clean up
   163  	os.RemoveAll(dir)       //删除已存在目录
   164  
   165  	blockStoreDB := dbm.NewDB("blockchain", "leveldb", dir, 100)
   166  
   167  	chain := InitEnv()
   168  	blockStore := NewBlockStore(chain, blockStoreDB, nil)
   169  	assert.NotNil(t, blockStore)
   170  	blockStore.saveSequence = false
   171  	blockStore.isParaChain = true
   172  
   173  	batch := blockStore.NewBatch(true)
   174  	for i := 0; i <= 100; i++ {
   175  		var header types.Header
   176  		header.Height = int64(i)
   177  		header.Hash = []byte(fmt.Sprintf("%d", i))
   178  		headerkvs, err := saveHeaderTable(blockStore.db, &header)
   179  		assert.Nil(t, err)
   180  		for _, kv := range headerkvs {
   181  			batch.Set(kv.GetKey(), kv.GetValue())
   182  		}
   183  		batch.Set(calcHeightToHashKey(int64(i)), []byte(fmt.Sprintf("%d", i)))
   184  	}
   185  	blockStore.height = 100
   186  	batch.Write()
   187  
   188  	blockStore.saveSequence = true
   189  	blockStore.CreateSequences(10)
   190  	seq, err := blockStore.LoadBlockLastSequence()
   191  	assert.Nil(t, err)
   192  	assert.Equal(t, int64(100), seq)
   193  
   194  	seq, err = blockStore.GetSequenceByHash([]byte("1"))
   195  	assert.Nil(t, err)
   196  	assert.Equal(t, int64(1), seq)
   197  
   198  	seq, err = blockStore.GetSequenceByHash([]byte("0"))
   199  	assert.Nil(t, err)
   200  	assert.Equal(t, int64(0), seq)
   201  }
   202  
   203  func TestHasTx(t *testing.T) {
   204  	dir, err := ioutil.TempDir("", "example")
   205  	assert.Nil(t, err)
   206  	defer os.RemoveAll(dir) // clean up
   207  	os.RemoveAll(dir)       //删除已存在目录
   208  
   209  	blockStoreDB := dbm.NewDB("blockchain", "leveldb", dir, 100)
   210  
   211  	chain := InitEnv()
   212  	cfg := chain.client.GetConfig()
   213  	blockStore := NewBlockStore(chain, blockStoreDB, chain.client)
   214  	assert.NotNil(t, blockStore)
   215  	blockStore.saveSequence = false
   216  	blockStore.isParaChain = false
   217  	cfg.S("quickIndex", true)
   218  
   219  	//txstring1 和txstring2的短hash是一样的,但是全hash是不一样的
   220  	txstring1 := "0xaf095d11326ebb97d142fdb0e0138ef28524470c121b4811bdd05857b2d06764"
   221  	txstring2 := "0xaf095d11326ebb97d142fdb0e0138ef28524470c121b4811bdd05857b2d06765"
   222  	txstring3 := "0x8fac317e02ee25b1bbc5bd5a8570962b482928b014d14817b3c7a4e6aeddb3c6"
   223  	txstring4 := "0x6522279c4fae53965e7bfbd35651dcd68813a50c65bf7af20b02c9bfe3d2ce8b"
   224  
   225  	txhash1, err := common.FromHex(txstring1)
   226  	assert.Nil(t, err)
   227  	txhash2, err := common.FromHex(txstring2)
   228  	assert.Nil(t, err)
   229  	txhash3, err := common.FromHex(txstring3)
   230  	assert.Nil(t, err)
   231  	txhash4, err := common.FromHex(txstring4)
   232  	assert.Nil(t, err)
   233  
   234  	batch := blockStore.NewBatch(true)
   235  
   236  	var txresult types.TxResult
   237  	txresult.Height = 1
   238  	txresult.Index = int32(1)
   239  	batch.Set(cfg.CalcTxKey(txhash1), types.Encode(&txresult))
   240  	batch.Set(types.CalcTxShortKey(txhash1), []byte("1"))
   241  
   242  	txresult.Height = 3
   243  	txresult.Index = int32(3)
   244  	batch.Set(cfg.CalcTxKey(txhash3), types.Encode(&txresult))
   245  	batch.Set(types.CalcTxShortKey(txhash3), []byte("1"))
   246  
   247  	batch.Write()
   248  
   249  	has, _ := blockStore.HasTx(txhash1)
   250  	assert.Equal(t, has, true)
   251  
   252  	has, _ = blockStore.HasTx(txhash2)
   253  	assert.Equal(t, has, false)
   254  
   255  	has, _ = blockStore.HasTx(txhash3)
   256  	assert.Equal(t, has, true)
   257  
   258  	has, _ = blockStore.HasTx(txhash4)
   259  	assert.Equal(t, has, false)
   260  }
   261  
   262  func TestGetRealTxResult(t *testing.T) {
   263  	dir, err := ioutil.TempDir("", "example")
   264  	assert.Nil(t, err)
   265  	defer os.RemoveAll(dir) // clean up
   266  	os.RemoveAll(dir)       //删除已存在目录
   267  	blockStoreDB := dbm.NewDB("blockchain", "leveldb", dir, 100)
   268  	chain := InitEnv()
   269  	cfg := chain.client.GetConfig()
   270  	blockStore := NewBlockStore(chain, blockStoreDB, chain.client)
   271  	assert.NotNil(t, blockStore)
   272  
   273  	// generate blockdetail
   274  	txs := util.GenCoinsTxs(cfg, util.HexToPrivkey("4257D8692EF7FE13C68B65D6A52F03933DB2FA5CE8FAF210B5B8B80C721CED01"), 10)
   275  	block := &types.Block{Txs: txs}
   276  	block.MainHash = block.Hash(cfg)
   277  	block.Height = 0
   278  	blockdetail := &types.BlockDetail{
   279  		Block: block,
   280  		Receipts: []*types.ReceiptData{
   281  			{Ty: 0, Logs: []*types.ReceiptLog{{Ty: 0, Log: []byte("000")}, {Ty: 0, Log: []byte("0000")}}},
   282  			{Ty: 1, Logs: []*types.ReceiptLog{{Ty: 111, Log: []byte("111")}, {Ty: 1111, Log: []byte("1111")}}},
   283  			{Ty: 2, Logs: []*types.ReceiptLog{{Ty: 222, Log: []byte("222")}, {Ty: 2222, Log: []byte("2222")}}},
   284  			{Ty: 3, Logs: []*types.ReceiptLog{{Ty: 333, Log: []byte("333")}, {Ty: 3333, Log: []byte("3333")}}},
   285  		},
   286  		KV: []*types.KeyValue{{Key: []byte("000"), Value: []byte("000")}, {Key: []byte("111"), Value: []byte("111")}},
   287  	}
   288  
   289  	// save blockdetail
   290  	newbatch := blockStore.NewBatch(true)
   291  	_, err = blockStore.SaveBlock(newbatch, blockdetail, 0)
   292  	assert.NoError(t, err)
   293  	newbatch.Write()
   294  
   295  	// check
   296  	cfg.S("reduceLocaldb", true)
   297  	txr := &types.TxResult{
   298  		Height: 0,
   299  		Index:  0,
   300  	}
   301  	blockStore.getRealTxResult(txr)
   302  	assert.Equal(t, txr.Tx.Nonce, txs[0].Nonce)
   303  	assert.Equal(t, txr.Receiptdate.Ty, blockdetail.Receipts[0].Ty)
   304  }
   305  
   306  func TestMustSaveKvset(t *testing.T) {
   307  	kvset := types.LocalDBSet{
   308  		KV: []*types.KeyValue{
   309  			{Key: []byte("000"), Value: []byte("000")},
   310  			{Key: []byte("111"), Value: []byte("111")},
   311  			{Key: []byte("222"), Value: nil},
   312  		},
   313  	}
   314  
   315  	dir, err := ioutil.TempDir("", "example")
   316  	assert.Nil(t, err)
   317  	defer os.RemoveAll(dir) // clean up
   318  	os.RemoveAll(dir)       //删除已存在目录
   319  	blockStoreDB := dbm.NewDB("blockchain", "leveldb", dir, 100)
   320  
   321  	chain := InitEnv()
   322  	blockStore := NewBlockStore(chain, blockStoreDB, chain.client)
   323  	assert.NotNil(t, blockStore)
   324  	blockStore.Set([]byte("222"), []byte("222"))
   325  
   326  	blockStore.mustSaveKvset(&kvset)
   327  
   328  	v, err := blockStoreDB.Get([]byte("000"))
   329  	assert.Nil(t, err)
   330  	assert.Equal(t, []byte("000"), v)
   331  
   332  	v, err = blockStoreDB.Get([]byte("111"))
   333  	assert.Nil(t, err)
   334  	assert.Equal(t, []byte("111"), v)
   335  
   336  	_, err = blockStoreDB.Get([]byte("222"))
   337  	assert.Equal(t, types.ErrNotFound, err)
   338  }
   339  
   340  func TestGetCurChunkNumAndRecvChunkHash(t *testing.T) {
   341  	dir, err := ioutil.TempDir("", "example")
   342  	assert.Nil(t, err)
   343  	defer os.RemoveAll(dir) // clean up
   344  	os.RemoveAll(dir)       //删除已存在目录
   345  	blockStoreDB := dbm.NewDB("blockchain", "leveldb", dir, 100)
   346  
   347  	chain := InitEnv()
   348  	blockStore := NewBlockStore(chain, blockStoreDB, chain.client)
   349  	assert.NotNil(t, blockStore)
   350  	height := blockStore.getCurChunkNum(ChunkNumToHash)
   351  	assert.Equal(t, height, int64(-1))
   352  	height = blockStore.getCurChunkNum(RecvChunkNumToHash)
   353  	assert.Equal(t, height, int64(-1))
   354  	blockStore.Set(calcChunkNumToHash(1), []byte("1111"))
   355  	blockStore.Set(calcChunkNumToHash(8), []byte("8888"))
   356  	height = blockStore.getCurChunkNum(ChunkNumToHash)
   357  	assert.Equal(t, height, int64(8))
   358  	blockStore.Set(calcRecvChunkNumToHash(1), []byte("1111"))
   359  	blockStore.Set(calcRecvChunkNumToHash(8), []byte("1111"))
   360  	height = blockStore.getCurChunkNum(RecvChunkNumToHash)
   361  	assert.Equal(t, height, int64(8))
   362  
   363  	blockStore.Set(append(ChunkNumToHash, []byte("jfakjl")...), []byte("8888"))
   364  	height = blockStore.getCurChunkNum(ChunkNumToHash)
   365  	assert.Equal(t, height, int64(-1))
   366  
   367  	// test getRecvChunkHash
   368  	_, err = blockStore.getRecvChunkHash(15)
   369  	assert.Equal(t, err, types.ErrNotFound)
   370  	hash := []byte("11111111111111111")
   371  	blockStore.Set(calcRecvChunkNumToHash(15), types.Encode(&types.ChunkInfo{
   372  		ChunkNum:  1,
   373  		ChunkHash: hash,
   374  		Start:     1,
   375  		End:       2,
   376  	}))
   377  	v, err := blockStore.getRecvChunkHash(15)
   378  	assert.Nil(t, err)
   379  	assert.Equal(t, v, hash)
   380  }
   381  
   382  func TestGetSetSerialChunkNum(t *testing.T) {
   383  	dir, err := ioutil.TempDir("", "example")
   384  	assert.Nil(t, err)
   385  	defer os.RemoveAll(dir) // clean up
   386  	os.RemoveAll(dir)       //删除已存在目录
   387  	blockStoreDB := dbm.NewDB("blockchain", "leveldb", dir, 100)
   388  
   389  	chain := InitEnv()
   390  	blockStore := NewBlockStore(chain, blockStoreDB, chain.client)
   391  
   392  	height := blockStore.GetMaxSerialChunkNum()
   393  	assert.Equal(t, height, int64(-1))
   394  
   395  	err = blockStore.SetMaxSerialChunkNum(10)
   396  	assert.Nil(t, err)
   397  	height = blockStore.GetMaxSerialChunkNum()
   398  	assert.Equal(t, height, int64(10))
   399  }
   400  
   401  func TestGetBodyFromP2Pstore(t *testing.T) {
   402  	cfg := types.NewTuringchainConfig(types.GetDefaultCfgstring())
   403  	q := queue.New("channel")
   404  	q.SetConfig(cfg)
   405  	chain := New(cfg)
   406  	client := &qmocks.Client{}
   407  	chain.client = client
   408  
   409  	dir, err := ioutil.TempDir("", "example")
   410  	assert.Nil(t, err)
   411  	defer os.RemoveAll(dir) // clean up
   412  	os.RemoveAll(dir)       //删除已存在目录
   413  	blockStoreDB := dbm.NewDB("blockchain", "leveldb", dir, 100)
   414  
   415  	client.On("GetConfig").Return(cfg)
   416  	client.On("NewMessage", mock.Anything, mock.Anything, mock.Anything).Return(&queue.Message{})
   417  	blockStore := NewBlockStore(chain, blockStoreDB, chain.client)
   418  	blockStore.UpdateHeight2(100000)
   419  	client.On("Send", mock.Anything, mock.Anything).Return(nil)
   420  	rspMsg := &queue.Message{Data: &types.BlockBodys{Items: []*types.BlockBody{{}, {}}}}
   421  	client.On("WaitTimeout", mock.Anything, mock.Anything).Return(rspMsg, nil)
   422  
   423  	blockHash := []byte("111111111111111")
   424  	chunkHash := []byte("222222222222222")
   425  	chunkInfo := types.ChunkInfo{
   426  		ChunkHash: chunkHash,
   427  		Start:     0,
   428  		End:       999,
   429  	}
   430  	blockStoreDB.Set(calcChunkNumToHash(0), types.Encode(&chunkInfo))
   431  	bodys, err := blockStore.getBodyFromP2Pstore(blockHash, 1, 10)
   432  	assert.Nil(t, err)
   433  	assert.Equal(t, len(bodys.Items), 2)
   434  
   435  	blockheader := &types.Header{
   436  		Hash:   blockHash,
   437  		Height: 1,
   438  	}
   439  	body, err := blockStore.multiGetBody(blockheader, "", calcHeightHashKey(1, blockHash), nil)
   440  	assert.Nil(t, body)
   441  	assert.Equal(t, err, types.ErrHashNotExist)
   442  	bcConfig := cfg.GetModuleConfig().BlockChain
   443  	bcConfig.EnableFetchP2pstore = true
   444  	body, err = blockStore.multiGetBody(blockheader, "", calcHeightHashKey(1, blockHash), nil)
   445  	assert.Nil(t, err)
   446  	assert.NotNil(t, body)
   447  }