Skip to content

Commit

Permalink
Introduce Anchor peer API and other refractoring
Browse files Browse the repository at this point in the history
Signed-off-by: n0s09by <[email protected]>
  • Loading branch information
nidhi-singh02 committed Jan 3, 2024
1 parent 75664d6 commit f827021
Show file tree
Hide file tree
Showing 12 changed files with 493 additions and 191 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package hlf.java.rest.client.controller;

import hlf.java.rest.client.model.AnchorPeerParamsDTO;
import hlf.java.rest.client.model.ClientResponseModel;
import hlf.java.rest.client.model.CommitChannelParamsDTO;
import hlf.java.rest.client.model.NewOrgParamsDTO;
Expand Down Expand Up @@ -105,7 +106,6 @@ public ResponseEntity<ClientResponseModel> addOrgToChannel(
@RequestBody @Validated NewOrgParamsDTO organizationDetails) {
return networkStatus.addOrgToChannel(channelName, organizationDetails);
}

/**
* Use to decode an base64 encoded json file, with options to also decode the interior elements
* and/or print the output in a cleaner format
Expand All @@ -126,4 +126,21 @@ public ResponseEntity<ClientResponseModel> getDeserializedJson(
@RequestParam(name = "prettyPrint", required = true) boolean prettyPrint) {
return serializationUtil.decodeContents(encodedJson, decodeInterior, prettyPrint);
}

/**
* Add anchor peer(s) of an organization to a channel. Anchor peer addition should be done once
* the peer nodes of the organization have joined the channel.
*
* @param channelName - the name of the channel for which you wish to add the anchor peer nodes
* to.
* @param anchorPeerParamsDTO - contains the details for the organization peers you wish to be
* added to the channel as anchor peer.
* @return ResponseEntity<ClientResponseModel> - contains the result of the operation.
*/
@PostMapping(value = "/channel/{channelName}/add_anchor_peer")
public ResponseEntity<ClientResponseModel> addAnchorPeersToChannel(
@PathVariable @Validated String channelName,
@RequestBody @Validated AnchorPeerParamsDTO anchorPeerParamsDTO) {
return networkStatus.addAnchorPeersToChannel(channelName, anchorPeerParamsDTO);
}
}
10 changes: 10 additions & 0 deletions src/main/java/hlf/java/rest/client/model/AnchorPeerParamsDTO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package hlf.java.rest.client.model;

import java.util.List;
import lombok.Data;

