func (stub *ChaincodeStub) GetStateByRange(startKey, endKey string) (StateQueryIteratorInterface, error) {
	if startKey == "" {
		startKey = emptyKeySubstitute
	}
	if err := validateSimpleKeys(startKey, endKey); err != nil {
		return nil, err
	}
	return stub.handleGetStateByRange(startKey, endKey)
}
GetStateByRange documentation can be found in interfaces.go
package shim
import (
	"errors"
	"flag"
	"fmt"
	"io"
	"os"
	"strings"
	"unicode/utf8"
	"math/big"
	"github.com/golang/protobuf/proto"
	"github.com/golang/protobuf/ptypes/timestamp"
	"github.com/inklabsfoundation/inkchain/bccsp/factory"
	"github.com/inklabsfoundation/inkchain/common/flogging"
	commonledger "github.com/inklabsfoundation/inkchain/common/ledger"
	"github.com/inklabsfoundation/inkchain/core/comm"
	"github.com/inklabsfoundation/inkchain/core/wallet"
	"github.com/inklabsfoundation/inkchain/protos/ledger/queryresult"
	"github.com/inklabsfoundation/inkchain/protos/ledger/transet/kvtranset"
	pb "github.com/inklabsfoundation/inkchain/protos/peer"
	"github.com/inklabsfoundation/inkchain/protos/utils"
	putils "github.com/inklabsfoundation/inkchain/protos/utils"
	"github.com/op/go-logging"
	"github.com/spf13/viper"
	"golang.org/x/net/context"
	"google.golang.org/grpc"
)
var chaincodeLogger = logging.MustGetLogger("shim")
var logOutput = os.Stderr
const (
	minUnicodeRuneValue   = 0             
	maxUnicodeRuneValue   = utf8.MaxRune  
	compositeKeyNamespace = "\x00"
	emptyKeySubstitute    = "\x01"
)
type ChaincodeStub struct {
	TxID           string
	Sender         string
	SenderPubKey   string
	chaincodeEvent *pb.ChaincodeEvent
	args           [][]byte
	handler        *Handler
	signedProposal *pb.SignedProposal
	proposal       *pb.Proposal
	creator   []byte
	transient map[string][]byte
	binding   []byte
}
var peerAddress string
type peerStreamGetter func(name string) (PeerChaincodeStream, error)
var streamGetter peerStreamGetter
func userChaincodeStreamGetter(name string) (PeerChaincodeStream, error) {
	flag.StringVar(&peerAddress, "peer.address", "", "peer address")
	flag.Parse()
	chaincodeLogger.Debugf("Peer address: %s", getPeerAddress())
	clientConn, err := newPeerClientConnection()
	if err != nil {
		chaincodeLogger.Errorf("Error trying to connect to local peer: %s", err)
		return nil, fmt.Errorf("Error trying to connect to local peer: %s", err)
	}
	chaincodeLogger.Debugf("os.Args returns: %s", os.Args)
	chaincodeSupportClient := pb.NewChaincodeSupportClient(clientConn)
	stream, err := chaincodeSupportClient.Register(context.Background())
	if err != nil {
		return nil, fmt.Errorf("Error chatting with leader at address=%s:  %s", getPeerAddress(), err)
	}
	return stream, nil
}
func Start(cc Chaincode) error {
	SetupChaincodeLogging()
	chaincodename := viper.GetString("chaincode.id.name")
	if chaincodename == "" {
		return fmt.Errorf("Error chaincode id not provided")
	}
	err := factory.InitFactories(factory.GetDefaultOpts())
	if err != nil {
		return fmt.Errorf("Internal error, BCCSP could not be initialized with default options: %s", err)
	}
	if streamGetter == nil {
		streamGetter = userChaincodeStreamGetter
	}
	stream, err := streamGetter(chaincodename)
	if err != nil {
		return err
	}
	err = chatWithPeer(chaincodename, stream, cc)
	return err
}
func IsEnabledForLogLevel(logLevel string) bool {
	lvl, _ := logging.LogLevel(logLevel)
	return chaincodeLogger.IsEnabledFor(lvl)
}
func SetupChaincodeLogging() {
	viper.SetEnvPrefix("CORE")
	viper.AutomaticEnv()
	replacer := strings.NewReplacer(".", "_")
	viper.SetEnvKeyReplacer(replacer)
	logFormat := flogging.SetFormat(viper.GetString("chaincode.logging.format"))
	flogging.InitBackend(logFormat, logOutput)
	chaincodeLogLevelString := viper.GetString("chaincode.logging.level")
	if chaincodeLogLevelString == "" {
		chaincodeLogger.Infof("Chaincode log level not provided; defaulting to: %s", flogging.DefaultLevel())
		flogging.InitFromSpec(flogging.DefaultLevel())
	} else {
		_, err := LogLevel(chaincodeLogLevelString)
		if err == nil {
			flogging.InitFromSpec(chaincodeLogLevelString)
		} else {
			chaincodeLogger.Warningf("Error: '%s' for chaincode log level: %s; defaulting to %s", err, chaincodeLogLevelString, flogging.DefaultLevel())
			flogging.InitFromSpec(flogging.DefaultLevel())
		}
	}
	shimLogLevelString := viper.GetString("chaincode.logging.shim")
	if shimLogLevelString != "" {
		shimLogLevel, err := LogLevel(shimLogLevelString)
		if err == nil {
			SetLoggingLevel(shimLogLevel)
		} else {
			chaincodeLogger.Warningf("Error: %s for shim log level: %s", err, shimLogLevelString)
		}
	}
	buildLevel := viper.GetString("chaincode.buildlevel")
	chaincodeLogger.Infof("Chaincode (build level: %s) starting up ...", buildLevel)
}
func StartInProc(env []string, args []string, cc Chaincode, recv <-chan *pb.ChaincodeMessage, send chan<- *pb.ChaincodeMessage) error {
	chaincodeLogger.Debugf("in proc %v", args)
	var chaincodename string
	for _, v := range env {
		if strings.Index(v, "CORE_CHAINCODE_ID_NAME=") == 0 {
			p := strings.SplitAfter(v, "CORE_CHAINCODE_ID_NAME=")
			chaincodename = p[1]
			break
		}
	}
	if chaincodename == "" {
		return fmt.Errorf("Error chaincode id not provided")
	}
	stream := newInProcStream(recv, send)
	chaincodeLogger.Debugf("starting chat with peer using name=%s", chaincodename)
	err := chatWithPeer(chaincodename, stream, cc)
	return err
}
func getPeerAddress() string {
	if peerAddress != "" {
		return peerAddress
	}
	if peerAddress = viper.GetString("peer.address"); peerAddress == "" {
		chaincodeLogger.Fatalf("peer.address not configured, can't connect to peer")
	}
	return peerAddress
}
func newPeerClientConnection() (*grpc.ClientConn, error) {
	var peerAddress = getPeerAddress()
	if comm.TLSEnabled() {
		return comm.NewClientConnectionWithAddress(peerAddress, true, true, comm.InitTLSForPeer())
	}
	return comm.NewClientConnectionWithAddress(peerAddress, true, false, nil)
}
func chatWithPeer(chaincodename string, stream PeerChaincodeStream, cc Chaincode) error {
	handler := newChaincodeHandler(stream, cc)
	defer stream.CloseSend()
	chaincodeID := &pb.ChaincodeID{Name: chaincodename}
	payload, err := proto.Marshal(chaincodeID)
	if err != nil {
		return fmt.Errorf("Error marshalling chaincodeID during chaincode registration: %s", err)
	}
	chaincodeLogger.Debugf("Registering.. sending %s", pb.ChaincodeMessage_REGISTER)
	if err = handler.serialSend(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_REGISTER, Payload: payload}); err != nil {
		return fmt.Errorf("Error sending chaincode REGISTER: %s", err)
	}
	waitc := make(chan struct{})
	errc := make(chan error)
	go func() {
		defer close(waitc)
		msgAvail := make(chan *pb.ChaincodeMessage)
		var nsInfo *nextStateInfo
		var in *pb.ChaincodeMessage
		recv := true
		for {
			in = nil
			err = nil
			nsInfo = nil
			if recv {
				recv = false
				go func() {
					var in2 *pb.ChaincodeMessage
					in2, err = stream.Recv()
					msgAvail <- in2
				}()
			}
			select {
			case sendErr := <-errc:
				if sendErr == nil {
					continue
				}
				err = fmt.Errorf("Error sending %s: %s", in.Type.String(), sendErr)
				return
			case in = <-msgAvail:
				if err == io.EOF {
					chaincodeLogger.Debugf("Received EOF, ending chaincode stream, %s", err)
					return
				} else if err != nil {
					chaincodeLogger.Errorf("Received error from server: %s, ending chaincode stream", err)
					return
				} else if in == nil {
					err = fmt.Errorf("Received nil message, ending chaincode stream")
					chaincodeLogger.Debug("Received nil message, ending chaincode stream")
					return
				}
				chaincodeLogger.Debugf("[%s]Received message %s from shim", shorttxid(in.Txid), in.Type.String())
				recv = true
			case nsInfo = <-handler.nextState:
				in = nsInfo.msg
				if in == nil {
					panic("nil msg")
				}
				chaincodeLogger.Debugf("[%s]Move state message %s", shorttxid(in.Txid), in.Type.String())
			}
			err = handler.handleMessage(in)
			if err != nil {
				err = fmt.Errorf("Error handling message: %s", err)
				return
			}
			if in.Type == pb.ChaincodeMessage_KEEPALIVE {
				chaincodeLogger.Debug("Sending KEEPALIVE response")
				handler.serialSendAsync(in, nil)
			} else if nsInfo != nil && nsInfo.sendToCC {
				chaincodeLogger.Debugf("[%s]send state message %s", shorttxid(in.Txid), in.Type.String())
				handler.serialSendAsync(in, errc)
			}
		}
	}()
	<-waitc
	return err
}
func (stub *ChaincodeStub) verifySigAndGetSender(proposal *pb.Proposal) (string, error) {
	cis, err := putils.GetChaincodeInvocationSpecFromSignedProposal(proposal)
	if err != nil {
		return "", fmt.Errorf("Failed extracting signedProposal from signed signedProposal. [%s]", err)
	}
	if cis.Sig == nil || cis.SenderSpec == nil {
		return "", nil
	}
	hash, err := wallet.GetInvokeHash(cis.ChaincodeSpec, cis.IdGenerationAlg, cis.SenderSpec)
	if err != nil {
		return "", fmt.Errorf("invalid signature1. [%s]", err)
	}
	sender, err := wallet.GetSenderFromSignature(hash, cis.Sig)
	senderStr := sender.ToString()
	if strings.Compare(senderStr, string(cis.SenderSpec.Sender[:])) != 0 {
		return "", fmt.Errorf("invalid signature2. [%s]", err.Error())
	}
	return senderStr, nil
}
func (stub *ChaincodeStub) verifySigAndGetSenderPubKey(proposal *pb.Proposal) (string, error) {
	cis, err := putils.GetChaincodeInvocationSpecFromSignedProposal(proposal)
	if err != nil {
		return "", fmt.Errorf("Failed extracting signedProposal from signed signedProposal. 1 [%s]", err)
	}
	if cis.Sig == nil || cis.SenderSpec == nil {
		return "", nil
	}
	hash, err := wallet.GetInvokeHash(cis.ChaincodeSpec, cis.IdGenerationAlg, cis.SenderSpec)
	if err != nil {
		return "", fmt.Errorf("invalid signature1. [%s]", err)
	}
	senderPubKey, err := wallet.GetSenderPubKeyFromSignature(hash, cis.Sig)
	return senderPubKey, nil
}
func (stub *ChaincodeStub) getSenderMsg(proposal *pb.Proposal) (string, error) {
	cis, err := putils.GetChaincodeInvocationSpecFromSignedProposal(proposal)
	if err != nil {
		return "", fmt.Errorf("Failed extracting signedProposal from signed signedProposal. [%s]", err)
	}
	if cis.Sig == nil || cis.SenderSpec == nil {
		return "", nil
	}
	return string(cis.SenderSpec.Msg), nil
}
func (stub *ChaincodeStub) init(handler *Handler, txid string, input *pb.ChaincodeInput, signedProposal *pb.SignedProposal) error {
	stub.TxID = txid
	stub.args = input.Args
	stub.handler = handler
	stub.signedProposal = signedProposal
	if signedProposal != nil {
		var err error
		stub.proposal, err = utils.GetProposal(signedProposal.ProposalBytes)
		if err != nil {
			return fmt.Errorf("Failed extracting signedProposal from signed signedProposal. [%s]", err)
		}
		stub.creator, stub.transient, err = utils.GetChaincodeProposalContext(stub.proposal)
		if err != nil {
			return fmt.Errorf("Failed extracting signedProposal fields. [%s]", err)
		}
		stub.binding, err = utils.ComputeProposalBinding(stub.proposal)
		if err != nil {
			return fmt.Errorf("Failed computing binding from signedProposal. [%s]", err)
		}
		sender, err := stub.verifySigAndGetSender(stub.proposal)
		bytes := make([]byte, len(sender))
		copy(bytes,sender)
		stub.Sender = string(bytes)
		senderPubKey, err := stub.verifySigAndGetSenderPubKey(stub.proposal)
		if err != nil {
			return fmt.Errorf("unable to get pub key. [%s]", err)
		}
		pubBytes := make([]byte, len(senderPubKey))
		copy(pubBytes,senderPubKey)
		stub.SenderPubKey = string(pubBytes)
	}
	return nil
}
func (stub *ChaincodeStub) GetTxID() string {
	return stub.TxID
}
func (stub *ChaincodeStub) InvokeChaincode(chaincodeName string, args [][]byte, channel string) pb.Response {
	if channel != "" {
		chaincodeName = chaincodeName + "/" + channel
	}
	return stub.handler.handleInvokeChaincode(chaincodeName, args, stub.TxID)
}
func (stub *ChaincodeStub) GetState(key string) ([]byte, error) {
	return stub.handler.handleGetState(key, stub.TxID)
}
func (stub *ChaincodeStub) PutState(key string, value []byte) error {
	if key == "" {
		return fmt.Errorf("key must not be an empty string")
	}
	return stub.handler.handlePutState(key, value, stub.TxID)
}
func (stub *ChaincodeStub) DelState(key string) error {
	return stub.handler.handleDelState(key, stub.TxID)
}
type CommonIterator struct {
	handler    *Handler
	uuid       string
	response   *pb.QueryResponse
	currentLoc int
}
type StateQueryIterator struct {
	*CommonIterator
}
type HistoryQueryIterator struct {
	*CommonIterator
}
type resultType uint8
const (
	STATE_QUERY_RESULT   resultType = iota + 1
	HISTORY_QUERY_RESULT
)
func (stub *ChaincodeStub) handleGetStateByRange(startKey, endKey string) (StateQueryIteratorInterface, error) {
	response, err := stub.handler.handleGetStateByRange(startKey, endKey, stub.TxID)
	if err != nil {
		return nil, err
	}
	return &StateQueryIterator{CommonIterator: &CommonIterator{stub.handler, stub.TxID, response, 0}}, nil
}