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
This commit is contained in:
sqrrm 2020-05-31 15:08:00 +02:00
parent 7bd5969dcf
commit 0dc769bf9b
No known key found for this signature in database
GPG key ID: 45235F9EF87089EC
5 changed files with 51 additions and 24 deletions

View file

@ -50,12 +50,15 @@ import java.time.temporal.ChronoUnit;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Comparator;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.Stack; import java.util.Stack;
import java.util.stream.Collector;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import lombok.Getter; import lombok.Getter;
@ -125,6 +128,8 @@ public class SignedWitnessService {
} }
}); });
} }
// TODO: Enable cleaning of signed witness list when necessary
// cleanSignedWitnesses();
} }
private void onBootstrapComplete() { private void onBootstrapComplete() {
@ -441,7 +446,6 @@ public class SignedWitnessService {
@VisibleForTesting @VisibleForTesting
void addToMap(SignedWitness signedWitness) { void addToMap(SignedWitness signedWitness) {
// TODO: Perhaps filter out all but one signedwitness per accountagewitness
signedWitnessMap.putIfAbsent(signedWitness.getHashAsByteArray(), signedWitness); signedWitnessMap.putIfAbsent(signedWitness.getHashAsByteArray(), signedWitness);
} }
@ -456,4 +460,19 @@ public class SignedWitnessService {
private void doRepublishAllSignedWitnesses() { private void doRepublishAllSignedWitnesses() {
signedWitnessMap.forEach((e, signedWitness) -> p2PService.addPersistableNetworkPayload(signedWitness, true)); 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());
}
}));
}
} }

View file