@Data
public class AnchorPeerParamsDTO {
private String organizationMspId;
private List<AnchorPeerDTO> anchorPeerDTOs;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package hlf.java.rest.client.service;

import hlf.java.rest.client.exception.ServiceException;
import hlf.java.rest.client.model.AnchorPeerParamsDTO;
import org.hyperledger.fabric.protos.common.Configtx.ConfigGroup;

public interface AddAnchorPeerToChannelWriteSetBuilder {

ConfigGroup buildWriteSetForAnchorPeers(
ConfigGroup readset, AnchorPeerParamsDTO anchorPeerParamsDTO) throws ServiceException;
}
4 changes: 4 additions & 0 deletions src/main/java/hlf/java/rest/client/service/NetworkStatus.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package hlf.java.rest.client.service;

import hlf.java.rest.client.model.AnchorPeerParamsDTO;
import hlf.java.rest.client.model.ClientResponseModel;
import hlf.java.rest.client.model.CommitChannelParamsDTO;
import hlf.java.rest.client.model.NewOrgParamsDTO;
Expand All @@ -20,4 +21,7 @@ ResponseEntity<ClientResponseModel> commitChannelConfigTransaction(

ResponseEntity<ClientResponseModel> addOrgToChannel(
String channelName, NewOrgParamsDTO organizationDetails);

ResponseEntity<ClientResponseModel> addAnchorPeersToChannel(
String channelName, AnchorPeerParamsDTO anchorPeerParamsDTO);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package hlf.java.rest.client.service.impl;

import hlf.java.rest.client.exception.ServiceException;
import hlf.java.rest.client.model.AnchorPeerDTO;
import hlf.java.rest.client.model.AnchorPeerParamsDTO;
import hlf.java.rest.client.service.AddAnchorPeerToChannelWriteSetBuilder;
import hlf.java.rest.client.util.FabricChannelUtil;
import hlf.java.rest.client.util.FabricClientConstants;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.hyperledger.fabric.protos.common.Configtx.ConfigGroup;
import org.hyperledger.fabric.protos.common.Configtx.ConfigValue;
import org.hyperledger.fabric.protos.peer.Configuration.AnchorPeer;
import org.hyperledger.fabric.protos.peer.Configuration.AnchorPeers;
import org.springframework.stereotype.Service;

@Service
public class AddAnchorPeerToChannelWriteSetBuilderImpl
implements AddAnchorPeerToChannelWriteSetBuilder {

private AnchorPeerParamsDTO anchorPeerParamsDTO;

@Override
public ConfigGroup buildWriteSetForAnchorPeers(
ConfigGroup readset, AnchorPeerParamsDTO anchorPeerParamsDTO) throws ServiceException {
this.anchorPeerParamsDTO = anchorPeerParamsDTO;
String orgMspId = anchorPeerParamsDTO.getOrganizationMspId();
Map<String, ConfigGroup> existingOrganizations =
FabricChannelUtil.getExistingOrgsFromReadset(readset);
// The "Application" group
ConfigGroup applicationGroup =
ConfigGroup.newBuilder()
.setModPolicy(FabricClientConstants.CHANNEL_CONFIG_MOD_POLICY_ADMINS)
.putAllPolicies(FabricChannelUtil.setApplicationPolicies(readset))
.putGroups(orgMspId, setAnchorPeerInGroup(orgMspId, readset))
// putAllGroups excludes new organization
.putAllGroups(existingOrganizations)
// Application group version
.setVersion(
FabricChannelUtil.retrieveMSPGroupVersionFromReadset(
readset, FabricClientConstants.CHANNEL_CONFIG_GROUP_APPLICATION)
+ 1) // will be tied to current version + 1 for this level
.build();
// the "/Channel" group
return ConfigGroup.newBuilder()
.putGroups(FabricClientConstants.CHANNEL_CONFIG_GROUP_APPLICATION, applicationGroup)
.setModPolicy(FabricClientConstants.CHANNEL_CONFIG_MOD_POLICY_ADMINS)
// Channel group version
.setVersion(readset.getVersion())
.build();
}

private ConfigGroup setAnchorPeerInGroup(String orgMspId, ConfigGroup readSet) {
Map<String, ConfigValue> valueMap = new HashMap<>();
if (anchorPeerParamsDTO.getAnchorPeerDTOs() != null) {
valueMap.put(
FabricClientConstants.CHANNEL_CONFIG_GROUP_VALUE_ANCHORPEERS, setNewOrgAnchorPeerValue());
}
return ConfigGroup.newBuilder()
.setModPolicy(FabricClientConstants.CHANNEL_CONFIG_MOD_POLICY_ADMINS)
.putAllPolicies(FabricChannelUtil.getDefaultRolePolicy(orgMspId))
.putAllValues(valueMap)
.setVersion(
FabricChannelUtil.retrieveMSPGroupVersionFromReadset(
readSet, FabricClientConstants.CHANNEL_CONFIG_GROUP_APPLICATION)
+ 1)
.build();
}

private ConfigValue setNewOrgAnchorPeerValue() {
return ConfigValue.newBuilder()
.setModPolicy(FabricClientConstants.CHANNEL_CONFIG_MOD_POLICY_ADMINS)
.setValue(setAnchorPeers().toByteString())
.setVersion(0)
.build();
}

private AnchorPeers setAnchorPeers() {
List<AnchorPeer> anchorPeerList = new ArrayList<>();
for (AnchorPeerDTO anchorPeerDTO : anchorPeerParamsDTO.getAnchorPeerDTOs()) {
anchorPeerList.add(
AnchorPeer.newBuilder()
.setHost(anchorPeerDTO.getHostname())
.setPort(anchorPeerDTO.getPort())
.build());
}
return AnchorPeers.newBuilder().addAllAnchorPeers(anchorPeerList).build();
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package hlf.java.rest.client.service.impl;

import com.google.protobuf.ByteString;
import hlf.java.rest.client.exception.ErrorCode;
import hlf.java.rest.client.exception.ServiceException;
import hlf.java.rest.client.model.AnchorPeerDTO;
import hlf.java.rest.client.model.NewOrgParamsDTO;
Expand All @@ -12,9 +11,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.hyperledger.fabric.protos.common.Configtx.ConfigGroup;
import org.hyperledger.fabric.protos.common.Configtx.ConfigPolicy;
import org.hyperledger.fabric.protos.common.Configtx.ConfigValue;
import org.hyperledger.fabric.protos.msp.MspConfigPackage.FabricCryptoConfig;
import org.hyperledger.fabric.protos.msp.MspConfigPackage.FabricMSPConfig;
Expand All @@ -29,48 +26,28 @@
public class AddOrgToChannelWriteSetBuilderImpl implements AddOrgToChannelWriteSetBuilder {

private NewOrgParamsDTO organizationDetails;
private static final int DEFAULT_VERSION = 0;

@Override
public ConfigGroup buildWriteset(ConfigGroup readset, NewOrgParamsDTO organizationDetails)
throws ServiceException {
this.organizationDetails = organizationDetails;
String newOrgMspId = organizationDetails.getOrganizationMspId();
// Get existing organizations in the channel and set with as objects and their
// version to prevent deletion or modification
// Omitting existing groups results in their deletion.
Map<String, ConfigGroup> existingOrganizations = new HashMap<>();
ConfigGroup applicationConfigGroup =
readset.getGroupsOrThrow(FabricClientConstants.CHANNEL_CONFIG_GROUP_APPLICATION);
applicationConfigGroup
.getGroupsMap()
.forEach(
(k, v) ->
existingOrganizations.put(
k,
setEmptyGroup(retrieveMSPGroupVersionFromReadset(applicationConfigGroup, k))));
Map<String, ConfigGroup> existingOrganizations =
FabricChannelUtil.getExistingOrgsFromReadset(readset);

// The "Application" group
ConfigGroup applicationGroup =
ConfigGroup.newBuilder()
.setModPolicy(FabricClientConstants.CHANNEL_CONFIG_MOD_POLICY_ADMINS)
.putAllPolicies(setApplicationPolicies(readset))
.putAllPolicies(FabricChannelUtil.setApplicationPolicies(readset))
.putGroups(newOrgMspId, setNewOrgGroup(newOrgMspId))
// putAllGroups excludes new organization
.putAllGroups(existingOrganizations)
// Application group version
.setVersion(
retrieveMSPGroupVersionFromReadset(
FabricChannelUtil.retrieveMSPGroupVersionFromReadset(
readset, FabricClientConstants.CHANNEL_CONFIG_GROUP_APPLICATION)
+ 1) // will
// be
// tied
// to
// current
// version
// + 1
// for
// this
// level
+ 1) // will be tied to current version + 1 for this level
.build();
// the "/Channel" group
return ConfigGroup.newBuilder()
Expand All @@ -81,89 +58,6 @@ public ConfigGroup buildWriteset(ConfigGroup readset, NewOrgParamsDTO organizati
.build();
}

private long retrieveMSPGroupVersionFromReadset(ConfigGroup readset, String mspId)
throws ServiceException {
long versionLong = DEFAULT_VERSION;
try {
ConfigGroup group = readset.getGroupsOrThrow(mspId);
versionLong = group.getVersion();
} catch (IllegalArgumentException e) {
throw new ServiceException(
ErrorCode.NOT_FOUND,
"WriteBuilder version iteration error: ConfigGroup with name - \""
+ mspId
+ "\" - not found in Readset",
e);
}
return versionLong;
}

private Map<String, Long> retrievePolicyVersionFromReadset(ConfigGroup readset, String groupName)
throws ServiceException {
Map<String, Long> map = new HashMap<>();
try {
ConfigGroup group = readset.getGroupsOrThrow(groupName);
for (Entry<String, ConfigPolicy> entry : group.getPoliciesMap().entrySet()) {
map.put(entry.getKey(), entry.getValue().getVersion());
}
} catch (IllegalArgumentException e) {
throw new ServiceException(
ErrorCode.NOT_FOUND,
"WriteBuilder version iteration error: ConfigGroup with name - \""
+ groupName
+ "\" - not found in Readset",
e);
}
return map;
}

private Map<String, ConfigPolicy> setApplicationPolicies(ConfigGroup readset) {
Map<String, Long> map =
retrievePolicyVersionFromReadset(
readset, FabricClientConstants.CHANNEL_CONFIG_GROUP_APPLICATION);
ConfigPolicy adminPolicy =
ConfigPolicy.newBuilder()
.setModPolicy("")
.setVersion(map.get(FabricClientConstants.CHANNEL_CONFIG_POLICY_TYPE_ADMINS))
.build();
ConfigPolicy endorsementPolicy =
ConfigPolicy.newBuilder()
.setModPolicy("")
.setVersion(map.get(FabricClientConstants.CHANNEL_CONFIG_POLICY_TYPE_ENDORSEMENT))
.build();
ConfigPolicy lifeCycleEndorsementPolicy =
ConfigPolicy.newBuilder()
.setModPolicy("")
.setVersion(
map.get(FabricClientConstants.CHANNEL_CONFIG_POLICY_TYPE_LIFECYCLE_ENDORSEMENT))
.build();
ConfigPolicy readerPolicy =
ConfigPolicy.newBuilder()
.setModPolicy("")
.setVersion(map.get(FabricClientConstants.CHANNEL_CONFIG_POLICY_TYPE_READERS))
.build();
ConfigPolicy writerPolicy =
ConfigPolicy.newBuilder()
.setModPolicy("")
.setVersion(map.get(FabricClientConstants.CHANNEL_CONFIG_POLICY_TYPE_WRITERS))
.build();
Map<String, ConfigPolicy> applicationPoliciesMap = new HashMap<>();
// add Admins, Readers, Writers, Endorsement and LifeCycle Endorsement policies at the channel
// level
applicationPoliciesMap.put(
FabricClientConstants.CHANNEL_CONFIG_POLICY_TYPE_ADMINS, adminPolicy);
applicationPoliciesMap.put(
FabricClientConstants.CHANNEL_CONFIG_POLICY_TYPE_ENDORSEMENT, endorsementPolicy);
applicationPoliciesMap.put(
FabricClientConstants.CHANNEL_CONFIG_POLICY_TYPE_LIFECYCLE_ENDORSEMENT,
lifeCycleEndorsementPolicy);
applicationPoliciesMap.put(
FabricClientConstants.CHANNEL_CONFIG_POLICY_TYPE_READERS, readerPolicy);
applicationPoliciesMap.put(
FabricClientConstants.CHANNEL_CONFIG_POLICY_TYPE_WRITERS, writerPolicy);
return applicationPoliciesMap;
}

private ConfigGroup setNewOrgGroup(String newOrgMspId) {
Map<String, ConfigValue> valueMap = new HashMap<>();
valueMap.put(
Expand All @@ -181,10 +75,6 @@ private ConfigGroup setNewOrgGroup(String newOrgMspId) {
.build();
}

private ConfigGroup setEmptyGroup(long version) {
return ConfigGroup.newBuilder().setModPolicy("").setVersion(version).build();
}

private ConfigValue setNewOrgMspValue(String newOrgMspId) {
return ConfigValue.newBuilder()
.setModPolicy(FabricClientConstants.CHANNEL_CONFIG_MOD_POLICY_ADMINS)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,9 @@ private Common.Envelope getChannelCreationTransaction(
*/
private Configtx.ConfigUpdate newConfigUpdate(ChannelOperationRequest channelOperationRequest) {
Map<String, MSPDTO> mspMap = new HashMap<>();
channelOperationRequest.getPeers().forEach(p -> mspMap.putIfAbsent(p.getMspid(), p.getMspDTO()));
channelOperationRequest
.getPeers()
.forEach(p -> mspMap.putIfAbsent(p.getMspid(), p.getMspDTO()));
return Configtx.ConfigUpdate.newBuilder()
.setChannelId(channelOperationRequest.getChannelName())
.setReadSet(newChannelGroup(channelOperationRequest.getConsortiumName(), mspMap, false))
Expand Down
Loading

0 comments on commit f827021

Please sign in to comment.