use of org.hyperledger.fabric.protos.orderer.Ab.BroadcastResponse in project fabric-sdk-java by hyperledger.
the class Channel method sendUpdateChannel.
private void sendUpdateChannel(byte[] configupdate, byte[][] signers, Orderer orderer) throws TransactionException, InvalidArgumentException {
logger.debug(format("Channel %s sendUpdateChannel", name));
checkOrderer(orderer);
try {
final long nanoTimeStart = System.nanoTime();
int statusCode = 0;
do {
// Make sure we have fresh transaction context for each try just to be safe.
TransactionContext transactionContext = getTransactionContext();
ConfigUpdateEnvelope.Builder configUpdateEnvBuilder = ConfigUpdateEnvelope.newBuilder();
configUpdateEnvBuilder.setConfigUpdate(ByteString.copyFrom(configupdate));
for (byte[] signer : signers) {
configUpdateEnvBuilder.addSignatures(ConfigSignature.parseFrom(signer));
}
// --------------
// Construct Payload Envelope.
final ByteString sigHeaderByteString = getSignatureHeaderAsByteString(transactionContext);
final ChannelHeader payloadChannelHeader = ProtoUtils.createChannelHeader(HeaderType.CONFIG_UPDATE, transactionContext.getTxID(), name, transactionContext.getEpoch(), transactionContext.getFabricTimestamp(), null, null);
final Header payloadHeader = Header.newBuilder().setChannelHeader(payloadChannelHeader.toByteString()).setSignatureHeader(sigHeaderByteString).build();
final ByteString payloadByteString = Payload.newBuilder().setHeader(payloadHeader).setData(configUpdateEnvBuilder.build().toByteString()).build().toByteString();
ByteString payloadSignature = transactionContext.signByteStrings(payloadByteString);
Envelope payloadEnv = Envelope.newBuilder().setSignature(payloadSignature).setPayload(payloadByteString).build();
BroadcastResponse trxResult = orderer.sendTransaction(payloadEnv);
statusCode = trxResult.getStatusValue();
logger.debug(format("Channel %s sendUpdateChannel %d", name, statusCode));
if (statusCode == 404 || statusCode == 503) {
// these we can retry..
final long duration = TimeUnit.MILLISECONDS.convert(System.nanoTime() - nanoTimeStart, TimeUnit.NANOSECONDS);
if (duration > CHANNEL_CONFIG_WAIT_TIME) {
// waited long enough .. throw an exception
String info = trxResult.getInfo();
if (null == info) {
info = "";
}
throw new TransactionException(format("Channel %s update error timed out after %d ms. Status value %d. Status %s. %s", name, duration, statusCode, trxResult.getStatus().name(), info));
}
try {
// try again sleep
Thread.sleep(ORDERER_RETRY_WAIT_TIME);
} catch (InterruptedException e) {
TransactionException te = new TransactionException("update thread Sleep", e);
logger.warn(te.getMessage(), te);
}
} else if (200 != statusCode) {
// Can't retry.
String info = trxResult.getInfo();
if (null == info) {
info = "";
}
throw new TransactionException(format("New channel %s error. StatusValue %d. Status %s. %s", name, statusCode, "" + trxResult.getStatus(), info));
}
} while (// try again
200 != statusCode);
} catch (TransactionException e) {
logger.error(format("Channel %s error: %s", name, e.getMessage()), e);
throw e;
} catch (Exception e) {
String msg = format("Channel %s error: %s", name, e.getMessage());
logger.error(msg, e);
throw new TransactionException(msg, e);
}
}
use of org.hyperledger.fabric.protos.orderer.Ab.BroadcastResponse in project fabric-sdk-java by hyperledger.
the class Channel method sendTransaction.
/**
* Send transaction to one of a specified set of orderers with the specified user context.
* IF there are no event hubs or eventing peers this future returns immediately completed
* indicating that orderer has accepted the transaction only.
*
* @param proposalResponses
* @param transactionOptions
* @return Future allowing access to the result of the transaction invocation.
*/
public CompletableFuture<TransactionEvent> sendTransaction(Collection<ProposalResponse> proposalResponses, TransactionOptions transactionOptions) {
try {
if (null == transactionOptions) {
throw new InvalidArgumentException("Parameter transactionOptions can't be null");
}
checkChannelState();
User userContext = transactionOptions.userContext != null ? transactionOptions.userContext : client.getUserContext();
userContextCheck(userContext);
if (null == proposalResponses) {
throw new InvalidArgumentException("sendTransaction proposalResponses was null");
}
List<Orderer> orderers = transactionOptions.orderers != null ? transactionOptions.orderers : new ArrayList<>(getOrderers());
// make certain we have our own copy
final List<Orderer> shuffeledOrderers = new ArrayList<>(orderers);
if (transactionOptions.shuffleOrders) {
Collections.shuffle(shuffeledOrderers);
}
if (config.getProposalConsistencyValidation()) {
HashSet<ProposalResponse> invalid = new HashSet<>();
int consistencyGroups = SDKUtils.getProposalConsistencySets(proposalResponses, invalid).size();
if (consistencyGroups != 1 || !invalid.isEmpty()) {
throw new IllegalArgumentException(format("The proposal responses have %d inconsistent groups with %d that are invalid." + " Expected all to be consistent and none to be invalid.", consistencyGroups, invalid.size()));
}
}
List<FabricProposalResponse.Endorsement> ed = new LinkedList<>();
FabricProposal.Proposal proposal = null;
ByteString proposalResponsePayload = null;
String proposalTransactionID = null;
for (ProposalResponse sdkProposalResponse : proposalResponses) {
ed.add(sdkProposalResponse.getProposalResponse().getEndorsement());
if (proposal == null) {
proposal = sdkProposalResponse.getProposal();
proposalTransactionID = sdkProposalResponse.getTransactionID();
proposalResponsePayload = sdkProposalResponse.getProposalResponse().getPayload();
}
}
TransactionBuilder transactionBuilder = TransactionBuilder.newBuilder();
Payload transactionPayload = transactionBuilder.chaincodeProposal(proposal).endorsements(ed).proposalResponsePayload(proposalResponsePayload).build();
Envelope transactionEnvelope = createTransactionEnvelope(transactionPayload, userContext);
NOfEvents nOfEvents = transactionOptions.nOfEvents;
if (nOfEvents == null) {
nOfEvents = NOfEvents.createNofEvents();
Collection<Peer> eventingPeers = getEventingPeers();
boolean anyAdded = false;
if (!eventingPeers.isEmpty()) {
anyAdded = true;
nOfEvents.addPeers(eventingPeers);
}
Collection<EventHub> eventHubs = getEventHubs();
if (!eventHubs.isEmpty()) {
anyAdded = true;
nOfEvents.addEventHubs(getEventHubs());
}
if (!anyAdded) {
nOfEvents = NOfEvents.createNoEvents();
}
} else if (nOfEvents != NOfEvents.nofNoEvents) {
StringBuilder issues = new StringBuilder(100);
Collection<Peer> eventingPeers = getEventingPeers();
nOfEvents.unSeenPeers().forEach(peer -> {
if (peer.getChannel() != this) {
issues.append(format("Peer %s added to NOFEvents does not belong this channel. ", peer.getName()));
} else if (!eventingPeers.contains(peer)) {
issues.append(format("Peer %s added to NOFEvents is not a eventing Peer in this channel. ", peer.getName()));
}
});
nOfEvents.unSeenEventHubs().forEach(eventHub -> {
if (!eventHubs.contains(eventHub)) {
issues.append(format("Eventhub %s added to NOFEvents does not belong this channel. ", eventHub.getName()));
}
});
if (nOfEvents.unSeenEventHubs().isEmpty() && nOfEvents.unSeenPeers().isEmpty()) {
issues.append("NofEvents had no Eventhubs added or Peer eventing services.");
}
String foundIssues = issues.toString();
if (!foundIssues.isEmpty()) {
throw new InvalidArgumentException(foundIssues);
}
}
final boolean replyonly = nOfEvents == NOfEvents.nofNoEvents || (getEventHubs().isEmpty() && getEventingPeers().isEmpty());
CompletableFuture<TransactionEvent> sret;
if (replyonly) {
// If there are no eventhubs to complete the future, complete it
// immediately but give no transaction event
logger.debug(format("Completing transaction id %s immediately no event hubs or peer eventing services found in channel %s.", proposalTransactionID, name));
sret = new CompletableFuture<>();
} else {
sret = registerTxListener(proposalTransactionID, nOfEvents, transactionOptions.failFast);
}
logger.debug(format("Channel %s sending transaction to orderer(s) with TxID %s ", name, proposalTransactionID));
boolean success = false;
// Save last exception to report to user .. others are just logged.
Exception lException = null;
BroadcastResponse resp = null;
Orderer failed = null;
for (Orderer orderer : shuffeledOrderers) {
if (failed != null) {
logger.warn(format("Channel %s %s failed. Now trying %s.", name, failed, orderer));
}
failed = orderer;
try {
if (null != diagnosticFileDumper) {
logger.trace(format("Sending to channel %s, orderer: %s, transaction: %s", name, orderer.getName(), diagnosticFileDumper.createDiagnosticProtobufFile(transactionEnvelope.toByteArray())));
}
resp = orderer.sendTransaction(transactionEnvelope);
// no longer last exception .. maybe just failed.
lException = null;
if (resp.getStatus() == Status.SUCCESS) {
success = true;
break;
} else {
logger.warn(format("Channel %s %s failed. Status returned %s", name, orderer, getRespData(resp)));
}
} catch (Exception e) {
String emsg = format("Channel %s unsuccessful sendTransaction to orderer %s (%s)", name, orderer.getName(), orderer.getUrl());
if (resp != null) {
emsg = format("Channel %s unsuccessful sendTransaction to orderer %s (%s). %s", name, orderer.getName(), orderer.getUrl(), getRespData(resp));
}
logger.error(emsg);
lException = new Exception(emsg, e);
}
}
if (success) {
logger.debug(format("Channel %s successful sent to Orderer transaction id: %s", name, proposalTransactionID));
if (replyonly) {
// just say we're done.
sret.complete(null);
}
return sret;
} else {
String emsg = format("Channel %s failed to place transaction %s on Orderer. Cause: UNSUCCESSFUL. %s", name, proposalTransactionID, getRespData(resp));
unregisterTxListener(proposalTransactionID);
CompletableFuture<TransactionEvent> ret = new CompletableFuture<>();
ret.completeExceptionally(lException != null ? new Exception(emsg, lException) : new Exception(emsg));
return ret;
}
} catch (Exception e) {
CompletableFuture<TransactionEvent> future = new CompletableFuture<>();
future.completeExceptionally(e);
return future;
}
}
Aggregations