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

FABGW-20 Specify endorsing organizations #2578

Merged
merged 1 commit into from
May 21, 2021

Conversation

andrew-coleman
Copy link
Member

Implementation of endorsingOrgs in gateway Endorse method.

  • The set of endorsing peers from the discovery service is filtered down to only include those from the specified orgs.
  • The discovery handling code has been upgraded to step through all given layouts to find a layout that satisfies the endorsingOrgs constraint.

Signed-off-by: andrew-coleman andrew_coleman@uk.ibm.com

@andrew-coleman andrew-coleman requested a review from a team as a code owner May 7, 2021 09:56
@andrew-coleman
Copy link
Member Author

/ci-run

Comment on lines 44 to 45
endorser *endorser
endpoint string
Copy link
Contributor

Choose a reason for hiding this comment

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

As you introduced endorser, can we remove endpoint and use the endorser.address instead? Same info in multiple form cause confusion.

Copy link
Member Author

Choose a reason for hiding this comment

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

Good spot. Removed.

Comment on lines 122 to 123
peerGroup := groupPeers[0:quantity]
r = append(r, peerGroup...)
Copy link
Contributor

Choose a reason for hiding this comment

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

Not related to this PR but a minor suggestion - A single letter variable works fine if the life of the variable spans a few lines (e.g., peerGroup). The variable r is declared far above from where it is used so a meaningful name would be better.

Suggested change
peerGroup := groupPeers[0:quantity]
r = append(r, peerGroup...)
r = append(r, groupPeers[0:quantity]...)

} else {
reg.logger.Warnf("Failed to find endorser at %s", peer.endpoint)
}
endorsers = append(endorsers, peer.endorser)
Copy link
Contributor

Choose a reason for hiding this comment

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

Just a clarification related to discovery - I assume that the assumption here is that a peer does not appear in more than one groups for a given layout? Or this final slice can contain duplicates?

Copy link
Member Author

Choose a reason for hiding this comment

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

That's my assumption too. I followed the usage algorithm documented in the proto file:
https://github.com/hyperledger/fabric-protos/blob/main/discovery/protocol.proto#L175
My observation is that each group contains the peers of a single org, and the layouts give the various permutations of those orgs/groups

Comment on lines 108 to 109
if len(endorsingOrgs) == 0 || contains(endorsingOrgs, endorser.mspid) {
groupPeers = append(groupPeers, &endorserState{peer: peer, endorser: endorser, endpoint: endpoint, height: height})
Copy link
Contributor

Choose a reason for hiding this comment

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

I guess that we should discuss the semantics of user supplied endorsingOrgs little more clearly. The endorsement policies are specified at the chaincode level and could possibly be overwritten at the collection level. In addition, my understanding was that the purpose of this third option was to allow apps to specify the names of the orgs explicitly and this option (instead of knowing the names of the collections) would be helpful for some apps . In other words, the app explicitly supplies an AND policy and the assumption is that the app knows that the supplied AND policy is a superset of the union of all policies for the collections that the transaction writes into. However, the semantics of the implementation here is that the app is supposed to supply an AND policy that we would be intersect with chaincode level policy.

Copy link
Contributor

Choose a reason for hiding this comment

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

The endorsers service discovery query takes into consideration both the chaincode level and collection level endorsement policy. But Manish is correct, we need to discuss the semantics of endorsingOrgs.

I think the primary use case is when the application knows exactly which orgs to target. In that case, the Service Discovery peers query should be utilized, rather than the more expensive endorsers query. This will often be the case when using state-based endorsement (as SD endorsers query doesn't consider state-based endorsement requirements). See more history in https://jira.hyperledger.org/browse/FABN-1601.

Another use case is when the endorsement policy should be used (for example 3 out of 100 orgs), but you want to target some specific orgs, for example you want to utilize OrgA and OrgB but let service discovery pick any third org.

Bret implemented both approaches for the node SDK, and I think we have to do the same for Gateway.

A note on the endorsers query org filtering approach... Bret used a client side endorsers query filter in node SDK , but that approach doesn't work at all when there are many layouts returned since service discovery may only return a random subset. That means you may entirely miss on the intersection of layouts returned and orgs required. The filter therefore must be done on the service discovery side - we need to consider extending the SD endorsers query to take the list of required orgs. In fact, this is why we have a single team responsible for Gateway and Service Discovery now.

Copy link
Member Author

Choose a reason for hiding this comment

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

I've reimplemented this as Dave suggests to return all the peers from the list of 'endorsingOrganizations' that have the given chaincode installed.

return nil, fmt.Errorf("failed to select a set of endorsers that satisfy the endorsement policy")
}

// endorsersForOrgs returns a set of endorsers oen by the given orgs for the given chaincode on a channel.
Copy link
Contributor

Choose a reason for hiding this comment

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

what does "oen" mean?

}

var endorsers []*endorser
members := reg.discovery.PeersOfChannel(common.ChannelID(channel))
Copy link
Contributor

Choose a reason for hiding this comment

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

Nothing to be done in this PR, However, just to take a note, this appears to be case to revisit if the discovery api/code could be extended to take the org names as a filter that could improve the efficiency of this as compared to get all the peers and iterate over to filter.

for _, installedChaincode := range member.Properties.Chaincodes {
// only consider the peers that have our chaincode installed
if installedChaincode.Name == chaincode {
endorsers = append(endorsers, endorser)
Copy link
Contributor

Choose a reason for hiding this comment

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

Like the existing function, I was expecting here as well - only one peer (with the maximum height) for one org. Am I missing something?

Comment on lines 173 to 175
if len(es) > 0 {
endorsers = append(endorsers, es[0].endorser)
}
Copy link
Contributor

@manish-sethi manish-sethi May 21, 2021

Choose a reason for hiding this comment

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

Isn't it a noop check?

Copy link
Member Author

Choose a reason for hiding this comment

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

If, for any reason, the endorser returned by the discovery service is not in the gateway registry, then this could be an empty array. Perhaps if a new endorser had just come online and not been added to the registry yet. There's still a TODO comment in registerChannels() to handle this type of dynamic update.

Copy link
Contributor

Choose a reason for hiding this comment

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

Discussed offline and @andrew-coleman is going to push a new patch. Holding it from merging for now.

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks Manish, I've added an error check that will report which orgs fail to find endorsing peers, and added extra unit tests

Copy link
Contributor

@manish-sethi manish-sethi left a comment

Choose a reason for hiding this comment

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

Based on off-line discussion, expecting a minor fix and test for handling the case of insufficient available peers

Implementation of endorsingOrgs in gateway Endorse method.
- The set of endorsing peers from the discovery service is filtered down to only include those from the specified orgs.
- The discovery handling code has been upgraded to step through all given layouts to find a layout that satisfies the endorsingOrgs constraint.

Signed-off-by: andrew-coleman <andrew_coleman@uk.ibm.com>
@manish-sethi manish-sethi merged commit b4efe85 into hyperledger:main May 21, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants