Skip to content

Commit

Permalink
Capability to get anchor peer nodes in a channel introduced
Browse files Browse the repository at this point in the history
Signed-off-by: n0s09by <Nidhi.singh0@walmart.com>
  • Loading branch information
nidhi-singh02 committed Feb 12, 2024
1 parent 3ed78a2 commit 4f0716b
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 0 deletions.
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(
@PathVariable @Validated String channelName) {
return networkStatus.getAnchorPeerForChannel(channelName);
}
/**
* Obtain the channel configuration details.
*
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/hlf/java/rest/client/service/NetworkStatus.java
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 @@ -7,6 +7,7 @@
import hlf.java.rest.client.exception.ErrorCode;
import hlf.java.rest.client.exception.ErrorConstants;
import hlf.java.rest.client.exception.FabricTransactionException;
import hlf.java.rest.client.exception.NotFoundException;
import hlf.java.rest.client.exception.ServiceException;
import hlf.java.rest.client.model.AnchorPeerDTO;
import hlf.java.rest.client.model.ChannelUpdateParamsDTO;
Expand All @@ -15,16 +16,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 +64,73 @@ private String getDeserializedConfig(MessageOrBuilder message) {
return Base64.getEncoder().encodeToString(channelConfigString.getBytes());
}

@Override
public ResponseEntity<ClientResponseModel> getAnchorPeerForChannel(String channelName) {
Network network = gateway.getNetwork(channelName);
try {
Set<String> anchorPeersSet = new HashSet<>();
if (network != null) {
Channel selectedChannel = network.getChannel();
byte[] selectedChannelBytes = selectedChannel.getChannelConfigurationBytes();
log.debug("peers: {} ", selectedChannel.getPeers());
Configtx.Config.Builder configBuilderUpdate =
Config.parseFrom(selectedChannelBytes).toBuilder();
ConfigGroup.Builder channelGroupBuild = configBuilderUpdate.getChannelGroup().toBuilder();
Map<String, ConfigGroup> groupsMap = channelGroupBuild.getGroupsMap();
ConfigGroup.Builder application =
groupsMap.get(FabricClientConstants.CHANNEL_CONFIG_GROUP_APPLICATION).toBuilder();
// Get all MSP IDs for a particular channel
Collection<String> peersOrganizationMSPIDs = selectedChannel.getPeersOrganizationMSPIDs();
log.debug("peersOrganizationMSPIDs: {}", peersOrganizationMSPIDs.toString());
for (String peerOrganizationMSPID : peersOrganizationMSPIDs) {
ConfigGroup peerOrgConfigGroup = application.getGroupsMap().get(peerOrganizationMSPID);
if (peerOrgConfigGroup != null) {
ConfigGroup.Builder peerOrgConfigGroupBuilder = peerOrgConfigGroup.toBuilder();
Map<String, Configtx.ConfigValue> valuesMap = peerOrgConfigGroupBuilder.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 new ResponseEntity<>(
new ClientResponseModel(ErrorConstants.NO_ERROR, (Serializable) anchorPeersSet),
HttpStatus.OK);
} else {
log.warn("Error retrieving anchor peers: Network cannot be NULL");
throw new NotFoundException(ErrorCode.NOT_FOUND, "Network cannot be NULL");
}

} 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) {
log.warn("Error retrieving anchor peers: {}", e.getMessage());
throw new ServiceException(
ErrorCode.HYPERLEDGER_FABRIC_TRANSACTION_ERROR, "Error retrieving anchor peers", e);
}
}

@Override
/**
* Obtains the channel configuration
Expand Down
8 changes: 8 additions & 0 deletions src/test/java/hlf/java/rest/client/IT/ChannelIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -353,4 +353,12 @@ public void addAnchorPeersToChannelTest() {
networkStatus.addAnchorPeersToChannel(CHANNEL_NAME, channelUpdateParamsDTO);
Assertions.assertEquals(new Integer(200), responseModel.getStatusCodeValue());
}

@Test
@Order(8)
public void getAnchorPeerForChannelTest() {
ResponseEntity<ClientResponseModel> responseModel =
networkStatus.getAnchorPeerForChannel(CHANNEL_NAME);
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 @@ -89,6 +93,33 @@ public class NetworkStatusImplTest {
@Mock private ByteString byteString;

@Mock private ConfigUpdate.Builder configUpdateBuilder;
@Mock private ConfigGroup.Builder configGroupBuilder;

@Mock private Configtx.Config.Builder configtxConfigBuilder;
@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.toBuilder()).thenReturn(configtxConfigBuilder);
Mockito.when(configtxConfigBuilder.getChannelGroup()).thenReturn(configTxConfigGroup);
Mockito.when(configTxConfigGroup.toBuilder()).thenReturn(configGroupBuilder);
Mockito.when(configGroupBuilder.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

0 comments on commit 4f0716b

Please sign in to comment.