From 766b1e2e1e8bf86c9e8df104a3b56807d0a73e40 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Sat, 26 Sep 2020 12:42:17 -0500 Subject: [PATCH] Add check to not add a duplicate address entry with same offer ID and context. In debugging trade protocol and taking same offer I could generate problems where the multisig entry was twice but with diff. keys, so take offer failed. I remember the error log to have seen in the past and I assume this was a rare bug we encountered when users took again the same offer which failed with an uncritical state earlier. --- .../bisq/core/btc/model/AddressEntryList.java | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/bisq/core/btc/model/AddressEntryList.java b/core/src/main/java/bisq/core/btc/model/AddressEntryList.java index 913a8e996a..c25e2e1a8b 100644 --- a/core/src/main/java/bisq/core/btc/model/AddressEntryList.java +++ b/core/src/main/java/bisq/core/btc/model/AddressEntryList.java @@ -108,11 +108,11 @@ public final class AddressEntryList implements UserThreadMappedPersistableEnvelo Set toBeRemoved = new HashSet<>(); entrySet.forEach(addressEntry -> { DeterministicKey keyFromPubHash = (DeterministicKey) wallet.findKeyFromPubKeyHash( - addressEntry.getPubKeyHash(), - Script.ScriptType.P2PKH); + addressEntry.getPubKeyHash(), + Script.ScriptType.P2PKH); if (keyFromPubHash != null) { Address addressFromKey = LegacyAddress.fromKey(Config.baseCurrencyNetworkParameters(), - keyFromPubHash); + keyFromPubHash); // 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); @@ -173,6 +173,18 @@ public final class AddressEntryList implements UserThreadMappedPersistableEnvelo } public void addAddressEntry(AddressEntry addressEntry) { + boolean entryWithSameOfferIdAndContextAlreadyExist = entrySet.stream().anyMatch(e -> { + if (addressEntry.getOfferId() != null) { + return addressEntry.getOfferId().equals(e.getOfferId()) && addressEntry.getContext() == e.getContext(); + } + return false; + }); + if (entryWithSameOfferIdAndContextAlreadyExist) { + log.error("We have an address entry with the same offer ID and context. We do not add the new one. " + + "addressEntry={}, entrySet={}", addressEntry, entrySet); + return; + } + boolean setChangedByAdd = entrySet.add(addressEntry); if (setChangedByAdd) persist(); @@ -181,7 +193,7 @@ public final class AddressEntryList implements UserThreadMappedPersistableEnvelo public void swapToAvailable(AddressEntry addressEntry) { boolean setChangedByRemove = entrySet.remove(addressEntry); boolean setChangedByAdd = entrySet.add(new AddressEntry(addressEntry.getKeyPair(), - AddressEntry.Context.AVAILABLE)); + AddressEntry.Context.AVAILABLE)); if (setChangedByRemove || setChangedByAdd) { persist(); } @@ -215,7 +227,7 @@ public final class AddressEntryList implements UserThreadMappedPersistableEnvelo .filter(Objects::nonNull) .filter(this::isAddressNotInEntries) .map(address -> (DeterministicKey) wallet.findKeyFromPubKeyHash(address.getHash(), - Script.ScriptType.P2PKH)) + Script.ScriptType.P2PKH)) .filter(Objects::nonNull) .map(deterministicKey -> new AddressEntry(deterministicKey, AddressEntry.Context.AVAILABLE)) .forEach(this::addAddressEntry);