github.com/inklabsfoundation/inkchain@v0.17.1-0.20181025012015-c3cef8062f19/core/chaincode/shim/chaincode.go (about) 1 /* 2 Copyright IBM Corp. 2016 All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 // Package shim provides APIs for the chaincode to access its state 18 // variables, transaction context and call other chaincodes. 19 package shim 20 21 import ( 22 "errors" 23 "flag" 24 "fmt" 25 "io" 26 "os" 27 "strings" 28 "unicode/utf8" 29 30 "math/big" 31 32 "github.com/golang/protobuf/proto" 33 "github.com/golang/protobuf/ptypes/timestamp" 34 "github.com/inklabsfoundation/inkchain/bccsp/factory" 35 "github.com/inklabsfoundation/inkchain/common/flogging" 36 commonledger "github.com/inklabsfoundation/inkchain/common/ledger" 37 "github.com/inklabsfoundation/inkchain/core/comm" 38 "github.com/inklabsfoundation/inkchain/core/wallet" 39 "github.com/inklabsfoundation/inkchain/protos/ledger/queryresult" 40 "github.com/inklabsfoundation/inkchain/protos/ledger/transet/kvtranset" 41 pb "github.com/inklabsfoundation/inkchain/protos/peer" 42 "github.com/inklabsfoundation/inkchain/protos/utils" 43 putils "github.com/inklabsfoundation/inkchain/protos/utils" 44 "github.com/op/go-logging" 45 "github.com/spf13/viper" 46 "golang.org/x/net/context" 47 "google.golang.org/grpc" 48 ) 49 50 // Logger for the shim package. 51 var chaincodeLogger = logging.MustGetLogger("shim") 52 var logOutput = os.Stderr 53 54 const ( 55 minUnicodeRuneValue = 0 //U+0000 56 maxUnicodeRuneValue = utf8.MaxRune //U+10FFFF - maximum (and unallocated) code point 57 compositeKeyNamespace = "\x00" 58 emptyKeySubstitute = "\x01" 59 ) 60 61 // ChaincodeStub is an object passed to chaincode for shim side handling of 62 // APIs. 63 type ChaincodeStub struct { 64 TxID string 65 Sender string 66 SenderPubKey string 67 chaincodeEvent *pb.ChaincodeEvent 68 args [][]byte 69 handler *Handler 70 signedProposal *pb.SignedProposal 71 proposal *pb.Proposal 72 73 // Additional fields extracted from the signedProposal 74 creator []byte 75 transient map[string][]byte 76 binding []byte 77 } 78 79 // Peer address derived from command line or env var 80 var peerAddress string 81 82 //this separates the chaincode stream interface establishment 83 //so we can replace it with a mock peer stream 84 type peerStreamGetter func(name string) (PeerChaincodeStream, error) 85 86 //UTs to setup mock peer stream getter 87 var streamGetter peerStreamGetter 88 89 //the non-mock user CC stream establishment func 90 func userChaincodeStreamGetter(name string) (PeerChaincodeStream, error) { 91 flag.StringVar(&peerAddress, "peer.address", "", "peer address") 92 93 flag.Parse() 94 95 chaincodeLogger.Debugf("Peer address: %s", getPeerAddress()) 96 97 // Establish connection with validating peer 98 clientConn, err := newPeerClientConnection() 99 if err != nil { 100 chaincodeLogger.Errorf("Error trying to connect to local peer: %s", err) 101 return nil, fmt.Errorf("Error trying to connect to local peer: %s", err) 102 } 103 104 chaincodeLogger.Debugf("os.Args returns: %s", os.Args) 105 106 chaincodeSupportClient := pb.NewChaincodeSupportClient(clientConn) 107 108 // Establish stream with validating peer 109 stream, err := chaincodeSupportClient.Register(context.Background()) 110 if err != nil { 111 return nil, fmt.Errorf("Error chatting with leader at address=%s: %s", getPeerAddress(), err) 112 } 113 114 return stream, nil 115 } 116 117 // chaincodes. 118 func Start(cc Chaincode) error { 119 // If Start() is called, we assume this is a standalone chaincode and set 120 // up formatted logging. 121 SetupChaincodeLogging() 122 123 chaincodename := viper.GetString("chaincode.id.name") 124 if chaincodename == "" { 125 return fmt.Errorf("Error chaincode id not provided") 126 } 127 128 err := factory.InitFactories(factory.GetDefaultOpts()) 129 if err != nil { 130 return fmt.Errorf("Internal error, BCCSP could not be initialized with default options: %s", err) 131 } 132 133 //mock stream not set up ... get real stream 134 if streamGetter == nil { 135 streamGetter = userChaincodeStreamGetter 136 } 137 138 stream, err := streamGetter(chaincodename) 139 if err != nil { 140 return err 141 } 142 143 err = chatWithPeer(chaincodename, stream, cc) 144 145 return err 146 } 147 148 // IsEnabledForLogLevel checks to see if the chaincodeLogger is enabled for a specific logging level 149 // used primarily for testing 150 func IsEnabledForLogLevel(logLevel string) bool { 151 lvl, _ := logging.LogLevel(logLevel) 152 return chaincodeLogger.IsEnabledFor(lvl) 153 } 154 155 // SetupChaincodeLogging sets the chaincode logging format and the level 156 // to the values of CORE_CHAINCODE_LOGFORMAT and CORE_CHAINCODE_LOGLEVEL set 157 // from core.yaml by chaincode_support.go 158 func SetupChaincodeLogging() { 159 viper.SetEnvPrefix("CORE") 160 viper.AutomaticEnv() 161 replacer := strings.NewReplacer(".", "_") 162 viper.SetEnvKeyReplacer(replacer) 163 164 // setup system-wide logging backend 165 logFormat := flogging.SetFormat(viper.GetString("chaincode.logging.format")) 166 flogging.InitBackend(logFormat, logOutput) 167 168 // set default log level for all modules 169 chaincodeLogLevelString := viper.GetString("chaincode.logging.level") 170 if chaincodeLogLevelString == "" { 171 chaincodeLogger.Infof("Chaincode log level not provided; defaulting to: %s", flogging.DefaultLevel()) 172 flogging.InitFromSpec(flogging.DefaultLevel()) 173 } else { 174 _, err := LogLevel(chaincodeLogLevelString) 175 if err == nil { 176 flogging.InitFromSpec(chaincodeLogLevelString) 177 } else { 178 chaincodeLogger.Warningf("Error: '%s' for chaincode log level: %s; defaulting to %s", err, chaincodeLogLevelString, flogging.DefaultLevel()) 179 flogging.InitFromSpec(flogging.DefaultLevel()) 180 } 181 } 182 183 // override the log level for the shim logging module - note: if this value is 184 // blank or an invalid log level, then the above call to 185 // `flogging.InitFromSpec` already set the default log level so no action 186 // is required here. 187 shimLogLevelString := viper.GetString("chaincode.logging.shim") 188 if shimLogLevelString != "" { 189 shimLogLevel, err := LogLevel(shimLogLevelString) 190 if err == nil { 191 SetLoggingLevel(shimLogLevel) 192 } else { 193 chaincodeLogger.Warningf("Error: %s for shim log level: %s", err, shimLogLevelString) 194 } 195 } 196 197 //now that logging is setup, print build level. This will help making sure 198 //chaincode is matched with peer. 199 buildLevel := viper.GetString("chaincode.buildlevel") 200 chaincodeLogger.Infof("Chaincode (build level: %s) starting up ...", buildLevel) 201 } 202 203 // StartInProc is an entry point for system chaincodes bootstrap. It is not an 204 // API for chaincodes. 205 func StartInProc(env []string, args []string, cc Chaincode, recv <-chan *pb.ChaincodeMessage, send chan<- *pb.ChaincodeMessage) error { 206 chaincodeLogger.Debugf("in proc %v", args) 207 208 var chaincodename string 209 for _, v := range env { 210 if strings.Index(v, "CORE_CHAINCODE_ID_NAME=") == 0 { 211 p := strings.SplitAfter(v, "CORE_CHAINCODE_ID_NAME=") 212 chaincodename = p[1] 213 break 214 } 215 } 216 if chaincodename == "" { 217 return fmt.Errorf("Error chaincode id not provided") 218 } 219 220 stream := newInProcStream(recv, send) 221 chaincodeLogger.Debugf("starting chat with peer using name=%s", chaincodename) 222 err := chatWithPeer(chaincodename, stream, cc) 223 return err 224 } 225 226 func getPeerAddress() string { 227 if peerAddress != "" { 228 return peerAddress 229 } 230 231 if peerAddress = viper.GetString("peer.address"); peerAddress == "" { 232 chaincodeLogger.Fatalf("peer.address not configured, can't connect to peer") 233 } 234 235 return peerAddress 236 } 237 238 func newPeerClientConnection() (*grpc.ClientConn, error) { 239 var peerAddress = getPeerAddress() 240 if comm.TLSEnabled() { 241 return comm.NewClientConnectionWithAddress(peerAddress, true, true, comm.InitTLSForPeer()) 242 } 243 return comm.NewClientConnectionWithAddress(peerAddress, true, false, nil) 244 } 245 246 func chatWithPeer(chaincodename string, stream PeerChaincodeStream, cc Chaincode) error { 247 248 // Create the shim handler responsible for all control logic 249 handler := newChaincodeHandler(stream, cc) 250 251 defer stream.CloseSend() 252 // Send the ChaincodeID during register. 253 chaincodeID := &pb.ChaincodeID{Name: chaincodename} 254 payload, err := proto.Marshal(chaincodeID) 255 if err != nil { 256 return fmt.Errorf("Error marshalling chaincodeID during chaincode registration: %s", err) 257 } 258 // Register on the stream 259 chaincodeLogger.Debugf("Registering.. sending %s", pb.ChaincodeMessage_REGISTER) 260 if err = handler.serialSend(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_REGISTER, Payload: payload}); err != nil { 261 return fmt.Errorf("Error sending chaincode REGISTER: %s", err) 262 } 263 waitc := make(chan struct{}) 264 errc := make(chan error) 265 go func() { 266 defer close(waitc) 267 msgAvail := make(chan *pb.ChaincodeMessage) 268 var nsInfo *nextStateInfo 269 var in *pb.ChaincodeMessage 270 recv := true 271 for { 272 in = nil 273 err = nil 274 nsInfo = nil 275 if recv { 276 recv = false 277 go func() { 278 var in2 *pb.ChaincodeMessage 279 in2, err = stream.Recv() 280 msgAvail <- in2 281 }() 282 } 283 select { 284 case sendErr := <-errc: 285 //serialSendAsync successful? 286 if sendErr == nil { 287 continue 288 } 289 //no, bail 290 err = fmt.Errorf("Error sending %s: %s", in.Type.String(), sendErr) 291 return 292 case in = <-msgAvail: 293 if err == io.EOF { 294 chaincodeLogger.Debugf("Received EOF, ending chaincode stream, %s", err) 295 return 296 } else if err != nil { 297 chaincodeLogger.Errorf("Received error from server: %s, ending chaincode stream", err) 298 return 299 } else if in == nil { 300 err = fmt.Errorf("Received nil message, ending chaincode stream") 301 chaincodeLogger.Debug("Received nil message, ending chaincode stream") 302 return 303 } 304 chaincodeLogger.Debugf("[%s]Received message %s from shim", shorttxid(in.Txid), in.Type.String()) 305 recv = true 306 case nsInfo = <-handler.nextState: 307 in = nsInfo.msg 308 if in == nil { 309 panic("nil msg") 310 } 311 chaincodeLogger.Debugf("[%s]Move state message %s", shorttxid(in.Txid), in.Type.String()) 312 } 313 314 // Call FSM.handleMessage() 315 err = handler.handleMessage(in) 316 if err != nil { 317 err = fmt.Errorf("Error handling message: %s", err) 318 return 319 } 320 321 //keepalive messages are PONGs to the inkchain's PINGs 322 if in.Type == pb.ChaincodeMessage_KEEPALIVE { 323 chaincodeLogger.Debug("Sending KEEPALIVE response") 324 //ignore any errors, maybe next KEEPALIVE will work 325 handler.serialSendAsync(in, nil) 326 } else if nsInfo != nil && nsInfo.sendToCC { 327 chaincodeLogger.Debugf("[%s]send state message %s", shorttxid(in.Txid), in.Type.String()) 328 handler.serialSendAsync(in, errc) 329 } 330 } 331 }() 332 <-waitc 333 return err 334 } 335 336 // -- init stub --- 337 // ChaincodeInvocation functionality 338 //*********inkchain 339 func (stub *ChaincodeStub) verifySigAndGetSender(proposal *pb.Proposal) (string, error) { 340 341 cis, err := putils.GetChaincodeInvocationSpecFromSignedProposal(proposal) 342 if err != nil { 343 return "", fmt.Errorf("Failed extracting signedProposal from signed signedProposal. [%s]", err) 344 } 345 if cis.Sig == nil || cis.SenderSpec == nil { 346 return "", nil 347 } 348 hash, err := wallet.GetInvokeHash(cis.ChaincodeSpec, cis.IdGenerationAlg, cis.SenderSpec) 349 if err != nil { 350 return "", fmt.Errorf("invalid signature1. [%s]", err) 351 } 352 sender, err := wallet.GetSenderFromSignature(hash, cis.Sig) 353 senderStr := sender.ToString() 354 if strings.Compare(senderStr, string(cis.SenderSpec.Sender[:])) != 0 { 355 return "", fmt.Errorf("invalid signature2. [%s]", err.Error()) 356 } 357 return senderStr, nil 358 } 359 360 func (stub *ChaincodeStub) verifySigAndGetSenderPubKey(proposal *pb.Proposal) (string, error) { 361 362 cis, err := putils.GetChaincodeInvocationSpecFromSignedProposal(proposal) 363 if err != nil { 364 return "", fmt.Errorf("Failed extracting signedProposal from signed signedProposal. 1 [%s]", err) 365 } 366 if cis.Sig == nil || cis.SenderSpec == nil { 367 return "", nil 368 } 369 hash, err := wallet.GetInvokeHash(cis.ChaincodeSpec, cis.IdGenerationAlg, cis.SenderSpec) 370 if err != nil { 371 return "", fmt.Errorf("invalid signature1. [%s]", err) 372 } 373 senderPubKey, err := wallet.GetSenderPubKeyFromSignature(hash, cis.Sig) 374 return senderPubKey, nil 375 } 376 377 // get sender msg info 378 func (stub *ChaincodeStub) getSenderMsg(proposal *pb.Proposal) (string, error) { 379 cis, err := putils.GetChaincodeInvocationSpecFromSignedProposal(proposal) 380 if err != nil { 381 return "", fmt.Errorf("Failed extracting signedProposal from signed signedProposal. [%s]", err) 382 } 383 if cis.Sig == nil || cis.SenderSpec == nil { 384 return "", nil 385 } 386 return string(cis.SenderSpec.Msg), nil 387 } 388 389 //********* 390 391 func (stub *ChaincodeStub) init(handler *Handler, txid string, input *pb.ChaincodeInput, signedProposal *pb.SignedProposal) error { 392 stub.TxID = txid 393 stub.args = input.Args 394 stub.handler = handler 395 stub.signedProposal = signedProposal 396 397 // TODO: sanity check: verify that every call to init with a nil 398 // signedProposal is a legitimate one, meaning it is an internal call 399 // to system chaincodes. 400 if signedProposal != nil { 401 var err error 402 403 stub.proposal, err = utils.GetProposal(signedProposal.ProposalBytes) 404 if err != nil { 405 return fmt.Errorf("Failed extracting signedProposal from signed signedProposal. [%s]", err) 406 } 407 408 // Extract creator, transient, binding... 409 stub.creator, stub.transient, err = utils.GetChaincodeProposalContext(stub.proposal) 410 if err != nil { 411 return fmt.Errorf("Failed extracting signedProposal fields. [%s]", err) 412 } 413 414 stub.binding, err = utils.ComputeProposalBinding(stub.proposal) 415 if err != nil { 416 return fmt.Errorf("Failed computing binding from signedProposal. [%s]", err) 417 } 418 sender, err := stub.verifySigAndGetSender(stub.proposal) 419 bytes := make([]byte, len(sender)) 420 copy(bytes,sender) 421 stub.Sender = string(bytes) 422 423 senderPubKey, err := stub.verifySigAndGetSenderPubKey(stub.proposal) 424 if err != nil { 425 return fmt.Errorf("unable to get pub key. [%s]", err) 426 } 427 pubBytes := make([]byte, len(senderPubKey)) 428 copy(pubBytes,senderPubKey) 429 stub.SenderPubKey = string(pubBytes) 430 } 431 432 return nil 433 } 434 435 // GetTxID returns the transaction ID 436 func (stub *ChaincodeStub) GetTxID() string { 437 return stub.TxID 438 } 439 440 // --------- Security functions ---------- 441 //CHAINCODE SEC INTERFACE FUNCS TOBE IMPLEMENTED BY ANGELO 442 443 // ------------- Call Chaincode functions --------------- 444 445 // InvokeChaincode documentation can be found in interfaces.go 446 func (stub *ChaincodeStub) InvokeChaincode(chaincodeName string, args [][]byte, channel string) pb.Response { 447 // Internally we handle chaincode name as a composite name 448 if channel != "" { 449 chaincodeName = chaincodeName + "/" + channel 450 } 451 return stub.handler.handleInvokeChaincode(chaincodeName, args, stub.TxID) 452 } 453 454 // --------- State functions ---------- 455 456 // GetState documentation can be found in interfaces.go 457 func (stub *ChaincodeStub) GetState(key string) ([]byte, error) { 458 return stub.handler.handleGetState(key, stub.TxID) 459 } 460 461 // PutState documentation can be found in interfaces.go 462 func (stub *ChaincodeStub) PutState(key string, value []byte) error { 463 if key == "" { 464 return fmt.Errorf("key must not be an empty string") 465 } 466 return stub.handler.handlePutState(key, value, stub.TxID) 467 } 468 469 // DelState documentation can be found in interfaces.go 470 func (stub *ChaincodeStub) DelState(key string) error { 471 return stub.handler.handleDelState(key, stub.TxID) 472 } 473 474 // CommonIterator documentation can be found in interfaces.go 475 type CommonIterator struct { 476 handler *Handler 477 uuid string 478 response *pb.QueryResponse 479 currentLoc int 480 } 481 482 // StateQueryIterator documentation can be found in interfaces.go 483 type StateQueryIterator struct { 484 *CommonIterator 485 } 486 487 // HistoryQueryIterator documentation can be found in interfaces.go 488 type HistoryQueryIterator struct { 489 *CommonIterator 490 } 491 492 type resultType uint8 493 494 const ( 495 STATE_QUERY_RESULT resultType = iota + 1 496 HISTORY_QUERY_RESULT 497 ) 498 499 func (stub *ChaincodeStub) handleGetStateByRange(startKey, endKey string) (StateQueryIteratorInterface, error) { 500 response, err := stub.handler.handleGetStateByRange(startKey, endKey, stub.TxID) 501 if err != nil { 502 return nil, err 503 } 504 return &StateQueryIterator{CommonIterator: &CommonIterator{stub.handler, stub.TxID, response, 0}}, nil 505 } 506 507 // GetStateByRange documentation can be found in interfaces.go 508 func (stub *ChaincodeStub) GetStateByRange(startKey, endKey string) (StateQueryIteratorInterface, error) { 509 if startKey == "" { 510 startKey = emptyKeySubstitute 511 } 512 if err := validateSimpleKeys(startKey, endKey); err != nil { 513 return nil, err 514 } 515 return stub.handleGetStateByRange(startKey, endKey) 516 } 517 518 // GetQueryResult documentation can be found in interfaces.go 519 func (stub *ChaincodeStub) GetQueryResult(query string) (StateQueryIteratorInterface, error) { 520 response, err := stub.handler.handleGetQueryResult(query, stub.TxID) 521 if err != nil { 522 return nil, err 523 } 524 return &StateQueryIterator{CommonIterator: &CommonIterator{stub.handler, stub.TxID, response, 0}}, nil 525 } 526 527 // GetHistoryForKey documentation can be found in interfaces.go 528 func (stub *ChaincodeStub) GetHistoryForKey(key string) (HistoryQueryIteratorInterface, error) { 529 response, err := stub.handler.handleGetHistoryForKey(key, stub.TxID) 530 if err != nil { 531 return nil, err 532 } 533 return &HistoryQueryIterator{CommonIterator: &CommonIterator{stub.handler, stub.TxID, response, 0}}, nil 534 } 535 536 //CreateCompositeKey documentation can be found in interfaces.go 537 func (stub *ChaincodeStub) CreateCompositeKey(objectType string, attributes []string) (string, error) { 538 return createCompositeKey(objectType, attributes) 539 } 540 541 //SplitCompositeKey documentation can be found in interfaces.go 542 func (stub *ChaincodeStub) SplitCompositeKey(compositeKey string) (string, []string, error) { 543 return splitCompositeKey(compositeKey) 544 } 545 546 func createCompositeKey(objectType string, attributes []string) (string, error) { 547 if err := validateCompositeKeyAttribute(objectType); err != nil { 548 return "", err 549 } 550 ck := compositeKeyNamespace + objectType + string(minUnicodeRuneValue) 551 for _, att := range attributes { 552 if err := validateCompositeKeyAttribute(att); err != nil { 553 return "", err 554 } 555 ck += att + string(minUnicodeRuneValue) 556 } 557 return ck, nil 558 } 559 560 func splitCompositeKey(compositeKey string) (string, []string, error) { 561 componentIndex := 1 562 components := []string{} 563 for i := 1; i < len(compositeKey); i++ { 564 if compositeKey[i] == minUnicodeRuneValue { 565 components = append(components, compositeKey[componentIndex:i]) 566 componentIndex = i + 1 567 } 568 } 569 return components[0], components[1:], nil 570 } 571 572 func validateCompositeKeyAttribute(str string) error { 573 if !utf8.ValidString(str) { 574 return fmt.Errorf("Not a valid utf8 string: [%x]", str) 575 } 576 for index, runeValue := range str { 577 if runeValue == minUnicodeRuneValue || runeValue == maxUnicodeRuneValue { 578 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`, 579 runeValue, index, minUnicodeRuneValue, maxUnicodeRuneValue) 580 } 581 } 582 return nil 583 } 584 585 //To ensure that simple keys do not go into composite key namespace, 586 //we validate simplekey to check whether the key starts with 0x00 (which 587 //is the namespace for compositeKey). This helps in avoding simple/composite 588 //key collisions. 589 func validateSimpleKeys(simpleKeys ...string) error { 590 for _, key := range simpleKeys { 591 if len(key) > 0 && key[0] == compositeKeyNamespace[0] { 592 return fmt.Errorf(`First character of the key [%s] contains a null character which is not allowed`, key) 593 } 594 } 595 return nil 596 } 597 598 //GetStateByPartialCompositeKey function can be invoked by a chaincode to query the 599 //state based on a given partial composite key. This function returns an 600 //iterator which can be used to iterate over all composite keys whose prefix 601 //matches the given partial composite key. This function should be used only for 602 //a partial composite key. For a full composite key, an iter with empty response 603 //would be returned. 604 func (stub *ChaincodeStub) GetStateByPartialCompositeKey(objectType string, attributes []string) (StateQueryIteratorInterface, error) { 605 if partialCompositeKey, err := stub.CreateCompositeKey(objectType, attributes); err == nil { 606 return stub.handleGetStateByRange(partialCompositeKey, partialCompositeKey+string(maxUnicodeRuneValue)) 607 } else { 608 return nil, err 609 } 610 } 611 612 func (iter *StateQueryIterator) Next() (*queryresult.KV, error) { 613 if result, err := iter.nextResult(STATE_QUERY_RESULT); err == nil { 614 return result.(*queryresult.KV), err 615 } else { 616 return nil, err 617 } 618 } 619 620 func (iter *HistoryQueryIterator) Next() (*queryresult.KeyModification, error) { 621 if result, err := iter.nextResult(HISTORY_QUERY_RESULT); err == nil { 622 return result.(*queryresult.KeyModification), err 623 } else { 624 return nil, err 625 } 626 } 627 628 // HasNext documentation can be found in interfaces.go 629 func (iter *CommonIterator) HasNext() bool { 630 if iter.currentLoc < len(iter.response.Results) || iter.response.HasMore { 631 return true 632 } 633 return false 634 } 635 636 // getResultsFromBytes deserializes QueryResult and return either a KV struct 637 // or KeyModification depending on the result type (i.e., state (range/execute) 638 // query, history query). Note that commonledger.QueryResult is an empty golang 639 // interface that can hold values of any type. 640 func (iter *CommonIterator) getResultFromBytes(queryResultBytes *pb.QueryResultBytes, 641 rType resultType) (commonledger.QueryResult, error) { 642 643 if rType == STATE_QUERY_RESULT { 644 stateQueryResult := &queryresult.KV{} 645 if err := proto.Unmarshal(queryResultBytes.ResultBytes, stateQueryResult); err != nil { 646 return nil, err 647 } 648 return stateQueryResult, nil 649 650 } else if rType == HISTORY_QUERY_RESULT { 651 historyQueryResult := &queryresult.KeyModification{} 652 if err := proto.Unmarshal(queryResultBytes.ResultBytes, historyQueryResult); err != nil { 653 return nil, err 654 } 655 return historyQueryResult, nil 656 } 657 return nil, errors.New("Wrong result type") 658 } 659 660 func (iter *CommonIterator) fetchNextQueryResult() error { 661 if response, err := iter.handler.handleQueryStateNext(iter.response.Id, iter.uuid); err == nil { 662 iter.currentLoc = 0 663 iter.response = response 664 return nil 665 } else { 666 return err 667 } 668 } 669 670 // nextResult returns the next QueryResult (i.e., either a KV struct or KeyModification) 671 // from the state or history query iterator. Note that commonledger.QueryResult is an 672 // empty golang interface that can hold values of any type. 673 func (iter *CommonIterator) nextResult(rType resultType) (commonledger.QueryResult, error) { 674 if iter.currentLoc < len(iter.response.Results) { 675 // On valid access of an element from cached results 676 queryResult, err := iter.getResultFromBytes(iter.response.Results[iter.currentLoc], rType) 677 if err != nil { 678 chaincodeLogger.Errorf("Failed to decode query results [%s]", err) 679 return nil, err 680 } 681 iter.currentLoc++ 682 683 if iter.currentLoc == len(iter.response.Results) && iter.response.HasMore { 684 // On access of last item, pre-fetch to update HasMore flag 685 if err = iter.fetchNextQueryResult(); err != nil { 686 chaincodeLogger.Errorf("Failed to fetch next results [%s]", err) 687 return nil, err 688 } 689 } 690 691 return queryResult, err 692 } else if !iter.response.HasMore { 693 // On call to Next() without check of HasMore 694 return nil, errors.New("No such key") 695 } 696 697 // should not fall through here 698 // case: no cached results but HasMore is true. 699 return nil, errors.New("Invalid iterator state") 700 } 701 702 // Close documentation can be found in interfaces.go 703 func (iter *CommonIterator) Close() error { 704 _, err := iter.handler.handleQueryStateClose(iter.response.Id, iter.uuid) 705 return err 706 } 707 708 // GetArgs documentation can be found in interfaces.go 709 func (stub *ChaincodeStub) GetArgs() [][]byte { 710 return stub.args 711 } 712 713 // GetStringArgs documentation can be found in interfaces.go 714 func (stub *ChaincodeStub) GetStringArgs() []string { 715 args := stub.GetArgs() 716 strargs := make([]string, 0, len(args)) 717 for _, barg := range args { 718 strargs = append(strargs, string(barg)) 719 } 720 return strargs 721 } 722 723 // GetFunctionAndParameters documentation can be found in interfaces.go 724 func (stub *ChaincodeStub) GetFunctionAndParameters() (function string, params []string) { 725 allargs := stub.GetStringArgs() 726 function = "" 727 params = []string{} 728 if len(allargs) >= 1 { 729 function = allargs[0] 730 params = allargs[1:] 731 } 732 return 733 } 734 735 // GetCreator documentation can be found in interfaces.go 736 func (stub *ChaincodeStub) GetCreator() ([]byte, error) { 737 return stub.creator, nil 738 } 739 740 // GetTransient documentation can be found in interfaces.go 741 func (stub *ChaincodeStub) GetTransient() (map[string][]byte, error) { 742 return stub.transient, nil 743 } 744 745 // GetBinding documentation can be found in interfaces.go 746 func (stub *ChaincodeStub) GetBinding() ([]byte, error) { 747 return stub.binding, nil 748 } 749 750 // GetSignedProposal documentation can be found in interfaces.go 751 func (stub *ChaincodeStub) GetSignedProposal() (*pb.SignedProposal, error) { 752 return stub.signedProposal, nil 753 } 754 755 // GetArgsSlice documentation can be found in interfaces.go 756 func (stub *ChaincodeStub) GetArgsSlice() ([]byte, error) { 757 args := stub.GetArgs() 758 res := []byte{} 759 for _, barg := range args { 760 res = append(res, barg...) 761 } 762 return res, nil 763 } 764 765 // GetTxTimestamp documentation can be found in interfaces.go 766 func (stub *ChaincodeStub) GetTxTimestamp() (*timestamp.Timestamp, error) { 767 hdr, err := utils.GetHeader(stub.proposal.Header) 768 if err != nil { 769 return nil, err 770 } 771 chdr, err := utils.UnmarshalChannelHeader(hdr.ChannelHeader) 772 if err != nil { 773 return nil, err 774 } 775 776 return chdr.GetTimestamp(), nil 777 } 778 779 // ------------- ChaincodeEvent API ---------------------- 780 781 // SetEvent documentation can be found in interfaces.go 782 func (stub *ChaincodeStub) SetEvent(name string, payload []byte) error { 783 if name == "" { 784 return errors.New("Event name can not be nil string.") 785 } 786 stub.chaincodeEvent = &pb.ChaincodeEvent{EventName: name, Payload: payload} 787 return nil 788 } 789 790 // ------------- inkchain wallet ---------------------- 791 func (stub *ChaincodeStub) Transfer(to string, balanceType string, amount *big.Int) error { 792 if to == "" || len(to) != wallet.AddressStringLength { 793 return fmt.Errorf(".invalid address length.") 794 } 795 if amount.Cmp(big.NewInt(0)) < 0 { 796 return fmt.Errorf(".transfer amount should be a half-positive number.") 797 } 798 to = strings.ToLower(to) 799 addr := wallet.StringToAddress(to) 800 if addr == nil { 801 return fmt.Errorf("must be valid address") 802 } 803 tran := &kvtranset.KVTrans{} 804 tran.To = to 805 tran.BalanceType = balanceType 806 tran.Amount = amount.Bytes() 807 var tranSet []*kvtranset.KVTrans 808 tranSet = append(tranSet, tran) 809 kvTranSet := &kvtranset.KVTranSet{Trans: tranSet} 810 return stub.handler.handleTransfer(kvTranSet, stub.TxID) 811 } 812 813 func (stub *ChaincodeStub) GetAccount(address string) (*wallet.Account, error) { 814 if address == "" || len(address) != wallet.AddressStringLength { 815 return nil, fmt.Errorf("invalid address length") 816 } 817 address = strings.ToLower(address) 818 addr := wallet.StringToAddress(address) 819 if addr == nil { 820 return nil, fmt.Errorf("must be valid address") 821 } 822 return stub.handler.handleGetAccount(address, stub.TxID) 823 } 824 825 // PutState documentation can be found in interfaces.go 826 func (stub *ChaincodeStub) IssueToken(address string, balanceType string, amount *big.Int) error { 827 if address == "" || len(address) != wallet.AddressStringLength { 828 return fmt.Errorf("invalid address length") 829 } 830 address = strings.ToLower(address) 831 addr := wallet.StringToAddress(address) 832 if addr == nil { 833 return fmt.Errorf("must be valid address") 834 } 835 return stub.handler.handleIssueToken(address, balanceType, amount, stub.TxID) 836 } 837 838 func (stub *ChaincodeStub) GetSender() (string, error) { 839 return stub.Sender, nil 840 } 841 842 func (stub *ChaincodeStub) GetSenderPubKey() (string, error) { 843 return stub.SenderPubKey, nil 844 } 845 846 847 //calc fee for the invoke function 848 func (stub *ChaincodeStub) CalcFeeByInvoke() (*big.Int, error) { 849 msg, err := stub.getSenderMsg(stub.proposal) 850 if err != nil { 851 return nil, err 852 } 853 content := msg 854 return stub.handler.handleCalcFee(content, stub.TxID) 855 } 856 857 //calc fee by passed paramaters 858 func (stub *ChaincodeStub) CalcFee(content string) (*big.Int, error) { 859 return stub.handler.handleCalcFee(content, stub.TxID) 860 } 861 862 func (stub *ChaincodeStub) MultiTransfer(trans *kvtranset.KVTranSet) error { 863 return stub.handler.handleTransfer(trans, stub.TxID) 864 } 865 866 //sign data 867 func (stub *ChaincodeStub) Sign(data []byte) (sign string, err error) { 868 return stub.handler.handleSign(data, stub.TxID) 869 } 870 871 //verify signature from Sign 872 func (stub *ChaincodeStub) Verify(sign string, data []byte, address string) (result bool, err error) { 873 if data == nil || len(data) <= 0 { 874 return false, fmt.Errorf("data must not be empty") 875 } 876 if len(strings.TrimSpace(sign)) <= 0 { 877 return false, fmt.Errorf("signature must be none-empty string") 878 } 879 if len(strings.TrimSpace(address)) <= 0 { 880 return false, fmt.Errorf("address must be none-empty string") 881 } 882 return stub.handler.handleVerify(sign, data,address, stub.TxID) 883 } 884 885 // ------------- Logging Control and Chaincode Loggers --------------- 886 887 // As independent programs, Go language chaincodes can use any logging 888 // methodology they choose, from simple fmt.Printf() to os.Stdout, to 889 // decorated logs created by the author's favorite logging package. The 890 // chaincode "shim" interface, however, is defined by the inkchain inkchain 891 // and implements its own logging methodology. This methodology currently 892 // includes severity-based logging control and a standard way of decorating 893 // the logs. 894 // 895 // The facilities defined here allow a Go language chaincode to control the 896 // logging level of its shim, and to create its own logs formatted 897 // consistently with, and temporally interleaved with the shim logs without 898 // any knowledge of the underlying implementation of the shim, and without any 899 // other package requirements. The lack of package requirements is especially 900 // important because even if the chaincode happened to explicitly use the same 901 // logging package as the shim, unless the chaincode is physically included as 902 // part of the inkchain inkchain source code tree it could actually end up 903 // using a distinct binary instance of the logging package, with different 904 // formats and severity levels than the binary package used by the shim. 905 // 906 // Another approach that might have been taken, and could potentially be taken 907 // in the future, would be for the chaincode to supply a logging object for 908 // the shim to use, rather than the other way around as implemented 909 // here. There would be some complexities associated with that approach, so 910 // for the moment we have chosen the simpler implementation below. The shim 911 // provides one or more abstract logging objects for the chaincode to use via 912 // the NewLogger() API, and allows the chaincode to control the severity level 913 // of shim logs using the SetLoggingLevel() API. 914 915 // LoggingLevel is an enumerated type of severity levels that control 916 // chaincode logging. 917 type LoggingLevel logging.Level 918 919 // These constants comprise the LoggingLevel enumeration 920 const ( 921 LogDebug = LoggingLevel(logging.DEBUG) 922 LogInfo = LoggingLevel(logging.INFO) 923 LogNotice = LoggingLevel(logging.NOTICE) 924 LogWarning = LoggingLevel(logging.WARNING) 925 LogError = LoggingLevel(logging.ERROR) 926 LogCritical = LoggingLevel(logging.CRITICAL) 927 ) 928 929 var shimLoggingLevel = LogInfo // Necessary for correct initialization; See Start() 930 931 // SetLoggingLevel allows a Go language chaincode to set the logging level of 932 // its shim. 933 func SetLoggingLevel(level LoggingLevel) { 934 shimLoggingLevel = level 935 logging.SetLevel(logging.Level(level), "shim") 936 } 937 938 // LogLevel converts a case-insensitive string chosen from CRITICAL, ERROR, 939 // WARNING, NOTICE, INFO or DEBUG into an element of the LoggingLevel 940 // type. In the event of errors the level returned is LogError. 941 func LogLevel(levelString string) (LoggingLevel, error) { 942 l, err := logging.LogLevel(levelString) 943 level := LoggingLevel(l) 944 if err != nil { 945 level = LogError 946 } 947 return level, err 948 } 949 950 // ------------- Chaincode Loggers --------------- 951 952 // ChaincodeLogger is an abstraction of a logging object for use by 953 // chaincodes. These objects are created by the NewLogger API. 954 type ChaincodeLogger struct { 955 logger *logging.Logger 956 } 957 958 // NewLogger allows a Go language chaincode to create one or more logging 959 // objects whose logs will be formatted consistently with, and temporally 960 // interleaved with the logs created by the shim interface. The logs created 961 // by this object can be distinguished from shim logs by the name provided, 962 // which will appear in the logs. 963 func NewLogger(name string) *ChaincodeLogger { 964 return &ChaincodeLogger{logging.MustGetLogger(name)} 965 } 966 967 // SetLevel sets the logging level for a chaincode logger. Note that currently 968 // the levels are actually controlled by the name given when the logger is 969 // created, so loggers should be given unique names other than "shim". 970 func (c *ChaincodeLogger) SetLevel(level LoggingLevel) { 971 logging.SetLevel(logging.Level(level), c.logger.Module) 972 } 973 974 // IsEnabledFor returns true if the logger is enabled to creates logs at the 975 // given logging level. 976 func (c *ChaincodeLogger) IsEnabledFor(level LoggingLevel) bool { 977 return c.logger.IsEnabledFor(logging.Level(level)) 978 } 979 980 // Debug logs will only appear if the ChaincodeLogger LoggingLevel is set to 981 // LogDebug. 982 func (c *ChaincodeLogger) Debug(args ...interface{}) { 983 c.logger.Debug(args...) 984 } 985 986 // Info logs will appear if the ChaincodeLogger LoggingLevel is set to 987 // LogInfo or LogDebug. 988 func (c *ChaincodeLogger) Info(args ...interface{}) { 989 c.logger.Info(args...) 990 } 991 992 // Notice logs will appear if the ChaincodeLogger LoggingLevel is set to 993 // LogNotice, LogInfo or LogDebug. 994 func (c *ChaincodeLogger) Notice(args ...interface{}) { 995 c.logger.Notice(args...) 996 } 997 998 // Warning logs will appear if the ChaincodeLogger LoggingLevel is set to 999 // LogWarning, LogNotice, LogInfo or LogDebug. 1000 func (c *ChaincodeLogger) Warning(args ...interface{}) { 1001 c.logger.Warning(args...) 1002 } 1003 1004 // Error logs will appear if the ChaincodeLogger LoggingLevel is set to 1005 // LogError, LogWarning, LogNotice, LogInfo or LogDebug. 1006 func (c *ChaincodeLogger) Error(args ...interface{}) { 1007 c.logger.Error(args...) 1008 } 1009 1010 // Critical logs always appear; They can not be disabled. 1011 func (c *ChaincodeLogger) Critical(args ...interface{}) { 1012 c.logger.Critical(args...) 1013 } 1014 1015 // Debugf logs will only appear if the ChaincodeLogger LoggingLevel is set to 1016 // LogDebug. 1017 func (c *ChaincodeLogger) Debugf(format string, args ...interface{}) { 1018 c.logger.Debugf(format, args...) 1019 } 1020 1021 // Infof logs will appear if the ChaincodeLogger LoggingLevel is set to 1022 // LogInfo or LogDebug. 1023 func (c *ChaincodeLogger) Infof(format string, args ...interface{}) { 1024 c.logger.Infof(format, args...) 1025 } 1026 1027 // Noticef logs will appear if the ChaincodeLogger LoggingLevel is set to 1028 // LogNotice, LogInfo or LogDebug. 1029 func (c *ChaincodeLogger) Noticef(format string, args ...interface{}) { 1030 c.logger.Noticef(format, args...) 1031 } 1032 1033 // Warningf logs will appear if the ChaincodeLogger LoggingLevel is set to 1034 // LogWarning, LogNotice, LogInfo or LogDebug. 1035 func (c *ChaincodeLogger) Warningf(format string, args ...interface{}) { 1036 c.logger.Warningf(format, args...) 1037 } 1038 1039 // Errorf logs will appear if the ChaincodeLogger LoggingLevel is set to 1040 // LogError, LogWarning, LogNotice, LogInfo or LogDebug. 1041 func (c *ChaincodeLogger) Errorf(format string, args ...interface{}) { 1042 c.logger.Errorf(format, args...) 1043 } 1044 1045 // Criticalf logs always appear; They can not be disabled. 1046 func (c *ChaincodeLogger) Criticalf(format string, args ...interface{}) { 1047 c.logger.Criticalf(format, args...) 1048 }