github.com/kchristidis/fabric@v1.0.4-0.20171028114726-837acd08cde1/common/ledger/blkstorage/fsblkstorage/block_serialization.go (about) 1 /* 2 Copyright IBM Corp. 2016 All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package fsblkstorage 18 19 import ( 20 "github.com/golang/protobuf/proto" 21 ledgerutil "github.com/hyperledger/fabric/common/ledger/util" 22 "github.com/hyperledger/fabric/protos/common" 23 "github.com/hyperledger/fabric/protos/utils" 24 ) 25 26 type serializedBlockInfo struct { 27 blockHeader *common.BlockHeader 28 txOffsets []*txindexInfo 29 metadata *common.BlockMetadata 30 } 31 32 //The order of the transactions must be maintained for history 33 type txindexInfo struct { 34 txID string 35 loc *locPointer 36 } 37 38 func serializeBlock(block *common.Block) ([]byte, *serializedBlockInfo, error) { 39 buf := proto.NewBuffer(nil) 40 var err error 41 info := &serializedBlockInfo{} 42 info.blockHeader = block.Header 43 info.metadata = block.Metadata 44 if err = addHeaderBytes(block.Header, buf); err != nil { 45 return nil, nil, err 46 } 47 if info.txOffsets, err = addDataBytes(block.Data, buf); err != nil { 48 return nil, nil, err 49 } 50 if err = addMetadataBytes(block.Metadata, buf); err != nil { 51 return nil, nil, err 52 } 53 return buf.Bytes(), info, nil 54 } 55 56 func deserializeBlock(serializedBlockBytes []byte) (*common.Block, error) { 57 block := &common.Block{} 58 var err error 59 b := ledgerutil.NewBuffer(serializedBlockBytes) 60 if block.Header, err = extractHeader(b); err != nil { 61 return nil, err 62 } 63 if block.Data, _, err = extractData(b); err != nil { 64 return nil, err 65 } 66 if block.Metadata, err = extractMetadata(b); err != nil { 67 return nil, err 68 } 69 return block, nil 70 } 71 72 func extractSerializedBlockInfo(serializedBlockBytes []byte) (*serializedBlockInfo, error) { 73 info := &serializedBlockInfo{} 74 var err error 75 b := ledgerutil.NewBuffer(serializedBlockBytes) 76 info.blockHeader, err = extractHeader(b) 77 if err != nil { 78 return nil, err 79 } 80 _, info.txOffsets, err = extractData(b) 81 if err != nil { 82 return nil, err 83 } 84 85 info.metadata, err = extractMetadata(b) 86 if err != nil { 87 return nil, err 88 } 89 90 return info, nil 91 } 92 93 func addHeaderBytes(blockHeader *common.BlockHeader, buf *proto.Buffer) error { 94 if err := buf.EncodeVarint(blockHeader.Number); err != nil { 95 return err 96 } 97 if err := buf.EncodeRawBytes(blockHeader.DataHash); err != nil { 98 return err 99 } 100 if err := buf.EncodeRawBytes(blockHeader.PreviousHash); err != nil { 101 return err 102 } 103 return nil 104 } 105 106 func addDataBytes(blockData *common.BlockData, buf *proto.Buffer) ([]*txindexInfo, error) { 107 var txOffsets []*txindexInfo 108 109 if err := buf.EncodeVarint(uint64(len(blockData.Data))); err != nil { 110 return nil, err 111 } 112 for _, txEnvelopeBytes := range blockData.Data { 113 offset := len(buf.Bytes()) 114 txid, err := extractTxID(txEnvelopeBytes) 115 if err != nil { 116 return nil, err 117 } 118 if err := buf.EncodeRawBytes(txEnvelopeBytes); err != nil { 119 return nil, err 120 } 121 idxInfo := &txindexInfo{txid, &locPointer{offset, len(buf.Bytes()) - offset}} 122 txOffsets = append(txOffsets, idxInfo) 123 } 124 return txOffsets, nil 125 } 126 127 func addMetadataBytes(blockMetadata *common.BlockMetadata, buf *proto.Buffer) error { 128 numItems := uint64(0) 129 if blockMetadata != nil { 130 numItems = uint64(len(blockMetadata.Metadata)) 131 } 132 if err := buf.EncodeVarint(numItems); err != nil { 133 return err 134 } 135 for _, b := range blockMetadata.Metadata { 136 if err := buf.EncodeRawBytes(b); err != nil { 137 return err 138 } 139 } 140 return nil 141 } 142 143 func extractHeader(buf *ledgerutil.Buffer) (*common.BlockHeader, error) { 144 header := &common.BlockHeader{} 145 var err error 146 if header.Number, err = buf.DecodeVarint(); err != nil { 147 return nil, err 148 } 149 if header.DataHash, err = buf.DecodeRawBytes(false); err != nil { 150 return nil, err 151 } 152 if header.PreviousHash, err = buf.DecodeRawBytes(false); err != nil { 153 return nil, err 154 } 155 if len(header.PreviousHash) == 0 { 156 header.PreviousHash = nil 157 } 158 return header, nil 159 } 160 161 func extractData(buf *ledgerutil.Buffer) (*common.BlockData, []*txindexInfo, error) { 162 data := &common.BlockData{} 163 var txOffsets []*txindexInfo 164 var numItems uint64 165 var err error 166 167 if numItems, err = buf.DecodeVarint(); err != nil { 168 return nil, nil, err 169 } 170 for i := uint64(0); i < numItems; i++ { 171 var txEnvBytes []byte 172 var txid string 173 txOffset := buf.GetBytesConsumed() 174 if txEnvBytes, err = buf.DecodeRawBytes(false); err != nil { 175 return nil, nil, err 176 } 177 if txid, err = extractTxID(txEnvBytes); err != nil { 178 return nil, nil, err 179 } 180 data.Data = append(data.Data, txEnvBytes) 181 idxInfo := &txindexInfo{txid, &locPointer{txOffset, buf.GetBytesConsumed() - txOffset}} 182 txOffsets = append(txOffsets, idxInfo) 183 } 184 return data, txOffsets, nil 185 } 186 187 func extractMetadata(buf *ledgerutil.Buffer) (*common.BlockMetadata, error) { 188 metadata := &common.BlockMetadata{} 189 var numItems uint64 190 var metadataEntry []byte 191 var err error 192 if numItems, err = buf.DecodeVarint(); err != nil { 193 return nil, err 194 } 195 for i := uint64(0); i < numItems; i++ { 196 if metadataEntry, err = buf.DecodeRawBytes(false); err != nil { 197 return nil, err 198 } 199 metadata.Metadata = append(metadata.Metadata, metadataEntry) 200 } 201 return metadata, nil 202 } 203 204 func extractTxID(txEnvelopBytes []byte) (string, error) { 205 txEnvelope, err := utils.GetEnvelopeFromBlock(txEnvelopBytes) 206 if err != nil { 207 return "", err 208 } 209 txPayload, err := utils.GetPayload(txEnvelope) 210 if err != nil { 211 return "", nil 212 } 213 chdr, err := utils.UnmarshalChannelHeader(txPayload.Header.ChannelHeader) 214 if err != nil { 215 return "", err 216 } 217 return chdr.TxId, nil 218 }