github.com/inklabsfoundation/inkchain@v0.17.1-0.20181025012015-c3cef8062f19/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/inklabsfoundation/inkchain/common/ledger/util" 22 "github.com/inklabsfoundation/inkchain/protos/common" 23 "github.com/inklabsfoundation/inkchain/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.EncodeVarint(blockHeader.Version); err != nil { 98 return err 99 } 100 if err := buf.EncodeRawBytes(blockHeader.DataHash); err != nil { 101 return err 102 } 103 if err := buf.EncodeRawBytes(blockHeader.PreviousHash); err != nil { 104 return err 105 } 106 if err := buf.EncodeRawBytes(blockHeader.FeeAddress); err != nil { 107 return err 108 } 109 return nil 110 } 111 112 func addDataBytes(blockData *common.BlockData, buf *proto.Buffer) ([]*txindexInfo, error) { 113 var txOffsets []*txindexInfo 114 115 if err := buf.EncodeVarint(uint64(len(blockData.Data))); err != nil { 116 return nil, err 117 } 118 for _, txEnvelopeBytes := range blockData.Data { 119 offset := len(buf.Bytes()) 120 txid, err := extractTxID(txEnvelopeBytes) 121 if err != nil { 122 return nil, err 123 } 124 if err := buf.EncodeRawBytes(txEnvelopeBytes); err != nil { 125 return nil, err 126 } 127 idxInfo := &txindexInfo{txid, &locPointer{offset, len(buf.Bytes()) - offset}} 128 txOffsets = append(txOffsets, idxInfo) 129 } 130 return txOffsets, nil 131 } 132 133 func addMetadataBytes(blockMetadata *common.BlockMetadata, buf *proto.Buffer) error { 134 numItems := uint64(0) 135 if blockMetadata != nil { 136 numItems = uint64(len(blockMetadata.Metadata)) 137 } 138 if err := buf.EncodeVarint(numItems); err != nil { 139 return err 140 } 141 for _, b := range blockMetadata.Metadata { 142 if err := buf.EncodeRawBytes(b); err != nil { 143 return err 144 } 145 } 146 return nil 147 } 148 149 func extractHeader(buf *ledgerutil.Buffer) (*common.BlockHeader, error) { 150 header := &common.BlockHeader{} 151 var err error 152 if header.Number, err = buf.DecodeVarint(); err != nil { 153 return nil, err 154 } 155 if header.Version, err = buf.DecodeVarint(); err != nil { 156 return nil, err 157 } 158 if header.DataHash, err = buf.DecodeRawBytes(false); err != nil { 159 return nil, err 160 } 161 if header.PreviousHash, err = buf.DecodeRawBytes(false); err != nil { 162 return nil, err 163 } 164 if len(header.PreviousHash) == 0 { 165 header.PreviousHash = nil 166 } 167 if header.FeeAddress, err = buf.DecodeRawBytes(false); err != nil { 168 return nil, err 169 } 170 return header, nil 171 } 172 173 func extractData(buf *ledgerutil.Buffer) (*common.BlockData, []*txindexInfo, error) { 174 data := &common.BlockData{} 175 var txOffsets []*txindexInfo 176 var numItems uint64 177 var err error 178 179 if numItems, err = buf.DecodeVarint(); err != nil { 180 return nil, nil, err 181 } 182 for i := uint64(0); i < numItems; i++ { 183 var txEnvBytes []byte 184 var txid string 185 txOffset := buf.GetBytesConsumed() 186 if txEnvBytes, err = buf.DecodeRawBytes(false); err != nil { 187 return nil, nil, err 188 } 189 if txid, err = extractTxID(txEnvBytes); err != nil { 190 return nil, nil, err 191 } 192 data.Data = append(data.Data, txEnvBytes) 193 idxInfo := &txindexInfo{txid, &locPointer{txOffset, buf.GetBytesConsumed() - txOffset}} 194 txOffsets = append(txOffsets, idxInfo) 195 } 196 return data, txOffsets, nil 197 } 198 199 func extractMetadata(buf *ledgerutil.Buffer) (*common.BlockMetadata, error) { 200 metadata := &common.BlockMetadata{} 201 var numItems uint64 202 var metadataEntry []byte 203 var err error 204 if numItems, err = buf.DecodeVarint(); err != nil { 205 return nil, err 206 } 207 for i := uint64(0); i < numItems; i++ { 208 if metadataEntry, err = buf.DecodeRawBytes(false); err != nil { 209 return nil, err 210 } 211 metadata.Metadata = append(metadata.Metadata, metadataEntry) 212 } 213 return metadata, nil 214 } 215 216 func extractTxID(txEnvelopBytes []byte) (string, error) { 217 txEnvelope, err := utils.GetEnvelopeFromBlock(txEnvelopBytes) 218 if err != nil { 219 return "", err 220 } 221 txPayload, err := utils.GetPayload(txEnvelope) 222 if err != nil { 223 return "", nil 224 } 225 chdr, err := utils.UnmarshalChannelHeader(txPayload.Header.ChannelHeader) 226 if err != nil { 227 return "", err 228 } 229 return chdr.TxId, nil 230 }