mirror of
https://github.com/bisq-network/bisq.git
synced 2025-02-23 15:00:30 +01:00
Arbitrator sign accountAgeWitnesses
Automatically filter to only sign accounts that - have chargeback risk - bought BTC - was winner in dispute
This commit is contained in:
parent
aed1e8027e
commit
61895102fd
7 changed files with 130 additions and 2 deletions
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
60
core/src/main/java/bisq/core/arbitration/BuyerDataItem.java
Normal file
60
core/src/main/java/bisq/core/arbitration/BuyerDataItem.java
Normal 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);
|
||||
}
|
||||
}
|
|
@ -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) ||
|
||||
|
|
|
@ -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});
|
||||
|
|
Loading…
Add table
Reference in a new issue