diff --git a/docs/tutorials/chaincode-lifecycle.md b/docs/tutorials/chaincode-lifecycle.md
index 912e942a55..917aceeaa0 100644
--- a/docs/tutorials/chaincode-lifecycle.md
+++ b/docs/tutorials/chaincode-lifecycle.md
@@ -24,8 +24,8 @@ The Fabric 2.0 Alpha introduces decentralized governance for chaincode. The new
Fabric chaincode lifecycle allows multiple organizations to come to agreement
on the parameters of a chaincode, such as the chaincode endorsement policy,
before it can be used to interact with the ledger. You will need to enable the
-new Fabric chaincode lifecycle on your network by setting the channel
-capabilities to `V2_0` to use the steps in this tutorial.
+new Fabric chaincode lifecycle on your channel definition by setting the
+Applications capabilities to `V2_0: true` to use the steps in this tutorial.
Channel members need to complete the following steps before they can start
using a chaincode:
@@ -166,7 +166,7 @@ const packge_request = {
chaincodeType: 'golang',
goPath: '/gopath',
chaincodePath: '/path/to/code',
- metadataPath: '/path/to/metadat'
+ metadataPath: '/path/to/metadata'
}
const package = await mychaincode.package(package_request);
```
@@ -292,13 +292,13 @@ const results = await mychannel.sendTransaction(orderer_request);
The chaincode is ready to be used after it is defined on a channel. If you did
not request the execution of your chaincode's `Init` function, then the chaincode
container will start after the first invoke. If you used `setInitRequired(true)`
-to request that the `Init` function be executed, then you need to invoke the
-`Init` before any other transactions can be executed.
+then you need to invoke with `is_init` set to `true`
+before any other transactions can be executed.
-The following code snippet below requests the execution of the `Init` function.
+The following code snippet below requests the initialization of your chaincode.
Note that `is_init` needs to be set to `true` as part of the request, and the
-`Init` function must be called using `sendTransaction` rather than the
-"Invoke" method of your chaincode.
+`Init` method will be called rather than the
+`Invoke` method of your chaincode.
```
// initialize the chaincode
diff --git a/fabric-client/lib/Chaincode.js b/fabric-client/lib/Chaincode.js
index a12fcee851..85ee856ce0 100644
--- a/fabric-client/lib/Chaincode.js
+++ b/fabric-client/lib/Chaincode.js
@@ -339,7 +339,7 @@ const Chaincode = class {
/**
* Provide the endorsement policy definition for this chaincode. The input is a JSON object.
*
- * @example
Endorsement policy: "Signed by any member from one of the organizations"
+ * @example Object Endorsement policy: "Signed by any member from one of the organizations"
* {
* identities: [
* { role: {name: "member", mspId: "org1"}},
@@ -349,7 +349,7 @@ const Chaincode = class {
* "1-of": [{"signed-by": 0}, {"signed-by": 1}]
* }
* }
- * @example Endorsement policy: "Signed by admin of the ordererOrg and any member from one of the peer organizations"
+ * @example Object Endorsement policy: "Signed by admin of the ordererOrg and any member from one of the peer organizations"
* {
* identities: [
* {role: {name: "member", mspId: "peerOrg1"}},
@@ -363,7 +363,12 @@ const Chaincode = class {
* ]
* }
* }
- * @param {string} policy - The JSON representation of an fabric endorsement policy.
+ * @example String Endorsement policy: "Policy reference of an existing policy in your channel configuration"
+ * /Channel/Application/Endorsement
+ * @param {string | object} policy - When the policy is a string it will be
+ * the canonical path to a policy in the Channel configuration.
+ * When an object, it will be the fabric-client's JSON representation
+ * of an fabric endorsement policy.
*/
setEndorsementPolicyDefinition(policy) {
const method = 'setEndorsementPolicyDefinition';
diff --git a/test/scenario/features/chaincode_lifecycle.feature b/test/scenario/features/chaincode_lifecycle.feature
index 569f4ca820..6f0e5e3ce1 100644
--- a/test/scenario/features/chaincode_lifecycle.feature
+++ b/test/scenario/features/chaincode_lifecycle.feature
@@ -23,9 +23,9 @@ Feature: Use the v2.0 chaincode lifecycle process
And I can install java chaincode at version v1 named example_cc_java as organization org1
And I can install golang chaincode at version v1 named example_cc_golang as organization org1
- And I can approve node chaincode at version v1 named example_cc_node as organization org1 on channel tokenchannel
- And I can approve java chaincode at version v1 named example_cc_java as organization org1 on channel tokenchannel
- And I can approve golang chaincode at version v1 named example_cc_golang as organization org1 on channel tokenchannel
+ And I can approve node chaincode at version v1 named example_cc_node as organization org1 on channel tokenchannel with endorsement policy both_orgs
+ And I can approve java chaincode at version v1 named example_cc_java as organization org1 on channel tokenchannel with endorsement policy both_orgs
+ And I can approve golang chaincode at version v1 named example_cc_golang as organization org1 on channel tokenchannel with endorsement policy both_orgs
And I can package node chaincode at version v1 named example_cc_node as organization org2 with goPath na located at ../../../../test/fixtures/chaincode/node_cc/example_cc and metadata located at ../../../../test/fixtures/chaincode/metadata
And I can package java chaincode at version v1 named example_cc_java as organization org2 with goPath na located at ../../../../test/fixtures/chaincode/java_cc/example_cc and metadata located at ../../../../test/fixtures/chaincode/metadata
@@ -35,9 +35,9 @@ Feature: Use the v2.0 chaincode lifecycle process
And I can install java chaincode at version v1 named example_cc_java as organization org2
And I can install golang chaincode at version v1 named example_cc_golang as organization org2
- And I can approve node chaincode at version v1 named example_cc_node as organization org2 on channel tokenchannel
- And I can approve java chaincode at version v1 named example_cc_java as organization org2 on channel tokenchannel
- And I can approve golang chaincode at version v1 named example_cc_golang as organization org2 on channel tokenchannel
+ And I can approve node chaincode at version v1 named example_cc_node as organization org2 on channel tokenchannel with endorsement policy both_orgs
+ And I can approve java chaincode at version v1 named example_cc_java as organization org2 on channel tokenchannel with endorsement policy both_orgs
+ And I can approve golang chaincode at version v1 named example_cc_golang as organization org2 on channel tokenchannel with endorsement policy both_orgs
And I can query for chaincode example_cc_node for approval status as organization org1 on channel tokenchannel
And I can query for chaincode example_cc_java for approval status as organization org1 on channel tokenchannel
diff --git a/test/scenario/features/lib/utils.js b/test/scenario/features/lib/utils.js
index ae62ae6e6f..7cb62be805 100644
--- a/test/scenario/features/lib/utils.js
+++ b/test/scenario/features/lib/utils.js
@@ -413,7 +413,7 @@ async function commitProposal(tx_id, proposalResponses, proposal, channel, peer)
logError('Timeout - Failed to receive the event: waiting on ' + channel_event_hub.getPeerAddr());
channel_event_hub.disconnect();
reject('TIMEOUT waiting on ' + channel_event_hub.getPeerAddr());
- }, 15000);
+ }, 120000);
channel_event_hub.registerTxEvent(deployId.toString(), (tx, code) => {
logMsg('The chaincode transaction has been committed on peer ' + channel_event_hub.getPeerAddr());
@@ -437,7 +437,13 @@ async function commitProposal(tx_id, proposalResponses, proposal, channel, peer)
logMsg('register eventhub tx=' + deployId);
promises.push(txPromise);
- const results = await Promise.all(promises);
+ let results = null;
+ try {
+ results = await Promise.all(promises);
+ } catch (error) {
+ logMsg('Transaction failed ::' + error);
+ throw error;
+ }
// orderer results are first as it was the first promise
if (results && results[0]) {
diff --git a/test/scenario/features/steps/chaincode_steps.js b/test/scenario/features/steps/chaincode_steps.js
index 1035dc73d5..abe277308a 100644
--- a/test/scenario/features/steps/chaincode_steps.js
+++ b/test/scenario/features/steps/chaincode_steps.js
@@ -31,18 +31,6 @@ module.exports = function () {
const chaincode = client.newChaincode(chaincode_name, chaincode_version);
// chaincode.setInitRequired(true);
- const ENDORSEMENT_POLICY = {
- identities: [
- {role: {name: 'member', mspId: 'Org1MSP'}},
- {role: {name: 'member', mspId: 'Org2MSP'}}
- ],
- policy: {
- '1-of': [{'signed-by': 0}, {'signed-by': 1}]
- }
- };
-
- chaincode.setEndorsementPolicyDefinition(ENDORSEMENT_POLICY);
-
const request = {
chaincodePath: chaincode_path,
metadataPath: metadata_path,
@@ -81,11 +69,11 @@ module.exports = function () {
}
});
- this.Then(/^I can approve (.+?) chaincode at version (.+?) named (.+?) as organization (.+?) on channel (.+?)$/,
- {timeout: testUtil.TIMEOUTS.SHORT_STEP},
- async (chaincode_type, chaincode_version, chaincode_name, org_name, channel_name) => {
+ this.Then(/^I can approve (.+?) chaincode at version (.+?) named (.+?) as organization (.+?) on channel (.+?) with endorsement policy (.+?)$/,
+ {timeout: testUtil.TIMEOUTS.LONG_STEP},
+ async (chaincode_type, chaincode_version, chaincode_name, org_name, channel_name, endorsement_policy) => {
const step = 'Chaincode approval';
- testUtil.logMsg(format('%s - starting for %s, %s, %s, %s, %s', step, chaincode_type, chaincode_version, chaincode_name, org_name, channel_name));
+ testUtil.logMsg(format('%s - starting for %s, %s, %s, %s, %s, %s', step, chaincode_type, chaincode_version, chaincode_name, org_name, channel_name, endorsement_policy));
const cc_save_name = format('chaincode-%s-%s', org_name, chaincode_name);
@@ -95,6 +83,31 @@ module.exports = function () {
const chaincode = Client.getConfigSetting(cc_save_name).value;
const channel = Client.getConfigSetting('channel-' + org_name + '-' + channel_name).value;
+
+ const ENDORSEMENT_POLICY = {
+ identities: [
+ {role: {name: 'member', mspId: 'Org1MSP'}},
+ {role: {name: 'member', mspId: 'Org2MSP'}}
+ ],
+ policy: {
+ '1-of': [{'signed-by': 0}, {'signed-by': 1}]
+ }
+ };
+
+ switch (endorsement_policy) {
+ case 'default':
+ // leave it blank and let fabric decide
+ break;
+ case 'both_orgs':
+ chaincode.setEndorsementPolicyDefinition(ENDORSEMENT_POLICY);
+ break;
+ default:
+ chaincode.setEndorsementPolicyDefinition(endorsement_policy);
+ }
+
+ // replace the saved one with the one updated with endorsement policy
+ Client.setConfigSetting(cc_save_name, {value: chaincode});
+
const txId = client.newTransactionID(true);
const request = {