@ -17,7 +17,6 @@
package bisq.core.account.witness; package bisq.core.account.witness;
import bisq.core.account.sign.SignedWitness;
import bisq.core.account.sign.SignedWitnessService; import bisq.core.account.sign.SignedWitnessService;
import bisq.core.filter.FilterManager; import bisq.core.filter.FilterManager;
import bisq.core.filter.PaymentAccountFilter; import bisq.core.filter.PaymentAccountFilter;
@ -67,14 +66,12 @@ import java.util.Arrays;
import java.util.Date; import java.util.Date;
import java.util.GregorianCalendar; import java.util.GregorianCalendar;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import java.util.Random; import java.util.Random;
import java.util.Set; import java.util.Set;
import java.util.Stack;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
@ -82,8 +79,6 @@ import java.util.stream.Stream;
import lombok.Getter; import lombok.Getter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import javax.annotation.Nullable;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
@Slf4j @Slf4j
@ -248,7 +243,7 @@ public class AccountAgeWitnessService {
} }
Optional<AccountAgeWitness> findWitness(PaymentAccountPayload paymentAccountPayload, Optional<AccountAgeWitness> findWitness(PaymentAccountPayload paymentAccountPayload,
PubKeyRing pubKeyRing) { PubKeyRing pubKeyRing) {
byte[] accountInputDataWithSalt = getAccountInputDataWithSalt(paymentAccountPayload); byte[] accountInputDataWithSalt = getAccountInputDataWithSalt(paymentAccountPayload);
byte[] hash = Hash.getSha256Ripemd160hash(Utilities.concatenateByteArrays(accountInputDataWithSalt, byte[] hash = Hash.getSha256Ripemd160hash(Utilities.concatenateByteArrays(accountInputDataWithSalt,
pubKeyRing.getSignaturePubKeyBytes())); pubKeyRing.getSignaturePubKeyBytes()));
@ -640,17 +635,24 @@ public class AccountAgeWitnessService {
signedWitnessService.signAccountAgeWitness(tradeAmount, accountAgeWitness, key, peersPubKey); signedWitnessService.signAccountAgeWitness(tradeAmount, accountAgeWitness, key, peersPubKey);
} }
public String arbitratorSignAccountAgeWitness(AccountAgeWitness accountAgeWitness, public String arbitratorSignOrphanWitness(AccountAgeWitness accountAgeWitness,
ECKey key, ECKey key,
long time) { long time) {
return signedWitnessService.signAccountAgeWitness(accountAgeWitness, key, null, 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, public void arbitratorSignAccountAgeWitness(AccountAgeWitness accountAgeWitness,
ECKey key, ECKey key,
byte[] tradersPubKey, byte[] tradersPubKey,
long time) { long time) {
return signedWitnessService.signAccountAgeWitness(accountAgeWitness, key, tradersPubKey, time); signedWitnessService.signAccountAgeWitness(accountAgeWitness, key, tradersPubKey, time);
} }
public void traderSignPeersAccountAgeWitness(Trade trade) { public void traderSignPeersAccountAgeWitness(Trade trade) {

View file

@ -55,18 +55,23 @@ public class AccountAgeWitnessUtils {
// Log tree of signed witnesses // Log tree of signed witnesses
public void logSignedWitnesses() { public void logSignedWitnesses() {
var orphanSigners = signedWitnessService.getRootSignedWitnessSet(false); var orphanSigners = signedWitnessService.getRootSignedWitnessSet(true);
log.info("Orphaned signed account age witnesses:"); log.info("Orphaned signed account age witnesses:");
orphanSigners.forEach(w -> { orphanSigners.forEach(w -> {
log.warn("{}: {}", w.getVerificationMethod().toString(), log.info("{}: Signer PKH: {} Owner PKH: {} time: {}", w.getVerificationMethod().toString(),
Utilities.bytesAsHexString(Hash.getRipemd160hash(w.getSignerPubKey()))); Utilities.bytesAsHexString(Hash.getRipemd160hash(w.getSignerPubKey())).substring(0,7),
Utilities.bytesAsHexString(Hash.getRipemd160hash(w.getWitnessOwnerPubKey())).substring(0,7),
w.getDate());
logChild(w, " ", new Stack<>()); logChild(w, " ", new Stack<>());
}); });
} }
private void logChild(SignedWitness sigWit, String initString, Stack<P2PDataStorage.ByteArray> excluded) { private void logChild(SignedWitness sigWit, String initString, Stack<P2PDataStorage.ByteArray> excluded) {
var allSig = signedWitnessService.getSignedWitnessMap(); 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 -> { allSig.values().forEach(w -> {
if (!excluded.contains(new P2PDataStorage.ByteArray(w.getWitnessOwnerPubKey())) && if (!excluded.contains(new P2PDataStorage.ByteArray(w.getWitnessOwnerPubKey())) &&
Arrays.equals(w.getSignerPubKey(), sigWit.getWitnessOwnerPubKey())) { Arrays.equals(w.getSignerPubKey(), sigWit.getWitnessOwnerPubKey())) {

View file

@ -324,11 +324,11 @@ public class AccountAgeWitnessServiceTest {
assertFalse(signedWitnessService.isSignedAccountAgeWitness(aew2)); assertFalse(signedWitnessService.isSignedAccountAgeWitness(aew2));
// Sign dummy AccountAgeWitness using signer key from SW_1 // 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 // TODO: move this to accountagewitnessservice
@SuppressWarnings("OptionalGetWithoutIsPresent") @SuppressWarnings("OptionalGetWithoutIsPresent")
var orphanedSignedWitness = signedWitnessService.getRootSignedWitnessSet().stream().findAny().get(); var orphanedSignedWitness = signedWitnessService.getRootSignedWitnessSet(false).stream().findAny().get();
var dummyAccountAgeWitnessHash = Hash.getRipemd160hash(orphanedSignedWitness.getSignerPubKey()); var dummyAccountAgeWitnessHash = Hash.getRipemd160hash(orphanedSignedWitness.getSignerPubKey());
var dummyAEW = new AccountAgeWitness(dummyAccountAgeWitnessHash, var dummyAEW = new AccountAgeWitness(dummyAccountAgeWitnessHash,
orphanedSignedWitness.getDate() - orphanedSignedWitness.getDate() -

View file

@ -94,7 +94,7 @@ public class SignSpecificWitnessWindow extends Overlay<SignSpecificWitnessWindow
searchAutoComplete = new JFXAutoCompletePopup<>(); searchAutoComplete = new JFXAutoCompletePopup<>();
searchAutoComplete.setPrefWidth(400); searchAutoComplete.setPrefWidth(400);
searchAutoComplete.getSuggestions().addAll(accountAgeWitnessService.getAccountAgeWitnessMap().values()); searchAutoComplete.getSuggestions().addAll(accountAgeWitnessService.getOrphanSignedWitnesses());
searchAutoComplete.setSuggestionsCellFactory(param -> new ListCell<>() { searchAutoComplete.setSuggestionsCellFactory(param -> new ListCell<>() {
@Override @Override
protected void updateItem(AccountAgeWitness item, boolean empty) { protected void updateItem(AccountAgeWitness item, boolean empty) {
@ -160,7 +160,8 @@ public class SignSpecificWitnessWindow extends Overlay<SignSpecificWitnessWindow
var arbitratorPubKeyAsHex = Utils.HEX.encode(arbitratorKey.getPubKey()); var arbitratorPubKeyAsHex = Utils.HEX.encode(arbitratorKey.getPubKey());
var isKeyValid = arbitratorManager.isPublicKeyInList(arbitratorPubKeyAsHex); var isKeyValid = arbitratorManager.isPublicKeyInList(arbitratorPubKeyAsHex);
if (isKeyValid) { if (isKeyValid) {
var result = accountAgeWitnessService.arbitratorSignAccountAgeWitness(selectedWitness, arbitratorKey, var result = accountAgeWitnessService.arbitratorSignOrphanWitness(selectedWitness,
arbitratorKey,
datePicker.getValue().atStartOfDay().toEpochSecond(ZoneOffset.UTC) * 1000); datePicker.getValue().atStartOfDay().toEpochSecond(ZoneOffset.UTC) * 1000);
if (result.isEmpty()) { if (result.isEmpty()) {
addSuccessContent(); addSuccessContent();