Skip to content

Commit

Permalink
Improved gateway error for transient data failure
Browse files Browse the repository at this point in the history
When transient data is passed to the gateway in a transaction submit, the gateway is more cautious about which orgs it will select to endorse.  It alters the ChaincodeInterest to only allow orgs that are in the distribution policy for the PDCs written to by the chaincode.
This commit doesn’t change the behaviour, but gives a more helpful error message if this layer of protection caused the submit to fail due to the lack of endorsing orgs.
This will help to diagnose issues such as #3328 which took a long time to resolve because of the generic error message.

Signed-off-by: andrew-coleman <andrew_coleman@uk.ibm.com>
(cherry picked from commit 807c6de)
  • Loading branch information
andrew-coleman authored and denyeart committed May 25, 2022
1 parent a6947fa commit 60638b5
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 1 deletion.
16 changes: 15 additions & 1 deletion internal/pkg/gateway/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -340,16 +340,30 @@ func (gs *Server) planFromFirstEndorser(ctx context.Context, channel string, cha

// 4. If transient data is involved, then we need to ensure that discovery only returns orgs which own the collections involved.
// Do this by setting NoPrivateReads to false on each collection
originalInterest := &peer.ChaincodeInterest{}
var protectedCollections []string
if hasTransientData {
for _, call := range interest.GetChaincodes() {
call.NoPrivateReads = false
ccc := *call // shallow copy
originalInterest.Chaincodes = append(originalInterest.Chaincodes, &ccc)
if call.NoPrivateReads {
call.NoPrivateReads = false
protectedCollections = append(protectedCollections, call.CollectionNames...)
}
}
}

// 5. Get a set of endorsers from discovery via the registry
// The preferred discovery layout will contain the firstEndorser's Org.
plan, err = gs.registry.endorsementPlan(channel, interest, firstEndorser)
if err != nil {
if len(protectedCollections) > 0 {
// may have failed because of the cautious approach we are taking with transient data - check
_, err = gs.registry.endorsementPlan(channel, originalInterest, firstEndorser)
if err == nil {
return nil, status.Error(codes.FailedPrecondition, fmt.Sprintf("requires endorsement from organisation(s) that are not in the distribution policy of the private data collection(s): %v; retry specifying trusted endorsing organizations to protect transient data", protectedCollections))
}
}
return nil, status.Error(codes.FailedPrecondition, err.Error())
}

Expand Down
27 changes: 27 additions & 0 deletions internal/pkg/gateway/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -720,6 +720,33 @@ func TestEndorse(t *testing.T) {
errCode: codes.FailedPrecondition,
errString: "no endorsers found in the gateway's organization; retry specifying endorsing organization(s) to protect transient data",
},
{
name: "local and non-local endorsers with transient data will fail",
plan: endorsementPlan{
"g1": {{endorser: localhostMock, height: 3}}, // msp1
"g2": {{endorser: peer3Mock, height: 4}}, // msp2
},
layouts: []endorsementLayout{
{"g1": 1, "g2": 1},
},
members: []networkMember{
{"id1", "localhost:7051", "msp1", 3},
{"id3", "peer3:10051", "msp2", 4},
},
interest: &peer.ChaincodeInterest{
Chaincodes: []*peer.ChaincodeCall{{
Name: testChaincode,
CollectionNames: []string{"mycollection1", "mycollection2"},
NoPrivateReads: true,
}},
},
transientData: map[string][]byte{"transient-key": []byte("transient-value")},
postSetup: func(t *testing.T, def *preparedTest) {
def.discovery.PeersForEndorsementReturnsOnCall(0, nil, errors.New("protect-transient"))
},
errCode: codes.FailedPrecondition,
errString: "requires endorsement from organisation(s) that are not in the distribution policy of the private data collection(s): [mycollection1 mycollection2]; retry specifying trusted endorsing organizations to protect transient data",
},
{
name: "extra endorsers with transient data",
plan: endorsementPlan{
Expand Down

0 comments on commit 60638b5

Please sign in to comment.