Arbitrator sign accountAgeWitnesses

Automatically filter to only sign accounts that
- have chargeback risk
- bought BTC
- was winner in dispute
This commit is contained in:
sqrrm 2019-07-20 17:51:54 +02:00
parent aed1e8027e
commit 61895102fd
No known key found for this signature in database
GPG key ID: 45235F9EF87089EC
7 changed files with 130 additions and 2 deletions

View file

@ -20,7 +20,12 @@ package bisq.core.account.sign;
import bisq.core.account.witness.AccountAgeWitness;
import bisq.core.account.witness.AccountAgeWitnessService;
import bisq.core.arbitration.ArbitratorManager;
import bisq.core.arbitration.BuyerDataItem;
import bisq.core.arbitration.Dispute;
import bisq.core.arbitration.DisputeManager;
import bisq.core.arbitration.DisputeResult;
import bisq.core.payment.payload.PaymentAccountPayload;
import bisq.core.payment.payload.PaymentMethod;
import bisq.network.p2p.P2PService;
import bisq.network.p2p.storage.P2PDataStorage;
@ -28,6 +33,7 @@ import bisq.network.p2p.storage.persistence.AppendOnlyDataStoreService;
import bisq.common.crypto.CryptoException;
import bisq.common.crypto.KeyRing;
import bisq.common.crypto.PubKeyRing;
import bisq.common.crypto.Sig;
import bisq.common.util.Utilities;
@ -50,12 +56,17 @@ import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.Stack;
import java.util.stream.Collectors;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.Nullable;
@Slf4j
public class SignedWitnessService {
public static final long CHARGEBACK_SAFETY_DAYS = 30;
@ -64,6 +75,8 @@ public class SignedWitnessService {
private final P2PService p2PService;
private final AccountAgeWitnessService accountAgeWitnessService;
private final ArbitratorManager arbitratorManager;
private final DisputeManager disputeManager;
private final Map<P2PDataStorage.ByteArray, SignedWitness> signedWitnessMap = new HashMap<>();
@ -77,11 +90,13 @@ public class SignedWitnessService {
AccountAgeWitnessService accountAgeWitnessService,
ArbitratorManager arbitratorManager,
SignedWitnessStorageService signedWitnessStorageService,
AppendOnlyDataStoreService appendOnlyDataStoreService) {
AppendOnlyDataStoreService appendOnlyDataStoreService,
DisputeManager disputeManager) {
this.keyRing = keyRing;
this.p2PService = p2PService;
this.accountAgeWitnessService = accountAgeWitnessService;
this.arbitratorManager = arbitratorManager;
this.disputeManager = disputeManager;
// We need to add that early (before onAllServicesInitialized) as it will be used at startup.
appendOnlyDataStoreService.addService(signedWitnessStorageService);
@ -305,4 +320,38 @@ public class SignedWitnessService {
}
}
// Arbitrator signing
public List<BuyerDataItem> getBuyerPaymentAccounts(long safeDate) {
return disputeManager.getDisputesAsObservableList().stream()
.filter(this::hasChargebackRisk)
.filter(this::isBuyerWinner)
.map(this::getBuyerData)
.filter(Objects::nonNull)
.filter(buyerDataItem -> buyerDataItem.getAccountAgeWitness().getDate() < safeDate)
.distinct()
.collect(Collectors.toList());
}
private boolean hasChargebackRisk(Dispute dispute) {
return PaymentMethod.hasChargebackRisk(dispute.getContract().getPaymentMethodId());
}
private boolean isBuyerWinner(Dispute dispute) {
return dispute.getDisputeResultProperty().get().getWinner() == DisputeResult.Winner.BUYER;
}
@Nullable
private BuyerDataItem getBuyerData(Dispute dispute) {
PubKeyRing buyerPubKeyRing = dispute.getContract().getBuyerPubKeyRing();
PaymentAccountPayload buyerPaymentAccountPaload = dispute.getContract().getBuyerPaymentAccountPayload();
Optional<AccountAgeWitness> optionalWitness = accountAgeWitnessService
.findWitness(buyerPaymentAccountPaload, buyerPubKeyRing);
return optionalWitness.map(witness -> new BuyerDataItem(
buyerPaymentAccountPaload,
witness,
dispute.getContract().getTradeAmount(),
dispute.getContract().getSellerPubKeyRing().getSignaturePubKey()))
.orElse(null);
}
}

View file

@ -17,6 +17,7 @@
package bisq.core.app;
import bisq.core.account.sign.SignedWitnessService;
import bisq.core.account.witness.AccountAgeWitnessService;
import bisq.core.alert.Alert;
import bisq.core.alert.AlertManager;
@ -143,6 +144,7 @@ public class BisqSetup {
private final KeyRing keyRing;
private final BisqEnvironment bisqEnvironment;
private final AccountAgeWitnessService accountAgeWitnessService;
private final SignedWitnessService signedWitnessService;
private final MobileNotificationService mobileNotificationService;
private final MyOfferTakenEvents myOfferTakenEvents;
private final TradeEvents tradeEvents;
@ -221,6 +223,7 @@ public class BisqSetup {
KeyRing keyRing,
BisqEnvironment bisqEnvironment,
AccountAgeWitnessService accountAgeWitnessService,
SignedWitnessService signedWitnessService,
MobileNotificationService mobileNotificationService,
MyOfferTakenEvents myOfferTakenEvents,
TradeEvents tradeEvents,
@ -261,6 +264,7 @@ public class BisqSetup {
this.keyRing = keyRing;
this.bisqEnvironment = bisqEnvironment;
this.accountAgeWitnessService = accountAgeWitnessService;
this.signedWitnessService = signedWitnessService;
this.mobileNotificationService = mobileNotificationService;
this.myOfferTakenEvents = myOfferTakenEvents;
this.tradeEvents = tradeEvents;
@ -647,6 +651,7 @@ public class BisqSetup {
assetService.onAllServicesInitialized();
accountAgeWitnessService.onAllServicesInitialized();
signedWitnessService.onAllServicesInitialized();
priceFeedService.setCurrencyCodeOnInit();

View file

@ -17,6 +17,7 @@
package bisq.core.app.misc;
import bisq.core.account.sign.SignedWitnessService;
import bisq.core.account.witness.AccountAgeWitnessService;
import bisq.core.app.SetupUtils;
import bisq.core.app.TorSetup;
@ -46,6 +47,7 @@ import lombok.extern.slf4j.Slf4j;
public class AppSetupWithP2P extends AppSetup {
protected final P2PService p2PService;
protected final AccountAgeWitnessService accountAgeWitnessService;
private final SignedWitnessService signedWitnessService;
protected final FilterManager filterManager;
private final TorSetup torSetup;
protected BooleanProperty p2pNetWorkReady;
@ -58,12 +60,14 @@ public class AppSetupWithP2P extends AppSetup {
P2PService p2PService,
TradeStatisticsManager tradeStatisticsManager,
AccountAgeWitnessService accountAgeWitnessService,
SignedWitnessService signedWitnessService,
FilterManager filterManager,
TorSetup torSetup) {
super(encryptionService, keyRing);
this.p2PService = p2PService;
this.tradeStatisticsManager = tradeStatisticsManager;
this.accountAgeWitnessService = accountAgeWitnessService;
this.signedWitnessService = signedWitnessService;
this.filterManager = filterManager;
this.torSetup = torSetup;
this.persistedDataHosts = new ArrayList<>();
@ -184,6 +188,7 @@ public class AppSetupWithP2P extends AppSetup {
tradeStatisticsManager.onAllServicesInitialized();
accountAgeWitnessService.onAllServicesInitialized();
signedWitnessService.onAllServicesInitialized();
filterManager.onAllServicesInitialized();
}

View file

@ -17,6 +17,7 @@
package bisq.core.app.misc;
import bisq.core.account.sign.SignedWitnessService;
import bisq.core.account.witness.AccountAgeWitnessService;
import bisq.core.app.TorSetup;
import bisq.core.dao.DaoOptionKeys;
@ -50,6 +51,7 @@ public class AppSetupWithP2PAndDAO extends AppSetupWithP2P {
P2PService p2PService,
TradeStatisticsManager tradeStatisticsManager,
AccountAgeWitnessService accountAgeWitnessService,
SignedWitnessService signedWitnessService,
FilterManager filterManager,
DaoSetup daoSetup,
MyVoteListService myVoteListService,
@ -65,6 +67,7 @@ public class AppSetupWithP2PAndDAO extends AppSetupWithP2P {
p2PService,
tradeStatisticsManager,
accountAgeWitnessService,
signedWitnessService,
filterManager,
torSetup);

View file

@ -0,0 +1,60 @@
/*
* 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.core.arbitration;
import bisq.core.account.witness.AccountAgeWitness;
import bisq.core.payment.payload.PaymentAccountPayload;
import org.bitcoinj.core.Coin;
import java.security.PublicKey;
import java.util.Objects;
import lombok.Getter;
@Getter
public class BuyerDataItem {
private final PaymentAccountPayload paymentAccountPayload;
private final AccountAgeWitness accountAgeWitness;
private final Coin tradeAmount;
private final PublicKey sellerPubKey;
public BuyerDataItem(PaymentAccountPayload paymentAccountPayload,
AccountAgeWitness accountAgeWitness,
Coin tradeAmount,
PublicKey sellerPubKey) {
this.paymentAccountPayload = paymentAccountPayload;
this.accountAgeWitness = accountAgeWitness;
this.tradeAmount = tradeAmount;
this.sellerPubKey = sellerPubKey;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof BuyerDataItem)) return false;
// Only distinguish data by AccountAgeWitness. Other details are irrelevant
return accountAgeWitness.equals(((BuyerDataItem) o).accountAgeWitness);
}
@Override
public int hashCode() {
return Objects.hash(accountAgeWitness);
}
}

View file

@ -321,6 +321,10 @@ public final class PaymentMethod implements PersistablePayload, Comparable {
return false;
String id = paymentMethod.getId();
return hasChargebackRisk(id);
}
public static boolean hasChargebackRisk(String id) {
return id.equals(PaymentMethod.SEPA_ID) ||
id.equals(PaymentMethod.SEPA_INSTANT_ID) ||
id.equals(PaymentMethod.INTERAC_E_TRANSFER_ID) ||

View file

@ -20,6 +20,7 @@ package bisq.core.account.sign;
import bisq.core.account.witness.AccountAgeWitness;
import bisq.core.arbitration.ArbitratorManager;
import bisq.core.arbitration.DisputeManager;
import bisq.network.p2p.storage.persistence.AppendOnlyDataStoreService;
@ -74,8 +75,9 @@ public class SignedWitnessServiceTest {
public void setup() throws Exception {
AppendOnlyDataStoreService appendOnlyDataStoreService = mock(AppendOnlyDataStoreService.class);
ArbitratorManager arbitratorManager = mock(ArbitratorManager.class);
DisputeManager disputeManager = mock(DisputeManager.class);
when(arbitratorManager.isPublicKeyInList(any())).thenReturn(true);
signedWitnessService = new SignedWitnessService(null, null, null, arbitratorManager, null, appendOnlyDataStoreService);
signedWitnessService = new SignedWitnessService(null, null, null, arbitratorManager, null, appendOnlyDataStoreService, disputeManager);
account1DataHash = org.bitcoinj.core.Utils.sha256hash160(new byte[]{1});
account2DataHash = org.bitcoinj.core.Utils.sha256hash160(new byte[]{2});
account3DataHash = org.bitcoinj.core.Utils.sha256hash160(new byte[]{3});