github.com/lzy4123/fabric@v2.1.1+incompatible/common/ledger/blkstorage/fsblkstorage/block_serialization.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package fsblkstorage 8 9 import ( 10 "github.com/golang/protobuf/proto" 11 "github.com/hyperledger/fabric-protos-go/common" 12 "github.com/hyperledger/fabric/protoutil" 13 "github.com/pkg/errors" 14 ) 15 16 type serializedBlockInfo struct { 17 blockHeader *common.BlockHeader 18 txOffsets []*txindexInfo 19 metadata *common.BlockMetadata 20 } 21 22 //The order of the transactions must be maintained for history 23 type txindexInfo struct { 24 txID string 25 loc *locPointer 26 } 27 28 func serializeBlock(block *common.Block) ([]byte, *serializedBlockInfo, error) { 29 buf := proto.NewBuffer(nil) 30 var err error 31 info := &serializedBlockInfo{} 32 info.blockHeader = block.Header 33 info.metadata = block.Metadata 34 if err = addHeaderBytes(block.Header, buf); err != nil { 35 return nil, nil, err 36 } 37 if info.txOffsets, err = addDataBytesAndConstructTxIndexInfo(block.Data, buf); err != nil { 38 return nil, nil, err 39 } 40 if err = addMetadataBytes(block.Metadata, buf); err != nil { 41 return nil, nil, err 42 } 43 return buf.Bytes(), info, nil 44 } 45 46 func deserializeBlock(serializedBlockBytes []byte) (*common.Block, error) { 47 block := &common.Block{} 48 var err error 49 b := newBuffer(serializedBlockBytes) 50 if block.Header, err = extractHeader(b); err != nil { 51 return nil, err 52 } 53 if block.Data, _, err = extractData(b); err != nil { 54 return nil, err 55 } 56 if block.Metadata, err = extractMetadata(b); err != nil { 57 return nil, err 58 } 59 return block, nil 60 } 61 62 func extractSerializedBlockInfo(serializedBlockBytes []byte) (*serializedBlockInfo, error) { 63 info := &serializedBlockInfo{} 64 var err error 65 b := newBuffer(serializedBlockBytes) 66 info.blockHeader, err = extractHeader(b) 67 if err != nil { 68 return nil, err 69 } 70 _, info.txOffsets, err = extractData(b) 71 if err != nil { 72 return nil, err 73 } 74 75 info.metadata, err = extractMetadata(b) 76 if err != nil { 77 return nil, err 78 } 79 return info, nil 80 } 81 82 func addHeaderBytes(blockHeader *common.BlockHeader, buf *proto.Buffer) error { 83 if err := buf.EncodeVarint(blockHeader.Number); err != nil { 84 return errors.Wrapf(err, "error encoding the block number [%d]", blockHeader.Number) 85 } 86 if err := buf.EncodeRawBytes(blockHeader.DataHash); err != nil { 87 return errors.Wrapf(err, "error encoding the data hash [%v]", blockHeader.DataHash) 88 } 89 if err := buf.EncodeRawBytes(blockHeader.PreviousHash); err != nil { 90 return errors.Wrapf(err, "error encoding the previous hash [%v]", blockHeader.PreviousHash) 91 } 92 return nil 93 } 94 95 func addDataBytesAndConstructTxIndexInfo(blockData *common.BlockData, buf *proto.Buffer) ([]*txindexInfo, error) { 96 var txOffsets []*txindexInfo 97 98 if err := buf.EncodeVarint(uint64(len(blockData.Data))); err != nil { 99 return nil, errors.Wrap(err, "error encoding the length of block data") 100 } 101 for _, txEnvelopeBytes := range blockData.Data { 102 offset := len(buf.Bytes()) 103 txid, err := protoutil.GetOrComputeTxIDFromEnvelope(txEnvelopeBytes) 104 if err != nil { 105 logger.Warningf("error while extracting txid from tx envelope bytes during serialization of block. Ignoring this error as this is caused by a malformed transaction. Error:%s", 106 err) 107 } 108 if err := buf.EncodeRawBytes(txEnvelopeBytes); err != nil { 109 return nil, errors.Wrap(err, "error encoding the transaction envelope") 110 } 111 idxInfo := &txindexInfo{txID: txid, loc: &locPointer{offset, len(buf.Bytes()) - offset}} 112 txOffsets = append(txOffsets, idxInfo) 113 } 114 return txOffsets, nil 115 } 116 117 func addMetadataBytes(blockMetadata *common.BlockMetadata, buf *proto.Buffer) error { 118 numItems := uint64(0) 119 if blockMetadata != nil { 120 numItems = uint64(len(blockMetadata.Metadata)) 121 } 122 if err := buf.EncodeVarint(numItems); err != nil { 123 return errors.Wrap(err, "error encoding the length of metadata") 124 } 125 for _, b := range blockMetadata.Metadata { 126 if err := buf.EncodeRawBytes(b); err != nil { 127 return errors.Wrap(err, "error encoding the block metadata") 128 } 129 } 130 return nil 131 } 132 133 func extractHeader(buf *buffer) (*common.BlockHeader, error) { 134 header := &common.BlockHeader{} 135 var err error 136 if header.Number, err = buf.DecodeVarint(); err != nil { 137 return nil, errors.Wrap(err, "error decoding the block number") 138 } 139 if header.DataHash, err = buf.DecodeRawBytes(false); err != nil { 140 return nil, errors.Wrap(err, "error decoding the data hash") 141 } 142 if header.PreviousHash, err = buf.DecodeRawBytes(false); err != nil { 143 return nil, errors.Wrap(err, "error decoding the previous hash") 144 } 145 if len(header.PreviousHash) == 0 { 146 header.PreviousHash = nil 147 } 148 return header, nil 149 } 150 151 func extractData(buf *buffer) (*common.BlockData, []*txindexInfo, error) { 152 data := &common.BlockData{} 153 var txOffsets []*txindexInfo 154 var numItems uint64 155 var err error 156 157 if numItems, err = buf.DecodeVarint(); err != nil { 158 return nil, nil, errors.Wrap(err, "error decoding the length of block data") 159 } 160 for i := uint64(0); i < numItems; i++ { 161 var txEnvBytes []byte 162 var txid string 163 txOffset := buf.GetBytesConsumed() 164 if txEnvBytes, err = buf.DecodeRawBytes(false); err != nil { 165 return nil, nil, errors.Wrap(err, "error decoding the transaction enevelope") 166 } 167 if txid, err = protoutil.GetOrComputeTxIDFromEnvelope(txEnvBytes); err != nil { 168 logger.Warningf("error while extracting txid from tx envelope bytes during deserialization of block. Ignoring this error as this is caused by a malformed transaction. Error:%s", 169 err) 170 171 } 172 data.Data = append(data.Data, txEnvBytes) 173 idxInfo := &txindexInfo{txID: txid, loc: &locPointer{txOffset, buf.GetBytesConsumed() - txOffset}} 174 txOffsets = append(txOffsets, idxInfo) 175 } 176 return data, txOffsets, nil 177 } 178 179 func extractMetadata(buf *buffer) (*common.BlockMetadata, error) { 180 metadata := &common.BlockMetadata{} 181 var numItems uint64 182 var metadataEntry []byte 183 var err error 184 if numItems, err = buf.DecodeVarint(); err != nil { 185 return nil, errors.Wrap(err, "error decoding the length of block metadata") 186 } 187 for i := uint64(0); i < numItems; i++ { 188 if metadataEntry, err = buf.DecodeRawBytes(false); err != nil { 189 return nil, errors.Wrap(err, "error decoding the block metadata") 190 } 191 metadata.Metadata = append(metadata.Metadata, metadataEntry) 192 } 193 return metadata, nil 194 }