Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update asset-transfer-sbe/chaincode-java #1192

Merged
merged 1 commit into from
Apr 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 2 additions & 12 deletions asset-transfer-sbe/chaincode-java/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,9 @@ group 'org.hyperledger.fabric.samples'
version '1.0-SNAPSHOT'

dependencies {

implementation 'org.hyperledger.fabric-chaincode-java:fabric-chaincode-shim:2.5.+'
implementation 'org.json:json:+'
implementation 'com.google.protobuf:protobuf-java:3.+'
implementation 'org.hyperledger.fabric-chaincode-java:fabric-chaincode-protos:2.4.1'
implementation 'com.owlike:genson:1.5'

testImplementation 'org.hyperledger.fabric-chaincode-java:fabric-chaincode-shim:2.5.+'
testImplementation 'org.junit.jupiter:junit-jupiter:5.4.2'
testImplementation 'org.assertj:assertj-core:3.11.1'
testImplementation 'org.mockito:mockito-core:2.+'
implementation 'org.hyperledger.fabric:fabric-protos:0.3.3'
implementation 'com.owlike:genson:1.6'
}

repositories {
Expand Down Expand Up @@ -79,8 +71,6 @@ test {
}
}

mainClassName = 'org.hyperledger.fabric.contract.ContractRouter'

