diff --git a/fabric-client/lib/BlockDecoder.js b/fabric-client/lib/BlockDecoder.js index 46fbe31994..5ad04faa30 100644 --- a/fabric-client/lib/BlockDecoder.js +++ b/fabric-client/lib/BlockDecoder.js @@ -153,6 +153,7 @@ nonce -- {byte[]} config sequence -- {int} channel_group -- {{@link ConfigGroup}} + type -- {int} last_update signature -- {byte[]} payload @@ -228,6 +229,7 @@ config_update channel_id -- {string} read_set -- {{@link ChannelConfigGroup}} write_set -- {{@link ChannelConfigGroup}} + type -- {int} signatures -- {array} signature_header -- {{@link SignatureHeader}} signature -- {byte[]} @@ -442,11 +444,11 @@ policy * A "SignaturePolicy" will have the following object structure.
 type -- SIGNATURE
-policy
+rule
 	Type -- n_out_of
 	n_out_of
 		N -- {int}
-		policies -- {array}
+		rules -- {array}
 			Type -- signed_by
 			signed_by -- {int}
 	identities -- {array}
@@ -683,7 +685,6 @@ function decodeConfigEnvelope(config_envelope_bytes) {
 	var config_envelope = {};
 	var proto_config_envelope = _configtxProto.ConfigEnvelope.decode(config_envelope_bytes);
 	config_envelope.config = decodeConfig(proto_config_envelope.getConfig());
-
 	logger.debug('decodeConfigEnvelope - decode complete for config envelope - start config update');
 	config_envelope.last_update = {};
 	var proto_last_update = proto_config_envelope.getLastUpdate(); //this is a common.Envelope
@@ -702,6 +703,7 @@ function decodeConfig(proto_config) {
 	var config = {};
 	config.sequence = proto_config.getSequence();
 	config.channel_group = decodeConfigGroup(proto_config.getChannelGroup());
+	config.type = proto_config.getType();
 
 	return config;
 };
@@ -727,6 +729,7 @@ function decodeConfigUpdate(config_update_bytes) {
 	config_update.channel_id = proto_config_update.getChannelId();
 	config_update.read_set = decodeConfigGroup(proto_config_update.getReadSet());
 	config_update.write_set = decodeConfigGroup(proto_config_update.getWriteSet());
+	config_update.type = proto_config_update.getType();
 
 	return config_update;
 };
@@ -873,14 +876,14 @@ function decodeConfigPolicy(proto_config_policy) {
 		logger.debug('decodeConfigPolicy ======> Policy item ::%s', proto_config_policy.key);
 		switch (proto_config_policy.value.policy.type) {
 		case _policiesProto.Policy.PolicyType.SIGNATURE:
-			config_policy.policy.policy = decodeSignaturePolicyEnvelope(proto_config_policy.value.policy.policy);
+			config_policy.policy.value = decodeSignaturePolicyEnvelope(proto_config_policy.value.policy.value);
 			break;
 		case _policiesProto.Policy.PolicyType.MSP:
-			var proto_msp = _policiesProto.Policy.decode(proto_config_policy.value.policy.policy);
+			var proto_msp = _policiesProto.Policy.decode(proto_config_policy.value.policy.value);
 			logger.warn('decodeConfigPolicy - found a PolicyType of MSP. This policy type has not been implemented yet.');
 			break;
 		case _policiesProto.Policy.PolicyType.IMPLICIT_META:
-			config_policy.policy.policy = decodeImplicitMetaPolicy(proto_config_policy.value.policy.policy);
+			config_policy.policy.value = decodeImplicitMetaPolicy(proto_config_policy.value.policy.value);
 			break;
 		default:
 			throw new Error('Unknown Policy type');
@@ -904,7 +907,7 @@ function decodeSignaturePolicyEnvelope(signature_policy_envelope_bytes) {
 	var signature_policy_envelope = {};
 	var porto_signature_policy_envelope = _policiesProto.SignaturePolicyEnvelope.decode(signature_policy_envelope_bytes);
 	signature_policy_envelope.version = decodeVersion(porto_signature_policy_envelope.getVersion());
-	signature_policy_envelope.policy = decodeSignaturePolicy(porto_signature_policy_envelope.getPolicy());
+	signature_policy_envelope.rule = decodeSignaturePolicy(porto_signature_policy_envelope.getRule());
 	var identities = [];
 	var proto_identities = porto_signature_policy_envelope.getIdentities();
 	if (proto_identities)
@@ -923,11 +926,11 @@ function decodeSignaturePolicy(proto_signature_policy) {
 	if (signature_policy.Type == 'n_out_of') {
 		signature_policy.n_out_of = {};
 		signature_policy.n_out_of.N = proto_signature_policy.n_out_of.getN();
-		signature_policy.n_out_of.policies = [];
-		for (var i in proto_signature_policy.n_out_of.policies) {
-			var proto_policy = proto_signature_policy.n_out_of.policies[i];
+		signature_policy.n_out_of.rules = [];
+		for (var i in proto_signature_policy.n_out_of.rules) {
+			var proto_policy = proto_signature_policy.n_out_of.rules[i];
 			var policy = decodeSignaturePolicy(proto_policy);
-			signature_policy.n_out_of.policies.push(policy);
+			signature_policy.n_out_of.rules.push(policy);
 		}
 	} else if (signature_policy.Type == 'signed_by') {
 		signature_policy.signed_by = proto_signature_policy.getSignedBy();
@@ -1009,6 +1012,8 @@ function decodeFabricMSPConfig(msp_config_bytes) {
 	msp_config.revocation_list = toPEMcerts(proto_msp_config.getRevocationList());
 	msp_config.signing_identity = decodeSigningIdentityInfo(proto_msp_config.getSigningIdentity());
 	msp_config.organizational_unit_identifiers = decodeFabricOUIdentifier(proto_msp_config.getOrganizationalUnitIdentifiers());
+	msp_config.tls_root_certs = toPEMcerts(proto_msp_config.getTlsRootCerts());
+	msp_config.tls_intermediate_certs = toPEMcerts(proto_msp_config.getTlsIntermediateCerts());
 
 	return msp_config;
 };
@@ -1149,11 +1154,13 @@ function decodeProposalResponsePayload(proposal_response_payload_bytes) {
 };
 
 function decodeChaincodeAction(action_bytes) {
+	logger.debug('decodeChaincodeAction - start');
 	var chaincode_action = {};
 	var proto_chaincode_action = _proposalProto.ChaincodeAction.decode(action_bytes);
 	chaincode_action.results = decodeReadWriteSets(proto_chaincode_action.getResults());
 	chaincode_action.events = decodeChaincodeEvents(proto_chaincode_action.getEvents());
 	chaincode_action.response = decodeResponse(proto_chaincode_action.getResponse());
+	chaincode_action.chaincode_id = decodeChaincodeID(proto_chaincode_action.getChaincodeId());
 
 	return chaincode_action;
 };
@@ -1165,9 +1172,24 @@ function decodeChaincodeEvents(event_bytes) {
 	events.tx_id = proto_events.getTxId();
 	events.event_name = proto_events.getEventName();
 	events.payload = proto_events.getPayload().toBuffer();
+
 	return events;
 }
 
+function decodeChaincodeID(proto_chaincode_id) {
+	var chaincode_id = {};
+	if(!proto_chaincode_id) {
+		logger.debug('decodeChaincodeID - no proto_chaincode_id found');
+		return chaincode_id;
+	}
+	logger.debug('decodeChaincodeID - start');
+	chaincode_id.path = proto_chaincode_id.getPath();
+	chaincode_id.name = proto_chaincode_id.getName();
+	chaincode_id.version = proto_chaincode_id.getVersion();
+
+	return chaincode_id;
+}
+
 function decodeReadWriteSets(rw_sets_bytes) {
 	var proto_tx_read_write_set = _rwsetProto.TxReadWriteSet.decode(rw_sets_bytes);
 	var tx_read_write_set = {};
diff --git a/fabric-client/lib/Channel.js b/fabric-client/lib/Channel.js
index 0370f4981b..3b659e814a 100755
--- a/fabric-client/lib/Channel.js
+++ b/fabric-client/lib/Channel.js
@@ -2084,7 +2084,7 @@ function loadPolicy(config_items, versions, key, policy, group_name, org) {
 			logger.debug('loadPolicy - %s - policy SIGNATURE :: %s %s',group_name, signature_policy.encodeJSON(),this.decodeSignaturePolicy(signature_policy.getIdentities()));
 			break;
 		case _policiesProto.Policy.PolicyType.IMPLICIT_META:
-			let implicit_policy = _policiesProto.ImplicitMetaPolicy.decode(policy.policy);
+			let implicit_policy = _policiesProto.ImplicitMetaPolicy.decode(policy.value);
 			let rule = ImplicitMetaPolicy_Rule[implicit_policy.getRule()];
 			logger.debug('loadPolicy - %s - policy IMPLICIT_META :: %s %s',group_name, rule, implicit_policy.getSubPolicy());
 			break;
diff --git a/fabric-client/lib/Orderer.js b/fabric-client/lib/Orderer.js
index 350f004fca..9559ef3a0b 100644
--- a/fabric-client/lib/Orderer.js
+++ b/fabric-client/lib/Orderer.js
@@ -97,6 +97,9 @@ var Orderer = class extends Remote {
 			broadcast.on('data', function (response) {
 				logger.debug('sendBroadcast - on data response: %j', response);
 				broadcast.end();
+				if(response.info) {
+					logger.debug('sendBroadcast - response info :: %s', response.info);
+				}
 				if(response.status) {
 					if (response.status === 'SUCCESS') {
 						logger.debug('sendBroadcast - resolve with %s', response.status);
diff --git a/fabric-client/lib/Policy.js b/fabric-client/lib/Policy.js
index ae1d290b7d..c74cd280c9 100644
--- a/fabric-client/lib/Policy.js
+++ b/fabric-client/lib/Policy.js
@@ -103,14 +103,14 @@ var EndorsementPolicy = class {
 			// construct 'one of any' policy
 			var oneOfAny = new _policiesProto.SignaturePolicy.NOutOf();
 			oneOfAny.setN(1);
-			oneOfAny.setPolicies(signedBys);
+			oneOfAny.setRules(signedBys);
 
 			var noutof = new _policiesProto.SignaturePolicy();
 			noutof.set('n_out_of', oneOfAny);
 
 			var envelope = new _policiesProto.SignaturePolicyEnvelope();
 			envelope.setVersion(0);
-			envelope.setPolicy(noutof);
+			envelope.setRule(noutof);
 			envelope.setIdentities(principals);
 
 			return envelope.toBuffer();
@@ -136,7 +136,7 @@ var EndorsementPolicy = class {
 
 			var envelope = new _policiesProto.SignaturePolicyEnvelope();
 			envelope.setVersion(0);
-			envelope.setPolicy(thePolicy);
+			envelope.setRule(thePolicy);
 			envelope.setIdentities(principals);
 
 			return envelope.toBuffer();
@@ -232,7 +232,7 @@ function parsePolicy(spec) {
 			subs.push(subPolicy);
 		});
 
-		nOutOf.setPolicies(subs);
+		nOutOf.setRules(subs);
 
 		let nOf = new _policiesProto.SignaturePolicy();
 		nOf.set('n_out_of', nOutOf);
diff --git a/fabric-client/lib/msp/msp-manager.js b/fabric-client/lib/msp/msp-manager.js
index ac822849db..b7345e94b9 100755
--- a/fabric-client/lib/msp/msp-manager.js
+++ b/fabric-client/lib/msp/msp-manager.js
@@ -97,7 +97,9 @@ var MSPManager = class {
 				admins: fabricConfig.getAdmins(),
 				id: fabricConfig.getName(),
 				orgs : orgs,
-				cryptoSuite: cs
+				cryptoSuite: cs,
+				tls_root_certs: fabricConfig.getTlsRootCerts(),
+				tls_intermediate_certs: fabricConfig.getTlsIntermediateCerts()
 			});
 			logger.debug('loadMSPs - found msp=',newMSP.getId());
 			//will eliminate duplicates
diff --git a/fabric-client/lib/msp/msp.js b/fabric-client/lib/msp/msp.js
index 7a293ba894..2b6f159018 100755
--- a/fabric-client/lib/msp/msp.js
+++ b/fabric-client/lib/msp/msp.js
@@ -64,6 +64,8 @@ var MSP = class {
 		this.cryptoSuite = config.cryptoSuite;
 		this._id = config.id;
 		this._organization_units = config.orgs;
+		this._tls_root_certs = config.tls_root_certs;
+		this._tls_intermediate_certs = config.tls_intermediate_certs;
 	}
 
 	/**
@@ -126,6 +128,12 @@ var MSP = class {
 			//organizational_unit_identifiers
 			proto_fabric_msp_config.setOrganizationalUnitIdentifiers(this._organization_units);
 		}
+		if(this._tls_root_certs) {
+			proto_fabric_msp_config.setTlsRootCerts(this._tls_root_certs);
+		}
+		if(this._tls_intermediate_certs) {
+			proto_fabric_msp_config.getTlsIntermediateCerts(this._tls_intermediate_certs);
+		}
 		proto_msp_config.setConfig(proto_fabric_msp_config.toBuffer());
 		return proto_msp_config;
 	}
diff --git a/fabric-client/lib/protos/common/configtx.proto b/fabric-client/lib/protos/common/configtx.proto
index 74f6ef669d..fef542f35a 100644
--- a/fabric-client/lib/protos/common/configtx.proto
+++ b/fabric-client/lib/protos/common/configtx.proto
@@ -1,17 +1,7 @@
 /*
 Copyright IBM Corp. 2017 All Rights Reserved.
 
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-                 http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
+SPDX-License-Identifier: Apache-2.0
 */
 
 syntax = "proto3";
@@ -24,6 +14,13 @@ option java_package = "org.hyperledger.fabric.protos.common";
 
 package common;
 
+// ConfigType is an enumeration of possible types for the config.  The type field in the config is
+// an int32 for extensibility, but this enum type should generally be used to populate it
+enum ConfigType {
+	CHANNEL = 0;  // The original and default configuration type, defines parameters for the operation of a channel
+	RESOURCE = 1; // Defines a set of resource names, and their mapping to policies which restrict access to those resources
+}
+
 // ConfigEnvelope is designed to contain _all_ configuration for a chain with no dependency
 // on previous configuration transactions.
 //
@@ -64,7 +61,8 @@ message ConfigPolicySchema {}
 // Config represents the config for a particular channel
 message Config {
     uint64 sequence = 1;
-    ConfigGroup channel_group = 2;
+    ConfigGroup channel_group = 2; // channel_group is a bad name for this, it should be changed to root when API breakage is allowed
+    int32 type = 3;
 }
 
 message ConfigUpdateEnvelope {
@@ -82,9 +80,11 @@ message ConfigUpdateEnvelope {
 // 4. Each policy is checked against the signatures from the ConfigUpdateEnvelope, any failing to verify are rejected
 // 5. The write_set is applied to the Config and the ConfigGroupSchema verifies that the updates were legal
 message ConfigUpdate {
-    string channel_id = 1;     // Which channel this config update is for
-    ConfigGroup read_set = 2;  // ReadSet explicitly lists the portion of the config which was read, this should be sparse with only Version set
-    ConfigGroup write_set = 3; // WriteSet lists the portion of the config which was written, this should included updated Versions
+    string channel_id = 1;                // Which channel this config update is for
+    ConfigGroup read_set = 2;             // ReadSet explicitly lists the portion of the config which was read, this should be sparse with only Version set
+    ConfigGroup write_set = 3;            // WriteSet lists the portion of the config which was written, this should included updated Versions
+    int32 type = 4;                       // The type of config this update is intended for (usually a value from ConfigType enum) , must match the type in the Config message
+    map isolated_data = 5; // Data which is not to be reflected in the resulting Config, but is still needed for some other purpose.  For instance, rscc_seed_data
 }
 
 // ConfigGroup is the hierarchical data structure for holding config
diff --git a/fabric-client/lib/protos/common/policies.proto b/fabric-client/lib/protos/common/policies.proto
index 6ab984e9b6..9c8b478dab 100644
--- a/fabric-client/lib/protos/common/policies.proto
+++ b/fabric-client/lib/protos/common/policies.proto
@@ -33,13 +33,13 @@ message Policy {
         IMPLICIT_META = 3;
     }
     int32 type = 1; // For outside implementors, consider the first 1000 types reserved, otherwise one of PolicyType
-    bytes policy = 2;
+    bytes value = 2;
 }
 
 // SignaturePolicyEnvelope wraps a SignaturePolicy and includes a version for future enhancements
 message SignaturePolicyEnvelope {
     int32 version = 1;
-    SignaturePolicy policy = 2;
+    SignaturePolicy rule = 2;
     repeated MSPPrincipal identities = 3;
 }
 
@@ -52,7 +52,7 @@ message SignaturePolicyEnvelope {
 message SignaturePolicy {
     message NOutOf {
         int32 n = 1;
-        repeated SignaturePolicy policies = 2;
+        repeated SignaturePolicy rules = 2;
     }
     oneof Type {
         int32 signed_by = 1;
diff --git a/fabric-client/lib/protos/ledger/rwset/kvrwset/kv_rwset.proto b/fabric-client/lib/protos/ledger/rwset/kvrwset/kv_rwset.proto
index b24997e6aa..d5b73a3f77 100644
--- a/fabric-client/lib/protos/ledger/rwset/kvrwset/kv_rwset.proto
+++ b/fabric-client/lib/protos/ledger/rwset/kvrwset/kv_rwset.proto
@@ -22,12 +22,19 @@ option java_package = "org.hyperledger.fabric.protos.ledger.rwset.kvrwset";
 package kvrwset;
 
 // KVRWSet encapsulates the read-write set for a chaincode that operates upon a KV or Document data model
+// This structure is used for both the public data and the private data
 message KVRWSet {
     repeated KVRead reads = 1;
     repeated RangeQueryInfo range_queries_info = 2;
     repeated KVWrite writes = 3;
 }
 
+// HashedRWSet encapsulates hashed representation of a private read-write set for KV or Document data model
+message HashedRWSet {
+    repeated KVReadHash hashed_reads = 1;
+    repeated KVWriteHash hashed_writes = 2;
+}
+
 // KVRead captures a read operation performed during transaction simulation
 // A 'nil' version indicates a non-existing key read by the transaction
 message KVRead {
@@ -42,6 +49,21 @@ message KVWrite {
     bytes value = 3;
 }
 
+// KVReadHash is similar to the KVRead in spirit. However, it captures the hash of the key instead of the key itself
+// version is kept as is for now. However, if the version also needs to be privacy-protected, it would need to be the
+// hash of the version and hence of 'bytes' type
+message KVReadHash {
+    bytes key_hash = 1;
+    Version version = 2;
+}
+
+// KVWriteHash is similar to the KVWrite in spiritcaptures a write (update/delete) operation performed during transaction simulation
+message KVWriteHash {
+    bytes key_hash = 1;
+    bool is_delete = 2;
+    bytes value_hash = 3;
+}
+
 // Version encapsulates the version of a Key
 // A version of a committed key is maintained as the height of the transaction that committed the key.
 // The height is represenetd as a tuple  where the txNum is the height of the transaction
diff --git a/fabric-client/lib/protos/ledger/rwset/rwset.proto b/fabric-client/lib/protos/ledger/rwset/rwset.proto
index 84081c902b..7f7e6c7740 100644
--- a/fabric-client/lib/protos/ledger/rwset/rwset.proto
+++ b/fabric-client/lib/protos/ledger/rwset/rwset.proto
@@ -36,4 +36,30 @@ message TxReadWriteSet {
 message NsReadWriteSet {
    string namespace = 1;
    bytes rwset = 2; // Data model specific serialized proto message (e.g., kvrwset.KVRWSet for KV and Document data models)
+   repeated CollectionHashedReadWriteSet collection_hashed_rwset = 3;
+}
+
+// CollectionHashedReadWriteSet encapsulate the hashed representation for the private read-write set for a collection
+message CollectionHashedReadWriteSet {
+    string collection_name = 1;
+    bytes hashed_rwset = 2; // Data model specific serialized proto message (e.g., kvrwset.HashedRWSet for KV and Document data models)
+    bytes pvt_rwset_hash = 3; // Hash of entire private read-write set for a specific collection. This helps in authenticating the private read-write set efficiently
+}
+
+// TxPvtReadWriteSet encapsulate the private read-write set for a transaction
+message TxPvtReadWriteSet {
+    TxReadWriteSet.DataModel data_model = 1;
+    repeated NsPvtReadWriteSet ns_pvt_rwset = 2;
+}
+
+// NsPvtReadWriteSet encapsulates the private read-write set for a chaincode
+message NsPvtReadWriteSet {
+   string namespace = 1;
+   repeated CollectionPvtReadWriteSet collection_pvt_rwset = 2;
+}
+
+// CollectionPvtReadWriteSet encapsulates the private read-write set for a collection
+message CollectionPvtReadWriteSet {
+    string collection_name = 1;
+    bytes rwset = 2; // Data model specific serialized proto message (e.g., kvrwset.KVRWSet for KV and Document data models)
 }
diff --git a/fabric-client/lib/protos/msp/msp_config.proto b/fabric-client/lib/protos/msp/msp_config.proto
index 307ae77ac9..3d26f0a804 100644
--- a/fabric-client/lib/protos/msp/msp_config.proto
+++ b/fabric-client/lib/protos/msp/msp_config.proto
@@ -84,6 +84,14 @@ message FabricMSPConfig {
     // FabricCryptoConfig contains the configuration parameters
     // for the cryptographic algorithms used by this MSP
     FabricCryptoConfig crypto_config = 8;
+
+    // List of TLS root certificates trusted by this MSP.
+    // They are returned by GetTLSRootCerts.
+    repeated bytes tls_root_certs = 9;
+
+    // List of TLS intermediate certificates trusted by this MSP;
+    // They are returned by GetTLSIntermediateCerts.
+    repeated bytes tls_intermediate_certs = 10;
 }
 
 // FabricCryptoConfig contains configuration parameters
diff --git a/fabric-client/lib/protos/orderer/ab.proto b/fabric-client/lib/protos/orderer/ab.proto
index c4ed04fc35..89e7615d9c 100644
--- a/fabric-client/lib/protos/orderer/ab.proto
+++ b/fabric-client/lib/protos/orderer/ab.proto
@@ -24,7 +24,10 @@ option java_package = "org.hyperledger.fabric.protos.orderer";
 package orderer;
 
 message BroadcastResponse {
+    // Status code, which may be used to programatically respond to success/failure
     common.Status status = 1;
+    // Info string which may contain additional information about the status returned
+    string info = 2;
 }
 
 message SeekNewest { }
diff --git a/fabric-client/lib/protos/peer/admin.proto b/fabric-client/lib/protos/peer/admin.proto
index cd761c45a6..2fd3327ffe 100644
--- a/fabric-client/lib/protos/peer/admin.proto
+++ b/fabric-client/lib/protos/peer/admin.proto
@@ -29,7 +29,6 @@ service Admin {
     // Return the serve status.
     rpc GetStatus(google.protobuf.Empty) returns (ServerStatus) {}
     rpc StartServer(google.protobuf.Empty) returns (ServerStatus) {}
-    rpc StopServer(google.protobuf.Empty) returns (ServerStatus) {}
     rpc GetModuleLogLevel(LogLevelRequest) returns (LogLevelResponse) {}
     rpc SetModuleLogLevel(LogLevelRequest) returns (LogLevelResponse) {}
     rpc RevertLogLevels(google.protobuf.Empty) returns (google.protobuf.Empty) {}
diff --git a/fabric-client/lib/protos/peer/chaincode.proto b/fabric-client/lib/protos/peer/chaincode.proto
index 8af59f3218..d4f8ff6764 100644
--- a/fabric-client/lib/protos/peer/chaincode.proto
+++ b/fabric-client/lib/protos/peer/chaincode.proto
@@ -53,6 +53,7 @@ message ChaincodeID {
 // the []byte-based current ChaincodeInput structure.
 message ChaincodeInput {
     repeated bytes args  = 1;
+    map decorations = 2;
 }
 
 // Carries the chaincode specification. This is the actual metadata required for
diff --git a/fabric-client/lib/protos/peer/proposal.proto b/fabric-client/lib/protos/peer/proposal.proto
index ffe924002c..2c4beea6de 100644
--- a/fabric-client/lib/protos/peer/proposal.proto
+++ b/fabric-client/lib/protos/peer/proposal.proto
@@ -240,6 +240,7 @@ message ChaincodeProposalPayload {
 
 	// Input contains the arguments for this invocation. If this invocation
 	// deploys a new chaincode, ESCC/VSCC are part of this field.
+	// This is usually a marshaled ChaincodeInvocationSpec
 	bytes input  = 1;
 
 	// TransientMap contains data (e.g. cryptographic material) that might be used
@@ -263,4 +264,11 @@ message ChaincodeAction {
 
 	// This field contains the result of executing this invocation.
 	Response response = 3;
+
+	// This field contains the ChaincodeID of executing this invocation. Endorser
+	// will set it with the ChaincodeID called by endorser while simulating proposal.
+	// Committer will validate the version matching with latest chaincode version.
+	// Adding ChaincodeID to keep version opens up the possibility of multiple
+	// ChaincodeAction per transaction.
+	ChaincodeID chaincode_id = 4;
 }
diff --git a/test/integration/query.js b/test/integration/query.js
index 2ca28d3bfa..6695a9580d 100644
--- a/test/integration/query.js
+++ b/test/integration/query.js
@@ -142,7 +142,7 @@ test('  ---->>>>> Query channel working <<<<<-----', function(t) {
 		t.equal(block.header.number.toString(),'0','checking query results are correct that we got zero block back');
 		t.equal(block.data.data[0].payload.data.config.channel_group.groups.Orderer.groups.OrdererMSP.values.MSP.value.config.name,'OrdererMSP','checking query results are correct that we got the correct orderer MSP name');
 		t.equal(block.data.data[0].payload.data.config.channel_group.groups.Application.groups.Org2MSP.policies.Writers.policy.type,'SIGNATURE','checking query results are correct that we got the correct policy type');
-		t.equal(block.data.data[0].payload.data.config.channel_group.groups.Application.policies.Writers.policy.policy.rule,'ANY','checking query results are correct that we got the correct policy rule');
+		t.equal(block.data.data[0].payload.data.config.channel_group.groups.Application.policies.Writers.policy.value.rule,'ANY','checking query results are correct that we got the correct policy rule');
 		t.equal(block.data.data[0].payload.data.config.channel_group.policies.Admins.mod_policy,'Admins','checking query results are correct that we got the correct mod policy name');
 		return channel.queryBlock(1);
 	}).then((block) => {
diff --git a/test/unit/block.js b/test/unit/block.js
index 30044862b1..3b6d6bb71d 100644
--- a/test/unit/block.js
+++ b/test/unit/block.js
@@ -189,7 +189,7 @@ test('\n\n*** BlockDecoder.js tests ***\n\n', (t) => {
 			getModPolicy: function() { return {}; },
 			policy: {
 				type: policiesProto.Policy.PolicyType.MSP,
-				policy: mockPolicy.toBuffer()
+				value: mockPolicy.toBuffer()
 			}
 		}
 	});
@@ -204,7 +204,7 @@ test('\n\n*** BlockDecoder.js tests ***\n\n', (t) => {
 					getModPolicy: function() { return {}; },
 					policy: {
 						type: policiesProto.Policy.PolicyType.MSB, // setting to an invalid type
-						policy: mockPolicy.toBuffer()
+						value: mockPolicy.toBuffer()
 					}
 				}
 			});
diff --git a/test/unit/channel.js b/test/unit/channel.js
index 5f596b46c2..07691ce3c1 100644
--- a/test/unit/channel.js
+++ b/test/unit/channel.js
@@ -502,8 +502,8 @@ test('\n\n ** Channel _buildDefaultEndorsementPolicy() tests **\n\n', function (
 	t.equal(env.identities.length, 2, 'Checking decoded default policy has two array items');
 	t.equal(env.identities[0].getPrincipalClassification(), _mspPrProto.MSPPrincipal.Classification.ROLE, 'Checking decoded default policy has a ROLE identity');
 
-	t.equal(typeof env.getPolicy().get('n_out_of'), 'object', 'Checking decoded default policy has an "n_out_of" policy');
-	t.equal(env.getPolicy().get('n_out_of').getN(), 1, 'Checking decoded default policy has an "n_out_of" policy with N = 1');
+	t.equal(typeof env.getRule().get('n_out_of'), 'object', 'Checking decoded default policy has an "n_out_of" policy');
+	t.equal(env.getRule().get('n_out_of').getN(), 1, 'Checking decoded default policy has an "n_out_of" policy with N = 1');
 
 	t.throws(
 		() => {
@@ -585,8 +585,8 @@ test('\n\n ** Channel _buildDefaultEndorsementPolicy() tests **\n\n', function (
 		'Checking decoded custom policy has two items'
 	);
 
-	t.equals(env.policy['n_out_of'].getN(), 1, 'Checking decoded custom policy has "1 out of"');
-	t.equals(env.policy['n_out_of'].getPolicies().length, 2, 'Checking decoded custom policy has two target policies');
+	t.equals(env.rule['n_out_of'].getN(), 1, 'Checking decoded custom policy has "1 out of"');
+	t.equals(env.rule['n_out_of'].getRules().length, 2, 'Checking decoded custom policy has two target policies');
 
 	t.doesNotThrow(
 		() => {
@@ -597,8 +597,8 @@ test('\n\n ** Channel _buildDefaultEndorsementPolicy() tests **\n\n', function (
 	);
 
 	env = _policiesProto.SignaturePolicyEnvelope.decode(policy);
-	t.equals(env.policy['n_out_of'].getN(), 2, 'Checking decoded custom policy has "2 out of"');
-	t.equals(env.policy['n_out_of'].getPolicies().length, 2, 'Checking decoded custom policy has two target policies');
+	t.equals(env.rule['n_out_of'].getN(), 2, 'Checking decoded custom policy has "2 out of"');
+	t.equals(env.rule['n_out_of'].getRules().length, 2, 'Checking decoded custom policy has two target policies');
 
 	t.doesNotThrow(
 		() => {
@@ -609,11 +609,11 @@ test('\n\n ** Channel _buildDefaultEndorsementPolicy() tests **\n\n', function (
 	);
 
 	env = _policiesProto.SignaturePolicyEnvelope.decode(policy);
-	t.equals(env.policy['n_out_of'].getN(), 2, 'Checking decoded custom policy has "2 out of"');
-	t.equals(env.policy['n_out_of'].getPolicies().length, 2, 'Checking decoded custom policy has two target policies');
-	t.equals(env.policy['n_out_of'].policies[0]['n_out_of'].getN(), 1, 'Checking decoded custom policy has "1 out of" inside the "2 out of"');
-	t.equals(env.policy['n_out_of'].policies[0]['n_out_of'].getPolicies().length, 2, 'Checking decoded custom policy has two target policies inside the "1 out of" inside the "2 out of"');
-	t.equals(env.policy['n_out_of'].policies[1]['signed_by'], 2, 'Checking decoded custom policy has "signed-by: 2" inside the "2 out of"');
+	t.equals(env.rule['n_out_of'].getN(), 2, 'Checking decoded custom policy has "2 out of"');
+	t.equals(env.rule['n_out_of'].getRules().length, 2, 'Checking decoded custom policy has two target policies');
+	t.equals(env.rule['n_out_of'].rules[0]['n_out_of'].getN(), 1, 'Checking decoded custom policy has "1 out of" inside the "2 out of"');
+	t.equals(env.rule['n_out_of'].rules[0]['n_out_of'].getRules().length, 2, 'Checking decoded custom policy has two target policies inside the "1 out of" inside the "2 out of"');
+	t.equals(env.rule['n_out_of'].rules[1]['signed_by'], 2, 'Checking decoded custom policy has "signed-by: 2" inside the "2 out of"');
 
 	t.doesNotThrow(
 		() => {
@@ -624,18 +624,18 @@ test('\n\n ** Channel _buildDefaultEndorsementPolicy() tests **\n\n', function (
 	);
 
 	env = _policiesProto.SignaturePolicyEnvelope.decode(policy);
-	t.equals(env.policy['n_out_of'].getN(), 2, 'Checking decoded custom policy has "2 out of"');
-	t.equals(env.policy['n_out_of'].getPolicies().length, 2, 'Checking decoded custom policy has two target policies');
-	t.equals(env.policy['n_out_of'].policies[0]['n_out_of'].getN(), 1, 'Checking decoded custom policy has "1 out of" inside the "2 out of"');
-	t.equals(env.policy['n_out_of'].policies[0]['n_out_of'].getPolicies().length, 2, 'Checking decoded custom policy has two target policies inside the "1 out of" inside the "2 out of"');
-	t.equals(env.policy['n_out_of'].policies[1]['n_out_of'].getN(), 1, 'Checking decoded custom policy has "1 out of" inside the "2 out of"');
-	t.equals(env.policy['n_out_of'].policies[1]['n_out_of'].getPolicies().length, 2, 'Checking decoded custom policy has two target policies inside the "1 out of" inside the "2 out of"');
-	t.equals(env.policy['n_out_of'].policies[1]['n_out_of'].getPolicies()[0]['n_out_of'].getN(), 2, 'Checking decoded custom policy has "2 out of " inside "1 out of" inside the "2 out of"');
-	t.equals(env.policy['n_out_of'].policies[1]['n_out_of'].getPolicies()[0]['n_out_of'].getPolicies().length, 3, 'Checking decoded custom policy has 3 target policies for "2 out of " inside "1 out of" inside the "2 out of"');
-	t.equals(env.policy['n_out_of'].policies[1]['n_out_of'].getPolicies()[1]['n_out_of'].getN(), 2, 'Checking decoded custom policy has "2 out of " inside "1 out of" inside the "2 out of"');
-	t.equals(env.policy['n_out_of'].policies[1]['n_out_of'].getPolicies()[1]['n_out_of'].getPolicies().length, 2, 'Checking decoded custom policy has 2 target policies for "2 out of " inside "1 out of" inside the "2 out of"');
-	t.equals(env.policy['n_out_of'].policies[1]['n_out_of'].getPolicies()[1]['n_out_of'].getPolicies()[0]['signed_by'], 2, 'Checking decoded custom policy has "signed-by: 2" for "2 out of " inside "1 out of" inside the "2 out of"');
-	t.equals(env.policy['n_out_of'].policies[1]['n_out_of'].getPolicies()[1]['n_out_of'].getPolicies()[1]['n_out_of'].getN(), 1, 'Checking decoded custom policy has "1 out of" inside "2 out of " inside "1 out of" inside the "2 out of"');
+	t.equals(env.rule['n_out_of'].getN(), 2, 'Checking decoded custom policy has "2 out of"');
+	t.equals(env.rule['n_out_of'].getRules().length, 2, 'Checking decoded custom policy has two target policies');
+	t.equals(env.rule['n_out_of'].rules[0]['n_out_of'].getN(), 1, 'Checking decoded custom policy has "1 out of" inside the "2 out of"');
+	t.equals(env.rule['n_out_of'].rules[0]['n_out_of'].getRules().length, 2, 'Checking decoded custom policy has two target policies inside the "1 out of" inside the "2 out of"');
+	t.equals(env.rule['n_out_of'].rules[1]['n_out_of'].getN(), 1, 'Checking decoded custom policy has "1 out of" inside the "2 out of"');
+	t.equals(env.rule['n_out_of'].rules[1]['n_out_of'].getRules().length, 2, 'Checking decoded custom policy has two target policies inside the "1 out of" inside the "2 out of"');
+	t.equals(env.rule['n_out_of'].rules[1]['n_out_of'].getRules()[0]['n_out_of'].getN(), 2, 'Checking decoded custom policy has "2 out of " inside "1 out of" inside the "2 out of"');
+	t.equals(env.rule['n_out_of'].rules[1]['n_out_of'].getRules()[0]['n_out_of'].getRules().length, 3, 'Checking decoded custom policy has 3 target policies for "2 out of " inside "1 out of" inside the "2 out of"');
+	t.equals(env.rule['n_out_of'].rules[1]['n_out_of'].getRules()[1]['n_out_of'].getN(), 2, 'Checking decoded custom policy has "2 out of " inside "1 out of" inside the "2 out of"');
+	t.equals(env.rule['n_out_of'].rules[1]['n_out_of'].getRules()[1]['n_out_of'].getRules().length, 2, 'Checking decoded custom policy has 2 target policies for "2 out of " inside "1 out of" inside the "2 out of"');
+	t.equals(env.rule['n_out_of'].rules[1]['n_out_of'].getRules()[1]['n_out_of'].getRules()[0]['signed_by'], 2, 'Checking decoded custom policy has "signed-by: 2" for "2 out of " inside "1 out of" inside the "2 out of"');
+	t.equals(env.rule['n_out_of'].rules[1]['n_out_of'].getRules()[1]['n_out_of'].getRules()[1]['n_out_of'].getN(), 1, 'Checking decoded custom policy has "1 out of" inside "2 out of " inside "1 out of" inside the "2 out of"');
 
 	t.end();
 });