src/fabric/e2eUtils.js
/**
 * Submit a transaction to the given chaincode with the specified options.
 * @param {object} context The Fabric context.
 * @param {string} id The name of the chaincode.
 * @param {string} version The version of the chaincode.
 * @param {string[]} args The arguments to pass to the chaincode.
 * @param {number} timeout The timeout for the transaction invocation.
 * @return {Promise<TxStatus>} The result and stats of the transaction invocation.
 */
Submit a transaction to the given chaincode with the specified options.
@param {object} context The Fabric context.
@param {string} id The name of the chaincode.
@param {string} version The version of the chaincode.
@param {string[]} args The arguments to pass to the chaincode.
@param {number} timeout The timeout for the transaction invocation.
@return {Promise} The result and stats of the transaction invocation.
Submit a transaction to the given chaincode with the specified options . @param { object } context The Fabric context . @param { string } id The name of the chaincode . @param { string } version The version of the chaincode . @param { string [] } args The arguments to pass to the chaincode . @param { number } timeout The timeout for the transaction invocation . @return { Promise } The result and stats of the transaction invocation .
async function invokebycontext(context, id, version, args, timeout, endorseSleepMS){
    const TxErrorEnum = require('./constant.js').TxErrorEnum;
    const TxErrorIndex = require('./constant.js').TxErrorIndex;
    const channel = context.channel;
    const startTime = Date.now();
    const txIdObject = context.client.newTransactionID();
    const txId = txIdObject.getTransactionID().toString();
    let invokeStatus = new TxStatus(txId);
    let errFlag = TxErrorEnum.NoError;
    invokeStatus.SetFlag(errFlag);
    const f = args[0];
    args.shift();
    const proposalRequest = {
        chaincodeId: id,
        fcn: f,
        args: args,
        txId: txIdObject,
    };
    let proposalResponseObject = null;
    try {
        try {
            invokeStatus.Set('time_create', Date.now());
            proposalResponseObject = await channel.sendTransactionProposal(proposalRequest, timeout * 1000);
            invokeStatus.Set('time_endorse', Date.now());
        } catch (err) {
            invokeStatus.Set('time_endorse', Date.now());
            errFlag |= TxErrorEnum.ProposalResponseError;
            invokeStatus.SetFlag (errFlag);
            invokeStatus.SetErrMsg(TxErrorIndex.ProposalResponseError, err.toString());
            invokeStatus.SetVerification(true);
            throw err; 
        }
        const proposalResponses = proposalResponseObject[0];
        const proposal = proposalResponseObject[1];
        let allGood = true;
        for(let i in proposalResponses) {
            let one_good = false;
            let proposal_response = proposalResponses[i];
            if( proposal_response.response && proposal_response.response.status === 200) {
                one_good = true;
            } else {
                let err = new Error('Endorsement denied: ' + proposal_response.toString());
                errFlag |= TxErrorEnum.BadProposalResponseError;
                invokeStatus.SetFlag(errFlag);
                invokeStatus.SetErrMsg(TxErrorIndex.BadProposalResponseError, err.toString());
                invokeStatus.SetVerification(true);
                throw err;
            }
            allGood = allGood && one_good;
        }
        if (allGood) {
            allGood = channel.compareProposalResponseResults(proposalResponses);
            if (!allGood) {
                let err = new Error('Read/Write set mismatch between endorsements');
                errFlag |= TxErrorEnum.BadProposalResponseError;
                invokeStatus.SetFlag(errFlag);
                invokeStatus.SetErrMsg(TxErrorIndex.BadProposalResponseError, err.toString());
                invokeStatus.SetVerification(true);
                throw err;
            }
        }
        invokeStatus.SetResult(proposalResponses[0].response.payload);
        const transactionRequest = {
            proposalResponses: proposalResponses,
            proposal: proposal,
        };
        if (endorseSleepMS != null && endorseSleepMS > 0) {
            await timeoutPromise(endorseSleepMS);
        }
        let broadcastResponse;
        try {
            broadcastResponse = await channel.sendTransaction(transactionRequest);
        } catch (err) {
            errFlag |= TxErrorEnum.OrdererResponseError;
            invokeStatus.SetFlag(errFlag);
            invokeStatus.SetErrMsg(TxErrorIndex.OrdererResponseError,err.toString());
        }
        invokeStatus.Set('time_order', Date.now());
        if (broadcastResponse && broadcastResponse.status === 'SUCCESS') {
            invokeStatus.Set('status', 'submitted');
        } else if (broadcastResponse && broadcastResponse.status !== 'SUCCESS') {
            let err = new Error('Received rejection from orderer service: ' + broadcastResponse.status);
            errFlag |= TxErrorEnum.BadOrdererResponseError;
            invokeStatus.SetFlag(errFlag);
            invokeStatus.SetErrMsg(TxErrorIndex.BadOrdererResponseError, err.toString());
            invokeStatus.SetVerification(true);
            throw err;
        }
        );
    } catch (err) {
        invokeStatus.SetStatusFail();
        commUtils.log('Failed to issue transaction [' + txId.substring(0, 5) + '...]:' + (err instanceof Error ? err.stack : err));
    }
    return invokeStatus;
}
async function invokebycontext ( context , id , version , args , timeout , endorseSleepMS ) { const TxErrorEnum = require ( './constant.js' ) . TxErrorEnum ; const TxErrorIndex = require ( './constant.js' ) . TxErrorIndex ; const channel = context . channel ; const startTime = Date . now ( ) ; const txIdObject = context . client . newTransactionID ( ) ; const txId = txIdObject . getTransactionID ( ) . toString ( ) ; let invokeStatus = new TxStatus ( txId ) ; let errFlag = TxErrorEnum . NoError ; invokeStatus . SetFlag ( errFlag ) ; const f = args [ 0 ] ; args . shift ( ) ; const proposalRequest = { chaincodeId : id , fcn : f , args : args , txId : txIdObject , } ; let proposalResponseObject = null ; try { try { invokeStatus . Set ( 'time_create' , Date . now ( ) ) ; proposalResponseObject = await channel . sendTransactionProposal ( proposalRequest , timeout * 1000 ) ; invokeStatus . Set ( 'time_endorse' , Date . now ( ) ) ; } catch ( err ) { invokeStatus . Set ( 'time_endorse' , Date . now ( ) ) ; errFlag |= TxErrorEnum . ProposalResponseError ; invokeStatus . SetFlag ( errFlag ) ; invokeStatus . SetErrMsg ( TxErrorIndex . ProposalResponseError , err . toString ( ) ) ; invokeStatus . SetVerification ( true ) ; throw err ; } const proposalResponses = proposalResponseObject [ 0 ] ; const proposal = proposalResponseObject [ 1 ] ; let allGood = true ; for ( let i in proposalResponses ) { let one_good = false ; let proposal_response = proposalResponses [ i ] ; if ( proposal_response . response && proposal_response . response . status === 200 ) { one_good = true ; } else { let err = new Error ( 'Endorsement denied: ' + proposal_response . toString ( ) ) ; errFlag |= TxErrorEnum . BadProposalResponseError ; invokeStatus . SetFlag ( errFlag ) ; invokeStatus . SetErrMsg ( TxErrorIndex . BadProposalResponseError , err . toString ( ) ) ; invokeStatus . SetVerification ( true ) ; throw err ; } allGood = allGood && one_good ; } if ( allGood ) { allGood = channel . compareProposalResponseResults ( proposalResponses ) ; if ( ! allGood ) { let err = new Error ( 'Read/Write set mismatch between endorsements' ) ; errFlag |= TxErrorEnum . BadProposalResponseError ; invokeStatus . SetFlag ( errFlag ) ; invokeStatus . SetErrMsg ( TxErrorIndex . BadProposalResponseError , err . toString ( ) ) ; invokeStatus . SetVerification ( true ) ; throw err ; } } invokeStatus . SetResult ( proposalResponses [ 0 ] . response . payload ) ; const transactionRequest = { proposalResponses : proposalResponses , proposal : proposal , } ; if ( endorseSleepMS != null && endorseSleepMS > 0 ) { await timeoutPromise ( endorseSleepMS ) ; } let broadcastResponse ; try { broadcastResponse = await channel . sendTransaction ( transactionRequest ) ; } catch ( err ) { errFlag |= TxErrorEnum . OrdererResponseError ; invokeStatus . SetFlag ( errFlag ) ; invokeStatus . SetErrMsg ( TxErrorIndex . OrdererResponseError , err . toString ( ) ) ; } invokeStatus . Set ( 'time_order' , Date . now ( ) ) ; if ( broadcastResponse && broadcastResponse . status === 'SUCCESS' ) { invokeStatus . Set ( 'status' , 'submitted' ) ; } else if ( broadcastResponse && broadcastResponse . status !== 'SUCCESS' ) { let err = new Error ( 'Received rejection from orderer service: ' + broadcastResponse . status ) ; errFlag |= TxErrorEnum . BadOrdererResponseError ; invokeStatus . SetFlag ( errFlag ) ; invokeStatus . SetErrMsg ( TxErrorIndex . BadOrdererResponseError , err . toString ( ) ) ; invokeStatus . SetVerification ( true ) ; throw err ; } } catch ( err ) { invokeStatus . SetStatusFail ( ) ; commUtils . log ( 'Failed to issue transaction [' + txId . substring ( 0 , 5 ) + '...]:' + ( err instanceof Error ? err . stack : err ) ) ; } return invokeStatus ; }
Submit a transaction to the given chaincode with the specified options.
Submit a transaction to the given chaincode with the specified options .
// const eventHubs = context.eventhubs; // timestamps are recorded for every phase regardless of success/failure // invokeStatus.Set('operation', 'invoke'); // TODO: should resolve endorsement policy to decides the target of endorsers // now random peers ( one peer per organization ) are used as endorsers as default, see the implementation of getContext // send proposal to endorser // if(context.engine) { //     context.engine.submitCallback(1); // } // error occurred, early life-cycle termination, definitely failed // handle logging in one place // TODO: the CPU cost of verifying response is too high. // Now we ignore this step to improve concurrent capacity for the client // so a client can initialize multiple concurrent transactions // Is it a reasonable way? // one_good = channel.verifyProposalResponse(proposal_response); // explicit rejection, early life-cycle termination, definitely failed // check all the read/write sets to see if the same, verify that each peer // got the same results on the proposal // r/w set mismatch, early life-cycle termination, definitely failed // missing the ACK does not mean anything, the Tx could be already under ordering // so let the events decide the final status, but log this error // the submission was explicitly rejected, so the Tx will definitely not be ordered ////////////////////////////////////////////////////////////////////////////////////////////////////// // Use eventhub to determine txn status // let eh = context.eventhub; // let event_promise = new Promise((resolve, reject) => { //     let handle = setTimeout(() => reject(new Error('Timeout')), 10000); //     eh.registerTxEvent(txId, //         (tx, code) => { //             clearTimeout(handle); //             eh.unregisterTxEvent(txId); //             // either explicit invalid event or valid event, verified in both cases by at least one peer //             invokeStatus.SetVerification(true); //             if (code !== 'VALID') { //                 let err = new Error('Invalid transaction: ' + code); //                 errFlag |= TxErrorEnum.BadEventNotificationError; //                 invokeStatus.SetStatusFail(); //                 invokeStatus.SetFlag(errFlag); //                 invokeStatus.SetErrMsg(TxErrorIndex.BadEventNotificationError, err.toString()); //                 reject(err); // handle error in final catch //             } else { //                 invokeStatus.SetStatusSuccess(); //                 invokeStatus.Set('time_commit', Date.now()); //                 resolve(); //             } //         }, //         (err) => { //             clearTimeout(handle); //             errFlag |= TxErrorEnum.EventNotificationError; //             invokeStatus.SetStatusFail(); //             invokeStatus.SetFlag(errFlag); //             invokeStatus.SetErrMsg(TxErrorIndex.EventNotificationError, err.toString()); //             resolve(); //         } //     ); // }); // await event_promise; ////////////////////////////////////////////////////////////////////////////////////////////////////// // at this point the Tx should be verified