@@ -25,6 +25,8 @@ var grpc = require('grpc');
25
25
26
26
var _ccProto = grpc . load ( __dirname + '/protos/chaincode.proto' ) . protos ;
27
27
var _ccProposalProto = grpc . load ( __dirname + '/protos/chaincode_proposal.proto' ) . protos ;
28
+ var _ccTransProto = grpc . load ( __dirname + '/protos/chaincode_transaction.proto' ) . protos ;
29
+ var _transProto = grpc . load ( __dirname + '/protos/fabric_transaction.proto' ) . protos ;
28
30
var _headerProto = grpc . load ( __dirname + '/protos/fabric_transaction_header.proto' ) . protos ;
29
31
var _proposalProto = grpc . load ( __dirname + '/protos/fabric_proposal.proto' ) . protos ;
30
32
var _responseProto = grpc . load ( __dirname + '/protos/fabric_proposal_response.proto' ) . protos ;
@@ -332,54 +334,82 @@ var Member = class {
332
334
333
335
/**
334
336
* Sends the orderer an endorsed proposal.
337
+ * The caller must use the proposal response returned from the endorser along
338
+ * with the original proposal request sent to the endorser.
335
339
*
336
- * @param {Object } request An object containing the data:
337
- * TODO explain data object
338
- * @returns Promise for the sendTransaction
340
+ * @param {ProposalResponse } proposalResponse - A ProposalResponse object containing
341
+ * the response from the endorsement (see fabric_proposal_response.proto)
342
+ * @param {Proposal } chaincodeProposal - A Proposal object containing the original
343
+ * request for endorsement (see fabric_proposal.proto)
344
+ * @returns Promise for an acknowledgement from the orderer of successfully submitted transaction
339
345
*/
340
- sendTransaction ( data ) {
346
+ sendTransaction ( proposalResponse , chaincodeProposal ) {
347
+ logger . debug ( 'Member.sendTransaction - start :: chain ' + this . _chain ) ;
348
+
341
349
// Verify that data is being passed in
342
- if ( ! data ) {
343
- logger . error ( 'Member.sendTransaction - input data missing' ) ;
344
- return Promise . reject ( new Error ( 'missing data in broadcast request' ) ) ;
350
+ if ( ! proposalResponse ) {
351
+ logger . error ( 'Member.sendTransaction - input proposalResponse missing' ) ;
352
+ return Promise . reject ( new Error ( 'Missing proposalResponse object parameter' ) ) ;
353
+ }
354
+ if ( ! chaincodeProposal ) {
355
+ logger . error ( 'Member.sendTransaction - input chaincodeProposal missing' ) ;
356
+ return Promise . reject ( new Error ( 'Missing chaincodeProposal object parameter' ) ) ;
345
357
}
346
358
// verify that we have an orderer configured
347
359
if ( ! this . _chain . getOrderer ( ) ) {
348
360
logger . error ( 'Member.sendTransaction - no orderer defined' ) ;
349
361
return Promise . reject ( new Error ( 'no Orderer defined' ) ) ;
350
362
}
351
363
352
- logger . debug ( 'Member.sendTransaction - chain ::' + this . _chain ) ;
364
+ //logger.debug('Member.sendTransaction - proposalResponse %j', proposalResponse);
365
+ //logger.debug('Member.sendTransaction - chaincodePropsoal %j', chaincodeProposal);
366
+
367
+ var endorsements = [ ] ;
368
+ endorsements . push ( proposalResponse . endorsement ) ;
369
+ var chaincodeEndorsedAction = new _ccTransProto . ChaincodeEndorsedAction ( ) ;
370
+ chaincodeEndorsedAction . setProposalResponsePayload ( proposalResponse . payload ) ;
371
+ chaincodeEndorsedAction . setEndorsements ( endorsements ) ;
372
+
373
+ var chaincodeActionPayload = new _ccTransProto . ChaincodeActionPayload ( ) ;
374
+ chaincodeActionPayload . setAction ( chaincodeEndorsedAction ) ;
375
+ chaincodeActionPayload . setChaincodeProposalPayload ( chaincodeProposal . payload ) ;
376
+
377
+ var transactionAction = new _transProto . TransactionAction ( ) ;
378
+ transactionAction . setHeader ( chaincodeProposal . header ) ;
379
+ transactionAction . setPayload ( chaincodeActionPayload . toBuffer ( ) ) ;
380
+
381
+ var transaction2 = new _transProto . Transaction2 ( ) ;
382
+ var actions = [ ] ;
383
+ actions . push ( transactionAction ) ;
384
+ transaction2 . setActions ( actions ) ;
353
385
354
386
var orderer = this . _chain . getOrderer ( ) ;
355
- return orderer . sendBroadcast ( data ) ;
387
+ return orderer . sendBroadcast ( transaction2 . toBuffer ( ) ) ;
356
388
}
357
389
358
390
/**
359
391
* Sends a deployment proposal to an endorser.
360
392
*
361
393
* @param {Object } request An object containing the following fields:
362
- * endorserUrl: Peer URL
394
+ * target : Endorsing Peer Object
363
395
* chaincodePath : String
364
396
* fcn : String
365
397
* args : Strings
366
398
* @returns Promise for a ProposalResponse
367
399
*/
368
400
sendDeploymentProposal ( request ) {
369
- if ( ! request . endorserUrl || request . endorserUrl === '' ) {
370
- logger . error ( 'Invalid input parameter to "sendDeploymentProposal": must have "endorserUrl"' ) ;
371
- return Promise . reject ( new Error ( 'missing endorserUrl in Deployment proposal request' ) ) ;
372
- }
373
-
401
+ // Verify that chaincodePath is being passed
374
402
if ( ! request . chaincodePath || request . chaincodePath === '' ) {
375
403
logger . error ( 'Invalid input parameter to "sendDeploymentProposal": must have "chaincodePath"' ) ;
376
404
return Promise . reject ( new Error ( 'missing chaincodePath in Deployment proposal request' ) ) ;
377
405
}
378
-
379
- if ( ! request . fcn || request . fnc === '' ) {
380
- logger . error ( 'Invalid input parameter to "sendDeploymentProposal": must have "fcn" for the target function to call during chaincode initialization ' ) ;
381
- return Promise . reject ( new Error ( 'missing fcn in Deployment proposal request' ) ) ;
406
+ // verify that the caller has included a peer object
407
+ if ( ! request . target ) {
408
+ logger . error ( 'Invalid input parameter to "sendDeploymentProposal": must have "target" object ' ) ;
409
+ return Promise . reject ( new Error ( 'Missing "target" for the endorsing peer object in the Deployment proposal request' ) ) ;
382
410
}
411
+ let peer = request . target ;
412
+ var chaincode_id ;
383
413
384
414
// args is optional because some chaincode may not need any input parameters during initialization
385
415
if ( ! request . args ) {
@@ -391,6 +421,7 @@ var Member = class {
391
421
function ( data ) {
392
422
var targzFilePath = data [ 0 ] ;
393
423
var hash = data [ 1 ] ;
424
+ chaincode_id = hash ;
394
425
395
426
logger . debug ( 'Successfully generated chaincode deploy archive and name hash (%s)' , hash ) ;
396
427
@@ -455,11 +486,11 @@ var Member = class {
455
486
payload : payload . toBuffer ( )
456
487
} ;
457
488
458
- let peer = new Peer ( request . endorserUrl ) ;
459
489
return peer . sendProposal ( proposal )
460
490
. then (
461
- function ( data ) {
462
- resolve ( data ) ;
491
+ function ( response ) {
492
+ response . chaincodeId = chaincode_id ;
493
+ resolve ( [ response , proposal ] ) ;
463
494
}
464
495
) ;
465
496
}
@@ -468,6 +499,128 @@ var Member = class {
468
499
}
469
500
) . catch (
470
501
function ( err ) {
502
+ logger . error ( 'Failed Deployment Proposal. Error: %s' , err . stack ? err . stack : err ) ;
503
+ return Promise . reject ( err ) ;
504
+ }
505
+ ) ;
506
+ }
507
+
508
+ /**
509
+ * Sends a transaction proposal to an endorsing peer.
510
+ *
511
+ * @param {Object } request:
512
+ * target : {Object} Endorsing Peer object as the target of the request
513
+ * chaincodeId : {String} The id of the chaincode to perform the transaction proposal
514
+ * args : {Array} Arguments specific to the chaincode 'innvoke'
515
+ * @returns Promise for a ProposalResponse
516
+ */
517
+ sendTransactionProposal ( request ) {
518
+ logger . debug ( 'Member.sendTransactionProposal - start' ) ;
519
+
520
+ // verify that the caller has included a peer object
521
+ if ( ! request . target ) {
522
+ logger . error ( 'Missing "target" endorser peer object in the Transaction proposal request' ) ;
523
+ return Promise . reject ( new Error ( 'Missing "target" for endorser peer object in the Transaction proposal request' ) ) ;
524
+ }
525
+
526
+ if ( ! request . chaincodeId ) {
527
+ logger . error ( 'Missing chaincode ID in the Transaction proposal request' ) ;
528
+ return Promise . reject ( new Error ( 'Missing chaincode ID in the Transaction proposal request' ) ) ;
529
+ }
530
+
531
+ // args is not optional because we need for transaction to execute
532
+ if ( ! request . args ) {
533
+ logger . error ( 'Missing arguments in Transaction proposal request' ) ;
534
+ return Promise . reject ( new Error ( 'Missing arguments in Transaction proposal request' ) ) ;
535
+ }
536
+
537
+ var args = [ ] ;
538
+ // leaving this for now... but this call is always an invoke and we are not telling caller to include 'fcn' any longer
539
+ args . push ( Buffer . from ( request . fcn ? request . fcn : 'invoke' , 'utf8' ) ) ;
540
+ logger . debug ( 'Member.sendTransactionProposal - adding function arg:%s' , request . fcn ? request . fcn : 'invoke' ) ;
541
+
542
+ for ( let i = 0 ; i < request . args . length ; i ++ ) {
543
+ args . push ( Buffer . from ( request . args [ i ] , 'utf8' ) ) ;
544
+ logger . debug ( 'Member.sendTransactionProposal - adding arg:%s' , request . args [ i ] ) ;
545
+ }
546
+
547
+ let invokeSpec = {
548
+ type : _ccProto . ChaincodeSpec . Type . GOLANG ,
549
+ chaincodeID : {
550
+ name : request . chaincodeId
551
+ } ,
552
+ ctorMsg : {
553
+ args : args
554
+ }
555
+ } ;
556
+
557
+ // construct the ChaincodeInvocationSpec
558
+ let cciSpec = new _ccProto . ChaincodeInvocationSpec ( ) ;
559
+ cciSpec . setChaincodeSpec ( invokeSpec ) ;
560
+ cciSpec . setIdGenerationAlg ( '' ) ;
561
+
562
+ // construct the enveloping Proposal object
563
+ // - the header part of the proposal
564
+ let headerExt = new _ccProposalProto . ChaincodeHeaderExtension ( ) ;
565
+ let header = new _headerProto . Header ( ) ;
566
+ header . setType ( _headerProto . Header . Type . CHAINCODE ) ;
567
+ header . setExtensions ( headerExt . toBuffer ( ) ) ;
568
+ //header.setChainID()
569
+
570
+ // - the payload part of the proposal for chaincode deploy is ChaincodeProposalPayload
571
+ let payload = new _ccProposalProto . ChaincodeProposalPayload ( ) ;
572
+ payload . setInput ( cciSpec . toBuffer ( ) ) ;
573
+
574
+ let proposal = {
575
+ header : header . toBuffer ( ) ,
576
+ payload : payload . toBuffer ( )
577
+ } ;
578
+
579
+ let peer = request . target ;
580
+ return peer . sendProposal ( proposal )
581
+ . then (
582
+ function ( response ) {
583
+ return Promise . resolve ( [ response , proposal ] ) ;
584
+ }
585
+ ) . catch (
586
+ function ( err ) {
587
+ logger . error ( 'Failed Transaction Proposal. Error: %s' , err . stack ? err . stack : err ) ;
588
+ return Promise . reject ( err ) ;
589
+ }
590
+ ) ;
591
+ }
592
+
593
+ /**
594
+ * Sends a proposal to an endorsing peer that will be handled by the chaincode.
595
+ * This request will be presented to the chaincode 'invoke' and must understand
596
+ * from the arguments that this is a query request. The chaincode must also return
597
+ * results in the byte array format and the caller will have to be able to decode
598
+ * these results
599
+ *
600
+ * @param {Object } request:
601
+ * target : {Object} Endorsing Peer object as the target of the request
602
+ * chaincodeId : {String} The id of the chaincode to perform the query
603
+ * args : {Array} Arguments for the 'invoke' function call on the chaincode
604
+ * that represent a query invocation
605
+ * @returns Promise for a byte array results from the chaincode
606
+ */
607
+ queryByChaincode ( request ) {
608
+ logger . debug ( 'Member.sendQueryProposal - start' ) ;
609
+
610
+ return this . sendTransactionProposal ( request )
611
+ . then (
612
+ function ( results ) {
613
+ var response = results [ 0 ] ;
614
+ var proposal = results [ 1 ] ;
615
+ logger . debug ( 'Member-sendQueryProposal - response %j' , response ) ;
616
+ if ( response . response && response . response . payload ) {
617
+ return Promise . resolve ( response . response . payload ) ;
618
+ }
619
+ return Promise . reject ( new Error ( 'Payload results are missing from the chaincode query' ) ) ;
620
+ }
621
+ ) . catch (
622
+ function ( err ) {
623
+ logger . error ( 'Failed Query by chaincode. Error: %s' , err . stack ? err . stack : err ) ;
471
624
return Promise . reject ( err ) ;
472
625
}
473
626
) ;
@@ -553,6 +706,7 @@ function packageChaincode(chaincodePath, fcn, args) {
553
706
}
554
707
) . catch (
555
708
function ( err ) {
709
+ logger . error ( 'Failed to build chaincode package: %s' , err . stack ? err . stack : err ) ;
556
710
reject ( err ) ;
557
711
}
558
712
) ;
0 commit comments