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.
This commit is contained in:
chimp1984 2020-09-26 12:42:17 -05:00
parent 2bb4bff41d
commit 766b1e2e1e
No known key found for this signature in database
GPG key ID: 9801B4EC591F90E3

View file

@ -108,11 +108,11 @@ public final class AddressEntryList implements UserThreadMappedPersistableEnvelo
Set<AddressEntry> toBeRemoved = new HashSet<>(); Set<AddressEntry> toBeRemoved = new HashSet<>();
entrySet.forEach(addressEntry -> { entrySet.forEach(addressEntry -> {
DeterministicKey keyFromPubHash = (DeterministicKey) wallet.findKeyFromPubKeyHash( DeterministicKey keyFromPubHash = (DeterministicKey) wallet.findKeyFromPubKeyHash(
addressEntry.getPubKeyHash(), addressEntry.getPubKeyHash(),
Script.ScriptType.P2PKH); Script.ScriptType.P2PKH);
if (keyFromPubHash != null) { if (keyFromPubHash != null) {
Address addressFromKey = LegacyAddress.fromKey(Config.baseCurrencyNetworkParameters(), 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 // 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())) { if (addressEntry.getAddress() == null || addressFromKey.equals(addressEntry.getAddress())) {
addressEntry.setDeterministicKey(keyFromPubHash); addressEntry.setDeterministicKey(keyFromPubHash);
@ -173,6 +173,18 @@ public final class AddressEntryList implements UserThreadMappedPersistableEnvelo
} }
public void addAddressEntry(AddressEntry addressEntry) { 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); boolean setChangedByAdd = entrySet.add(addressEntry);
if (setChangedByAdd) if (setChangedByAdd)
persist(); persist();
@ -181,7 +193,7 @@ public final class AddressEntryList implements UserThreadMappedPersistableEnvelo
public void swapToAvailable(AddressEntry addressEntry) { public void swapToAvailable(AddressEntry addressEntry) {
boolean setChangedByRemove = entrySet.remove(addressEntry); boolean setChangedByRemove = entrySet.remove(addressEntry);
boolean setChangedByAdd = entrySet.add(new AddressEntry(addressEntry.getKeyPair(), boolean setChangedByAdd = entrySet.add(new AddressEntry(addressEntry.getKeyPair(),
AddressEntry.Context.AVAILABLE)); AddressEntry.Context.AVAILABLE));
if (setChangedByRemove || setChangedByAdd) { if (setChangedByRemove || setChangedByAdd) {
persist(); persist();
} }
@ -215,7 +227,7 @@ public final class AddressEntryList implements UserThreadMappedPersistableEnvelo
.filter(Objects::nonNull) .filter(Objects::nonNull)
.filter(this::isAddressNotInEntries) .filter(this::isAddressNotInEntries)
.map(address -> (DeterministicKey) wallet.findKeyFromPubKeyHash(address.getHash(), .map(address -> (DeterministicKey) wallet.findKeyFromPubKeyHash(address.getHash(),
Script.ScriptType.P2PKH)) Script.ScriptType.P2PKH))
.filter(Objects::nonNull) .filter(Objects::nonNull)
.map(deterministicKey -> new AddressEntry(deterministicKey, AddressEntry.Context.AVAILABLE)) .map(deterministicKey -> new AddressEntry(deterministicKey, AddressEntry.Context.AVAILABLE))
.forEach(this::addAddressEntry); .forEach(this::addAddressEntry);