OSDN Git Service

edit dup sup link struct (#1988)
[bytom/bytom.git] / database / store.go
index 1a4594b..70b6fed 100644 (file)
@@ -2,7 +2,6 @@ package database
 
 import (
        "encoding/binary"
-       "encoding/hex"
        "encoding/json"
        "time"
 
@@ -64,7 +63,11 @@ func NewStore(db dbm.DB) *Store {
                return GetBlockHashesByHeight(db, height)
        }
 
-       cache := newCache(fillBlockHeaderFn, fillBlockTxsFn, fillBlockHashesFn)
+       fillMainChainHashFn := func(height uint64) (*bc.Hash, error) {
+               return GetMainChainHash(db, height)
+       }
+
+       cache := newCache(fillBlockHeaderFn, fillBlockTxsFn, fillBlockHashesFn, fillMainChainHashFn)
        return &Store{
                db:    db,
                cache: cache,
@@ -109,6 +112,11 @@ func (s *Store) GetBlockHashesByHeight(height uint64) ([]*bc.Hash, error) {
        return s.cache.lookupBlockHashesByHeight(height)
 }
 
+// GetMainChainHash return the block hash by the specified height
+func (s *Store) GetMainChainHash(height uint64) (*bc.Hash, error) {
+       return s.cache.lookupMainChainHash(height)
+}
+
 // SaveBlock persists a new block in the protocol.
 func (s *Store) SaveBlock(block *types.Block) error {
        startTime := time.Now()
@@ -186,52 +194,8 @@ func (s *Store) GetStoreStatus() *protocol.BlockStoreState {
        return loadBlockStoreStateJSON(s.db)
 }
 
-// LoadBlockIndex loadblockIndex by bestHeight
-func (s *Store) LoadBlockIndex(stateBestHeight uint64) (*state.BlockIndex, error) {
-       startTime := time.Now()
-       blockIndex := state.NewBlockIndex()
-       bhIter := s.db.IteratorPrefix(BlockHeaderIndexPrefix)
-       defer bhIter.Release()
-
-       var lastNode *state.BlockNode
-       for bhIter.Next() {
-               bh := &types.BlockHeader{}
-               if err := bh.UnmarshalText(bhIter.Value()); err != nil {
-                       return nil, err
-               }
-
-               // If a block with a height greater than the best height of state is added to the index,
-               // It may cause a bug that the new block cant not be process properly.
-               if bh.Height > stateBestHeight {
-                       break
-               }
-
-               var parent *state.BlockNode
-               if lastNode == nil || lastNode.Hash == bh.PreviousBlockHash {
-                       parent = lastNode
-               } else {
-                       parent = blockIndex.GetNode(&bh.PreviousBlockHash)
-               }
-
-               node, err := state.NewBlockNode(bh, parent)
-               if err != nil {
-                       return nil, err
-               }
-
-               blockIndex.AddNode(node)
-               lastNode = node
-       }
-
-       log.WithFields(log.Fields{
-               "module":   logModule,
-               "height":   stateBestHeight,
-               "duration": time.Since(startTime),
-       }).Debug("initialize load history block index from database")
-       return blockIndex, nil
-}
-
 // SaveChainStatus save the core's newest status && delete old status
-func (s *Store) SaveChainStatus(node *state.BlockNode, view *state.UtxoViewpoint, contractView *state.ContractViewpoint, finalizedHeight uint64, finalizedHash *bc.Hash) error {
+func (s *Store) SaveChainStatus(blockHeader *types.BlockHeader, mainBlockHeaders []*types.BlockHeader, view *state.UtxoViewpoint, contractView *state.ContractViewpoint, finalizedHeight uint64, finalizedHash *bc.Hash) error {
        batch := s.db.NewBatch()
        if err := saveUtxoView(batch, view); err != nil {
                return err
@@ -245,13 +209,40 @@ func (s *Store) SaveChainStatus(node *state.BlockNode, view *state.UtxoViewpoint
                return err
        }
 
-       bytes, err := json.Marshal(protocol.BlockStoreState{Height: node.Height, Hash: &node.Hash, FinalizedHeight: finalizedHeight, FinalizedHash: finalizedHash})
+       blockHeaderHash := blockHeader.Hash()
+       bytes, err := json.Marshal(
+               protocol.BlockStoreState{
+                       Height:          blockHeader.Height,
+                       Hash:            &blockHeaderHash,
+                       FinalizedHeight: finalizedHeight,
+                       FinalizedHash:   finalizedHash,
+               })
        if err != nil {
                return err
        }
 
        batch.Set(BlockStoreKey, bytes)
+
+       var clearCacheFuncs []func()
+       // save main chain blockHeaders
+       for _, blockHeader := range mainBlockHeaders {
+               bh := blockHeader
+               blockHash := bh.Hash()
+               binaryBlockHash, err := blockHash.MarshalText()
+               if err != nil {
+                       return errors.Wrap(err, "Marshal block hash")
+               }
+
+               batch.Set(calcMainChainIndexPrefix(bh.Height), binaryBlockHash)
+               clearCacheFuncs = append(clearCacheFuncs, func() {
+                       s.cache.removeMainChainHash(bh.Height)
+               })
+       }
        batch.Write()
+       for _, clearCacheFunc := range clearCacheFuncs {
+               clearCacheFunc()
+       }
+
        return nil
 }
 
@@ -277,7 +268,7 @@ func (s *Store) GetCheckpoint(hash *bc.Hash) (*state.Checkpoint, error) {
                return nil, err
        }
 
-       setSupLinkToCheckpoint(checkpoint, header.SupLinks)
+       checkpoint.SupLinks = append(checkpoint.SupLinks, header.SupLinks...)
        return checkpoint, nil
 }
 
@@ -322,7 +313,7 @@ func (s *Store) loadCheckpointsFromIter(iter dbm.Iterator) ([]*state.Checkpoint,
                        return nil, err
                }
 
-               setSupLinkToCheckpoint(checkpoint, header.SupLinks)
+               checkpoint.SupLinks = append(checkpoint.SupLinks, header.SupLinks...)
                checkpoints = append(checkpoints, checkpoint)
        }
        return checkpoints, nil
@@ -348,7 +339,7 @@ func (s *Store) saveCheckpoints(batch dbm.Batch, checkpoints []*state.Checkpoint
                        return err
                }
 
-               if checkpoint.Height%state.BlocksOfEpoch != 1 {
+               if checkpoint.Height%consensus.ActiveNetParams.BlocksOfEpoch != 1 {
                        header, err := s.GetBlockHeader(&checkpoint.Hash)
                        if err != nil {
                                return err
@@ -359,27 +350,12 @@ func (s *Store) saveCheckpoints(batch dbm.Batch, checkpoints []*state.Checkpoint
 
                batch.Set(calcCheckpointKey(checkpoint.Height, &checkpoint.Hash), data)
                log.WithFields(log.Fields{
-                       "module": logModule,
-                       "height": checkpoint.Height,
-                       "hash":   checkpoint.Hash.String(),
-                       "status": checkpoint.Status,
+                       "module":   logModule,
+                       "height":   checkpoint.Height,
+                       "hash":     checkpoint.Hash.String(),
+                       "status":   checkpoint.Status,
                        "duration": time.Since(startTime),
                }).Info("checkpoint saved on disk")
        }
        return nil
 }
-
-func setSupLinkToCheckpoint(c *state.Checkpoint, supLinks types.SupLinks) {
-       for _, supLink := range supLinks {
-               var signatures [consensus.MaxNumOfValidators]string
-               for i, signature := range supLink.Signatures {
-                       signatures[i] = hex.EncodeToString(signature)
-               }
-
-               c.SupLinks = append(c.SupLinks, &state.SupLink{
-                       SourceHeight: supLink.SourceHeight,
-                       SourceHash:   supLink.SourceHash,
-                       Signatures:   signatures,
-               })
-       }
-}