func (state *State) FetchStateDeltaFromDB(blockNumber uint64) (*statemgmt.StateDelta, error) {
	stateDeltaBytes, err := db.GetDBHandle().GetFromStateDeltaCF(encodeStateDeltaKey(blockNumber))
	if err != nil {
		return nil, err
	}
	if stateDeltaBytes == nil {
		return nil, nil
	}
	stateDelta := statemgmt.NewStateDelta()
	stateDelta.Unmarshal(stateDeltaBytes)
	return stateDelta, nil
}
FetchStateDeltaFromDB fetches the StateDelta corrsponding to given blockNumber
package state
import (
	"encoding/binary"
	"fmt"
	"github.com/op/go-logging"
	"github.com/openblockchain/obc-peer/openchain/db"
	"github.com/openblockchain/obc-peer/openchain/ledger/statemgmt"
	"github.com/openblockchain/obc-peer/openchain/ledger/statemgmt/buckettree"
	"github.com/openblockchain/obc-peer/openchain/ledger/statemgmt/trie"
	"github.com/spf13/viper"
	"github.com/tecbot/gorocksdb"
)
var logger = logging.MustGetLogger("state")
const detaultStateImpl = "buckettree"
var stateImpl statemgmt.HashableState
type State struct {
	stateImpl             statemgmt.HashableState
	stateDelta            *statemgmt.StateDelta
	currentTxStateDelta   *statemgmt.StateDelta
	currentTxUUID         string
	txStateDeltaHash      map[string][]byte
	updateStateImpl       bool
	historyStateDeltaSize uint64
}
func NewState() *State {
	stateImplName := viper.GetString("ledger.state.dataStructure.name")
	stateImplConfigs := viper.GetStringMap("ledger.state.dataStructure.configs")
	if len(stateImplName) == 0 {
		stateImplName = detaultStateImpl
		stateImplConfigs = nil
	}
	switch stateImplName {
	case "buckettree":
		stateImpl = buckettree.NewStateImpl()
	case "trie":
		stateImpl = trie.NewStateTrie()
	default:
		panic(fmt.Errorf("Error during initialization of state implementation. State data structure '%s' is not valid.", stateImplName))
	}
	err := stateImpl.Initialize(stateImplConfigs)
	if err != nil {
		panic(fmt.Errorf("Error during initialization of state implementation: %s", err))
	}
	deltaHistorySize := viper.GetInt("ledger.state.deltaHistorySize")
	if deltaHistorySize < 0 {
		panic(fmt.Errorf("Delta history size must be greater than or equal to 0. Current value is %d.", deltaHistorySize))
	}
	return &State{stateImpl, statemgmt.NewStateDelta(), statemgmt.NewStateDelta(), "", make(map[string][]byte),
		false, uint64(deltaHistorySize)}
}
func (state *State) TxBegin(txUUID string) {
	logger.Debug("txBegin() for txUuid [%s]", txUUID)
	if state.txInProgress() {
		panic(fmt.Errorf("A tx [%s] is already in progress. Received call for begin of another tx [%s]", state.currentTxUUID, txUUID))
	}
	state.currentTxUUID = txUUID
}
func (state *State) TxFinish(txUUID string, txSuccessful bool) {
	logger.Debug("txFinish() for txUuid [%s], txSuccessful=[%t]", txUUID, txSuccessful)
	if state.currentTxUUID != txUUID {
		panic(fmt.Errorf("Different Uuid in tx-begin [%s] and tx-finish [%s]", state.currentTxUUID, txUUID))
	}
	if txSuccessful {
		if !state.currentTxStateDelta.IsEmpty() {
			logger.Debug("txFinish() for txUuid [%s] merging state changes", txUUID)
			state.stateDelta.ApplyChanges(state.currentTxStateDelta)
			state.txStateDeltaHash[txUUID] = state.currentTxStateDelta.ComputeCryptoHash()
			state.updateStateImpl = true
		} else {
			state.txStateDeltaHash[txUUID] = nil
		}
	}
	state.currentTxStateDelta = statemgmt.NewStateDelta()
	state.currentTxUUID = ""
}
func (state *State) txInProgress() bool {
	return state.currentTxUUID != ""
}
func (state *State) Get(chaincodeID string, key string, committed bool) ([]byte, error) {
	if !committed {
		valueHolder := state.currentTxStateDelta.Get(chaincodeID, key)
		if valueHolder != nil {
			return valueHolder.GetValue(), nil
		}
		valueHolder = state.stateDelta.Get(chaincodeID, key)
		if valueHolder != nil {
			return valueHolder.GetValue(), nil
		}
	}
	return state.stateImpl.Get(chaincodeID, key)
}
func (state *State) GetRangeScanIterator(chaincodeID string, startKey string, endKey string, committed bool) (statemgmt.RangeScanIterator, error) {
	stateImplItr, err := state.stateImpl.GetRangeScanIterator(chaincodeID, startKey, endKey)
	if err != nil {
		return nil, err
	}
	if committed {
		return stateImplItr, nil
	}
	return newCompositeRangeScanIterator(
		statemgmt.NewStateDeltaRangeScanIterator(state.currentTxStateDelta, chaincodeID, startKey, endKey),
		statemgmt.NewStateDeltaRangeScanIterator(state.stateDelta, chaincodeID, startKey, endKey),
		stateImplItr), nil
}
func (state *State) Set(chaincodeID string, key string, value []byte) error {
	logger.Debug("set() chaincodeID=[%s], key=[%s], value=[%#v]", chaincodeID, key, value)
	if !state.txInProgress() {
		panic("State can be changed only in context of a tx.")
	}
	if state.currentTxStateDelta.IsUpdatedValueSet(chaincodeID, key) {
		state.currentTxStateDelta.Set(chaincodeID, key, value, nil)
	} else {
		previousValue, err := state.Get(chaincodeID, key, true)
		if err != nil {
			return err
		}
		state.currentTxStateDelta.Set(chaincodeID, key, value, previousValue)
	}
	return nil
}
func (state *State) Delete(chaincodeID string, key string) error {
	logger.Debug("delete() chaincodeID=[%s], key=[%s]", chaincodeID, key)
	if !state.txInProgress() {
		panic("State can be changed only in context of a tx.")
	}
	if state.currentTxStateDelta.IsUpdatedValueSet(chaincodeID, key) {
		state.currentTxStateDelta.Delete(chaincodeID, key, nil)
	} else {
		previousValue, err := state.Get(chaincodeID, key, true)
		if err != nil {
			return err
		}
		state.currentTxStateDelta.Delete(chaincodeID, key, previousValue)
	}
	return nil
}
func (state *State) GetHash() ([]byte, error) {
	logger.Debug("Enter - GetHash()")
	if state.updateStateImpl {
		logger.Debug("updating stateImpl with working-set")
		state.stateImpl.PrepareWorkingSet(state.stateDelta)
		state.updateStateImpl = false
	}
	hash, err := state.stateImpl.ComputeCryptoHash()
	if err != nil {
		return nil, err
	}
	logger.Debug("Exit - GetHash()")
	return hash, nil
}
func (state *State) GetTxStateDeltaHash() map[string][]byte {
	return state.txStateDeltaHash
}
func (state *State) ClearInMemoryChanges(changesPersisted bool) {
	state.stateDelta = statemgmt.NewStateDelta()
	state.txStateDeltaHash = make(map[string][]byte)
	state.stateImpl.ClearWorkingSet(changesPersisted)
}
func (state *State) getStateDelta() *statemgmt.StateDelta {
	return state.stateDelta
}
func (state *State) GetSnapshot(blockNumber uint64, dbSnapshot *gorocksdb.Snapshot) (*StateSnapshot, error) {
	return newStateSnapshot(blockNumber, dbSnapshot)
}