github.com/leonlxy/hyperledger@v1.0.0-alpha.0.20170427033203-34922035d248/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 "fmt" 21 22 "github.com/golang/protobuf/proto" 23 ledgerutil "github.com/hyperledger/fabric/common/ledger/util" 24 "github.com/hyperledger/fabric/protos/common" 25 "github.com/hyperledger/fabric/protos/utils" 26 ) 27 28 type serializedBlockInfo struct { 29 blockHeader *common.BlockHeader 30 txOffsets []*txindexInfo 31 metadata *common.BlockMetadata 32 } 33 34 //The order of the transactions must be maintained for history 35 type txindexInfo struct { 36 txID string 37 loc *locPointer 38 } 39 40 func serializeBlock(block *common.Block) ([]byte, *serializedBlockInfo, error) { 41 buf := proto.NewBuffer(nil) 42 var err error 43 info := &serializedBlockInfo{} 44 info.blockHeader = block.Header 45 info.metadata = block.Metadata 46 if err = addHeaderBytes(block.Header, buf); err != nil { 47 return nil, nil, err 48 } 49 if info.txOffsets, err = addDataBytes(block.Data, buf); err != nil { 50 return nil, nil, err 51 } 52 if err = addMetadataBytes(block.Metadata, buf); err != nil { 53 return nil, nil, err 54 } 55 return buf.Bytes(), info, nil 56 } 57 58 func deserializeBlock(serializedBlockBytes []byte) (*common.Block, error) { 59 block := &common.Block{} 60 var err error 61 b := ledgerutil.NewBuffer(serializedBlockBytes) 62 if block.Header, err = extractHeader(b); err != nil { 63 fmt.Printf("h:%s\n", err) 64 return nil, err 65 } 66 if block.Data, _, err = extractData(b); err != nil { 67 fmt.Printf("d:%s\n", err) 68 return nil, err 69 } 70 if block.Metadata, err = extractMetadata(b); err != nil { 71 fmt.Printf("m:%s\n", err) 72 return nil, err 73 } 74 return block, nil 75 } 76 77 func extractSerializedBlockInfo(serializedBlockBytes []byte) (*serializedBlockInfo, error) { 78 info := &serializedBlockInfo{} 79 var err error 80 b := ledgerutil.NewBuffer(serializedBlockBytes) 81 info.blockHeader, err = extractHeader(b) 82 if err != nil { 83 return nil, err 84 } 85 _, info.txOffsets, err = extractData(b) 86 if err != nil { 87 return nil, err 88 } 89 90 info.metadata, err = extractMetadata(b) 91 if err != nil { 92 return nil, err 93 } 94 95 return info, nil 96 } 97 98 func addHeaderBytes(blockHeader *common.BlockHeader, buf *proto.Buffer) error { 99 if err := buf.EncodeVarint(blockHeader.Number); err != nil { 100 return err 101 } 102 if err := buf.EncodeRawBytes(blockHeader.DataHash); err != nil { 103 return err 104 } 105 if err := buf.EncodeRawBytes(blockHeader.PreviousHash); err != nil { 106 return err 107 } 108 return nil 109 } 110 111 func addDataBytes(blockData *common.BlockData, buf *proto.Buffer) ([]*txindexInfo, error) { 112 var txOffsets []*txindexInfo 113 114 if err := buf.EncodeVarint(uint64(len(blockData.Data))); err != nil { 115 return nil, err 116 } 117 for _, txEnvelopeBytes := range blockData.Data { 118 offset := len(buf.Bytes()) 119 txid, err := extractTxID(txEnvelopeBytes) 120 if err != nil { 121 return nil, err 122 } 123 if err := buf.EncodeRawBytes(txEnvelopeBytes); err != nil { 124 return nil, err 125 } 126 idxInfo := &txindexInfo{txid, &locPointer{offset, len(buf.Bytes()) - offset}} 127 txOffsets = append(txOffsets, idxInfo) 128 } 129 return txOffsets, nil 130 } 131 132 func addMetadataBytes(blockMetadata *common.BlockMetadata, buf *proto.Buffer) error { 133 numItems := uint64(0) 134 if blockMetadata != nil { 135 numItems = uint64(len(blockMetadata.Metadata)) 136 } 137 if err := buf.EncodeVarint(numItems); err != nil { 138 return err 139 } 140 if numItems == 0 { 141 return nil 142 } 143 for _, b := range blockMetadata.Metadata { 144 if err := buf.EncodeRawBytes(b); err != nil { 145 return err 146 } 147 } 148 return nil 149 } 150 151 func extractHeader(buf *ledgerutil.Buffer) (*common.BlockHeader, error) { 152 header := &common.BlockHeader{} 153 var err error 154 if header.Number, err = buf.DecodeVarint(); err != nil { 155 return nil, err 156 } 157 if header.DataHash, err = buf.DecodeRawBytes(false); err != nil { 158 return nil, err 159 } 160 if header.PreviousHash, err = buf.DecodeRawBytes(false); err != nil { 161 return nil, err 162 } 163 if len(header.PreviousHash) == 0 { 164 header.PreviousHash = nil 165 } 166 return header, nil 167 } 168 169 func extractData(buf *ledgerutil.Buffer) (*common.BlockData, []*txindexInfo, error) { 170 data := &common.BlockData{} 171 var txOffsets []*txindexInfo 172 var numItems uint64 173 var err error 174 175 if numItems, err = buf.DecodeVarint(); err != nil { 176 return nil, nil, err 177 } 178 for i := uint64(0); i < numItems; i++ { 179 var txEnvBytes []byte 180 var txid string 181 txOffset := buf.GetBytesConsumed() 182 if txEnvBytes, err = buf.DecodeRawBytes(false); err != nil { 183 return nil, nil, err 184 } 185 if txid, err = extractTxID(txEnvBytes); err != nil { 186 return nil, nil, err 187 } 188 data.Data = append(data.Data, txEnvBytes) 189 idxInfo := &txindexInfo{txid, &locPointer{txOffset, buf.GetBytesConsumed() - txOffset}} 190 txOffsets = append(txOffsets, idxInfo) 191 } 192 return data, txOffsets, nil 193 } 194 195 func extractMetadata(buf *ledgerutil.Buffer) (*common.BlockMetadata, error) { 196 metadata := &common.BlockMetadata{} 197 var numItems uint64 198 var metadataEntry []byte 199 var err error 200 if numItems, err = buf.DecodeVarint(); err != nil { 201 return nil, err 202 } 203 for i := uint64(0); i < numItems; i++ { 204 if metadataEntry, err = buf.DecodeRawBytes(false); err != nil { 205 return nil, err 206 } 207 metadata.Metadata = append(metadata.Metadata, metadataEntry) 208 } 209 return metadata, nil 210 } 211 212 func extractTxID(txEnvelopBytes []byte) (string, error) { 213 txEnvelope, err := utils.GetEnvelopeFromBlock(txEnvelopBytes) 214 if err != nil { 215 return "", err 216 } 217 txPayload, err := utils.GetPayload(txEnvelope) 218 if err != nil { 219 return "", nil 220 } 221 chdr, err := utils.UnmarshalChannelHeader(txPayload.Header.ChannelHeader) 222 if err != nil { 223 return "", err 224 } 225 return chdr.TxId, nil 226 }