Skip to content
This repository was archived by the owner on Apr 22, 2025. It is now read-only.

Commit ef604d1

Browse files
committed
FAB-11570 Endorsing error
Change-Id: I23a9098af6f440ee8584c0f78500f259a36b7835 Signed-off-by: rickr <cr22rc@gmail.com>
1 parent 502b7ea commit ef604d1

File tree

9 files changed

+921
-230
lines changed

9 files changed

+921
-230
lines changed

src/main/java/org/hyperledger/fabric/sdk/Channel.java

Lines changed: 85 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1363,17 +1363,14 @@ public SDOrdererAddition setSDOrdererAddition(SDOrdererAddition sdOrdererAdditio
13631363

13641364
}
13651365

1366-
static byte[] combineCerts(Collection<byte[]>... certCollections) throws IOException {
1366+
private static byte[] combineCerts(Collection<byte[]>... certCollections) throws IOException {
13671367
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
13681368
for (Collection<byte[]> certCollection : certCollections) {
13691369

13701370
for (byte[] cert : certCollection) {
13711371
outputStream.write(cert);
1372-
13731372
}
1374-
13751373
}
1376-
13771374
return outputStream.toByteArray();
13781375
}
13791376
}
@@ -3176,6 +3173,28 @@ public Collection<ProposalResponse> sendTransactionProposal(TransactionProposalR
31763173
return sendProposal(transactionProposalRequest, getEndorsingPeers());
31773174
}
31783175

