Merge branch 'master' of github.com:bisq-network/bisq into release/v1.3.8

# Conflicts:
#	core/src/main/java/bisq/core/support/dispute/agent/MultipleHolderNameDetection.java
#	core/src/main/java/bisq/core/trade/txproof/xmr/XmrTxProofService.java
This commit is contained in:
Christoph Atteneder 2020-09-15 13:24:06 +02:00
commit 98b03937d8
No known key found for this signature in database
GPG key ID: CD5DC1C529CDFD3B
23 changed files with 359 additions and 213 deletions

View file

@ -63,7 +63,7 @@ configure(subprojects) {
loggingVersion = '1.2'
lombokVersion = '1.18.2'
mockitoVersion = '3.0.0'
netlayerVersion = '0.6.7'
netlayerVersion = '0.6.8'
protobufVersion = '3.10.0'
protocVersion = protobufVersion
pushyVersion = '0.13.2'

View file

@ -102,7 +102,9 @@ public class FileUtil {
deleteDirectory(file, null, true);
}
public static void deleteDirectory(File file, @Nullable File exclude, boolean ignoreLockedFiles) throws IOException {
public static void deleteDirectory(File file,
@Nullable File exclude,
boolean ignoreLockedFiles) throws IOException {
boolean excludeFileFound = false;
if (file.isDirectory()) {
File[] files = file.listFiles();
@ -156,7 +158,8 @@ public class FileUtil {
return !file.canWrite();
}
public static void resourceToFile(String resourcePath, File destinationFile) throws ResourceNotFoundException, IOException {
public static void resourceToFile(String resourcePath,
File destinationFile) throws ResourceNotFoundException, IOException {
try (InputStream inputStream = ClassLoader.getSystemClassLoader().getResourceAsStream(resourcePath)) {
if (inputStream == null) {
throw new ResourceNotFoundException(resourcePath);
@ -182,6 +185,20 @@ public class FileUtil {
}
}
public static void copyFile(File origin, File target) throws IOException {
if (!origin.exists()) {
return;
}
try {
Files.copy(origin, target);
} catch (IOException e) {
log.error("Copy file failed", e);
throw new IOException("Failed to copy " + origin + " to " + target);
}
}
public static void copyDirectory(File source, File destination) throws IOException {
FileUtils.copyDirectory(source, destination);
}

View file

@ -20,7 +20,6 @@ package bisq.core.account.witness;
import bisq.core.account.sign.SignedWitness;
import bisq.core.account.sign.SignedWitnessService;
import bisq.core.filter.FilterManager;
import bisq.core.filter.PaymentAccountFilter;
import bisq.core.locale.CurrencyUtil;
import bisq.core.locale.Res;
import bisq.core.offer.Offer;
@ -718,10 +717,8 @@ public class AccountAgeWitnessService {
filterManager.isCurrencyBanned(dispute.getContract().getOfferPayload().getCurrencyCode()) ||
filterManager.isPaymentMethodBanned(
PaymentMethod.getPaymentMethodById(dispute.getContract().getPaymentMethodId())) ||
filterManager.arePeersPaymentAccountDataBanned(dispute.getContract().getBuyerPaymentAccountPayload(),
new PaymentAccountFilter[1]) ||
filterManager.arePeersPaymentAccountDataBanned(dispute.getContract().getSellerPaymentAccountPayload(),
new PaymentAccountFilter[1]) ||
filterManager.arePeersPaymentAccountDataBanned(dispute.getContract().getBuyerPaymentAccountPayload()) ||
filterManager.arePeersPaymentAccountDataBanned(dispute.getContract().getSellerPaymentAccountPayload()) ||
filterManager.isWitnessSignerPubKeyBanned(
Utils.HEX.encode(dispute.getContract().getBuyerPubKeyRing().getSignaturePubKeyBytes())) ||
filterManager.isWitnessSignerPubKeyBanned(

View file

@ -186,10 +186,6 @@ public final class AddressEntry implements PersistablePayload {
return context == Context.MULTI_SIG || context == Context.TRADE_PAYOUT;
}
public boolean isTradable() {
return isOpenOffer() || isTrade();
}
public Coin getCoinLockedInMultiSig() {
return Coin.valueOf(coinLockedInMultiSig);
}
@ -197,9 +193,10 @@ public final class AddressEntry implements PersistablePayload {
@Override
public String toString() {
return "AddressEntry{" +
"offerId='" + getOfferId() + '\'' +
"address=" + address +
", context=" + context +
", address=" + getAddressString() +
'}';
", offerId='" + offerId + '\'' +
", coinLockedInMultiSig=" + coinLockedInMultiSig +
"}";
}
}

View file

@ -17,38 +17,41 @@
package bisq.core.btc.model;
import bisq.common.config.Config;
import bisq.common.proto.persistable.PersistedDataHost;
import bisq.common.proto.persistable.UserThreadMappedPersistableEnvelope;
import bisq.common.storage.Storage;
import com.google.protobuf.Message;
import org.bitcoinj.core.Address;
import org.bitcoinj.core.Transaction;
import org.bitcoinj.crypto.DeterministicKey;
import org.bitcoinj.wallet.Wallet;
import com.google.inject.Inject;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import com.google.common.collect.ImmutableList;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.stream.Collectors;
import lombok.Getter;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
/**
* The List supporting our persistence solution.
* The AddressEntries was previously stored as list, now as hashSet. We still keep the old name to reflect the
* associated protobuf message.
*/
@ToString
@Slf4j
public final class AddressEntryList implements UserThreadMappedPersistableEnvelope, PersistedDataHost {
transient private Storage<AddressEntryList> storage;
transient private Wallet wallet;
@Getter
private List<AddressEntry> list;
private final Set<AddressEntry> entrySet = new CopyOnWriteArraySet<>();
@Inject
public AddressEntryList(Storage<AddressEntryList> storage) {
@ -58,8 +61,10 @@ public final class AddressEntryList implements UserThreadMappedPersistableEnvelo
@Override
public void readPersisted() {
AddressEntryList persisted = storage.initAndGetPersisted(this, 50);
if (persisted != null)
list = new ArrayList<>(persisted.getList());
if (persisted != null) {
entrySet.clear();
entrySet.addAll(persisted.entrySet);
}
}
@ -67,22 +72,22 @@ public final class AddressEntryList implements UserThreadMappedPersistableEnvelo
// PROTO BUFFER
///////////////////////////////////////////////////////////////////////////////////////////
private AddressEntryList(List<AddressEntry> list) {
this.list = list;
private AddressEntryList(Set<AddressEntry> entrySet) {
this.entrySet.addAll(entrySet);
}
public static AddressEntryList fromProto(protobuf.AddressEntryList proto) {
return new AddressEntryList(new ArrayList<>(proto.getAddressEntryList().stream().map(AddressEntry::fromProto).collect(Collectors.toList())));
Set<AddressEntry> entrySet = proto.getAddressEntryList().stream()
.map(AddressEntry::fromProto)
.collect(Collectors.toSet());
return new AddressEntryList(entrySet);
}
@Override
public Message toProtoMessage() {
// We clone list as we got ConcurrentModificationExceptions
List<AddressEntry> clone = new ArrayList<>(list);
List<protobuf.AddressEntry> addressEntries = clone.stream()
Set<protobuf.AddressEntry> addressEntries = entrySet.stream()
.map(AddressEntry::toProtoMessage)
.collect(Collectors.toList());
.collect(Collectors.toSet());
return protobuf.PersistableEnvelope.newBuilder()
.setAddressEntryList(protobuf.AddressEntryList.newBuilder()
.addAllAddressEntry(addressEntries))
@ -97,29 +102,50 @@ public final class AddressEntryList implements UserThreadMappedPersistableEnvelo
public void onWalletReady(Wallet wallet) {
this.wallet = wallet;
if (list != null) {
list.forEach(addressEntry -> {
if (!entrySet.isEmpty()) {
Set<AddressEntry> toBeRemoved = new HashSet<>();
entrySet.forEach(addressEntry -> {
DeterministicKey keyFromPubHash = (DeterministicKey) wallet.findKeyFromPubHash(addressEntry.getPubKeyHash());
if (keyFromPubHash != null) {
addressEntry.setDeterministicKey(keyFromPubHash);
Address addressFromKey = keyFromPubHash.toAddress(Config.baseCurrencyNetworkParameters());
// We want to ensure key and address matches in case we have address in entry available already
if (addressEntry.getAddress() == null || addressFromKey.equals(addressEntry.getAddress())) {
addressEntry.setDeterministicKey(keyFromPubHash);
} else {
log.error("We found an address entry without key but cannot apply the key as the address " +
"is not matching. " +
"We remove that entry as it seems it is not compatible with our wallet. " +
"addressFromKey={}, addressEntry.getAddress()={}",
addressFromKey, addressEntry.getAddress());
toBeRemoved.add(addressEntry);
}
} else {
log.error("Key from addressEntry not found in that wallet " + addressEntry.toString());
log.error("Key from addressEntry {} not found in that wallet. We remove that entry. " +
"This is expected at restore from seeds.", addressEntry.toString());
toBeRemoved.add(addressEntry);
}
});
} else {
list = new ArrayList<>();
add(new AddressEntry(wallet.freshReceiveKey(), AddressEntry.Context.ARBITRATOR));
// In case we restore from seed words and have balance we need to add the relevant addresses to our list.
// IssuedReceiveAddresses does not contain all addresses where we expect balance so we need to listen to
// incoming txs at blockchain sync to add the rest.
if (wallet.getBalance().isPositive()) {
wallet.getIssuedReceiveAddresses().forEach(address -> {
log.info("Create AddressEntry for IssuedReceiveAddress. address={}", address.toString());
add(new AddressEntry((DeterministicKey) wallet.findKeyFromPubHash(address.getHash160()), AddressEntry.Context.AVAILABLE));
});
}
persist();
toBeRemoved.forEach(entrySet::remove);
} else {
// As long the old arbitration domain is not removed from the code base we still support it here.
entrySet.add(new AddressEntry(wallet.freshReceiveKey(), AddressEntry.Context.ARBITRATOR));
}
// In case we restore from seed words and have balance we need to add the relevant addresses to our list.
// IssuedReceiveAddresses does not contain all addresses where we expect balance so we need to listen to
// incoming txs at blockchain sync to add the rest.
if (wallet.getBalance().isPositive()) {
wallet.getIssuedReceiveAddresses().stream()
.filter(this::isAddressNotInEntries)
.forEach(address -> {
log.info("Create AddressEntry for IssuedReceiveAddress. address={}", address.toString());
DeterministicKey key = (DeterministicKey) wallet.findKeyFromPubHash(address.getHash160());
if (key != null) {
// Address will be derived from key in getAddress method
entrySet.add(new AddressEntry(key, AddressEntry.Context.AVAILABLE));
}
});
}
// We add those listeners to get notified about potential new transactions and
@ -127,62 +153,41 @@ public final class AddressEntryList implements UserThreadMappedPersistableEnvelo
// but can help as well in case the addressEntry list would miss an address where the wallet was received
// funds (e.g. if the user sends funds to an address which has not been provided in the main UI - like from the
// wallet details window).
wallet.addCoinsReceivedEventListener((w, tx, prevBalance, newBalance) -> {
updateList(tx);
wallet.addCoinsReceivedEventListener((wallet1, tx, prevBalance, newBalance) -> {
maybeAddNewAddressEntry(tx);
});
wallet.addCoinsSentEventListener((w, tx, prevBalance, newBalance) -> {
updateList(tx);
wallet.addCoinsSentEventListener((wallet1, tx, prevBalance, newBalance) -> {
maybeAddNewAddressEntry(tx);
});
persist();
}
private void updateList(Transaction tx) {
tx.getOutputs().stream()
.filter(output -> output.isMine(wallet))
.map(output -> output.getAddressFromP2PKHScript(wallet.getNetworkParameters()))
.filter(Objects::nonNull)
.filter(address -> !listContainsEntryWithAddress(address.toBase58()))
.map(address -> (DeterministicKey) wallet.findKeyFromPubHash(address.getHash160()))
.filter(Objects::nonNull)
.map(deterministicKey -> new AddressEntry(deterministicKey, AddressEntry.Context.AVAILABLE))
.forEach(addressEntry -> list.add(addressEntry));
public ImmutableList<AddressEntry> getAddressEntriesAsListImmutable() {
return ImmutableList.copyOf(entrySet);
}
private boolean listContainsEntryWithAddress(String addressString) {
return list.stream().anyMatch(addressEntry -> Objects.equals(addressEntry.getAddressString(), addressString));
}
private boolean add(AddressEntry addressEntry) {
return list.add(addressEntry);
}
private boolean remove(AddressEntry addressEntry) {
return list.remove(addressEntry);
}
public AddressEntry addAddressEntry(AddressEntry addressEntry) {
boolean changed = add(addressEntry);
if (changed)
public void addAddressEntry(AddressEntry addressEntry) {
boolean setChangedByAdd = entrySet.add(addressEntry);
if (setChangedByAdd)
persist();
return addressEntry;
}
public void swapTradeToSavings(String offerId) {
list.stream().filter(addressEntry -> offerId.equals(addressEntry.getOfferId()))
.findAny().ifPresent(this::swapToAvailable);
}
public void swapToAvailable(AddressEntry addressEntry) {
boolean changed1 = remove(addressEntry);
boolean changed2 = add(new AddressEntry(addressEntry.getKeyPair(), AddressEntry.Context.AVAILABLE));
if (changed1 || changed2)
boolean setChangedByRemove = entrySet.remove(addressEntry);
boolean setChangedByAdd = entrySet.add(new AddressEntry(addressEntry.getKeyPair(), AddressEntry.Context.AVAILABLE));
if (setChangedByRemove || setChangedByAdd) {
persist();
}
}
public AddressEntry swapAvailableToAddressEntryWithOfferId(AddressEntry addressEntry, AddressEntry.Context context, String offerId) {
boolean changed1 = remove(addressEntry);
public AddressEntry swapAvailableToAddressEntryWithOfferId(AddressEntry addressEntry,
AddressEntry.Context context,
String offerId) {
boolean setChangedByRemove = entrySet.remove(addressEntry);
final AddressEntry newAddressEntry = new AddressEntry(addressEntry.getKeyPair(), context, offerId);
boolean changed2 = add(newAddressEntry);
if (changed1 || changed2)
boolean setChangedByAdd = entrySet.add(newAddressEntry);
if (setChangedByRemove || setChangedByAdd)
persist();
return newAddressEntry;
@ -192,7 +197,24 @@ public final class AddressEntryList implements UserThreadMappedPersistableEnvelo
storage.queueUpForSave(50);
}
public Stream<AddressEntry> stream() {
return list.stream();
///////////////////////////////////////////////////////////////////////////////////////////
// Private
///////////////////////////////////////////////////////////////////////////////////////////
private void maybeAddNewAddressEntry(Transaction tx) {
tx.getOutputs().stream()
.filter(output -> output.isMine(wallet))
.map(output -> output.getAddressFromP2PKHScript(wallet.getNetworkParameters()))
.filter(Objects::nonNull)
.filter(this::isAddressNotInEntries)
.map(address -> (DeterministicKey) wallet.findKeyFromPubHash(address.getHash160()))
.filter(Objects::nonNull)
.map(deterministicKey -> new AddressEntry(deterministicKey, AddressEntry.Context.AVAILABLE))
.forEach(this::addAddressEntry);
}
private boolean isAddressNotInEntries(Address address) {
return entrySet.stream().noneMatch(e -> address.equals(e.getAddress()));
}
}

View file

@ -59,7 +59,6 @@ import javax.inject.Inject;
import javax.inject.Named;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import com.google.common.util.concurrent.Service;
import org.apache.commons.lang3.StringUtils;
@ -498,7 +497,7 @@ public class WalletsSetup {
}
public Set<Address> getAddressesByContext(@SuppressWarnings("SameParameterValue") AddressEntry.Context context) {
return ImmutableList.copyOf(addressEntryList.getList()).stream()
return addressEntryList.getAddressEntriesAsListImmutable().stream()
.filter(addressEntry -> addressEntry.getContext() == context)
.map(AddressEntry::getAddress)
.collect(Collectors.toSet());

View file

@ -47,7 +47,6 @@ import org.bitcoinj.wallet.Wallet;
import javax.inject.Inject;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
@ -108,8 +107,8 @@ public class BtcWalletService extends WalletService {
void decryptWallet(@NotNull KeyParameter key) {
super.decryptWallet(key);
addressEntryList.stream().forEach(e -> {
final DeterministicKey keyPair = e.getKeyPair();
addressEntryList.getAddressEntriesAsListImmutable().stream().forEach(e -> {
DeterministicKey keyPair = e.getKeyPair();
if (keyPair.isEncrypted())
e.setDeterministicKey(keyPair.decrypt(key));
});
@ -119,8 +118,8 @@ public class BtcWalletService extends WalletService {
@Override
void encryptWallet(KeyCrypterScrypt keyCrypterScrypt, KeyParameter key) {
super.encryptWallet(keyCrypterScrypt, key);
addressEntryList.stream().forEach(e -> {
final DeterministicKey keyPair = e.getKeyPair();
addressEntryList.getAddressEntriesAsListImmutable().stream().forEach(e -> {
DeterministicKey keyPair = e.getKeyPair();
if (keyPair.isEncrypted())
e.setDeterministicKey(keyPair.encrypt(keyCrypterScrypt, key));
});
@ -157,12 +156,18 @@ public class BtcWalletService extends WalletService {
// Proposal txs
///////////////////////////////////////////////////////////////////////////////////////////
public Transaction completePreparedReimbursementRequestTx(Coin issuanceAmount, Address issuanceAddress, Transaction feeTx, byte[] opReturnData)
public Transaction completePreparedReimbursementRequestTx(Coin issuanceAmount,
Address issuanceAddress,
Transaction feeTx,
byte[] opReturnData)
throws TransactionVerificationException, WalletException, InsufficientMoneyException {
return completePreparedProposalTx(feeTx, opReturnData, issuanceAmount, issuanceAddress);
}
public Transaction completePreparedCompensationRequestTx(Coin issuanceAmount, Address issuanceAddress, Transaction feeTx, byte[] opReturnData)
public Transaction completePreparedCompensationRequestTx(Coin issuanceAmount,
Address issuanceAddress,
Transaction feeTx,
byte[] opReturnData)
throws TransactionVerificationException, WalletException, InsufficientMoneyException {
return completePreparedProposalTx(feeTx, opReturnData, issuanceAmount, issuanceAddress);
}
@ -292,7 +297,8 @@ public class BtcWalletService extends WalletService {
return completePreparedBsqTxWithBtcFee(preparedTx, opReturnData);
}
private Transaction completePreparedBsqTxWithBtcFee(Transaction preparedTx, byte[] opReturnData) throws InsufficientMoneyException, TransactionVerificationException, WalletException {
private Transaction completePreparedBsqTxWithBtcFee(Transaction preparedTx,
byte[] opReturnData) throws InsufficientMoneyException, TransactionVerificationException, WalletException {
// Remember index for first BTC input
int indexOfBtcFirstInput = preparedTx.getInputs().size();
@ -306,7 +312,8 @@ public class BtcWalletService extends WalletService {
return tx;
}
private Transaction addInputsForMinerFee(Transaction preparedTx, byte[] opReturnData) throws InsufficientMoneyException {
private Transaction addInputsForMinerFee(Transaction preparedTx,
byte[] opReturnData) throws InsufficientMoneyException {
// safety check counter to avoid endless loops
int counter = 0;
// estimated size of input sig
@ -421,7 +428,9 @@ public class BtcWalletService extends WalletService {
return completePreparedBsqTx(preparedBsqTx, isSendTx, null);
}
public Transaction completePreparedBsqTx(Transaction preparedBsqTx, boolean useCustomTxFee, @Nullable byte[] opReturnData) throws
public Transaction completePreparedBsqTx(Transaction preparedBsqTx,
boolean useCustomTxFee,
@Nullable byte[] opReturnData) throws
TransactionVerificationException, WalletException, InsufficientMoneyException {
// preparedBsqTx has following structure:
@ -545,7 +554,8 @@ public class BtcWalletService extends WalletService {
// AddressEntry
///////////////////////////////////////////////////////////////////////////////////////////
public Optional<AddressEntry> getAddressEntry(String offerId, @SuppressWarnings("SameParameterValue") AddressEntry.Context context) {
public Optional<AddressEntry> getAddressEntry(String offerId,
@SuppressWarnings("SameParameterValue") AddressEntry.Context context) {
return getAddressEntryListAsImmutableList().stream()
.filter(e -> offerId.equals(e.getOfferId()))
.filter(e -> context == e.getContext())
@ -592,17 +602,14 @@ public class BtcWalletService extends WalletService {
return getOrCreateAddressEntry(context, addressEntry);
}
public AddressEntry getNewAddressEntry(String offerId, AddressEntry.Context context) {
public void getNewAddressEntry(String offerId, AddressEntry.Context context) {
AddressEntry entry = new AddressEntry(wallet.freshReceiveKey(), context, offerId);
addressEntryList.addAddressEntry(entry);
return entry;
}
public AddressEntry recoverAddressEntry(String offerId, String address, AddressEntry.Context context) {
var available = findAddressEntry(address, AddressEntry.Context.AVAILABLE);
if (!available.isPresent())
return null;
return addressEntryList.swapAvailableToAddressEntryWithOfferId(available.get(), context, offerId);
public void recoverAddressEntry(String offerId, String address, AddressEntry.Context context) {
findAddressEntry(address, AddressEntry.Context.AVAILABLE).ifPresent(addressEntry ->
addressEntryList.swapAvailableToAddressEntryWithOfferId(addressEntry, context, offerId));
}
private AddressEntry getOrCreateAddressEntry(AddressEntry.Context context, Optional<AddressEntry> addressEntry) {
@ -655,20 +662,18 @@ public class BtcWalletService extends WalletService {
}
public List<AddressEntry> getAddressEntryListAsImmutableList() {
return ImmutableList.copyOf(addressEntryList.getList());
return addressEntryList.getAddressEntriesAsListImmutable();
}
public void swapTradeEntryToAvailableEntry(String offerId, AddressEntry.Context context) {
Optional<AddressEntry> addressEntryOptional = getAddressEntryListAsImmutableList().stream()
getAddressEntryListAsImmutableList().stream()
.filter(e -> offerId.equals(e.getOfferId()))
.filter(e -> context == e.getContext())
.findAny();
addressEntryOptional.ifPresent(e -> {
log.info("swap addressEntry with address {} and offerId {} from context {} to available",
e.getAddressString(), e.getOfferId(), context);
addressEntryList.swapToAvailable(e);
saveAddressEntryList();
});
.forEach(e -> {
log.info("swap addressEntry with address {} and offerId {} from context {} to available",
e.getAddressString(), e.getOfferId(), context);
addressEntryList.swapToAvailable(e);
});
}
public void resetAddressEntriesForOpenOffer(String offerId) {

View file

@ -371,24 +371,19 @@ public class FilterManager {
return requireUpdateToNewVersion;
}
public boolean arePeersPaymentAccountDataBanned(PaymentAccountPayload paymentAccountPayload,
PaymentAccountFilter[] appliedPaymentAccountFilter) {
public boolean arePeersPaymentAccountDataBanned(PaymentAccountPayload paymentAccountPayload) {
return getFilter() != null &&
getFilter().getBannedPaymentAccounts().stream()
.filter(paymentAccountFilter -> paymentAccountFilter.getPaymentMethodId().equals(
paymentAccountPayload.getPaymentMethodId()))
.anyMatch(paymentAccountFilter -> {
final boolean samePaymentMethodId = paymentAccountFilter.getPaymentMethodId().equals(
paymentAccountPayload.getPaymentMethodId());
if (samePaymentMethodId) {
try {
Method method = paymentAccountPayload.getClass().getMethod(paymentAccountFilter.getGetMethodName());
String result = (String) method.invoke(paymentAccountPayload);
appliedPaymentAccountFilter[0] = paymentAccountFilter;
return result.toLowerCase().equals(paymentAccountFilter.getValue().toLowerCase());
} catch (Throwable e) {
log.error(e.getMessage());
return false;
}
} else {
try {
Method method = paymentAccountPayload.getClass().getMethod(paymentAccountFilter.getGetMethodName());
// We invoke getter methods (no args), e.g. getHolderName
String valueFromInvoke = (String) method.invoke(paymentAccountPayload);
return valueFromInvoke.equalsIgnoreCase(paymentAccountFilter.getValue());
} catch (Throwable e) {
log.error(e.getMessage());
return false;
}
});

View file

@ -200,18 +200,19 @@ public class MultipleHolderNameDetection {
private Map<String, List<Dispute>> getAllDisputesByTraderMap() {
Map<String, List<Dispute>> allDisputesByTraderMap = new HashMap<>();
disputeManager.getDisputesAsObservableList()
.forEach(dispute -> {
disputeManager.getDisputesAsObservableList().stream()
.filter(dispute -> {
Contract contract = dispute.getContract();
PaymentAccountPayload paymentAccountPayload = isBuyer(dispute) ?
contract.getBuyerPaymentAccountPayload() :
contract.getSellerPaymentAccountPayload();
if (paymentAccountPayload instanceof PayloadWithHolderName) {
String traderPubKeyHash = getSigPubKeyHashAsHex(dispute);
allDisputesByTraderMap.putIfAbsent(traderPubKeyHash, new ArrayList<>());
List<Dispute> disputes = allDisputesByTraderMap.get(traderPubKeyHash);
disputes.add(dispute);
}
return paymentAccountPayload instanceof PayloadWithHolderName;
})
.forEach(dispute -> {
String traderPubKeyHash = getSigPubKeyHashAsHex(dispute);
allDisputesByTraderMap.putIfAbsent(traderPubKeyHash, new ArrayList<>());
List<Dispute> disputes = allDisputesByTraderMap.get(traderPubKeyHash);
disputes.add(dispute);
});
return allDisputesByTraderMap;
}

View file

@ -18,7 +18,6 @@
package bisq.core.trade.protocol.tasks;
import bisq.core.filter.FilterManager;
import bisq.core.filter.PaymentAccountFilter;
import bisq.core.payment.payload.PaymentAccountPayload;
import bisq.core.trade.Trade;
@ -42,9 +41,8 @@ public class ApplyFilter extends TradeTask {
try {
runInterceptHook();
final NodeAddress nodeAddress = processModel.getTempTradingPeerNodeAddress();
NodeAddress nodeAddress = processModel.getTempTradingPeerNodeAddress();
PaymentAccountPayload paymentAccountPayload = checkNotNull(processModel.getTradingPeer().getPaymentAccountPayload());
final PaymentAccountFilter[] appliedPaymentAccountFilter = new PaymentAccountFilter[1];
FilterManager filterManager = processModel.getFilterManager();
if (nodeAddress != null && filterManager.isNodeAddressBanned(nodeAddress)) {
@ -56,13 +54,12 @@ public class ApplyFilter extends TradeTask {
} else if (trade.getOffer() != null && filterManager.isCurrencyBanned(trade.getOffer().getCurrencyCode())) {
failed("Currency is banned.\n" +
"Currency code=" + trade.getOffer().getCurrencyCode());
} else if (filterManager.isPaymentMethodBanned(trade.getOffer().getPaymentMethod())) {
} else if (filterManager.isPaymentMethodBanned(checkNotNull(trade.getOffer()).getPaymentMethod())) {
failed("Payment method is banned.\n" +
"Payment method=" + trade.getOffer().getPaymentMethod().getId());
} else if (filterManager.arePeersPaymentAccountDataBanned(paymentAccountPayload, appliedPaymentAccountFilter)) {
} else if (filterManager.arePeersPaymentAccountDataBanned(paymentAccountPayload)) {
failed("Other trader is banned by their trading account data.\n" +
"paymentAccountPayload=" + paymentAccountPayload.getPaymentDetails() + "\n" +
"banFilter=" + appliedPaymentAccountFilter[0].toString());
"paymentAccountPayload=" + paymentAccountPayload.getPaymentDetails());
} else if (filterManager.requireUpdateToNewVersionForTrading()) {
failed("Your version of Bisq is not compatible for trading anymore. " +
"Please update to the latest Bisq version at https://bisq.network/downloads.");

View file

@ -166,6 +166,7 @@ public class XmrTxProofService implements AssetTxProofService {
if (!preferences.findAutoConfirmSettings("XMR").isPresent()) {
log.error("AutoConfirmSettings is not present");
return;
}
autoConfirmSettings = preferences.findAutoConfirmSettings("XMR").get();

View file

@ -1931,9 +1931,9 @@ dao.bond.bondedRoleType.DATA_RELAY_NODE_OPERATOR=Price node operator
# suppress inspection "UnusedProperty"
dao.bond.bondedRoleType.BTC_NODE_OPERATOR=Bitcoin node operator
# suppress inspection "UnusedProperty"
dao.bond.bondedRoleType.MARKETS_OPERATOR=Markets API operator
dao.bond.bondedRoleType.MARKETS_OPERATOR=Markets operator
# suppress inspection "UnusedProperty"
dao.bond.bondedRoleType.BSQ_EXPLORER_OPERATOR=BSQ explorer operator
dao.bond.bondedRoleType.BSQ_EXPLORER_OPERATOR=Explorer operator
# suppress inspection "UnusedProperty"
dao.bond.bondedRoleType.MOBILE_NOTIFICATIONS_RELAY_OPERATOR=Mobile notifications relay operator
# suppress inspection "UnusedProperty"
@ -3036,6 +3036,8 @@ Ideally you should specify the date your wallet seed was created.\n\n\n\
Are you sure you want to go ahead without specifying a wallet date?
seed.restore.success=Wallets restored successfully with the new seed words.\n\nYou need to shut down and restart the application.
seed.restore.error=An error occurred when restoring the wallets with seed words.{0}
seed.restore.openOffers.warn=You have open offers which will be removed if you restore from seed words.\n\
Are you sure that you want to continue?
####################################################################

View file

@ -218,7 +218,7 @@ public class AccountAgeWitnessServiceTest {
when(filterManager.isNodeAddressBanned(any())).thenReturn(false);
when(filterManager.isCurrencyBanned(any())).thenReturn(false);
when(filterManager.isPaymentMethodBanned(any())).thenReturn(false);
when(filterManager.arePeersPaymentAccountDataBanned(any(), any())).thenReturn(false);
when(filterManager.arePeersPaymentAccountDataBanned(any())).thenReturn(false);
when(filterManager.isWitnessSignerPubKeyBanned(any())).thenReturn(false);
when(chargeBackRisk.hasChargebackRisk(any(), any())).thenReturn(true);

View file

@ -54,6 +54,8 @@ import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.name.Names;
import com.google.common.base.Joiner;
import javafx.application.Application;
import javafx.stage.Modality;
@ -69,6 +71,8 @@ import javafx.scene.layout.StackPane;
import java.awt.GraphicsEnvironment;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
@ -241,8 +245,19 @@ public class BisqApp extends Application implements UncaughtExceptionHandler {
// configure the primary stage
String appName = injector.getInstance(Key.get(String.class, Names.named(Config.APP_NAME)));
if (!Config.baseCurrencyNetwork().isMainnet())
appName += " [" + Res.get(Config.baseCurrencyNetwork().name()) + "]";
List<String> postFixes = new ArrayList<>();
if (!Config.baseCurrencyNetwork().isMainnet()) {
postFixes.add(Config.baseCurrencyNetwork().name());
}
if (injector.getInstance(Config.class).useLocalhostForP2P) {
postFixes.add("LOCALHOST");
}
if (injector.getInstance(Config.class).useDevMode) {
postFixes.add("DEV MODE");
}
if (!postFixes.isEmpty()) {
appName += " [" + Joiner.on(", ").join(postFixes) + " ]";
}
stage.setTitle(appName);
stage.setScene(scene);

View file

@ -38,6 +38,7 @@ import bisq.core.payment.validation.AltCoinAddressValidator;
import bisq.core.util.coin.CoinFormatter;
import bisq.core.util.validation.InputValidator;
import bisq.common.UserThread;
import bisq.common.util.Tuple3;
import org.apache.commons.lang3.StringUtils;
@ -123,6 +124,13 @@ public class AssetsForm extends PaymentMethodForm {
addressInputTextField.setValidator(altCoinAddressValidator);
addressInputTextField.textProperty().addListener((ov, oldValue, newValue) -> {
if (newValue.startsWith("monero:")) {
UserThread.execute(() -> {
String addressWithoutPrefix = newValue.replace("monero:", "");
addressInputTextField.setText(addressWithoutPrefix);
});
return;
}
assetAccount.setAddress(newValue);
updateFromInputs();
});

View file

@ -685,10 +685,20 @@ public class MainViewModel implements ViewModel, BisqSetup.BisqSetupListener {
return marketPricePresentation.getPriceFeedComboBoxItems();
}
// We keep daoPresentation and accountPresentation support even it is not used atm. But if we add a new feature and
// add a badge again it will be needed.
@SuppressWarnings({"unused"})
public BooleanProperty getShowDaoUpdatesNotification() {
return daoPresentation.getShowDaoUpdatesNotification();
}
// We keep daoPresentation and accountPresentation support even it is not used atm. But if we add a new feature and
// add a badge again it will be needed.
@SuppressWarnings("unused")
public BooleanProperty getShowAccountUpdatesNotification() {
return accountPresentation.getShowAccountUpdatesNotification();
}
public BooleanProperty getShowSettingsUpdatesNotification() {
return settingsPresentation.getShowSettingsUpdatesNotification();
}

View file

@ -0,0 +1,87 @@
/*
* This file is part of Bisq.
*
* Bisq is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bisq is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.desktop.main;
import bisq.desktop.app.BisqApp;
import bisq.desktop.main.overlays.popups.Popup;
import bisq.core.btc.wallet.WalletsManager;
import bisq.core.locale.Res;
import bisq.core.offer.OpenOfferManager;
import bisq.common.UserThread;
import bisq.common.storage.FileUtil;
import org.bitcoinj.wallet.DeterministicSeed;
import java.io.File;
import java.util.concurrent.TimeUnit;
import lombok.extern.slf4j.Slf4j;
/**
* This serves as shared space for static methods used from different views where no common parent view would fit as
* owner of that code. We keep it strictly static. It should replace GUIUtil for those methods which are not utility
* methods.
*/
@Slf4j
public class SharedPresentation {
public static void restoreSeedWords(WalletsManager walletsManager,
OpenOfferManager openOfferManager,
DeterministicSeed seed,
File storageDir) {
if (!openOfferManager.getObservableList().isEmpty()) {
UserThread.runAfter(() ->
new Popup().warning(Res.get("seed.restore.openOffers.warn"))
.actionButtonText(Res.get("shared.yes"))
.onAction(() -> {
openOfferManager.removeAllOpenOffers(() -> {
doRestoreSeedWords(walletsManager, seed, storageDir);
});
})
.show(), 100, TimeUnit.MILLISECONDS);
} else {
doRestoreSeedWords(walletsManager, seed, storageDir);
}
}
private static void doRestoreSeedWords(WalletsManager walletsManager,
DeterministicSeed seed,
File storageDir) {
try {
File backup = new File(storageDir, "AddressEntryList_backup_pre_wallet_restore_" + System.currentTimeMillis());
FileUtil.copyFile(new File(storageDir, "AddressEntryList"), backup);
} catch (Throwable t) {
new Popup().error(Res.get("error.deleteAddressEntryListFailed", t)).show();
}
walletsManager.restoreSeedWords(
seed,
() -> UserThread.execute(() -> {
log.info("Wallets restored with seed words");
new Popup().feedback(Res.get("seed.restore.success")).hideCloseButton().show();
BisqApp.getShutDownHandler().run();
}),
throwable -> UserThread.execute(() -> {
log.error(throwable.toString());
new Popup().error(Res.get("seed.restore.error", Res.get("shared.errorMessageInline", throwable)))
.show();
}));
}
}

View file

@ -19,14 +19,15 @@ package bisq.desktop.main.account.content.seedwords;
import bisq.desktop.common.view.ActivatableView;
import bisq.desktop.common.view.FxmlView;
import bisq.desktop.main.SharedPresentation;
import bisq.desktop.main.overlays.popups.Popup;
import bisq.desktop.main.overlays.windows.WalletPasswordWindow;
import bisq.desktop.util.GUIUtil;
import bisq.desktop.util.Layout;
import bisq.core.btc.wallet.BtcWalletService;
import bisq.core.btc.wallet.WalletsManager;
import bisq.core.locale.Res;
import bisq.core.offer.OpenOfferManager;
import bisq.core.user.DontShowAgainLookup;
import bisq.common.config.Config;
@ -68,6 +69,7 @@ import static javafx.beans.binding.Bindings.createBooleanBinding;
@FxmlView
public class SeedWordsView extends ActivatableView<GridPane, Void> {
private final WalletsManager walletsManager;
private final OpenOfferManager openOfferManager;
private final BtcWalletService btcWalletService;
private final WalletPasswordWindow walletPasswordWindow;
private final File storageDir;
@ -91,10 +93,12 @@ public class SeedWordsView extends ActivatableView<GridPane, Void> {
@Inject
private SeedWordsView(WalletsManager walletsManager,
OpenOfferManager openOfferManager,
BtcWalletService btcWalletService,
WalletPasswordWindow walletPasswordWindow,
@Named(Config.STORAGE_DIR) File storageDir) {
this.walletsManager = walletsManager;
this.openOfferManager = openOfferManager;
this.btcWalletService = btcWalletService;
this.walletPasswordWindow = walletPasswordWindow;
this.storageDir = storageDir;
@ -166,20 +170,18 @@ public class SeedWordsView extends ActivatableView<GridPane, Void> {
String key = "showBackupWarningAtSeedPhrase";
if (DontShowAgainLookup.showAgain(key)) {
new Popup().warning(Res.get("account.seed.backup.warning"))
.onAction(() -> {
showSeedPhrase();
})
.actionButtonText(Res.get("shared.iUnderstand"))
.useIUnderstandButton()
.dontShowAgainId(key)
.hideCloseButton()
.show();
.onAction(this::showSeedPhrase)
.actionButtonText(Res.get("shared.iUnderstand"))
.useIUnderstandButton()
.dontShowAgainId(key)
.hideCloseButton()
.show();
} else {
showSeedPhrase();
}
}
public void showSeedPhrase() {
private void showSeedPhrase() {
DeterministicSeed keyChainSeed = btcWalletService.getKeyChainSeed();
// wallet creation date is not encrypted
walletCreationDate = Instant.ofEpochSecond(walletsManager.getChainSeedCreationTimeSeconds()).atZone(ZoneId.systemDefault()).toLocalDate();
@ -305,6 +307,6 @@ public class SeedWordsView extends ActivatableView<GridPane, Void> {
long date = localDateTime.toEpochSecond(ZoneOffset.UTC);
DeterministicSeed seed = new DeterministicSeed(Splitter.on(" ").splitToList(seedWordsTextArea.getText()), null, "", date);
GUIUtil.restoreSeedWords(seed, walletsManager, storageDir);
SharedPresentation.restoreSeedWords(walletsManager, openOfferManager, seed, storageDir);
}
}

View file

@ -21,15 +21,16 @@ import bisq.desktop.components.AutoTooltipButton;
import bisq.desktop.components.AutoTooltipLabel;
import bisq.desktop.components.BusyAnimation;
import bisq.desktop.components.PasswordTextField;
import bisq.desktop.main.SharedPresentation;
import bisq.desktop.main.overlays.Overlay;
import bisq.desktop.main.overlays.popups.Popup;
import bisq.desktop.util.GUIUtil;
import bisq.desktop.util.Layout;
import bisq.desktop.util.Transitions;
import bisq.core.btc.wallet.WalletsManager;
import bisq.core.crypto.ScryptUtil;
import bisq.core.locale.Res;
import bisq.core.offer.OpenOfferManager;
import bisq.common.UserThread;
import bisq.common.config.Config;
@ -88,6 +89,7 @@ import static javafx.beans.binding.Bindings.createBooleanBinding;
@Slf4j
public class WalletPasswordWindow extends Overlay<WalletPasswordWindow> {
private final WalletsManager walletsManager;
private final OpenOfferManager openOfferManager;
private File storageDir;
private Button unlockButton;
@ -115,8 +117,10 @@ public class WalletPasswordWindow extends Overlay<WalletPasswordWindow> {
@Inject
private WalletPasswordWindow(WalletsManager walletsManager,
OpenOfferManager openOfferManager,
@Named(Config.STORAGE_DIR) File storageDir) {
this.walletsManager = walletsManager;
this.openOfferManager = openOfferManager;
this.storageDir = storageDir;
type = Type.Attention;
width = 900;
@ -277,7 +281,6 @@ public class WalletPasswordWindow extends Overlay<WalletPasswordWindow> {
gridPane.getChildren().add(headLine2Label);
seedWordsTextArea = addTextArea(gridPane, ++rowIndex, Res.get("seed.enterSeedWords"), 5);
;
seedWordsTextArea.setPrefHeight(60);
Tuple2<Label, DatePicker> labelDatePickerTuple2 = addTopLabelDatePicker(gridPane, ++rowIndex,
@ -356,6 +359,6 @@ public class WalletPasswordWindow extends Overlay<WalletPasswordWindow> {
//TODO Is ZoneOffset correct?
long date = value != null ? value.atStartOfDay().toEpochSecond(ZoneOffset.UTC) : 0;
DeterministicSeed seed = new DeterministicSeed(Splitter.on(" ").splitToList(seedWordsTextArea.getText()), null, "", date);
GUIUtil.restoreSeedWords(seed, walletsManager, storageDir);
SharedPresentation.restoreSeedWords(walletsManager, openOfferManager, seed, storageDir);
}
}

View file

@ -32,7 +32,6 @@ import bisq.desktop.util.validation.RegexValidator;
import bisq.core.account.witness.AccountAgeWitness;
import bisq.core.account.witness.AccountAgeWitnessService;
import bisq.core.btc.setup.WalletsSetup;
import bisq.core.btc.wallet.WalletsManager;
import bisq.core.locale.Country;
import bisq.core.locale.CountryUtil;
import bisq.core.locale.CurrencyUtil;
@ -63,7 +62,6 @@ import bisq.common.config.Config;
import bisq.common.proto.persistable.PersistableList;
import bisq.common.proto.persistable.PersistenceProtoResolver;
import bisq.common.storage.CorruptedDatabaseFilesHandler;
import bisq.common.storage.FileUtil;
import bisq.common.storage.Storage;
import bisq.common.util.MathUtils;
import bisq.common.util.Tuple2;
@ -75,7 +73,6 @@ import org.bitcoinj.core.Coin;
import org.bitcoinj.core.TransactionConfidence;
import org.bitcoinj.uri.BitcoinURI;
import org.bitcoinj.utils.Fiat;
import org.bitcoinj.wallet.DeterministicSeed;
import com.googlecode.jcsv.CSVStrategy;
import com.googlecode.jcsv.writer.CSVEntryConverter;
@ -803,26 +800,6 @@ public class GUIUtil {
}
}
public static void restoreSeedWords(DeterministicSeed seed, WalletsManager walletsManager, File storageDir) {
try {
FileUtil.renameFile(new File(storageDir, "AddressEntryList"), new File(storageDir, "AddressEntryList_wallet_restore_" + System.currentTimeMillis()));
} catch (Throwable t) {
new Popup().error(Res.get("error.deleteAddressEntryListFailed", t)).show();
}
walletsManager.restoreSeedWords(
seed,
() -> UserThread.execute(() -> {
log.info("Wallets restored with seed words");
new Popup().feedback(Res.get("seed.restore.success")).hideCloseButton().show();
BisqApp.getShutDownHandler().run();
}),
throwable -> UserThread.execute(() -> {
log.error(throwable.toString());
new Popup().error(Res.get("seed.restore.error", Res.get("shared.errorMessageInline", throwable)))
.show();
}));
}
public static void showSelectableTextModal(String title, String text) {
TextArea textArea = new BisqTextArea();
textArea.setText(text);

View file

@ -7,7 +7,7 @@ Bisq uses Git LFS to track certain large binary files. Follow the instructions a
$ git lfs version
git-lfs/2.10.0 (GitHub; darwin amd64; go 1.13.6)
## Clone
@ -17,8 +17,9 @@ Bisq uses Git LFS to track certain large binary files. Follow the instructions a
## Build
You do _not_ need to install Gradle to complete the following command. The `gradlew` shell script will install it for you if necessary.
You do _not_ need to install Gradle to complete the following command. The `gradlew` shell script will install it for you if necessary. Pull the lfs data first.
git lfs pull
./gradlew build
If on Windows run `gradlew.bat build` instead.

View file

@ -19,14 +19,14 @@ dependencyVerification {
'com.fasterxml.jackson.core:jackson-annotations:2566b3a6662afa3c6af4f5b25006cb46be2efc68f1b5116291d6998a8cdf7ed3',
'com.fasterxml.jackson.core:jackson-core:39a74610521d7fb9eb3f437bb8739bbf47f6435be12d17bf954c731a0c6352bb',
'com.fasterxml.jackson.core:jackson-databind:fcf3c2b0c332f5f54604f7e27fa7ee502378a2cc5df6a944bbfae391872c32ff',
'com.github.JesusMcCloud.netlayer:tor.external:fb080d812aa88f5fb1ec74273ae24ae13980b7902c75e0ffc3ac462b4cf6b242',
'com.github.JesusMcCloud.netlayer:tor.native:1227275377ac73d9d25dec1d05bc2f7a2ae3b1f1afde77f39049637dcb8fc407',
'com.github.JesusMcCloud.netlayer:tor:6ff47a97dc0dc97079d83c1f2c66ebcc956f25dd3bacfa6e24206cb2c742f52b',
'com.github.JesusMcCloud.tor-binary:tor-binary-geoip:13a3c6e02f37f9def172ce1d231ea1a45aa1ddbc36b1d9e81b7a91632bc474ed',
'com.github.JesusMcCloud.tor-binary:tor-binary-linux32:2022da3a398527d366bd954bea92069cf209218c649aeb3342f85f7434aa0786',
'com.github.JesusMcCloud.tor-binary:tor-binary-linux64:972d5a946964176fe849eb872baa64a591d9e6fe0467c62ae71986b946101836',
'com.github.JesusMcCloud.tor-binary:tor-binary-macos:95a4d093e2d48099623015e70add1bd7dcc3e392f9e87ed4d691286c868516c9',
'com.github.JesusMcCloud.tor-binary:tor-binary-windows:43a07290443a1c55211eaa6001681839f9cb7453574089a939d0da3dd20e2cf2',
'com.github.JesusMcCloud.netlayer:tor.external:1facb63d5f4107a1d4a176a03c149b60eed19a76371b58d1b6aa62ad5cacde3f',
'com.github.JesusMcCloud.netlayer:tor.native:88267f1a3b2d1433a77a2fd9dc3a8f1d5cd28fbbefa2e078d83b176cbe91d477',
'com.github.JesusMcCloud.netlayer:tor:0eaae7bcea11ef25e4f041e77c237ebc96f120462e64a7818073a88dadf9b805',
'com.github.JesusMcCloud.tor-binary:tor-binary-geoip:08a461608990aed2c272121dc835a38687017d3bb172bc181ea0793df7ebb5aa',
'com.github.JesusMcCloud.tor-binary:tor-binary-linux32:81fb1e80d191ed9d0a509e514311d21d59c87c6edee6a490975061a18390b10c',
'com.github.JesusMcCloud.tor-binary:tor-binary-linux64:7b90b5e8f1cc32d86ed8e2e5b1f57d774bc27bebc679ececdbf1ff0699bd1f4c',
'com.github.JesusMcCloud.tor-binary:tor-binary-macos:db5aef1082fdd8afb4f7f21cf0956f46a76e93aad75bed6ed149dd3e3767c0a7',
'com.github.JesusMcCloud.tor-binary:tor-binary-windows:1bb83786a71449d8edb152e40ce5efc129eaca6a0900f4912d7555b6df2f52a2',
'com.github.JesusMcCloud:jtorctl:389d61b1b5a85eb2f23c582c3913ede49f80c9f2b553e4762382c836270e57e5',
'com.github.bisq-network.bitcoinj:bitcoinj-core:f979c2187e61ee3b08dd4cbfc49a149734cff64c045d29ed112f2e12f34068a3',
'com.github.ravn:jsocks:3c71600af027b2b6d4244e4ad14d98ff2352a379410daebefff5d8cd48d742a4',

View file

@ -48,6 +48,8 @@ import bisq.common.proto.network.NetworkEnvelope;
import bisq.common.proto.network.NetworkProtoResolver;
import bisq.common.util.Utilities;
import com.google.protobuf.InvalidProtocolBufferException;
import javax.inject.Inject;
import com.google.common.util.concurrent.MoreExecutors;
@ -283,12 +285,20 @@ public class Connection implements HasCapabilities, Runnable, MessageListener {
bundleSender.schedule(() -> {
if (!stopped) {
synchronized (lock) {
BundleOfEnvelopes current = queueOfBundles.poll();
if (current != null && !stopped) {
if (current.getEnvelopes().size() == 1) {
protoOutputStream.writeEnvelope(current.getEnvelopes().get(0));
} else {
protoOutputStream.writeEnvelope(current);
BundleOfEnvelopes bundle = queueOfBundles.poll();
if (bundle != null && !stopped) {
NetworkEnvelope envelope = bundle.getEnvelopes().size() == 1 ?
bundle.getEnvelopes().get(0) :
bundle;
try {
protoOutputStream.writeEnvelope(envelope);
} catch (Throwable t) {
log.error("Sending envelope of class {} to address {} " +
"failed due {}",
envelope.getClass().getSimpleName(),
this.getPeersNodeAddressOptional(),
t.toString());
log.error("envelope: {}", envelope);
}
}
}
@ -876,7 +886,7 @@ public class Connection implements HasCapabilities, Runnable, MessageListener {
log.error(e.getMessage());
e.printStackTrace();
reportInvalidRequest(RuleViolation.INVALID_CLASS);
} catch (ProtobufferException | NoClassDefFoundError e) {
} catch (ProtobufferException | NoClassDefFoundError | InvalidProtocolBufferException e) {
log.error(e.getMessage());
e.printStackTrace();
reportInvalidRequest(RuleViolation.INVALID_DATA_TYPE);