shadowJar {
archiveBaseName = 'chaincode'
archiveVersion = ''
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,11 @@

package org.hyperledger.fabric.samples.sbe;

import java.util.Objects;

import com.owlike.genson.annotation.JsonProperty;
import org.hyperledger.fabric.contract.annotation.DataType;
import org.hyperledger.fabric.contract.annotation.Property;

import com.owlike.genson.annotation.JsonProperty;
import java.util.Objects;

@DataType()
public final class Asset {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,27 @@

package org.hyperledger.fabric.samples.sbe;

import com.owlike.genson.Genson;
import org.hyperledger.fabric.contract.Context;
import org.hyperledger.fabric.contract.ContractInterface;
import org.hyperledger.fabric.contract.annotation.Contract;
import org.hyperledger.fabric.contract.annotation.Default;
import org.hyperledger.fabric.contract.annotation.Info;
import org.hyperledger.fabric.contract.annotation.License;
import org.hyperledger.fabric.contract.annotation.Transaction;
import org.hyperledger.fabric.protos.common.MspPrincipal;
import org.hyperledger.fabric.protos.common.Policies;
import org.hyperledger.fabric.protos.common.MSPPrincipal;
import org.hyperledger.fabric.protos.common.MSPRole;
import org.hyperledger.fabric.protos.common.SignaturePolicy;
import org.hyperledger.fabric.protos.common.SignaturePolicyEnvelope;
import org.hyperledger.fabric.shim.ChaincodeException;
import org.hyperledger.fabric.shim.ChaincodeStub;
import org.hyperledger.fabric.shim.ext.sbe.StateBasedEndorsement;
import org.hyperledger.fabric.shim.ext.sbe.impl.StateBasedEndorsementFactory;

import com.owlike.genson.Genson;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

@Contract(
name = "sbe",
Expand All @@ -36,7 +37,6 @@
url = "http://www.apache.org/licenses/LICENSE-2.0.html")))
@Default
public final class AssetContract implements ContractInterface {

private final Genson genson = new Genson();

private enum AssetTransferErrors {
Expand Down Expand Up @@ -71,7 +71,7 @@ public Asset CreateAsset(final Context ctx, final String assetId, final int valu
stub.putStringState(assetId, assetJSON);

// 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});
setStateBasedEndorsement(ctx, assetId, List.of(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
// setStateBasedEndorsementNOutOf(ctx, assetId, 1, new String[]{"Org1MSP", "Org2MSP"});
Expand Down Expand Up @@ -165,10 +165,10 @@ public Asset TransferAsset(final Context ctx, final String assetId, final String
stub.putStringState(assetId, updatedAssetJSON);

// 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});
setStateBasedEndorsement(ctx, assetId, List.of(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"});
// setStateBasedEndorsementNOutOf(ctx, assetId, 1, List.of("Org1MSP", "Org2MSP"));

return asset;
}
Expand Down Expand Up @@ -205,9 +205,9 @@ private static String getClientOrgId(final Context ctx) {
* @param assetId the id of the asset
* @param ownerOrgs the list of Owner Org MSPID's
*/
private static void setStateBasedEndorsement(final Context ctx, final String assetId, final String[] ownerOrgs) {
private static void setStateBasedEndorsement(final Context ctx, final String assetId, final List<String> ownerOrgs) {
StateBasedEndorsement stateBasedEndorsement = StateBasedEndorsementFactory.getInstance().newStateBasedEndorsement(null);
stateBasedEndorsement.addOrgs(StateBasedEndorsement.RoleType.RoleTypeMember, ownerOrgs);
stateBasedEndorsement.addOrgs(StateBasedEndorsement.RoleType.RoleTypeMember, ownerOrgs.toArray(new String[0]));
ctx.getStub().setStateValidationParameter(assetId, stateBasedEndorsement.policy());
}

Expand All @@ -220,36 +220,50 @@ private static void setStateBasedEndorsement(final Context ctx, final String ass
* @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 setStateBasedEndorsementNOutOf(final Context ctx, final String assetId, final int nOrgs, final String[] ownerOrgs) {
ctx.getStub().setStateValidationParameter(assetId, policy(nOrgs, Arrays.asList(ownerOrgs)));
private static void setStateBasedEndorsementNOutOf(final Context ctx, final String assetId, final int nOrgs, final List<String> ownerOrgs) {
ctx.getStub().setStateValidationParameter(assetId, policy(nOrgs, ownerOrgs));
}

/**
* 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 Org principals signatures required to endorse (out of the provided list of Orgs)
* @param mspids the list of Owner Org MSPID's
* @param mspIds the list of Owner Org MSPID's
*/
private static byte[] policy(final int nOrgs, final List<String> mspids) {
mspids.sort(Comparator.naturalOrder());
final List<MspPrincipal.MSPPrincipal> principals = new ArrayList<>();
final List<Policies.SignaturePolicy> signPolicy = new ArrayList<>();
for (int i = 0; i < mspids.size(); i++) {
final String mspid = mspids.get(i);
principals.add(MspPrincipal.MSPPrincipal.newBuilder().setPrincipalClassification(MspPrincipal.MSPPrincipal.Classification.ROLE)
.setPrincipal(MspPrincipal.MSPRole.newBuilder().setMspIdentifier(mspid).setRole(MspPrincipal.MSPRole.MSPRoleType.MEMBER).build().toByteString()).build());
signPolicy.add(signedBy(i));
}
// Create the policy such that it requires any N signature's from all of the principals provided
return Policies.SignaturePolicyEnvelope.newBuilder().setVersion(0).setRule(nOutOf(nOrgs, signPolicy))
.addAllIdentities(principals).build().toByteArray();
private static byte[] policy(final int nOrgs, final List<String> mspIds) {
mspIds.sort(Comparator.naturalOrder());

var principals = mspIds.stream()
.map(mspId -> MSPRole.newBuilder()
.setMspIdentifier(mspId)
.setRole(MSPRole.MSPRoleType.MEMBER)
.build())
.map(role -> MSPPrincipal.newBuilder()
.setPrincipalClassification(MSPPrincipal.Classification.ROLE)
.setPrincipal(role.toByteString())
.build())
.collect(Collectors.toList());

var signPolicy = IntStream.range(0, mspIds.size())
.mapToObj(AssetContract::signedBy)
.collect(Collectors.toList());

// Create the policy such that it requires any N signature's from all the principals provided
return SignaturePolicyEnvelope.newBuilder()
.setVersion(0)
.setRule(nOutOf(nOrgs, signPolicy))
.addAllIdentities(principals)
.build()
.toByteArray();
}

private static Policies.SignaturePolicy signedBy(final int index) {
return Policies.SignaturePolicy.newBuilder().setSignedBy(index).build();
private static SignaturePolicy signedBy(final int index) {
return SignaturePolicy.newBuilder().setSignedBy(index).build();
}

private static Policies.SignaturePolicy nOutOf(final int n, final List<Policies.SignaturePolicy> policies) {
return Policies.SignaturePolicy.newBuilder().setNOutOf(Policies.SignaturePolicy.NOutOf.newBuilder().setN(n).addAllRules(policies).build()).build();
private static SignaturePolicy nOutOf(final int n, final List<SignaturePolicy> policies) {
return SignaturePolicy.newBuilder().setNOutOf(
SignaturePolicy.NOutOf.newBuilder().setN(n).addAllRules(policies).build()
).build();
}
}
Loading