mirror of
https://github.com/hyperledger/fabric-samples.git
synced 2026-06-17 07:25:10 +00:00
add setStateBasedEndorsementNOutOf for typescript chaincode (#330)
Signed-off-by: Gaurav Giri <girigaurav@gmail.com>
This commit is contained in:
parent
6d196bd9df
commit
a432e7d70c
3 changed files with 75 additions and 21 deletions
|
|
@ -19,7 +19,7 @@ state-based endorsement, visit the
|
|||
[Endorsement Policies](https://hyperledger-fabric.readthedocs.io/en/release-2.2/endorsement-policies.html)
|
||||
topic in the Fabric documentation.
|
||||
|
||||
The implementation provided by State Based interface creates a policy which requires signatures from all the Org principals added, and hence is equivalent to an AND policy. For other advanced State Based policy implementations which are not supported by State Based interface directly like OR or NOutOf policies, please refer to method implementations setAssetStateBasedEndorsementWithNOutOfPolicy(), which can be used as an alternative for setAssetStateBasedEndorsement() inside asset-transfer-sbe smart contracts.
|
||||
The implementation provided by State Based interface creates a policy which requires signatures from all the Org principals added, and hence is equivalent to an AND policy. For other advanced State Based policy implementations which are not supported by State Based interface directly like OR or NOutOf policies, please refer to method implementations setStateBasedEndorsementNOutOf(), which can be used as an alternative for setStateBasedEndorsement() inside asset-transfer-sbe smart contracts.
|
||||
|
||||
## About the Sample
|
||||
|
||||
|
|
|
|||
|
|
@ -70,11 +70,11 @@ public final class AssetContract implements ContractInterface {
|
|||
String assetJSON = genson.serialize(asset);
|
||||
stub.putStringState(assetId, assetJSON);
|
||||
|
||||
// Set the endorsement policy of the assetId Key, such that current owner Org Peer is required to endorse future updates
|
||||
setAssetStateBasedEndorsement(ctx, assetId, new String[]{ownerOrg});
|
||||
// Set the endorsement policy of the assetId Key, such that current owner Org is required to endorse future updates
|
||||
setStateBasedEndorsement(ctx, assetId, new String[]{ownerOrg});
|
||||
|
||||
// Optionally, set the endorsement policy of the assetId Key, such that any 1(N) out of the Org's specified can endorse future updates
|
||||
// setAssetStateBasedEndorsementWithNOutOfPolicy(ctx, assetId, 1, new String[]{"Org1MSP", "Org2MSP"});
|
||||
// Optionally, set the endorsement policy of the assetId Key, such that any 1 Org (N) out of the specified Orgs can endorse future updates
|
||||
// setStateBasedEndorsementNOutOf(ctx, assetId, 1, new String[]{"Org1MSP", "Org2MSP"});
|
||||
|
||||
return asset;
|
||||
}
|
||||
|
|
@ -164,7 +164,11 @@ public final class AssetContract implements ContractInterface {
|
|||
String updatedAssetJSON = genson.serialize(asset);
|
||||
stub.putStringState(assetId, updatedAssetJSON);
|
||||
|
||||
setAssetStateBasedEndorsement(ctx, assetId, new String[]{newOwnerOrg});
|
||||
// Re-Set the endorsement policy of the assetId Key, such that a new owner Org Peer is required to endorse future updates
|
||||
setStateBasedEndorsement(ctx, assetId, new String[]{newOwnerOrg});
|
||||
|
||||
// Optionally, set the endorsement policy of the assetId Key, such that any 1 Org (N) out of the specified Orgs can endorse future updates
|
||||
// setStateBasedEndorsementNOutOf(ctx, assetId, 1, new String[]{"Org1MSP", "Org2MSP"});
|
||||
|
||||
return asset;
|
||||
}
|
||||
|
|
@ -195,13 +199,13 @@ public final class AssetContract implements ContractInterface {
|
|||
|
||||
/**
|
||||
* Sets an endorsement policy to the assetId Key.
|
||||
* Enforces that the owner Org Peers must endorse future update transactions for the specified assetId Key.
|
||||
* Enforces that the owner Org must endorse future update transactions for the specified assetId Key.
|
||||
*
|
||||
* @param ctx the transaction context
|
||||
* @param assetId the id of the asset
|
||||
* @param ownerOrgs the list of Owner Org MSPID's
|
||||
*/
|
||||
private static void setAssetStateBasedEndorsement(final Context ctx, final String assetId, final String[] ownerOrgs) {
|
||||
private static void setStateBasedEndorsement(final Context ctx, final String assetId, final String[] ownerOrgs) {
|
||||
StateBasedEndorsement stateBasedEndorsement = StateBasedEndorsementFactory.getInstance().newStateBasedEndorsement(null);
|
||||
stateBasedEndorsement.addOrgs(StateBasedEndorsement.RoleType.RoleTypeMember, ownerOrgs);
|
||||
ctx.getStub().setStateValidationParameter(assetId, stateBasedEndorsement.policy());
|
||||
|
|
@ -209,21 +213,21 @@ public final class AssetContract implements ContractInterface {
|
|||
|
||||
/**
|
||||
* Sets an endorsement policy to the assetId Key.
|
||||
* Enforces that any N out of the Org's Peers specified must endorse future update transactions for the specified assetId Key.
|
||||
* Enforces that a given number of Orgs (N) out of the specified Orgs must endorse future update transactions for the specified assetId Key.
|
||||
*
|
||||
* @param ctx the transaction context
|
||||
* @param assetId the id of the asset
|
||||
* @param nOrgs the number of N Orgs to endorse out of the list of Orgs provided
|
||||
* @param ownerOrgs the list of Owner Org MSPID's
|
||||
*/
|
||||
private static void setAssetStateBasedEndorsementWithNOutOfPolicy(final Context ctx, final String assetId, final int nOrgs, final String[] ownerOrgs) {
|
||||
private static void setStateBasedEndorsementNOutOf(final Context ctx, final String assetId, final int nOrgs, final String[] ownerOrgs) {
|
||||
ctx.getStub().setStateValidationParameter(assetId, policy(nOrgs, Arrays.asList(ownerOrgs)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the policy such that it requires any N signature's from all of the principals provided
|
||||
* Create a policy that requires a given number (N) of Org principals signatures out of the provided list of Orgs
|
||||
*
|
||||
* @param nOrgs the number of N Org signature's to endorse out of the list of Orgs provided
|
||||
* @param nOrgs the number of Org principals signatures required to endorse (out of the provided list of Orgs)
|
||||
* @param mspids the list of Owner Org MSPID's
|
||||
*/
|
||||
private static byte[] policy(final int nOrgs, final List<String> mspids) {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
import { Context, Contract, Info, Transaction } from 'fabric-contract-api';
|
||||
import { Asset } from './asset';
|
||||
import { KeyEndorsementPolicy } from 'fabric-shim';
|
||||
import * as fabprotos from 'fabric-shim/bundle';
|
||||
|
||||
@Info({title: 'AssetContract', description: 'Asset Transfer Smart Contract, using State Based Endorsement(SBE), implemented in TypeScript' })
|
||||
export class AssetContract extends Contract {
|
||||
|
|
@ -26,8 +27,12 @@ export class AssetContract extends Contract {
|
|||
const buffer = Buffer.from(JSON.stringify(asset));
|
||||
// Create the asset
|
||||
await ctx.stub.putState(assetId, buffer);
|
||||
// Set the endorsement policy of the assetId Key, such that current owner Org Peer is required to endorse future updates
|
||||
await AssetContract.setAssetStateBasedEndorsement(ctx, asset.ID, [ownerOrg]);
|
||||
|
||||
// Set the endorsement policy of the assetId Key, such that current owner Org is required to endorse future updates
|
||||
await AssetContract.setStateBasedEndorsement(ctx, assetId, [ownerOrg]);
|
||||
|
||||
// Optionally, set the endorsement policy of the assetId Key, such that any 1 Org (N) out of the specified Orgs can endorse future updates
|
||||
// await AssetContract.setStateBasedEndorsementNOutOf(ctx, assetId, 1, ["Org1MSP", "Org2MSP"]);
|
||||
}
|
||||
|
||||
// ReadAsset returns asset with given assetId
|
||||
|
|
@ -78,7 +83,10 @@ export class AssetContract extends Contract {
|
|||
// Update the asset
|
||||
await ctx.stub.putState(assetId, Buffer.from(JSON.stringify(asset)));
|
||||
// Re-Set the endorsement policy of the assetId Key, such that a new owner Org Peer is required to endorse future updates
|
||||
await AssetContract.setAssetStateBasedEndorsement(ctx, asset.ID, [newOwnerOrg]);
|
||||
await AssetContract.setStateBasedEndorsement(ctx, asset.ID, [newOwnerOrg]);
|
||||
|
||||
// Optionally, set the endorsement policy of the assetId Key, such that any 1 Org (N) out of the specified Orgs can endorse future updates
|
||||
// await AssetContract.setStateBasedEndorsementNOutOf(ctx, assetId, 1, ["Org1MSP", "Org2MSP"]);
|
||||
}
|
||||
|
||||
// AssetExists returns true when asset with given ID exists
|
||||
|
|
@ -87,16 +95,58 @@ export class AssetContract extends Contract {
|
|||
return (!!buffer && buffer.length > 0);
|
||||
}
|
||||
|
||||
// setAssetStateBasedEndorsement sets an endorsement policy to the assetId Key
|
||||
// setAssetStateBasedEndorsement enforces that the owner Org Peers must endorse future update transactions for the specified assetId Key
|
||||
private static async setAssetStateBasedEndorsement(ctx: Context, assetId: string, ownerOrgs: string[]): Promise<void> {
|
||||
// getClientOrgId gets the client's OrgId (MSPID)
|
||||
private static getClientOrgId(ctx: Context): string {
|
||||
return ctx.clientIdentity.getMSPID();
|
||||
}
|
||||
|
||||
// setStateBasedEndorsement sets an endorsement policy to the assetId Key
|
||||
// setStateBasedEndorsement enforces that the owner Org must endorse future update transactions for the specified assetId Key
|
||||
private static async setStateBasedEndorsement(ctx: Context, assetId: string, ownerOrgs: string[]): Promise<void> {
|
||||
const ep = new KeyEndorsementPolicy();
|
||||
ep.addOrgs('MEMBER', ...ownerOrgs);
|
||||
await ctx.stub.setStateValidationParameter(assetId, ep.getPolicy());
|
||||
}
|
||||
|
||||
// getClientOrgId gets the client's OrgId (MSPID)
|
||||
private static getClientOrgId(ctx: Context): string {
|
||||
return ctx.clientIdentity.getMSPID();
|
||||
// setStateBasedEndorsementNOutOf sets an endorsement policy to the assetId Key
|
||||
// setStateBasedEndorsementNOutOf enforces that a given number of Orgs (N) out of the specified Orgs must endorse future update transactions for the specified assetId Key.
|
||||
private static async setStateBasedEndorsementNOutOf(ctx: Context, assetId: string, nOrgs:number, ownerOrgs: string[]): Promise<void> {
|
||||
await ctx.stub.setStateValidationParameter(assetId, AssetContract.policy(nOrgs, ownerOrgs));
|
||||
}
|
||||
|
||||
// Create a policy that requires a given number (N) of Org principals signatures out of the provided list of Orgs
|
||||
private static policy(nOrgs: number, mspIds: string[]): Uint8Array {
|
||||
const principals = [];
|
||||
const sigsPolicies = [];
|
||||
mspIds.forEach((mspId, i) => {
|
||||
const mspRole = {
|
||||
role: fabprotos.common.MSPRole.MSPRoleType.MEMBER,
|
||||
mspIdentifier: mspId
|
||||
};
|
||||
const principal = {
|
||||
principalClassification: fabprotos.common.MSPPrincipal.Classification.ROLE,
|
||||
principal: fabprotos.common.MSPRole.encode(mspRole).finish()
|
||||
};
|
||||
principals.push(principal);
|
||||
const signedBy = {
|
||||
signedBy: i,
|
||||
};
|
||||
sigsPolicies.push(signedBy);
|
||||
});
|
||||
|
||||
// create the policy such that it requires any N signature's from all of the principals provided
|
||||
const allOf = {
|
||||
n: nOrgs,
|
||||
rules: sigsPolicies
|
||||
};
|
||||
const noutof = {
|
||||
nOutOf: allOf
|
||||
};
|
||||
const spe = {
|
||||
version: 0,
|
||||
rule: noutof,
|
||||
identities: principals
|
||||
};
|
||||
return fabprotos.common.SignaturePolicyEnvelope.encode(spe).finish();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue