func (stub *ChaincodeStub) GetStateByPartialCompositeKey(objectType string, attributes []string) (StateQueryIteratorInterface, error) {
	if partialCompositeKey, err := stub.CreateCompositeKey(objectType, attributes); err == nil {
		return stub.handleGetStateByRange(partialCompositeKey, partialCompositeKey+string(maxUnicodeRuneValue))
	} else {
		return nil, err
	}
}
GetStateByPartialCompositeKey function can be invoked by a chaincode to query the
state based on a given partial composite key. This function returns an
iterator which can be used to iterate over all composite keys whose prefix
matches the given partial composite key. This function should be used only for
a partial composite key. For a full composite key, an iter with empty response
would be returned.
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
}
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)
}
func (stub *ChaincodeStub) GetQueryResult(query string) (StateQueryIteratorInterface, error) {
	response, err := stub.handler.handleGetQueryResult(query, stub.TxID)
	if err != nil {
		return nil, err
	}
	return &StateQueryIterator{CommonIterator: &CommonIterator{stub.handler, stub.TxID, response, 0}}, nil
}
func (stub *ChaincodeStub) GetHistoryForKey(key string) (HistoryQueryIteratorInterface, error) {
	response, err := stub.handler.handleGetHistoryForKey(key, stub.TxID)
	if err != nil {
		return nil, err
	}
	return &HistoryQueryIterator{CommonIterator: &CommonIterator{stub.handler, stub.TxID, response, 0}}, nil
}
func (stub *ChaincodeStub) CreateCompositeKey(objectType string, attributes []string) (string, error) {
	return createCompositeKey(objectType, attributes)
}
func (stub *ChaincodeStub) SplitCompositeKey(compositeKey string) (string, []string, error) {
	return splitCompositeKey(compositeKey)
}
func createCompositeKey(objectType string, attributes []string) (string, error) {
	if err := validateCompositeKeyAttribute(objectType); err != nil {
		return "", err
	}
	ck := compositeKeyNamespace + objectType + string(minUnicodeRuneValue)
	for _, att := range attributes {
		if err := validateCompositeKeyAttribute(att); err != nil {
			return "", err
		}
		ck += att + string(minUnicodeRuneValue)
	}
	return ck, nil
}
func splitCompositeKey(compositeKey string) (string, []string, error) {
	componentIndex := 1
	components := []string{}
	for i := 1; i < len(compositeKey); i++ {
		if compositeKey[i] == minUnicodeRuneValue {
			components = append(components, compositeKey[componentIndex:i])
			componentIndex = i + 1
		}
	}
	return components[0], components[1:], nil
}
func validateCompositeKeyAttribute(str string) error {
	if !utf8.ValidString(str) {
		return fmt.Errorf("Not a valid utf8 string: [%x]", str)
	}
	for index, runeValue := range str {
		if runeValue == minUnicodeRuneValue || runeValue == maxUnicodeRuneValue {
			return fmt.Errorf(`Input contain unicode %#U starting at position [%d]. %#U and %#U are not allowed in the input attribute of a composite key`,
				runeValue, index, minUnicodeRuneValue, maxUnicodeRuneValue)
		}
	}
	return nil
}
func validateSimpleKeys(simpleKeys ...string) error {
	for _, key := range simpleKeys {
		if len(key) > 0 && key[0] == compositeKeyNamespace[0] {
			return fmt.Errorf(`First character of the key [%s] contains a null character which is not allowed`, key)
		}
	}
	return nil
}