github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/core/ledger/kvledger/history/kv_encoding.go (about)

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