mirror of
https://github.com/bisq-network/bisq.git
synced 2025-02-23 06:55:08 +01:00
Merge branch 'master_upstream' into Fix-small-P2P-network-issues
# Conflicts: # core/src/main/java/bisq/core/setup/CoreNetworkCapabilities.java
This commit is contained in:
commit
a0e690997a
17 changed files with 271 additions and 28 deletions
|
@ -31,7 +31,7 @@ public enum Capability {
|
|||
PROPOSAL,
|
||||
BLIND_VOTE,
|
||||
ACK_MSG,
|
||||
BSQ_BLOCK,
|
||||
RECEIVE_BSQ_BLOCK,
|
||||
DAO_STATE,
|
||||
BUNDLE_OF_ENVELOPES,
|
||||
SIGNED_ACCOUNT_AGE_WITNESS
|
||||
|
|
|
@ -20,6 +20,11 @@ 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.ChargeBackRisk;
|
||||
import bisq.core.payment.payload.PaymentAccountPayload;
|
||||
|
||||
import bisq.network.p2p.P2PService;
|
||||
|
@ -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,16 @@ 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.extern.slf4j.Slf4j;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@Slf4j
|
||||
public class SignedWitnessService {
|
||||
public static final long CHARGEBACK_SAFETY_DAYS = 30;
|
||||
|
@ -64,6 +74,9 @@ public class SignedWitnessService {
|
|||
private final P2PService p2PService;
|
||||
private final AccountAgeWitnessService accountAgeWitnessService;
|
||||
private final ArbitratorManager arbitratorManager;
|
||||
private final DisputeManager disputeManager;
|
||||
private final ChargeBackRisk chargeBackRisk;
|
||||
|
||||
private final Map<P2PDataStorage.ByteArray, SignedWitness> signedWitnessMap = new HashMap<>();
|
||||
|
||||
|
||||
|
@ -77,11 +90,15 @@ public class SignedWitnessService {
|
|||
AccountAgeWitnessService accountAgeWitnessService,
|
||||
ArbitratorManager arbitratorManager,
|
||||
SignedWitnessStorageService signedWitnessStorageService,
|
||||
AppendOnlyDataStoreService appendOnlyDataStoreService) {
|
||||
AppendOnlyDataStoreService appendOnlyDataStoreService,
|
||||
DisputeManager disputeManager,
|
||||
ChargeBackRisk chargeBackRisk) {
|
||||
this.keyRing = keyRing;
|
||||
this.p2PService = p2PService;
|
||||
this.accountAgeWitnessService = accountAgeWitnessService;
|
||||
this.arbitratorManager = arbitratorManager;
|
||||
this.disputeManager = disputeManager;
|
||||
this.chargeBackRisk = chargeBackRisk;
|
||||
|
||||
// We need to add that early (before onAllServicesInitialized) as it will be used at startup.
|
||||
appendOnlyDataStoreService.addService(signedWitnessStorageService);
|
||||
|
@ -133,25 +150,29 @@ public class SignedWitnessService {
|
|||
public SignedWitness signAccountAgeWitness(Coin tradeAmount, AccountAgeWitness accountAgeWitness, ECKey key, PublicKey peersPubKey) {
|
||||
String accountAgeWitnessHashAsHex = Utilities.encodeToHex(accountAgeWitness.getHash());
|
||||
String signatureBase64 = key.signMessage(accountAgeWitnessHashAsHex);
|
||||
return new SignedWitness(true,
|
||||
SignedWitness signedWitness = new SignedWitness(true,
|
||||
accountAgeWitness.getHash(),
|
||||
signatureBase64.getBytes(Charsets.UTF_8),
|
||||
key.getPubKey(),
|
||||
peersPubKey.getEncoded(),
|
||||
new Date().getTime(),
|
||||
tradeAmount.value);
|
||||
publishSignedWitness(signedWitness);
|
||||
return signedWitness;
|
||||
}
|
||||
|
||||
// Any peer can sign with DSA key
|
||||
public SignedWitness signAccountAgeWitness(Coin tradeAmount, AccountAgeWitness accountAgeWitness, PublicKey peersPubKey) throws CryptoException {
|
||||
byte[] signature = Sig.sign(keyRing.getSignatureKeyPair().getPrivate(), accountAgeWitness.getHash());
|
||||
return new SignedWitness(false,
|
||||
SignedWitness signedWitness = new SignedWitness(false,
|
||||
accountAgeWitness.getHash(),
|
||||
signature,
|
||||
keyRing.getSignatureKeyPair().getPublic().getEncoded(),
|
||||
peersPubKey.getEncoded(),
|
||||
new Date().getTime(),
|
||||
tradeAmount.value);
|
||||
publishSignedWitness(signedWitness);
|
||||
return signedWitness;
|
||||
}
|
||||
|
||||
public boolean verifySignature(SignedWitness signedWitness) {
|
||||
|
@ -286,7 +307,6 @@ public class SignedWitnessService {
|
|||
return signedWitnessDateMillis <= childSignedWitnessDateMinusChargebackPeriodMillis;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Private
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -295,4 +315,45 @@ public class SignedWitnessService {
|
|||
void addToMap(SignedWitness signedWitness) {
|
||||
signedWitnessMap.putIfAbsent(signedWitness.getHashAsByteArray(), signedWitness);
|
||||
}
|
||||
|
||||
private void publishSignedWitness(SignedWitness signedWitness) {
|
||||
if (!signedWitnessMap.containsKey(signedWitness.getHashAsByteArray())) {
|
||||
p2PService.addPersistableNetworkPayload(signedWitness, false);
|
||||
}
|
||||
}
|
||||
|
||||
// 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 chargeBackRisk.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);
|
||||
|
||||
|
|
48
core/src/main/java/bisq/core/arbitration/BuyerDataItem.java
Normal file
48
core/src/main/java/bisq/core/arbitration/BuyerDataItem.java
Normal file
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* 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 lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
|
||||
public class BuyerDataItem {
|
||||
private final PaymentAccountPayload paymentAccountPayload;
|
||||
@EqualsAndHashCode.Include
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -64,6 +64,6 @@ public final class NewBlockBroadcastMessage extends BroadcastMessage implements
|
|||
|
||||
@Override
|
||||
public Capabilities getRequiredCapabilities() {
|
||||
return new Capabilities(Capability.BSQ_BLOCK);
|
||||
return new Capabilities(Capability.RECEIVE_BSQ_BLOCK);
|
||||
}
|
||||
}
|
||||
|
|
29
core/src/main/java/bisq/core/payment/ChargeBackRisk.java
Normal file
29
core/src/main/java/bisq/core/payment/ChargeBackRisk.java
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* 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.payment;
|
||||
|
||||
import bisq.core.payment.payload.PaymentMethod;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
@Singleton
|
||||
public class ChargeBackRisk {
|
||||
public boolean hasChargebackRisk(String id) {
|
||||
return PaymentMethod.hasChargebackRisk(id);
|
||||
}
|
||||
}
|
|
@ -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) ||
|
||||
|
|
|
@ -40,7 +40,6 @@ public class CoreNetworkCapabilities {
|
|||
Capabilities.app.addAll(
|
||||
Capability.PROPOSAL,
|
||||
Capability.BLIND_VOTE,
|
||||
Capability.BSQ_BLOCK,
|
||||
Capability.DAO_STATE
|
||||
);
|
||||
|
||||
|
@ -56,6 +55,10 @@ public class CoreNetworkCapabilities {
|
|||
if (isFullDaoNode != null && !isFullDaoNode.isEmpty() && isFullDaoNode.toLowerCase().equals("true")) {
|
||||
log.info("Set Capability.DAO_FULL_NODE");
|
||||
Capabilities.app.addAll(Capability.DAO_FULL_NODE);
|
||||
} else {
|
||||
// A lite node has the capability to receive bsq blocks. We do not want to send BSQ blocks to full nodes
|
||||
// as they ignore them anyway.
|
||||
Capabilities.app.addAll(Capability.RECEIVE_BSQ_BLOCK);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
5quyxpxheyvzmb2d.onion:8000 (@miker)
|
||||
s67qglwhkgkyvr74.onion:8000 (@emzy)
|
||||
ef5qnzx6znifo3df.onion:8000 (@alexej996)
|
||||
jhgcy2won7xnslrb.onion:8000 (@wiz)
|
||||
jhgcy2won7xnslrb.onion:8000 (@wiz, @nicolasdorier)
|
||||
3f3cu2yw7u457ztq.onion:8000 (@devinbileck)
|
||||
723ljisnynbtdohi.onion:8000 (@emzy)
|
||||
rm7b56wbrcczpjvl.onion:8000 (@miker)
|
||||
|
|
|
@ -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, null);
|
||||
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});
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
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 org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
public class BuyerDataItemTest {
|
||||
private BuyerDataItem buyerDataItem1;
|
||||
private BuyerDataItem buyerDataItem2;
|
||||
private BuyerDataItem buyerDataItem3;
|
||||
private AccountAgeWitness accountAgeWitness1;
|
||||
private AccountAgeWitness accountAgeWitness2;
|
||||
private byte[] hash1 = "1".getBytes();
|
||||
private byte[] hash2 = "2".getBytes();
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
accountAgeWitness1 = new AccountAgeWitness(hash1, 123);
|
||||
accountAgeWitness2 = new AccountAgeWitness(hash2, 124);
|
||||
buyerDataItem1 = new BuyerDataItem(mock(PaymentAccountPayload.class), accountAgeWitness1, Coin.valueOf(546),
|
||||
mock(PublicKey.class));
|
||||
buyerDataItem2 = new BuyerDataItem(mock(PaymentAccountPayload.class), accountAgeWitness1, Coin.valueOf(547),
|
||||
mock(PublicKey.class));
|
||||
buyerDataItem3 = new BuyerDataItem(mock(PaymentAccountPayload.class), accountAgeWitness2, Coin.valueOf(548),
|
||||
mock(PublicKey.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEquals() {
|
||||
assertEquals(buyerDataItem1, buyerDataItem2);
|
||||
assertNotEquals(buyerDataItem1, buyerDataItem3);
|
||||
assertNotEquals(buyerDataItem2, buyerDataItem3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHashCode() {
|
||||
assertEquals(buyerDataItem1.hashCode(), buyerDataItem2.hashCode());
|
||||
assertNotEquals(buyerDataItem1.hashCode(), buyerDataItem3.hashCode());
|
||||
}
|
||||
}
|
|
@ -82,6 +82,7 @@ import java.sql.Date;
|
|||
public class SupplyView extends ActivatableView<GridPane, Void> implements DaoStateListener {
|
||||
|
||||
private static final String MONTH = "month";
|
||||
private static final String DAY = "day";
|
||||
|
||||
private final DaoFacade daoFacade;
|
||||
private DaoStateService daoStateService;
|
||||
|
@ -113,6 +114,7 @@ public class SupplyView extends ActivatableView<GridPane, Void> implements DaoSt
|
|||
public void initialize() {
|
||||
|
||||
ADJUSTERS.put(MONTH, TemporalAdjusters.firstDayOfMonth());
|
||||
ADJUSTERS.put(DAY, TemporalAdjusters.ofDateAdjuster(d -> d));
|
||||
|
||||
createSupplyIncreasedInformation();
|
||||
createSupplyReducedInformation();
|
||||
|
@ -161,7 +163,7 @@ public class SupplyView extends ActivatableView<GridPane, Void> implements DaoSt
|
|||
|
||||
|
||||
seriesBSQIssued = new XYChart.Series<>();
|
||||
createChart(seriesBSQIssued, Res.get("dao.factsAndFigures.supply.issued"));
|
||||
createChart(seriesBSQIssued, Res.get("dao.factsAndFigures.supply.issued"), "MMM uu");
|
||||
}
|
||||
|
||||
private void createSupplyReducedInformation() {
|
||||
|
@ -173,7 +175,7 @@ public class SupplyView extends ActivatableView<GridPane, Void> implements DaoSt
|
|||
Res.get("dao.factsAndFigures.supply.invalidTxs"), Layout.FIRST_ROW_AND_GROUP_DISTANCE).second;
|
||||
|
||||
seriesBSQBurnt = new XYChart.Series<>();
|
||||
createChart(seriesBSQBurnt, Res.get("dao.factsAndFigures.supply.burnt"));
|
||||
createChart(seriesBSQBurnt, Res.get("dao.factsAndFigures.supply.burnt"), "d MMM");
|
||||
}
|
||||
|
||||
private void createSupplyLockedInformation() {
|
||||
|
@ -193,7 +195,8 @@ public class SupplyView extends ActivatableView<GridPane, Void> implements DaoSt
|
|||
Res.get("dao.factsAndFigures.supply.totalConfiscatedAmount")).second;
|
||||
}
|
||||
|
||||
private void createChart(XYChart.Series<Number, Number> series, String seriesLabel) {
|
||||
@SuppressWarnings("unchecked")
|
||||
private void createChart(XYChart.Series<Number, Number> series, String seriesLabel, String datePattern) {
|
||||
NumberAxis xAxis = new NumberAxis();
|
||||
xAxis.setForceZeroInRange(false);
|
||||
xAxis.setAutoRanging(true);
|
||||
|
@ -205,7 +208,7 @@ public class SupplyView extends ActivatableView<GridPane, Void> implements DaoSt
|
|||
public String toString(Number timestamp) {
|
||||
LocalDateTime localDateTime = LocalDateTime.ofEpochSecond(timestamp.longValue(),
|
||||
0, OffsetDateTime.now(ZoneId.systemDefault()).getOffset());
|
||||
return localDateTime.format(DateTimeFormatter.ofPattern("MMM uu", GlobalSettings.getLocale()));
|
||||
return localDateTime.format(DateTimeFormatter.ofPattern(datePattern, GlobalSettings.getLocale()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -296,15 +299,15 @@ public class SupplyView extends ActivatableView<GridPane, Void> implements DaoSt
|
|||
Set<Tx> burntTxs = new HashSet<>(daoStateService.getBurntFeeTxs());
|
||||
burntTxs.addAll(daoStateService.getInvalidTxs());
|
||||
|
||||
Map<LocalDate, List<Tx>> burntBsqByMonth = burntTxs.stream()
|
||||
Map<LocalDate, List<Tx>> burntBsqByDay = burntTxs.stream()
|
||||
.sorted(Comparator.comparing(Tx::getTime))
|
||||
.collect(Collectors.groupingBy(item -> new Date(item.getTime()).toLocalDate()
|
||||
.with(ADJUSTERS.get(MONTH))));
|
||||
.with(ADJUSTERS.get(DAY))));
|
||||
|
||||
List<XYChart.Data<Number, Number>> updatedBurntBsq = burntBsqByMonth.keySet().stream()
|
||||
List<XYChart.Data<Number, Number>> updatedBurntBsq = burntBsqByDay.keySet().stream()
|
||||
.map(date -> {
|
||||
ZonedDateTime zonedDateTime = date.atStartOfDay(ZoneId.systemDefault());
|
||||
return new XYChart.Data<Number, Number>(zonedDateTime.toInstant().getEpochSecond(), burntBsqByMonth.get(date)
|
||||
return new XYChart.Data<Number, Number>(zonedDateTime.toInstant().getEpochSecond(), burntBsqByDay.get(date)
|
||||
.stream()
|
||||
.mapToDouble(Tx::getBurntBsq)
|
||||
.sum()
|
||||
|
|
|
@ -32,6 +32,7 @@ import bisq.core.notifications.alerts.MyOfferTakenEvents;
|
|||
import bisq.core.notifications.alerts.TradeEvents;
|
||||
import bisq.core.notifications.alerts.market.MarketAlerts;
|
||||
import bisq.core.notifications.alerts.price.PriceAlert;
|
||||
import bisq.core.payment.ChargeBackRisk;
|
||||
import bisq.core.payment.TradeLimits;
|
||||
import bisq.core.proto.network.CoreNetworkProtoResolver;
|
||||
import bisq.core.proto.persistable.CorePersistenceProtoResolver;
|
||||
|
@ -131,6 +132,7 @@ public class GuiceSetupTest {
|
|||
assertSingleton(TradeEvents.class);
|
||||
assertSingleton(PriceAlert.class);
|
||||
assertSingleton(MarketAlerts.class);
|
||||
assertSingleton(ChargeBackRisk.class);
|
||||
|
||||
assertNotSingleton(Storage.class);
|
||||
}
|
||||
|
|
|
@ -201,8 +201,10 @@ public class P2PDataStorage implements MessageListener, ConnectionListener, Pers
|
|||
// Batch processing can cause performance issues, so we give listeners a chance to deal with it by notifying
|
||||
// about start and end of iteration.
|
||||
hashMapChangedListeners.forEach(HashMapChangedListener::onBatchRemoveExpiredDataStarted);
|
||||
toRemoveSet.forEach(protectedDataToRemove -> hashMapChangedListeners.forEach(
|
||||
listener -> listener.onRemoved(protectedDataToRemove)));
|
||||
toRemoveSet.forEach(protectedStorageEntry -> {
|
||||
hashMapChangedListeners.forEach(l -> l.onRemoved(protectedStorageEntry));
|
||||
removeFromProtectedDataStore(protectedStorageEntry);
|
||||
});
|
||||
hashMapChangedListeners.forEach(HashMapChangedListener::onBatchRemoveExpiredDataCompleted);
|
||||
|
||||
if (sequenceNumberMap.size() > 1000)
|
||||
|
@ -483,6 +485,15 @@ public class P2PDataStorage implements MessageListener, ConnectionListener, Pers
|
|||
|
||||
broadcast(new RemoveDataMessage(protectedStorageEntry), sender, null, isDataOwner);
|
||||
|
||||
removeFromProtectedDataStore(protectedStorageEntry);
|
||||
} else {
|
||||
log.debug("remove failed");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private void removeFromProtectedDataStore(ProtectedStorageEntry protectedStorageEntry) {
|
||||
ProtectedStoragePayload protectedStoragePayload = protectedStorageEntry.getProtectedStoragePayload();
|
||||
if (protectedStoragePayload instanceof PersistablePayload) {
|
||||
ByteArray compactHash = getCompactHashAsByteArray(protectedStoragePayload);
|
||||
ProtectedStorageEntry previous = protectedDataStoreService.remove(compactHash, protectedStorageEntry);
|
||||
|
@ -492,10 +503,6 @@ public class P2PDataStorage implements MessageListener, ConnectionListener, Pers
|
|||
log.info("We cannot remove the protectedStorageEntry from the persistedEntryMap as it does not exist.");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.debug("remove failed");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnusedReturnValue")
|
||||
|
|
|
@ -3,6 +3,8 @@ package bisq.seednode;
|
|||
import bisq.core.app.BisqEnvironment;
|
||||
import bisq.core.app.misc.AppSetupWithP2PAndDAO;
|
||||
import bisq.core.app.misc.ModuleForAppWithP2p;
|
||||
import bisq.core.locale.CurrencyUtil;
|
||||
import bisq.core.locale.Res;
|
||||
|
||||
import org.springframework.mock.env.MockPropertySource;
|
||||
|
||||
|
@ -13,6 +15,9 @@ import org.junit.Test;
|
|||
public class GuiceSetupTest {
|
||||
@Test
|
||||
public void testGuiceSetup() {
|
||||
Res.setup();
|
||||
CurrencyUtil.setup();
|
||||
|
||||
ModuleForAppWithP2p module = new ModuleForAppWithP2p(new BisqEnvironment(new MockPropertySource()));
|
||||
Guice.createInjector(module).getInstance(AppSetupWithP2PAndDAO.class);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue