github.com/adnan-c/fabric_e2e_couchdb@v0.6.1-preview.0.20170228180935-21ce6b23cf91/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 return header, nil 164 } 165 166 func extractData(buf *ledgerutil.Buffer) (*common.BlockData, []*txindexInfo, error) { 167 data := &common.BlockData{} 168 var txOffsets []*txindexInfo 169 var numItems uint64 170 var err error 171 172 if numItems, err = buf.DecodeVarint(); err != nil { 173 return nil, nil, err 174 } 175 for i := uint64(0); i < numItems; i++ { 176 var txEnvBytes []byte 177 var txid string 178 txOffset := buf.GetBytesConsumed() 179 if txEnvBytes, err = buf.DecodeRawBytes(false); err != nil { 180 return nil, nil, err 181 } 182 if txid, err = extractTxID(txEnvBytes); err != nil { 183 return nil, nil, err 184 } 185 data.Data = append(data.Data, txEnvBytes) 186 idxInfo := &txindexInfo{txid, &locPointer{txOffset, buf.GetBytesConsumed() - txOffset}} 187 txOffsets = append(txOffsets, idxInfo) 188 } 189 return data, txOffsets, nil 190 } 191 192 func extractMetadata(buf *ledgerutil.Buffer) (*common.BlockMetadata, error) { 193 metadata := &common.BlockMetadata{} 194 var numItems uint64 195 var metadataEntry []byte 196 var err error 197 if numItems, err = buf.DecodeVarint(); err != nil { 198 return nil, err 199 } 200 for i := uint64(0); i < numItems; i++ { 201 if metadataEntry, err = buf.DecodeRawBytes(false); err != nil { 202 return nil, err 203 } 204 metadata.Metadata = append(metadata.Metadata, metadataEntry) 205 } 206 return metadata, nil 207 } 208 209 func extractTxID(txEnvelopBytes []byte) (string, error) { 210 txEnvelope, err := utils.GetEnvelopeFromBlock(txEnvelopBytes) 211 if err != nil { 212 return "", err 213 } 214 txPayload, err := utils.GetPayload(txEnvelope) 215 if err != nil { 216 return "", nil 217 } 218 chdr, err := utils.UnmarshalChannelHeader(txPayload.Header.ChannelHeader) 219 if err != nil { 220 return "", err 221 } 222 return chdr.TxId, nil 223 }