github.com/kaituanwang/hyperledger@v2.0.1+incompatible/core/ledger/pvtdatastorage/kv_encoding.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package pvtdatastorage 8 9 import ( 10 "bytes" 11 "math" 12 13 "github.com/golang/protobuf/proto" 14 "github.com/hyperledger/fabric-protos-go/ledger/rwset" 15 "github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/version" 16 "github.com/hyperledger/fabric/core/ledger/util" 17 "github.com/pkg/errors" 18 "github.com/willf/bitset" 19 ) 20 21 var ( 22 pendingCommitKey = []byte{0} 23 lastCommittedBlkkey = []byte{1} 24 pvtDataKeyPrefix = []byte{2} 25 expiryKeyPrefix = []byte{3} 26 eligibleMissingDataKeyPrefix = []byte{4} 27 ineligibleMissingDataKeyPrefix = []byte{5} 28 collElgKeyPrefix = []byte{6} 29 lastUpdatedOldBlocksKey = []byte{7} 30 31 nilByte = byte(0) 32 emptyValue = []byte{} 33 ) 34 35 func getDataKeysForRangeScanByBlockNum(blockNum uint64) (startKey, endKey []byte) { 36 startKey = append(pvtDataKeyPrefix, version.NewHeight(blockNum, 0).ToBytes()...) 37 endKey = append(pvtDataKeyPrefix, version.NewHeight(blockNum+1, 0).ToBytes()...) 38 return 39 } 40 41 func getExpiryKeysForRangeScan(minBlkNum, maxBlkNum uint64) (startKey, endKey []byte) { 42 startKey = append(expiryKeyPrefix, version.NewHeight(minBlkNum, 0).ToBytes()...) 43 endKey = append(expiryKeyPrefix, version.NewHeight(maxBlkNum+1, 0).ToBytes()...) 44 return 45 } 46 47 func encodeLastCommittedBlockVal(blockNum uint64) []byte { 48 return proto.EncodeVarint(blockNum) 49 } 50 51 func decodeLastCommittedBlockVal(blockNumBytes []byte) uint64 { 52 s, _ := proto.DecodeVarint(blockNumBytes) 53 return s 54 } 55 56 func encodeDataKey(key *dataKey) []byte { 57 dataKeyBytes := append(pvtDataKeyPrefix, version.NewHeight(key.blkNum, key.txNum).ToBytes()...) 58 dataKeyBytes = append(dataKeyBytes, []byte(key.ns)...) 59 dataKeyBytes = append(dataKeyBytes, nilByte) 60 return append(dataKeyBytes, []byte(key.coll)...) 61 } 62 63 func encodeDataValue(collData *rwset.CollectionPvtReadWriteSet) ([]byte, error) { 64 return proto.Marshal(collData) 65 } 66 67 func encodeExpiryKey(expiryKey *expiryKey) []byte { 68 // reusing version encoding scheme here 69 return append(expiryKeyPrefix, version.NewHeight(expiryKey.expiringBlk, expiryKey.committingBlk).ToBytes()...) 70 } 71 72 func encodeExpiryValue(expiryData *ExpiryData) ([]byte, error) { 73 return proto.Marshal(expiryData) 74 } 75 76 func decodeExpiryKey(expiryKeyBytes []byte) (*expiryKey, error) { 77 height, _, err := version.NewHeightFromBytes(expiryKeyBytes[1:]) 78 if err != nil { 79 return nil, err 80 } 81 return &expiryKey{expiringBlk: height.BlockNum, committingBlk: height.TxNum}, nil 82 } 83 84 func decodeExpiryValue(expiryValueBytes []byte) (*ExpiryData, error) { 85 expiryData := &ExpiryData{} 86 err := proto.Unmarshal(expiryValueBytes, expiryData) 87 return expiryData, err 88 } 89 90 func decodeDatakey(datakeyBytes []byte) (*dataKey, error) { 91 v, n, err := version.NewHeightFromBytes(datakeyBytes[1:]) 92 if err != nil { 93 return nil, err 94 } 95 blkNum := v.BlockNum 96 tranNum := v.TxNum 97 remainingBytes := datakeyBytes[n+1:] 98 nilByteIndex := bytes.IndexByte(remainingBytes, nilByte) 99 ns := string(remainingBytes[:nilByteIndex]) 100 coll := string(remainingBytes[nilByteIndex+1:]) 101 return &dataKey{nsCollBlk{ns, coll, blkNum}, tranNum}, nil 102 } 103 104 func decodeDataValue(datavalueBytes []byte) (*rwset.CollectionPvtReadWriteSet, error) { 105 collPvtdata := &rwset.CollectionPvtReadWriteSet{} 106 err := proto.Unmarshal(datavalueBytes, collPvtdata) 107 return collPvtdata, err 108 } 109 110 func encodeMissingDataKey(key *missingDataKey) []byte { 111 if key.isEligible { 112 keyBytes := append(eligibleMissingDataKeyPrefix, util.EncodeReverseOrderVarUint64(key.blkNum)...) 113 keyBytes = append(keyBytes, []byte(key.ns)...) 114 keyBytes = append(keyBytes, nilByte) 115 return append(keyBytes, []byte(key.coll)...) 116 } 117 118 keyBytes := append(ineligibleMissingDataKeyPrefix, []byte(key.ns)...) 119 keyBytes = append(keyBytes, nilByte) 120 keyBytes = append(keyBytes, []byte(key.coll)...) 121 keyBytes = append(keyBytes, nilByte) 122 return append(keyBytes, []byte(util.EncodeReverseOrderVarUint64(key.blkNum))...) 123 } 124 125 func decodeMissingDataKey(keyBytes []byte) *missingDataKey { 126 key := &missingDataKey{nsCollBlk: nsCollBlk{}} 127 if keyBytes[0] == eligibleMissingDataKeyPrefix[0] { 128 blkNum, numBytesConsumed := util.DecodeReverseOrderVarUint64(keyBytes[1:]) 129 130 splittedKey := bytes.Split(keyBytes[numBytesConsumed+1:], []byte{nilByte}) 131 key.ns = string(splittedKey[0]) 132 key.coll = string(splittedKey[1]) 133 key.blkNum = blkNum 134 key.isEligible = true 135 return key 136 } 137 138 splittedKey := bytes.SplitN(keyBytes[1:], []byte{nilByte}, 3) //encoded bytes for blknum may contain empty bytes 139 key.ns = string(splittedKey[0]) 140 key.coll = string(splittedKey[1]) 141 key.blkNum, _ = util.DecodeReverseOrderVarUint64(splittedKey[2]) 142 key.isEligible = false 143 return key 144 } 145 146 func encodeMissingDataValue(bitmap *bitset.BitSet) ([]byte, error) { 147 return bitmap.MarshalBinary() 148 } 149 150 func decodeMissingDataValue(bitmapBytes []byte) (*bitset.BitSet, error) { 151 bitmap := &bitset.BitSet{} 152 if err := bitmap.UnmarshalBinary(bitmapBytes); err != nil { 153 return nil, err 154 } 155 return bitmap, nil 156 } 157 158 func encodeCollElgKey(blkNum uint64) []byte { 159 return append(collElgKeyPrefix, util.EncodeReverseOrderVarUint64(blkNum)...) 160 } 161 162 func decodeCollElgKey(b []byte) uint64 { 163 blkNum, _ := util.DecodeReverseOrderVarUint64(b[1:]) 164 return blkNum 165 } 166 167 func encodeCollElgVal(m *CollElgInfo) ([]byte, error) { 168 return proto.Marshal(m) 169 } 170 171 func decodeCollElgVal(b []byte) (*CollElgInfo, error) { 172 m := &CollElgInfo{} 173 if err := proto.Unmarshal(b, m); err != nil { 174 return nil, errors.WithStack(err) 175 } 176 return m, nil 177 } 178 179 func createRangeScanKeysForEligibleMissingDataEntries(blkNum uint64) (startKey, endKey []byte) { 180 startKey = append(eligibleMissingDataKeyPrefix, util.EncodeReverseOrderVarUint64(blkNum)...) 181 endKey = append(eligibleMissingDataKeyPrefix, util.EncodeReverseOrderVarUint64(0)...) 182 183 return startKey, endKey 184 } 185 186 func createRangeScanKeysForIneligibleMissingData(maxBlkNum uint64, ns, coll string) (startKey, endKey []byte) { 187 startKey = encodeMissingDataKey( 188 &missingDataKey{ 189 nsCollBlk: nsCollBlk{ns: ns, coll: coll, blkNum: maxBlkNum}, 190 isEligible: false, 191 }, 192 ) 193 endKey = encodeMissingDataKey( 194 &missingDataKey{ 195 nsCollBlk: nsCollBlk{ns: ns, coll: coll, blkNum: 0}, 196 isEligible: false, 197 }, 198 ) 199 return 200 } 201 202 func createRangeScanKeysForCollElg() (startKey, endKey []byte) { 203 return encodeCollElgKey(math.MaxUint64), 204 encodeCollElgKey(0) 205 } 206 207 func datakeyRange(blockNum uint64) (startKey, endKey []byte) { 208 startKey = append(pvtDataKeyPrefix, version.NewHeight(blockNum, 0).ToBytes()...) 209 endKey = append(pvtDataKeyPrefix, version.NewHeight(blockNum, math.MaxUint64).ToBytes()...) 210 return 211 } 212 213 func eligibleMissingdatakeyRange(blkNum uint64) (startKey, endKey []byte) { 214 startKey = append(eligibleMissingDataKeyPrefix, util.EncodeReverseOrderVarUint64(blkNum)...) 215 endKey = append(eligibleMissingDataKeyPrefix, util.EncodeReverseOrderVarUint64(blkNum-1)...) 216 return 217 }