User split in User and UserVO, all persisted stuff goes to UserVO, a lot cleaner than a class loading itself and fiddling at its internal bits - now you load your VO and replace it with the loaded version, update observables and done, code is shorter and more readable as well. Added fromProto() methods. Fixed a toProto bug.

This commit is contained in:
Mike Rosseel 2017-04-20 08:50:58 +02:00
parent 18be5ec9aa
commit 93b9847e47
19 changed files with 384 additions and 253 deletions

View File

@ -108,7 +108,7 @@ public final class PubKeyRing implements Payload {
}
} catch (InvalidKeySpecException | NoSuchAlgorithmException | NoSuchProviderException e) {
e.printStackTrace();
log.error(e.getMessage());
log.error(e.getMessage() + toString());
}
}

View File

@ -761,12 +761,13 @@ message DiskEnvelope {
oneof message {
AddressEntryList address_entry_list = 2;
Navigation navigation = 3;
PersistedPeers persisted_peers = 4;
PeersList peers_list = 4;
Preferences preferences = 5;
User user = 6;
PersistedP2PStorageData persisted_p2p_storage_data = 7;
SequenceNumberMap sequence_number_map = 8;
LongPersistable bloom_filter_nonce = 9;
TradeStatisticsList trade_statistics_list = 10;
}
}
@ -778,10 +779,14 @@ message LongPersistable {
int64 long = 1;
}
message PersistedPeers {
message PeersList {
repeated Peer peers = 1;
}
message TradeStatisticsList {
repeated TradeStatistics trade_statistics = 1;
}
@ -1090,8 +1095,9 @@ message User {
Alert displayed_alert = 6;
Filter developers_filter = 7;
repeated Arbitrator accepted_arbitrators = 8;
Arbitrator registered_arbitrator = 9;
Mediator registered_mediator = 10;
repeated Mediator accepted_mediators = 9;
Arbitrator registered_arbitrator = 10;
Mediator registered_mediator = 11;
}
message ViewPath {

View File

@ -27,6 +27,7 @@ import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;
import javax.annotation.Nullable;
import java.security.PublicKey;
@ -150,4 +151,14 @@ public final class Alert implements StoragePayload {
Optional.ofNullable(getExtraDataMap()).ifPresent(builder::putAllExtraDataMap);
return PB.StoragePayload.newBuilder().setAlert(builder).build();
}
public static Alert fromProto(PB.Alert alert) {
return new Alert(alert.getMessage(),
alert.getIsUpdateInfo(),
alert.getVersion(),
alert.getStoragePublicKeyBytes().toByteArray(),
alert.getSignatureAsBase64(),
CollectionUtils.isEmpty(alert.getExtraDataMapMap()) ?
null : alert.getExtraDataMapMap());
}
}

View File

@ -20,6 +20,7 @@ package io.bisq.core.arbitration;
import com.google.protobuf.ByteString;
import io.bisq.common.app.Version;
import io.bisq.common.crypto.PubKeyRing;
import io.bisq.core.proto.ProtoUtil;
import io.bisq.generated.protobuffer.PB;
import io.bisq.network.p2p.NodeAddress;
import io.bisq.network.p2p.storage.payload.StoragePayload;
@ -27,6 +28,7 @@ import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;
import javax.annotation.Nullable;
import java.security.PublicKey;
@ -35,6 +37,7 @@ import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@EqualsAndHashCode
@Slf4j
@ -113,4 +116,21 @@ public final class Arbitrator implements StoragePayload {
return PB.StoragePayload.newBuilder().setArbitrator(builder).build();
}
public static Arbitrator fromProto(PB.Arbitrator arbitrator) {
List<String> strings = arbitrator.getLanguageCodesList().stream().collect(Collectors.toList());
Date date = new Date(arbitrator.getRegistrationDate());
String emailAddress = arbitrator.getEmailAddress().isEmpty() ? null : arbitrator.getEmailAddress();
return new Arbitrator(NodeAddress.fromProto(arbitrator.getNodeAddress()),
arbitrator.getBtcPubKey().toByteArray(),
arbitrator.getBtcAddress(),
ProtoUtil.getPubKeyRing(arbitrator.getPubKeyRing()),
strings,
date,
arbitrator.getRegistrationPubKey().toByteArray(),
arbitrator.getRegistrationSignature(),
emailAddress,
CollectionUtils.isEmpty(arbitrator.getExtraDataMapMap()) ?
null : arbitrator.getExtraDataMapMap());
}
}

View File

@ -20,6 +20,7 @@ package io.bisq.core.arbitration;
import com.google.protobuf.ByteString;
import io.bisq.common.app.Version;
import io.bisq.common.crypto.PubKeyRing;
import io.bisq.core.proto.ProtoUtil;
import io.bisq.generated.protobuffer.PB;
import io.bisq.network.p2p.NodeAddress;
import io.bisq.network.p2p.storage.payload.StoragePayload;
@ -27,6 +28,7 @@ import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;
import javax.annotation.Nullable;
import java.security.PublicKey;
@ -35,6 +37,7 @@ import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@EqualsAndHashCode
@Slf4j
@ -105,4 +108,20 @@ public final class Mediator implements StoragePayload {
return PB.StoragePayload.newBuilder().setMediator(builder).build();
}
public static Mediator fromProto(PB.Mediator mediator) {
List<String> strings = mediator.getLanguageCodesList().stream().collect(Collectors.toList());
Date date = new Date(mediator.getRegistrationDate());
String emailAddress = mediator.getEmailAddress().isEmpty() ? null : mediator.getEmailAddress();
return new Mediator(NodeAddress.fromProto(mediator.getNodeAddress()),
ProtoUtil.getPubKeyRing(mediator.getPubKeyRing()),
strings,
date,
mediator.getRegistrationPubKey().toByteArray(),
mediator.getRegistrationSignature(),
emailAddress,
CollectionUtils.isEmpty(mediator.getExtraDataMapMap()) ?
null : mediator.getExtraDataMapMap());
}
}

View File

