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 }