This article will appeal to open source technology enthusiasts interested in blockchain technologies and with a working knowledge of the Hyperledger Fabric project.
Prior to the release of Hyperledger Fabric v1.2, the SDK needed a lot of information in order to allow applications to connect to the relevant network nodes. This information was statically encoded. However, this implementation was not dynamically reactive to network changes like the addition of peers who have installed the relevant chaincode, or are temporarily offline. Static configurations also do not allow applications to react to changes in the endorsement policies itself, which might happen when a new organisation joins a channel. The client application has no way of knowing which peers have updated ledgers and which do not. The application might submit proposals to peers whose ledger data is not in sync with the rest of the network, resulting in transactions being invalidated upon commit and resources getting wasted as a consequence. In order to execute chaincode on peers, we need to submit transactions to orderers, and these need to be updated about the status of transactions as well as the applications connect to an API exposed by an SDK.
The discovery service improves this process by having the peers compute the needed information dynamically and presenting it to the SDK in a consumable manner.
Service discovery in Fabric
The application issues a configuration query to the discovery service and obtains all the static information it would have otherwise needed to communicate with the rest of the nodes of the network. This information can be refreshed at any time by sending a subsequent query to the discovery service of a peer. The application is bootstrapped, knowing about a group of peers which is trusted by the application developer/administrator to provide authentic responses to discovery queries. A good candidate peer to be used by the client application is one that is in the same organisation.
The service runs on peers – not on the application – and uses the network metadata information maintained by the gossip communication layer to find out which peers are online. It also fetches information such as any relevant endorsement policies from the peer’s state database. With service discovery, applications no longer need to specify which peers they need endorsements from. The SDK can simply send a query to the discovery service, asking which peers are needed, given a channel and a chaincode ID.
Capabilities of the discovery service
The discovery service can respond to the following queries.
Configuration query: Returns the MSPConfig of all organisations in the channel along with the orderer endpoints of the channel.
Peer membership query: Returns the peers that have joined the channel.
Endorsement query: Returns an endorsement descriptor for given chaincode(s) in a channel.
Local peer membership query: Returns the local membership information of the peer that responds to the query. By default, the client needs to be an administrator for the peer to respond to this query.
How it works
The discovery service will then compute a descriptor comprising two objects.
Layouts: This is a list of groups of peers, and a corresponding number of peers should be selected from each group.
Group-to-peer mapping: This is from the groups in the layouts to the peers of the channel. In practice, each group will most likely comprise peers that represent individual organisations, but because the service API is generic and ignorant about organisations, this is just a group.
The following is an example of a descriptor from the evaluation of a policy of AND(Org1, Org2) where there are two peers in each of the organisations:
Layouts: [ QuantitiesByGroup: { “Org1”: 1, “Org2”: 1, } ], EndorsersByGroups: { “Org1”: [peer0.org1, peer1.org1], “Org2”: [peer0.org2, peer1.org2] }
In other words, the endorsement policy requires a signature from one peer in Org1 and one peer in Org2. And it provides the names of available peers in those orgs who can endorse (peer0 and peer1 in both Org1 and in Org2).
The SDK then selects a random layout from the list. In the example above, the endorsement policy is Org1 AND Org2. If instead it was an OR policy, the SDK would randomly select either Org1 or Org2, since a signature from a peer from either Org would satisfy the policy.
After the SDK has selected a layout, it selects from the peers in the layout based on criteria specified on the client side (the SDK can do this because it has access to metadata like ledger height). For example, it can prefer peers with higher ledger heights over others – or to exclude peers whose applications have been discovered to be offline – according to the number of peers from each group in the layout. If no single peer is preferable based on the criteria, the SDK will randomly select from the peers that best meet the criteria. Note: When the peer is running with TLS enabled, the client must provide a TLS certificate when connecting to the peer. If the peer isn’t configured to verify client certificates (clientAuthRequired is false), this TLS certificate can be self-signed.