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

     1  // Copyright Turing Corp. 2018 All Rights Reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package blockchain
     6  
     7  import (
     8  	"bytes"
     9  	"encoding/json"
    10  	"errors"
    11  	"fmt"
    12  	"math/big"
    13  	"strconv"
    14  	"sync"
    15  	"sync/atomic"
    16  	"time"
    17  
    18  	"github.com/turingchain2020/turingchain/common"
    19  	dbm "github.com/turingchain2020/turingchain/common/db"
    20  	"github.com/turingchain2020/turingchain/common/difficulty"
    21  	"github.com/turingchain2020/turingchain/common/utils"
    22  	"github.com/turingchain2020/turingchain/common/version"
    23  	"github.com/turingchain2020/turingchain/queue"
    24  	"github.com/turingchain2020/turingchain/types"
    25  	"github.com/golang/protobuf/proto"
    26  )
    27  
    28  //var
    29  var (
    30  	blockLastHeight       = []byte("blockLastHeight")
    31  	bodyPrefix            = []byte("Body:")
    32  	LastSequence          = []byte("LastSequence")
    33  	headerPrefix          = []byte("Header:")
    34  	heightToHeaderPrefix  = []byte("HH:")
    35  	hashPrefix            = []byte("Hash:")
    36  	tdPrefix              = []byte("TD:")
    37  	heightToHashKeyPrefix = []byte("Height:")
    38  	seqToHashKey          = []byte("Seq:")
    39  	HashToSeqPrefix       = []byte("HashToSeq:")
    40  	pushPrefix            = []byte("push2subscribe:")
    41  	lastSeqNumPrefix      = []byte("lastSeqNumPrefix:")
    42  	paraSeqToHashKey      = []byte("ParaSeq:")
    43  	HashToParaSeqPrefix   = []byte("HashToParaSeq:")
    44  	LastParaSequence      = []byte("LastParaSequence")
    45  	// chunk相关
    46  	BodyHashToChunk    = []byte("BodyHashToChunk:")
    47  	ChunkNumToHash     = []byte("ChunkNumToHash:")
    48  	ChunkHashToNum     = []byte("ChunkHashToNum:")
    49  	RecvChunkNumToHash = []byte("RecvChunkNumToHash:")
    50  	MaxSerialChunkNum  = []byte("MaxSilChunkNum:")
    51  	MaxDeletedChunkNum = []byte("MaxDeletedChunkNum:")
    52  	storeLog           = chainlog.New("submodule", "store")
    53  )
    54  
    55  //GetLocalDBKeyList 获取本地键值列表
    56  //增加chainBody和chainHeader对应的四个key。chainParaTx的可以在区块0高度时是没有的
    57  //bodyPrefix,headerPrefix,heightToHeaderPrefix这三个key不再使用
    58  func GetLocalDBKeyList() [][]byte {
    59  	return [][]byte{
    60  		blockLastHeight, bodyPrefix, LastSequence, headerPrefix, heightToHeaderPrefix,
    61  		hashPrefix, tdPrefix, heightToHashKeyPrefix, seqToHashKey, HashToSeqPrefix,
    62  		pushPrefix, lastSeqNumPrefix, tempBlockKey, lastTempBlockKey, LastParaSequence,
    63  		chainParaTxPrefix, chainBodyPrefix, chainHeaderPrefix, chainReceiptPrefix,
    64  		BodyHashToChunk, ChunkNumToHash, ChunkHashToNum, RecvChunkNumToHash,
    65  		MaxSerialChunkNum, MaxDeletedChunkNum,
    66  	}
    67  }
    68  
    69  //存储block hash对应的blockbody信息
    70  func calcHashToBlockBodyKey(hash []byte) []byte {
    71  	return append(bodyPrefix, hash...)
    72  }
    73  
    74  func calcPushKey(name string) []byte {
    75  	return []byte(string(pushPrefix) + name)
    76  }
    77  
    78  func calcLastPushSeqNumKey(name string) []byte {
    79  	return []byte(string(lastSeqNumPrefix) + name)
    80  }
    81  
    82  //存储block hash对应的header信息
    83  func calcHashToBlockHeaderKey(hash []byte) []byte {
    84  	return append(headerPrefix, hash...)
    85  }
    86  
    87  func calcHeightToBlockHeaderKey(height int64) []byte {
    88  	return append(heightToHeaderPrefix, []byte(fmt.Sprintf("%012d", height))...)
    89  }
    90  
    91  //存储block hash对应的block height
    92  func calcHashToHeightKey(hash []byte) []byte {
    93  	return append(hashPrefix, hash...)
    94  }
    95  
    96  //存储block hash对应的block总难度TD
    97  func calcHashToTdKey(hash []byte) []byte {
    98  	return append(tdPrefix, hash...)
    99  }
   100  
   101  //存储block height 对应的block  hash
   102  func calcHeightToHashKey(height int64) []byte {
   103  	return append(heightToHashKeyPrefix, []byte(fmt.Sprintf("%v", height))...)
   104  }
   105  
   106  //存储block操作序列号对应的block hash,KEY=Seq:sequence
   107  func calcSequenceToHashKey(sequence int64, isPara bool) []byte {
   108  	if isPara {
   109  		return append(paraSeqToHashKey, []byte(fmt.Sprintf("%v", sequence))...)
   110  	}
   111  	return append(seqToHashKey, []byte(fmt.Sprintf("%v", sequence))...)
   112  }
   113  
   114  //存储block hash对应的seq序列号,KEY=Seq:sequence,只用于平行链addblock操作,方便delblock回退是查找对应seq的hash
   115  func calcHashToSequenceKey(hash []byte, isPara bool) []byte {
   116  	if isPara {
   117  		return append(HashToParaSeqPrefix, hash...)
   118  	}
   119  	return append(HashToSeqPrefix, hash...)
   120  }
   121  
   122  func calcLastSeqKey(isPara bool) []byte {
   123  	if isPara {
   124  		return LastParaSequence
   125  	}
   126  	return LastSequence
   127  }
   128  
   129  //存储block hash对应的seq序列号,KEY=Seq:sequence,只用于平行链addblock操作,方便delblock回退是查找对应seq的hash
   130  func calcHashToMainSequenceKey(hash []byte) []byte {
   131  	return append(HashToSeqPrefix, hash...)
   132  }
   133  
   134  //存储block操作序列号对应的block hash,KEY=MainSeq:sequence
   135  func calcMainSequenceToHashKey(sequence int64) []byte {
   136  	return append(seqToHashKey, []byte(fmt.Sprintf("%v", sequence))...)
   137  }
   138  
   139  //// 存储归档索引 blockhash--->chunkhash
   140  //func calcBlockHashToChunkHash(hash []byte) []byte {
   141  //	return append(BodyHashToChunk, hash...)
   142  //}
   143  
   144  // 存储归档索引 chunkNum--->chunkhash
   145  func calcChunkNumToHash(chunkNum int64) []byte {
   146  	return append(ChunkNumToHash, []byte(fmt.Sprintf("%012d", chunkNum))...)
   147  }
   148  
   149  // 存储归档索引 chunkhash--->chunkNum
   150  func calcChunkHashToNum(hash []byte) []byte {
   151  	return append(ChunkHashToNum, hash...)
   152  }
   153  
   154  // 存储归档索引 chunkNum--->chunkhash 从对端节点同步过来的归档索引
   155  func calcRecvChunkNumToHash(chunkNum int64) []byte {
   156  	return append(RecvChunkNumToHash, []byte(fmt.Sprintf("%012d", chunkNum))...)
   157  }
   158  
   159  //BlockStore 区块存储 TODO:有较多的冗余代码,接口函数需要进行功能梳理和重写
   160  type BlockStore struct {
   161  	db             dbm.DB
   162  	client         queue.Client
   163  	height         int64
   164  	lastBlock      *types.Block
   165  	lastheaderlock sync.Mutex
   166  	saveSequence   bool
   167  	isParaChain    bool
   168  	batch          dbm.Batch
   169  
   170  	//记录当前活跃的block,减少数据库的访问提高效率
   171  	activeBlocks *utils.SpaceLimitCache
   172  	chain        *BlockChain
   173  	blockCache   *BlockCache
   174  }
   175  
   176  //NewBlockStore new
   177  func NewBlockStore(chain *BlockChain, db dbm.DB, client queue.Client) *BlockStore {
   178  	height, err := LoadBlockStoreHeight(db)
   179  	if err != nil {
   180  		chainlog.Info("init::LoadBlockStoreHeight::database may be crash", "err", err.Error())
   181  		if err != types.ErrHeightNotExist {
   182  			panic(err)
   183  		}
   184  	}
   185  	blockStore := &BlockStore{
   186  		height:     height,
   187  		db:         db,
   188  		client:     client,
   189  		chain:      chain,
   190  		blockCache: chain.blockCache,
   191  	}
   192  	if chain != nil {
   193  		blockStore.saveSequence = chain.isRecordBlockSequence
   194  		blockStore.isParaChain = chain.isParaChain
   195  	}
   196  	cfg := chain.client.GetConfig()
   197  	if height == -1 {
   198  		chainlog.Info("load block height error, may be init database", "height", height)
   199  		if cfg.IsEnable("quickIndex") {
   200  			blockStore.saveQuickIndexFlag()
   201  		}
   202  	} else {
   203  		blockdetail, err := blockStore.LoadBlock(height, nil)
   204  		if err != nil {
   205  			chainlog.Error("init::LoadBlock::database may be crash")
   206  			panic(err)
   207  		}
   208  		blockStore.lastBlock = blockdetail.GetBlock()
   209  		flag, err := blockStore.loadFlag(types.FlagTxQuickIndex)
   210  		if err != nil {
   211  			panic(err)
   212  		}
   213  		if cfg.IsEnable("quickIndex") {
   214  			if flag == 0 {
   215  				blockStore.initQuickIndex(height)
   216  			}
   217  		} else {
   218  			if flag != 0 {
   219  				panic("toml config disable tx quick index, but database enable quick index")
   220  			}
   221  		}
   222  	}
   223  	blockStore.batch = db.NewBatch(true)
   224  
   225  	//初始化活跃区块的缓存
   226  	maxActiveBlockNum := maxActiveBlocks
   227  	maxActiveBlockSize := maxActiveBlocksCacheSize
   228  	if cfg.GetModuleConfig().BlockChain.MaxActiveBlockNum > 0 {
   229  		maxActiveBlockNum = cfg.GetModuleConfig().BlockChain.MaxActiveBlockNum
   230  	}
   231  	if cfg.GetModuleConfig().BlockChain.MaxActiveBlockSize > 0 {
   232  		maxActiveBlockSize = cfg.GetModuleConfig().BlockChain.MaxActiveBlockSize
   233  	}
   234  	blockStore.activeBlocks = utils.NewSpaceLimitCache(maxActiveBlockNum, maxActiveBlockSize*1024*1024)
   235  
   236  	return blockStore
   237  }
   238  
   239  //步骤:
   240  //检查数据库是否已经进行quickIndex改造
   241  //如果没有,那么进行下面的步骤
   242  //1. 先把hash 都给改成 TX:hash
   243  //2. 把所有的 Tx:hash 都加一个 8字节的index
   244  //3. 2000个交易处理一次,并且打印进度
   245  //4. 全部处理完成了,添加quickIndex 的标记
   246  func (bs *BlockStore) initQuickIndex(height int64) {
   247  	storeLog.Info("quickIndex upgrade start", "current height", height)
   248  	batch := bs.db.NewBatch(true)
   249  	var maxsize = 100 * 1024 * 1024
   250  	var count = 0
   251  	cfg := bs.client.GetConfig()
   252  	for i := int64(0); i <= height; i++ {
   253  		blockdetail, err := bs.LoadBlock(i, nil)
   254  		if err != nil {
   255  			panic(err)
   256  		}
   257  		for _, tx := range blockdetail.Block.Txs {
   258  			hash := tx.Hash()
   259  			txresult, err := bs.db.Get(hash)
   260  			if err != nil {
   261  				panic(err)
   262  			}
   263  			count += len(txresult)
   264  			batch.Set(cfg.CalcTxKey(hash), txresult)
   265  			batch.Set(types.CalcTxShortKey(hash), []byte("1"))
   266  		}
   267  		if count > maxsize {
   268  			storeLog.Info("initQuickIndex", "height", i)
   269  			err := batch.Write()
   270  			if err != nil {
   271  				panic(err)
   272  			}
   273  			batch.Reset()
   274  			count = 0
   275  		}
   276  	}
   277  	if count > 0 {
   278  		err := batch.Write()
   279  		if err != nil {
   280  			panic(err)
   281  		}
   282  		storeLog.Info("initQuickIndex", "height", height)
   283  		batch.Reset()
   284  	}
   285  	bs.saveQuickIndexFlag()
   286  }
   287  
   288  // store通用接口: 非block相关的保存功能,用通用的接口
   289  // 避免store相关的代码膨胀
   290  
   291  // SetSync store通用接口
   292  func (bs *BlockStore) SetSync(key, value []byte) error {
   293  	return bs.db.SetSync(key, value)
   294  }
   295  
   296  // Set store通用接口
   297  func (bs *BlockStore) Set(key, value []byte) error {
   298  	return bs.db.Set(key, value)
   299  }
   300  
   301  // GetKey store通用接口, Get 已经被使用
   302  func (bs *BlockStore) GetKey(key []byte) ([]byte, error) {
   303  	value, err := bs.db.Get(key)
   304  	if err != nil && err != dbm.ErrNotFoundInDb {
   305  		return nil, types.ErrNotFound
   306  
   307  	}
   308  	return value, err
   309  }
   310  
   311  // PrefixCount store通用接口
   312  func (bs *BlockStore) PrefixCount(prefix []byte) int64 {
   313  	counts := dbm.NewListHelper(bs.db).PrefixCount(prefix)
   314  	return counts
   315  }
   316  
   317  // List store通用接口
   318  func (bs *BlockStore) List(prefix []byte) ([][]byte, error) {
   319  	values := dbm.NewListHelper(bs.db).PrefixScan(prefix)
   320  	if values == nil {
   321  		return nil, types.ErrNotFound
   322  	}
   323  	return values, nil
   324  }
   325  
   326  func (bs *BlockStore) delAllKeys() {
   327  	var allkeys [][]byte
   328  	allkeys = append(allkeys, GetLocalDBKeyList()...)
   329  	allkeys = append(allkeys, version.GetLocalDBKeyList()...)
   330  	allkeys = append(allkeys, types.GetLocalDBKeyList()...)
   331  	var lastkey []byte
   332  	isvalid := true
   333  	for isvalid {
   334  		lastkey, isvalid = bs.delKeys(lastkey, allkeys)
   335  	}
   336  }
   337  
   338  func (bs *BlockStore) delKeys(seek []byte, allkeys [][]byte) ([]byte, bool) {
   339  	it := bs.db.Iterator(seek, types.EmptyValue, false)
   340  	defer it.Close()
   341  	i := 0
   342  	count := 0
   343  	var lastkey []byte
   344  	for it.Rewind(); it.Valid(); it.Next() {
   345  		key := it.Key()
   346  		lastkey = key
   347  		if it.Error() != nil {
   348  			panic(it.Error())
   349  		}
   350  		has := false
   351  		for _, prefix := range allkeys {
   352  			if bytes.HasPrefix(key, prefix) {
   353  				has = true
   354  				break
   355  			}
   356  		}
   357  		if !has {
   358  			i++
   359  			if i > 0 && i%10000 == 0 {
   360  				chainlog.Info("del key count", "count", i)
   361  			}
   362  			err := bs.db.Delete(key)
   363  			if err != nil {
   364  				panic(err)
   365  			}
   366  		}
   367  		count++
   368  		if count == 1000000 {
   369  			break
   370  		}
   371  	}
   372  	return lastkey, it.Valid()
   373  }
   374  
   375  func (bs *BlockStore) saveQuickIndexFlag() {
   376  	kv := types.FlagKV(types.FlagTxQuickIndex, 1)
   377  	err := bs.db.Set(kv.Key, kv.Value)
   378  	if err != nil {
   379  		panic(err)
   380  	}
   381  }
   382  
   383  func (bs *BlockStore) loadFlag(key []byte) (int64, error) {
   384  	flag := &types.Int64{}
   385  	flagBytes, err := bs.db.Get(key)
   386  	if err == nil {
   387  		err = types.Decode(flagBytes, flag)
   388  		if err != nil {
   389  			return 0, err
   390  		}
   391  		return flag.GetData(), nil
   392  	} else if err == types.ErrNotFound || err == dbm.ErrNotFoundInDb {
   393  		return 0, nil
   394  	}
   395  	return 0, err
   396  }
   397  
   398  //HasTx 是否包含该交易
   399  func (bs *BlockStore) HasTx(key []byte) (bool, error) {
   400  	cfg := bs.client.GetConfig()
   401  	if cfg.IsEnable("quickIndex") {
   402  		if _, err := bs.db.Get(types.CalcTxShortKey(key)); err != nil {
   403  			if err == dbm.ErrNotFoundInDb {
   404  				return false, nil
   405  			}
   406  			return false, err
   407  		}
   408  		//通过短hash查询交易存在时,需要再通过全hash索引查询一下。
   409  		//避免短hash重复,而全hash不一样的情况
   410  		//return true, nil
   411  	}
   412  	if _, err := bs.db.Get(cfg.CalcTxKey(key)); err != nil {
   413  		if err == dbm.ErrNotFoundInDb {
   414  			return false, nil
   415  		}
   416  		return false, err
   417  	}
   418  	return true, nil
   419  }
   420  
   421  //Height 返回BlockStore保存的当前block高度
   422  func (bs *BlockStore) Height() int64 {
   423  	return atomic.LoadInt64(&bs.height)
   424  }
   425  
   426  //UpdateHeight 更新db中的block高度到BlockStore.Height
   427  func (bs *BlockStore) UpdateHeight() {
   428  	height, err := LoadBlockStoreHeight(bs.db)
   429  	if err != nil && err != types.ErrHeightNotExist {
   430  		storeLog.Error("UpdateHeight", "LoadBlockStoreHeight err", err)
   431  		return
   432  	}
   433  	atomic.StoreInt64(&bs.height, height)
   434  	storeLog.Debug("UpdateHeight", "curblockheight", height)
   435  }
   436  
   437  //UpdateHeight2 更新指定的block高度到BlockStore.Height TODO:命名不清晰,不能体现和原来函数的区别
   438  func (bs *BlockStore) UpdateHeight2(height int64) {
   439  	atomic.StoreInt64(&bs.height, height)
   440  	storeLog.Debug("UpdateHeight2", "curblockheight", height)
   441  }
   442  
   443  //LastHeader 返回BlockStore保存的当前blockheader
   444  func (bs *BlockStore) LastHeader() *types.Header {
   445  	bs.lastheaderlock.Lock()
   446  	defer bs.lastheaderlock.Unlock()
   447  
   448  	// 通过lastBlock获取lastheader
   449  	var blockheader = types.Header{}
   450  	if bs.lastBlock != nil {
   451  		blockheader.Version = bs.lastBlock.Version
   452  		blockheader.ParentHash = bs.lastBlock.ParentHash
   453  		blockheader.TxHash = bs.lastBlock.TxHash
   454  		blockheader.StateHash = bs.lastBlock.StateHash
   455  		blockheader.Height = bs.lastBlock.Height
   456  		blockheader.BlockTime = bs.lastBlock.BlockTime
   457  		blockheader.Signature = bs.lastBlock.Signature
   458  		blockheader.Difficulty = bs.lastBlock.Difficulty
   459  
   460  		blockheader.Hash = bs.lastBlock.Hash(bs.client.GetConfig())
   461  		blockheader.TxCount = int64(len(bs.lastBlock.Txs))
   462  	}
   463  	return &blockheader
   464  }
   465  
   466  //UpdateLastBlock 更新LastBlock到缓存中
   467  func (bs *BlockStore) UpdateLastBlock(hash []byte) {
   468  	blockdetail, err := bs.LoadBlockByHash(hash)
   469  	if err != nil {
   470  		storeLog.Error("UpdateLastBlock", "hash", common.ToHex(hash), "error", err)
   471  		return
   472  	}
   473  	bs.lastheaderlock.Lock()
   474  	defer bs.lastheaderlock.Unlock()
   475  	if blockdetail != nil {
   476  		bs.lastBlock = blockdetail.Block
   477  	}
   478  	storeLog.Debug("UpdateLastBlock", "UpdateLastBlock", blockdetail.Block.Height, "LastHederhash", common.ToHex(blockdetail.Block.Hash(bs.client.GetConfig())))
   479  }
   480  
   481  //UpdateLastBlock2 更新LastBlock到缓存中 TODO:命名不清晰,不能体现和原来函数的区别
   482  func (bs *BlockStore) UpdateLastBlock2(block *types.Block) {
   483  	bs.lastheaderlock.Lock()
   484  	defer bs.lastheaderlock.Unlock()
   485  	bs.lastBlock = block
   486  	storeLog.Debug("UpdateLastBlock", "UpdateLastBlock", block.Height, "LastHederhash", common.ToHex(block.Hash(bs.client.GetConfig())))
   487  }
   488  
   489  //LastBlock 获取最新的block信息
   490  func (bs *BlockStore) LastBlock() *types.Block {
   491  	bs.lastheaderlock.Lock()
   492  	defer bs.lastheaderlock.Unlock()
   493  	if bs.lastBlock != nil {
   494  		return bs.lastBlock
   495  	}
   496  	return nil
   497  }
   498  
   499  //Get get
   500  func (bs *BlockStore) Get(keys *types.LocalDBGet) *types.LocalReplyValue {
   501  	var reply types.LocalReplyValue
   502  	for i := 0; i < len(keys.Keys); i++ {
   503  		key := keys.Keys[i]
   504  		value, err := bs.db.Get(key)
   505  		if err != nil && err != types.ErrNotFound {
   506  			storeLog.Error("Get", "error", err)
   507  		}
   508  		reply.Values = append(reply.Values, value)
   509  	}
   510  	return &reply
   511  }
   512  
   513  //LoadBlock 通过height高度获取BlockDetail信息, hash可为空
   514  //首先通过height+hash 主键获取header和body
   515  //如果失败使用旧的代码获取block信息
   516  //主要考虑到使用新的软件在localdb没有完成升级之前,
   517  //启动的过程中通过height获取区块时需要兼容旧的存储格式
   518  //升级完成正常启动之后通过loadBlockByIndex获取block不应该有失败
   519  //TODO:升级是否是一次性的,升级完成后需要将无效代码移除
   520  func (bs *BlockStore) LoadBlock(height int64, hash []byte) (block *types.BlockDetail, err error) {
   521  
   522  	if len(hash) == 0 {
   523  		hash, err = bs.GetBlockHashByHeight(height)
   524  		if err != nil {
   525  			return nil, err
   526  		}
   527  	}
   528  	block, err = bs.loadBlockByIndex("", calcHeightHashKey(height, hash), nil)
   529  	if block == nil && err != nil {
   530  		return bs.loadBlockByHashOld(hash)
   531  	}
   532  	return block, nil
   533  }
   534  
   535  //LoadBlockByHash 通过hash获取BlockDetail信息
   536  func (bs *BlockStore) LoadBlockByHash(hash []byte) (*types.BlockDetail, error) {
   537  	block, _, err := bs.loadBlockByHash(hash)
   538  	return block, err
   539  }
   540  
   541  func (bs *BlockStore) loadBlockByHash(hash []byte) (*types.BlockDetail, int, error) {
   542  	var blockSize int
   543  
   544  	//通过hash索引获取blockdetail
   545  	blockdetail, err := bs.loadBlockByIndex("hash", hash, nil)
   546  	if err != nil {
   547  		storeLog.Error("loadBlockByHash:loadBlockByIndex", "hash", common.ToHex(hash), "err", err)
   548  		return nil, blockSize, err
   549  	}
   550  	blockSize = blockdetail.Size()
   551  	return blockdetail, blockSize, nil
   552  }
   553  
   554  //SaveBlock 批量保存blocks信息到db数据库中,并返回最新的sequence值
   555  func (bs *BlockStore) SaveBlock(storeBatch dbm.Batch, blockdetail *types.BlockDetail, sequence int64) (int64, error) {
   556  	cfg := bs.client.GetConfig()
   557  	var lastSequence int64 = -1
   558  	height := blockdetail.Block.Height
   559  	if len(blockdetail.Receipts) == 0 && len(blockdetail.Block.Txs) != 0 {
   560  		storeLog.Error("SaveBlock Receipts is nil ", "height", height)
   561  	}
   562  	hash := blockdetail.Block.Hash(cfg)
   563  	//存储区块body和header信息
   564  	err := bs.saveBlockForTable(storeBatch, blockdetail, true, true)
   565  	if err != nil {
   566  		storeLog.Error("SaveBlock:saveBlockForTable", "height", height, "hash", common.ToHex(hash), "error", err)
   567  		return lastSequence, err
   568  	}
   569  	//更新最新的block 高度
   570  	heightbytes := types.Encode(&types.Int64{Data: height})
   571  	storeBatch.Set(blockLastHeight, heightbytes)
   572  
   573  	//存储block hash和height的对应关系,便于通过hash查询block
   574  	storeBatch.Set(calcHashToHeightKey(hash), heightbytes)
   575  
   576  	//存储block height和block hash的对应关系,便于通过height查询block
   577  	storeBatch.Set(calcHeightToHashKey(height), hash)
   578  
   579  	if bs.saveSequence || bs.isParaChain {
   580  		//存储记录block序列执行的type add
   581  		lastSequence, err = bs.saveBlockSequence(storeBatch, hash, height, types.AddBlock, sequence)
   582  		if err != nil {
   583  			storeLog.Error("SaveBlock SaveBlockSequence", "height", height, "hash", common.ToHex(hash), "error", err)
   584  			return lastSequence, err
   585  		}
   586  	}
   587  	storeLog.Debug("SaveBlock success", "blockheight", height, "hash", common.ToHex(hash))
   588  
   589  	return lastSequence, nil
   590  }
   591  
   592  //BlockdetailToBlockBody get block detail
   593  func (bs *BlockStore) BlockdetailToBlockBody(blockdetail *types.BlockDetail) *types.BlockBody {
   594  	cfg := bs.client.GetConfig()
   595  	height := blockdetail.Block.Height
   596  	hash := blockdetail.Block.Hash(cfg)
   597  	var blockbody types.BlockBody
   598  	blockbody.Txs = blockdetail.Block.Txs
   599  	blockbody.Receipts = blockdetail.Receipts
   600  	blockbody.MainHash = hash
   601  	blockbody.MainHeight = height
   602  	blockbody.Hash = hash
   603  	blockbody.Height = height
   604  	if bs.isParaChain {
   605  		blockbody.MainHash = blockdetail.Block.MainHash
   606  		blockbody.MainHeight = blockdetail.Block.MainHeight
   607  	}
   608  	return &blockbody
   609  }
   610  
   611  //DelBlock 删除block信息从db数据库中
   612  func (bs *BlockStore) DelBlock(storeBatch dbm.Batch, blockdetail *types.BlockDetail, sequence int64) (int64, error) {
   613  	var lastSequence int64 = -1
   614  	height := blockdetail.Block.Height
   615  	hash := blockdetail.Block.Hash(bs.client.GetConfig())
   616  
   617  	//更新最新的block高度为前一个高度
   618  	bytes := types.Encode(&types.Int64{Data: height - 1})
   619  	storeBatch.Set(blockLastHeight, bytes)
   620  
   621  	//删除block hash和height的对应关系
   622  	storeBatch.Delete(calcHashToHeightKey(hash))
   623  
   624  	//删除block height和block hash的对应关系,便于通过height查询block
   625  	storeBatch.Delete(calcHeightToHashKey(height))
   626  
   627  	if bs.saveSequence || bs.isParaChain {
   628  		//存储记录block序列执行的type del
   629  		lastSequence, err := bs.saveBlockSequence(storeBatch, hash, height, types.DelBlock, sequence)
   630  		if err != nil {
   631  			storeLog.Error("DelBlock SaveBlockSequence", "height", height, "hash", common.ToHex(hash), "error", err)
   632  			return lastSequence, err
   633  		}
   634  	}
   635  	// 删除主链上本区块存储的平行链标识,侧链的不记录
   636  	if !bs.isParaChain {
   637  		parakvs, _ := delParaTxTable(bs.db, height)
   638  		for _, kv := range parakvs {
   639  			if len(kv.GetKey()) != 0 && kv.GetValue() == nil {
   640  				storeBatch.Delete(kv.GetKey())
   641  			}
   642  		}
   643  	}
   644  	storeLog.Debug("DelBlock success", "blockheight", height, "hash", common.ToHex(hash))
   645  	return lastSequence, nil
   646  }
   647  
   648  //GetTx 通过tx hash 从db数据库中获取tx交易信息
   649  func (bs *BlockStore) GetTx(hash []byte) (*types.TxResult, error) {
   650  	if len(hash) == 0 {
   651  		err := errors.New("input hash is null")
   652  		return nil, err
   653  	}
   654  	cfg := bs.client.GetConfig()
   655  	rawBytes, err := bs.db.Get(cfg.CalcTxKey(hash))
   656  	if rawBytes == nil || err != nil {
   657  		if err != dbm.ErrNotFoundInDb {
   658  			storeLog.Error("GetTx", "hash", common.ToHex(hash), "err", err)
   659  		}
   660  		err = errors.New("tx not exist")
   661  		return nil, err
   662  	}
   663  
   664  	var txResult types.TxResult
   665  	err = proto.Unmarshal(rawBytes, &txResult)
   666  	if err != nil {
   667  		return nil, err
   668  	}
   669  	return bs.getRealTxResult(&txResult), nil
   670  }
   671  
   672  func (bs *BlockStore) getRealTxResult(txr *types.TxResult) *types.TxResult {
   673  	cfg := bs.client.GetConfig()
   674  	if !cfg.IsEnable("reduceLocaldb") {
   675  		return txr
   676  	}
   677  
   678  	var blockinfo *types.BlockDetail
   679  	var err error
   680  	var exist bool
   681  
   682  	//首先从缓存的活跃区块中获取,不存在时再从数据库获取并保存到活跃区块中供下次使用
   683  	hash, err := bs.GetBlockHashByHeight(txr.Height)
   684  	if err != nil {
   685  		chainlog.Error("getRealTxResult GetBlockHashByHeight", "height", txr.Height, "error", err)
   686  		return txr
   687  	}
   688  
   689  	blockinfo, exist = bs.GetActiveBlock(string(hash))
   690  	if !exist {
   691  		// 如果是精简版的localdb 则需要从block中获取tx交易内容以及receipt
   692  		blockinfo, err = bs.LoadBlockByHash(hash)
   693  		if err != nil {
   694  			chainlog.Error("getRealTxResult LoadBlockByHash", "height", txr.Height, "hash", common.ToHex(hash), "error", err)
   695  			return txr
   696  		}
   697  
   698  		//添加到活跃区块的缓存中
   699  		bs.AddActiveBlock(string(hash), blockinfo)
   700  	}
   701  
   702  	if int(txr.Index) < len(blockinfo.Block.Txs) {
   703  		txr.Tx = blockinfo.Block.Txs[txr.Index]
   704  	}
   705  	if int(txr.Index) < len(blockinfo.Receipts) {
   706  		txr.Receiptdate = blockinfo.Receipts[txr.Index]
   707  	}
   708  
   709  	return txr
   710  }
   711  
   712  //AddTxs 通过批量存储tx信息到db中
   713  func (bs *BlockStore) AddTxs(storeBatch dbm.Batch, blockDetail *types.BlockDetail) error {
   714  	kv, err := bs.getLocalKV(blockDetail)
   715  	if err != nil {
   716  		storeLog.Error("indexTxs getLocalKV err", "Height", blockDetail.Block.Height, "err", err)
   717  		return err
   718  	}
   719  	//storelog.Info("add txs kv num", "n", len(kv.KV))
   720  	for i := 0; i < len(kv.KV); i++ {
   721  		if kv.KV[i].Value == nil {
   722  			storeBatch.Delete(kv.KV[i].Key)
   723  		} else {
   724  			storeBatch.Set(kv.KV[i].Key, kv.KV[i].Value)
   725  		}
   726  	}
   727  	return nil
   728  }
   729  
   730  //DelTxs 通过批量删除tx信息从db中
   731  func (bs *BlockStore) DelTxs(storeBatch dbm.Batch, blockDetail *types.BlockDetail) error {
   732  	//存储key:addr:flag:height ,value:txhash
   733  	//flag :0-->from,1--> to
   734  	//height=height*10000+index 存储账户地址相关的交易
   735  	kv, err := bs.getDelLocalKV(blockDetail)
   736  	if err != nil {
   737  		storeLog.Error("indexTxs getLocalKV err", "Height", blockDetail.Block.Height, "err", err)
   738  		return err
   739  	}
   740  	for i := 0; i < len(kv.KV); i++ {
   741  		if kv.KV[i].Value == nil {
   742  			storeBatch.Delete(kv.KV[i].Key)
   743  		} else {
   744  			storeBatch.Set(kv.KV[i].Key, kv.KV[i].Value)
   745  		}
   746  	}
   747  
   748  	return nil
   749  }
   750  
   751  //GetHeightByBlockHash 从db数据库中获取指定hash对应的block高度
   752  func (bs *BlockStore) GetHeightByBlockHash(hash []byte) (int64, error) {
   753  
   754  	heightbytes, err := bs.db.Get(calcHashToHeightKey(hash))
   755  	if heightbytes == nil || err != nil {
   756  		if err != dbm.ErrNotFoundInDb {
   757  			storeLog.Error("GetHeightByBlockHash", "error", err)
   758  		}
   759  		return -1, types.ErrHashNotExist
   760  	}
   761  	return decodeHeight(heightbytes)
   762  }
   763  
   764  func decodeHeight(heightbytes []byte) (int64, error) {
   765  	var height types.Int64
   766  	err := types.Decode(heightbytes, &height)
   767  	if err != nil {
   768  		//may be old database format json...
   769  		err = json.Unmarshal(heightbytes, &height.Data)
   770  		if err != nil {
   771  			storeLog.Error("GetHeightByBlockHash Could not unmarshal height bytes", "error", err)
   772  			return -1, types.ErrUnmarshal
   773  		}
   774  	}
   775  	return height.Data, nil
   776  }
   777  
   778  //GetBlockHashByHeight 从db数据库中获取指定height对应的blockhash
   779  func (bs *BlockStore) GetBlockHashByHeight(height int64) ([]byte, error) {
   780  
   781  	if hash := bs.blockCache.GetBlockHash(height); len(hash) > 0 {
   782  		return hash, nil
   783  	}
   784  	hash, err := bs.db.Get(calcHeightToHashKey(height))
   785  	if hash == nil || err != nil {
   786  		if err != dbm.ErrNotFoundInDb {
   787  			storeLog.Error("GetBlockHashByHeight", "error", err)
   788  		}
   789  		return nil, types.ErrHeightNotExist
   790  	}
   791  	return hash, nil
   792  }
   793  
   794  //GetBlockHeaderByHeight 通过blockheight获取blockheader
   795  //为了兼容旧版本的,需要先通过新的方式来获取,获取失败就使用旧的再获取一次
   796  func (bs *BlockStore) GetBlockHeaderByHeight(height int64) (*types.Header, error) {
   797  	return bs.loadHeaderByIndex(height)
   798  }
   799  
   800  //GetBlockHeaderByHash 通过blockhash获取blockheader
   801  func (bs *BlockStore) GetBlockHeaderByHash(hash []byte) (*types.Header, error) {
   802  	//使用table的方式获取,hash索引查table表获取
   803  	header, err := getHeaderByIndex(bs.db, "hash", hash, nil)
   804  	if header == nil || err != nil {
   805  		if err != dbm.ErrNotFoundInDb {
   806  			storeLog.Error("GetBlockHerderByHash:getHeaderByIndex ", "err", err)
   807  		}
   808  		return nil, types.ErrHashNotExist
   809  	}
   810  	return header, nil
   811  }
   812  
   813  func (bs *BlockStore) getLocalKV(detail *types.BlockDetail) (*types.LocalDBSet, error) {
   814  	if bs.client == nil {
   815  		panic("client not bind message queue.")
   816  	}
   817  	msg := bs.client.NewMessage("execs", types.EventAddBlock, detail)
   818  	err := bs.client.Send(msg, true)
   819  	if err != nil {
   820  		return nil, err
   821  	}
   822  	resp, err := bs.client.Wait(msg)
   823  	if err != nil {
   824  		return nil, err
   825  	}
   826  	kv := resp.GetData().(*types.LocalDBSet)
   827  	return kv, nil
   828  }
   829  
   830  func (bs *BlockStore) getDelLocalKV(detail *types.BlockDetail) (*types.LocalDBSet, error) {
   831  	if bs.client == nil {
   832  		panic("client not bind message queue.")
   833  	}
   834  	msg := bs.client.NewMessage("execs", types.EventDelBlock, detail)
   835  	err := bs.client.Send(msg, true)
   836  	if err != nil {
   837  		return nil, err
   838  	}
   839  	resp, err := bs.client.Wait(msg)
   840  	if err != nil {
   841  		return nil, err
   842  	}
   843  	localDBSet := resp.GetData().(*types.LocalDBSet)
   844  	return localDBSet, nil
   845  }
   846  
   847  //GetTdByBlockHash 从db数据库中获取指定blockhash对应的block总难度td
   848  func (bs *BlockStore) GetTdByBlockHash(hash []byte) (*big.Int, error) {
   849  
   850  	blocktd, err := bs.db.Get(calcHashToTdKey(hash))
   851  	if blocktd == nil || err != nil {
   852  		if err != dbm.ErrNotFoundInDb {
   853  			storeLog.Error("GetTdByBlockHash ", "error", err)
   854  		}
   855  		return nil, types.ErrHashNotExist
   856  	}
   857  	td := new(big.Int)
   858  	return td.SetBytes(blocktd), nil
   859  }
   860  
   861  //SaveTdByBlockHash 保存block hash对应的总难度到db中
   862  func (bs *BlockStore) SaveTdByBlockHash(storeBatch dbm.Batch, hash []byte, td *big.Int) error {
   863  	if td == nil {
   864  		return types.ErrInvalidParam
   865  	}
   866  
   867  	storeBatch.Set(calcHashToTdKey(hash), td.Bytes())
   868  	return nil
   869  }
   870  
   871  //NewBatch new
   872  func (bs *BlockStore) NewBatch(sync bool) dbm.Batch {
   873  	storeBatch := bs.db.NewBatch(sync)
   874  	return storeBatch
   875  }
   876  
   877  //LoadBlockStoreHeight 加载区块高度
   878  func LoadBlockStoreHeight(db dbm.DB) (int64, error) {
   879  	bytes, err := db.Get(blockLastHeight)
   880  	if bytes == nil || err != nil {
   881  		if err != dbm.ErrNotFoundInDb {
   882  			storeLog.Error("LoadBlockStoreHeight", "error", err)
   883  		}
   884  		return -1, types.ErrHeightNotExist
   885  	}
   886  	return decodeHeight(bytes)
   887  }
   888  
   889  // 将收到的block都暂时存储到db中,加入主链之后会重新覆盖。主要是用于chain重组时获取侧链的block使用
   890  func (bs *BlockStore) dbMaybeStoreBlock(blockdetail *types.BlockDetail, sync bool) error {
   891  	if blockdetail == nil {
   892  		return types.ErrInvalidParam
   893  	}
   894  	height := blockdetail.Block.GetHeight()
   895  	hash := blockdetail.Block.Hash(bs.client.GetConfig())
   896  	storeBatch := bs.batch
   897  	storeBatch.Reset()
   898  	storeBatch.UpdateWriteSync(sync)
   899  	//Save block header和body使用table形式存储
   900  	err := bs.saveBlockForTable(storeBatch, blockdetail, false, true)
   901  	if err != nil {
   902  		chainlog.Error("dbMaybeStoreBlock:saveBlockForTable", "height", height, "hash", common.ToHex(hash), "err", err)
   903  		return err
   904  	}
   905  	//保存block的总难度到db中
   906  	parentHash := blockdetail.Block.ParentHash
   907  
   908  	//转换自己的难度成big.int
   909  	difficulty := difficulty.CalcWork(blockdetail.Block.Difficulty)
   910  
   911  	var blocktd *big.Int
   912  	if height == 0 {
   913  		blocktd = difficulty
   914  	} else {
   915  		parenttd, err := bs.GetTdByBlockHash(parentHash)
   916  		if err != nil {
   917  			chainlog.Error("dbMaybeStoreBlock GetTdByBlockHash", "height", height, "parentHash", common.ToHex(parentHash))
   918  			return err
   919  		}
   920  		blocktd = new(big.Int).Add(difficulty, parenttd)
   921  	}
   922  
   923  	err = bs.SaveTdByBlockHash(storeBatch, blockdetail.Block.Hash(bs.client.GetConfig()), blocktd)
   924  	if err != nil {
   925  		chainlog.Error("dbMaybeStoreBlock SaveTdByBlockHash:", "height", height, "hash", common.ToHex(hash), "err", err)
   926  		return err
   927  	}
   928  
   929  	err = storeBatch.Write()
   930  	if err != nil {
   931  		chainlog.Error("dbMaybeStoreBlock storeBatch.Write:", "err", err)
   932  		panic(err)
   933  	}
   934  	return nil
   935  }
   936  
   937  //LoadBlockLastSequence 获取当前最新的block操作序列号
   938  func (bs *BlockStore) LoadBlockLastSequence() (int64, error) {
   939  	lastKey := calcLastSeqKey(bs.isParaChain)
   940  	bytes, err := bs.db.Get(lastKey)
   941  	if bytes == nil || err != nil {
   942  		if err != dbm.ErrNotFoundInDb {
   943  			storeLog.Error("LoadBlockLastSequence", "error", err)
   944  		}
   945  		return -1, types.ErrHeightNotExist
   946  	}
   947  	return decodeHeight(bytes)
   948  }
   949  
   950  //LoadBlockLastMainSequence 获取当前最新的block操作序列号
   951  func (bs *BlockStore) LoadBlockLastMainSequence() (int64, error) {
   952  	bytes, err := bs.db.Get(LastSequence)
   953  	if bytes == nil || err != nil {
   954  		if err != dbm.ErrNotFoundInDb {
   955  			storeLog.Error("LoadBlockLastMainSequence", "error", err)
   956  		}
   957  		return -1, types.ErrHeightNotExist
   958  	}
   959  	return decodeHeight(bytes)
   960  }
   961  
   962  //SaveBlockSequence 存储block 序列执行的类型用于blockchain的恢复
   963  //获取当前的序列号,将此序列号加1存储本block的hash ,当使能isRecordBlockSequence
   964  //平行链使能isParaChain时,而外保存主链的 sequence
   965  // 需要保存
   966  // seq->hash, hash->seq, last_seq
   967  // 平行链需要主链的对应信息
   968  func (bs *BlockStore) saveBlockSequence(storeBatch dbm.Batch, hash []byte, height int64, Type int64, sequence int64) (int64, error) {
   969  	var newSequence int64
   970  	if bs.saveSequence {
   971  		Sequence, err := bs.LoadBlockLastSequence()
   972  		if err != nil {
   973  			storeLog.Error("SaveBlockSequence", "LoadBlockLastSequence err", err)
   974  			if err != types.ErrHeightNotExist {
   975  				panic(err)
   976  			}
   977  		}
   978  
   979  		newSequence = Sequence + 1
   980  		//开启isRecordBlockSequence功能必须从0开始同步数据,不允许从非0高度开启此功能
   981  		if newSequence == 0 && height != 0 {
   982  			storeLog.Error("isRecordBlockSequence is true must Synchronizing data from zero block", "height", height, "seq", newSequence)
   983  			panic(errors.New("isRecordBlockSequence is true must Synchronizing data from zero block"))
   984  		}
   985  
   986  		// seq->hash
   987  		var blockSequence types.BlockSequence
   988  		blockSequence.Hash = hash
   989  		blockSequence.Type = Type
   990  		BlockSequenceByte, err := proto.Marshal(&blockSequence)
   991  		if err != nil {
   992  			storeLog.Error("SaveBlockSequence Marshal BlockSequence", "hash", common.ToHex(hash), "error", err)
   993  			return newSequence, err
   994  		}
   995  		storeBatch.Set(calcSequenceToHashKey(newSequence, bs.isParaChain), BlockSequenceByte)
   996  
   997  		sequenceBytes := types.Encode(&types.Int64{Data: newSequence})
   998  		// hash->seq 只记录add block时的hash和seq对应关系
   999  		if Type == types.AddBlock {
  1000  			storeBatch.Set(calcHashToSequenceKey(hash, bs.isParaChain), sequenceBytes)
  1001  		}
  1002  
  1003  		// 记录last seq
  1004  		storeBatch.Set(calcLastSeqKey(bs.isParaChain), sequenceBytes)
  1005  	}
  1006  
  1007  	if !bs.isParaChain {
  1008  		return newSequence, nil
  1009  	}
  1010  
  1011  	mainSeq := sequence
  1012  	var blockSequence types.BlockSequence
  1013  	blockSequence.Hash = hash
  1014  	blockSequence.Type = Type
  1015  	BlockSequenceByte, err := proto.Marshal(&blockSequence)
  1016  	if err != nil {
  1017  		storeLog.Error("SaveBlockSequence Marshal BlockSequence", "hash", common.ToHex(hash), "error", err)
  1018  		return newSequence, err
  1019  	}
  1020  	storeBatch.Set(calcMainSequenceToHashKey(mainSeq), BlockSequenceByte)
  1021  
  1022  	// hash->seq 只记录add block时的hash和seq对应关系
  1023  	sequenceBytes := types.Encode(&types.Int64{Data: mainSeq})
  1024  	if Type == types.AddBlock {
  1025  		storeBatch.Set(calcHashToMainSequenceKey(hash), sequenceBytes)
  1026  	}
  1027  	storeBatch.Set(LastSequence, sequenceBytes)
  1028  
  1029  	return newSequence, nil
  1030  }
  1031  
  1032  //LoadBlockBySequence 通过seq高度获取BlockDetail信息
  1033  func (bs *BlockStore) LoadBlockBySequence(Sequence int64) (*types.BlockDetail, int, error) {
  1034  	//首先通过Sequence序列号获取对应的blockhash和操作类型从db中
  1035  	BlockSequence, err := bs.GetBlockSequence(Sequence)
  1036  	if err != nil {
  1037  		return nil, 0, err
  1038  	}
  1039  	return bs.loadBlockByHash(BlockSequence.Hash)
  1040  }
  1041  
  1042  //LoadBlockByMainSequence 通过main seq高度获取BlockDetail信息
  1043  func (bs *BlockStore) LoadBlockByMainSequence(sequence int64) (*types.BlockDetail, int, error) {
  1044  	//首先通过Sequence序列号获取对应的blockhash和操作类型从db中
  1045  	BlockSequence, err := bs.GetBlockByMainSequence(sequence)
  1046  	if err != nil {
  1047  		return nil, 0, err
  1048  	}
  1049  	return bs.loadBlockByHash(BlockSequence.Hash)
  1050  }
  1051  
  1052  //GetBlockSequence 从db数据库中获取指定Sequence对应的block序列操作信息
  1053  func (bs *BlockStore) GetBlockSequence(Sequence int64) (*types.BlockSequence, error) {
  1054  	var blockSeq types.BlockSequence
  1055  	blockSeqByte, err := bs.db.Get(calcSequenceToHashKey(Sequence, bs.isParaChain))
  1056  	if blockSeqByte == nil || err != nil {
  1057  		if err != dbm.ErrNotFoundInDb {
  1058  			storeLog.Error("GetBlockSequence", "error", err)
  1059  		}
  1060  		return nil, types.ErrHeightNotExist
  1061  	}
  1062  
  1063  	err = proto.Unmarshal(blockSeqByte, &blockSeq)
  1064  	if err != nil {
  1065  		storeLog.Error("GetBlockSequence", "err", err)
  1066  		return nil, err
  1067  	}
  1068  	return &blockSeq, nil
  1069  }
  1070  
  1071  //GetBlockByMainSequence 从db数据库中获取指定Sequence对应的block序列操作信息
  1072  func (bs *BlockStore) GetBlockByMainSequence(sequence int64) (*types.BlockSequence, error) {
  1073  	var blockSeq types.BlockSequence
  1074  	blockSeqByte, err := bs.db.Get(calcMainSequenceToHashKey(sequence))
  1075  	if blockSeqByte == nil || err != nil {
  1076  		if err != dbm.ErrNotFoundInDb {
  1077  			storeLog.Error("GetBlockByMainSequence", "error", err)
  1078  		}
  1079  		return nil, types.ErrHeightNotExist
  1080  	}
  1081  
  1082  	err = proto.Unmarshal(blockSeqByte, &blockSeq)
  1083  	if err != nil {
  1084  		storeLog.Error("GetBlockByMainSequence", "err", err)
  1085  		return nil, err
  1086  	}
  1087  	return &blockSeq, nil
  1088  }
  1089  
  1090  //GetSequenceByHash 通过block还是获取对应的seq
  1091  func (bs *BlockStore) GetSequenceByHash(hash []byte) (int64, error) {
  1092  	var seq types.Int64
  1093  	seqbytes, err := bs.db.Get(calcHashToSequenceKey(hash, bs.isParaChain))
  1094  	if seqbytes == nil || err != nil {
  1095  		if err != dbm.ErrNotFoundInDb {
  1096  			storeLog.Error("GetSequenceByHash", "error", err)
  1097  		}
  1098  		return -1, types.ErrHashNotExist
  1099  	}
  1100  
  1101  	err = types.Decode(seqbytes, &seq)
  1102  	if err != nil {
  1103  		storeLog.Error("GetSequenceByHash  types.Decode", "error", err)
  1104  		return -1, types.ErrUnmarshal
  1105  	}
  1106  	return seq.Data, nil
  1107  }
  1108  
  1109  //GetMainSequenceByHash 通过block还是获取对应的seq,只提供给parachain使用
  1110  func (bs *BlockStore) GetMainSequenceByHash(hash []byte) (int64, error) {
  1111  	var seq types.Int64
  1112  	seqbytes, err := bs.db.Get(calcHashToMainSequenceKey(hash))
  1113  	if seqbytes == nil || err != nil {
  1114  		if err != dbm.ErrNotFoundInDb {
  1115  			storeLog.Error("GetMainSequenceByHash", "error", err)
  1116  		}
  1117  		return -1, types.ErrHashNotExist
  1118  	}
  1119  
  1120  	err = types.Decode(seqbytes, &seq)
  1121  	if err != nil {
  1122  		storeLog.Error("GetMainSequenceByHash  types.Decode", "error", err)
  1123  		return -1, types.ErrUnmarshal
  1124  	}
  1125  	return seq.Data, nil
  1126  }
  1127  
  1128  //GetDbVersion 获取blockchain的数据库版本号
  1129  func (bs *BlockStore) GetDbVersion() int64 {
  1130  	ver := types.Int64{}
  1131  	version, err := bs.db.Get(version.BlockChainVerKey)
  1132  	if err != nil && err != types.ErrNotFound {
  1133  		storeLog.Info("GetDbVersion", "err", err)
  1134  		return 0
  1135  	}
  1136  	if len(version) == 0 {
  1137  		storeLog.Info("GetDbVersion len(version)==0")
  1138  		return 0
  1139  	}
  1140  	err = types.Decode(version, &ver)
  1141  	if err != nil {
  1142  		storeLog.Info("GetDbVersion", "types.Decode err", err)
  1143  		return 0
  1144  	}
  1145  	storeLog.Info("GetDbVersion", "blockchain db version", ver.Data)
  1146  	return ver.Data
  1147  }
  1148  
  1149  //SetDbVersion 获取blockchain的数据库版本号
  1150  func (bs *BlockStore) SetDbVersion(versionNo int64) error {
  1151  	ver := types.Int64{Data: versionNo}
  1152  	verByte := types.Encode(&ver)
  1153  
  1154  	storeLog.Info("SetDbVersion", "blcokchain db version", versionNo)
  1155  
  1156  	return bs.db.SetSync(version.BlockChainVerKey, verByte)
  1157  }
  1158  
  1159  //GetUpgradeMeta 获取blockchain的数据库版本号
  1160  func (bs *BlockStore) GetUpgradeMeta() (*types.UpgradeMeta, error) {
  1161  	ver := types.UpgradeMeta{}
  1162  	version, err := bs.db.Get(version.LocalDBMeta)
  1163  	if err != nil && err != dbm.ErrNotFoundInDb {
  1164  		return nil, err
  1165  	}
  1166  	if len(version) == 0 {
  1167  		return &types.UpgradeMeta{Version: "0.0.0"}, nil
  1168  	}
  1169  	err = types.Decode(version, &ver)
  1170  	if err != nil {
  1171  		return nil, err
  1172  	}
  1173  	storeLog.Info("GetUpgradeMeta", "blockchain db version", ver)
  1174  	return &ver, nil
  1175  }
  1176  
  1177  //SetUpgradeMeta 设置blockchain的数据库版本号
  1178  func (bs *BlockStore) SetUpgradeMeta(meta *types.UpgradeMeta) error {
  1179  	verByte := types.Encode(meta)
  1180  	storeLog.Info("SetUpgradeMeta", "meta", meta)
  1181  	return bs.db.SetSync(version.LocalDBMeta, verByte)
  1182  }
  1183  
  1184  //GetStoreUpgradeMeta 获取存在blockchain中的Store的数据库版本号
  1185  func (bs *BlockStore) GetStoreUpgradeMeta() (*types.UpgradeMeta, error) {
  1186  	ver := types.UpgradeMeta{}
  1187  	version, err := bs.db.Get(version.StoreDBMeta)
  1188  	if err != nil && err != dbm.ErrNotFoundInDb {
  1189  		return nil, err
  1190  	}
  1191  	if len(version) == 0 {
  1192  		return &types.UpgradeMeta{Version: "0.0.0"}, nil
  1193  	}
  1194  	err = types.Decode(version, &ver)
  1195  	if err != nil {
  1196  		return nil, err
  1197  	}
  1198  	storeLog.Info("GetStoreUpgradeMeta", "blockchain db version", ver)
  1199  	return &ver, nil
  1200  }
  1201  
  1202  //SetStoreUpgradeMeta 设置blockchain中的Store的数据库版本号
  1203  func (bs *BlockStore) SetStoreUpgradeMeta(meta *types.UpgradeMeta) error {
  1204  	verByte := types.Encode(meta)
  1205  	storeLog.Debug("SetStoreUpgradeMeta", "meta", meta)
  1206  	return bs.db.SetSync(version.StoreDBMeta, verByte)
  1207  }
  1208  
  1209  const (
  1210  	seqStatusOk = iota
  1211  	seqStatusNeedCreate
  1212  )
  1213  
  1214  //CheckSequenceStatus 配置的合法性检测
  1215  func (bs *BlockStore) CheckSequenceStatus(recordSequence bool) int {
  1216  	lastHeight := bs.Height()
  1217  	lastSequence, err := bs.LoadBlockLastSequence()
  1218  	if err != nil {
  1219  		if err != types.ErrHeightNotExist {
  1220  			storeLog.Error("CheckSequenceStatus", "LoadBlockLastSequence err", err)
  1221  			panic(err)
  1222  		}
  1223  	}
  1224  	//使能isRecordBlockSequence时的检测
  1225  	if recordSequence {
  1226  		//中途开启isRecordBlockSequence报错
  1227  		if lastSequence == -1 && lastHeight != -1 {
  1228  			storeLog.Error("CheckSequenceStatus", "lastHeight", lastHeight, "lastSequence", lastSequence)
  1229  			return seqStatusNeedCreate
  1230  		}
  1231  		//lastSequence 必须大于等于lastheight
  1232  		if lastHeight > lastSequence {
  1233  			storeLog.Error("CheckSequenceStatus", "lastHeight", lastHeight, "lastSequence", lastSequence)
  1234  			return seqStatusNeedCreate
  1235  		}
  1236  		return seqStatusOk
  1237  	}
  1238  	//去使能isRecordBlockSequence时的检测
  1239  	if lastSequence != -1 {
  1240  		storeLog.Error("CheckSequenceStatus", "lastSequence", lastSequence)
  1241  		panic("can not disable isRecordBlockSequence")
  1242  	}
  1243  	return seqStatusOk
  1244  }
  1245  
  1246  //CreateSequences 根据高度生成sequence记录
  1247  func (bs *BlockStore) CreateSequences(batchSize int64) {
  1248  	lastSeq, err := bs.LoadBlockLastSequence()
  1249  	if err != nil {
  1250  		if err != types.ErrHeightNotExist {
  1251  			storeLog.Error("CreateSequences LoadBlockLastSequence", "error", err)
  1252  			panic("CreateSequences LoadBlockLastSequence" + err.Error())
  1253  		}
  1254  	}
  1255  	storeLog.Info("CreateSequences LoadBlockLastSequence", "start", lastSeq)
  1256  
  1257  	newBatch := bs.NewBatch(true)
  1258  	lastHeight := bs.Height()
  1259  
  1260  	for i := lastSeq + 1; i <= lastHeight; i++ {
  1261  		seq := i
  1262  		header, err := bs.GetBlockHeaderByHeight(i)
  1263  		if err != nil {
  1264  			storeLog.Error("CreateSequences GetBlockHeaderByHeight", "height", i, "error", err)
  1265  			panic("CreateSequences GetBlockHeaderByHeight" + err.Error())
  1266  		}
  1267  
  1268  		// seq->hash
  1269  		var blockSequence types.BlockSequence
  1270  		blockSequence.Hash = header.Hash
  1271  		blockSequence.Type = types.AddBlock
  1272  		BlockSequenceByte, err := proto.Marshal(&blockSequence)
  1273  		if err != nil {
  1274  			storeLog.Error("CreateSequences Marshal BlockSequence", "height", i, "hash", common.ToHex(header.Hash), "error", err)
  1275  			panic("CreateSequences Marshal BlockSequence" + err.Error())
  1276  		}
  1277  		newBatch.Set(calcSequenceToHashKey(seq, bs.isParaChain), BlockSequenceByte)
  1278  
  1279  		// hash -> seq
  1280  		sequenceBytes := types.Encode(&types.Int64{Data: seq})
  1281  		newBatch.Set(calcHashToSequenceKey(header.Hash, bs.isParaChain), sequenceBytes)
  1282  
  1283  		if i-lastSeq == batchSize {
  1284  			storeLog.Info("CreateSequences ", "height", i)
  1285  			newBatch.Set(calcLastSeqKey(bs.isParaChain), types.Encode(&types.Int64{Data: i}))
  1286  			err = newBatch.Write()
  1287  			if err != nil {
  1288  				storeLog.Error("CreateSequences newBatch.Write", "error", err)
  1289  				panic("CreateSequences newBatch.Write" + err.Error())
  1290  			}
  1291  			lastSeq = i
  1292  			newBatch.Reset()
  1293  		}
  1294  	}
  1295  	// last seq
  1296  	newBatch.Set(calcLastSeqKey(bs.isParaChain), types.Encode(&types.Int64{Data: lastHeight}))
  1297  	err = newBatch.Write()
  1298  	if err != nil {
  1299  		storeLog.Error("CreateSequences newBatch.Write", "error", err)
  1300  		panic("CreateSequences newBatch.Write" + err.Error())
  1301  	}
  1302  	storeLog.Info("CreateSequences done")
  1303  }
  1304  
  1305  //SetConsensusPara 设置kv到数据库,当value是空时需要delete操作
  1306  func (bs *BlockStore) SetConsensusPara(kvs *types.LocalDBSet) error {
  1307  	var isSync bool
  1308  	if kvs.GetTxid() != 0 {
  1309  		isSync = true
  1310  	}
  1311  	batch := bs.db.NewBatch(isSync)
  1312  	for i := 0; i < len(kvs.KV); i++ {
  1313  		if types.CheckConsensusParaTxsKey(kvs.KV[i].Key) {
  1314  			if kvs.KV[i].Value == nil {
  1315  				batch.Delete(kvs.KV[i].Key)
  1316  			} else {
  1317  				batch.Set(kvs.KV[i].Key, kvs.KV[i].Value)
  1318  			}
  1319  		} else {
  1320  			storeLog.Error("Set:CheckConsensusParaTxsKey:fail", "key", string(kvs.KV[i].Key))
  1321  		}
  1322  	}
  1323  	err := batch.Write()
  1324  	if err != nil {
  1325  		panic(err)
  1326  	}
  1327  	return err
  1328  }
  1329  
  1330  //saveBlockForTable 将block的header和body以及paratx保存成table形式,方便快速查询
  1331  func (bs *BlockStore) saveBlockForTable(storeBatch dbm.Batch, blockdetail *types.BlockDetail, isBestChain, isSaveReceipt bool) error {
  1332  
  1333  	height := blockdetail.Block.Height
  1334  	cfg := bs.client.GetConfig()
  1335  	hash := blockdetail.Block.Hash(cfg)
  1336  
  1337  	// Save blockbody
  1338  	blockbody := bs.BlockdetailToBlockBody(blockdetail)
  1339  	// 这里将blockbody进行中的receipt拆分成独立的一张表,
  1340  	// 因此body中只保存Receipts的结果,具体内容在ReceiptTable中
  1341  	blockbody.Receipts = reduceReceipts(blockbody)
  1342  	bodykvs, err := saveBlockBodyTable(bs.db, blockbody)
  1343  	if err != nil {
  1344  		storeLog.Error("SaveBlockForTable:saveBlockBodyTable", "height", height, "hash", common.ToHex(hash), "err", err)
  1345  		return err
  1346  	}
  1347  	for _, kv := range bodykvs {
  1348  		storeBatch.Set(kv.GetKey(), kv.GetValue())
  1349  	}
  1350  
  1351  	// Save blockReceipt
  1352  	if isSaveReceipt {
  1353  		blockReceipt := &types.BlockReceipt{
  1354  			Receipts: blockdetail.Receipts,
  1355  			Hash:     hash,
  1356  			Height:   height,
  1357  		}
  1358  		recptkvs, err := saveBlockReceiptTable(bs.db, blockReceipt)
  1359  		if err != nil {
  1360  			storeLog.Error("SaveBlockForTable:saveBlockReceiptTable", "height", height, "hash", common.ToHex(hash), "err", err)
  1361  			return err
  1362  		}
  1363  		for _, kv := range recptkvs {
  1364  			storeBatch.Set(kv.GetKey(), kv.GetValue())
  1365  		}
  1366  	}
  1367  
  1368  	// Save blockheader
  1369  	var blockheader types.Header
  1370  	blockheader.Version = blockdetail.Block.Version
  1371  	blockheader.ParentHash = blockdetail.Block.ParentHash
  1372  	blockheader.TxHash = blockdetail.Block.TxHash
  1373  	blockheader.StateHash = blockdetail.Block.StateHash
  1374  	blockheader.Height = blockdetail.Block.Height
  1375  	blockheader.BlockTime = blockdetail.Block.BlockTime
  1376  	blockheader.Signature = blockdetail.Block.Signature
  1377  	blockheader.Difficulty = blockdetail.Block.Difficulty
  1378  	blockheader.Hash = hash
  1379  	blockheader.TxCount = int64(len(blockdetail.Block.Txs))
  1380  
  1381  	headerkvs, err := saveHeaderTable(bs.db, &blockheader)
  1382  	if err != nil {
  1383  		storeLog.Error("SaveBlock:saveHeaderTable", "height", height, "hash", common.ToHex(hash), "err", err)
  1384  		return err
  1385  	}
  1386  	for _, kv := range headerkvs {
  1387  		storeBatch.Set(kv.GetKey(), kv.GetValue())
  1388  	}
  1389  
  1390  	//只过滤主链上的平行链交易
  1391  	if isBestChain && !bs.isParaChain {
  1392  		paratxkvs, err := saveParaTxTable(cfg, bs.db, height, hash, blockdetail.Block.Txs)
  1393  		if err != nil {
  1394  			storeLog.Error("SaveBlock:saveParaTxTable", "height", height, "hash", common.ToHex(hash), "err", err)
  1395  			return err
  1396  		}
  1397  		for _, kv := range paratxkvs {
  1398  			storeBatch.Set(kv.GetKey(), kv.GetValue())
  1399  		}
  1400  	}
  1401  	return nil
  1402  }
  1403  
  1404  //loadBlockByIndex 通过索引获取BlockDetail信息
  1405  func (bs *BlockStore) loadBlockByIndex(indexName string, prefix []byte, primaryKey []byte) (*types.BlockDetail, error) {
  1406  	cfg := bs.client.GetConfig()
  1407  	//获取header
  1408  	blockheader, err := getHeaderByIndex(bs.db, indexName, prefix, primaryKey)
  1409  	if blockheader == nil || err != nil {
  1410  		if err != dbm.ErrNotFoundInDb {
  1411  			storeLog.Error("loadBlockByIndex:getHeaderByIndex", "indexName", indexName, "prefix", prefix, "primaryKey", primaryKey, "err", err)
  1412  		}
  1413  		return nil, types.ErrHashNotExist
  1414  	}
  1415  
  1416  	//获取body
  1417  	blockbody, err := bs.multiGetBody(blockheader, indexName, prefix, primaryKey)
  1418  	if blockbody == nil || err != nil {
  1419  		return nil, err
  1420  	}
  1421  
  1422  	blockreceipt := blockbody.Receipts
  1423  	// 非精简节点查询时候需要在ReceiptTable中获取详细的receipt信息, 精简情况下可以获取未精简部分receipt
  1424  	if !cfg.IsEnable("reduceLocaldb") || bs.Height() < blockheader.Height+ReduceHeight {
  1425  		receipt, err := getReceiptByIndex(bs.db, indexName, prefix, primaryKey)
  1426  		if receipt != nil {
  1427  			blockreceipt = receipt.Receipts
  1428  		} else {
  1429  			storeLog.Error("loadBlockByIndex:getReceiptByIndex", "indexName", indexName, "prefix", prefix, "primaryKey", primaryKey, "err", err)
  1430  			if !cfg.IsEnable("reduceLocaldb") {
  1431  				return nil, types.ErrHashNotExist
  1432  			}
  1433  		}
  1434  	}
  1435  
  1436  	var blockdetail types.BlockDetail
  1437  	var block types.Block
  1438  
  1439  	block.Version = blockheader.Version
  1440  	block.ParentHash = blockheader.ParentHash
  1441  	block.TxHash = blockheader.TxHash
  1442  	block.StateHash = blockheader.StateHash
  1443  	block.Height = blockheader.Height
  1444  	block.BlockTime = blockheader.BlockTime
  1445  	block.Signature = blockheader.Signature
  1446  	block.Difficulty = blockheader.Difficulty
  1447  	block.Txs = blockbody.Txs
  1448  	block.MainHeight = blockbody.MainHeight
  1449  	block.MainHash = blockbody.MainHash
  1450  
  1451  	blockdetail.Receipts = blockreceipt
  1452  	blockdetail.Block = &block
  1453  	return &blockdetail, nil
  1454  }
  1455  
  1456  //loadHeaderByIndex 通过索引获取区块头信息
  1457  func (bs *BlockStore) loadHeaderByIndex(height int64) (*types.Header, error) {
  1458  
  1459  	hash, err := bs.GetBlockHashByHeight(height)
  1460  	if err != nil {
  1461  		return nil, err
  1462  	}
  1463  
  1464  	header, err := getHeaderByIndex(bs.db, "", calcHeightHashKey(height, hash), nil)
  1465  	if header == nil || err != nil {
  1466  		if err != dbm.ErrNotFoundInDb {
  1467  			storeLog.Error("loadHeaderByHeight:getHeaderByIndex", "error", err)
  1468  		}
  1469  		return nil, types.ErrHashNotExist
  1470  	}
  1471  	return header, nil
  1472  }
  1473  
  1474  //loadBlockByHashOld 需要在db升级之前使用旧的key值获取block信息
  1475  func (bs *BlockStore) loadBlockByHashOld(hash []byte) (*types.BlockDetail, error) {
  1476  	var blockdetail types.BlockDetail
  1477  	var blockheader types.Header
  1478  	var blockbody types.BlockBody
  1479  	var block types.Block
  1480  
  1481  	//通过hash获取blockheader
  1482  	header, err := bs.db.Get(calcHashToBlockHeaderKey(hash))
  1483  	if header == nil || err != nil {
  1484  		if err != dbm.ErrNotFoundInDb {
  1485  			storeLog.Error("loadBlockByHashOld:calcHashToBlockHeaderKey", "hash", common.ToHex(hash), "err", err)
  1486  		}
  1487  		return nil, types.ErrHashNotExist
  1488  	}
  1489  	err = proto.Unmarshal(header, &blockheader)
  1490  	if err != nil {
  1491  		storeLog.Error("loadBlockByHashOld", "err", err)
  1492  		return nil, err
  1493  	}
  1494  
  1495  	//通过hash获取blockbody
  1496  	body, err := bs.db.Get(calcHashToBlockBodyKey(hash))
  1497  	if body == nil || err != nil {
  1498  		if err != dbm.ErrNotFoundInDb {
  1499  			storeLog.Error("loadBlockByHashOld:calcHashToBlockBodyKey ", "err", err)
  1500  		}
  1501  		return nil, types.ErrHashNotExist
  1502  	}
  1503  	err = proto.Unmarshal(body, &blockbody)
  1504  	if err != nil {
  1505  		storeLog.Error("loadBlockByHashOld", "err", err)
  1506  		return nil, err
  1507  	}
  1508  
  1509  	block.Version = blockheader.Version
  1510  	block.ParentHash = blockheader.ParentHash
  1511  	block.TxHash = blockheader.TxHash
  1512  	block.StateHash = blockheader.StateHash
  1513  	block.Height = blockheader.Height
  1514  	block.BlockTime = blockheader.BlockTime
  1515  	block.Signature = blockheader.Signature
  1516  	block.Difficulty = blockheader.Difficulty
  1517  	block.Txs = blockbody.Txs
  1518  	block.MainHeight = blockbody.MainHeight
  1519  	block.MainHash = blockbody.MainHash
  1520  	blockdetail.Receipts = blockbody.Receipts
  1521  	blockdetail.Block = &block
  1522  
  1523  	return &blockdetail, nil
  1524  }
  1525  
  1526  //loadBlockByHeightOld 在版本升级到2.0.0时需要使用旧接口获取block信息
  1527  func (bs *BlockStore) loadBlockByHeightOld(height int64) (*types.BlockDetail, error) {
  1528  	hash, err := bs.GetBlockHashByHeight(height)
  1529  	if err != nil {
  1530  		return nil, err
  1531  	}
  1532  	return bs.loadBlockByHashOld(hash)
  1533  }
  1534  
  1535  //getBlockHeaderByHeightOld 需要在db升级之前使用旧的key值获取header信息
  1536  func (bs *BlockStore) getBlockHeaderByHeightOld(height int64) (*types.Header, error) {
  1537  	blockheader, err := bs.db.Get(calcHeightToBlockHeaderKey(height))
  1538  	if err != nil {
  1539  		var hash []byte
  1540  		hash, err = bs.GetBlockHashByHeight(height)
  1541  		if err != nil {
  1542  			return nil, err
  1543  		}
  1544  		blockheader, err = bs.db.Get(calcHashToBlockHeaderKey(hash))
  1545  	}
  1546  	if blockheader == nil || err != nil {
  1547  		if err != dbm.ErrNotFoundInDb {
  1548  			storeLog.Error("getBlockHeaderByHeightOld:calcHashToBlockHeaderKey", "error", err)
  1549  		}
  1550  		return nil, types.ErrHashNotExist
  1551  	}
  1552  	var header types.Header
  1553  	err = proto.Unmarshal(blockheader, &header)
  1554  	if err != nil {
  1555  		storeLog.Error("getBlockHeaderByHeightOld", "Could not unmarshal blockheader:", blockheader)
  1556  		return nil, err
  1557  	}
  1558  	return &header, nil
  1559  }
  1560  
  1561  //loadBlockBySequenceOld 通过seq高度获取BlockDetail信息,v2版本升级时调用
  1562  //可能存在回滚的处理,所以先查旧的,查抄不到就按新的方式再查
  1563  func (bs *BlockStore) loadBlockBySequenceOld(Sequence int64) (*types.BlockDetail, int64, error) {
  1564  
  1565  	blockSeq, err := bs.GetBlockSequence(Sequence)
  1566  	if err != nil {
  1567  		return nil, 0, err
  1568  	}
  1569  
  1570  	block, err := bs.loadBlockByHashOld(blockSeq.Hash)
  1571  	if err != nil {
  1572  		block, err = bs.LoadBlockByHash(blockSeq.Hash)
  1573  		if err != nil {
  1574  			storeLog.Error("getBlockHeaderByHeightOld", "Sequence", Sequence, "type", blockSeq.Type, "hash", common.ToHex(blockSeq.Hash), "err", err)
  1575  			panic(err)
  1576  		}
  1577  	}
  1578  	return block, blockSeq.GetType(), nil
  1579  }
  1580  
  1581  func (bs *BlockStore) saveReduceLocaldbFlag() {
  1582  	kv := types.FlagKV(types.FlagReduceLocaldb, 1)
  1583  	err := bs.db.Set(kv.Key, kv.Value)
  1584  	if err != nil {
  1585  		panic(err)
  1586  	}
  1587  }
  1588  
  1589  func (bs *BlockStore) mustSaveKvset(kv *types.LocalDBSet) {
  1590  	batch := bs.NewBatch(false)
  1591  	for i := 0; i < len(kv.KV); i++ {
  1592  		if kv.KV[i].Value == nil {
  1593  			batch.Delete(kv.KV[i].Key)
  1594  		} else {
  1595  			batch.Set(kv.KV[i].Key, kv.KV[i].Value)
  1596  		}
  1597  	}
  1598  	dbm.MustWrite(batch)
  1599  }
  1600  
  1601  func (bs *BlockStore) multiGetBody(blockheader *types.Header, indexName string, prefix []byte, primaryKey []byte) (*types.BlockBody, error) {
  1602  	cfg := bs.client.GetConfig()
  1603  	chainCfg := cfg.GetModuleConfig().BlockChain
  1604  
  1605  	blockbody, err := getBodyByIndex(bs.db, indexName, prefix, primaryKey)
  1606  	if blockbody == nil || err != nil {
  1607  		if blockheader.GetHeight() > bs.Height()-MaxRollBlockNum-(chainCfg.ChunkblockNum)*int64(DelRollbackChunkNum) {
  1608  			// 该高度范围应该保存在本地
  1609  			return nil, types.ErrHashNotExist
  1610  		}
  1611  		if !chainCfg.DisableShard && chainCfg.EnableFetchP2pstore {
  1612  			bodys, err := bs.getBodyFromP2Pstore(blockheader.Hash, blockheader.Height, blockheader.Height)
  1613  			if bodys == nil || len(bodys.Items) == 0 || err != nil {
  1614  				if err != dbm.ErrNotFoundInDb {
  1615  					storeLog.Error("multiGetBody:getBodyFromP2Pstore", "indexName", indexName, "prefix", prefix,
  1616  						"primaryKey", primaryKey, "err", err, "hash", common.ToHex(blockheader.Hash))
  1617  				}
  1618  				return nil, types.ErrHashNotExist
  1619  			}
  1620  			blockbody = bodys.Items[0]
  1621  			return blockbody, nil
  1622  		}
  1623  
  1624  		if err != dbm.ErrNotFoundInDb {
  1625  			storeLog.Error("multiGetBody:getBodyByIndex", "indexName", indexName, "prefix", prefix, "primaryKey", primaryKey, "err", err)
  1626  		}
  1627  		return nil, types.ErrHashNotExist
  1628  	}
  1629  	return blockbody, nil
  1630  }
  1631  
  1632  func (bs *BlockStore) getBodyFromP2Pstore(hash []byte, start, end int64) (*types.BlockBodys, error) {
  1633  	stime := time.Now()
  1634  	defer func() {
  1635  		etime := time.Now()
  1636  		storeLog.Info("getBodyFromP2Pstore", "start", start, "end", end, "cost time", etime.Sub(stime))
  1637  	}()
  1638  	//value, err := bs.db.Get(calcBlockHashToChunkHash(hash))
  1639  	//if value == nil || err != nil {
  1640  	//	if err != dbm.ErrNotFoundInDb {
  1641  	//		storeLog.Error("getBodyFromP2Pstore:calcBlockHashToChunkHash", "hash", common.ToHex(hash), "chunkhash", common.ToHex(value), "err", err)
  1642  	//	}
  1643  	//	return nil, types.ErrHashNotExist
  1644  	//}
  1645  	cfg := bs.client.GetConfig()
  1646  	chainCfg := cfg.GetModuleConfig().BlockChain
  1647  	chunkNum := start / chainCfg.ChunkblockNum
  1648  	value, err := bs.db.Get(calcChunkNumToHash(chunkNum))
  1649  	if err != nil {
  1650  		return nil, types.ErrHashNotExist
  1651  	}
  1652  	var chunkInfo types.ChunkInfo
  1653  	if err := types.Decode(value, &chunkInfo); err != nil {
  1654  		return nil, types.ErrDecode
  1655  	}
  1656  
  1657  	if bs.client == nil {
  1658  		storeLog.Error("getBodyFromP2Pstore: chain client not bind message queue.")
  1659  		return nil, types.ErrClientNotBindQueue
  1660  	}
  1661  	req := &types.ChunkInfoMsg{
  1662  		ChunkHash: chunkInfo.ChunkHash,
  1663  		Start:     start,
  1664  		End:       end,
  1665  	}
  1666  	msg := bs.client.NewMessage("p2p", types.EventGetChunkBlockBody, req)
  1667  	err = bs.client.Send(msg, true)
  1668  	if err != nil {
  1669  		storeLog.Error("EventGetChunkBlockBody", "chunk hash", common.ToHex(value), "hash", common.ToHex(hash), "err", err)
  1670  		return nil, err
  1671  	}
  1672  	// 网络查询阻塞最长等待3分钟
  1673  	resp, err := bs.client.WaitTimeout(msg, time.Minute*3)
  1674  	if err != nil {
  1675  		storeLog.Error("EventGetChunkBlockBody", "client.Wait err:", err)
  1676  		return nil, err
  1677  	}
  1678  	bodys, ok := resp.Data.(*types.BlockBodys)
  1679  	if !ok {
  1680  		err = types.ErrNotFound
  1681  		storeLog.Error("EventGetChunkBlockBody", "client.Wait err:", err)
  1682  		return nil, err
  1683  	}
  1684  	return bodys, nil
  1685  }
  1686  
  1687  func (bs *BlockStore) getCurChunkNum(prefix []byte) int64 {
  1688  	it := bs.db.Iterator(prefix, nil, true)
  1689  	defer it.Close()
  1690  	height := int64(-1)
  1691  	var err error
  1692  	if it.Rewind() && it.Valid() {
  1693  		height, err = strconv.ParseInt(string(bytes.TrimPrefix(it.Key(), prefix)), 10, 64)
  1694  		if err != nil {
  1695  			return -1
  1696  		}
  1697  	}
  1698  	return height
  1699  }
  1700  
  1701  func (bs *BlockStore) getRecvChunkHash(chunkNum int64) ([]byte, error) {
  1702  	value, err := bs.GetKey(calcRecvChunkNumToHash(chunkNum))
  1703  	if err != nil {
  1704  		storeLog.Error("getRecvChunkHash", "chunkNum", chunkNum, "error", err)
  1705  		return nil, err
  1706  	}
  1707  	var chunk types.ChunkInfo
  1708  	err = types.Decode(value, &chunk)
  1709  	if err != nil {
  1710  		storeLog.Error("getRecvChunkHash", "chunkNum", chunkNum, "decode err:", err)
  1711  		return nil, err
  1712  	}
  1713  	return chunk.ChunkHash, err
  1714  }
  1715  
  1716  //GetMaxSerialChunkNum get max serial chunk num
  1717  func (bs *BlockStore) GetMaxSerialChunkNum() int64 {
  1718  	value, err := bs.db.Get(MaxSerialChunkNum)
  1719  	if err != nil {
  1720  		return -1
  1721  	}
  1722  	chunkNum := &types.Int64{}
  1723  	err = types.Decode(value, chunkNum)
  1724  	if err != nil {
  1725  		return -1
  1726  	}
  1727  	return chunkNum.Data
  1728  }
  1729  
  1730  //SetMaxSerialChunkNum set max serial chunk num
  1731  func (bs *BlockStore) SetMaxSerialChunkNum(chunkNum int64) error {
  1732  	data := &types.Int64{
  1733  		Data: chunkNum,
  1734  	}
  1735  	return bs.db.Set(MaxSerialChunkNum, types.Encode(data))
  1736  }
  1737  
  1738  // GetMaxDeletedChunkNum gets max chunkNum of deleted chunks.
  1739  func (bs *BlockStore) GetMaxDeletedChunkNum() int64 {
  1740  	value, err := bs.db.Get(MaxDeletedChunkNum)
  1741  	if err != nil {
  1742  		return -1
  1743  	}
  1744  	chunkNum := &types.Int64{}
  1745  	err = types.Decode(value, chunkNum)
  1746  	if err != nil {
  1747  		return -1
  1748  	}
  1749  	return chunkNum.Data
  1750  }
  1751  
  1752  // SetMaxDeletedChunkNum sets max chunkNum of deleted chunks.
  1753  func (bs *BlockStore) SetMaxDeletedChunkNum(chunkNum int64) error {
  1754  	data := &types.Int64{
  1755  		Data: chunkNum,
  1756  	}
  1757  	return bs.db.Set(MaxDeletedChunkNum, types.Encode(data))
  1758  }
  1759  
  1760  // GetActiveBlock :从缓存的活跃区块中获取对应高度的区块
  1761  func (bs *BlockStore) GetActiveBlock(hash string) (*types.BlockDetail, bool) {
  1762  	block := bs.activeBlocks.Get(hash)
  1763  	if block != nil {
  1764  		return block.(*types.BlockDetail), true
  1765  	}
  1766  	return nil, false
  1767  }
  1768  
  1769  // AddActiveBlock :将区块缓存到活跃区块中
  1770  func (bs *BlockStore) AddActiveBlock(hash string, block *types.BlockDetail) bool {
  1771  	return bs.activeBlocks.Add(hash, block, block.Size())
  1772  }
  1773  
  1774  // RemoveActiveBlock :从缓存的活跃区块中删除对应的区块
  1775  func (bs *BlockStore) RemoveActiveBlock(hash string) bool {
  1776  	_, ok := bs.activeBlocks.Remove(hash)
  1777  	return ok
  1778  }