From 0dc769bf9bc1f995a3e543f7a4e06eff5f436aee Mon Sep 17 00:00:00 2001 From: sqrrm Date: Sun, 31 May 2020 15:08:00 +0200 Subject: [PATCH] Arbitrator signing of AccountAgeWitness with known pubkey Improve debug logging. Lower level from warning to info Fix broken test Add example code to clean out unnecessary SignedWitnesses --- .../account/sign/SignedWitnessService.java | 21 +++++++++++- .../witness/AccountAgeWitnessService.java | 32 ++++++++++--------- .../witness/AccountAgeWitnessUtils.java | 13 +++++--- .../witness/AccountAgeWitnessServiceTest.java | 4 +-- .../windows/SignSpecificWitnessWindow.java | 5 +-- 5 files changed, 51 insertions(+), 24 deletions(-) diff --git a/core/src/main/java/bisq/core/account/sign/SignedWitnessService.java b/core/src/main/java/bisq/core/account/sign/SignedWitnessService.java index 79beae2e58..a2eaf8c1dc 100644 --- a/core/src/main/java/bisq/core/account/sign/SignedWitnessService.java +++ b/core/src/main/java/bisq/core/account/sign/SignedWitnessService.java @@ -50,12 +50,15 @@ import java.time.temporal.ChronoUnit; import java.util.ArrayList; import java.util.Arrays; +import java.util.Comparator; import java.util.Date; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.Stack; +import java.util.stream.Collector; import java.util.stream.Collectors; import lombok.Getter; @@ -125,6 +128,8 @@ public class SignedWitnessService { } }); } + // TODO: Enable cleaning of signed witness list when necessary + // cleanSignedWitnesses(); } private void onBootstrapComplete() { @@ -441,7 +446,6 @@ public class SignedWitnessService { @VisibleForTesting void addToMap(SignedWitness signedWitness) { - // TODO: Perhaps filter out all but one signedwitness per accountagewitness signedWitnessMap.putIfAbsent(signedWitness.getHashAsByteArray(), signedWitness); } @@ -456,4 +460,19 @@ public class SignedWitnessService { private void doRepublishAllSignedWitnesses() { signedWitnessMap.forEach((e, signedWitness) -> p2PService.addPersistableNetworkPayload(signedWitness, true)); } + + // Remove SignedWitnesses that are signed by TRADE that also have an ARBITRATOR signature + // for the same ownerPubKey and AccountAgeWitnessHash + private void cleanSignedWitnesses() { + var orphans = getRootSignedWitnessSet(false); + var signedWitnessesCopy = new HashSet<>(signedWitnessMap.values()); + signedWitnessesCopy.forEach(sw -> orphans.forEach(orphan -> { + if (sw.getVerificationMethod() == SignedWitness.VerificationMethod.ARBITRATOR && + Arrays.equals(sw.getWitnessOwnerPubKey(), orphan.getWitnessOwnerPubKey()) && + Arrays.equals(sw.getAccountAgeWitnessHash(), orphan.getAccountAgeWitnessHash())) { + signedWitnessMap.remove(orphan.getHashAsByteArray()); + log.info("Remove duplicate SignedWitness: {}", orphan.toString()); + } + })); + } } diff --git a/core/src/main/java/bisq/core/account/witness/AccountAgeWitnessService.java b/core/src/main/java/bisq/core/account/witness/AccountAgeWitnessService.java index 46e6e821a8..dde667a373 100644 --- a/core/src/main/java/bisq/core/account/witness/AccountAgeWitnessService.java +++ b/core/src/main/java/bisq/core/account/witness/AccountAgeWitnessService.java @@ -17,7 +17,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; @@ -67,14 +66,12 @@ import java.util.Arrays; import java.util.Date; import java.util.GregorianCalendar; import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.Random; import java.util.Set; -import java.util.Stack; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -82,8 +79,6 @@ import java.util.stream.Stream; import lombok.Getter; import lombok.extern.slf4j.Slf4j; -import javax.annotation.Nullable; - import static com.google.common.base.Preconditions.checkNotNull; @Slf4j @@ -248,7 +243,7 @@ public class AccountAgeWitnessService { } Optional findWitness(PaymentAccountPayload paymentAccountPayload, - PubKeyRing pubKeyRing) { + PubKeyRing pubKeyRing) { byte[] accountInputDataWithSalt = getAccountInputDataWithSalt(paymentAccountPayload); byte[] hash = Hash.getSha256Ripemd160hash(Utilities.concatenateByteArrays(accountInputDataWithSalt, pubKeyRing.getSignaturePubKeyBytes())); @@ -640,17 +635,24 @@ public class AccountAgeWitnessService { signedWitnessService.signAccountAgeWitness(tradeAmount, accountAgeWitness, key, peersPubKey); } - public String arbitratorSignAccountAgeWitness(AccountAgeWitness accountAgeWitness, - ECKey key, - long time) { - return signedWitnessService.signAccountAgeWitness(accountAgeWitness, key, null, time); + public String arbitratorSignOrphanWitness(AccountAgeWitness accountAgeWitness, + ECKey key, + long time) { + // Find AccountAgeWitness as signedwitness + var signedWitness = signedWitnessService.getSignedWitnessMap().values().stream() + .filter(sw -> Arrays.equals(sw.getAccountAgeWitnessHash(), accountAgeWitness.getHash())) + .findAny() + .orElse(null); + checkNotNull(signedWitness); + return signedWitnessService.signAccountAgeWitness(accountAgeWitness, key, signedWitness.getWitnessOwnerPubKey(), + time); } - public String arbitratorSignAccountAgeWitness(AccountAgeWitness accountAgeWitness, - ECKey key, - byte[] tradersPubKey, - long time) { - return signedWitnessService.signAccountAgeWitness(accountAgeWitness, key, tradersPubKey, time); + public void arbitratorSignAccountAgeWitness(AccountAgeWitness accountAgeWitness, + ECKey key, + byte[] tradersPubKey, + long time) { + signedWitnessService.signAccountAgeWitness(accountAgeWitness, key, tradersPubKey, time); } public void traderSignPeersAccountAgeWitness(Trade trade) { diff --git a/core/src/main/java/bisq/core/account/witness/AccountAgeWitnessUtils.java b/core/src/main/java/bisq/core/account/witness/AccountAgeWitnessUtils.java index 5fc14b579e..c156348604 100644 --- a/core/src/main/java/bisq/core/account/witness/AccountAgeWitnessUtils.java +++ b/core/src/main/java/bisq/core/account/witness/AccountAgeWitnessUtils.java @@ -55,18 +55,23 @@ public class AccountAgeWitnessUtils { // Log tree of signed witnesses public void logSignedWitnesses() { - var orphanSigners = signedWitnessService.getRootSignedWitnessSet(false); + var orphanSigners = signedWitnessService.getRootSignedWitnessSet(true); log.info("Orphaned signed account age witnesses:"); orphanSigners.forEach(w -> { - log.warn("{}: {}", w.getVerificationMethod().toString(), - Utilities.bytesAsHexString(Hash.getRipemd160hash(w.getSignerPubKey()))); + log.info("{}: Signer PKH: {} Owner PKH: {} time: {}", w.getVerificationMethod().toString(), + Utilities.bytesAsHexString(Hash.getRipemd160hash(w.getSignerPubKey())).substring(0,7), + Utilities.bytesAsHexString(Hash.getRipemd160hash(w.getWitnessOwnerPubKey())).substring(0,7), + w.getDate()); logChild(w, " ", new Stack<>()); }); } private void logChild(SignedWitness sigWit, String initString, Stack excluded) { var allSig = signedWitnessService.getSignedWitnessMap(); - log.warn("{}{}", initString, Utilities.bytesAsHexString(sigWit.getAccountAgeWitnessHash())); + log.info("{}AEW: {} PKH: {} time: {}", initString, + Utilities.bytesAsHexString(sigWit.getAccountAgeWitnessHash()).substring(0, 7), + Utilities.bytesAsHexString(Hash.getRipemd160hash(sigWit.getWitnessOwnerPubKey())).substring(0, 7), + sigWit.getDate()); allSig.values().forEach(w -> { if (!excluded.contains(new P2PDataStorage.ByteArray(w.getWitnessOwnerPubKey())) && Arrays.equals(w.getSignerPubKey(), sigWit.getWitnessOwnerPubKey())) { diff --git a/core/src/test/java/bisq/core/account/witness/AccountAgeWitnessServiceTest.java b/core/src/test/java/bisq/core/account/witness/AccountAgeWitnessServiceTest.java index c8e1cc6b59..36d52df74d 100644 --- a/core/src/test/java/bisq/core/account/witness/AccountAgeWitnessServiceTest.java +++ b/core/src/test/java/bisq/core/account/witness/AccountAgeWitnessServiceTest.java @@ -324,11 +324,11 @@ public class AccountAgeWitnessServiceTest { assertFalse(signedWitnessService.isSignedAccountAgeWitness(aew2)); // Sign dummy AccountAgeWitness using signer key from SW_1 - assertEquals(signedWitnessService.getRootSignedWitnessSet().size(), 1); + assertEquals(signedWitnessService.getRootSignedWitnessSet(false).size(), 1); // TODO: move this to accountagewitnessservice @SuppressWarnings("OptionalGetWithoutIsPresent") - var orphanedSignedWitness = signedWitnessService.getRootSignedWitnessSet().stream().findAny().get(); + var orphanedSignedWitness = signedWitnessService.getRootSignedWitnessSet(false).stream().findAny().get(); var dummyAccountAgeWitnessHash = Hash.getRipemd160hash(orphanedSignedWitness.getSignerPubKey()); var dummyAEW = new AccountAgeWitness(dummyAccountAgeWitnessHash, orphanedSignedWitness.getDate() - diff --git a/desktop/src/main/java/bisq/desktop/main/overlays/windows/SignSpecificWitnessWindow.java b/desktop/src/main/java/bisq/desktop/main/overlays/windows/SignSpecificWitnessWindow.java index bf1d89a88a..3f8638878e 100644 --- a/desktop/src/main/java/bisq/desktop/main/overlays/windows/SignSpecificWitnessWindow.java +++ b/desktop/src/main/java/bisq/desktop/main/overlays/windows/SignSpecificWitnessWindow.java @@ -94,7 +94,7 @@ public class SignSpecificWitnessWindow extends Overlay(); searchAutoComplete.setPrefWidth(400); - searchAutoComplete.getSuggestions().addAll(accountAgeWitnessService.getAccountAgeWitnessMap().values()); + searchAutoComplete.getSuggestions().addAll(accountAgeWitnessService.getOrphanSignedWitnesses()); searchAutoComplete.setSuggestionsCellFactory(param -> new ListCell<>() { @Override protected void updateItem(AccountAgeWitness item, boolean empty) { @@ -160,7 +160,8 @@ public class SignSpecificWitnessWindow extends Overlay