Skip to content

Commit

Permalink
Merge pull request #3279 from HenrikJannsen/fix-handling-of-tor-contr…
Browse files Browse the repository at this point in the history
…ol-reply-code

Fix handling of tor control reply code
  • Loading branch information
HenrikJannsen authored Mar 8, 2025
2 parents ee8f4a5 + 8004e69 commit 93219fc
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 46 deletions.
65 changes: 31 additions & 34 deletions identity/src/main/java/bisq/identity/IdentityService.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import bisq.common.application.Service;
import bisq.common.network.TransportType;
import bisq.common.observable.Observable;
import bisq.common.util.CompletableFutureUtils;
import bisq.network.NetworkIdService;
import bisq.network.NetworkService;
import bisq.network.identity.NetworkId;
Expand All @@ -36,11 +37,11 @@
import lombok.extern.slf4j.Slf4j;

import java.security.KeyPair;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Stream;

Expand Down Expand Up @@ -84,35 +85,36 @@ public CompletableFuture<Boolean> initialize() {
// Create default identity
getOrCreateDefaultIdentity();

Map<TransportType, CompletableFuture<Node>> map = networkService.getInitializedDefaultNodeByTransport();
if (map.isEmpty()) {
Map<TransportType, CompletableFuture<Node>> defaultNodeResultByTransport = networkService.getInitializedDefaultNodeByTransport();
if (defaultNodeResultByTransport.isEmpty()) {
return CompletableFuture.failedFuture(new RuntimeException("networkService.getInitializedDefaultNodeByTransport returns an empty map"));
}

CompletableFuture<Boolean> resultFuture = new CompletableFuture<>();
AtomicInteger failures = new AtomicInteger();
map.forEach((transportType, future) -> future.whenComplete((node, throwable) -> {
if (throwable == null && node != null) {
// After each successful initialisation of the default node on a transport we start to
// initialize the active identities for that transport using a blocking call.
// This will delay app startup until all identities are ready on the network side.
try {
initializeActiveIdentities(transportType);
if (!resultFuture.isDone()) {
resultFuture.complete(true);
defaultNodeResultByTransport.forEach((transportType, future) -> future
.whenComplete((defaultNode, throwable) -> {
if (throwable == null && defaultNode != null) {
// After each successful initialisation of the default node on a transport we start to
// initialize the active identities for that transport using a blocking call.
// This will delay app startup until all identities are ready on the network side.
try {
initializeAllActiveIdentities(transportType).get();
if (!resultFuture.isDone()) {
resultFuture.complete(true);
}
} catch (Exception e) {
if (!resultFuture.isDone()) {
resultFuture.completeExceptionally(e);
}
}
} else if (!resultFuture.isDone()) {
if (failures.incrementAndGet() == defaultNodeResultByTransport.size()) {
// All failed
resultFuture.completeExceptionally(new RuntimeException("Default node initialization on all transports failed"));
}
}
} catch (Exception e) {
if (!resultFuture.isDone()) {
resultFuture.completeExceptionally(e);
}
}
} else if (!resultFuture.isDone()) {
if (failures.incrementAndGet() == map.size()) {
// All failed
resultFuture.completeExceptionally(new RuntimeException("Default node initialization on all transports failed"));
}
}
}));
}));
return resultFuture;
}

Expand Down Expand Up @@ -214,19 +216,14 @@ public Optional<Identity> findAnyIdentityByNetworkId(NetworkId networkId) {
// Private
/* --------------------------------------------------------------------- */

private void initializeActiveIdentities(TransportType transportType) {
getActiveIdentityByTag().values().stream()
private CompletableFuture<List<Node>> initializeAllActiveIdentities(TransportType transportType) {
Stream<CompletableFuture<Node>> futures = getActiveIdentityByTag().values().stream()
.filter(identity -> !identity.getTag().equals(IdentityService.DEFAULT_IDENTITY_TAG))
.forEach(identity -> {
.map(identity -> {
maybeRecoverNetworkId(identity);
try {
// We use a blocking call
networkService.supplyInitializedNode(transportType, identity.getNetworkId()).get();
} catch (InterruptedException | ExecutionException e) {
log.error("Initializing node failed for identity with tag {}", identity.getTag(), e);
throw new RuntimeException("Initializing node failed for identity with tag " + identity.getTag(), e);
}
return networkService.supplyInitializedNode(transportType, identity.getNetworkId());
});
return CompletableFutureUtils.allOf(futures);
}

private CompletableFuture<Identity> createAndInitializeNewActiveIdentity(String identityTag, Identity identity) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@

package bisq.network.p2p.services.confidential;

import bisq.common.network.Address;
import bisq.common.threading.ExecutorFactory;
import bisq.common.threading.ThreadName;
import bisq.common.util.CompletableFutureUtils;
import bisq.common.network.Address;
import bisq.network.identity.NetworkId;
import bisq.network.p2p.message.EnvelopePayloadMessage;
import bisq.network.p2p.node.CloseReason;
Expand Down Expand Up @@ -347,6 +347,7 @@ private SendConfidentialMessageResult storeMailBoxMessage(MetaData metaData,

// TODO (refactor, low prio) async for creating the stores, could be made blocking
BroadcastResult mailboxFuture = dataService.get().addMailboxData(mailboxData, senderKeyPair, publicKey).join();
log.info("Try to store confidentialMessage to mailbox. ReceiverKeyId={}", confidentialMessage.getReceiverKeyId());
return new SendConfidentialMessageResult(MessageDeliveryStatus.TRY_ADD_TO_MAILBOX).setMailboxFuture(mailboxFuture);
}

Expand All @@ -366,7 +367,7 @@ private CompletableFuture<Boolean> processConfidentialMessage(ConfidentialMessag
return keyBundleService.findKeyPair(confidentialMessage.getReceiverKeyId())
.map(receiversKeyPair -> supplyAsync(() -> {
try {
log.info("Found a matching key for processing confidentialMessage");
log.info("Found a matching key for processing confidentialMessage. ReceiverKeyId={}", confidentialMessage.getReceiverKeyId());
ConfidentialData confidentialData = confidentialMessage.getConfidentialData();
byte[] decryptedBytes = HybridEncryption.decryptAndVerify(confidentialData, receiversKeyPair);
bisq.network.protobuf.EnvelopePayloadMessage decryptedProto = bisq.network.protobuf.EnvelopePayloadMessage.parseFrom(decryptedBytes);
Expand All @@ -378,7 +379,7 @@ private CompletableFuture<Boolean> processConfidentialMessage(ConfidentialMessag
boolean wasNotPresent = processedEnvelopePayloadMessages.add(decryptedEnvelopePayloadMessage);
if (wasNotPresent) {
PublicKey senderPublicKey = KeyGeneration.generatePublic(confidentialData.getSenderPublicKey());
log.info("Decrypted confidentialMessage");
log.info("Decrypted confidentialMessage. decryptedEnvelopePayloadMessage={}", decryptedEnvelopePayloadMessage.getClass().getSimpleName());
runAsync(() -> listeners.forEach(listener -> {
try {
listener.onMessage(decryptedEnvelopePayloadMessage);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ public void authenticate(PasswordDigest passwordDigest) {
sendCommand(command);
String reply = receiveReply().findFirst().orElseThrow();

if (reply.equals("250 OK")) {
if (isSuccessReply(reply)) {
return;
}

Expand All @@ -92,7 +92,7 @@ public void authenticate(byte[] authCookie) {
sendCommand(command);
String reply = receiveReply().findFirst().orElseThrow();

if (reply.equals("250 OK")) {
if (isSuccessReply(reply)) {
return;
}

Expand Down Expand Up @@ -121,7 +121,7 @@ public void hsFetch(String hsAddress) {
String command = "HSFETCH " + hsAddress + "\r\n";
sendCommand(command);
String reply = receiveReply().findFirst().orElseThrow();
if (!reply.equals("250 OK")) {
if (!isSuccessReply(reply)) {
throw new ControlCommandFailedException("Couldn't initiate HSFETCH for : " + hsAddress);
}
}
Expand All @@ -130,7 +130,7 @@ public void resetConf(String configName) {
String command = "RESETCONF " + configName + "\r\n";
sendCommand(command);
String reply = receiveReply().findFirst().orElseThrow();
if (!reply.equals("250 OK")) {
if (!isSuccessReply(reply)) {
throw new ControlCommandFailedException("Couldn't reset config: " + configName);
}
}
Expand All @@ -139,7 +139,7 @@ public void setConfig(String configName, String configValue) {
String command = "SETCONF " + configName + "=" + configValue + "\r\n";
sendCommand(command);
String reply = receiveReply().findFirst().orElseThrow();
if (!reply.equals("250 OK")) {
if (!isSuccessReply(reply)) {
throw new ControlCommandFailedException("Couldn't set config: " + configName + "=" + configValue);
}
}
Expand All @@ -148,7 +148,7 @@ public void takeOwnership() {
String command = "TAKEOWNERSHIP\r\n";
sendCommand(command);
String reply = receiveReply().findFirst().orElseThrow();
if (!reply.equals("250 OK")) {
if (!isSuccessReply(reply)) {
throw new ControlCommandFailedException("Couldn't take ownership");
}
}
Expand Down Expand Up @@ -242,7 +242,7 @@ private void registerEvents(Set<String> events) {
String command = stringBuilder.toString();
sendCommand(command);
String reply = receiveReply().findFirst().orElseThrow();
if (!reply.equals("250 OK")) {
if (!isSuccessReply(reply)) {
throw new ControlCommandFailedException("Couldn't set events: " + events);
}
}
Expand Down Expand Up @@ -341,4 +341,8 @@ private String validateReply(Stream<String> replyStream, String commandName) {
return firstLine;*/
}

private boolean isSuccessReply(String reply) {
return reply.startsWith("250");
}
}
8 changes: 6 additions & 2 deletions security/src/main/java/bisq/security/ConfidentialData.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,17 @@ public ConfidentialData(byte[] senderPublicKey,
this.cipherText = cipherText;
this.signature = signature;

verify();
try {
verify();
} catch (Exception e) {
log.error("ConfidentialData verification failed", e);
}
}

@Override
public void verify() {
checkArgument(iv.length <= 20);
checkArgument(cipherText.length <= MAX_SIZE_CIPHERTEXT);
checkArgument(cipherText.length <= MAX_SIZE_CIPHERTEXT, "cipherText size must not exceed 20 000 bytes");
NetworkDataValidation.validateECPubKey(senderPublicKey);
NetworkDataValidation.validateECSignature(signature);
}
Expand Down

0 comments on commit 93219fc

Please sign in to comment.