3176+
private static class PeerExactMatch { // use original equals of Peer and not what's overrident
3177+
final Peer peer;
3178+
3179+
private PeerExactMatch(Peer peer) {
3180+
this.peer = peer;
3181+
}
3182+
3183+
@Override
3184+
public boolean equals(Object obj) {
3185+
if (!(obj instanceof PeerExactMatch)) {
3186+
return false;
3187+
}
3188+
3189+
return peer == ((PeerExactMatch) obj).peer;
3190+
}
3191+
3192+
@Override
3193+
public int hashCode() {
3194+
return System.identityHashCode(peer);
3195+
}
3196+
}
3197+
31793198
/**
31803199
* Send a transaction proposal.
31813200
*
@@ -3247,30 +3266,45 @@ public Collection<ProposalResponse> sendTransactionProposalToEndorsers(Transacti
32473266
throw new ServiceDiscoveryException(format("Channel %s failed to find and endorsers for chaincode %s no layouts found.", name, chaincodeName));
32483267
}
32493268

3250-
SDChaindcode sdChaindcodeNI = new SDChaindcode(sdChaindcode); //copy. no ignored.
3269+
SDChaindcode sdChaindcodeEndorsementCopy = new SDChaindcode(sdChaindcode); //copy. no ignored.
32513270

32523271
final boolean inspectResults = discoveryOptions.inspectResults;
32533272

3254-
if (sdChaindcodeNI.ignoreList(discoveryOptions.getIgnoreList()) < 1) { // apply ignore list
3273+
if (sdChaindcodeEndorsementCopy.ignoreList(discoveryOptions.getIgnoreList()) < 1) { // apply ignore list
32553274
throw new ServiceDiscoveryException("Applying ignore list reduced to no available endorser options.");
32563275
}
32573276

32583277
if (IS_TRACE_LEVEL && null != discoveryOptions.getIgnoreList() && !discoveryOptions.getIgnoreList().isEmpty()) {
3259-
logger.trace(format("SDchaincode after ignore list: %s", sdChaindcodeNI));
3278+
logger.trace(format("SDchaincode after ignore list: %s", sdChaindcodeEndorsementCopy));
32603279
}
3261-
final EndorsementSelector lendorsementSelector = discoveryOptions.endorsementSelector != null ?
3280+
final ServiceDiscovery.EndorsementSelector lendorsementSelector = discoveryOptions.endorsementSelector != null ?
32623281
discoveryOptions.endorsementSelector : this.endorsementSelector;
32633282
try {
32643283

3265-
final Map<String, ProposalResponse> goodResponses = new HashMap<>(); // all good endorsements by endpoint
3266-
final Map<String, ProposalResponse> allTried = new HashMap<>(); // all tried by endpoint
3284+
final Map<SDEndorser, ProposalResponse> goodResponses = new HashMap<>(); // all good endorsements by endpoint
3285+
final Map<SDEndorser, ProposalResponse> allTried = new HashMap<>(); // all tried by endpoint
32673286

32683287
boolean done = false;
32693288
int attempts = 1; //safety valve
32703289

32713290
do {
3272-
logger.trace(format("Attempts: %d, chaincode discovery state: %s", attempts, sdChaindcodeNI));
3273-
final SDEndorserState sdEndorserState = lendorsementSelector.endorserSelector(sdChaindcodeNI);
3291+
if (IS_TRACE_LEVEL) {
3292+
logger.trace(format("Attempts: %d, chaincode discovery state: %s", attempts, sdChaindcodeEndorsementCopy));
3293+
}
3294+
final SDEndorserState sdEndorserState = lendorsementSelector.endorserSelector(sdChaindcodeEndorsementCopy);
3295+
3296+
if (IS_TRACE_LEVEL) {
3297+
3298+
StringBuilder sb = new StringBuilder(1000);
3299+
String sep = "";
3300+
for (SDEndorser sdEndorser : sdEndorserState.getSdEndorsers()) {
3301+
sb.append(sep).append(sdEndorser);
3302+
sep = ", ";
3303+
}
3304+
3305+
logger.trace(format("Attempts: %d, chaincode discovery state: %s. Endorser selector picked: %s. With selected endorsers: %s", attempts, sdChaindcodeEndorsementCopy.name, sdEndorserState.getPickedLayout(), sb.toString()));
3306+
3307+
}
32743308

32753309
Collection<SDEndorser> ep = sdEndorserState.getSdEndorsers();
32763310
ep = new ArrayList<>(ep); // just in case it's not already a copy
@@ -3286,11 +3320,13 @@ public Collection<ProposalResponse> sendTransactionProposalToEndorsers(Transacti
32863320
}
32873321

32883322
//Safety check make sure the selector isn't giving back endpoints to retry
3289-
ep.removeIf(sdEndorser -> goodResponses.keySet().contains(sdEndorser.getEndpoint()));
3323+
ep.removeIf(sdEndorser -> goodResponses.keySet().contains(sdEndorser));
32903324

32913325
if (ep.isEmpty()) { // this would be odd but lets go with it.
3292-
Set<String> needed = sdChaindcode.meetsEndorsmentPolicy(goodResponses.keySet());
3293-
if (needed != null) {
3326+
logger.debug(format("Channel %s, chaincode %s attempts: %d endorser selector returned no additional endorements needed.", name, chaincodeName, attempts));
3327+
3328+
Collection<SDEndorser> needed = sdChaindcode.meetsEndorsmentPolicy(goodResponses.keySet());
3329+
if (needed != null) { // means endorsment meet with those in the needed.
32943330
ArrayList<ProposalResponse> ret = new ArrayList<>(needed.size());
32953331
needed.forEach(s -> ret.add(goodResponses.get(s)));
32963332

@@ -3319,16 +3355,17 @@ public Collection<ProposalResponse> sendTransactionProposalToEndorsers(Transacti
33193355
}
33203356
}
33213357

3322-
HashMap<String, Peer> stringPeerHashMap = new HashMap<>(peerEndpointMap);
3323-
ArrayList<Peer> endorsers = new ArrayList<>(ep.size());
3324-
for (SDEndorser endpoint : ep) {
3358+
Map<String, Peer> lpeerEndpointMap = new HashMap<>(peerEndpointMap);
3359+
Map<SDEndorser, Peer> endorsers = new HashMap<>(ep.size());
3360+
Map<PeerExactMatch, SDEndorser> peer2sdEndorser = new HashMap<>(ep.size());
3361+
for (SDEndorser sdEndorser : ep) {
33253362

3326-
Peer epeer = stringPeerHashMap.get(endpoint.getEndpoint());
3363+
Peer epeer = lpeerEndpointMap.get(sdEndorser.getEndpoint());
33273364
if (epeer != null && !epeer.hasConnected()) {
33283365
// mostly because gossip may have malicious data so if we've not connected update TLS props from chaincode discovery.
33293366
final Properties properties = epeer.getProperties();
33303367

3331-
final byte[] bytes = combineCerts(endpoint.getTLSCerts(), endpoint.getTLSIntermediateCerts());
3368+
final byte[] bytes = combineCerts(sdEndorser.getTLSCerts(), sdEndorser.getTLSIntermediateCerts());
33323369
properties.put("pemBytes", bytes);
33333370
epeer.setProperties(properties);
33343371

@@ -3337,12 +3374,12 @@ public Collection<ProposalResponse> sendTransactionProposalToEndorsers(Transacti
33373374

33383375
@Override
33393376
public String getMspId() {
3340-
return endpoint.getMspid();
3377+
return sdEndorser.getMspid();
33413378
}
33423379

33433380
@Override
33443381
public String getEndpoint() {
3345-
return endpoint.getEndpoint();
3382+
return sdEndorser.getEndpoint();
33463383
}
33473384

33483385
@Override
@@ -3358,12 +3395,12 @@ public HFClient getClient() {
33583395
@Override
33593396
public byte[][] getTLSCerts() {
33603397

3361-
return endpoint.getTLSCerts().toArray(new byte[endpoint.getTLSCerts().size()][]);
3398+
return sdEndorser.getTLSCerts().toArray(new byte[sdEndorser.getTLSCerts().size()][]);
33623399
}
33633400

33643401
@Override
33653402
public byte[][] getTLSIntermediateCerts() {
3366-
return endpoint.getTLSIntermediateCerts().toArray(new byte[endpoint.getTLSIntermediateCerts().size()][]);
3403+
return sdEndorser.getTLSIntermediateCerts().toArray(new byte[sdEndorser.getTLSIntermediateCerts().size()][]);
33673404
}
33683405

33693406
@Override
@@ -3372,36 +3409,37 @@ public Map<String, Peer> getEndpointMap() {
33723409
}
33733410
});
33743411
}
3375-
endorsers.add(epeer);
3412+
endorsers.put(sdEndorser, epeer);
3413+
peer2sdEndorser.put(new PeerExactMatch(epeer), sdEndorser); // reverse
33763414
}
33773415

3378-
final Collection<ProposalResponse> proposalResponses = sendProposalToPeers(endorsers, invokeProposal, transactionContext);
3379-
HashSet<String> loopGood = new HashSet<>();
3380-
HashSet<String> loopBad = new HashSet<>();
3416+
final Collection<ProposalResponse> proposalResponses = sendProposalToPeers(endorsers.values(), invokeProposal, transactionContext);
3417+
HashSet<SDEndorser> loopGood = new HashSet<>();
3418+
HashSet<SDEndorser> loopBad = new HashSet<>();
33813419

33823420
for (ProposalResponse proposalResponse : proposalResponses) {
3383-
final String endpoint = proposalResponse.getPeer().getEndpoint();
3384-
allTried.put(endpoint, proposalResponse);
3421+
final SDEndorser sdEndorser = peer2sdEndorser.get(new PeerExactMatch(proposalResponse.getPeer()));
3422+
allTried.put(sdEndorser, proposalResponse);
33853423

33863424
final ChaincodeResponse.Status status = proposalResponse.getStatus();
33873425

33883426
if (ChaincodeResponse.Status.SUCCESS.equals(status)) {
33893427

3390-
goodResponses.put(endpoint, proposalResponse);
3391-
logger.trace(format("Channel %s, chaincode %s attempts %d good endorsements: %s", name, chaincodeName, attempts, endpoint));
3392-
loopGood.add(endpoint);
3428+
goodResponses.put(sdEndorser, proposalResponse);
3429+
logger.trace(format("Channel %s, chaincode %s attempts %d good endorsements: %s", name, chaincodeName, attempts, sdEndorser));
3430+
loopGood.add(sdEndorser);
33933431

33943432
} else {
3395-
logger.debug(format("Channel %s, chaincode %s attempts %d bad endorsements: %s", name, chaincodeName, attempts, endpoint));
3396-
loopBad.add(endpoint);
3433+
logger.debug(format("Channel %s, chaincode %s attempts %d bad endorsements: %s", name, chaincodeName, attempts, sdEndorser));
3434+
loopBad.add(sdEndorser);
33973435
}
33983436
}
33993437

34003438
//Always check on original
3401-
Set<String> needed = sdChaindcode.meetsEndorsmentPolicy(goodResponses.keySet());
3402-
if (needed != null) {
3403-
ArrayList<ProposalResponse> ret = new ArrayList<>(needed.size());
3404-
needed.forEach(s -> ret.add(goodResponses.get(s)));
3439+
Collection<SDEndorser> required = sdChaindcode.meetsEndorsmentPolicy(goodResponses.keySet());
3440+
if (required != null) {
3441+
ArrayList<ProposalResponse> ret = new ArrayList<>(required.size());
3442+
required.forEach(s -> ret.add(goodResponses.get(s)));
34053443

34063444
if (IS_DEBUG_LEVEL) {
34073445

@@ -3410,26 +3448,22 @@ public Map<String, Peer> getEndpointMap() {
34103448
for (ProposalResponse proposalResponse : ret) {
34113449
sb.append(sep).append(proposalResponse.getPeer());
34123450
sep = ", ";
3413-
34143451
}
3415-
34163452
logger.debug(format("Channel %s, chaincode %s got all needed endorsements: %s", name, chaincodeName, sb.toString()));
3417-
34183453
}
3419-
34203454
return ret; // the happy path :)!
34213455

34223456
} else { //still don't have the needed endorsements.
34233457

3424-
sdChaindcodeNI.endorsedList(loopGood);
3458+
sdChaindcodeEndorsementCopy.endorsedList(loopGood); // mark the good ones in the working copy.
34253459

3426-
if (sdChaindcodeNI.ignoreList(loopBad) < 1) { // apply ignore list
3460+
if (sdChaindcodeEndorsementCopy.ignoreListSDEndorser(loopBad) < 1) { // apply ignore list
34273461
done = true; // no more layouts
34283462
}
34293463
}
34303464

34313465
} while (!done && ++attempts <= 5);
3432-
logger.trace(format("Endorsements not achieved chaincode: %s, done: %b, attempts: %d", chaincodeName, done, attempts));
3466+
logger.debug(format("Endorsements not achieved chaincode: %s, done: %b, attempts: %d", chaincodeName, done, attempts));
34333467
if (inspectResults) {
34343468
return allTried.values();
34353469
} else {
@@ -3598,10 +3632,10 @@ private Collection<ProposalResponse> sendProposal(TransactionRequest proposalReq
35983632
}
35993633
}
36003634

3601-
private transient EndorsementSelector endorsementSelector = ServiceDiscovery.DEFAULT_ENDORSEMENT_SELECTION;
3635+
private transient ServiceDiscovery.EndorsementSelector endorsementSelector = ServiceDiscovery.DEFAULT_ENDORSEMENT_SELECTION;
36023636

3603-
public EndorsementSelector setSDEndorserSelector(EndorsementSelector endorsementSelector) {
3604-
EndorsementSelector ret = this.endorsementSelector;
3637+
public ServiceDiscovery.EndorsementSelector setSDEndorserSelector(ServiceDiscovery.EndorsementSelector endorsementSelector) {
3638+
ServiceDiscovery.EndorsementSelector ret = this.endorsementSelector;
36053639
this.endorsementSelector = endorsementSelector;
36063640
return ret;
36073641

@@ -4204,7 +4238,7 @@ List<String> getCollections() {
42044238
*/
42054239
public static class DiscoveryOptions {
42064240
Set<String> ignoreList = new HashSet<>();
4207-
EndorsementSelector endorsementSelector = null;
4241+
ServiceDiscovery.EndorsementSelector endorsementSelector = null;
42084242
boolean inspectResults = false;
42094243
boolean forceDiscovery = false;
42104244

@@ -4245,7 +4279,7 @@ public DiscoveryOptions setInspectResults(boolean inspectResults) {
42454279
* @return
42464280
* @throws InvalidArgumentException
42474281
*/
4248-
public DiscoveryOptions setEndorsementSelector(EndorsementSelector endorsementSelector) throws InvalidArgumentException {
4282+
public DiscoveryOptions setEndorsementSelector(ServiceDiscovery.EndorsementSelector endorsementSelector) throws InvalidArgumentException {
42494283
if (endorsementSelector == null) {
42504284
throw new InvalidArgumentException("endorsementSelector parameter is null.");
42514285
}

src/main/java/org/hyperledger/fabric/sdk/EndorsementSelector.java

Lines changed: 0 additions & 24 deletions
This file was deleted.

src/main/java/org/hyperledger/fabric/sdk/HFClient.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -527,10 +527,10 @@ public Orderer newOrderer(String name, String grpcURL, Properties properties) th
527527
}
528528

529529
/**
530-
* Query the channels for peers
530+
* Query the joined channels for peers
531531
*
532532
* @param peer the peer to query
533-
* @return A set of strings with the peer names.
533+
* @return A set of strings with the names of the channels the peer has joined.
534534
* @throws InvalidArgumentException
535535
* @throws ProposalException
536536
*/

0 commit comments

Comments
 (0)