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

Introduce capability to get anchor peer nodes in a channel #133

Merged
merged 3 commits into from
Feb 20, 2024
Merged
Show file tree
Hide file tree
Changes from 2 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
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,18 @@ public class FabricOperationsController {

@Autowired private SerializationUtil serializationUtil;

/**
* Get the anchor peers defined in a channel.
*
* @param channelName - the name of the channel for which you will retrieve the anchor peer nodes
* @return ResponseEntity<ClientResponseModel> - contains the list of anchor peers in a particular
* channel
*/
@GetMapping(value = "/channel/{channelName}/anchor_peers")
public ResponseEntity<ClientResponseModel> getAnchorPeerForChannel(
nidhi-singh02 marked this conversation as resolved.
Show resolved Hide resolved
@PathVariable @Validated String channelName) {
return networkStatus.getAnchorPeerForChannel(channelName);
}
/**
* Obtain the channel configuration details.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ public interface NetworkStatus {

ResponseEntity<ClientResponseModel> getChannelFromNetwork(String channelName);

ResponseEntity<ClientResponseModel> getAnchorPeerForChannel(String channelName);

ResponseEntity<ClientResponseModel> signChannelConfigTransaction(
String channelName, String configUpdate);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,24 @@
import hlf.java.rest.client.service.ChannelConfigDeserialization;
import hlf.java.rest.client.service.NetworkStatus;
import hlf.java.rest.client.service.UpdateChannel;
import hlf.java.rest.client.util.FabricClientConstants;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import lombok.extern.slf4j.Slf4j;
import org.hyperledger.fabric.gateway.Gateway;
import org.hyperledger.fabric.gateway.Network;
import org.hyperledger.fabric.protos.common.Configtx;
import org.hyperledger.fabric.protos.common.Configtx.Config;
import org.hyperledger.fabric.protos.common.Configtx.ConfigGroup;
import org.hyperledger.fabric.protos.common.Configtx.ConfigUpdate;
import org.hyperledger.fabric.protos.peer.Configuration;
import org.hyperledger.fabric.sdk.Channel;
import org.hyperledger.fabric.sdk.UpdateChannelConfiguration;
import org.hyperledger.fabric.sdk.User;
Expand Down Expand Up @@ -55,6 +63,74 @@ private String getDeserializedConfig(MessageOrBuilder message) {
return Base64.getEncoder().encodeToString(channelConfigString.getBytes());
}

private Set<String> getAnchorPeersFromOrgConfigGroup(
Collection<String> peersOrganizationMSPIDs, ConfigGroup application)
throws InvalidProtocolBufferException {
Set<String> anchorPeersSet = new HashSet<>();
for (String peerOrganizationMSPID : peersOrganizationMSPIDs) {
ConfigGroup peerOrgConfigGroup = application.getGroupsMap().get(peerOrganizationMSPID);
if (peerOrgConfigGroup != null) {
Map<String, Configtx.ConfigValue> valuesMap = peerOrgConfigGroup.getValuesMap();
Configtx.ConfigValue anchorPeers =
valuesMap.get(FabricClientConstants.CHANNEL_CONFIG_GROUP_VALUE_ANCHORPEERS);
if (null != anchorPeers && anchorPeers.getValue() != null) {
Configuration.AnchorPeers anchorPeersValue =
Configuration.AnchorPeers.parseFrom(anchorPeers.getValue());
List<Configuration.AnchorPeer> anchorPeersList = anchorPeersValue.getAnchorPeersList();
if (anchorPeersList != null) {
for (Configuration.AnchorPeer anchorPeer : anchorPeersList) {
// Concatenating the host and port to form a URL
anchorPeersSet.add(anchorPeer.getHost() + ":" + anchorPeer.getPort());
}
}
}
}
}
return anchorPeersSet;
}

@Override
public ResponseEntity<ClientResponseModel> getAnchorPeerForChannel(String channelName) {
Network network = gateway.getNetwork(channelName);
Set<String> anchorPeersSet = new HashSet<>();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] declare just before where this Set will get used.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Setting it here as it is getting used outside the try-catch blocks as well.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can return it directly from line # 107 instead of performing an assignment.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed, Thanks :)

try {
if (network != null) {
Channel selectedChannel = network.getChannel();
byte[] selectedChannelBytes = selectedChannel.getChannelConfigurationBytes();
log.debug("peers: {} ", selectedChannel.getPeers());
Map<String, ConfigGroup> groupsMap =
Config.parseFrom(selectedChannelBytes).getChannelGroup().getGroupsMap();
ConfigGroup application =
groupsMap.get(FabricClientConstants.CHANNEL_CONFIG_GROUP_APPLICATION);
// Get all MSP IDs for a particular channel
Collection<String> peersOrganizationMSPIDs = selectedChannel.getPeersOrganizationMSPIDs();
log.debug("peersOrganizationMSPIDs: {}", peersOrganizationMSPIDs.toString());
anchorPeersSet = getAnchorPeersFromOrgConfigGroup(peersOrganizationMSPIDs, application);
}

} catch (InvalidArgumentException e) {
log.warn(
"Error while fetching channel config: Channel has no peer or orderer defined. Can not get configuration block");
throw new ServiceException(
ErrorCode.HYPERLEDGER_FABRIC_TRANSACTION_ERROR,
"Channel has no peer or orderer defined. Can not get configuration block",
e);
} catch (TransactionException e) {
log.warn("Error retrieving anchor peers: {} ", e.getMessage());
throw new FabricTransactionException(
ErrorCode.HYPERLEDGER_FABRIC_TRANSACTION_ERROR,
ErrorCode.HYPERLEDGER_FABRIC_TRANSACTION_ERROR.name(),
e);
} catch (InvalidProtocolBufferException e) {
nidhi-singh02 marked this conversation as resolved.
Show resolved Hide resolved
log.warn("Error retrieving anchor peers: {}", e.getMessage());
throw new ServiceException(
ErrorCode.HYPERLEDGER_FABRIC_TRANSACTION_ERROR, "Error retrieving anchor peers", e);
}
return new ResponseEntity<>(
new ClientResponseModel(ErrorConstants.NO_ERROR, (Serializable) anchorPeersSet),
HttpStatus.OK);
}

@Override
/**
* Obtains the channel configuration
Expand Down
10 changes: 9 additions & 1 deletion src/test/java/hlf/java/rest/client/IT/ChannelIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,15 @@ public void addAnchorPeersToChannelTest() {
anchorPeerDTOs.add(anchorPeerDTO);
channelUpdateParamsDTO.setAnchorPeerDTOs(anchorPeerDTOs);
ResponseEntity<ClientResponseModel> responseModel =
networkStatus.addAnchorPeersToChannel(CHANNEL_NAME, channelUpdateParamsDTO);
networkStatus.addAnchorPeersToChannel(CHANNEL_NAME_TWO_ORGS, channelUpdateParamsDTO);
Assertions.assertEquals(new Integer(200), responseModel.getStatusCodeValue());
}

@Test
@Order(8)
public void getAnchorPeerForChannelTest() {
nidhi-singh02 marked this conversation as resolved.
Show resolved Hide resolved
ResponseEntity<ClientResponseModel> responseModel =
networkStatus.getAnchorPeerForChannel(CHANNEL_NAME_TWO_ORGS);
Assertions.assertEquals(new Integer(200), responseModel.getStatusCodeValue());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,15 @@ public class FabricOperationsControllerTest {
@Mock private NetworkStatus networkStatus;
@Mock private SerializationUtil serializationUtil;

@Test
public void getAnchorPeerForChannelTest() {
ResponseEntity responseEntity = new ResponseEntity(HttpStatus.OK);
Mockito.when(networkStatus.getAnchorPeerForChannel(Mockito.anyString()))
.thenReturn(responseEntity);
assertEquals(
responseEntity, fabricOperationsController.getAnchorPeerForChannel("some_channel_name"));
}

@Test
public void getChannelConfigurationTest() {
ResponseEntity responseEntity = new ResponseEntity(HttpStatus.OK);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,15 @@
import hlf.java.rest.client.model.CommitChannelParamsDTO;
import hlf.java.rest.client.model.MSPDTO;
import hlf.java.rest.client.service.ChannelConfigDeserialization;
import hlf.java.rest.client.util.FabricClientConstants;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import org.hyperledger.fabric.gateway.Network;
import org.hyperledger.fabric.gateway.impl.GatewayImpl;
import org.hyperledger.fabric.protos.common.Configtx;
import org.hyperledger.fabric.protos.common.Configtx.Config;
import org.hyperledger.fabric.protos.common.Configtx.ConfigGroup;
import org.hyperledger.fabric.protos.common.Configtx.ConfigUpdate;
Expand Down Expand Up @@ -88,7 +92,28 @@ public class NetworkStatusImplTest {

@Mock private ByteString byteString;

@Mock private ConfigUpdate.Builder configUpdateBuilder;
@Mock private Configtx.Config configTxConfig;
@Mock private Configtx.ConfigGroup configTxConfigGroup;

@Mock private Map<String, ConfigGroup> groupMap;

@Test
public void getAnchorPeerForChannelTest() throws InvalidArgumentException, TransactionException {
ResponseEntity<ClientResponseModel> responseEntity =
new ResponseEntity<>(
new ClientResponseModel(ErrorConstants.NO_ERROR, new HashSet<>()), HttpStatus.OK);
Mockito.when(gateway.getNetwork(Mockito.anyString())).thenReturn(network);
Mockito.when(network.getChannel()).thenReturn(channel);
Mockito.when(channel.getChannelConfigurationBytes()).thenReturn(new byte[0]);
staticConfig.when(() -> Config.parseFrom(Mockito.any(byte[].class))).thenReturn(configTxConfig);
Mockito.when(configTxConfig.getChannelGroup()).thenReturn(configTxConfigGroup);
Mockito.when(configTxConfigGroup.getGroupsMap()).thenReturn(groupMap);
Mockito.when(groupMap.get(FabricClientConstants.CHANNEL_CONFIG_GROUP_APPLICATION))
.thenReturn(readset);
assertEquals(
responseEntity.getStatusCode(),
networkStatus.getAnchorPeerForChannel("some_channelname").getStatusCode());
}

@Test
public void getChannelFromNetworkTest()
Expand Down
Loading