github.com/true-sqn/fabric@v2.1.1+incompatible/core/ledger/kvledger/history/kv_encoding.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package history 8 9 import ( 10 "bytes" 11 12 "github.com/hyperledger/fabric/common/ledger/util" 13 "github.com/pkg/errors" 14 ) 15 16 type dataKey []byte 17 type rangeScan struct { 18 startKey, endKey []byte 19 } 20 21 var ( 22 compositeKeySep = []byte{0x00} // used as a separator between different components of dataKey 23 dataKeyPrefix = []byte{'d'} // prefix added to dataKeys 24 savePointKey = []byte{'s'} // a single key in db for persisting savepoint 25 emptyValue = []byte{} // used to store as value for keys where only key needs to be stored (e.g., dataKeys) 26 ) 27 28 // constructDataKey builds the key of the format namespace~len(key)~key~blocknum~trannum 29 // using an order preserving encoding so that history query results are ordered by height 30 // Note: this key format is different than the format in pre-v2.0 releases and requires 31 // a historydb rebuild when upgrading an older version to v2.0. 32 func constructDataKey(ns string, key string, blocknum uint64, trannum uint64) dataKey { 33 k := append([]byte(ns), compositeKeySep...) 34 k = append(k, util.EncodeOrderPreservingVarUint64(uint64(len(key)))...) 35 k = append(k, []byte(key)...) 36 k = append(k, compositeKeySep...) 37 k = append(k, util.EncodeOrderPreservingVarUint64(blocknum)...) 38 k = append(k, util.EncodeOrderPreservingVarUint64(trannum)...) 39 return dataKey(k) 40 } 41 42 // constructRangescanKeys returns start and endKey for performing a range scan 43 // that covers all the keys for <ns, key>. 44 // startKey = namespace~len(key)~key~ 45 // endKey = namespace~len(key)~key~0xff 46 func constructRangeScan(ns string, key string) *rangeScan { 47 k := append([]byte(ns), compositeKeySep...) 48 k = append(k, util.EncodeOrderPreservingVarUint64(uint64(len(key)))...) 49 k = append(k, []byte(key)...) 50 k = append(k, compositeKeySep...) 51 52 return &rangeScan{ 53 startKey: k, 54 endKey: append(k, 0xff), 55 } 56 } 57 58 func (r *rangeScan) decodeBlockNumTranNum(dataKey dataKey) (uint64, uint64, error) { 59 blockNumTranNumBytes := bytes.TrimPrefix(dataKey, r.startKey) 60 blockNum, blockBytesConsumed, err := util.DecodeOrderPreservingVarUint64(blockNumTranNumBytes) 61 if err != nil { 62 return 0, 0, err 63 } 64 65 tranNum, tranBytesConsumed, err := util.DecodeOrderPreservingVarUint64(blockNumTranNumBytes[blockBytesConsumed:]) 66 if err != nil { 67 return 0, 0, err 68 } 69 70 // The following error should never happen. Keep the check just in case there is some unknown bug. 71 if blockBytesConsumed+tranBytesConsumed != len(blockNumTranNumBytes) { 72 return 0, 0, errors.Errorf("number of decoded bytes (%d) is not equal to the length of blockNumTranNumBytes (%d)", 73 blockBytesConsumed+tranBytesConsumed, len(blockNumTranNumBytes)) 74 } 75 return blockNum, tranNum, nil 76 }