@ -21,12 +21,14 @@ import com.google.common.collect.Maps;
import com.google.protobuf.ByteString;
import io.bisq.common.app.Version;
import io.bisq.common.crypto.Sig;
import io.bisq.core.proto.ProtoUtil;
import io.bisq.generated.protobuffer.PB;
import io.bisq.network.p2p.storage.payload.StoragePayload;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.util.encoders.Hex;
import org.springframework.util.CollectionUtils;
import javax.annotation.Nullable;
import java.io.IOException;
@ -139,6 +141,18 @@ public final class Filter implements StoragePayload {
return PB.StoragePayload.newBuilder().setFilter(builder).build();
}
public static Filter fromProto(PB.Filter filter) {
List<PaymentAccountFilter> paymentAccountFilters = filter.getBannedPaymentAccountsList()
.stream().map(accountFilter -> ProtoUtil.getPaymentAccountFilter(accountFilter)).collect(Collectors.toList());
return new Filter(filter.getBannedOfferIdsList().stream().collect(Collectors.toList()),
filter.getBannedNodeAddressList().stream().collect(Collectors.toList()),
paymentAccountFilters,
filter.getSignatureAsBase64(),
filter.getPublicKeyBytes().toByteArray(),
CollectionUtils.isEmpty(filter.getExtraDataMapMap()) ?
null : filter.getExtraDataMapMap());
}
@Override
public String toString() {

View File

@ -31,6 +31,7 @@ import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import javax.annotation.Nullable;
import java.security.PublicKey;
@ -63,7 +64,13 @@ public final class OfferPayload implements StoragePayload, RequiresOwnerIsOnline
// Enums
///////////////////////////////////////////////////////////////////////////////////////////
public enum Direction {BUY, SELL}
public enum Direction {
BUY, SELL;
public static OfferPayload.Direction fromProto(PB.OfferPayload.Direction direction) {
return OfferPayload.Direction.valueOf(direction.name());
}
}
///////////////////////////////////////////////////////////////////////////////////////////
@ -124,7 +131,7 @@ public final class OfferPayload implements StoragePayload, RequiresOwnerIsOnline
// reserved for future use cases
// Close offer when certain price is reached
private final boolean useAutoClose;
// If useReOpenAfterAutoClose=true we re-open a new offer with the remaining funds if the trade amount
// If useReOpenAfterAutoClose=true we re-open a new offer with the remaining funds if the trade amount
// was less then the offer's max. trade amount.
private final boolean useReOpenAfterAutoClose;
// Used when useAutoClose is set for canceling the offer when lowerClosePrice is triggered
@ -136,8 +143,8 @@ public final class OfferPayload implements StoragePayload, RequiresOwnerIsOnline
@Nullable
private final String hashOfChallenge;
// Should be only used in emergency case if we need to add data but do not want to break backward compatibility
// at the P2P network storage checks. The hash of the object will be used to verify if the data is valid. Any new
// Should be only used in emergency case if we need to add data but do not want to break backward compatibility
// at the P2P network storage checks. The hash of the object will be used to verify if the data is valid. Any new
// field in a class would break that hash and therefore break the storage mechanism.
@Nullable
private Map<String, String> extraDataMap;

View File

@ -116,6 +116,6 @@ public abstract class PaymentAccount implements Persistable {
@Override
public PB.PaymentAccount toProto() {
return PB.PaymentAccount.newBuilder().setPaymentMethod(PB.PaymentMethod.newBuilder().setId(getId())).build();
return PB.PaymentAccount.newBuilder().setPaymentMethod(PB.PaymentMethod.newBuilder().setId(paymentMethod.getId())).build();
}
}

View File

@ -10,10 +10,14 @@ import io.bisq.core.btc.AddressEntryList;
import io.bisq.core.payment.PaymentAccount;
import io.bisq.core.payment.PaymentAccountFactory;
import io.bisq.core.payment.payload.PaymentMethod;
import io.bisq.core.trade.statistics.TradeStatistics;
import io.bisq.core.user.BlockChainExplorer;
import io.bisq.core.user.Preferences;
import io.bisq.core.user.User;
import io.bisq.core.user.UserVO;
import io.bisq.generated.protobuffer.PB;
import io.bisq.network.p2p.peers.PersistedList;
import io.bisq.network.p2p.peers.peerexchange.Peer;
import lombok.extern.slf4j.Slf4j;
import org.bitcoinj.core.Coin;
@ -22,6 +26,9 @@ import java.util.HashMap;
import java.util.Locale;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import static io.bisq.core.proto.ProtoUtil.getPaymentAccount;
/**
* If the Messages class is giving errors in IntelliJ, you should change the IntelliJ IDEA Platform Properties file,
@ -40,11 +47,11 @@ public class CoreDiskProtoResolver implements PersistenceProtoResolver {
private Provider<AddressEntryList> addressEntryListProvider;
private Provider<Preferences> preferencesProvider;
private Provider<User> user;
@Inject
public CoreDiskProtoResolver(Provider<Preferences> preferencesProvider,
Provider<AddressEntryList> addressEntryListProvider) {
Provider<AddressEntryList> addressEntryListProvider
) {
this.preferencesProvider = preferencesProvider;
this.addressEntryListProvider = addressEntryListProvider;
}
@ -67,15 +74,16 @@ public class CoreDiskProtoResolver implements PersistenceProtoResolver {
case NAVIGATION:
result = getPing(envelope);
break;
case PERSISTED_PEERS:
result = getPing(envelope);
break;
*/
case PEERS_LIST:
result = getPeersList(envelope.getPeersList());
break;
case PREFERENCES:
result = fillPreferences(envelope, preferencesProvider.get());
break;
case USER:
result = getUser(envelope, user.get());
result = UserVO.fromProto(envelope.getUser());
break;
/*
case PERSISTED_P2P_STORAGE_DATA:
@ -85,6 +93,8 @@ public class CoreDiskProtoResolver implements PersistenceProtoResolver {
result = getPing(envelope);
break;
*/
case TRADE_STATISTICS_LIST:
result = getTradeStatisticsList(envelope.getTradeStatisticsList());
case BLOOM_FILTER_NONCE:
result = getLongPersistable(envelope.getBloomFilterNonce());
break;
@ -94,9 +104,14 @@ public class CoreDiskProtoResolver implements PersistenceProtoResolver {
return Optional.ofNullable(result);
}
private Persistable getUser(PB.DiskEnvelope envelope, User user) {
final PB.User userpb = envelope.getUser();
return null; // TODO
private Persistable getTradeStatisticsList(PB.TradeStatisticsList tradeStatisticsList) {
return new PersistedList<>(tradeStatisticsList.getTradeStatisticsList().stream()
.map(tradeStatistics -> TradeStatistics.fromProto(tradeStatistics)).collect(Collectors.toList()));
}
private Persistable getPeersList(PB.PeersList envelope) {
return new PersistedList<>(envelope.getPeersList().stream().map(peer -> Peer.fromProto(peer))
.collect(Collectors.toList()));
}
private Preferences fillPreferences(PB.DiskEnvelope envelope, Preferences preferences) {
@ -151,9 +166,6 @@ public class CoreDiskProtoResolver implements PersistenceProtoResolver {
return preferences;
}
private PaymentAccount getPaymentAccount(PB.PaymentAccount account) {
return PaymentAccountFactory.getPaymentAccount(PaymentMethod.getPaymentMethodById(account.getPaymentMethod().getId()));
}
private TradeCurrency getTradeCurrency(PB.TradeCurrency tradeCurrency) {
switch (tradeCurrency.getMessageCase()) {

View File

@ -205,14 +205,14 @@ public class CoreNetworkProtoResolver implements NetworkProtoResolver {
private static Msg getPrivateNotificationMessage(PB.PrivateNotificationMessage privateNotificationMessage) {
return new PrivateNotificationMsg(getPrivateNotification(privateNotificationMessage.getPrivateNotificationPayload()),
ProtoUtil.getNodeAddress(privateNotificationMessage.getMyNodeAddress()),
NodeAddress.fromProto(privateNotificationMessage.getMyNodeAddress()),
privateNotificationMessage.getUid());
}
private static Msg getPayoutTxPublishedMessage(PB.PayoutTxPublishedMessage payoutTxPublishedMessage) {
return new PayoutTxPublishedMsg(payoutTxPublishedMessage.getTradeId(),
payoutTxPublishedMessage.getPayoutTx().toByteArray(),
ProtoUtil.getNodeAddress(payoutTxPublishedMessage.getSenderNodeAddress()),
NodeAddress.fromProto(payoutTxPublishedMessage.getSenderNodeAddress()),
payoutTxPublishedMessage.getUid());
}
@ -232,7 +232,7 @@ public class CoreNetworkProtoResolver implements NetworkProtoResolver {
private static Msg getFiatTransferStartedMessage(PB.FiatTransferStartedMessage fiatTransferStartedMessage) {
return new FiatTransferStartedMsg(fiatTransferStartedMessage.getTradeId(),
fiatTransferStartedMessage.getBuyerPayoutAddress(),
ProtoUtil.getNodeAddress(fiatTransferStartedMessage.getSenderNodeAddress()),
NodeAddress.fromProto(fiatTransferStartedMessage.getSenderNodeAddress()),
fiatTransferStartedMessage.getBuyerSignature().toByteArray(),
fiatTransferStartedMessage.getUid()
);
@ -253,7 +253,7 @@ public class CoreNetworkProtoResolver implements NetworkProtoResolver {
publishDepositTxRequest.getMakerPayoutAddressString(),
publishDepositTxRequest.getPreparedDepositTx().toByteArray(),
rawTransactionInputs,
ProtoUtil.getNodeAddress(publishDepositTxRequest.getSenderNodeAddress()),
NodeAddress.fromProto(publishDepositTxRequest.getSenderNodeAddress()),
publishDepositTxRequest.getUid());
}
@ -263,10 +263,10 @@ public class CoreNetworkProtoResolver implements NetworkProtoResolver {
rawTransactionInput.getParentTransaction().toByteArray(), rawTransactionInput.getValue()))
.collect(Collectors.toList());
List<NodeAddress> arbitratorNodeAddresses = payDepositRequest.getAcceptedArbitratorNodeAddressesList().stream()
.map(ProtoUtil::getNodeAddress).collect(Collectors.toList());
.map(NodeAddress::fromProto).collect(Collectors.toList());
List<NodeAddress> mediatorNodeAddresses = payDepositRequest.getAcceptedMediatorNodeAddressesList().stream()
.map(ProtoUtil::getNodeAddress).collect(Collectors.toList());
return new PayDepositRequest(ProtoUtil.getNodeAddress(payDepositRequest.getSenderNodeAddress()),
.map(NodeAddress::fromProto).collect(Collectors.toList());
return new PayDepositRequest(NodeAddress.fromProto(payDepositRequest.getSenderNodeAddress()),
payDepositRequest.getTradeId(),
payDepositRequest.getTradeAmount(),
payDepositRequest.getTradePrice(),
@ -283,14 +283,14 @@ public class CoreNetworkProtoResolver implements NetworkProtoResolver {
payDepositRequest.getTakerFeeTxId(),
arbitratorNodeAddresses,
mediatorNodeAddresses,
ProtoUtil.getNodeAddress(payDepositRequest.getArbitratorNodeAddress()),
ProtoUtil.getNodeAddress(payDepositRequest.getMediatorNodeAddress()));
NodeAddress.fromProto(payDepositRequest.getArbitratorNodeAddress()),
NodeAddress.fromProto(payDepositRequest.getMediatorNodeAddress()));
}
private static Msg getPeerPublishedPayoutTxMessage(PB.PeerPublishedPayoutTxMessage peerPublishedPayoutTxMessage) {
return new PeerPublishedPayoutTxMsg(peerPublishedPayoutTxMessage.getTransaction().toByteArray(),
peerPublishedPayoutTxMessage.getTradeId(),
ProtoUtil.getNodeAddress(peerPublishedPayoutTxMessage.getMyNodeAddress()),
NodeAddress.fromProto(peerPublishedPayoutTxMessage.getMyNodeAddress()),
peerPublishedPayoutTxMessage.getUid());
}
@ -308,18 +308,18 @@ public class CoreNetworkProtoResolver implements NetworkProtoResolver {
disputeResultproto.getArbitratorPubKey().toByteArray(), disputeResultproto.getCloseDate(),
disputeResultproto.getIsLoserPublisher());
return new DisputeResultMsg(disputeResult,
ProtoUtil.getNodeAddress(disputeResultMessage.getMyNodeAddress()),
NodeAddress.fromProto(disputeResultMessage.getMyNodeAddress()),
disputeResultMessage.getUid());
}
private static Msg getPeerOpenedDisputeMessage(PB.PeerOpenedDisputeMessage peerOpenedDisputeMessage) {
return new PeerOpenedDisputeMsg(ProtoUtil.getDispute(peerOpenedDisputeMessage.getDispute()),
ProtoUtil.getNodeAddress(peerOpenedDisputeMessage.getMyNodeAddress()), peerOpenedDisputeMessage.getUid());
NodeAddress.fromProto(peerOpenedDisputeMessage.getMyNodeAddress()), peerOpenedDisputeMessage.getUid());
}
private static Msg getOpenNewDisputeMessage(PB.OpenNewDisputeMessage openNewDisputeMessage) {
return new OpenNewDisputeMsg(ProtoUtil.getDispute(openNewDisputeMessage.getDispute()),
ProtoUtil.getNodeAddress(openNewDisputeMessage.getMyNodeAddress()), openNewDisputeMessage.getUid());
NodeAddress.fromProto(openNewDisputeMessage.getMyNodeAddress()), openNewDisputeMessage.getUid());
}
private static Msg getDisputeCommunicationMessage(PB.DisputeCommunicationMessage disputeCommunicationMessage) {
@ -330,7 +330,7 @@ public class CoreNetworkProtoResolver implements NetworkProtoResolver {
disputeCommunicationMessage.getAttachmentsList().stream()
.map(attachment -> new Attachment(attachment.getFileName(), attachment.getBytes().toByteArray()))
.collect(Collectors.toList()),
ProtoUtil.getNodeAddress(disputeCommunicationMessage.getMyNodeAddress()),
NodeAddress.fromProto(disputeCommunicationMessage.getMyNodeAddress()),
disputeCommunicationMessage.getDate(),
disputeCommunicationMessage.getArrived(),
disputeCommunicationMessage.getStoredInMailbox(),
@ -341,14 +341,14 @@ public class CoreNetworkProtoResolver implements NetworkProtoResolver {
return new FinalizePayoutTxRequest(finalizePayoutTxRequest.getTradeId(),
finalizePayoutTxRequest.getSellerSignature().toByteArray(),
finalizePayoutTxRequest.getSellerPayoutAddress(),
ProtoUtil.getNodeAddress(finalizePayoutTxRequest.getSenderNodeAddress()),
NodeAddress.fromProto(finalizePayoutTxRequest.getSenderNodeAddress()),
finalizePayoutTxRequest.getUid());
}
private static Msg getDepositTxPublishedMessage(PB.DepositTxPublishedMessage depositTxPublishedMessage) {
return new DepositTxPublishedMsg(depositTxPublishedMessage.getTradeId(),
depositTxPublishedMessage.getDepositTx().toByteArray(),
ProtoUtil.getNodeAddress(depositTxPublishedMessage.getSenderNodeAddress()), depositTxPublishedMessage.getUid());
NodeAddress.fromProto(depositTxPublishedMessage.getSenderNodeAddress()), depositTxPublishedMessage.getUid());
}
private static Msg getRemoveMailBoxDataMessage(PB.RemoveMailboxDataMessage msg) {
@ -474,62 +474,16 @@ public class CoreNetworkProtoResolver implements NetworkProtoResolver {
Map<String, String> extraDataMapMap;
switch (protoEntry.getMessageCase()) {
case ALERT:
PB.Alert protoAlert = protoEntry.getAlert();
extraDataMapMap = CollectionUtils.isEmpty(protoAlert.getExtraDataMapMap()) ?
null : protoAlert.getExtraDataMapMap();
storagePayload = new Alert(protoAlert.getMessage(),
protoAlert.getIsUpdateInfo(),
protoAlert.getVersion(),
protoAlert.getStoragePublicKeyBytes().toByteArray(),
protoAlert.getSignatureAsBase64(),
extraDataMapMap);
storagePayload = Alert.fromProto(protoEntry.getAlert());
break;
case ARBITRATOR:
PB.Arbitrator arbitrator = protoEntry.getArbitrator();
extraDataMapMap = CollectionUtils.isEmpty(arbitrator.getExtraDataMapMap()) ?
null : arbitrator.getExtraDataMapMap();
List<String> strings = arbitrator.getLanguageCodesList().stream().collect(Collectors.toList());
Date date = new Date(arbitrator.getRegistrationDate());
String emailAddress = arbitrator.getEmailAddress().isEmpty() ? null : arbitrator.getEmailAddress();
storagePayload = new Arbitrator(ProtoUtil.getNodeAddress(arbitrator.getNodeAddress()),
arbitrator.getBtcPubKey().toByteArray(),
arbitrator.getBtcAddress(),
ProtoUtil.getPubKeyRing(arbitrator.getPubKeyRing()),
strings,
date,
arbitrator.getRegistrationPubKey().toByteArray(),
arbitrator.getRegistrationSignature(),
emailAddress,
extraDataMapMap);
storagePayload = Arbitrator.fromProto(protoEntry.getArbitrator());
break;
case MEDIATOR:
PB.Mediator mediator = protoEntry.getMediator();
extraDataMapMap = CollectionUtils.isEmpty(mediator.getExtraDataMapMap()) ?
null : mediator.getExtraDataMapMap();
strings = mediator.getLanguageCodesList().stream().collect(Collectors.toList());
date = new Date(mediator.getRegistrationDate());
emailAddress = mediator.getEmailAddress().isEmpty() ? null : mediator.getEmailAddress();
storagePayload = new Mediator(ProtoUtil.getNodeAddress(mediator.getNodeAddress()),
ProtoUtil.getPubKeyRing(mediator.getPubKeyRing()),
strings,
date,
mediator.getRegistrationPubKey().toByteArray(),
mediator.getRegistrationSignature(),
emailAddress,
extraDataMapMap);
storagePayload = Mediator.fromProto(protoEntry.getMediator());
break;
case FILTER:
PB.Filter filter = protoEntry.getFilter();
extraDataMapMap = CollectionUtils.isEmpty(filter.getExtraDataMapMap()) ?
null : filter.getExtraDataMapMap();
List<PaymentAccountFilter> paymentAccountFilters = filter.getBannedPaymentAccountsList()
.stream().map(accountFilter -> ProtoUtil.getPaymentAccountFilter(accountFilter)).collect(Collectors.toList());
storagePayload = new Filter(filter.getBannedOfferIdsList().stream().collect(Collectors.toList()),
filter.getBannedNodeAddressList().stream().collect(Collectors.toList()),
paymentAccountFilters,
filter.getSignatureAsBase64(),
filter.getPublicKeyBytes().toByteArray(),
extraDataMapMap);
storagePayload = Filter.fromProto(protoEntry.getFilter());
break;
case COMPENSATION_REQUEST_PAYLOAD:
PB.CompensationRequestPayload compensationRequestPayload = protoEntry.getCompensationRequestPayload();
@ -550,27 +504,7 @@ public class CoreNetworkProtoResolver implements NetworkProtoResolver {
extraDataMapMap);
break;
case TRADE_STATISTICS:
PB.TradeStatistics protoTrade = protoEntry.getTradeStatistics();
extraDataMapMap = CollectionUtils.isEmpty(protoTrade.getExtraDataMapMap()) ?
null : protoTrade.getExtraDataMapMap();
storagePayload = new TradeStatistics(getDirection(protoTrade.getDirection()),
protoTrade.getBaseCurrency(),
protoTrade.getCounterCurrency(),
protoTrade.getPaymentMethodId(),
protoTrade.getOfferDate(),
protoTrade.getUseMarketBasedPrice(),
protoTrade.getMarketPriceMargin(),
protoTrade.getOfferAmount(),
protoTrade.getOfferMinAmount(),
protoTrade.getOfferId(),
protoTrade.getTradePrice(),
protoTrade.getTradeAmount(),
protoTrade.getTradeDate(),
protoTrade.getDepositTxId(),
new PubKeyRing(protoTrade.getPubKeyRing().getSignaturePubKeyBytes().toByteArray(),
protoTrade.getPubKeyRing().getEncryptionPubKeyBytes().toByteArray(),
protoTrade.getPubKeyRing().getPgpPubKeyAsPem()),
extraDataMapMap);
storagePayload = TradeStatistics.fromProto(protoEntry.getTradeStatistics());
break;
case MAILBOX_STORAGE_PAYLOAD:
PB.MailboxStoragePayload mbox = protoEntry.getMailboxStoragePayload();
@ -608,9 +542,9 @@ public class CoreNetworkProtoResolver implements NetworkProtoResolver {
public static OfferPayload getOfferPayload(PB.OfferPayload pbOffer) {
List<NodeAddress> arbitratorNodeAddresses = pbOffer.getArbitratorNodeAddressesList().stream()
.map(ProtoUtil::getNodeAddress).collect(Collectors.toList());
.map(NodeAddress::fromProto).collect(Collectors.toList());
List<NodeAddress> mediatorNodeAddresses = pbOffer.getMediatorNodeAddressesList().stream()
.map(ProtoUtil::getNodeAddress).collect(Collectors.toList());
.map(NodeAddress::fromProto).collect(Collectors.toList());
// Nullable object need to be checked against the default values in PB (not nice... ;-( )
@ -630,9 +564,9 @@ public class CoreNetworkProtoResolver implements NetworkProtoResolver {
return new OfferPayload(pbOffer.getId(),
pbOffer.getDate(),
ProtoUtil.getNodeAddress(pbOffer.getMakerNodeAddress()),
NodeAddress.fromProto(pbOffer.getMakerNodeAddress()),
ProtoUtil.getPubKeyRing(pbOffer.getPubKeyRing()),
getDirection(pbOffer.getDirection()),
OfferPayload.Direction.fromProto(pbOffer.getDirection()),
pbOffer.getPrice(),
pbOffer.getMarketPriceMargin(),
pbOffer.getUseMarketBasedPrice(),
@ -667,10 +601,6 @@ public class CoreNetworkProtoResolver implements NetworkProtoResolver {
extraDataMapMap);
}
@NotNull
public static OfferPayload.Direction getDirection(PB.OfferPayload.Direction direction) {
return OfferPayload.Direction.valueOf(direction.name());
}
///////////////////////////////////////////////////////////////////////////////////////////

View File

@ -18,22 +18,26 @@
package io.bisq.core.proto;
import com.google.protobuf.ByteString;
import io.bisq.common.Marshaller;
import io.bisq.common.crypto.PubKeyRing;
import io.bisq.common.locale.CurrencyUtil;
import io.bisq.common.monetary.Price;
import io.bisq.common.persistence.Persistable;
import io.bisq.core.arbitration.Dispute;
import io.bisq.core.filter.PaymentAccountFilter;
import io.bisq.core.payment.PaymentAccount;
import io.bisq.core.payment.PaymentAccountFactory;
import io.bisq.core.payment.payload.BankAccountPayload;
import io.bisq.core.payment.payload.CountryBasedPaymentAccountPayload;
import io.bisq.core.payment.payload.PaymentMethod;
import io.bisq.core.trade.Contract;
import io.bisq.generated.protobuffer.PB;
import io.bisq.network.p2p.NodeAddress;
import org.bitcoinj.core.Coin;
import org.jetbrains.annotations.NotNull;
import java.util.*;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
public class ProtoUtil {
@ -57,10 +61,10 @@ public class ProtoUtil {
Coin.valueOf(contract.getTradeAmount()),
Price.valueOf(getCurrencyCode(contract.getOfferPayload()), contract.getTradePrice()),
contract.getTakerFeeTxId(),
getNodeAddress(contract.getBuyerNodeAddress()),
getNodeAddress(contract.getSellerNodeAddress()),
getNodeAddress(contract.getArbitratorNodeAddress()),
getNodeAddress(contract.getMediatorNodeAddress()),
NodeAddress.fromProto(contract.getBuyerNodeAddress()),
NodeAddress.fromProto(contract.getSellerNodeAddress()),
NodeAddress.fromProto(contract.getArbitratorNodeAddress()),
NodeAddress.fromProto(contract.getMediatorNodeAddress()),
contract.getIsBuyerMakerAndSellerTaker(),
contract.getMakerAccountId(),
contract.getTakerAccountId(),
@ -75,17 +79,13 @@ public class ProtoUtil {
}
@NotNull
static PubKeyRing getPubKeyRing(PB.PubKeyRing pubKeyRing) {
public static PubKeyRing getPubKeyRing(PB.PubKeyRing pubKeyRing) {
return new PubKeyRing(pubKeyRing.getSignaturePubKeyBytes().toByteArray(),
pubKeyRing.getEncryptionPubKeyBytes().toByteArray(),
pubKeyRing.getPgpPubKeyAsPem());
}
static NodeAddress getNodeAddress(PB.NodeAddress protoNode) {
return new NodeAddress(protoNode.getHostName(), protoNode.getPort());
}
static PaymentAccountFilter getPaymentAccountFilter(PB.PaymentAccountFilter accountFilter) {
public static PaymentAccountFilter getPaymentAccountFilter(PB.PaymentAccountFilter accountFilter) {
return new PaymentAccountFilter(accountFilter.getPaymentMethodId(), accountFilter.getGetMethodName(),
accountFilter.getValue());
}
@ -125,4 +125,8 @@ public class ProtoUtil {
CountryBasedPaymentAccountPayload countryBasedPaymentAccountPayload) {
countryBasedPaymentAccountPayload.setCountryCode(protoEntry.getCountryBasedPaymentAccountPayload().getCountryCode());
}
public static PaymentAccount getPaymentAccount(PB.PaymentAccount account) {
return PaymentAccountFactory.getPaymentAccount(PaymentMethod.getPaymentMethodById(account.getPaymentMethod().getId()));
}
}

View File

@ -18,6 +18,7 @@ import lombok.extern.slf4j.Slf4j;
import org.bitcoinj.core.Coin;
import org.bitcoinj.utils.ExchangeRate;
import org.bitcoinj.utils.Fiat;
import org.springframework.util.CollectionUtils;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
@ -184,6 +185,27 @@ public final class TradeStatistics implements LazyProcessedStoragePayload, /*Cap
return PB.StoragePayload.newBuilder().setTradeStatistics(builder).build();
}
public static TradeStatistics fromProto(PB.TradeStatistics tradeStatistics) {
return new TradeStatistics(OfferPayload.Direction.fromProto(tradeStatistics.getDirection()),
tradeStatistics.getBaseCurrency(),
tradeStatistics.getCounterCurrency(),
tradeStatistics.getPaymentMethodId(),
tradeStatistics.getOfferDate(),
tradeStatistics.getUseMarketBasedPrice(),
tradeStatistics.getMarketPriceMargin(),
tradeStatistics.getOfferAmount(),
tradeStatistics.getOfferMinAmount(),
tradeStatistics.getOfferId(),
tradeStatistics.getTradePrice(),
tradeStatistics.getTradeAmount(),
tradeStatistics.getTradeDate(),
tradeStatistics.getDepositTxId(),
new PubKeyRing(tradeStatistics.getPubKeyRing().getSignaturePubKeyBytes().toByteArray(),
tradeStatistics.getPubKeyRing().getEncryptionPubKeyBytes().toByteArray(),
tradeStatistics.getPubKeyRing().getPgpPubKeyAsPem()),
CollectionUtils.isEmpty(tradeStatistics.getExtraDataMapMap()) ?
null : tradeStatistics.getExtraDataMapMap());
}
// We don't include the pubKeyRing as both traders might publish it if the maker uses an old
// version and update later (taker publishes first, then later maker)

View File

@ -4,10 +4,12 @@ import com.google.inject.Inject;
import com.google.inject.name.Named;
import io.bisq.common.locale.CurrencyTuple;
import io.bisq.common.locale.CurrencyUtil;
import io.bisq.common.proto.ProtoHelper;
import io.bisq.common.storage.PlainTextWrapper;
import io.bisq.common.storage.Storage;
import io.bisq.common.util.Utilities;
import io.bisq.core.app.AppOptionKeys;
import io.bisq.generated.protobuffer.PB;
import io.bisq.network.p2p.P2PService;
import io.bisq.network.p2p.peers.PersistedList;
import io.bisq.network.p2p.storage.HashMapChangedListener;
@ -102,8 +104,13 @@ public class TradeStatisticsManager {
tradeStatisticsSet.add(tradeStatistics);
observableTradeStatisticsSet.add(tradeStatistics);
if (storeLocally)
statisticsStorage.queueUpForSave(new PersistedList<TradeStatistics>(tradeStatisticsSet), 2000);
if (storeLocally) {
PersistedList<TradeStatistics> serializable = new PersistedList<>(tradeStatisticsSet);
serializable.setToProto((list) -> PB.DiskEnvelope.newBuilder()
.setTradeStatisticsList(PB.TradeStatisticsList.newBuilder()
.addAllTradeStatistics(ProtoHelper.collectionToProto(list))).build());
statisticsStorage.queueUpForSave(serializable, 2000);
}
dump();
} else {

View File

@ -38,6 +38,8 @@ import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableSet;
import javafx.collections.SetChangeListener;
import lombok.AllArgsConstructor;
import lombok.experimental.Delegate;
import lombok.extern.slf4j.Slf4j;
import javax.annotation.Nullable;
@ -52,50 +54,32 @@ import java.util.stream.Collectors;
* It must never be transmitted over the wire (messageKeyPair contains private key!).
*/
@Slf4j
@AllArgsConstructor
public final class User implements Persistable {
// That object is saved to disc. We need to take care of changes to not break deserialization.
private static final long serialVersionUID = Version.LOCAL_DB_VERSION;
// persisted fields
private UserVO userVO = new UserVO();
// Transient immutable fields
transient final private Storage<User> storage;
transient final private Storage<UserVO> storage;
transient private Set<TradeCurrency> tradeCurrenciesInPaymentAccounts;
// Persisted fields
private String accountID;
private Set<PaymentAccount> paymentAccounts = new HashSet<>();
private PaymentAccount currentPaymentAccount;
private List<String> acceptedLanguageLocaleCodes = new ArrayList<>();
@Nullable
private Alert developersAlert;
@Nullable
private Alert displayedAlert;
@Nullable
private Filter developersFilter;
@Nullable
private Arbitrator registeredArbitrator;
@Nullable
private Mediator registeredMediator;
private List<Arbitrator> acceptedArbitrators = new ArrayList<>();
private List<Mediator> acceptedMediators = new ArrayList<>();
// Observable wrappers
transient final private ObservableSet<PaymentAccount> paymentAccountsAsObservable = FXCollections.observableSet(paymentAccounts);
transient final private ObjectProperty<PaymentAccount> currentPaymentAccountProperty = new SimpleObjectProperty<>(currentPaymentAccount);
transient final private ObservableSet<PaymentAccount> paymentAccountsAsObservable = FXCollections.observableSet(userVO.getPaymentAccounts());
transient final private ObjectProperty<PaymentAccount> currentPaymentAccountProperty = new SimpleObjectProperty<>(userVO.getCurrentPaymentAccount());
@Inject
public User(Storage<User> storage, KeyRing keyRing) throws NoSuchAlgorithmException {
public User(Storage<UserVO> storage, KeyRing keyRing) throws NoSuchAlgorithmException {
this.storage = storage;
accountID = String.valueOf(Math.abs(keyRing.getPubKeyRing().hashCode()));
acceptedLanguageLocaleCodes.add(LanguageUtil.getDefaultLanguageLocaleAsCode());
userVO.setAccountID(String.valueOf(Math.abs(keyRing.getPubKeyRing().hashCode())));
// language setup
userVO.getAcceptedLanguageLocaleCodes().add(LanguageUtil.getDefaultLanguageLocaleAsCode());
String english = LanguageUtil.getEnglishLanguageLocaleCode();
if (!acceptedLanguageLocaleCodes.contains(english))
acceptedLanguageLocaleCodes.add(english);
acceptedArbitrators = new ArrayList<>();
acceptedMediators = new ArrayList<>();
if (!userVO.getAcceptedLanguageLocaleCodes().contains(english))
userVO.getAcceptedLanguageLocaleCodes().add(english);
}
// for unit tests
@ -103,48 +87,27 @@ public final class User implements Persistable {
this.storage = null;
}
public void init() {
User persisted = storage.initAndGetPersisted(this);
UserVO persisted = storage.initAndGetPersisted(userVO);
if (persisted != null) {
accountID = persisted.getAccountId();
// The check is only needed to not break old versions where paymentAccounts was not included and is null,
// Can be removed later
if (persisted.getPaymentAccounts() != null)
paymentAccounts = new HashSet<>(persisted.getPaymentAccounts());
paymentAccountsAsObservable.addAll(paymentAccounts);
currentPaymentAccount = persisted.getCurrentPaymentAccount();
currentPaymentAccountProperty.set(currentPaymentAccount);
acceptedLanguageLocaleCodes = persisted.getAcceptedLanguageLocaleCodes();
if (persisted.getAcceptedArbitrators() != null)
acceptedArbitrators = persisted.getAcceptedArbitrators();
if (persisted.getAcceptedMediators() != null)
acceptedMediators = persisted.getAcceptedMediators();
registeredArbitrator = persisted.getRegisteredArbitrator();
registeredMediator = persisted.getRegisteredMediator();
developersAlert = persisted.getDevelopersAlert();
displayedAlert = persisted.getDisplayedAlert();
developersFilter = persisted.getDevelopersFilter();
userVO = persisted;
paymentAccountsAsObservable.addAll(userVO.getPaymentAccounts());
currentPaymentAccountProperty.set(userVO.getCurrentPaymentAccount());
}
storage.queueUpForSave();
// Use that to guarantee update of the serializable field and to make a storage update in case of a change
paymentAccountsAsObservable.addListener((SetChangeListener<PaymentAccount>) change -> {
paymentAccounts = new HashSet<>(paymentAccountsAsObservable);
tradeCurrenciesInPaymentAccounts = paymentAccounts.stream().flatMap(e -> e.getTradeCurrencies().stream()).collect(Collectors.toSet());
userVO.setPaymentAccounts(new HashSet<>(paymentAccountsAsObservable));
tradeCurrenciesInPaymentAccounts = userVO.getPaymentAccounts().stream().flatMap(e -> e.getTradeCurrencies().stream()).collect(Collectors.toSet());
storage.queueUpForSave();
});
currentPaymentAccountProperty.addListener((ov) -> {
currentPaymentAccount = currentPaymentAccountProperty.get();
userVO.setCurrentPaymentAccount(currentPaymentAccountProperty.get());
storage.queueUpForSave();
});
tradeCurrenciesInPaymentAccounts = paymentAccounts.stream().flatMap(e -> e.getTradeCurrencies().stream()).collect(Collectors.toSet());
tradeCurrenciesInPaymentAccounts = userVO.getPaymentAccounts().stream().flatMap(e -> e.getTradeCurrencies().stream()).collect(Collectors.toSet());
}
///////////////////////////////////////////////////////////////////////////////////////////
@ -165,8 +128,8 @@ public final class User implements Persistable {
}
public boolean addAcceptedLanguageLocale(String localeCode) {
if (!acceptedLanguageLocaleCodes.contains(localeCode)) {
boolean changed = acceptedLanguageLocaleCodes.add(localeCode);
if (!userVO.getAcceptedLanguageLocaleCodes().contains(localeCode)) {
boolean changed = userVO.getAcceptedLanguageLocaleCodes().add(localeCode);
if (changed)
storage.queueUpForSave();
return changed;
@ -176,70 +139,70 @@ public final class User implements Persistable {
}
public boolean removeAcceptedLanguageLocale(String languageLocaleCode) {
boolean changed = acceptedLanguageLocaleCodes.remove(languageLocaleCode);
boolean changed = userVO.getAcceptedLanguageLocaleCodes().remove(languageLocaleCode);
if (changed)
storage.queueUpForSave();
return changed;
}
public void addAcceptedArbitrator(Arbitrator arbitrator) {
if (!acceptedArbitrators.contains(arbitrator) && !isMyOwnRegisteredArbitrator(arbitrator)) {
boolean changed = acceptedArbitrators.add(arbitrator);
if (!userVO.getAcceptedArbitrators().contains(arbitrator) && !isMyOwnRegisteredArbitrator(arbitrator)) {
boolean changed = userVO.getAcceptedArbitrators().add(arbitrator);
if (changed)
storage.queueUpForSave();
}
}
public void addAcceptedMediator(Mediator mediator) {
if (!acceptedMediators.contains(mediator) && !isMyOwnRegisteredMediator(mediator)) {
boolean changed = acceptedMediators.add(mediator);
if (!userVO.getAcceptedMediators().contains(mediator) && !isMyOwnRegisteredMediator(mediator)) {
boolean changed = userVO.getAcceptedMediators().add(mediator);
if (changed)
storage.queueUpForSave();
}
}
public boolean isMyOwnRegisteredArbitrator(Arbitrator arbitrator) {
return arbitrator.equals(registeredArbitrator);
return arbitrator.equals(userVO.getRegisteredArbitrator());
}
public boolean isMyOwnRegisteredMediator(Mediator mediator) {
return mediator.equals(registeredMediator);
return mediator.equals(userVO.getRegisteredArbitrator());
}
public void removeAcceptedArbitrator(Arbitrator arbitrator) {
boolean changed = acceptedArbitrators.remove(arbitrator);
boolean changed = userVO.getAcceptedArbitrators().remove(arbitrator);
if (changed)
storage.queueUpForSave();
}
public void clearAcceptedArbitrators() {
acceptedArbitrators.clear();
userVO.getAcceptedArbitrators().clear();
storage.queueUpForSave();
}
public void removeAcceptedMediator(Mediator mediator) {
boolean changed = acceptedMediators.remove(mediator);
boolean changed = userVO.getAcceptedMediators().remove(mediator);
if (changed)
storage.queueUpForSave();
}
public void clearAcceptedMediators() {
acceptedMediators.clear();
userVO.getAcceptedMediators().clear();
storage.queueUpForSave();
}
public void setRegisteredArbitrator(@Nullable Arbitrator arbitrator) {
this.registeredArbitrator = arbitrator;
userVO.setRegisteredArbitrator(arbitrator);
storage.queueUpForSave();
}
public void setRegisteredMediator(@Nullable Mediator mediator) {
this.registeredMediator = mediator;
userVO.setRegisteredMediator(mediator);
storage.queueUpForSave();
}
public void setDevelopersFilter(@Nullable Filter developersFilter) {
this.developersFilter = developersFilter;
userVO.setDevelopersFilter(developersFilter);
storage.queueUpForSave();
}
@ -250,7 +213,7 @@ public final class User implements Persistable {
@Nullable
public PaymentAccount getPaymentAccount(String paymentAccountId) {
Optional<PaymentAccount> optional = paymentAccounts.stream().filter(e -> e.getId().equals(paymentAccountId)).findAny();
Optional<PaymentAccount> optional = userVO.getPaymentAccounts().stream().filter(e -> e.getId().equals(paymentAccountId)).findAny();
if (optional.isPresent())
return optional.get();
else
@ -258,7 +221,7 @@ public final class User implements Persistable {
}
public String getAccountId() {
return accountID;
return userVO.getAccountID();
}
/* public boolean isRegistered() {
@ -266,7 +229,7 @@ public final class User implements Persistable {
}*/
private PaymentAccount getCurrentPaymentAccount() {
return currentPaymentAccount;
return userVO.getCurrentPaymentAccount();
}
public ObjectProperty<PaymentAccount> currentPaymentAccountProperty() {
@ -274,7 +237,7 @@ public final class User implements Persistable {
}
public Set<PaymentAccount> getPaymentAccounts() {
return paymentAccounts;
return userVO.getPaymentAccounts();
}
public ObservableSet<PaymentAccount> getPaymentAccountsAsObservable() {
@ -283,36 +246,36 @@ public final class User implements Persistable {
@Nullable
public Arbitrator getRegisteredArbitrator() {
return registeredArbitrator;
return userVO.getRegisteredArbitrator();
}
@Nullable
public Mediator getRegisteredMediator() {
return registeredMediator;
return userVO.getRegisteredMediator();
}
public List<Arbitrator> getAcceptedArbitrators() {
return acceptedArbitrators;
return userVO.getAcceptedArbitrators();
}
public List<NodeAddress> getAcceptedArbitratorAddresses() {
return acceptedArbitrators.stream().map(Arbitrator::getNodeAddress).collect(Collectors.toList());
return userVO.getAcceptedArbitrators().stream().map(Arbitrator::getNodeAddress).collect(Collectors.toList());
}
public List<Mediator> getAcceptedMediators() {
return acceptedMediators;
return userVO.getAcceptedMediators();
}
public List<NodeAddress> getAcceptedMediatorAddresses() {
return acceptedMediators.stream().map(Mediator::getNodeAddress).collect(Collectors.toList());
return userVO.getAcceptedMediators().stream().map(Mediator::getNodeAddress).collect(Collectors.toList());
}
public List<String> getAcceptedLanguageLocaleCodes() {
return acceptedLanguageLocaleCodes != null ? acceptedLanguageLocaleCodes : new ArrayList<>();
return userVO.getAcceptedLanguageLocaleCodes() != null ? userVO.getAcceptedLanguageLocaleCodes() : new ArrayList<>();
}
public Arbitrator getAcceptedArbitratorByAddress(NodeAddress nodeAddress) {
Optional<Arbitrator> arbitratorOptional = acceptedArbitrators.stream()
Optional<Arbitrator> arbitratorOptional = userVO.getAcceptedArbitrators().stream()
.filter(e -> e.getNodeAddress().equals(nodeAddress))
.findFirst();
if (arbitratorOptional.isPresent())
@ -322,7 +285,7 @@ public final class User implements Persistable {
}
public Mediator getAcceptedMediatorByAddress(NodeAddress nodeAddress) {
Optional<Mediator> mediatorOptionalOptional = acceptedMediators.stream()
Optional<Mediator> mediatorOptionalOptional = userVO.getAcceptedMediators().stream()
.filter(e -> e.getNodeAddress().equals(nodeAddress))
.findFirst();
if (mediatorOptionalOptional.isPresent())
@ -333,7 +296,7 @@ public final class User implements Persistable {
@Nullable
public Filter getDevelopersFilter() {
return developersFilter;
return userVO.getDevelopersFilter();
}
@ -350,7 +313,7 @@ public final class User implements Persistable {
@Nullable
public PaymentAccount findFirstPaymentAccountWithCurrency(TradeCurrency tradeCurrency) {
for (PaymentAccount paymentAccount : paymentAccounts) {
for (PaymentAccount paymentAccount : userVO.getPaymentAccounts()) {
for (TradeCurrency tradeCurrency1 : paymentAccount.getTradeCurrencies()) {
if (tradeCurrency1.equals(tradeCurrency))
return paymentAccount;
@ -361,7 +324,7 @@ public final class User implements Persistable {
public boolean hasMatchingLanguage(Arbitrator arbitrator) {
if (arbitrator != null) {
for (String acceptedCode : acceptedLanguageLocaleCodes) {
for (String acceptedCode : userVO.getAcceptedLanguageLocaleCodes()) {
for (String itemCode : arbitrator.getLanguageCodes()) {
if (acceptedCode.equals(itemCode))
return true;
@ -376,43 +339,27 @@ public final class User implements Persistable {
}
public void setDevelopersAlert(@Nullable Alert developersAlert) {
this.developersAlert = developersAlert;
userVO.setDevelopersAlert(developersAlert);
storage.queueUpForSave();
}
@Nullable
public Alert getDevelopersAlert() {
return developersAlert;
return userVO.getDevelopersAlert();
}
public void setDisplayedAlert(@Nullable Alert displayedAlert) {
this.displayedAlert = displayedAlert;
userVO.setDisplayedAlert(displayedAlert);
storage.queueUpForSave();
}
@Nullable
public Alert getDisplayedAlert() {
return displayedAlert;
return userVO.getDisplayedAlert();
}
@Override
public Message toProto() {
PB.User.Builder builder = PB.User.newBuilder()
.setAccountId(accountID)
.addAllPaymentAccounts(ProtoHelper.collectionToProto(paymentAccounts))
.setCurrentPaymentAccount(currentPaymentAccount.toProto())
.addAllAcceptedLanguageLocaleCodes(acceptedLanguageLocaleCodes)
.addAllAcceptedArbitrators(ProtoHelper.collectionToProto(acceptedArbitrators));
Optional.ofNullable(developersAlert)
.ifPresent(developersAlert -> builder.setDevelopersAlert(developersAlert.toProto().getAlert()));
Optional.ofNullable(displayedAlert)
.ifPresent(displayedAlert -> builder.setDisplayedAlert(displayedAlert.toProto().getAlert()));
Optional.ofNullable(developersFilter)
.ifPresent(developersFilter -> builder.setDevelopersFilter(developersFilter.toProto().getFilter()));
Optional.ofNullable(registeredArbitrator)
.ifPresent(registeredArbitrator -> builder.setRegisteredArbitrator(registeredArbitrator.toProto().getArbitrator()));
Optional.ofNullable(registeredMediator)
.ifPresent(developersAlert -> builder.setDevelopersAlert(developersAlert.toProto().getAlert()));
return PB.DiskEnvelope.newBuilder().setUser(builder).build();
return userVO.toProto();
}
}

View File

@ -0,0 +1,105 @@
/*
* 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 io.bisq.core.user;
import com.google.protobuf.Message;
import io.bisq.common.persistence.Persistable;
import io.bisq.common.proto.ProtoHelper;
import io.bisq.core.alert.Alert;
import io.bisq.core.arbitration.Arbitrator;
import io.bisq.core.arbitration.Mediator;
import io.bisq.core.filter.Filter;
import io.bisq.core.payment.PaymentAccount;
import io.bisq.core.proto.ProtoUtil;
import io.bisq.generated.protobuffer.PB;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import javax.annotation.Nullable;
import javax.print.attribute.standard.Media;
import java.util.*;
import java.util.stream.Collectors;
@Slf4j
@Data
@AllArgsConstructor
public class UserVO implements Persistable {
// Persisted fields
private String accountID;
private Set<PaymentAccount> paymentAccounts = new HashSet<>();
private PaymentAccount currentPaymentAccount;
private List<String> acceptedLanguageLocaleCodes = new ArrayList<>();
@Nullable
private Alert developersAlert;
@Nullable
private Alert displayedAlert;
@Nullable
private Filter developersFilter;
@Nullable
private Arbitrator registeredArbitrator;
@Nullable
private Mediator registeredMediator;
private List<Arbitrator> acceptedArbitrators = new ArrayList<>();
private List<Mediator> acceptedMediators = new ArrayList<>();
public UserVO() {
}
@Override
public Message toProto() {
PB.User.Builder builder = PB.User.newBuilder()
.setAccountId(accountID)
.addAllPaymentAccounts(ProtoHelper.collectionToProto(paymentAccounts))
.setCurrentPaymentAccount(currentPaymentAccount.toProto())
.addAllAcceptedLanguageLocaleCodes(acceptedLanguageLocaleCodes)
.addAllAcceptedArbitrators(ProtoHelper.collectionToProto(acceptedArbitrators))
.addAllAcceptedMediators(ProtoHelper.collectionToProto(acceptedMediators));
Optional.ofNullable(developersAlert)
.ifPresent(developersAlert -> builder.setDevelopersAlert(developersAlert.toProto().getAlert()));
Optional.ofNullable(displayedAlert)
.ifPresent(displayedAlert -> builder.setDisplayedAlert(displayedAlert.toProto().getAlert()));
Optional.ofNullable(developersFilter)
.ifPresent(developersFilter -> builder.setDevelopersFilter(developersFilter.toProto().getFilter()));
Optional.ofNullable(registeredArbitrator)
.ifPresent(registeredArbitrator -> builder.setRegisteredArbitrator(registeredArbitrator.toProto().getArbitrator()));
Optional.ofNullable(registeredMediator)
.ifPresent(developersAlert -> builder.setDevelopersAlert(developersAlert.toProto().getAlert()));
return PB.DiskEnvelope.newBuilder().setUser(builder).build();
}
public static UserVO fromProto(PB.User user) {
Set<PaymentAccount> collect = user.getPaymentAccountsList().stream().map(paymentAccount -> ProtoUtil.getPaymentAccount(paymentAccount)).collect(Collectors.toSet());
UserVO vo = new UserVO(user.getAccountId(),
collect,
ProtoUtil.getPaymentAccount(user.getCurrentPaymentAccount()),
user.getAcceptedLanguageLocaleCodesList(),
Alert.fromProto(user.getDevelopersAlert()),
Alert.fromProto(user.getDisplayedAlert()),
Filter.fromProto(user.getDevelopersFilter()),
Arbitrator.fromProto(user.getRegisteredArbitrator()),
Mediator.fromProto(user.getRegisteredMediator()),
user.getAcceptedArbitratorsList().stream().map(Arbitrator::fromProto).collect(Collectors.toList()),
user.getAcceptedMediatorsList().stream().map(Mediator::fromProto).collect(Collectors.toList())
);
return vo;
}
}

View File

@ -56,6 +56,10 @@ public final class NodeAddress implements Persistable, Payload {
return PB.NodeAddress.newBuilder().setHostName(hostName).setPort(port).build();
}
public static NodeAddress fromProto(PB.NodeAddress nodeAddress){
return new NodeAddress(nodeAddress.getHostName(), nodeAddress.getPort());
}
@Override
public String toString() {
return getFullAddress();

View File

@ -1,11 +1,14 @@
package io.bisq.network.p2p.peers;
import io.bisq.common.Clock;
import io.bisq.common.Marshaller;
import io.bisq.common.Timer;
import io.bisq.common.UserThread;
import io.bisq.common.app.Log;
import io.bisq.common.proto.PersistenceProtoResolver;
import io.bisq.common.proto.ProtoHelper;
import io.bisq.common.storage.Storage;
import io.bisq.generated.protobuffer.PB;
import io.bisq.network.p2p.NodeAddress;
import io.bisq.network.p2p.network.*;
import io.bisq.network.p2p.peers.peerexchange.Peer;
@ -96,7 +99,7 @@ public class PeerManager implements ConnectionListener {
this.seedNodeAddresses = new HashSet<>(seedNodeAddresses);
networkNode.addConnectionListener(this);
dbStorage = new Storage<>(storageDir, persistenceProtoResolver);
PersistedList persistedList = dbStorage.initAndGetPersistedWithFileName("PersistedList");
PersistedList persistedList = dbStorage.initAndGetPersistedWithFileName("PersistedPeers");
if (persistedList != null) {
log.debug("We have persisted reported list. persistedList.size()=" + persistedList.getList().size());
this.persistedPeers.addAll(persistedList.getList());
@ -456,6 +459,9 @@ public class PeerManager implements ConnectionListener {
if (dbStorage != null) {
PersistedList serializable = new PersistedList(persistedPeers);
serializable.setToProto((list) -> PB.DiskEnvelope.newBuilder()
.setPeersList(PB.PeersList.newBuilder()
.addAllPeers(ProtoHelper.collectionToProto((Collection<? extends Marshaller>) list))));
dbStorage.queueUpForSave(serializable, 2000);
}

View File

@ -20,30 +20,38 @@ package io.bisq.network.p2p.peers;
import com.google.protobuf.Message;
import io.bisq.common.Marshaller;
import io.bisq.common.persistence.Persistable;
import io.bisq.common.proto.ProtoHelper;
import io.bisq.generated.protobuffer.PB;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import sun.reflect.generics.reflectiveObjects.NotImplementedException;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;
@AllArgsConstructor
public class PersistedList<T extends Marshaller> implements Persistable {
@Getter
@Setter
private List<T> list;
@Setter
private Function<List<T>, Message> toProto;
public PersistedList(List<T> list) {
this.list = list;
}
/** convenience ctor */
public PersistedList(HashSet<T> set) {
this.list = set.stream().collect(Collectors.toList());
this(set.stream().collect(Collectors.toList()));
}
@Override
public Message toProto() {
return PB.DiskEnvelope.newBuilder().setPersistedPeers(
PB.PersistedPeers.newBuilder().addAllPeers(ProtoHelper.collectionToProto(list))).build();
if(Objects.isNull(toProto())) {
throw new NotImplementedException();
}
return toProto.apply(list);
}
}

View File

@ -8,6 +8,7 @@ import io.bisq.network.p2p.NodeAddress;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
import java.time.Instant;
import java.util.Date;
@ToString
@ -25,8 +26,12 @@ public final class Peer implements Payload, Persistable {
transient private int failedConnectionAttempts = 0;
public Peer(NodeAddress nodeAddress) {
this(nodeAddress, new Date());
}
public Peer(NodeAddress nodeAddress, Date date) {
this.nodeAddress = nodeAddress;
this.date = new Date();
this.date = date;
}
public void increaseFailedConnectionAttempts() {
@ -59,4 +64,8 @@ public final class Peer implements Payload, Persistable {
return PB.Peer.newBuilder().setNodeAddress(nodeAddress.toProto())
.setDate(date.getTime()).build();
}
public static Peer fromProto(PB.Peer peer) {
return new Peer(NodeAddress.fromProto(peer.getNodeAddress()), Date.from(Instant.ofEpochMilli(peer.getDate())));
}
}