github.com/iotexproject/iotex-core@v1.14.1-rc1/blockchain/filedao/filedao_header.go (about)

     1  // Copyright (c) 2020 IoTeX Foundation
     2  // This source code is provided 'as is' and no warranties are given as to title or non-infringement, merchantability
     3  // or fitness for purpose and, to the extent permitted by law, all liability for your use of the code is disclaimed.
     4  // This source code is governed by Apache License 2.0 that can be found in the LICENSE file.
     5  
     6  package filedao
     7  
     8  import (
     9  	"github.com/pkg/errors"
    10  	"google.golang.org/protobuf/proto"
    11  
    12  	"github.com/iotexproject/go-pkgs/hash"
    13  
    14  	"github.com/iotexproject/iotex-core/blockchain/filedao/headerpb"
    15  	"github.com/iotexproject/iotex-core/db"
    16  )
    17  
    18  // constants
    19  const (
    20  	FileLegacyMaster    = "V1-master"
    21  	FileLegacyAuxiliary = "V1-aux"
    22  	FileV2              = "V2"
    23  	FileAll             = "All"
    24  )
    25  
    26  type (
    27  	// FileHeader is header of chain db file
    28  	FileHeader struct {
    29  		Version        string
    30  		Compressor     string
    31  		BlockStoreSize uint64
    32  		Start          uint64
    33  	}
    34  
    35  	// FileTip is tip info of chain
    36  	FileTip struct {
    37  		Height uint64
    38  		Hash   hash.Hash256
    39  	}
    40  )
    41  
    42  // ReadHeaderLegacy reads header from KVStore
    43  func ReadHeaderLegacy(kv *db.BoltDB) (*FileHeader, error) {
    44  	// legacy file has these 6 buckets
    45  	if !kv.BucketExists(_receiptsNS) || !kv.BucketExists(_blockHeaderNS) ||
    46  		!kv.BucketExists(_blockBodyNS) || !kv.BucketExists(_blockFooterNS) {
    47  		return nil, ErrFileInvalid
    48  	}
    49  
    50  	// check tip height stored in master file
    51  	_, err := getValueMustBe8Bytes(kv, _blockNS, _topHeightKey)
    52  	if err == nil && kv.BucketExists(_blockHashHeightMappingNS) {
    53  		return &FileHeader{Version: FileLegacyMaster}, nil
    54  	}
    55  	return &FileHeader{Version: FileLegacyAuxiliary}, nil
    56  }
    57  
    58  // ReadHeaderV2 reads header from KVStore
    59  func ReadHeaderV2(kv db.KVStore) (*FileHeader, error) {
    60  	value, err := kv.Get(_headerDataNs, _fileHeaderKey)
    61  	if err != nil {
    62  		return nil, errors.Wrap(err, "file header not exist")
    63  	}
    64  	return DeserializeFileHeader(value)
    65  }
    66  
    67  // WriteHeaderV2 writes header to KVStore
    68  func WriteHeaderV2(kv db.KVStore, header *FileHeader) error {
    69  	ser, err := header.Serialize()
    70  	if err != nil {
    71  		return err
    72  	}
    73  	return kv.Put(_headerDataNs, _fileHeaderKey, ser)
    74  }
    75  
    76  // Serialize serializes FileHeader to byte-stream
    77  func (h *FileHeader) Serialize() ([]byte, error) {
    78  	return proto.Marshal(h.toProto())
    79  }
    80  
    81  func (h *FileHeader) toProto() *headerpb.FileHeader {
    82  	return &headerpb.FileHeader{
    83  		Version:        h.Version,
    84  		Compressor:     h.Compressor,
    85  		BlockStoreSize: h.BlockStoreSize,
    86  		Start:          h.Start,
    87  	}
    88  }
    89  
    90  func fromProtoFileHeader(pb *headerpb.FileHeader) *FileHeader {
    91  	return &FileHeader{
    92  		Version:        pb.Version,
    93  		Compressor:     pb.Compressor,
    94  		BlockStoreSize: pb.BlockStoreSize,
    95  		Start:          pb.Start,
    96  	}
    97  }
    98  
    99  // DeserializeFileHeader deserializes byte-stream to FileHeader
   100  func DeserializeFileHeader(buf []byte) (*FileHeader, error) {
   101  	pbHeader := &headerpb.FileHeader{}
   102  	if err := proto.Unmarshal(buf, pbHeader); err != nil {
   103  		return nil, err
   104  	}
   105  	return fromProtoFileHeader(pbHeader), nil
   106  }
   107  
   108  // ReadTip reads tip from KVStore
   109  func ReadTip(kv db.KVStore, ns string, key []byte) (*FileTip, error) {
   110  	value, err := kv.Get(ns, key)
   111  	if err != nil {
   112  		return nil, errors.Wrap(err, "file header not exist")
   113  	}
   114  	return DeserializeFileTip(value)
   115  }
   116  
   117  // WriteTip writes tip to KVStore
   118  func WriteTip(kv db.KVStore, ns string, key []byte, tip *FileTip) error {
   119  	ser, err := tip.Serialize()
   120  	if err != nil {
   121  		return err
   122  	}
   123  	return kv.Put(ns, key, ser)
   124  }
   125  
   126  // Serialize serializes FileTip to byte-stream
   127  func (t *FileTip) Serialize() ([]byte, error) {
   128  	return proto.Marshal(t.toProto())
   129  }
   130  
   131  func (t *FileTip) toProto() *headerpb.FileTip {
   132  	return &headerpb.FileTip{
   133  		Height: t.Height,
   134  		Hash:   t.Hash[:],
   135  	}
   136  }
   137  
   138  func fromProtoFileTip(pb *headerpb.FileTip) *FileTip {
   139  	return &FileTip{
   140  		Height: pb.Height,
   141  		Hash:   hash.BytesToHash256(pb.Hash),
   142  	}
   143  }
   144  
   145  // DeserializeFileTip deserializes byte-stream to FileTip
   146  func DeserializeFileTip(buf []byte) (*FileTip, error) {
   147  	pbTip := &headerpb.FileTip{}
   148  	if err := proto.Unmarshal(buf, pbTip); err != nil {
   149  		return nil, err
   150  	}
   151  	return fromProtoFileTip(pbTip), nil
   152  }