diff --git a/common/src/main/java/io/bitsquare/common/crypto/PubKeyRing.java b/common/src/main/java/io/bitsquare/common/crypto/PubKeyRing.java index f09b04142b..efcdd33acb 100644 --- a/common/src/main/java/io/bitsquare/common/crypto/PubKeyRing.java +++ b/common/src/main/java/io/bitsquare/common/crypto/PubKeyRing.java @@ -41,16 +41,14 @@ public final class PubKeyRing implements Payload { private static final Logger log = LoggerFactory.getLogger(PubKeyRing.class); - private final byte[] signaturePubKeyBytes; - private final byte[] encryptionPubKeyBytes; - transient private PublicKey signaturePubKey; + private final byte[] signaturePubKeyBytes; transient private PublicKey encryptionPubKey; + private final byte[] encryptionPubKeyBytes; public PubKeyRing(PublicKey signaturePubKey, PublicKey encryptionPubKey) { this.signaturePubKey = signaturePubKey; this.encryptionPubKey = encryptionPubKey; - this.signaturePubKeyBytes = new X509EncodedKeySpec(signaturePubKey.getEncoded()).getEncoded(); this.encryptionPubKeyBytes = new X509EncodedKeySpec(encryptionPubKey.getEncoded()).getEncoded(); } diff --git a/common/src/main/java/io/bitsquare/common/crypto/SealedAndSigned.java b/common/src/main/java/io/bitsquare/common/crypto/SealedAndSigned.java index fb6f7abb43..1515a081f1 100644 --- a/common/src/main/java/io/bitsquare/common/crypto/SealedAndSigned.java +++ b/common/src/main/java/io/bitsquare/common/crypto/SealedAndSigned.java @@ -19,24 +19,42 @@ package io.bitsquare.common.crypto; import io.bitsquare.app.Version; import io.bitsquare.common.wire.Payload; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.IOException; +import java.security.KeyFactory; import java.security.PublicKey; +import java.security.spec.X509EncodedKeySpec; import java.util.Arrays; public final class SealedAndSigned implements Payload { // That object is sent over the wire, so we need to take care of version compatibility. private static final long serialVersionUID = Version.P2P_NETWORK_VERSION; + private static final Logger log = LoggerFactory.getLogger(SealedAndSigned.class); public final byte[] encryptedSecretKey; public final byte[] encryptedPayloadWithHmac; public final byte[] signature; - public final PublicKey sigPublicKey; + public transient PublicKey sigPublicKey; + private final byte[] sigPublicKeyBytes; public SealedAndSigned(byte[] encryptedSecretKey, byte[] encryptedPayloadWithHmac, byte[] signature, PublicKey sigPublicKey) { this.encryptedSecretKey = encryptedSecretKey; this.encryptedPayloadWithHmac = encryptedPayloadWithHmac; this.signature = signature; this.sigPublicKey = sigPublicKey; + this.sigPublicKeyBytes = new X509EncodedKeySpec(this.sigPublicKey.getEncoded()).getEncoded(); + } + + private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { + try { + in.defaultReadObject(); + sigPublicKey = KeyFactory.getInstance(Sig.KEY_ALGO, "BC").generatePublic(new X509EncodedKeySpec(sigPublicKeyBytes)); + } catch (Throwable t) { + log.error("Exception at readObject: " + t.getMessage()); + t.printStackTrace(); + } } @Override diff --git a/common/src/main/java/io/bitsquare/storage/FileManager.java b/common/src/main/java/io/bitsquare/storage/FileManager.java index 4dddbd973f..f39cc931dd 100644 --- a/common/src/main/java/io/bitsquare/storage/FileManager.java +++ b/common/src/main/java/io/bitsquare/storage/FileManager.java @@ -197,7 +197,6 @@ public class FileManager { fileOutputStream = new FileOutputStream(tempFile); objectOutputStream = new ObjectOutputStream(fileOutputStream); - // TODO ConcurrentModificationException happens sometimes at that line objectOutputStream.writeObject(serializable); // Attempt to force the bits to hit the disk. In reality the OS or hard disk itself may still decide // to not write through to physical media for at least a few seconds, but this is the best we can do. diff --git a/core/src/main/java/io/bitsquare/alert/Alert.java b/core/src/main/java/io/bitsquare/alert/Alert.java index 0aa3b8ba8c..bb1a615d19 100644 --- a/core/src/main/java/io/bitsquare/alert/Alert.java +++ b/core/src/main/java/io/bitsquare/alert/Alert.java @@ -18,30 +18,48 @@ package io.bitsquare.alert; import io.bitsquare.app.Version; -import io.bitsquare.p2p.storage.data.StoragePayload; +import io.bitsquare.common.crypto.Sig; +import io.bitsquare.p2p.storage.payload.StoragePayload; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.IOException; +import java.security.KeyFactory; import java.security.PublicKey; +import java.security.spec.X509EncodedKeySpec; import java.util.concurrent.TimeUnit; public final class Alert implements StoragePayload { // That object is sent over the wire, so we need to take care of version compatibility. private static final long serialVersionUID = Version.P2P_NETWORK_VERSION; - + private static final Logger log = LoggerFactory.getLogger(Alert.class); private static final long TTL = TimeUnit.DAYS.toMillis(10); public final String message; public final boolean isUpdateInfo; private String signatureAsBase64; - private PublicKey storagePublicKey; + private transient PublicKey storagePublicKey; + private byte[] storagePublicKeyBytes; public Alert(String message, boolean isUpdateInfo) { this.message = message; this.isUpdateInfo = isUpdateInfo; } + private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { + try { + in.defaultReadObject(); + storagePublicKey = KeyFactory.getInstance(Sig.KEY_ALGO, "BC").generatePublic(new X509EncodedKeySpec(storagePublicKeyBytes)); + } catch (Throwable t) { + log.error("Exception at readObject: " + t.getMessage()); + t.printStackTrace(); + } + } + public void setSigAndStoragePubKey(String signatureAsBase64, PublicKey storagePublicKey) { this.signatureAsBase64 = signatureAsBase64; this.storagePublicKey = storagePublicKey; + this.storagePublicKeyBytes = new X509EncodedKeySpec(this.storagePublicKey.getEncoded()).getEncoded(); } public String getSignatureAsBase64() { diff --git a/core/src/main/java/io/bitsquare/alert/AlertManager.java b/core/src/main/java/io/bitsquare/alert/AlertManager.java index 1280f93130..fd854559fe 100644 --- a/core/src/main/java/io/bitsquare/alert/AlertManager.java +++ b/core/src/main/java/io/bitsquare/alert/AlertManager.java @@ -20,7 +20,7 @@ package io.bitsquare.alert; import com.google.inject.Inject; import io.bitsquare.common.crypto.KeyRing; import io.bitsquare.p2p.storage.HashMapChangedListener; -import io.bitsquare.p2p.storage.data.ProtectedData; +import io.bitsquare.p2p.storage.storageentry.ProtectedStorageEntry; import io.bitsquare.user.User; import javafx.beans.property.ObjectProperty; import javafx.beans.property.ReadOnlyObjectProperty; @@ -60,18 +60,18 @@ public class AlertManager { alertService.addHashSetChangedListener(new HashMapChangedListener() { @Override - public void onAdded(ProtectedData data) { - if (data.expirablePayload instanceof Alert) { - Alert alert = (Alert) data.expirablePayload; + public void onAdded(ProtectedStorageEntry data) { + if (data.getStoragePayload() instanceof Alert) { + Alert alert = (Alert) data.getStoragePayload(); if (verifySignature(alert)) alertMessageProperty.set(alert); } } @Override - public void onRemoved(ProtectedData data) { - if (data.expirablePayload instanceof Alert) { - Alert alert = (Alert) data.expirablePayload; + public void onRemoved(ProtectedStorageEntry data) { + if (data.getStoragePayload() instanceof Alert) { + Alert alert = (Alert) data.getStoragePayload(); if (verifySignature(alert)) alertMessageProperty.set(null); } diff --git a/core/src/main/java/io/bitsquare/arbitration/Arbitrator.java b/core/src/main/java/io/bitsquare/arbitration/Arbitrator.java index eb4014ee73..6680eeedef 100644 --- a/core/src/main/java/io/bitsquare/arbitration/Arbitrator.java +++ b/core/src/main/java/io/bitsquare/arbitration/Arbitrator.java @@ -20,9 +20,10 @@ package io.bitsquare.arbitration; import io.bitsquare.app.Version; import io.bitsquare.common.crypto.PubKeyRing; import io.bitsquare.p2p.NodeAddress; -import io.bitsquare.p2p.storage.data.StoragePayload; +import io.bitsquare.p2p.storage.payload.StoragePayload; import java.security.PublicKey; +import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.List; @@ -38,7 +39,7 @@ public final class Arbitrator implements StoragePayload { private final byte[] btcPubKey; private final PubKeyRing pubKeyRing; private final NodeAddress arbitratorNodeAddress; - private final List languageCodes; + private final ArrayList languageCodes; private final String btcAddress; private final long registrationDate; private final String registrationSignature; @@ -48,7 +49,7 @@ public final class Arbitrator implements StoragePayload { byte[] btcPubKey, String btcAddress, PubKeyRing pubKeyRing, - List languageCodes, + ArrayList languageCodes, Date registrationDate, byte[] registrationPubKey, String registrationSignature) { diff --git a/core/src/main/java/io/bitsquare/arbitration/ArbitratorManager.java b/core/src/main/java/io/bitsquare/arbitration/ArbitratorManager.java index 3d056643b3..25c992e0e0 100644 --- a/core/src/main/java/io/bitsquare/arbitration/ArbitratorManager.java +++ b/core/src/main/java/io/bitsquare/arbitration/ArbitratorManager.java @@ -29,7 +29,7 @@ import io.bitsquare.p2p.BootstrapListener; import io.bitsquare.p2p.NodeAddress; import io.bitsquare.p2p.P2PService; import io.bitsquare.p2p.storage.HashMapChangedListener; -import io.bitsquare.p2p.storage.data.ProtectedData; +import io.bitsquare.p2p.storage.storageentry.ProtectedStorageEntry; import io.bitsquare.user.User; import javafx.collections.FXCollections; import javafx.collections.ObservableMap; @@ -117,12 +117,12 @@ public class ArbitratorManager { arbitratorService.addHashSetChangedListener(new HashMapChangedListener() { @Override - public void onAdded(ProtectedData data) { + public void onAdded(ProtectedStorageEntry data) { applyArbitrators(); } @Override - public void onRemoved(ProtectedData data) { + public void onRemoved(ProtectedStorageEntry data) { applyArbitrators(); } }); diff --git a/core/src/main/java/io/bitsquare/arbitration/ArbitratorService.java b/core/src/main/java/io/bitsquare/arbitration/ArbitratorService.java index ab2388bfde..e99d9f3d81 100644 --- a/core/src/main/java/io/bitsquare/arbitration/ArbitratorService.java +++ b/core/src/main/java/io/bitsquare/arbitration/ArbitratorService.java @@ -84,8 +84,8 @@ public class ArbitratorService { public Map getArbitrators() { Set arbitratorSet = p2PService.getDataMap().values().stream() - .filter(data -> data.expirablePayload instanceof Arbitrator) - .map(data -> (Arbitrator) data.expirablePayload) + .filter(data -> data.getStoragePayload() instanceof Arbitrator) + .map(data -> (Arbitrator) data.getStoragePayload()) .collect(Collectors.toSet()); Map map = new HashMap<>(); diff --git a/core/src/main/java/io/bitsquare/arbitration/Dispute.java b/core/src/main/java/io/bitsquare/arbitration/Dispute.java index 50706fa41c..3dd6bd8189 100644 --- a/core/src/main/java/io/bitsquare/arbitration/Dispute.java +++ b/core/src/main/java/io/bitsquare/arbitration/Dispute.java @@ -26,7 +26,6 @@ import io.bitsquare.trade.Contract; import javafx.beans.property.*; import javafx.collections.FXCollections; import javafx.collections.ObservableList; -import org.bitcoinj.core.Transaction; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -36,7 +35,6 @@ import java.io.ObjectInputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; -import java.util.List; public final class Dispute implements Payload { // That object is sent over the wire, so we need to take care of version compatibility. @@ -71,11 +69,12 @@ public final class Dispute implements Payload { private final PubKeyRing arbitratorPubKeyRing; private final boolean isSupportTicket; - private final List disputeCommunicationMessages = new ArrayList<>(); + private final ArrayList disputeCommunicationMessages = new ArrayList<>(); private boolean isClosed; private DisputeResult disputeResult; - private Transaction disputePayoutTx; + @Nullable + private String disputePayoutTxId; transient private Storage> storage; transient private ObservableList disputeCommunicationMessagesAsObservableList = FXCollections.observableArrayList(disputeCommunicationMessages); @@ -171,8 +170,8 @@ public final class Dispute implements Payload { storage.queueUpForSave(); } - public void setDisputePayoutTx(Transaction disputePayoutTx) { - this.disputePayoutTx = disputePayoutTx; + public void setDisputePayoutTxId(String disputePayoutTxId) { + this.disputePayoutTxId = disputePayoutTxId; } @@ -280,8 +279,8 @@ public final class Dispute implements Payload { return new Date(tradeDate); } - public Transaction getDisputePayoutTx() { - return disputePayoutTx; + public String getDisputePayoutTxId() { + return disputePayoutTxId; } @Override @@ -299,6 +298,7 @@ public final class Dispute implements Payload { if (isSupportTicket != dispute.isSupportTicket) return false; if (isClosed != dispute.isClosed) return false; if (tradeId != null ? !tradeId.equals(dispute.tradeId) : dispute.tradeId != null) return false; + if (id != null ? !id.equals(dispute.id) : dispute.id != null) return false; if (traderPubKeyRing != null ? !traderPubKeyRing.equals(dispute.traderPubKeyRing) : dispute.traderPubKeyRing != null) return false; if (contract != null ? !contract.equals(dispute.contract) : dispute.contract != null) return false; @@ -317,13 +317,18 @@ public final class Dispute implements Payload { return false; if (disputeCommunicationMessages != null ? !disputeCommunicationMessages.equals(dispute.disputeCommunicationMessages) : dispute.disputeCommunicationMessages != null) return false; - return !(disputeResult != null ? !disputeResult.equals(dispute.disputeResult) : dispute.disputeResult != null); + if (disputeResult != null ? !disputeResult.equals(dispute.disputeResult) : dispute.disputeResult != null) + return false; + if (disputePayoutTxId != null ? !disputePayoutTxId.equals(dispute.disputePayoutTxId) : dispute.disputePayoutTxId != null) + return false; + return !(storage != null ? !storage.equals(dispute.storage) : dispute.storage != null); } @Override public int hashCode() { int result = tradeId != null ? tradeId.hashCode() : 0; + result = 31 * result + (id != null ? id.hashCode() : 0); result = 31 * result + traderId; result = 31 * result + (disputeOpenerIsBuyer ? 1 : 0); result = 31 * result + (disputeOpenerIsOfferer ? 1 : 0); @@ -344,27 +349,39 @@ public final class Dispute implements Payload { result = 31 * result + (disputeCommunicationMessages != null ? disputeCommunicationMessages.hashCode() : 0); result = 31 * result + (isClosed ? 1 : 0); result = 31 * result + (disputeResult != null ? disputeResult.hashCode() : 0); + result = 31 * result + (disputePayoutTxId != null ? disputePayoutTxId.hashCode() : 0); + result = 31 * result + (storage != null ? storage.hashCode() : 0); return result; } @Override public String toString() { return "Dispute{" + - ", tradeId='" + tradeId + '\'' + - ", traderId='" + traderId + '\'' + + "tradeId='" + tradeId + '\'' + + ", id='" + id + '\'' + + ", traderId=" + traderId + ", disputeOpenerIsBuyer=" + disputeOpenerIsBuyer + ", disputeOpenerIsOfferer=" + disputeOpenerIsOfferer + ", openingDate=" + openingDate + ", traderPubKeyRing=" + traderPubKeyRing + + ", tradeDate=" + tradeDate + ", contract=" + contract + + ", contractHash=" + Arrays.toString(contractHash) + + ", depositTxSerialized=" + Arrays.toString(depositTxSerialized) + + ", payoutTxSerialized=" + Arrays.toString(payoutTxSerialized) + + ", depositTxId='" + depositTxId + '\'' + + ", payoutTxId='" + payoutTxId + '\'' + ", contractAsJson='" + contractAsJson + '\'' + - ", buyerContractSignature='" + offererContractSignature + '\'' + - ", sellerContractSignature='" + takerContractSignature + '\'' + + ", offererContractSignature='" + offererContractSignature + '\'' + + ", takerContractSignature='" + takerContractSignature + '\'' + ", arbitratorPubKeyRing=" + arbitratorPubKeyRing + - ", disputeDirectMessages=" + disputeCommunicationMessages + - ", disputeDirectMessagesAsObservableList=" + disputeCommunicationMessagesAsObservableList + + ", isSupportTicket=" + isSupportTicket + + ", disputeCommunicationMessages=" + disputeCommunicationMessages + ", isClosed=" + isClosed + ", disputeResult=" + disputeResult + + ", disputePayoutTxId='" + disputePayoutTxId + '\'' + + ", disputeCommunicationMessagesAsObservableList=" + disputeCommunicationMessagesAsObservableList + + ", isClosedProperty=" + isClosedProperty + ", disputeResultProperty=" + disputeResultProperty + '}'; } diff --git a/core/src/main/java/io/bitsquare/arbitration/DisputeManager.java b/core/src/main/java/io/bitsquare/arbitration/DisputeManager.java index 4605af64b4..74cf206aec 100644 --- a/core/src/main/java/io/bitsquare/arbitration/DisputeManager.java +++ b/core/src/main/java/io/bitsquare/arbitration/DisputeManager.java @@ -28,11 +28,11 @@ import io.bitsquare.btc.exceptions.TransactionVerificationException; import io.bitsquare.btc.exceptions.WalletException; import io.bitsquare.common.crypto.KeyRing; import io.bitsquare.common.crypto.PubKeyRing; +import io.bitsquare.crypto.DecryptedMsgWithPubKey; import io.bitsquare.p2p.BootstrapListener; import io.bitsquare.p2p.Message; import io.bitsquare.p2p.NodeAddress; import io.bitsquare.p2p.P2PService; -import io.bitsquare.p2p.messaging.DecryptedMsgWithPubKey; import io.bitsquare.p2p.messaging.SendMailboxMessageListener; import io.bitsquare.storage.Storage; import io.bitsquare.trade.Contract; @@ -513,7 +513,7 @@ public class DisputeManager { // after successful publish we send peer the tx - dispute.setDisputePayoutTx(transaction); + dispute.setDisputePayoutTxId(transaction.getHashAsString()); sendPeerPublishedPayoutTxMessage(transaction, dispute, contract); } @@ -551,7 +551,7 @@ public class DisputeManager { // losing trader or in case of 50/50 the seller gets the tx sent from the winner or buyer private void onDisputedPayoutTxMessage(PeerPublishedPayoutTxMessage peerPublishedPayoutTxMessage) { Transaction transaction = tradeWalletService.addTransactionToWallet(peerPublishedPayoutTxMessage.transaction); - findOwnDispute(peerPublishedPayoutTxMessage.tradeId).ifPresent(dispute -> dispute.setDisputePayoutTx(transaction)); + findOwnDispute(peerPublishedPayoutTxMessage.tradeId).ifPresent(dispute -> dispute.setDisputePayoutTxId(transaction.getHashAsString())); } @@ -585,11 +585,11 @@ public class DisputeManager { /////////////////////////////////////////////////////////////////////////////////////////// private Optional findDispute(String tradeId, int traderId) { - return disputes.stream().filter(e -> e.getTradeId().equals(tradeId) && e.getTraderId() == traderId).findFirst(); + return disputes.stream().filter(e -> e.getTradeId().equals(tradeId) && e.getTraderId() == traderId).findAny(); } public Optional findOwnDispute(String tradeId) { - return disputes.stream().filter(e -> e.getTradeId().equals(tradeId)).findFirst(); + return disputes.stream().filter(e -> e.getTradeId().equals(tradeId)).findAny(); } public List findDisputesByTradeId(String tradeId) { diff --git a/core/src/main/java/io/bitsquare/arbitration/DisputeResult.java b/core/src/main/java/io/bitsquare/arbitration/DisputeResult.java index 50b4c2581d..7c4570f3d1 100644 --- a/core/src/main/java/io/bitsquare/arbitration/DisputeResult.java +++ b/core/src/main/java/io/bitsquare/arbitration/DisputeResult.java @@ -35,7 +35,7 @@ public final class DisputeResult implements Payload { private static final long serialVersionUID = Version.P2P_NETWORK_VERSION; private static final Logger log = LoggerFactory.getLogger(DisputeResult.class); - public enum FeePaymentPolicy { + public enum DisputeFeePolicy { LOSER, SPLIT, WAIVE @@ -49,7 +49,7 @@ public final class DisputeResult implements Payload { public final String tradeId; public final int traderId; - private FeePaymentPolicy feePaymentPolicy; + private DisputeFeePolicy disputeFeePolicy; private boolean tamperProofEvidence; private boolean idVerification; @@ -68,14 +68,14 @@ public final class DisputeResult implements Payload { transient private BooleanProperty tamperProofEvidenceProperty = new SimpleBooleanProperty(); transient private BooleanProperty idVerificationProperty = new SimpleBooleanProperty(); transient private BooleanProperty screenCastProperty = new SimpleBooleanProperty(); - transient private ObjectProperty feePaymentPolicyProperty = new SimpleObjectProperty<>(); + transient private ObjectProperty feePaymentPolicyProperty = new SimpleObjectProperty<>(); transient private StringProperty summaryNotesProperty = new SimpleStringProperty(); public DisputeResult(String tradeId, int traderId) { this.tradeId = tradeId; this.traderId = traderId; - feePaymentPolicy = FeePaymentPolicy.LOSER; + disputeFeePolicy = DisputeFeePolicy.LOSER; init(); } @@ -92,7 +92,7 @@ public final class DisputeResult implements Payload { tamperProofEvidenceProperty = new SimpleBooleanProperty(tamperProofEvidence); idVerificationProperty = new SimpleBooleanProperty(idVerification); screenCastProperty = new SimpleBooleanProperty(screenCast); - feePaymentPolicyProperty = new SimpleObjectProperty<>(feePaymentPolicy); + feePaymentPolicyProperty = new SimpleObjectProperty<>(disputeFeePolicy); summaryNotesProperty = new SimpleStringProperty(summaryNotes); tamperProofEvidenceProperty.addListener((observable, oldValue, newValue) -> { @@ -105,7 +105,7 @@ public final class DisputeResult implements Payload { screenCast = newValue; }); feePaymentPolicyProperty.addListener((observable, oldValue, newValue) -> { - feePaymentPolicy = newValue; + disputeFeePolicy = newValue; }); summaryNotesProperty.addListener((observable, oldValue, newValue) -> { summaryNotes = newValue; @@ -124,17 +124,17 @@ public final class DisputeResult implements Payload { return screenCastProperty; } - public void setFeePaymentPolicy(FeePaymentPolicy feePaymentPolicy) { - this.feePaymentPolicy = feePaymentPolicy; - feePaymentPolicyProperty.set(feePaymentPolicy); + public void setDisputeFeePolicy(DisputeFeePolicy disputeFeePolicy) { + this.disputeFeePolicy = disputeFeePolicy; + feePaymentPolicyProperty.set(disputeFeePolicy); } - public ReadOnlyObjectProperty feePaymentPolicyProperty() { + public ReadOnlyObjectProperty disputeFeePolicyProperty() { return feePaymentPolicyProperty; } - public FeePaymentPolicy getFeePaymentPolicy() { - return feePaymentPolicy; + public DisputeFeePolicy getDisputeFeePolicy() { + return disputeFeePolicy; } @@ -230,7 +230,7 @@ public final class DisputeResult implements Payload { if (arbitratorPayoutAmount != that.arbitratorPayoutAmount) return false; if (closeDate != that.closeDate) return false; if (tradeId != null ? !tradeId.equals(that.tradeId) : that.tradeId != null) return false; - if (feePaymentPolicy != that.feePaymentPolicy) return false; + if (disputeFeePolicy != that.disputeFeePolicy) return false; if (summaryNotes != null ? !summaryNotes.equals(that.summaryNotes) : that.summaryNotes != null) return false; if (disputeCommunicationMessage != null ? !disputeCommunicationMessage.equals(that.disputeCommunicationMessage) : that.disputeCommunicationMessage != null) return false; @@ -246,7 +246,7 @@ public final class DisputeResult implements Payload { public int hashCode() { int result = tradeId != null ? tradeId.hashCode() : 0; result = 31 * result + traderId; - result = 31 * result + (feePaymentPolicy != null ? feePaymentPolicy.hashCode() : 0); + result = 31 * result + (disputeFeePolicy != null ? disputeFeePolicy.hashCode() : 0); result = 31 * result + (tamperProofEvidence ? 1 : 0); result = 31 * result + (idVerification ? 1 : 0); result = 31 * result + (screenCast ? 1 : 0); diff --git a/core/src/main/java/io/bitsquare/arbitration/messages/DisputeCommunicationMessage.java b/core/src/main/java/io/bitsquare/arbitration/messages/DisputeCommunicationMessage.java index a6773c4a1e..87352e1636 100644 --- a/core/src/main/java/io/bitsquare/arbitration/messages/DisputeCommunicationMessage.java +++ b/core/src/main/java/io/bitsquare/arbitration/messages/DisputeCommunicationMessage.java @@ -42,7 +42,7 @@ public final class DisputeCommunicationMessage extends DisputeMessage { private final int traderId; private final boolean senderIsTrader; private final String message; - private final List attachments = new ArrayList<>(); + private final ArrayList attachments = new ArrayList<>(); private boolean arrived; private boolean storedInMailbox; private boolean isSystemMessage; diff --git a/core/src/main/java/io/bitsquare/arbitration/messages/DisputeMessage.java b/core/src/main/java/io/bitsquare/arbitration/messages/DisputeMessage.java index f07de6007d..7ddee3e1c9 100644 --- a/core/src/main/java/io/bitsquare/arbitration/messages/DisputeMessage.java +++ b/core/src/main/java/io/bitsquare/arbitration/messages/DisputeMessage.java @@ -20,11 +20,19 @@ package io.bitsquare.arbitration.messages; import io.bitsquare.app.Version; import io.bitsquare.p2p.messaging.MailboxMessage; +import java.util.UUID; + public abstract class DisputeMessage implements MailboxMessage { private final int messageVersion = Version.getP2PMessageVersion(); + private final String uid = UUID.randomUUID().toString(); @Override public int getMessageVersion() { return messageVersion; } + + @Override + public String getUID() { + return uid; + } } diff --git a/core/src/main/java/io/bitsquare/arbitration/messages/PeerOpenedDisputeMessage.java b/core/src/main/java/io/bitsquare/arbitration/messages/PeerOpenedDisputeMessage.java index 7701b546e3..6afaa4ffed 100644 --- a/core/src/main/java/io/bitsquare/arbitration/messages/PeerOpenedDisputeMessage.java +++ b/core/src/main/java/io/bitsquare/arbitration/messages/PeerOpenedDisputeMessage.java @@ -24,6 +24,7 @@ import io.bitsquare.p2p.NodeAddress; public final class PeerOpenedDisputeMessage extends DisputeMessage { // That object is sent over the wire, so we need to take care of version compatibility. private static final long serialVersionUID = Version.P2P_NETWORK_VERSION; + public final Dispute dispute; private final NodeAddress myNodeAddress; diff --git a/core/src/main/java/io/bitsquare/btc/BitcoinNetwork.java b/core/src/main/java/io/bitsquare/btc/BitcoinNetwork.java index 3200632dd4..27c20299a0 100644 --- a/core/src/main/java/io/bitsquare/btc/BitcoinNetwork.java +++ b/core/src/main/java/io/bitsquare/btc/BitcoinNetwork.java @@ -17,13 +17,12 @@ package io.bitsquare.btc; -import io.bitsquare.common.persistance.Persistable; import org.bitcoinj.core.NetworkParameters; import org.bitcoinj.params.MainNetParams; import org.bitcoinj.params.RegTestParams; import org.bitcoinj.params.TestNet3Params; -public enum BitcoinNetwork implements Persistable { +public enum BitcoinNetwork { MAINNET(MainNetParams.get()), TESTNET(TestNet3Params.get()), REGTEST(RegTestParams.get()); diff --git a/core/src/main/java/io/bitsquare/btc/TradeWalletService.java b/core/src/main/java/io/bitsquare/btc/TradeWalletService.java index 8f2d7e41ce..99900c9b33 100644 --- a/core/src/main/java/io/bitsquare/btc/TradeWalletService.java +++ b/core/src/main/java/io/bitsquare/btc/TradeWalletService.java @@ -25,7 +25,7 @@ import com.google.common.util.concurrent.ListenableFuture; import io.bitsquare.app.Log; import io.bitsquare.btc.data.InputsAndChangeOutput; import io.bitsquare.btc.data.PreparedDepositTxAndOffererInputs; -import io.bitsquare.btc.data.RawInput; +import io.bitsquare.btc.data.RawTransactionInput; import io.bitsquare.btc.exceptions.SigningException; import io.bitsquare.btc.exceptions.TransactionVerificationException; import io.bitsquare.btc.exceptions.WalletException; @@ -233,7 +233,7 @@ public class TradeWalletService { printTxWithInputs("dummyTX", dummyTX); - List rawInputList = dummyTX.getInputs().stream() + List rawTransactionInputList = dummyTX.getInputs().stream() .map(e -> { checkNotNull(e.getConnectedOutput(), "e.getConnectedOutput() must not be null"); checkNotNull(e.getConnectedOutput().getParentTransaction(), "e.getConnectedOutput().getParentTransaction() must not be null"); @@ -255,7 +255,7 @@ public class TradeWalletService { changeOutputAddress = addressFromP2PKHScript.toString(); } - return new InputsAndChangeOutput(rawInputList, changeOutputValue, changeOutputAddress); + return new InputsAndChangeOutput(new ArrayList<>(rawTransactionInputList), changeOutputValue, changeOutputAddress); } /** @@ -265,7 +265,7 @@ public class TradeWalletService { * @param contractHash The hash of the contract to be added to the OP_RETURN output. * @param offererInputAmount The input amount of the offerer. * @param msOutputAmount The output amount to our MS output. - * @param takerRawInputs Raw data for the connected outputs for all inputs of the taker (normally 1 input) + * @param takerRawTransactionInputs Raw data for the connected outputs for all inputs of the taker (normally 1 input) * @param takerChangeOutputValue Optional taker change output value * @param takerChangeAddressString Optional taker change address * @param offererAddressInfo The offerers address entry. @@ -281,7 +281,7 @@ public class TradeWalletService { byte[] contractHash, Coin offererInputAmount, Coin msOutputAmount, - List takerRawInputs, + List takerRawTransactionInputs, long takerChangeOutputValue, @Nullable String takerChangeAddressString, AddressEntry offererAddressInfo, @@ -293,14 +293,14 @@ public class TradeWalletService { log.trace("offererIsBuyer " + offererIsBuyer); log.trace("offererInputAmount " + offererInputAmount.toFriendlyString()); log.trace("msOutputAmount " + msOutputAmount.toFriendlyString()); - log.trace("takerRawInputs " + takerRawInputs.toString()); + log.trace("takerRawInputs " + takerRawTransactionInputs.toString()); log.trace("takerChangeOutputValue " + takerChangeOutputValue); log.trace("takerChangeAddressString " + takerChangeAddressString); log.trace("buyerPubKey " + ECKey.fromPublicOnly(buyerPubKey).toString()); log.trace("sellerPubKey " + ECKey.fromPublicOnly(sellerPubKey).toString()); log.trace("arbitratorPubKey " + ECKey.fromPublicOnly(arbitratorPubKey).toString()); - checkArgument(!takerRawInputs.isEmpty()); + checkArgument(!takerRawTransactionInputs.isEmpty()); // First we construct a dummy TX to get the inputs and outputs we want to use for the real deposit tx. // Similar to the way we did in the createTakerDepositTxInputs method. @@ -323,30 +323,30 @@ public class TradeWalletService { // Now we construct the real deposit tx Transaction preparedDepositTx = new Transaction(params); - List offererRawInputs = new ArrayList<>(); + ArrayList offererRawTransactionInputs = new ArrayList<>(); if (offererIsBuyer) { // Add buyer inputs for (TransactionInput input : offererInputs) { preparedDepositTx.addInput(input); - offererRawInputs.add(getRawInputFromTransactionInput(input)); + offererRawTransactionInputs.add(getRawInputFromTransactionInput(input)); } // Add seller inputs // the sellers input is not signed so we attach empty script bytes - for (RawInput rawInput : takerRawInputs) - preparedDepositTx.addInput(getTransactionInput(preparedDepositTx, new byte[]{}, rawInput)); + for (RawTransactionInput rawTransactionInput : takerRawTransactionInputs) + preparedDepositTx.addInput(getTransactionInput(preparedDepositTx, new byte[]{}, rawTransactionInput)); } else { // taker is buyer role // Add buyer inputs // the sellers input is not signed so we attach empty script bytes - for (RawInput rawInput : takerRawInputs) - preparedDepositTx.addInput(getTransactionInput(preparedDepositTx, new byte[]{}, rawInput)); + for (RawTransactionInput rawTransactionInput : takerRawTransactionInputs) + preparedDepositTx.addInput(getTransactionInput(preparedDepositTx, new byte[]{}, rawTransactionInput)); // Add seller inputs for (TransactionInput input : offererInputs) { preparedDepositTx.addInput(input); - offererRawInputs.add(getRawInputFromTransactionInput(input)); + offererRawTransactionInputs.add(getRawInputFromTransactionInput(input)); } } @@ -401,7 +401,7 @@ public class TradeWalletService { printTxWithInputs("preparedDepositTx", preparedDepositTx); - return new PreparedDepositTxAndOffererInputs(offererRawInputs, preparedDepositTx.bitcoinSerialize()); + return new PreparedDepositTxAndOffererInputs(offererRawTransactionInputs, preparedDepositTx.bitcoinSerialize()); } /** @@ -423,8 +423,8 @@ public class TradeWalletService { public void takerSignsAndPublishesDepositTx(boolean takerIsSeller, byte[] contractHash, byte[] offerersDepositTxSerialized, - List buyerInputs, - List sellerInputs, + List buyerInputs, + List sellerInputs, byte[] buyerPubKey, byte[] sellerPubKey, byte[] arbitratorPubKey, @@ -460,13 +460,13 @@ public class TradeWalletService { depositTx.addInput(getTransactionInput(depositTx, getScriptProgram(offerersDepositTx, i), buyerInputs.get(i))); // Add seller inputs - for (RawInput rawInput : sellerInputs) - depositTx.addInput(getTransactionInput(depositTx, new byte[]{}, rawInput)); + for (RawTransactionInput rawTransactionInput : sellerInputs) + depositTx.addInput(getTransactionInput(depositTx, new byte[]{}, rawTransactionInput)); } else { // taker is buyer // Add buyer inputs and apply signature - for (RawInput rawInput : buyerInputs) - depositTx.addInput(getTransactionInput(depositTx, new byte[]{}, rawInput)); + for (RawTransactionInput rawTransactionInput : buyerInputs) + depositTx.addInput(getTransactionInput(depositTx, new byte[]{}, rawTransactionInput)); // Add seller inputs // We grab the signature from the offerersDepositTx and apply it to the new tx input @@ -898,12 +898,12 @@ public class TradeWalletService { /////////////////////////////////////////////////////////////////////////////////////////// @NotNull - private RawInput getRawInputFromTransactionInput(@NotNull TransactionInput input) { + private RawTransactionInput getRawInputFromTransactionInput(@NotNull TransactionInput input) { checkNotNull(input.getConnectedOutput(), "input.getConnectedOutput() must not be null"); checkNotNull(input.getConnectedOutput().getParentTransaction(), "input.getConnectedOutput().getParentTransaction() must not be null"); checkNotNull(input.getValue(), "input.getValue() must not be null"); - return new RawInput(input.getOutpoint().getIndex(), input.getConnectedOutput().getParentTransaction().bitcoinSerialize(), input.getValue().value); + return new RawTransactionInput(input.getOutpoint().getIndex(), input.getConnectedOutput().getParentTransaction().bitcoinSerialize(), input.getValue().value); } private byte[] getScriptProgram(Transaction offerersDepositTx, int i) throws TransactionVerificationException { @@ -915,12 +915,12 @@ public class TradeWalletService { } @NotNull - private TransactionInput getTransactionInput(Transaction depositTx, byte[] scriptProgram, RawInput rawInput) { + private TransactionInput getTransactionInput(Transaction depositTx, byte[] scriptProgram, RawTransactionInput rawTransactionInput) { return new TransactionInput(params, depositTx, scriptProgram, - new TransactionOutPoint(params, rawInput.index, new Transaction(params, rawInput.parentTransaction)), - Coin.valueOf(rawInput.value)); + new TransactionOutPoint(params, rawTransactionInput.index, new Transaction(params, rawTransactionInput.parentTransaction)), + Coin.valueOf(rawTransactionInput.value)); } diff --git a/core/src/main/java/io/bitsquare/btc/data/InputsAndChangeOutput.java b/core/src/main/java/io/bitsquare/btc/data/InputsAndChangeOutput.java index f171d7d7a5..59eb3fa9dd 100644 --- a/core/src/main/java/io/bitsquare/btc/data/InputsAndChangeOutput.java +++ b/core/src/main/java/io/bitsquare/btc/data/InputsAndChangeOutput.java @@ -18,22 +18,22 @@ package io.bitsquare.btc.data; import javax.annotation.Nullable; -import java.util.List; +import java.util.ArrayList; import static com.google.common.base.Preconditions.checkArgument; public class InputsAndChangeOutput { - public final List rawInputs; + public final ArrayList rawTransactionInputs; // Is set to 0L in case we don't have an output public final long changeOutputValue; @Nullable public final String changeOutputAddress; - public InputsAndChangeOutput(List rawInputs, long changeOutputValue, @Nullable String changeOutputAddress) { - checkArgument(!rawInputs.isEmpty(), "rawInputs.isEmpty()"); + public InputsAndChangeOutput(ArrayList rawTransactionInputs, long changeOutputValue, @Nullable String changeOutputAddress) { + checkArgument(!rawTransactionInputs.isEmpty(), "rawInputs.isEmpty()"); - this.rawInputs = rawInputs; + this.rawTransactionInputs = rawTransactionInputs; this.changeOutputValue = changeOutputValue; this.changeOutputAddress = changeOutputAddress; } diff --git a/core/src/main/java/io/bitsquare/btc/data/PreparedDepositTxAndOffererInputs.java b/core/src/main/java/io/bitsquare/btc/data/PreparedDepositTxAndOffererInputs.java index 3e6e00ab6a..58d7de6d71 100644 --- a/core/src/main/java/io/bitsquare/btc/data/PreparedDepositTxAndOffererInputs.java +++ b/core/src/main/java/io/bitsquare/btc/data/PreparedDepositTxAndOffererInputs.java @@ -17,13 +17,13 @@ package io.bitsquare.btc.data; -import java.util.List; +import java.util.ArrayList; public class PreparedDepositTxAndOffererInputs { - public final List rawOffererInputs; + public final ArrayList rawOffererInputs; public final byte[] depositTransaction; - public PreparedDepositTxAndOffererInputs(List rawOffererInputs, byte[] depositTransaction) { + public PreparedDepositTxAndOffererInputs(ArrayList rawOffererInputs, byte[] depositTransaction) { this.rawOffererInputs = rawOffererInputs; this.depositTransaction = depositTransaction; } diff --git a/core/src/main/java/io/bitsquare/btc/data/RawInput.java b/core/src/main/java/io/bitsquare/btc/data/RawTransactionInput.java similarity index 76% rename from core/src/main/java/io/bitsquare/btc/data/RawInput.java rename to core/src/main/java/io/bitsquare/btc/data/RawTransactionInput.java index 0e9f4ac017..dcf468f03c 100644 --- a/core/src/main/java/io/bitsquare/btc/data/RawInput.java +++ b/core/src/main/java/io/bitsquare/btc/data/RawTransactionInput.java @@ -22,7 +22,7 @@ import io.bitsquare.common.wire.Payload; import java.util.Arrays; -public final class RawInput implements Payload { +public final class RawTransactionInput implements Payload { // That object is sent over the wire, so we need to take care of version compatibility. private static final long serialVersionUID = Version.P2P_NETWORK_VERSION; @@ -30,7 +30,7 @@ public final class RawInput implements Payload { public final byte[] parentTransaction; public final long value; - public RawInput(long index, byte[] parentTransaction, long value) { + public RawTransactionInput(long index, byte[] parentTransaction, long value) { this.index = index; this.parentTransaction = parentTransaction; this.value = value; @@ -39,13 +39,13 @@ public final class RawInput implements Payload { @Override public boolean equals(Object o) { if (this == o) return true; - if (!(o instanceof RawInput)) return false; + if (!(o instanceof RawTransactionInput)) return false; - RawInput rawInput = (RawInput) o; + RawTransactionInput rawTransactionInput = (RawTransactionInput) o; - if (index != rawInput.index) return false; - if (value != rawInput.value) return false; - return Arrays.equals(parentTransaction, rawInput.parentTransaction); + if (index != rawTransactionInput.index) return false; + if (value != rawTransactionInput.value) return false; + return Arrays.equals(parentTransaction, rawTransactionInput.parentTransaction); } diff --git a/core/src/main/java/io/bitsquare/trade/Trade.java b/core/src/main/java/io/bitsquare/trade/Trade.java index 40cc06a6b1..a5b10b81ae 100644 --- a/core/src/main/java/io/bitsquare/trade/Trade.java +++ b/core/src/main/java/io/bitsquare/trade/Trade.java @@ -29,9 +29,9 @@ import io.bitsquare.btc.TradeWalletService; import io.bitsquare.btc.WalletService; import io.bitsquare.common.crypto.KeyRing; import io.bitsquare.common.taskrunner.Model; +import io.bitsquare.crypto.DecryptedMsgWithPubKey; import io.bitsquare.p2p.NodeAddress; import io.bitsquare.p2p.P2PService; -import io.bitsquare.p2p.messaging.DecryptedMsgWithPubKey; import io.bitsquare.storage.Storage; import io.bitsquare.trade.offer.Offer; import io.bitsquare.trade.offer.OpenOfferManager; @@ -82,6 +82,7 @@ public abstract class Trade implements Tradable, Model { FIAT_PAYMENT_RECEIPT_MSG_SENT(Phase.FIAT_RECEIVED), FIAT_PAYMENT_RECEIPT_MSG_RECEIVED(Phase.FIAT_RECEIVED), + PAYOUT_TX_COMMITTED(Phase.PAYOUT_PAID), PAYOUT_TX_SENT(Phase.PAYOUT_PAID), PAYOUT_TX_RECEIVED_AND_COMMITTED(Phase.PAYOUT_PAID), PAYOUT_BROAD_CASTED(Phase.PAYOUT_PAID), diff --git a/core/src/main/java/io/bitsquare/trade/TradeManager.java b/core/src/main/java/io/bitsquare/trade/TradeManager.java index a94953aba5..7d08497a72 100644 --- a/core/src/main/java/io/bitsquare/trade/TradeManager.java +++ b/core/src/main/java/io/bitsquare/trade/TradeManager.java @@ -26,13 +26,13 @@ import io.bitsquare.btc.WalletService; import io.bitsquare.common.crypto.KeyRing; import io.bitsquare.common.handlers.FaultHandler; import io.bitsquare.common.handlers.ResultHandler; +import io.bitsquare.crypto.DecryptedMsgWithPubKey; import io.bitsquare.p2p.BootstrapListener; import io.bitsquare.p2p.Message; import io.bitsquare.p2p.NodeAddress; import io.bitsquare.p2p.P2PService; import io.bitsquare.p2p.messaging.DecryptedDirectMessageListener; import io.bitsquare.p2p.messaging.DecryptedMailboxListener; -import io.bitsquare.p2p.messaging.DecryptedMsgWithPubKey; import io.bitsquare.storage.Storage; import io.bitsquare.trade.closed.ClosedTradableManager; import io.bitsquare.trade.failed.FailedTradesManager; diff --git a/core/src/main/java/io/bitsquare/trade/offer/Offer.java b/core/src/main/java/io/bitsquare/trade/offer/Offer.java index dc7a65a043..45a901ab9e 100644 --- a/core/src/main/java/io/bitsquare/trade/offer/Offer.java +++ b/core/src/main/java/io/bitsquare/trade/offer/Offer.java @@ -25,8 +25,8 @@ import io.bitsquare.common.handlers.ResultHandler; import io.bitsquare.common.util.JsonExclude; import io.bitsquare.locale.Country; import io.bitsquare.p2p.NodeAddress; -import io.bitsquare.p2p.storage.data.RequiresOwnerIsOnlinePayload; -import io.bitsquare.p2p.storage.data.StoragePayload; +import io.bitsquare.p2p.storage.payload.RequiresOwnerIsOnlinePayload; +import io.bitsquare.p2p.storage.payload.StoragePayload; import io.bitsquare.payment.PaymentMethod; import io.bitsquare.trade.protocol.availability.OfferAvailabilityModel; import io.bitsquare.trade.protocol.availability.OfferAvailabilityProtocol; @@ -40,6 +40,7 @@ import org.slf4j.LoggerFactory; import javax.annotation.Nullable; import java.io.IOException; import java.security.PublicKey; +import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.concurrent.TimeUnit; @@ -48,20 +49,25 @@ import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload { + /////////////////////////////////////////////////////////////////////////////////////////// + // Static + /////////////////////////////////////////////////////////////////////////////////////////// + // That object is sent over the wire, so we need to take care of version compatibility. @JsonExclude private static final long serialVersionUID = Version.P2P_NETWORK_VERSION; @JsonExclude private static final Logger log = LoggerFactory.getLogger(Offer.class); - - // public static final long TTL = TimeUnit.SECONDS.toMillis(60); - public static final long TTL = TimeUnit.SECONDS.toMillis(10); //TODO - + public static final long TTL = TimeUnit.SECONDS.toMillis(60); public final static String TAC_OFFERER = "When placing that offer I accept that anyone who fulfills my conditions can " + "take that offer."; public static final String TAC_TAKER = "With taking the offer I commit to the trade conditions as defined."; + /////////////////////////////////////////////////////////////////////////////////////////// + // Enums + /////////////////////////////////////////////////////////////////////////////////////////// + public enum Direction {BUY, SELL} public enum State { @@ -74,6 +80,10 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload } + /////////////////////////////////////////////////////////////////////////////////////////// + // Instance fields + /////////////////////////////////////////////////////////////////////////////////////////// + private final String id; private final Direction direction; private final String currencyCode; @@ -91,8 +101,8 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload private final String offererPaymentAccountId; @Nullable - private final List acceptedCountryCodes; - private final List arbitratorNodeAddresses; + private final ArrayList acceptedCountryCodes; + private final ArrayList arbitratorNodeAddresses; // Mutable property. Has to be set before offer is save in P2P network as it changes the objects hash! private String offerFeePaymentTxID; @@ -104,6 +114,7 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload @JsonExclude transient private ObjectProperty stateProperty = new SimpleObjectProperty<>(state); @JsonExclude + @Nullable transient private OfferAvailabilityProtocol availabilityProtocol; @JsonExclude transient private StringProperty errorMessageProperty = new SimpleStringProperty(); @@ -124,8 +135,8 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload String currencyCode, @Nullable Country paymentMethodCountry, String offererPaymentAccountId, - List arbitratorNodeAddresses, - @Nullable List acceptedCountryCodes) { + ArrayList arbitratorNodeAddresses, + @Nullable ArrayList acceptedCountryCodes) { this.id = id; this.offererNodeAddress = offererNodeAddress; this.pubKeyRing = pubKeyRing; diff --git a/core/src/main/java/io/bitsquare/trade/offer/OfferBookService.java b/core/src/main/java/io/bitsquare/trade/offer/OfferBookService.java index e410b1da59..79f02b5486 100644 --- a/core/src/main/java/io/bitsquare/trade/offer/OfferBookService.java +++ b/core/src/main/java/io/bitsquare/trade/offer/OfferBookService.java @@ -21,7 +21,7 @@ import io.bitsquare.common.handlers.ErrorMessageHandler; import io.bitsquare.common.handlers.ResultHandler; import io.bitsquare.p2p.P2PService; import io.bitsquare.p2p.storage.HashMapChangedListener; -import io.bitsquare.p2p.storage.data.ProtectedData; +import io.bitsquare.p2p.storage.storageentry.ProtectedStorageEntry; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -58,18 +58,18 @@ public class OfferBookService { p2PService.addHashSetChangedListener(new HashMapChangedListener() { @Override - public void onAdded(ProtectedData data) { + public void onAdded(ProtectedStorageEntry data) { offerBookChangedListeners.stream().forEach(listener -> { - if (data.expirablePayload instanceof Offer) - listener.onAdded((Offer) data.expirablePayload); + if (data.getStoragePayload() instanceof Offer) + listener.onAdded((Offer) data.getStoragePayload()); }); } @Override - public void onRemoved(ProtectedData data) { + public void onRemoved(ProtectedStorageEntry data) { offerBookChangedListeners.stream().forEach(listener -> { - if (data.expirablePayload instanceof Offer) - listener.onRemoved((Offer) data.expirablePayload); + if (data.getStoragePayload() instanceof Offer) + listener.onRemoved((Offer) data.getStoragePayload()); }); } }); @@ -126,8 +126,8 @@ public class OfferBookService { public List getOffers() { return p2PService.getDataMap().values().stream() - .filter(data -> data.expirablePayload instanceof Offer) - .map(data -> (Offer) data.expirablePayload) + .filter(data -> data.getStoragePayload() instanceof Offer) + .map(data -> (Offer) data.getStoragePayload()) .collect(Collectors.toList()); } diff --git a/core/src/main/java/io/bitsquare/trade/offer/OpenOfferManager.java b/core/src/main/java/io/bitsquare/trade/offer/OpenOfferManager.java index 186c648ebd..91076c3421 100644 --- a/core/src/main/java/io/bitsquare/trade/offer/OpenOfferManager.java +++ b/core/src/main/java/io/bitsquare/trade/offer/OpenOfferManager.java @@ -26,12 +26,12 @@ import io.bitsquare.common.UserThread; import io.bitsquare.common.crypto.KeyRing; import io.bitsquare.common.handlers.ErrorMessageHandler; import io.bitsquare.common.handlers.ResultHandler; +import io.bitsquare.crypto.DecryptedMsgWithPubKey; import io.bitsquare.p2p.BootstrapListener; import io.bitsquare.p2p.Message; import io.bitsquare.p2p.NodeAddress; import io.bitsquare.p2p.P2PService; import io.bitsquare.p2p.messaging.DecryptedDirectMessageListener; -import io.bitsquare.p2p.messaging.DecryptedMsgWithPubKey; import io.bitsquare.p2p.messaging.SendDirectMessageListener; import io.bitsquare.p2p.peers.PeerManager; import io.bitsquare.storage.Storage; diff --git a/core/src/main/java/io/bitsquare/trade/protocol/trade/ProcessModel.java b/core/src/main/java/io/bitsquare/trade/protocol/trade/ProcessModel.java index ed42d34ac1..a33ad72e89 100644 --- a/core/src/main/java/io/bitsquare/trade/protocol/trade/ProcessModel.java +++ b/core/src/main/java/io/bitsquare/trade/protocol/trade/ProcessModel.java @@ -22,7 +22,7 @@ import io.bitsquare.arbitration.ArbitratorManager; import io.bitsquare.btc.AddressEntry; import io.bitsquare.btc.TradeWalletService; import io.bitsquare.btc.WalletService; -import io.bitsquare.btc.data.RawInput; +import io.bitsquare.btc.data.RawTransactionInput; import io.bitsquare.common.crypto.KeyRing; import io.bitsquare.common.crypto.PubKeyRing; import io.bitsquare.common.taskrunner.Model; @@ -44,6 +44,7 @@ import javax.annotation.Nullable; import java.io.IOException; import java.io.ObjectInputStream; import java.io.Serializable; +import java.util.ArrayList; import java.util.List; public class ProcessModel implements Model, Serializable { @@ -74,7 +75,7 @@ public class ProcessModel implements Model, Serializable { // After successful verified we copy that over to the trade.tradingPeerAddress private NodeAddress tempTradingPeerNodeAddress; private byte[] preparedDepositTx; - private List rawInputs; + private ArrayList rawTransactionInputs; private long changeOutputValue; @Nullable private String changeOutputAddress; @@ -243,12 +244,12 @@ public class ProcessModel implements Model, Serializable { return preparedDepositTx; } - public void setRawInputs(List rawInputs) { - this.rawInputs = rawInputs; + public void setRawTransactionInputs(ArrayList rawTransactionInputs) { + this.rawTransactionInputs = rawTransactionInputs; } - public List getRawInputs() { - return rawInputs; + public ArrayList getRawTransactionInputs() { + return rawTransactionInputs; } public void setChangeOutputValue(long changeOutputValue) { diff --git a/core/src/main/java/io/bitsquare/trade/protocol/trade/TradeProtocol.java b/core/src/main/java/io/bitsquare/trade/protocol/trade/TradeProtocol.java index 9a6d17afbd..6891c8d582 100644 --- a/core/src/main/java/io/bitsquare/trade/protocol/trade/TradeProtocol.java +++ b/core/src/main/java/io/bitsquare/trade/protocol/trade/TradeProtocol.java @@ -20,10 +20,10 @@ package io.bitsquare.trade.protocol.trade; import io.bitsquare.common.Timer; import io.bitsquare.common.UserThread; import io.bitsquare.common.crypto.PubKeyRing; +import io.bitsquare.crypto.DecryptedMsgWithPubKey; import io.bitsquare.p2p.Message; import io.bitsquare.p2p.NodeAddress; import io.bitsquare.p2p.messaging.DecryptedDirectMessageListener; -import io.bitsquare.p2p.messaging.DecryptedMsgWithPubKey; import io.bitsquare.trade.OffererTrade; import io.bitsquare.trade.TakerTrade; import io.bitsquare.trade.Trade; diff --git a/core/src/main/java/io/bitsquare/trade/protocol/trade/TradingPeer.java b/core/src/main/java/io/bitsquare/trade/protocol/trade/TradingPeer.java index bf66d05194..b870268342 100644 --- a/core/src/main/java/io/bitsquare/trade/protocol/trade/TradingPeer.java +++ b/core/src/main/java/io/bitsquare/trade/protocol/trade/TradingPeer.java @@ -18,7 +18,7 @@ package io.bitsquare.trade.protocol.trade; import io.bitsquare.app.Version; -import io.bitsquare.btc.data.RawInput; +import io.bitsquare.btc.data.RawTransactionInput; import io.bitsquare.common.crypto.PubKeyRing; import io.bitsquare.common.persistance.Persistable; import io.bitsquare.payment.PaymentAccountContractData; @@ -47,7 +47,7 @@ public final class TradingPeer implements Persistable { private byte[] signature; private PubKeyRing pubKeyRing; private byte[] tradeWalletPubKey; - private List rawInputs; + private List rawTransactionInputs; private long changeOutputValue; @Nullable private String changeOutputAddress; @@ -138,12 +138,12 @@ public final class TradingPeer implements Persistable { this.pubKeyRing = pubKeyRing; } - public void setRawInputs(List rawInputs) { - this.rawInputs = rawInputs; + public void setRawTransactionInputs(List rawTransactionInputs) { + this.rawTransactionInputs = rawTransactionInputs; } - public List getRawInputs() { - return rawInputs; + public List getRawTransactionInputs() { + return rawTransactionInputs; } public void setChangeOutputValue(long changeOutputValue) { diff --git a/core/src/main/java/io/bitsquare/trade/protocol/trade/messages/DepositTxPublishedMessage.java b/core/src/main/java/io/bitsquare/trade/protocol/trade/messages/DepositTxPublishedMessage.java index 2220118cb0..cd8284e646 100644 --- a/core/src/main/java/io/bitsquare/trade/protocol/trade/messages/DepositTxPublishedMessage.java +++ b/core/src/main/java/io/bitsquare/trade/protocol/trade/messages/DepositTxPublishedMessage.java @@ -23,6 +23,7 @@ import io.bitsquare.p2p.messaging.MailboxMessage; import javax.annotation.concurrent.Immutable; import java.util.Arrays; +import java.util.UUID; @Immutable public final class DepositTxPublishedMessage extends TradeMessage implements MailboxMessage { @@ -31,6 +32,7 @@ public final class DepositTxPublishedMessage extends TradeMessage implements Mai public final byte[] depositTx; private final NodeAddress senderNodeAddress; + private final String uid = UUID.randomUUID().toString(); public DepositTxPublishedMessage(String tradeId, byte[] depositTx, NodeAddress senderNodeAddress) { super(tradeId); @@ -43,6 +45,11 @@ public final class DepositTxPublishedMessage extends TradeMessage implements Mai return senderNodeAddress; } + @Override + public String getUID() { + return uid; + } + @Override public boolean equals(Object o) { if (this == o) return true; @@ -52,7 +59,9 @@ public final class DepositTxPublishedMessage extends TradeMessage implements Mai DepositTxPublishedMessage that = (DepositTxPublishedMessage) o; if (!Arrays.equals(depositTx, that.depositTx)) return false; - return !(senderNodeAddress != null ? !senderNodeAddress.equals(that.senderNodeAddress) : that.senderNodeAddress != null); + if (senderNodeAddress != null ? !senderNodeAddress.equals(that.senderNodeAddress) : that.senderNodeAddress != null) + return false; + return !(uid != null ? !uid.equals(that.uid) : that.uid != null); } @@ -61,6 +70,7 @@ public final class DepositTxPublishedMessage extends TradeMessage implements Mai int result = super.hashCode(); result = 31 * result + (depositTx != null ? Arrays.hashCode(depositTx) : 0); result = 31 * result + (senderNodeAddress != null ? senderNodeAddress.hashCode() : 0); + result = 31 * result + (uid != null ? uid.hashCode() : 0); return result; } } diff --git a/core/src/main/java/io/bitsquare/trade/protocol/trade/messages/FiatTransferStartedMessage.java b/core/src/main/java/io/bitsquare/trade/protocol/trade/messages/FiatTransferStartedMessage.java index 540bda376b..d665c63de7 100644 --- a/core/src/main/java/io/bitsquare/trade/protocol/trade/messages/FiatTransferStartedMessage.java +++ b/core/src/main/java/io/bitsquare/trade/protocol/trade/messages/FiatTransferStartedMessage.java @@ -22,6 +22,7 @@ import io.bitsquare.p2p.NodeAddress; import io.bitsquare.p2p.messaging.MailboxMessage; import javax.annotation.concurrent.Immutable; +import java.util.UUID; @Immutable public final class FiatTransferStartedMessage extends TradeMessage implements MailboxMessage { @@ -30,6 +31,7 @@ public final class FiatTransferStartedMessage extends TradeMessage implements Ma public final String buyerPayoutAddress; private final NodeAddress senderNodeAddress; + private final String uid = UUID.randomUUID().toString(); public FiatTransferStartedMessage(String tradeId, String buyerPayoutAddress, NodeAddress senderNodeAddress) { super(tradeId); @@ -42,6 +44,11 @@ public final class FiatTransferStartedMessage extends TradeMessage implements Ma return senderNodeAddress; } + @Override + public String getUID() { + return uid; + } + @Override public boolean equals(Object o) { if (this == o) return true; @@ -52,7 +59,9 @@ public final class FiatTransferStartedMessage extends TradeMessage implements Ma if (buyerPayoutAddress != null ? !buyerPayoutAddress.equals(that.buyerPayoutAddress) : that.buyerPayoutAddress != null) return false; - return !(senderNodeAddress != null ? !senderNodeAddress.equals(that.senderNodeAddress) : that.senderNodeAddress != null); + if (senderNodeAddress != null ? !senderNodeAddress.equals(that.senderNodeAddress) : that.senderNodeAddress != null) + return false; + return !(uid != null ? !uid.equals(that.uid) : that.uid != null); } @@ -61,6 +70,7 @@ public final class FiatTransferStartedMessage extends TradeMessage implements Ma int result = super.hashCode(); result = 31 * result + (buyerPayoutAddress != null ? buyerPayoutAddress.hashCode() : 0); result = 31 * result + (senderNodeAddress != null ? senderNodeAddress.hashCode() : 0); + result = 31 * result + (uid != null ? uid.hashCode() : 0); return result; } } diff --git a/core/src/main/java/io/bitsquare/trade/protocol/trade/messages/FinalizePayoutTxRequest.java b/core/src/main/java/io/bitsquare/trade/protocol/trade/messages/FinalizePayoutTxRequest.java index 5b8c32cf08..c61a06e18f 100644 --- a/core/src/main/java/io/bitsquare/trade/protocol/trade/messages/FinalizePayoutTxRequest.java +++ b/core/src/main/java/io/bitsquare/trade/protocol/trade/messages/FinalizePayoutTxRequest.java @@ -23,6 +23,7 @@ import io.bitsquare.p2p.messaging.MailboxMessage; import javax.annotation.concurrent.Immutable; import java.util.Arrays; +import java.util.UUID; @Immutable public final class FinalizePayoutTxRequest extends TradeMessage implements MailboxMessage { @@ -33,6 +34,7 @@ public final class FinalizePayoutTxRequest extends TradeMessage implements Mailb public final String sellerPayoutAddress; public final long lockTimeAsBlockHeight; private final NodeAddress senderNodeAddress; + private final String uid = UUID.randomUUID().toString(); public FinalizePayoutTxRequest(String tradeId, byte[] sellerSignature, @@ -51,6 +53,11 @@ public final class FinalizePayoutTxRequest extends TradeMessage implements Mailb return senderNodeAddress; } + @Override + public String getUID() { + return uid; + } + @Override public boolean equals(Object o) { if (this == o) return true; @@ -63,7 +70,9 @@ public final class FinalizePayoutTxRequest extends TradeMessage implements Mailb if (!Arrays.equals(sellerSignature, that.sellerSignature)) return false; if (sellerPayoutAddress != null ? !sellerPayoutAddress.equals(that.sellerPayoutAddress) : that.sellerPayoutAddress != null) return false; - return !(senderNodeAddress != null ? !senderNodeAddress.equals(that.senderNodeAddress) : that.senderNodeAddress != null); + if (senderNodeAddress != null ? !senderNodeAddress.equals(that.senderNodeAddress) : that.senderNodeAddress != null) + return false; + return !(uid != null ? !uid.equals(that.uid) : that.uid != null); } @@ -74,6 +83,7 @@ public final class FinalizePayoutTxRequest extends TradeMessage implements Mailb result = 31 * result + (sellerPayoutAddress != null ? sellerPayoutAddress.hashCode() : 0); result = 31 * result + (int) (lockTimeAsBlockHeight ^ (lockTimeAsBlockHeight >>> 32)); result = 31 * result + (senderNodeAddress != null ? senderNodeAddress.hashCode() : 0); + result = 31 * result + (uid != null ? uid.hashCode() : 0); return result; } } diff --git a/core/src/main/java/io/bitsquare/trade/protocol/trade/messages/PayDepositRequest.java b/core/src/main/java/io/bitsquare/trade/protocol/trade/messages/PayDepositRequest.java index a772a58c5e..6b85a45d29 100644 --- a/core/src/main/java/io/bitsquare/trade/protocol/trade/messages/PayDepositRequest.java +++ b/core/src/main/java/io/bitsquare/trade/protocol/trade/messages/PayDepositRequest.java @@ -18,15 +18,16 @@ package io.bitsquare.trade.protocol.trade.messages; import io.bitsquare.app.Version; -import io.bitsquare.btc.data.RawInput; +import io.bitsquare.btc.data.RawTransactionInput; import io.bitsquare.common.crypto.PubKeyRing; import io.bitsquare.p2p.NodeAddress; import io.bitsquare.p2p.messaging.MailboxMessage; import io.bitsquare.payment.PaymentAccountContractData; import javax.annotation.concurrent.Immutable; +import java.util.ArrayList; import java.util.Arrays; -import java.util.List; +import java.util.UUID; @Immutable public final class PayDepositRequest extends TradeMessage implements MailboxMessage { @@ -35,7 +36,7 @@ public final class PayDepositRequest extends TradeMessage implements MailboxMess public final long tradeAmount; public final byte[] takerTradeWalletPubKey; - public final List rawInputs; + public final ArrayList rawTransactionInputs; public final long changeOutputValue; public final String changeOutputAddress; public final String takerPayoutAddressString; @@ -43,14 +44,15 @@ public final class PayDepositRequest extends TradeMessage implements MailboxMess public final PaymentAccountContractData takerPaymentAccountContractData; public final String takerAccountId; public final String takeOfferFeeTxId; - public final List acceptedArbitratorNodeAddresses; + public final ArrayList acceptedArbitratorNodeAddresses; public final NodeAddress arbitratorNodeAddress; private final NodeAddress senderNodeAddress; + private final String uid = UUID.randomUUID().toString(); public PayDepositRequest(NodeAddress senderNodeAddress, String tradeId, long tradeAmount, - List rawInputs, + ArrayList rawTransactionInputs, long changeOutputValue, String changeOutputAddress, byte[] takerTradeWalletPubKey, @@ -59,12 +61,12 @@ public final class PayDepositRequest extends TradeMessage implements MailboxMess PaymentAccountContractData takerPaymentAccountContractData, String takerAccountId, String takeOfferFeeTxId, - List acceptedArbitratorNodeAddresses, + ArrayList acceptedArbitratorNodeAddresses, NodeAddress arbitratorNodeAddress) { super(tradeId); this.senderNodeAddress = senderNodeAddress; this.tradeAmount = tradeAmount; - this.rawInputs = rawInputs; + this.rawTransactionInputs = rawTransactionInputs; this.changeOutputValue = changeOutputValue; this.changeOutputAddress = changeOutputAddress; this.takerPayoutAddressString = takerPayoutAddressString; @@ -82,6 +84,11 @@ public final class PayDepositRequest extends TradeMessage implements MailboxMess return senderNodeAddress; } + @Override + public String getUID() { + return uid; + } + @Override public boolean equals(Object o) { if (this == o) return true; @@ -93,7 +100,8 @@ public final class PayDepositRequest extends TradeMessage implements MailboxMess if (tradeAmount != that.tradeAmount) return false; if (changeOutputValue != that.changeOutputValue) return false; if (!Arrays.equals(takerTradeWalletPubKey, that.takerTradeWalletPubKey)) return false; - if (rawInputs != null ? !rawInputs.equals(that.rawInputs) : that.rawInputs != null) return false; + if (rawTransactionInputs != null ? !rawTransactionInputs.equals(that.rawTransactionInputs) : that.rawTransactionInputs != null) + return false; if (changeOutputAddress != null ? !changeOutputAddress.equals(that.changeOutputAddress) : that.changeOutputAddress != null) return false; if (takerPayoutAddressString != null ? !takerPayoutAddressString.equals(that.takerPayoutAddressString) : that.takerPayoutAddressString != null) @@ -110,7 +118,9 @@ public final class PayDepositRequest extends TradeMessage implements MailboxMess return false; if (arbitratorNodeAddress != null ? !arbitratorNodeAddress.equals(that.arbitratorNodeAddress) : that.arbitratorNodeAddress != null) return false; - return !(senderNodeAddress != null ? !senderNodeAddress.equals(that.senderNodeAddress) : that.senderNodeAddress != null); + if (senderNodeAddress != null ? !senderNodeAddress.equals(that.senderNodeAddress) : that.senderNodeAddress != null) + return false; + return !(uid != null ? !uid.equals(that.uid) : that.uid != null); } @@ -119,7 +129,7 @@ public final class PayDepositRequest extends TradeMessage implements MailboxMess int result = super.hashCode(); result = 31 * result + (int) (tradeAmount ^ (tradeAmount >>> 32)); result = 31 * result + (takerTradeWalletPubKey != null ? Arrays.hashCode(takerTradeWalletPubKey) : 0); - result = 31 * result + (rawInputs != null ? rawInputs.hashCode() : 0); + result = 31 * result + (rawTransactionInputs != null ? rawTransactionInputs.hashCode() : 0); result = 31 * result + (int) (changeOutputValue ^ (changeOutputValue >>> 32)); result = 31 * result + (changeOutputAddress != null ? changeOutputAddress.hashCode() : 0); result = 31 * result + (takerPayoutAddressString != null ? takerPayoutAddressString.hashCode() : 0); @@ -130,6 +140,7 @@ public final class PayDepositRequest extends TradeMessage implements MailboxMess result = 31 * result + (acceptedArbitratorNodeAddresses != null ? acceptedArbitratorNodeAddresses.hashCode() : 0); result = 31 * result + (arbitratorNodeAddress != null ? arbitratorNodeAddress.hashCode() : 0); result = 31 * result + (senderNodeAddress != null ? senderNodeAddress.hashCode() : 0); + result = 31 * result + (uid != null ? uid.hashCode() : 0); return result; } } diff --git a/core/src/main/java/io/bitsquare/trade/protocol/trade/messages/PayoutTxFinalizedMessage.java b/core/src/main/java/io/bitsquare/trade/protocol/trade/messages/PayoutTxFinalizedMessage.java index 3a49354770..57125d5e35 100644 --- a/core/src/main/java/io/bitsquare/trade/protocol/trade/messages/PayoutTxFinalizedMessage.java +++ b/core/src/main/java/io/bitsquare/trade/protocol/trade/messages/PayoutTxFinalizedMessage.java @@ -23,6 +23,7 @@ import io.bitsquare.p2p.messaging.MailboxMessage; import javax.annotation.concurrent.Immutable; import java.util.Arrays; +import java.util.UUID; @Immutable public final class PayoutTxFinalizedMessage extends TradeMessage implements MailboxMessage { @@ -31,6 +32,7 @@ public final class PayoutTxFinalizedMessage extends TradeMessage implements Mail public final byte[] payoutTx; private final NodeAddress senderNodeAddress; + private final String uid = UUID.randomUUID().toString(); public PayoutTxFinalizedMessage(String tradeId, byte[] payoutTx, NodeAddress senderNodeAddress) { super(tradeId); @@ -43,6 +45,11 @@ public final class PayoutTxFinalizedMessage extends TradeMessage implements Mail return senderNodeAddress; } + @Override + public String getUID() { + return uid; + } + @Override public boolean equals(Object o) { if (this == o) return true; @@ -52,7 +59,9 @@ public final class PayoutTxFinalizedMessage extends TradeMessage implements Mail PayoutTxFinalizedMessage that = (PayoutTxFinalizedMessage) o; if (!Arrays.equals(payoutTx, that.payoutTx)) return false; - return !(senderNodeAddress != null ? !senderNodeAddress.equals(that.senderNodeAddress) : that.senderNodeAddress != null); + if (senderNodeAddress != null ? !senderNodeAddress.equals(that.senderNodeAddress) : that.senderNodeAddress != null) + return false; + return !(uid != null ? !uid.equals(that.uid) : that.uid != null); } @@ -61,6 +70,7 @@ public final class PayoutTxFinalizedMessage extends TradeMessage implements Mail int result = super.hashCode(); result = 31 * result + (payoutTx != null ? Arrays.hashCode(payoutTx) : 0); result = 31 * result + (senderNodeAddress != null ? senderNodeAddress.hashCode() : 0); + result = 31 * result + (uid != null ? uid.hashCode() : 0); return result; } } diff --git a/core/src/main/java/io/bitsquare/trade/protocol/trade/messages/PublishDepositTxRequest.java b/core/src/main/java/io/bitsquare/trade/protocol/trade/messages/PublishDepositTxRequest.java index 381a4eed55..633d26ba6d 100644 --- a/core/src/main/java/io/bitsquare/trade/protocol/trade/messages/PublishDepositTxRequest.java +++ b/core/src/main/java/io/bitsquare/trade/protocol/trade/messages/PublishDepositTxRequest.java @@ -18,7 +18,7 @@ package io.bitsquare.trade.protocol.trade.messages; import io.bitsquare.app.Version; -import io.bitsquare.btc.data.RawInput; +import io.bitsquare.btc.data.RawTransactionInput; import io.bitsquare.common.util.Utilities; import io.bitsquare.payment.PaymentAccountContractData; import org.slf4j.Logger; @@ -26,7 +26,6 @@ import org.slf4j.LoggerFactory; import javax.annotation.concurrent.Immutable; import java.util.ArrayList; -import java.util.List; @Immutable @@ -43,7 +42,7 @@ public final class PublishDepositTxRequest extends TradeMessage { public final String offererContractSignature; public final String offererPayoutAddressString; public final byte[] preparedDepositTx; - public final List offererInputs; + public final ArrayList offererInputs; public final int openDisputeTimeAsBlockHeight; public final int checkPaymentTimeAsBlockHeight; public final byte[] offererTradeWalletPubKey; @@ -56,7 +55,7 @@ public final class PublishDepositTxRequest extends TradeMessage { String offererContractSignature, String offererPayoutAddressString, byte[] preparedDepositTx, - List offererInputs, + ArrayList offererInputs, int openDisputeTimeAsBlockHeight, int checkPaymentTimeAsBlockHeight) { super(tradeId); diff --git a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/TradeTask.java b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/TradeTask.java index 00eb77217a..6080911d40 100644 --- a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/TradeTask.java +++ b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/TradeTask.java @@ -19,7 +19,7 @@ package io.bitsquare.trade.protocol.trade.tasks; import io.bitsquare.common.taskrunner.Task; import io.bitsquare.common.taskrunner.TaskRunner; -import io.bitsquare.p2p.messaging.DecryptedMsgWithPubKey; +import io.bitsquare.crypto.DecryptedMsgWithPubKey; import io.bitsquare.p2p.messaging.MailboxMessage; import io.bitsquare.trade.Trade; import io.bitsquare.trade.protocol.trade.ProcessModel; diff --git a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/buyer/CreateAndSignDepositTxAsBuyer.java b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/buyer/CreateAndSignDepositTxAsBuyer.java index b115c5b692..d4168ca471 100644 --- a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/buyer/CreateAndSignDepositTxAsBuyer.java +++ b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/buyer/CreateAndSignDepositTxAsBuyer.java @@ -56,7 +56,7 @@ public class CreateAndSignDepositTxAsBuyer extends TradeTask { contractHash, buyerInputAmount, msOutputAmount, - processModel.tradingPeer.getRawInputs(), + processModel.tradingPeer.getRawTransactionInputs(), processModel.tradingPeer.getChangeOutputValue(), processModel.tradingPeer.getChangeOutputAddress(), processModel.getAddressEntry(), @@ -65,7 +65,7 @@ public class CreateAndSignDepositTxAsBuyer extends TradeTask { processModel.getArbitratorPubKey(trade.getArbitratorNodeAddress())); processModel.setPreparedDepositTx(result.depositTransaction); - processModel.setRawInputs(result.rawOffererInputs); + processModel.setRawTransactionInputs(result.rawOffererInputs); complete(); } catch (Throwable t) { diff --git a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/buyer/CreateDepositTxInputsAsBuyer.java b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/buyer/CreateDepositTxInputsAsBuyer.java index c399bdce1d..5e4786d976 100644 --- a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/buyer/CreateDepositTxInputsAsBuyer.java +++ b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/buyer/CreateDepositTxInputsAsBuyer.java @@ -39,7 +39,7 @@ public class CreateDepositTxInputsAsBuyer extends TradeTask { runInterceptHook(); Coin takerInputAmount = FeePolicy.getSecurityDeposit().add(FeePolicy.getFixedTxFeeForTrades()); InputsAndChangeOutput result = processModel.getTradeWalletService().takerCreatesDepositsTxInputs(takerInputAmount, processModel.getAddressEntry()); - processModel.setRawInputs(result.rawInputs); + processModel.setRawTransactionInputs(result.rawTransactionInputs); processModel.setChangeOutputValue(result.changeOutputValue); processModel.setChangeOutputAddress(result.changeOutputAddress); diff --git a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/buyer/SendPayoutTxFinalizedMessage.java b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/buyer/SendPayoutTxFinalizedMessage.java index 0796eae3bf..f3b1eb37d8 100644 --- a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/buyer/SendPayoutTxFinalizedMessage.java +++ b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/buyer/SendPayoutTxFinalizedMessage.java @@ -49,24 +49,25 @@ public class SendPayoutTxFinalizedMessage extends TradeTask { @Override public void onArrived() { log.trace("Message arrived at peer."); - trade.setState(Trade.State.PAYOUT_TX_SENT); complete(); } @Override public void onStoredInMailbox() { log.trace("Message stored in mailbox."); - trade.setState(Trade.State.PAYOUT_TX_SENT); complete(); } @Override public void onFault(String errorMessage) { - appendToErrorMessage("PayoutTxFinalizedMessage sending failed"); - failed(); + appendToErrorMessage("PayoutTxFinalizedMessage sending failed. errorMessage=" + errorMessage); + failed(errorMessage); } } ); + // state must not be set in onArrived or onStoredInMailbox handlers as we would get that + // called delayed and would overwrite the broad cast state set by the next task + trade.setState(Trade.State.PAYOUT_TX_SENT); } else { log.error("trade.getPayoutTx() = " + trade.getPayoutTx()); failed("PayoutTx is null"); diff --git a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/buyer/SignAndFinalizePayoutTx.java b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/buyer/SignAndFinalizePayoutTx.java index 61aeb83718..59fccf9c4f 100644 --- a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/buyer/SignAndFinalizePayoutTx.java +++ b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/buyer/SignAndFinalizePayoutTx.java @@ -57,7 +57,7 @@ public class SignAndFinalizePayoutTx extends TradeTask { ); trade.setPayoutTx(transaction); - trade.setState(Trade.State.PAYOUT_TX_RECEIVED_AND_COMMITTED); + trade.setState(Trade.State.PAYOUT_TX_COMMITTED); complete(); } catch (Throwable t) { diff --git a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/buyer/SignAndPublishDepositTxAsBuyer.java b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/buyer/SignAndPublishDepositTxAsBuyer.java index dbf5ac52c7..feb45aa775 100644 --- a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/buyer/SignAndPublishDepositTxAsBuyer.java +++ b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/buyer/SignAndPublishDepositTxAsBuyer.java @@ -51,8 +51,8 @@ public class SignAndPublishDepositTxAsBuyer extends TradeTask { false, contractHash, processModel.getPreparedDepositTx(), - processModel.getRawInputs(), - processModel.tradingPeer.getRawInputs(), + processModel.getRawTransactionInputs(), + processModel.tradingPeer.getRawTransactionInputs(), processModel.getTradeWalletPubKey(), processModel.tradingPeer.getTradeWalletPubKey(), processModel.getArbitratorPubKey(trade.getArbitratorNodeAddress()), diff --git a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/offerer/LoadTakeOfferFeeTx.java b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/offerer/LoadTakeOfferFeeTx.java index 8bb84229de..efb09add04 100644 --- a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/offerer/LoadTakeOfferFeeTx.java +++ b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/offerer/LoadTakeOfferFeeTx.java @@ -35,7 +35,7 @@ public class LoadTakeOfferFeeTx extends TradeTask { try { runInterceptHook(); - // TODO impl. not completed + // TODO impl. missing //processModel.getWalletService().findTxInBlockChain(processModel.getTakeOfferFeeTxId()); complete(); diff --git a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/offerer/ProcessPayDepositRequest.java b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/offerer/ProcessPayDepositRequest.java index 25111cdaa8..f3e9021e13 100644 --- a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/offerer/ProcessPayDepositRequest.java +++ b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/offerer/ProcessPayDepositRequest.java @@ -50,8 +50,8 @@ public class ProcessPayDepositRequest extends TradeTask { checkTradeId(processModel.getId(), payDepositRequest); checkNotNull(payDepositRequest); - processModel.tradingPeer.setRawInputs(checkNotNull(payDepositRequest.rawInputs)); - checkArgument(payDepositRequest.rawInputs.size() > 0); + processModel.tradingPeer.setRawTransactionInputs(checkNotNull(payDepositRequest.rawTransactionInputs)); + checkArgument(payDepositRequest.rawTransactionInputs.size() > 0); processModel.tradingPeer.setChangeOutputValue(payDepositRequest.changeOutputValue); if (payDepositRequest.changeOutputAddress != null) diff --git a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/offerer/SendPublishDepositTxRequest.java b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/offerer/SendPublishDepositTxRequest.java index 9ca9f98e06..187d798a4c 100644 --- a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/offerer/SendPublishDepositTxRequest.java +++ b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/offerer/SendPublishDepositTxRequest.java @@ -45,7 +45,7 @@ public class SendPublishDepositTxRequest extends TradeTask { trade.getOffererContractSignature(), processModel.getAddressEntry().getAddressString(), processModel.getPreparedDepositTx(), - processModel.getRawInputs(), + processModel.getRawTransactionInputs(), trade.getOpenDisputeTimeAsBlockHeight(), trade.getCheckPaymentTimeAsBlockHeight() ); diff --git a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/offerer/VerifyTakerAccount.java b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/offerer/VerifyTakerAccount.java index 72a9961b0f..59c18ee36e 100644 --- a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/offerer/VerifyTakerAccount.java +++ b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/offerer/VerifyTakerAccount.java @@ -34,7 +34,7 @@ public class VerifyTakerAccount extends TradeTask { protected void run() { try { runInterceptHook(); - //TODO mocked yet + //TODO impl. missing /* if (processModel.getBlockChainService().isAccountBlackListed(processModel.tradingPeer.getAccountId(), processModel.tradingPeer.getPaymentAccountContractData())) { log.error("Taker is blacklisted"); diff --git a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/seller/CreateAndSignDepositTxAsSeller.java b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/seller/CreateAndSignDepositTxAsSeller.java index d5e3f9a94d..aa0c5467b6 100644 --- a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/seller/CreateAndSignDepositTxAsSeller.java +++ b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/seller/CreateAndSignDepositTxAsSeller.java @@ -56,7 +56,7 @@ public class CreateAndSignDepositTxAsSeller extends TradeTask { contractHash, sellerInputAmount, msOutputAmount, - processModel.tradingPeer.getRawInputs(), + processModel.tradingPeer.getRawTransactionInputs(), processModel.tradingPeer.getChangeOutputValue(), processModel.tradingPeer.getChangeOutputAddress(), processModel.getAddressEntry(), @@ -65,7 +65,7 @@ public class CreateAndSignDepositTxAsSeller extends TradeTask { processModel.getArbitratorPubKey(trade.getArbitratorNodeAddress())); processModel.setPreparedDepositTx(result.depositTransaction); - processModel.setRawInputs(result.rawOffererInputs); + processModel.setRawTransactionInputs(result.rawOffererInputs); complete(); } catch (Throwable t) { diff --git a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/seller/CreateDepositTxInputsAsSeller.java b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/seller/CreateDepositTxInputsAsSeller.java index dc8d33faab..bb6ac807df 100644 --- a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/seller/CreateDepositTxInputsAsSeller.java +++ b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/seller/CreateDepositTxInputsAsSeller.java @@ -42,7 +42,7 @@ public class CreateDepositTxInputsAsSeller extends TradeTask { InputsAndChangeOutput result = processModel.getTradeWalletService().takerCreatesDepositsTxInputs(takerInputAmount, processModel .getAddressEntry()); - processModel.setRawInputs(result.rawInputs); + processModel.setRawTransactionInputs(result.rawTransactionInputs); processModel.setChangeOutputValue(result.changeOutputValue); processModel.setChangeOutputAddress(result.changeOutputAddress); diff --git a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/seller/SendFinalizePayoutTxRequest.java b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/seller/SendFinalizePayoutTxRequest.java index 90e9c95e14..43616afc22 100644 --- a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/seller/SendFinalizePayoutTxRequest.java +++ b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/seller/SendFinalizePayoutTxRequest.java @@ -66,8 +66,8 @@ public class SendFinalizePayoutTxRequest extends TradeTask { @Override public void onFault(String errorMessage) { - appendToErrorMessage("FinalizePayoutTxRequest sending failed"); - failed(); + appendToErrorMessage("FinalizePayoutTxRequest sending failed. errorMessage=" + errorMessage); + failed(errorMessage); } } ); diff --git a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/seller/SignAndPublishDepositTxAsSeller.java b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/seller/SignAndPublishDepositTxAsSeller.java index aa64876945..62e09d1795 100644 --- a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/seller/SignAndPublishDepositTxAsSeller.java +++ b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/seller/SignAndPublishDepositTxAsSeller.java @@ -49,8 +49,8 @@ public class SignAndPublishDepositTxAsSeller extends TradeTask { true, contractHash, processModel.getPreparedDepositTx(), - processModel.tradingPeer.getRawInputs(), - processModel.getRawInputs(), + processModel.tradingPeer.getRawTransactionInputs(), + processModel.getRawTransactionInputs(), processModel.tradingPeer.getTradeWalletPubKey(), processModel.getTradeWalletPubKey(), processModel.getArbitratorPubKey(trade.getArbitratorNodeAddress()), diff --git a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/taker/LoadCreateOfferFeeTx.java b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/taker/LoadCreateOfferFeeTx.java index e028b8022c..1956dd61ce 100644 --- a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/taker/LoadCreateOfferFeeTx.java +++ b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/taker/LoadCreateOfferFeeTx.java @@ -35,7 +35,7 @@ public class LoadCreateOfferFeeTx extends TradeTask { try { runInterceptHook(); - // TODO impl. not completed + // TODO impl. missing ///processModel.getWalletService().findTxInBlockChain(trade.getOffer().getOfferFeePaymentTxID()); complete(); diff --git a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/taker/ProcessPublishDepositTxRequest.java b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/taker/ProcessPublishDepositTxRequest.java index 2628b7c010..21f6cd047f 100644 --- a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/taker/ProcessPublishDepositTxRequest.java +++ b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/taker/ProcessPublishDepositTxRequest.java @@ -63,7 +63,7 @@ public class ProcessPublishDepositTxRequest extends TradeTask { processModel.tradingPeer.setContractAsJson(nonEmptyStringOf(publishDepositTxRequest.offererContractAsJson)); processModel.tradingPeer.setContractSignature(nonEmptyStringOf(publishDepositTxRequest.offererContractSignature)); processModel.tradingPeer.setPayoutAddressString(nonEmptyStringOf(publishDepositTxRequest.offererPayoutAddressString)); - processModel.tradingPeer.setRawInputs(checkNotNull(publishDepositTxRequest.offererInputs)); + processModel.tradingPeer.setRawTransactionInputs(checkNotNull(publishDepositTxRequest.offererInputs)); processModel.setPreparedDepositTx(checkNotNull(publishDepositTxRequest.preparedDepositTx)); checkArgument(publishDepositTxRequest.offererInputs.size() > 0); if (publishDepositTxRequest.openDisputeTimeAsBlockHeight != 0) { diff --git a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/taker/SendPayDepositRequest.java b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/taker/SendPayDepositRequest.java index af94463592..c6b8302366 100644 --- a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/taker/SendPayDepositRequest.java +++ b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/taker/SendPayDepositRequest.java @@ -25,6 +25,8 @@ import io.bitsquare.trade.protocol.trade.tasks.TradeTask; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.ArrayList; + import static com.google.common.base.Preconditions.checkNotNull; public class SendPayDepositRequest extends TradeTask { @@ -47,7 +49,7 @@ public class SendPayDepositRequest extends TradeTask { processModel.getMyAddress(), processModel.getId(), trade.getTradeAmount().value, - processModel.getRawInputs(), + processModel.getRawTransactionInputs(), processModel.getChangeOutputValue(), processModel.getChangeOutputAddress(), processModel.getTradeWalletPubKey(), @@ -56,7 +58,7 @@ public class SendPayDepositRequest extends TradeTask { processModel.getPaymentAccountContractData(trade), processModel.getAccountId(), trade.getTakeOfferFeeTxId(), - processModel.getUser().getAcceptedArbitratorAddresses(), + new ArrayList<>(processModel.getUser().getAcceptedArbitratorAddresses()), trade.getArbitratorNodeAddress() ); diff --git a/core/src/main/java/io/bitsquare/user/User.java b/core/src/main/java/io/bitsquare/user/User.java index f11065e51b..6debe2c345 100644 --- a/core/src/main/java/io/bitsquare/user/User.java +++ b/core/src/main/java/io/bitsquare/user/User.java @@ -201,14 +201,6 @@ public final class User implements Persistable { // Getters /////////////////////////////////////////////////////////////////////////////////////////// - // TODO just a first attempt, refine when working on the embedded data for the reg. tx - public String getStringifiedBankAccounts() { - return paymentAccounts.stream() - .map(PaymentAccount::getId) - .collect(Collectors.joining(", ")); - } - - public PaymentAccount getPaymentAccount(String paymentAccountId) { Optional optional = paymentAccounts.stream().filter(e -> e.getId().equals(paymentAccountId)).findAny(); if (optional.isPresent()) diff --git a/gui/src/main/java/io/bitsquare/app/BitsquareApp.java b/gui/src/main/java/io/bitsquare/app/BitsquareApp.java index 51cbcbf5c3..1d5679f9cd 100644 --- a/gui/src/main/java/io/bitsquare/app/BitsquareApp.java +++ b/gui/src/main/java/io/bitsquare/app/BitsquareApp.java @@ -220,7 +220,7 @@ public class BitsquareApp extends Application { private void showSendAlertMessagePopup() { AlertManager alertManager = injector.getInstance(AlertManager.class); new SendAlertMessagePopup() - .onAddAlertMessage((alertMessage, privKeyString) -> alertManager.addAlertMessageIfKeyIsValid(alertMessage, privKeyString)) + .onAddAlertMessage((alert, privKeyString) -> alertManager.addAlertMessageIfKeyIsValid(alert, privKeyString)) .onRemoveAlertMessage(privKeyString -> alertManager.removeAlertMessageIfKeyIsValid(privKeyString)) .show(); } diff --git a/gui/src/main/java/io/bitsquare/gui/bitsquare.css b/gui/src/main/java/io/bitsquare/gui/bitsquare.css index 1efa722328..67b8e60d2c 100644 --- a/gui/src/main/java/io/bitsquare/gui/bitsquare.css +++ b/gui/src/main/java/io/bitsquare/gui/bitsquare.css @@ -866,7 +866,7 @@ textfield */ -fx-text-fill: white; -fx-font-weight: bold; -fx-font-size: 15; - -fx-background-radius: 20; + /*-fx-background-radius: 20;*/ } #buy-button-big:hover { @@ -878,7 +878,7 @@ textfield */ -fx-text-fill: white; -fx-font-weight: bold; -fx-font-size: 15; - -fx-background-radius: 20; + /* -fx-background-radius: 20;*/ } #sell-button-big:hover { @@ -889,7 +889,7 @@ textfield */ -fx-base: -bs-buy; -fx-text-fill: white; -fx-font-weight: bold; - -fx-background-radius: 13; + /* -fx-background-radius: 13;*/ } #buy-button:hover { @@ -900,7 +900,7 @@ textfield */ -fx-base: -bs-sell; -fx-text-fill: white; -fx-font-weight: bold; - -fx-background-radius: 13; + /* -fx-background-radius: 13;*/ } #sell-button:hover { @@ -911,7 +911,7 @@ textfield */ -fx-base: -bs-light-grey; -fx-text-fill: white; -fx-font-weight: bold; - -fx-background-radius: 13; + /* -fx-background-radius: 13;*/ } #cancel-button:hover { @@ -925,12 +925,12 @@ textfield */ ********************************************************************************************************************/ #popup-headline { - -fx-font-size: 18; + -fx-font-size: 16; -fx-text-fill: #333; } #popup-bg { - -fx-font-size: 15; + -fx-font-size: 14; -fx-text-fill: #333; -fx-background-color: white; -fx-background-radius: 5 5 5 5; diff --git a/gui/src/main/java/io/bitsquare/gui/main/MainViewModel.java b/gui/src/main/java/io/bitsquare/gui/main/MainViewModel.java index 3502382f0e..5442ac0b6e 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/MainViewModel.java +++ b/gui/src/main/java/io/bitsquare/gui/main/MainViewModel.java @@ -343,7 +343,7 @@ public class MainViewModel implements ViewModel { numberOfBtcPeersTimer = UserThread.runAfter(() -> { if (walletService.numPeersProperty().get() == 0) { walletServiceErrorMsg.set("You lost the connection to all bitcoin network peers.\n" + - "Maybe you lost your internet connection or your computer was in hibernate/sleep mode."); + "Maybe you lost your internet connection or your computer was in standby mode."); } else { walletServiceErrorMsg.set(null); } @@ -534,7 +534,7 @@ public class MainViewModel implements ViewModel { numberOfP2PNetworkPeersTimer = UserThread.runAfter(() -> { if (p2PService.getNumConnectedPeers().get() == 0) { p2PNetworkWarnMsg.set("You lost the connection to all P2P network peers.\n" + - "Maybe you lost your internet connection or your computer was in hibernate/sleep mode."); + "Maybe you lost your internet connection or your computer was in standby mode."); p2PNetworkLabelId.set("splash-error-state-msg"); } else { p2PNetworkWarnMsg.set(null); diff --git a/gui/src/main/java/io/bitsquare/gui/main/funds/transactions/TransactionsListItem.java b/gui/src/main/java/io/bitsquare/gui/main/funds/transactions/TransactionsListItem.java index 6820982fac..75df4d2e8d 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/funds/transactions/TransactionsListItem.java +++ b/gui/src/main/java/io/bitsquare/gui/main/funds/transactions/TransactionsListItem.java @@ -131,9 +131,9 @@ public class TransactionsListItem { details = "MultiSig payout: " + tradable.getShortId(); } else if (trade.getDisputeState() == Trade.DisputeState.DISPUTE_CLOSED) { if (valueSentToMe.isPositive()) - details = "Refund from dispute: " + tradable.getShortId(); + details = "Dispute payout: " + tradable.getShortId(); else - details = "Nothing refunded from dispute: " + tradable.getShortId(); + details = "Lost dispute case: " + tradable.getShortId(); } else { details = "Unknown reason: " + tradable.getShortId(); } diff --git a/gui/src/main/java/io/bitsquare/gui/main/funds/transactions/TransactionsView.fxml b/gui/src/main/java/io/bitsquare/gui/main/funds/transactions/TransactionsView.fxml index f198e78543..0b62c438ff 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/funds/transactions/TransactionsView.fxml +++ b/gui/src/main/java/io/bitsquare/gui/main/funds/transactions/TransactionsView.fxml @@ -33,7 +33,7 @@ - + diff --git a/gui/src/main/java/io/bitsquare/gui/main/funds/transactions/TransactionsView.java b/gui/src/main/java/io/bitsquare/gui/main/funds/transactions/TransactionsView.java index c6d89798dc..918e6f9c26 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/funds/transactions/TransactionsView.java +++ b/gui/src/main/java/io/bitsquare/gui/main/funds/transactions/TransactionsView.java @@ -172,31 +172,40 @@ public class TransactionsView extends ActivatableView { List listItems = walletService.getWallet().getRecentTransactions(1000, true).stream() .map(transaction -> { + log.error("tx ID " + transaction.getHashAsString()); Optional tradableOptional = all.stream() - .filter(e -> { + .filter(tradable -> { String txId = transaction.getHashAsString(); - if (e instanceof OpenOffer) - return e.getOffer().getOfferFeePaymentTxID().equals(txId); - else if (e instanceof Trade) { - Trade trade = (Trade) e; - return (trade.getTakeOfferFeeTxId() != null && - trade.getTakeOfferFeeTxId().equals(txId)) || - (trade.getOffer() != null && - trade.getOffer().getOfferFeePaymentTxID() != null && - trade.getOffer().getOfferFeePaymentTxID().equals(txId)) || - (trade.getDepositTx() != null && - trade.getDepositTx().getHashAsString().equals(txId)) || - (trade.getPayoutTx() != null && - trade.getPayoutTx().getHashAsString().equals(txId)) || - (disputeManager.getDisputesAsObservableList().stream() - .filter(dispute -> dispute.getDisputePayoutTx() != null && - dispute.getDisputePayoutTx().getHashAsString().equals(txId)) - .findAny() - .isPresent()); + if (tradable instanceof OpenOffer) + return tradable.getOffer().getOfferFeePaymentTxID().equals(txId); + else if (tradable instanceof Trade) { + Trade trade = (Trade) tradable; + boolean isTakeOfferFeeTx = txId.equals(trade.getTakeOfferFeeTxId()); + boolean isOfferFeeTx = trade.getOffer() != null && + txId.equals(trade.getOffer().getOfferFeePaymentTxID()); + boolean isDepositTx = trade.getDepositTx() != null && + trade.getDepositTx().getHashAsString().equals(txId); + boolean isPayoutTx = trade.getPayoutTx() != null && + trade.getPayoutTx().getHashAsString().equals(txId); + + boolean isDisputedPayoutTx = disputeManager.getDisputesAsObservableList().stream() + .filter(dispute -> txId.equals(dispute.getDisputePayoutTxId()) && + tradable.getId().equals(dispute.getTradeId())) + .findAny() + .isPresent(); + log.error("isTakeOfferFeeTx " + isTakeOfferFeeTx); + log.error("isOfferFeeTx " + isOfferFeeTx); + log.error("isDepositTx " + isDepositTx); + log.error("isPayoutTx " + isPayoutTx); + log.error("isDisputedPayoutTx " + isDisputedPayoutTx); + + return isTakeOfferFeeTx || isOfferFeeTx || isDepositTx || isPayoutTx || isDisputedPayoutTx; } else return false; }) .findAny(); + if (tradableOptional.isPresent()) + log.error("tradableOptional " + tradableOptional.get().getId()); return new TransactionsListItem(transaction, walletService, tradableOptional, formatter); }) .collect(Collectors.toList()); diff --git a/gui/src/main/java/io/bitsquare/gui/main/offer/createoffer/CreateOfferDataModel.java b/gui/src/main/java/io/bitsquare/gui/main/offer/createoffer/CreateOfferDataModel.java index fd982b738c..284a875030 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/offer/createoffer/CreateOfferDataModel.java +++ b/gui/src/main/java/io/bitsquare/gui/main/offer/createoffer/CreateOfferDataModel.java @@ -52,6 +52,7 @@ import org.bitcoinj.utils.ExchangeRate; import org.bitcoinj.utils.Fiat; import org.jetbrains.annotations.NotNull; +import java.util.ArrayList; import java.util.List; import java.util.UUID; @@ -237,9 +238,9 @@ class CreateOfferDataModel extends ActivatableDataModel { long amount = amountAsCoin.get() != null ? amountAsCoin.get().getValue() : 0L; long minAmount = minAmountAsCoin.get() != null ? minAmountAsCoin.get().getValue() : 0L; - List acceptedCountryCodes = null; + ArrayList acceptedCountryCodes = new ArrayList<>(); if (paymentAccount instanceof SepaAccount) - acceptedCountryCodes = ((SepaAccount) paymentAccount).getAcceptedCountryCodes(); + acceptedCountryCodes.addAll(((SepaAccount) paymentAccount).getAcceptedCountryCodes()); // That is optional and set to null if not supported (AltCoins, OKPay,...) Country country = paymentAccount.getCountry(); @@ -256,7 +257,7 @@ class CreateOfferDataModel extends ActivatableDataModel { tradeCurrencyCode.get(), country, paymentAccount.getId(), - user.getAcceptedArbitratorAddresses(), + new ArrayList<>(user.getAcceptedArbitratorAddresses()), acceptedCountryCodes); } diff --git a/gui/src/main/java/io/bitsquare/gui/main/popups/ContractPopup.java b/gui/src/main/java/io/bitsquare/gui/main/popups/ContractPopup.java index dea31da7cb..7afd2a210b 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/popups/ContractPopup.java +++ b/gui/src/main/java/io/bitsquare/gui/main/popups/ContractPopup.java @@ -130,7 +130,7 @@ public class ContractPopup extends Popup { addLabelTextField(gridPane, ++rowIndex, "Seller payment ID:", ((BlockChainAccountContractData) sellerPaymentAccountContractData).getPaymentId()); - if (offer.getAcceptedCountryCodes() != null) { + if (offer.getAcceptedCountryCodes() != null && !offer.getAcceptedCountryCodes().isEmpty()) { String countries; Tooltip tooltip = null; if (CountryUtil.containsAllSepaEuroCountries(offer.getAcceptedCountryCodes())) { diff --git a/gui/src/main/java/io/bitsquare/gui/main/popups/DisputeSummaryPopup.java b/gui/src/main/java/io/bitsquare/gui/main/popups/DisputeSummaryPopup.java index 6609e72f1d..7d7b7ce01d 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/popups/DisputeSummaryPopup.java +++ b/gui/src/main/java/io/bitsquare/gui/main/popups/DisputeSummaryPopup.java @@ -71,8 +71,8 @@ public class DisputeSummaryPopup extends Popup { private ToggleGroup feeToggleGroup; private String role; private TextArea summaryNotesTextArea; - private ObjectBinding> feePaymentPolicyChanged; - private ChangeListener> feePaymentPolicyListener; + private ObjectBinding> feePaymentPolicyChanged; + private ChangeListener> feePaymentPolicyListener; private ChangeListener shareRadioButtonSelectedListener; private ChangeListener feeToggleSelectionListener; // keep a reference to not get GCed @@ -163,7 +163,7 @@ public class DisputeSummaryPopup extends Popup { disputeResult.setBuyerPayoutAmount(peersDisputeResult.getBuyerPayoutAmount()); disputeResult.setSellerPayoutAmount(peersDisputeResult.getSellerPayoutAmount()); disputeResult.setArbitratorPayoutAmount(peersDisputeResult.getArbitratorPayoutAmount()); - disputeResult.setFeePaymentPolicy(peersDisputeResult.getFeePaymentPolicy()); + disputeResult.setDisputeFeePolicy(peersDisputeResult.getDisputeFeePolicy()); disputeResult.setWinner(peersDisputeResult.getWinner()); if (disputeResult.getBuyerPayoutAmount() != null) { @@ -181,13 +181,13 @@ public class DisputeSummaryPopup extends Popup { splitFeeRadioButton.setDisable(true); waiveFeeRadioButton.setDisable(true); - calculatePayoutAmounts(disputeResult.getFeePaymentPolicy()); + calculatePayoutAmounts(disputeResult.getDisputeFeePolicy()); applyTradeAmountRadioButtonStates(); } else { - applyPayoutAmounts(disputeResult.feePaymentPolicyProperty().get(), tradeAmountToggleGroup.selectedToggleProperty().get()); + applyPayoutAmounts(disputeResult.disputeFeePolicyProperty().get(), tradeAmountToggleGroup.selectedToggleProperty().get()); feePaymentPolicyChanged = Bindings.createObjectBinding( - () -> new Tuple2(disputeResult.feePaymentPolicyProperty().get(), tradeAmountToggleGroup.selectedToggleProperty().get()), - disputeResult.feePaymentPolicyProperty(), + () -> new Tuple2(disputeResult.disputeFeePolicyProperty().get(), tradeAmountToggleGroup.selectedToggleProperty().get()), + disputeResult.disputeFeePolicyProperty(), tradeAmountToggleGroup.selectedToggleProperty()); feePaymentPolicyListener = (observable, oldValue, newValue) -> { applyPayoutAmounts(newValue.first, newValue.second); @@ -302,11 +302,11 @@ public class DisputeSummaryPopup extends Popup { feeToggleSelectionListener = (observable, oldValue, newValue) -> { if (newValue == loserPaysFeeRadioButton) - disputeResult.setFeePaymentPolicy(DisputeResult.FeePaymentPolicy.LOSER); + disputeResult.setDisputeFeePolicy(DisputeResult.DisputeFeePolicy.LOSER); else if (newValue == splitFeeRadioButton) - disputeResult.setFeePaymentPolicy(DisputeResult.FeePaymentPolicy.SPLIT); + disputeResult.setDisputeFeePolicy(DisputeResult.DisputeFeePolicy.SPLIT); else if (newValue == waiveFeeRadioButton) - disputeResult.setFeePaymentPolicy(DisputeResult.FeePaymentPolicy.WAIVE); + disputeResult.setDisputeFeePolicy(DisputeResult.DisputeFeePolicy.WAIVE); }; feeToggleGroup.selectedToggleProperty().addListener(feeToggleSelectionListener); @@ -315,7 +315,7 @@ public class DisputeSummaryPopup extends Popup { } private void setFeeRadioButtonState() { - switch (disputeResult.getFeePaymentPolicy()) { + switch (disputeResult.getDisputeFeePolicy()) { case LOSER: feeToggleGroup.selectToggle(loserPaysFeeRadioButton); break; @@ -417,7 +417,7 @@ public class DisputeSummaryPopup extends Popup { // Controller /////////////////////////////////////////////////////////////////////////////////////////// - private void applyPayoutAmounts(DisputeResult.FeePaymentPolicy feePayment, Toggle selectedTradeAmountToggle) { + private void applyPayoutAmounts(DisputeResult.DisputeFeePolicy feePayment, Toggle selectedTradeAmountToggle) { calculatePayoutAmounts(feePayment); if (selectedTradeAmountToggle != null) { applyPayoutAmountsToDisputeResult(selectedTradeAmountToggle); @@ -425,7 +425,7 @@ public class DisputeSummaryPopup extends Popup { } } - private void calculatePayoutAmounts(DisputeResult.FeePaymentPolicy feePayment) { + private void calculatePayoutAmounts(DisputeResult.DisputeFeePolicy feePayment) { Contract contract = dispute.getContract(); Coin refund = FeePolicy.getSecurityDeposit(); Coin winnerRefund; diff --git a/gui/src/main/java/io/bitsquare/gui/main/popups/Popup.java b/gui/src/main/java/io/bitsquare/gui/main/popups/Popup.java index d0b03713d9..33d608b056 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/popups/Popup.java +++ b/gui/src/main/java/io/bitsquare/gui/main/popups/Popup.java @@ -103,23 +103,26 @@ public class Popup { public void hide() { animateHide(() -> { - Window window = owner.getScene().getWindow(); - window.xProperty().removeListener(positionListener); - window.yProperty().removeListener(positionListener); - window.widthProperty().removeListener(positionListener); + Scene rootScene = owner.getScene(); + if (rootScene != null) { + Window window = rootScene.getWindow(); + window.xProperty().removeListener(positionListener); + window.yProperty().removeListener(positionListener); + window.widthProperty().removeListener(positionListener); - if (centerTime != null) - centerTime.stop(); + if (centerTime != null) + centerTime.stop(); - removeEffectFromBackground(); + removeEffectFromBackground(); - if (stage != null) - stage.hide(); - else - log.warn("Stage is null"); + if (stage != null) + stage.hide(); + else + log.warn("Stage is null"); - cleanup(); - PopupManager.isHidden(Popup.this); + cleanup(); + PopupManager.isHidden(Popup.this); + } }); } @@ -245,39 +248,42 @@ public class Popup { if (owner == null) owner = MainView.getRootContainer(); - stage = new Stage(); - Scene scene = new Scene(gridPane); - scene.getStylesheets().setAll(owner.getScene().getStylesheets()); - scene.setFill(Color.TRANSPARENT); - stage.setScene(scene); - setModality(); - stage.initStyle(StageStyle.TRANSPARENT); - Window window = owner.getScene().getWindow(); - stage.initOwner(window); - stage.show(); + Scene rootScene = owner.getScene(); + if (rootScene != null) { + stage = new Stage(); + Scene scene = new Scene(gridPane); + scene.getStylesheets().setAll(rootScene.getStylesheets()); + scene.setFill(Color.TRANSPARENT); + stage.setScene(scene); + setModality(); + stage.initStyle(StageStyle.TRANSPARENT); + Window window = rootScene.getWindow(); + stage.initOwner(window); + stage.show(); - layout(); + layout(); - addEffectToBackground(); + addEffectToBackground(); - // On Linux the owner stage does not move the child stage as it does on Mac - // So we need to apply centerPopup. Further with fast movements the handler loses - // the latest position, with a delay it fixes that. - // Also on Mac sometimes the popups are positioned outside of the main app, so keep it for all OS - positionListener = (observable, oldValue, newValue) -> { - if (stage != null) { - layout(); - if (centerTime != null) - centerTime.stop(); + // On Linux the owner stage does not move the child stage as it does on Mac + // So we need to apply centerPopup. Further with fast movements the handler loses + // the latest position, with a delay it fixes that. + // Also on Mac sometimes the popups are positioned outside of the main app, so keep it for all OS + positionListener = (observable, oldValue, newValue) -> { + if (stage != null) { + layout(); + if (centerTime != null) + centerTime.stop(); - centerTime = UserThread.runAfter(this::layout, 3); - } - }; - window.xProperty().addListener(positionListener); - window.yProperty().addListener(positionListener); - window.widthProperty().addListener(positionListener); + centerTime = UserThread.runAfter(this::layout, 3); + } + }; + window.xProperty().addListener(positionListener); + window.yProperty().addListener(positionListener); + window.widthProperty().addListener(positionListener); - animateDisplay(); + animateDisplay(); + } } protected void animateDisplay() { @@ -302,10 +308,13 @@ public class Popup { } protected void layout() { - Window window = owner.getScene().getWindow(); - double titleBarHeight = window.getHeight() - owner.getScene().getHeight(); - stage.setX(Math.round(window.getX() + (owner.getWidth() - stage.getWidth()) / 2)); - stage.setY(Math.round(window.getY() + titleBarHeight + (owner.getHeight() - stage.getHeight()) / 2)); + Scene rootScene = owner.getScene(); + if (rootScene != null) { + Window window = rootScene.getWindow(); + double titleBarHeight = window.getHeight() - rootScene.getHeight(); + stage.setX(Math.round(window.getX() + (owner.getWidth() - stage.getWidth()) / 2)); + stage.setY(Math.round(window.getY() + titleBarHeight + (owner.getHeight() - stage.getHeight()) / 2)); + } } protected void addHeadLine() { diff --git a/gui/src/main/java/io/bitsquare/gui/main/popups/TradeDetailsPopup.java b/gui/src/main/java/io/bitsquare/gui/main/popups/TradeDetailsPopup.java index b3ecfbf9d2..ce44f09633 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/popups/TradeDetailsPopup.java +++ b/gui/src/main/java/io/bitsquare/gui/main/popups/TradeDetailsPopup.java @@ -180,8 +180,8 @@ public class TradeDetailsPopup extends Popup { addLabelTxIdTextField(gridPane, ++rowIndex, "Deposit transaction ID:", trade.getDepositTx().getHashAsString()); if (trade.getPayoutTx() != null) addLabelTxIdTextField(gridPane, ++rowIndex, "Payout transaction ID:", trade.getPayoutTx().getHashAsString()); - if (disputeManager.findOwnDispute(trade.getId()).isPresent() && disputeManager.findOwnDispute(trade.getId()).get().getDisputePayoutTx() != null) - addLabelTxIdTextField(gridPane, ++rowIndex, "Disputed payout transaction ID:", disputeManager.findOwnDispute(trade.getId()).get().getDisputePayoutTx().getHashAsString()); + if (disputeManager.findOwnDispute(trade.getId()).isPresent() && disputeManager.findOwnDispute(trade.getId()).get().getDisputePayoutTxId() != null) + addLabelTxIdTextField(gridPane, ++rowIndex, "Disputed payout transaction ID:", disputeManager.findOwnDispute(trade.getId()).get().getDisputePayoutTxId()); if (contract != null) { TextArea textArea = addLabelTextArea(gridPane, ++rowIndex, "Contract in JSON format:", trade.getContractAsJson()).second; diff --git a/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/PendingTradesView.java b/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/PendingTradesView.java index 4ac3dca90f..54d05c26bc 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/PendingTradesView.java +++ b/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/PendingTradesView.java @@ -245,13 +245,13 @@ public class PendingTradesView extends ActivatableViewAndModel. */ -package io.bitsquare.p2p.messaging; +package io.bitsquare.crypto; -import io.bitsquare.app.Version; import io.bitsquare.p2p.Message; import java.security.PublicKey; -// TODO is that sent over wire???? -public final class DecryptedMsgWithPubKey implements DirectMessage { - // That object is sent over the wire, so we need to take care of version compatibility. - private static final long serialVersionUID = Version.P2P_NETWORK_VERSION; - - private final int messageVersion = Version.getP2PMessageVersion(); +public final class DecryptedMsgWithPubKey { public final Message message; public final PublicKey signaturePubKey; @@ -36,11 +30,6 @@ public final class DecryptedMsgWithPubKey implements DirectMessage { this.signaturePubKey = signaturePubKey; } - @Override - public int getMessageVersion() { - return messageVersion; - } - @Override public boolean equals(Object o) { if (this == o) return true; @@ -48,7 +37,6 @@ public final class DecryptedMsgWithPubKey implements DirectMessage { DecryptedMsgWithPubKey that = (DecryptedMsgWithPubKey) o; - //noinspection SimplifiableIfStatement if (message != null ? !message.equals(that.message) : that.message != null) return false; return !(signaturePubKey != null ? !signaturePubKey.equals(that.signaturePubKey) : that.signaturePubKey != null); @@ -64,7 +52,6 @@ public final class DecryptedMsgWithPubKey implements DirectMessage { @Override public String toString() { return "DecryptedMsgWithPubKey{" + - "messageVersion=" + messageVersion + ", message=" + message + ", signaturePubKey.hashCode()=" + signaturePubKey.hashCode() + '}'; diff --git a/network/src/main/java/io/bitsquare/crypto/EncryptionService.java b/network/src/main/java/io/bitsquare/crypto/EncryptionService.java index 8b60480a88..e5af3a0d6b 100644 --- a/network/src/main/java/io/bitsquare/crypto/EncryptionService.java +++ b/network/src/main/java/io/bitsquare/crypto/EncryptionService.java @@ -19,7 +19,6 @@ package io.bitsquare.crypto; import io.bitsquare.common.crypto.*; import io.bitsquare.p2p.Message; -import io.bitsquare.p2p.messaging.DecryptedMsgWithPubKey; import javax.inject.Inject; import java.security.KeyPair; diff --git a/network/src/main/java/io/bitsquare/p2p/P2PService.java b/network/src/main/java/io/bitsquare/p2p/P2PService.java index 402f4041f3..694fb1e3f7 100644 --- a/network/src/main/java/io/bitsquare/p2p/P2PService.java +++ b/network/src/main/java/io/bitsquare/p2p/P2PService.java @@ -14,8 +14,8 @@ import io.bitsquare.common.UserThread; import io.bitsquare.common.crypto.CryptoException; import io.bitsquare.common.crypto.KeyRing; import io.bitsquare.common.crypto.PubKeyRing; +import io.bitsquare.crypto.DecryptedMsgWithPubKey; import io.bitsquare.crypto.EncryptionService; -import io.bitsquare.crypto.PrefixedSealedAndSignedMessage; import io.bitsquare.p2p.messaging.*; import io.bitsquare.p2p.network.*; import io.bitsquare.p2p.peers.Broadcaster; @@ -26,12 +26,12 @@ import io.bitsquare.p2p.peers.peerexchange.PeerExchangeManager; import io.bitsquare.p2p.seed.SeedNodesRepository; import io.bitsquare.p2p.storage.HashMapChangedListener; import io.bitsquare.p2p.storage.P2PDataStorage; -import io.bitsquare.p2p.storage.data.ExpirablePayload; -import io.bitsquare.p2p.storage.data.MailboxPayload; -import io.bitsquare.p2p.storage.data.ProtectedData; -import io.bitsquare.p2p.storage.data.ProtectedMailboxData; import io.bitsquare.p2p.storage.messages.AddDataMessage; import io.bitsquare.p2p.storage.messages.RefreshTTLMessage; +import io.bitsquare.p2p.storage.payload.MailboxStoragePayload; +import io.bitsquare.p2p.storage.payload.StoragePayload; +import io.bitsquare.p2p.storage.storageentry.ProtectedMailboxStorageEntry; +import io.bitsquare.p2p.storage.storageentry.ProtectedStorageEntry; import javafx.beans.property.*; import javafx.beans.value.ChangeListener; import org.fxmisc.easybind.EasyBind; @@ -74,7 +74,7 @@ public class P2PService implements SetupListener, MessageListener, ConnectionLis private final Set decryptedDirectMessageListeners = new CopyOnWriteArraySet<>(); private final Set decryptedMailboxListeners = new CopyOnWriteArraySet<>(); private final Set p2pServiceListeners = new CopyOnWriteArraySet<>(); - private final Map mailboxMap = new HashMap<>(); + private final Map mailboxMap = new HashMap<>(); private final Set shutDownResultHandlers = new CopyOnWriteArraySet<>(); private final BooleanProperty hiddenServicePublished = new SimpleBooleanProperty(); private final BooleanProperty preliminaryDataReceived = new SimpleBooleanProperty(); @@ -131,7 +131,7 @@ public class P2PService implements SetupListener, MessageListener, ConnectionLis p2PDataStorage = new P2PDataStorage(broadcaster, networkNode, storageDir); p2PDataStorage.addHashMapChangedListener(this); - + requestDataManager = new RequestDataManager(networkNode, p2PDataStorage, peerManager, seedNodeAddresses, this); peerExchangeManager = new PeerExchangeManager(networkNode, peerManager, seedNodeAddresses); @@ -177,7 +177,7 @@ public class P2PService implements SetupListener, MessageListener, ConnectionLis if (broadcaster != null) broadcaster.shutDown(); - + if (requestDataManager != null) requestDataManager.shutDown(); @@ -375,13 +375,13 @@ public class P2PService implements SetupListener, MessageListener, ConnectionLis /////////////////////////////////////////////////////////////////////////////////////////// @Override - public void onAdded(ProtectedData data) { - if (data instanceof ProtectedMailboxData) - processProtectedMailboxData((ProtectedMailboxData) data); + public void onAdded(ProtectedStorageEntry protectedStorageEntry) { + if (protectedStorageEntry instanceof ProtectedMailboxStorageEntry) + processProtectedMailboxStorageEntry((ProtectedMailboxStorageEntry) protectedStorageEntry); } @Override - public void onRemoved(ProtectedData data) { + public void onRemoved(ProtectedStorageEntry data) { } @@ -437,45 +437,42 @@ public class P2PService implements SetupListener, MessageListener, ConnectionLis // MailboxMessages /////////////////////////////////////////////////////////////////////////////////////////// - private void processProtectedMailboxData(ProtectedMailboxData mailboxData) { + private void processProtectedMailboxStorageEntry(ProtectedMailboxStorageEntry protectedMailboxStorageEntry) { // Seed nodes don't have set the encryptionService if (optionalEncryptionService.isPresent()) { Log.traceCall(); - ExpirablePayload expirablePayload = mailboxData.expirablePayload; - if (expirablePayload instanceof MailboxPayload) { - MailboxPayload expirableMailboxPayload = (MailboxPayload) expirablePayload; - PrefixedSealedAndSignedMessage prefixedSealedAndSignedMessage = expirableMailboxPayload.prefixedSealedAndSignedMessage; - if (verifyAddressPrefixHash(prefixedSealedAndSignedMessage)) { - try { - DecryptedMsgWithPubKey decryptedMsgWithPubKey = optionalEncryptionService.get().decryptAndVerify( - prefixedSealedAndSignedMessage.sealedAndSigned); - if (decryptedMsgWithPubKey.message instanceof io.bitsquare.p2p.messaging.MailboxMessage) { - io.bitsquare.p2p.messaging.MailboxMessage mailboxMessage = (io.bitsquare.p2p.messaging.MailboxMessage) decryptedMsgWithPubKey.message; - NodeAddress senderNodeAddress = mailboxMessage.getSenderNodeAddress(); - checkNotNull(senderNodeAddress, "senderAddress must not be null for mailbox messages"); + MailboxStoragePayload mailboxStoragePayload = protectedMailboxStorageEntry.getMailboxStoragePayload(); + PrefixedSealedAndSignedMessage prefixedSealedAndSignedMessage = mailboxStoragePayload.prefixedSealedAndSignedMessage; + if (verifyAddressPrefixHash(prefixedSealedAndSignedMessage)) { + try { + DecryptedMsgWithPubKey decryptedMsgWithPubKey = optionalEncryptionService.get().decryptAndVerify( + prefixedSealedAndSignedMessage.sealedAndSigned); + if (decryptedMsgWithPubKey.message instanceof MailboxMessage) { + MailboxMessage mailboxMessage = (MailboxMessage) decryptedMsgWithPubKey.message; + NodeAddress senderNodeAddress = mailboxMessage.getSenderNodeAddress(); + checkNotNull(senderNodeAddress, "senderAddress must not be null for mailbox messages"); - mailboxMap.put(decryptedMsgWithPubKey, mailboxData); - log.trace("Decryption of SealedAndSignedMessage succeeded. senderAddress=" - + senderNodeAddress + " / my address=" + getAddress()); - decryptedMailboxListeners.stream().forEach( - e -> e.onMailboxMessageAdded(decryptedMsgWithPubKey, senderNodeAddress)); - } else { - log.warn("tryDecryptMailboxData: Expected MailboxMessage but got other type. " + - "decryptedMsgWithPubKey.message=", decryptedMsgWithPubKey.message); - } - } catch (CryptoException e) { - log.trace("Decryption of SealedAndSignedMessage failed. " + - "That is expected if the message is not intended for us. " + e.getMessage()); + mailboxMap.put(mailboxMessage.getUID(), protectedMailboxStorageEntry); + log.trace("Decryption of SealedAndSignedMessage succeeded. senderAddress=" + + senderNodeAddress + " / my address=" + getAddress()); + decryptedMailboxListeners.stream().forEach( + e -> e.onMailboxMessageAdded(decryptedMsgWithPubKey, senderNodeAddress)); + } else { + log.warn("tryDecryptMailboxData: Expected MailboxMessage but got other type. " + + "decryptedMsgWithPubKey.message=", decryptedMsgWithPubKey.message); } - } else { - log.info("Wrong blurredAddressHash. The message is not intended for us."); + } catch (CryptoException e) { + log.trace("Decryption of SealedAndSignedMessage failed. " + + "That is expected if the message is not intended for us. " + e.getMessage()); } + } else { + log.info("Wrong blurredAddressHash. The message is not intended for us."); } } } public void sendEncryptedMailboxMessage(NodeAddress peersNodeAddress, PubKeyRing peersPubKeyRing, - io.bitsquare.p2p.messaging.MailboxMessage message, + MailboxMessage message, SendMailboxMessageListener sendMailboxMessageListener) { Log.traceCall("message " + message); checkNotNull(peersNodeAddress, @@ -514,7 +511,7 @@ public class P2PService implements SetupListener, MessageListener, ConnectionLis log.info("We cannot send message to peer. Peer might be offline. We will store message in mailbox."); log.trace("create MailboxEntry with peerAddress " + peersNodeAddress); PublicKey receiverStoragePublicKey = peersPubKeyRing.getSignaturePubKey(); - addMailboxData(new MailboxPayload(prefixedSealedAndSignedMessage, + addMailboxData(new MailboxStoragePayload(prefixedSealedAndSignedMessage, optionalKeyRing.get().getSignatureKeyPair().getPublic(), receiverStoragePublicKey), receiverStoragePublicKey, @@ -536,7 +533,7 @@ public class P2PService implements SetupListener, MessageListener, ConnectionLis } - private void addMailboxData(MailboxPayload expirableMailboxPayload, + private void addMailboxData(MailboxStoragePayload expirableMailboxStoragePayload, PublicKey receiversPublicKey, SendMailboxMessageListener sendMailboxMessageListener) { Log.traceCall(); @@ -546,19 +543,19 @@ public class P2PService implements SetupListener, MessageListener, ConnectionLis if (isBootstrapped()) { if (!networkNode.getAllConnections().isEmpty()) { try { - ProtectedMailboxData protectedMailboxData = p2PDataStorage.getMailboxDataWithSignedSeqNr( - expirableMailboxPayload, + ProtectedMailboxStorageEntry protectedMailboxStorageEntry = p2PDataStorage.getMailboxDataWithSignedSeqNr( + expirableMailboxStoragePayload, optionalKeyRing.get().getSignatureKeyPair(), receiversPublicKey); Timer sendMailboxMessageTimeoutTimer = UserThread.runAfter(() -> { - boolean result = p2PDataStorage.remove(protectedMailboxData, networkNode.getNodeAddress()); + boolean result = p2PDataStorage.remove(protectedMailboxStorageEntry, networkNode.getNodeAddress()); log.debug("remove result=" + result); sendMailboxMessageListener.onFault("A timeout occurred when trying to broadcast mailbox data."); }, 30); Broadcaster.Listener listener = message -> { if (message instanceof AddDataMessage && - ((AddDataMessage) message).data.equals(protectedMailboxData)) { + ((AddDataMessage) message).protectedStorageEntry.equals(protectedMailboxStorageEntry)) { sendMailboxMessageListener.onStoredInMailbox(); sendMailboxMessageTimeoutTimer.stop(); } @@ -573,20 +570,30 @@ public class P2PService implements SetupListener, MessageListener, ConnectionLis if ((int) newValue > 0) broadcaster.removeListener(listener); - UserThread.execute(() -> { + if (numOfBroadcastsChangeListener != null) { broadcaster.getNumOfBroadcastsProperty().removeListener(numOfBroadcastsChangeListener); numOfBroadcastsChangeListener = null; - }); + } + + /* UserThread.execute(() -> { + if (numOfBroadcastsChangeListener != null) { + broadcaster.getNumOfBroadcastsProperty().removeListener(numOfBroadcastsChangeListener); + numOfBroadcastsChangeListener = null; + } + });*/ }; broadcaster.getNumOfBroadcastsProperty().addListener(numOfBroadcastsChangeListener); - boolean result = p2PDataStorage.add(protectedMailboxData, networkNode.getNodeAddress()); + boolean result = p2PDataStorage.add(protectedMailboxStorageEntry, networkNode.getNodeAddress()); if (!result) { sendMailboxMessageTimeoutTimer.stop(); broadcaster.removeListener(listener); - broadcaster.getNumOfBroadcastsProperty().removeListener(numOfBroadcastsChangeListener); + + if (numOfBroadcastsChangeListener != null) + broadcaster.getNumOfBroadcastsProperty().removeListener(numOfBroadcastsChangeListener); + sendMailboxMessageListener.onFault("Data already exists in our local database"); - boolean result2 = p2PDataStorage.remove(protectedMailboxData, networkNode.getNodeAddress()); + boolean result2 = p2PDataStorage.remove(protectedMailboxStorageEntry, networkNode.getNodeAddress()); log.debug("remove result=" + result2); } } catch (CryptoException e) { @@ -605,29 +612,31 @@ public class P2PService implements SetupListener, MessageListener, ConnectionLis Log.traceCall(); checkArgument(optionalKeyRing.isPresent(), "keyRing not set. Seems that is called on a seed node which must not happen."); if (isBootstrapped()) { - if (mailboxMap.containsKey(decryptedMsgWithPubKey)) { - ProtectedMailboxData mailboxData = mailboxMap.get(decryptedMsgWithPubKey); - if (mailboxData != null && mailboxData.expirablePayload instanceof MailboxPayload) { - MailboxPayload expirableMailboxPayload = (MailboxPayload) mailboxData.expirablePayload; + MailboxMessage mailboxMessage = (MailboxMessage) decryptedMsgWithPubKey.message; + String uid = mailboxMessage.getUID(); + if (mailboxMap.containsKey(uid)) { + ProtectedMailboxStorageEntry mailboxData = mailboxMap.get(uid); + if (mailboxData != null && mailboxData.getStoragePayload() instanceof MailboxStoragePayload) { + MailboxStoragePayload expirableMailboxStoragePayload = (MailboxStoragePayload) mailboxData.getStoragePayload(); PublicKey receiversPubKey = mailboxData.receiversPubKey; checkArgument(receiversPubKey.equals(optionalKeyRing.get().getSignatureKeyPair().getPublic()), "receiversPubKey is not matching with our key. That must not happen."); try { - ProtectedMailboxData protectedMailboxData = p2PDataStorage.getMailboxDataWithSignedSeqNr( - expirableMailboxPayload, + ProtectedMailboxStorageEntry protectedMailboxStorageEntry = p2PDataStorage.getMailboxDataWithSignedSeqNr( + expirableMailboxStoragePayload, optionalKeyRing.get().getSignatureKeyPair(), receiversPubKey); - p2PDataStorage.removeMailboxData(protectedMailboxData, networkNode.getNodeAddress()); + p2PDataStorage.removeMailboxData(protectedMailboxStorageEntry, networkNode.getNodeAddress()); } catch (CryptoException e) { log.error("Signing at getDataWithSignedSeqNr failed. That should never happen."); } - mailboxMap.remove(decryptedMsgWithPubKey); + mailboxMap.remove(uid); log.trace("Removed successfully decryptedMsgWithPubKey."); } } else { - log.warn("decryptedMsgWithPubKey not found in mailboxMap. That should never happen." + - "\n\tdecryptedMsgWithPubKey={}\n\tmailboxMap={}", decryptedMsgWithPubKey, mailboxMap); + log.warn("uid for mailbox entry not found in mailboxMap. That should never happen." + + "\n\tuid={}\n\tmailboxMap={}\n\tmailboxMessage={}", uid, mailboxMap, mailboxMessage); } } else { throw new NetworkNotReadyException(); @@ -640,17 +649,17 @@ public class P2PService implements SetupListener, MessageListener, ConnectionLis // Data storage /////////////////////////////////////////////////////////////////////////////////////////// - public boolean addData(ExpirablePayload expirablePayload) { - return addData(expirablePayload, false); + public boolean addData(StoragePayload storagePayload) { + return addData(storagePayload, false); } - public boolean addData(ExpirablePayload expirablePayload, boolean forceBroadcast) { + public boolean addData(StoragePayload storagePayload, boolean forceBroadcast) { Log.traceCall(); checkArgument(optionalKeyRing.isPresent(), "keyRing not set. Seems that is called on a seed node which must not happen."); if (isBootstrapped()) { try { - ProtectedData protectedData = p2PDataStorage.getProtectedData(expirablePayload, optionalKeyRing.get().getSignatureKeyPair()); - return p2PDataStorage.add(protectedData, networkNode.getNodeAddress(), forceBroadcast); + ProtectedStorageEntry protectedStorageEntry = p2PDataStorage.getProtectedData(storagePayload, optionalKeyRing.get().getSignatureKeyPair()); + return p2PDataStorage.add(protectedStorageEntry, networkNode.getNodeAddress(), forceBroadcast); } catch (CryptoException e) { log.error("Signing at getDataWithSignedSeqNr failed. That should never happen."); return false; @@ -660,12 +669,12 @@ public class P2PService implements SetupListener, MessageListener, ConnectionLis } } - public boolean refreshTTL(ExpirablePayload expirablePayload) { + public boolean refreshTTL(StoragePayload storagePayload) { Log.traceCall(); checkArgument(optionalKeyRing.isPresent(), "keyRing not set. Seems that is called on a seed node which must not happen."); if (isBootstrapped()) { try { - RefreshTTLMessage refreshTTLMessage = p2PDataStorage.getRefreshTTLMessage(expirablePayload, optionalKeyRing.get().getSignatureKeyPair()); + RefreshTTLMessage refreshTTLMessage = p2PDataStorage.getRefreshTTLMessage(storagePayload, optionalKeyRing.get().getSignatureKeyPair()); return p2PDataStorage.refreshTTL(refreshTTLMessage, networkNode.getNodeAddress()); } catch (CryptoException e) { log.error("Signing at getDataWithSignedSeqNr failed. That should never happen."); @@ -676,13 +685,13 @@ public class P2PService implements SetupListener, MessageListener, ConnectionLis } } - public boolean removeData(ExpirablePayload expirablePayload) { + public boolean removeData(StoragePayload storagePayload) { Log.traceCall(); checkArgument(optionalKeyRing.isPresent(), "keyRing not set. Seems that is called on a seed node which must not happen."); if (isBootstrapped()) { try { - ProtectedData protectedData = p2PDataStorage.getProtectedData(expirablePayload, optionalKeyRing.get().getSignatureKeyPair()); - return p2PDataStorage.remove(protectedData, networkNode.getNodeAddress()); + ProtectedStorageEntry protectedStorageEntry = p2PDataStorage.getProtectedData(storagePayload, optionalKeyRing.get().getSignatureKeyPair()); + return p2PDataStorage.remove(protectedStorageEntry, networkNode.getNodeAddress()); } catch (CryptoException e) { log.error("Signing at getDataWithSignedSeqNr failed. That should never happen."); return false; @@ -747,7 +756,7 @@ public class P2PService implements SetupListener, MessageListener, ConnectionLis return numConnectedPeers; } - public Map getDataMap() { + public Map getDataMap() { return p2PDataStorage.getMap(); } diff --git a/network/src/main/java/io/bitsquare/p2p/messaging/DecryptedDirectMessageListener.java b/network/src/main/java/io/bitsquare/p2p/messaging/DecryptedDirectMessageListener.java index 126c735815..959ece287f 100644 --- a/network/src/main/java/io/bitsquare/p2p/messaging/DecryptedDirectMessageListener.java +++ b/network/src/main/java/io/bitsquare/p2p/messaging/DecryptedDirectMessageListener.java @@ -1,5 +1,6 @@ package io.bitsquare.p2p.messaging; +import io.bitsquare.crypto.DecryptedMsgWithPubKey; import io.bitsquare.p2p.NodeAddress; public interface DecryptedDirectMessageListener { diff --git a/network/src/main/java/io/bitsquare/p2p/messaging/DecryptedMailboxListener.java b/network/src/main/java/io/bitsquare/p2p/messaging/DecryptedMailboxListener.java index 66c8350a99..b2e09cbe0c 100644 --- a/network/src/main/java/io/bitsquare/p2p/messaging/DecryptedMailboxListener.java +++ b/network/src/main/java/io/bitsquare/p2p/messaging/DecryptedMailboxListener.java @@ -1,5 +1,6 @@ package io.bitsquare.p2p.messaging; +import io.bitsquare.crypto.DecryptedMsgWithPubKey; import io.bitsquare.p2p.NodeAddress; public interface DecryptedMailboxListener { diff --git a/network/src/main/java/io/bitsquare/p2p/messaging/MailboxMessage.java b/network/src/main/java/io/bitsquare/p2p/messaging/MailboxMessage.java index 504e75eb5b..e33579acd7 100644 --- a/network/src/main/java/io/bitsquare/p2p/messaging/MailboxMessage.java +++ b/network/src/main/java/io/bitsquare/p2p/messaging/MailboxMessage.java @@ -22,4 +22,6 @@ import io.bitsquare.p2p.NodeAddress; public interface MailboxMessage extends DirectMessage { NodeAddress getSenderNodeAddress(); + + String getUID(); } diff --git a/network/src/main/java/io/bitsquare/crypto/PrefixedSealedAndSignedMessage.java b/network/src/main/java/io/bitsquare/p2p/messaging/PrefixedSealedAndSignedMessage.java similarity index 88% rename from network/src/main/java/io/bitsquare/crypto/PrefixedSealedAndSignedMessage.java rename to network/src/main/java/io/bitsquare/p2p/messaging/PrefixedSealedAndSignedMessage.java index 4ff3415063..c2895ff0b0 100644 --- a/network/src/main/java/io/bitsquare/crypto/PrefixedSealedAndSignedMessage.java +++ b/network/src/main/java/io/bitsquare/p2p/messaging/PrefixedSealedAndSignedMessage.java @@ -1,12 +1,12 @@ -package io.bitsquare.crypto; +package io.bitsquare.p2p.messaging; import io.bitsquare.app.Version; import io.bitsquare.common.crypto.SealedAndSigned; import io.bitsquare.p2p.NodeAddress; -import io.bitsquare.p2p.messaging.MailboxMessage; import io.bitsquare.p2p.network.messages.SendersNodeAddressMessage; import java.util.Arrays; +import java.util.UUID; public final class PrefixedSealedAndSignedMessage implements MailboxMessage, SendersNodeAddressMessage { // That object is sent over the wire, so we need to take care of version compatibility. @@ -16,6 +16,7 @@ public final class PrefixedSealedAndSignedMessage implements MailboxMessage, Sen private final NodeAddress senderNodeAddress; public final SealedAndSigned sealedAndSigned; public final byte[] addressPrefixHash; + private final String uid = UUID.randomUUID().toString(); public PrefixedSealedAndSignedMessage(NodeAddress senderNodeAddress, SealedAndSigned sealedAndSigned, byte[] addressPrefixHash) { this.senderNodeAddress = senderNodeAddress; @@ -28,6 +29,11 @@ public final class PrefixedSealedAndSignedMessage implements MailboxMessage, Sen return senderNodeAddress; } + @Override + public String getUID() { + return uid; + } + @Override public int getMessageVersion() { return messageVersion; diff --git a/network/src/main/java/io/bitsquare/p2p/network/Connection.java b/network/src/main/java/io/bitsquare/p2p/network/Connection.java index ae15c8f884..1a7a0b2554 100644 --- a/network/src/main/java/io/bitsquare/p2p/network/Connection.java +++ b/network/src/main/java/io/bitsquare/p2p/network/Connection.java @@ -7,10 +7,10 @@ import io.bitsquare.app.Version; import io.bitsquare.common.ByteArrayUtils; import io.bitsquare.common.UserThread; import io.bitsquare.common.util.Tuple2; -import io.bitsquare.crypto.PrefixedSealedAndSignedMessage; import io.bitsquare.p2p.Message; import io.bitsquare.p2p.NodeAddress; import io.bitsquare.p2p.Utils; +import io.bitsquare.p2p.messaging.PrefixedSealedAndSignedMessage; import io.bitsquare.p2p.network.messages.CloseConnectionMessage; import io.bitsquare.p2p.network.messages.SendersNodeAddressMessage; import io.bitsquare.p2p.peers.keepalive.messages.KeepAliveMessage; @@ -57,12 +57,10 @@ public class Connection implements MessageListener { // Static /////////////////////////////////////////////////////////////////////////////////////////// - private static final int MAX_MSG_SIZE = 100 * 1024; // 100 kb of compressed data - private static final int MSG_THROTTLE_PER_SEC = 10; // With MAX_MSG_SIZE of 100kb results in bandwidth of 10 mbit/sec - private static final int MSG_THROTTLE_PER_10_SEC = 50; // With MAX_MSG_SIZE of 100kb results in bandwidth of 5 mbit/sec for 10 sec - //private static final int SOCKET_TIMEOUT = (int) TimeUnit.SECONDS.toMillis(60); - //TODO - private static final int SOCKET_TIMEOUT = (int) TimeUnit.SECONDS.toMillis(20); + private static final int MAX_MSG_SIZE = 100 * 1024; // 100 kb of compressed data + private static final int MSG_THROTTLE_PER_SEC = 20; // With MAX_MSG_SIZE of 100kb results in bandwidth of 20 mbit/sec + private static final int MSG_THROTTLE_PER_10_SEC = 100; // With MAX_MSG_SIZE of 100kb results in bandwidth of 10 mbit/sec for 10 sec + private static final int SOCKET_TIMEOUT = (int) TimeUnit.SECONDS.toMillis(60); public static int getMaxMsgSize() { return MAX_MSG_SIZE; @@ -519,7 +517,7 @@ public class Connection implements MessageListener { } else if (e instanceof SocketTimeoutException || e instanceof TimeoutException) { closeConnectionReason = CloseConnectionReason.SOCKET_TIMEOUT; log.warn("SocketTimeoutException at socket " + socket.toString() + "\n\tconnection={}" + this); - } else if (e instanceof EOFException) { + } else if (e instanceof EOFException || e instanceof StreamCorruptedException) { closeConnectionReason = CloseConnectionReason.TERMINATED; } else { closeConnectionReason = CloseConnectionReason.UNKNOWN_EXCEPTION; diff --git a/network/src/main/java/io/bitsquare/p2p/peers/Broadcaster.java b/network/src/main/java/io/bitsquare/p2p/peers/Broadcaster.java index 5d74c64f34..eee86602bb 100644 --- a/network/src/main/java/io/bitsquare/p2p/peers/Broadcaster.java +++ b/network/src/main/java/io/bitsquare/p2p/peers/Broadcaster.java @@ -9,7 +9,7 @@ import io.bitsquare.p2p.network.CloseConnectionReason; import io.bitsquare.p2p.network.Connection; import io.bitsquare.p2p.network.ConnectionListener; import io.bitsquare.p2p.network.NetworkNode; -import io.bitsquare.p2p.storage.messages.DataBroadcastMessage; +import io.bitsquare.p2p.storage.messages.BroadcastMessage; import javafx.beans.property.IntegerProperty; import javafx.beans.property.SimpleIntegerProperty; import org.apache.commons.lang3.StringUtils; @@ -26,7 +26,7 @@ public class Broadcaster implements ConnectionListener, PeerManager.Listener { public interface Listener { - void onBroadcasted(DataBroadcastMessage message); + void onBroadcasted(BroadcastMessage message); } private final NetworkNode networkNode; @@ -59,7 +59,7 @@ public class Broadcaster implements ConnectionListener, PeerManager.Listener { // API /////////////////////////////////////////////////////////////////////////////////////////// - public void broadcast(DataBroadcastMessage message, @Nullable NodeAddress sender) { + public void broadcast(BroadcastMessage message, @Nullable NodeAddress sender) { Log.traceCall("Sender=" + sender + "\n\t" + "Message=" + StringUtils.abbreviate(message.toString(), 100)); numOfBroadcasts.set(0); diff --git a/network/src/main/java/io/bitsquare/p2p/peers/getdata/messages/GetDataResponse.java b/network/src/main/java/io/bitsquare/p2p/peers/getdata/messages/GetDataResponse.java index 4b21828ffd..498d8e6da4 100644 --- a/network/src/main/java/io/bitsquare/p2p/peers/getdata/messages/GetDataResponse.java +++ b/network/src/main/java/io/bitsquare/p2p/peers/getdata/messages/GetDataResponse.java @@ -2,7 +2,7 @@ package io.bitsquare.p2p.peers.getdata.messages; import io.bitsquare.app.Version; import io.bitsquare.p2p.Message; -import io.bitsquare.p2p.storage.data.ProtectedData; +import io.bitsquare.p2p.storage.storageentry.ProtectedStorageEntry; import java.util.HashSet; @@ -11,10 +11,10 @@ public final class GetDataResponse implements Message { private static final long serialVersionUID = Version.P2P_NETWORK_VERSION; private final int messageVersion = Version.getP2PMessageVersion(); - public final HashSet dataSet; + public final HashSet dataSet; public final int requestNonce; - public GetDataResponse(HashSet dataSet, int requestNonce) { + public GetDataResponse(HashSet dataSet, int requestNonce) { this.dataSet = dataSet; this.requestNonce = requestNonce; } diff --git a/network/src/main/java/io/bitsquare/p2p/peers/keepalive/KeepAliveManager.java b/network/src/main/java/io/bitsquare/p2p/peers/keepalive/KeepAliveManager.java index 03dbd2318e..50e92b751c 100644 --- a/network/src/main/java/io/bitsquare/p2p/peers/keepalive/KeepAliveManager.java +++ b/network/src/main/java/io/bitsquare/p2p/peers/keepalive/KeepAliveManager.java @@ -17,13 +17,12 @@ import org.slf4j.LoggerFactory; import java.util.HashMap; import java.util.Map; +import java.util.Random; public class KeepAliveManager implements MessageListener, ConnectionListener, PeerManager.Listener { private static final Logger log = LoggerFactory.getLogger(KeepAliveManager.class); - //private static final int INTERVAL_SEC = new Random().nextInt(10) + 10; - //TODO - private static final int INTERVAL_SEC = 5; + private static final int INTERVAL_SEC = new Random().nextInt(10) + 10; private final NetworkNode networkNode; private final PeerManager peerManager; diff --git a/network/src/main/java/io/bitsquare/p2p/peers/peerexchange/GetPeersRequestHandler.java b/network/src/main/java/io/bitsquare/p2p/peers/peerexchange/GetPeersRequestHandler.java index 406ce5f457..5cd33bcffe 100644 --- a/network/src/main/java/io/bitsquare/p2p/peers/peerexchange/GetPeersRequestHandler.java +++ b/network/src/main/java/io/bitsquare/p2p/peers/peerexchange/GetPeersRequestHandler.java @@ -108,7 +108,6 @@ class GetPeersRequestHandler { /////////////////////////////////////////////////////////////////////////////////////////// private void handleFault(String errorMessage, CloseConnectionReason closeConnectionReason, Connection connection) { - // TODO retry cleanup(); peerManager.shutDownConnection(connection, closeConnectionReason); listener.onFault(errorMessage, connection); diff --git a/network/src/main/java/io/bitsquare/p2p/peers/peerexchange/PeerExchangeHandler.java b/network/src/main/java/io/bitsquare/p2p/peers/peerexchange/PeerExchangeHandler.java index afd2c976ea..567241a23a 100644 --- a/network/src/main/java/io/bitsquare/p2p/peers/peerexchange/PeerExchangeHandler.java +++ b/network/src/main/java/io/bitsquare/p2p/peers/peerexchange/PeerExchangeHandler.java @@ -85,11 +85,12 @@ class PeerExchangeHandler implements MessageListener { @Override public void onSuccess(Connection connection) { if (!stopped) { + if (!connection.getPeersNodeAddressOptional().isPresent()) { connection.setPeersNodeAddress(nodeAddress); - //TODO remove setPeersNodeAddress if never needed log.warn("sendGetPeersRequest: !connection.getPeersNodeAddressOptional().isPresent()"); } + PeerExchangeHandler.this.connection = connection; connection.addMessageListener(PeerExchangeHandler.this); log.trace("Send " + getPeersRequest + " to " + nodeAddress + " succeeded."); @@ -169,7 +170,6 @@ class PeerExchangeHandler implements MessageListener { private void handleFault(String errorMessage, CloseConnectionReason sendMsgFailure, NodeAddress nodeAddress) { Log.traceCall(); - // TODO retry cleanup(); if (connection == null) peerManager.shutDownConnection(nodeAddress, sendMsgFailure); diff --git a/network/src/main/java/io/bitsquare/p2p/peers/peerexchange/PeerExchangeManager.java b/network/src/main/java/io/bitsquare/p2p/peers/peerexchange/PeerExchangeManager.java index d062c7f3c6..1f56937cde 100644 --- a/network/src/main/java/io/bitsquare/p2p/peers/peerexchange/PeerExchangeManager.java +++ b/network/src/main/java/io/bitsquare/p2p/peers/peerexchange/PeerExchangeManager.java @@ -229,7 +229,6 @@ public class PeerExchangeManager implements MessageListener, ConnectionListener, handlerMap.put(nodeAddress, peerExchangeHandler); peerExchangeHandler.sendGetPeersRequest(nodeAddress); } else { - //TODO check when that happens log.warn("We have started already a peerExchangeHandler. " + "We ignore that call. nodeAddress=" + nodeAddress); } diff --git a/network/src/main/java/io/bitsquare/p2p/storage/HashMapChangedListener.java b/network/src/main/java/io/bitsquare/p2p/storage/HashMapChangedListener.java index 3bb9fd2086..9555ff6bf5 100644 --- a/network/src/main/java/io/bitsquare/p2p/storage/HashMapChangedListener.java +++ b/network/src/main/java/io/bitsquare/p2p/storage/HashMapChangedListener.java @@ -1,9 +1,9 @@ package io.bitsquare.p2p.storage; -import io.bitsquare.p2p.storage.data.ProtectedData; +import io.bitsquare.p2p.storage.storageentry.ProtectedStorageEntry; public interface HashMapChangedListener { - void onAdded(ProtectedData data); + void onAdded(ProtectedStorageEntry data); - void onRemoved(ProtectedData data); + void onRemoved(ProtectedStorageEntry data); } diff --git a/network/src/main/java/io/bitsquare/p2p/storage/P2PDataStorage.java b/network/src/main/java/io/bitsquare/p2p/storage/P2PDataStorage.java index bf5a1588a5..3eed51a1de 100644 --- a/network/src/main/java/io/bitsquare/p2p/storage/P2PDataStorage.java +++ b/network/src/main/java/io/bitsquare/p2p/storage/P2PDataStorage.java @@ -14,8 +14,13 @@ import io.bitsquare.p2p.Message; import io.bitsquare.p2p.NodeAddress; import io.bitsquare.p2p.network.*; import io.bitsquare.p2p.peers.Broadcaster; -import io.bitsquare.p2p.storage.data.*; import io.bitsquare.p2p.storage.messages.*; +import io.bitsquare.p2p.storage.payload.ExpirablePayload; +import io.bitsquare.p2p.storage.payload.MailboxStoragePayload; +import io.bitsquare.p2p.storage.payload.RequiresOwnerIsOnlinePayload; +import io.bitsquare.p2p.storage.payload.StoragePayload; +import io.bitsquare.p2p.storage.storageentry.ProtectedMailboxStorageEntry; +import io.bitsquare.p2p.storage.storageentry.ProtectedStorageEntry; import io.bitsquare.storage.Storage; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; @@ -36,11 +41,10 @@ public class P2PDataStorage implements MessageListener, ConnectionListener { private static final Logger log = LoggerFactory.getLogger(P2PDataStorage.class); @VisibleForTesting - //public static int CHECK_TTL_INTERVAL_MILLIS = (int) TimeUnit.SECONDS.toMillis(30); - public static int CHECK_TTL_INTERVAL_SEC = 5;//TODO + public static int CHECK_TTL_INTERVAL_SEC = 30; private final Broadcaster broadcaster; - private final Map map = new ConcurrentHashMap<>(); + private final Map map = new ConcurrentHashMap<>(); private final CopyOnWriteArraySet hashMapChangedListeners = new CopyOnWriteArraySet<>(); private Timer removeExpiredEntriesTimer; private HashMap sequenceNumberMap = new HashMap<>(); @@ -76,15 +80,15 @@ public class P2PDataStorage implements MessageListener, ConnectionListener { // object when we get it sent from new peers, we don’t remove the sequence number from the map. // That way an ADD message for an already expired data will fail because the sequence number // is equal and not larger as expected. - Map temp = new HashMap<>(map); - Set toRemoveSet = new HashSet<>(); + Map temp = new HashMap<>(map); + Set toRemoveSet = new HashSet<>(); temp.entrySet().stream() .filter(entry -> entry.getValue().isExpired()) .forEach(entry -> { ByteArray hashOfPayload = entry.getKey(); - ProtectedData protectedData = map.get(hashOfPayload); - toRemoveSet.add(protectedData); - log.warn("We found an expired data entry. We remove the protectedData:\n\t" + protectedData); + ProtectedStorageEntry protectedStorageEntry = map.get(hashOfPayload); + toRemoveSet.add(protectedStorageEntry); + log.warn("We found an expired data entry. We remove the protectedData:\n\t" + protectedStorageEntry); map.remove(hashOfPayload); }); @@ -104,15 +108,15 @@ public class P2PDataStorage implements MessageListener, ConnectionListener { @Override public void onMessage(Message message, Connection connection) { - if (message instanceof DataBroadcastMessage) { + if (message instanceof BroadcastMessage) { Log.traceCall(StringUtils.abbreviate(message.toString(), 100) + "\n\tconnection=" + connection); connection.getPeersNodeAddressOptional().ifPresent(peersNodeAddress -> { if (message instanceof AddDataMessage) { - add(((AddDataMessage) message).data, peersNodeAddress); + add(((AddDataMessage) message).protectedStorageEntry, peersNodeAddress); } else if (message instanceof RemoveDataMessage) { - remove(((RemoveDataMessage) message).data, peersNodeAddress); + remove(((RemoveDataMessage) message).protectedStorageEntry, peersNodeAddress); } else if (message instanceof RemoveMailboxDataMessage) { - removeMailboxData(((RemoveMailboxDataMessage) message).data, peersNodeAddress); + removeMailboxData(((RemoveMailboxDataMessage) message).protectedMailboxStorageEntry, peersNodeAddress); } else if (message instanceof RefreshTTLMessage) { refreshTTL((RefreshTTLMessage) message, peersNodeAddress); } @@ -134,7 +138,7 @@ public class P2PDataStorage implements MessageListener, ConnectionListener { if (connection.getPeersNodeAddressOptional().isPresent() && !closeConnectionReason.isIntended) { map.values().stream() .forEach(protectedData -> { - ExpirablePayload expirablePayload = protectedData.expirablePayload; + ExpirablePayload expirablePayload = protectedData.getStoragePayload(); if (expirablePayload instanceof RequiresOwnerIsOnlinePayload) { RequiresOwnerIsOnlinePayload requiresOwnerIsOnlinePayload = (RequiresOwnerIsOnlinePayload) expirablePayload; NodeAddress ownerNodeAddress = requiresOwnerIsOnlinePayload.getOwnerNodeAddress(); @@ -166,28 +170,27 @@ public class P2PDataStorage implements MessageListener, ConnectionListener { // API /////////////////////////////////////////////////////////////////////////////////////////// - public boolean add(ProtectedData protectedData, @Nullable NodeAddress sender) { - return add(protectedData, sender, false); + public boolean add(ProtectedStorageEntry protectedStorageEntry, @Nullable NodeAddress sender) { + return add(protectedStorageEntry, sender, false); } - public boolean add(ProtectedData protectedData, @Nullable NodeAddress sender, boolean forceBroadcast) { + public boolean add(ProtectedStorageEntry protectedStorageEntry, @Nullable NodeAddress sender, boolean forceBroadcast) { Log.traceCall(); - ByteArray hashOfPayload = getHashAsByteArray(protectedData.expirablePayload); - boolean result = checkPublicKeys(protectedData, true) - && checkSignature(protectedData) - && isSequenceNrValid(protectedData.sequenceNumber, hashOfPayload); + ByteArray hashOfPayload = getHashAsByteArray(protectedStorageEntry.getStoragePayload()); + boolean result = checkPublicKeys(protectedStorageEntry, true) + && checkSignature(protectedStorageEntry) + && isSequenceNrValid(protectedStorageEntry.sequenceNumber, hashOfPayload); boolean containsKey = map.containsKey(hashOfPayload); if (containsKey) - result &= checkIfStoredDataPubKeyMatchesNewDataPubKey(protectedData.ownerPubKey, hashOfPayload); + result &= checkIfStoredDataPubKeyMatchesNewDataPubKey(protectedStorageEntry.ownerPubKey, hashOfPayload); if (result) { - map.put(hashOfPayload, protectedData); + map.put(hashOfPayload, protectedStorageEntry); - sequenceNumberMap.put(hashOfPayload, new MapValue(protectedData.sequenceNumber, System.currentTimeMillis())); + sequenceNumberMap.put(hashOfPayload, new MapValue(protectedStorageEntry.sequenceNumber, System.currentTimeMillis())); storage.queueUpForSave(sequenceNumberMap, 100); - log.error("sequenceNumberMap queueUpForSave protectedData.sequenceNumber " + protectedData.sequenceNumber); StringBuilder sb = new StringBuilder("\n\n------------------------------------------------------------\n"); sb.append("Data set after doAdd (truncated)"); @@ -197,11 +200,11 @@ public class P2PDataStorage implements MessageListener, ConnectionListener { log.info("Data set after doAdd: size=" + map.values().size()); if (!containsKey || forceBroadcast) - broadcast(new AddDataMessage(protectedData), sender); + broadcast(new AddDataMessage(protectedStorageEntry), sender); else log.trace("Not broadcasting data as we had it already in our map."); - hashMapChangedListeners.stream().forEach(e -> e.onAdded(protectedData)); + hashMapChangedListeners.stream().forEach(e -> e.onAdded(protectedStorageEntry)); } else { log.trace("add failed"); } @@ -217,27 +220,26 @@ public class P2PDataStorage implements MessageListener, ConnectionListener { int sequenceNumber = refreshTTLMessage.sequenceNumber; if (map.containsKey(hashOfPayload)) { - ProtectedData storedData = map.get(hashOfPayload); + ProtectedStorageEntry storedData = map.get(hashOfPayload); - if (storedData.expirablePayload instanceof StoragePayload) { + if (storedData.getStoragePayload() instanceof StoragePayload) { if (sequenceNumberMap.containsKey(hashOfPayload) && sequenceNumberMap.get(hashOfPayload).sequenceNr == sequenceNumber) { log.trace("We got that message with that seq nr already from another peer. We ignore that message."); return true; } else { - PublicKey ownerPubKey = ((StoragePayload) storedData.expirablePayload).getOwnerPubKey(); + PublicKey ownerPubKey = ((StoragePayload) storedData.getStoragePayload()).getOwnerPubKey(); boolean result = checkSignature(ownerPubKey, hashOfDataAndSeqNr, signature) && isSequenceNrValid(sequenceNumber, hashOfPayload) && checkIfStoredDataPubKeyMatchesNewDataPubKey(ownerPubKey, hashOfPayload); if (result) { log.info("refreshDate called for storedData:\n\t" + StringUtils.abbreviate(storedData.toString(), 100)); - storedData.refreshDate(); + storedData.updateTimeStamp(); storedData.updateSequenceNumber(sequenceNumber); storedData.updateSignature(signature); sequenceNumberMap.put(hashOfPayload, new MapValue(sequenceNumber, System.currentTimeMillis())); storage.queueUpForSave(sequenceNumberMap, 100); - log.error("sequenceNumberMap queueUpForSave sequenceNumber " + sequenceNumber); StringBuilder sb = new StringBuilder("\n\n------------------------------------------------------------\n"); sb.append("Data set after refreshTTL (truncated)"); @@ -262,24 +264,25 @@ public class P2PDataStorage implements MessageListener, ConnectionListener { } } - public boolean remove(ProtectedData protectedData, @Nullable NodeAddress sender) { + public boolean remove(ProtectedStorageEntry protectedStorageEntry, @Nullable NodeAddress sender) { Log.traceCall(); - ByteArray hashOfPayload = getHashAsByteArray(protectedData.expirablePayload); + ByteArray hashOfPayload = getHashAsByteArray(protectedStorageEntry.getStoragePayload()); boolean containsKey = map.containsKey(hashOfPayload); - if (!containsKey) log.debug("Remove data ignored as we don't have an entry for that data."); + if (!containsKey) + log.debug("Remove data ignored as we don't have an entry for that data."); boolean result = containsKey - && checkPublicKeys(protectedData, false) - && isSequenceNrValid(protectedData.sequenceNumber, hashOfPayload) - && checkSignature(protectedData) - && checkIfStoredDataPubKeyMatchesNewDataPubKey(protectedData.ownerPubKey, hashOfPayload); + && checkPublicKeys(protectedStorageEntry, false) + && isSequenceNrValid(protectedStorageEntry.sequenceNumber, hashOfPayload) + && checkSignature(protectedStorageEntry) + && checkIfStoredDataPubKeyMatchesNewDataPubKey(protectedStorageEntry.ownerPubKey, hashOfPayload); if (result) { - doRemoveProtectedExpirableData(protectedData, hashOfPayload); + doRemoveProtectedExpirableData(protectedStorageEntry, hashOfPayload); - broadcast(new RemoveDataMessage(protectedData), sender); + broadcast(new RemoveDataMessage(protectedStorageEntry), sender); - sequenceNumberMap.put(hashOfPayload, new MapValue(protectedData.sequenceNumber, System.currentTimeMillis())); + sequenceNumberMap.put(hashOfPayload, new MapValue(protectedStorageEntry.sequenceNumber, System.currentTimeMillis())); storage.queueUpForSave(sequenceNumberMap, 100); } else { log.debug("remove failed"); @@ -287,24 +290,25 @@ public class P2PDataStorage implements MessageListener, ConnectionListener { return result; } - public boolean removeMailboxData(ProtectedMailboxData protectedMailboxData, @Nullable NodeAddress sender) { + public boolean removeMailboxData(ProtectedMailboxStorageEntry protectedMailboxStorageEntry, @Nullable NodeAddress sender) { Log.traceCall(); - ByteArray hashOfData = getHashAsByteArray(protectedMailboxData.expirablePayload); + ByteArray hashOfData = getHashAsByteArray(protectedMailboxStorageEntry.getStoragePayload()); boolean containsKey = map.containsKey(hashOfData); - if (!containsKey) log.debug("Remove data ignored as we don't have an entry for that data."); + if (!containsKey) + log.debug("Remove data ignored as we don't have an entry for that data."); boolean result = containsKey - && checkPublicKeys(protectedMailboxData, false) - && isSequenceNrValid(protectedMailboxData.sequenceNumber, hashOfData) - && protectedMailboxData.receiversPubKey.equals(protectedMailboxData.ownerPubKey) // at remove both keys are the same (only receiver is able to remove data) - && checkSignature(protectedMailboxData) - && checkIfStoredMailboxDataMatchesNewMailboxData(protectedMailboxData.receiversPubKey, hashOfData); + && checkPublicKeys(protectedMailboxStorageEntry, false) + && isSequenceNrValid(protectedMailboxStorageEntry.sequenceNumber, hashOfData) + && protectedMailboxStorageEntry.receiversPubKey.equals(protectedMailboxStorageEntry.receiversPubKey) // at remove both keys are the same (only receiver is able to remove data) + && checkSignature(protectedMailboxStorageEntry) + && checkIfStoredMailboxDataMatchesNewMailboxData(protectedMailboxStorageEntry.receiversPubKey, hashOfData); if (result) { - doRemoveProtectedExpirableData(protectedMailboxData, hashOfData); + doRemoveProtectedExpirableData(protectedMailboxStorageEntry, hashOfData); - broadcast(new RemoveMailboxDataMessage(protectedMailboxData), sender); + broadcast(new RemoveMailboxDataMessage(protectedMailboxStorageEntry), sender); - sequenceNumberMap.put(hashOfData, new MapValue(protectedMailboxData.sequenceNumber, System.currentTimeMillis())); + sequenceNumberMap.put(hashOfData, new MapValue(protectedMailboxStorageEntry.sequenceNumber, System.currentTimeMillis())); storage.queueUpForSave(sequenceNumberMap, 100); } else { log.debug("removeMailboxData failed"); @@ -313,55 +317,51 @@ public class P2PDataStorage implements MessageListener, ConnectionListener { } - public Map getMap() { + public Map getMap() { return map; } - public ProtectedData getProtectedData(ExpirablePayload payload, KeyPair ownerStoragePubKey) + public ProtectedStorageEntry getProtectedData(StoragePayload storagePayload, KeyPair ownerStoragePubKey) throws CryptoException { - ByteArray hashOfData = getHashAsByteArray(payload); + ByteArray hashOfData = getHashAsByteArray(storagePayload); int sequenceNumber; if (sequenceNumberMap.containsKey(hashOfData)) sequenceNumber = sequenceNumberMap.get(hashOfData).sequenceNr + 1; else sequenceNumber = 0; - log.error("getProtectedData sequenceNumber " + sequenceNumber); - - byte[] hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNrPair(payload, sequenceNumber)); + byte[] hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNrPair(storagePayload, sequenceNumber)); byte[] signature = Sig.sign(ownerStoragePubKey.getPrivate(), hashOfDataAndSeqNr); - return new ProtectedData(payload, payload.getTTL(), ownerStoragePubKey.getPublic(), sequenceNumber, signature); + return new ProtectedStorageEntry(storagePayload, ownerStoragePubKey.getPublic(), sequenceNumber, signature); } - public RefreshTTLMessage getRefreshTTLMessage(ExpirablePayload payload, KeyPair ownerStoragePubKey) + public RefreshTTLMessage getRefreshTTLMessage(StoragePayload storagePayload, KeyPair ownerStoragePubKey) throws CryptoException { - ByteArray hashOfPayload = getHashAsByteArray(payload); + ByteArray hashOfPayload = getHashAsByteArray(storagePayload); int sequenceNumber; if (sequenceNumberMap.containsKey(hashOfPayload)) sequenceNumber = sequenceNumberMap.get(hashOfPayload).sequenceNr + 1; else sequenceNumber = 0; - log.error("getRefreshTTLMessage sequenceNumber " + sequenceNumber); - - byte[] hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNrPair(payload, sequenceNumber)); + byte[] hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNrPair(storagePayload, sequenceNumber)); byte[] signature = Sig.sign(ownerStoragePubKey.getPrivate(), hashOfDataAndSeqNr); return new RefreshTTLMessage(hashOfDataAndSeqNr, signature, hashOfPayload.bytes, sequenceNumber); } - public ProtectedMailboxData getMailboxDataWithSignedSeqNr(MailboxPayload expirableMailboxPayload, + public ProtectedMailboxStorageEntry getMailboxDataWithSignedSeqNr(MailboxStoragePayload expirableMailboxStoragePayload, KeyPair storageSignaturePubKey, PublicKey receiversPublicKey) throws CryptoException { - ByteArray hashOfData = getHashAsByteArray(expirableMailboxPayload); + ByteArray hashOfData = getHashAsByteArray(expirableMailboxStoragePayload); int sequenceNumber; if (sequenceNumberMap.containsKey(hashOfData)) sequenceNumber = sequenceNumberMap.get(hashOfData).sequenceNr + 1; else sequenceNumber = 0; - byte[] hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNrPair(expirableMailboxPayload, sequenceNumber)); + byte[] hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNrPair(expirableMailboxStoragePayload, sequenceNumber)); byte[] signature = Sig.sign(storageSignaturePubKey.getPrivate(), hashOfDataAndSeqNr); - return new ProtectedMailboxData(expirableMailboxPayload, expirableMailboxPayload.getTTL(), + return new ProtectedMailboxStorageEntry(expirableMailboxStoragePayload, storageSignaturePubKey.getPublic(), sequenceNumber, signature, receiversPublicKey); } @@ -374,10 +374,10 @@ public class P2PDataStorage implements MessageListener, ConnectionListener { // Private /////////////////////////////////////////////////////////////////////////////////////////// - private void doRemoveProtectedExpirableData(ProtectedData protectedData, ByteArray hashOfPayload) { + private void doRemoveProtectedExpirableData(ProtectedStorageEntry protectedStorageEntry, ByteArray hashOfPayload) { map.remove(hashOfPayload); log.trace("Data removed from our map. We broadcast the message to our peers."); - hashMapChangedListeners.stream().forEach(e -> e.onRemoved(protectedData)); + hashMapChangedListeners.stream().forEach(e -> e.onRemoved(protectedStorageEntry)); StringBuilder sb = new StringBuilder("\n\n------------------------------------------------------------\n" + "Data set after removeProtectedExpirableData: (truncated)"); @@ -416,21 +416,21 @@ public class P2PDataStorage implements MessageListener, ConnectionListener { } } - private boolean checkSignature(ProtectedData data) { - byte[] hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNrPair(data.expirablePayload, data.sequenceNumber)); - return checkSignature(data.ownerPubKey, hashOfDataAndSeqNr, data.signature); + private boolean checkSignature(ProtectedStorageEntry protectedStorageEntry) { + byte[] hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNrPair(protectedStorageEntry.getStoragePayload(), protectedStorageEntry.sequenceNumber)); + return checkSignature(protectedStorageEntry.ownerPubKey, hashOfDataAndSeqNr, protectedStorageEntry.signature); } - private boolean checkPublicKeys(ProtectedData data, boolean isAddOperation) { - boolean result = false; - if (data.expirablePayload instanceof MailboxPayload) { - MailboxPayload expirableMailboxPayload = (MailboxPayload) data.expirablePayload; + private boolean checkPublicKeys(ProtectedStorageEntry protectedStorageEntry, boolean isAddOperation) { + boolean result; + if (protectedStorageEntry.getStoragePayload() instanceof MailboxStoragePayload) { + MailboxStoragePayload expirableMailboxStoragePayload = (MailboxStoragePayload) protectedStorageEntry.getStoragePayload(); if (isAddOperation) - result = expirableMailboxPayload.senderPubKeyForAddOperation.equals(data.ownerPubKey); + result = expirableMailboxStoragePayload.senderPubKeyForAddOperation.equals(protectedStorageEntry.ownerPubKey); else - result = expirableMailboxPayload.receiverPubKeyForRemoveOperation.equals(data.ownerPubKey); - } else if (data.expirablePayload instanceof StoragePayload) { - result = ((StoragePayload) data.expirablePayload).getOwnerPubKey().equals(data.ownerPubKey); + result = expirableMailboxStoragePayload.receiverPubKeyForRemoveOperation.equals(protectedStorageEntry.ownerPubKey); + } else { + result = protectedStorageEntry.getStoragePayload().getOwnerPubKey().equals(protectedStorageEntry.ownerPubKey); } if (!result) @@ -440,7 +440,7 @@ public class P2PDataStorage implements MessageListener, ConnectionListener { private boolean checkIfStoredDataPubKeyMatchesNewDataPubKey(PublicKey ownerPubKey, ByteArray hashOfData) { if (map.containsKey(hashOfData)) { - ProtectedData storedData = map.get(hashOfData); + ProtectedStorageEntry storedData = map.get(hashOfData); boolean result = storedData.ownerPubKey.equals(ownerPubKey); if (!result) log.error("New data entry does not match our stored data. Consider it might be an attempt of fraud"); @@ -452,12 +452,12 @@ public class P2PDataStorage implements MessageListener, ConnectionListener { } private boolean checkIfStoredMailboxDataMatchesNewMailboxData(PublicKey receiversPubKey, ByteArray hashOfData) { - ProtectedData storedData = map.get(hashOfData); - if (storedData instanceof ProtectedMailboxData) { - ProtectedMailboxData storedMailboxData = (ProtectedMailboxData) storedData; + ProtectedStorageEntry storedData = map.get(hashOfData); + if (storedData instanceof ProtectedMailboxStorageEntry) { + ProtectedMailboxStorageEntry storedMailboxData = (ProtectedMailboxStorageEntry) storedData; // publicKey is not the same (stored: sender, new: receiver) boolean result = storedMailboxData.receiversPubKey.equals(receiversPubKey) - && getHashAsByteArray(storedMailboxData.expirablePayload).equals(hashOfData); + && getHashAsByteArray(storedMailboxData.getStoragePayload()).equals(hashOfData); if (!result) log.error("New data entry does not match our stored data. Consider it might be an attempt of fraud"); @@ -468,7 +468,7 @@ public class P2PDataStorage implements MessageListener, ConnectionListener { } } - private void broadcast(DataBroadcastMessage message, @Nullable NodeAddress sender) { + private void broadcast(BroadcastMessage message, @Nullable NodeAddress sender) { broadcaster.broadcast(message, sender); } diff --git a/network/src/main/java/io/bitsquare/p2p/storage/data/ProtectedData.java b/network/src/main/java/io/bitsquare/p2p/storage/data/ProtectedData.java deleted file mode 100644 index 8cd54d8770..0000000000 --- a/network/src/main/java/io/bitsquare/p2p/storage/data/ProtectedData.java +++ /dev/null @@ -1,76 +0,0 @@ -package io.bitsquare.p2p.storage.data; - -import com.google.common.annotations.VisibleForTesting; -import io.bitsquare.common.wire.Payload; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.security.PublicKey; -import java.util.Arrays; -import java.util.Date; - -public class ProtectedData implements Payload { - private static final Logger log = LoggerFactory.getLogger(ProtectedData.class); - - public final ExpirablePayload expirablePayload; - - //TODO check if that field make sense as it is in expirableMessage.getTTL() - transient public long ttl; - - public final PublicKey ownerPubKey; - public int sequenceNumber; - public byte[] signature; - @VisibleForTesting - transient public Date date; - - public ProtectedData(ExpirablePayload expirablePayload, long ttl, PublicKey ownerPubKey, int sequenceNumber, byte[] signature) { - this.expirablePayload = expirablePayload; - this.ttl = ttl; - this.ownerPubKey = ownerPubKey; - this.sequenceNumber = sequenceNumber; - this.signature = signature; - this.date = new Date(); - } - - private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { - try { - in.defaultReadObject(); - ttl = expirablePayload.getTTL(); - date = new Date(); - - } catch (Throwable t) { - log.error("Exception at readObject: " + t.getMessage()); - t.printStackTrace(); - } - } - - public void refreshDate() { - date = new Date(); - } - - public void updateSequenceNumber(int sequenceNumber) { - this.sequenceNumber = sequenceNumber; - } - - public void updateSignature(byte[] signature) { - this.signature = signature; - } - - public boolean isExpired() { - return (new Date().getTime() - date.getTime()) > ttl; - } - - @Override - public String toString() { - return "ProtectedData{" + - "expirablePayload=" + expirablePayload + - ", ttl=" + ttl + - ", date=" + date + - ", sequenceNumber=" + sequenceNumber + - ", ownerPubKey.hashCode()=" + ownerPubKey.hashCode() + - ", signature.hashCode()=" + Arrays.toString(signature).hashCode() + - '}'; - } - -} diff --git a/network/src/main/java/io/bitsquare/p2p/storage/data/ProtectedMailboxData.java b/network/src/main/java/io/bitsquare/p2p/storage/data/ProtectedMailboxData.java deleted file mode 100644 index ed0d8cb11b..0000000000 --- a/network/src/main/java/io/bitsquare/p2p/storage/data/ProtectedMailboxData.java +++ /dev/null @@ -1,59 +0,0 @@ -package io.bitsquare.p2p.storage.data; - -import io.bitsquare.p2p.storage.P2PDataStorage; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.security.PublicKey; -import java.util.Date; -import java.util.concurrent.TimeUnit; - -public class ProtectedMailboxData extends ProtectedData { - private static final Logger log = LoggerFactory.getLogger(P2PDataStorage.class); - - public final PublicKey receiversPubKey; - - public ProtectedMailboxData(MailboxPayload data, long ttl, PublicKey ownerStoragePubKey, int sequenceNumber, byte[] signature, PublicKey receiversPubKey) { - super(data, ttl, ownerStoragePubKey, sequenceNumber, signature); - - this.receiversPubKey = receiversPubKey; - } - - private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { - try { - in.defaultReadObject(); - ttl = expirablePayload.getTTL(); - - // in case the reported creation date is in the future - // we reset the date to the current time - if (date.getTime() > new Date().getTime()) { - if (date.getTime() > new Date().getTime() + TimeUnit.MINUTES.toMillis(1)) - log.warn("Date of object is more then a minute in future. " + - "That might be ok as peers clocks are not synced but could be also a spam attack.\n" + - "date=" + date + " / now=" + new Date()); - else - log.debug("Date of object is slightly future. " + - "That is probably because peers clocks are not synced.\n" + - "date=" + date + " / now=" + new Date()); - date = new Date(); - } - date = new Date(); - - } catch (Throwable t) { - log.error("Exception at readObject: " + t.getMessage()); - t.printStackTrace(); - } - } - - public boolean isExpired() { - return (new Date().getTime() - date.getTime()) > ttl; - } - - @Override - public String toString() { - return "ProtectedMailboxData{" + - "receiversPubKey.hashCode()=" + receiversPubKey.hashCode() + - "} " + super.toString(); - } -} diff --git a/network/src/main/java/io/bitsquare/p2p/storage/messages/AddDataMessage.java b/network/src/main/java/io/bitsquare/p2p/storage/messages/AddDataMessage.java index 8d7fe07895..d0ca9cd86f 100644 --- a/network/src/main/java/io/bitsquare/p2p/storage/messages/AddDataMessage.java +++ b/network/src/main/java/io/bitsquare/p2p/storage/messages/AddDataMessage.java @@ -1,16 +1,16 @@ package io.bitsquare.p2p.storage.messages; import io.bitsquare.app.Version; -import io.bitsquare.p2p.storage.data.ProtectedData; +import io.bitsquare.p2p.storage.storageentry.ProtectedStorageEntry; -public final class AddDataMessage extends DataBroadcastMessage { +public final class AddDataMessage extends BroadcastMessage { // That object is sent over the wire, so we need to take care of version compatibility. private static final long serialVersionUID = Version.P2P_NETWORK_VERSION; - public final ProtectedData data; + public final ProtectedStorageEntry protectedStorageEntry; - public AddDataMessage(ProtectedData data) { - this.data = data; + public AddDataMessage(ProtectedStorageEntry protectedStorageEntry) { + this.protectedStorageEntry = protectedStorageEntry; } @Override @@ -20,18 +20,18 @@ public final class AddDataMessage extends DataBroadcastMessage { AddDataMessage that = (AddDataMessage) o; - return !(data != null ? !data.equals(that.data) : that.data != null); + return !(protectedStorageEntry != null ? !protectedStorageEntry.equals(that.protectedStorageEntry) : that.protectedStorageEntry != null); } @Override public int hashCode() { - return data != null ? data.hashCode() : 0; + return protectedStorageEntry != null ? protectedStorageEntry.hashCode() : 0; } @Override public String toString() { return "AddDataMessage{" + - "data=" + data + + "protectedStorageEntry=" + protectedStorageEntry + "} " + super.toString(); } } diff --git a/network/src/main/java/io/bitsquare/p2p/storage/messages/DataBroadcastMessage.java b/network/src/main/java/io/bitsquare/p2p/storage/messages/BroadcastMessage.java similarity index 87% rename from network/src/main/java/io/bitsquare/p2p/storage/messages/DataBroadcastMessage.java rename to network/src/main/java/io/bitsquare/p2p/storage/messages/BroadcastMessage.java index be3c7d0547..dc71201d5d 100644 --- a/network/src/main/java/io/bitsquare/p2p/storage/messages/DataBroadcastMessage.java +++ b/network/src/main/java/io/bitsquare/p2p/storage/messages/BroadcastMessage.java @@ -3,7 +3,7 @@ package io.bitsquare.p2p.storage.messages; import io.bitsquare.app.Version; import io.bitsquare.p2p.Message; -public abstract class DataBroadcastMessage implements Message { +public abstract class BroadcastMessage implements Message { private final int messageVersion = Version.getP2PMessageVersion(); @Override diff --git a/network/src/main/java/io/bitsquare/p2p/storage/messages/RefreshTTLMessage.java b/network/src/main/java/io/bitsquare/p2p/storage/messages/RefreshTTLMessage.java index db1a33706a..275ccb7aa4 100644 --- a/network/src/main/java/io/bitsquare/p2p/storage/messages/RefreshTTLMessage.java +++ b/network/src/main/java/io/bitsquare/p2p/storage/messages/RefreshTTLMessage.java @@ -4,7 +4,7 @@ import io.bitsquare.app.Version; import java.util.Arrays; -public final class RefreshTTLMessage extends DataBroadcastMessage { +public final class RefreshTTLMessage extends BroadcastMessage { // That object is sent over the wire, so we need to take care of version compatibility. private static final long serialVersionUID = Version.P2P_NETWORK_VERSION; diff --git a/network/src/main/java/io/bitsquare/p2p/storage/messages/RemoveDataMessage.java b/network/src/main/java/io/bitsquare/p2p/storage/messages/RemoveDataMessage.java index 808af238ee..4039c31773 100644 --- a/network/src/main/java/io/bitsquare/p2p/storage/messages/RemoveDataMessage.java +++ b/network/src/main/java/io/bitsquare/p2p/storage/messages/RemoveDataMessage.java @@ -1,16 +1,16 @@ package io.bitsquare.p2p.storage.messages; import io.bitsquare.app.Version; -import io.bitsquare.p2p.storage.data.ProtectedData; +import io.bitsquare.p2p.storage.storageentry.ProtectedStorageEntry; -public final class RemoveDataMessage extends DataBroadcastMessage { +public final class RemoveDataMessage extends BroadcastMessage { // That object is sent over the wire, so we need to take care of version compatibility. private static final long serialVersionUID = Version.P2P_NETWORK_VERSION; - public final ProtectedData data; + public final ProtectedStorageEntry protectedStorageEntry; - public RemoveDataMessage(ProtectedData data) { - this.data = data; + public RemoveDataMessage(ProtectedStorageEntry protectedStorageEntry) { + this.protectedStorageEntry = protectedStorageEntry; } @Override @@ -20,19 +20,19 @@ public final class RemoveDataMessage extends DataBroadcastMessage { RemoveDataMessage that = (RemoveDataMessage) o; - return !(data != null ? !data.equals(that.data) : that.data != null); + return !(protectedStorageEntry != null ? !protectedStorageEntry.equals(that.protectedStorageEntry) : that.protectedStorageEntry != null); } @Override public int hashCode() { - return data != null ? data.hashCode() : 0; + return protectedStorageEntry != null ? protectedStorageEntry.hashCode() : 0; } @Override public String toString() { return "RemoveDataMessage{" + - "data=" + data + + "protectedStorageEntry=" + protectedStorageEntry + "} " + super.toString(); } } diff --git a/network/src/main/java/io/bitsquare/p2p/storage/messages/RemoveMailboxDataMessage.java b/network/src/main/java/io/bitsquare/p2p/storage/messages/RemoveMailboxDataMessage.java index 954f480f9b..b954ab3753 100644 --- a/network/src/main/java/io/bitsquare/p2p/storage/messages/RemoveMailboxDataMessage.java +++ b/network/src/main/java/io/bitsquare/p2p/storage/messages/RemoveMailboxDataMessage.java @@ -1,16 +1,16 @@ package io.bitsquare.p2p.storage.messages; import io.bitsquare.app.Version; -import io.bitsquare.p2p.storage.data.ProtectedMailboxData; +import io.bitsquare.p2p.storage.storageentry.ProtectedMailboxStorageEntry; -public final class RemoveMailboxDataMessage extends DataBroadcastMessage { +public final class RemoveMailboxDataMessage extends BroadcastMessage { // That object is sent over the wire, so we need to take care of version compatibility. private static final long serialVersionUID = Version.P2P_NETWORK_VERSION; - public final ProtectedMailboxData data; + public final ProtectedMailboxStorageEntry protectedMailboxStorageEntry; - public RemoveMailboxDataMessage(ProtectedMailboxData data) { - this.data = data; + public RemoveMailboxDataMessage(ProtectedMailboxStorageEntry protectedMailboxStorageEntry) { + this.protectedMailboxStorageEntry = protectedMailboxStorageEntry; } @Override @@ -20,19 +20,18 @@ public final class RemoveMailboxDataMessage extends DataBroadcastMessage { RemoveMailboxDataMessage that = (RemoveMailboxDataMessage) o; - return !(data != null ? !data.equals(that.data) : that.data != null); - + return !(protectedMailboxStorageEntry != null ? !protectedMailboxStorageEntry.equals(that.protectedMailboxStorageEntry) : that.protectedMailboxStorageEntry != null); } @Override public int hashCode() { - return data != null ? data.hashCode() : 0; + return protectedMailboxStorageEntry != null ? protectedMailboxStorageEntry.hashCode() : 0; } @Override public String toString() { return "RemoveMailboxDataMessage{" + - "data=" + data + + "data=" + protectedMailboxStorageEntry + "} " + super.toString(); } } diff --git a/network/src/main/java/io/bitsquare/p2p/storage/data/ExpirablePayload.java b/network/src/main/java/io/bitsquare/p2p/storage/payload/ExpirablePayload.java similarity index 79% rename from network/src/main/java/io/bitsquare/p2p/storage/data/ExpirablePayload.java rename to network/src/main/java/io/bitsquare/p2p/storage/payload/ExpirablePayload.java index d5b24103f0..7ae9fcb836 100644 --- a/network/src/main/java/io/bitsquare/p2p/storage/data/ExpirablePayload.java +++ b/network/src/main/java/io/bitsquare/p2p/storage/payload/ExpirablePayload.java @@ -1,4 +1,4 @@ -package io.bitsquare.p2p.storage.data; +package io.bitsquare.p2p.storage.payload; import io.bitsquare.common.wire.Payload; @@ -8,7 +8,7 @@ import io.bitsquare.common.wire.Payload; * Implementations: * * @see StoragePayload - * @see MailboxPayload + * @see MailboxStoragePayload */ public interface ExpirablePayload extends Payload { /** diff --git a/network/src/main/java/io/bitsquare/p2p/storage/data/MailboxPayload.java b/network/src/main/java/io/bitsquare/p2p/storage/payload/MailboxStoragePayload.java similarity index 53% rename from network/src/main/java/io/bitsquare/p2p/storage/data/MailboxPayload.java rename to network/src/main/java/io/bitsquare/p2p/storage/payload/MailboxStoragePayload.java index 0e8c840996..56ef96915f 100644 --- a/network/src/main/java/io/bitsquare/p2p/storage/data/MailboxPayload.java +++ b/network/src/main/java/io/bitsquare/p2p/storage/payload/MailboxStoragePayload.java @@ -1,10 +1,17 @@ -package io.bitsquare.p2p.storage.data; +package io.bitsquare.p2p.storage.payload; import io.bitsquare.app.Version; -import io.bitsquare.crypto.PrefixedSealedAndSignedMessage; +import io.bitsquare.common.crypto.Sig; import io.bitsquare.p2p.NodeAddress; +import io.bitsquare.p2p.messaging.PrefixedSealedAndSignedMessage; +import io.bitsquare.p2p.storage.storageentry.ProtectedStorageEntry; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.IOException; +import java.security.KeyFactory; import java.security.PublicKey; +import java.security.spec.X509EncodedKeySpec; import java.util.concurrent.TimeUnit; /** @@ -15,9 +22,10 @@ import java.util.concurrent.TimeUnit; *

* Typical payloads are trade or dispute messages to be stored when the peer is offline. */ -public final class MailboxPayload implements ExpirablePayload { +public final class MailboxStoragePayload implements StoragePayload { // That object is sent over the wire, so we need to take care of version compatibility. private static final long serialVersionUID = Version.P2P_NETWORK_VERSION; + private static final Logger log = LoggerFactory.getLogger(MailboxStoragePayload.class); private static final long TTL = TimeUnit.DAYS.toMillis(10); @@ -30,24 +38,40 @@ public final class MailboxPayload implements ExpirablePayload { * Used for check if the add operation is permitted. * senderStoragePublicKey has to be equal to the ownerPubKey of the ProtectedData * - * @see ProtectedData#ownerPubKey - * @see io.bitsquare.p2p.storage.P2PDataStorage#add(ProtectedData, NodeAddress) + * @see ProtectedStorageEntry#ownerPubKey + * @see io.bitsquare.p2p.storage.P2PDataStorage#add(ProtectedStorageEntry, NodeAddress) */ - public final PublicKey senderPubKeyForAddOperation; - + public transient PublicKey senderPubKeyForAddOperation; + private final byte[] senderPubKeyForAddOperationBytes; /** * Used for check if the remove operation is permitted. * senderStoragePublicKey has to be equal to the ownerPubKey of the ProtectedData * - * @see ProtectedData#ownerPubKey - * @see io.bitsquare.p2p.storage.P2PDataStorage#remove(ProtectedData, NodeAddress) + * @see ProtectedStorageEntry#ownerPubKey + * @see io.bitsquare.p2p.storage.P2PDataStorage#remove(ProtectedStorageEntry, NodeAddress) */ - public final PublicKey receiverPubKeyForRemoveOperation; + public transient PublicKey receiverPubKeyForRemoveOperation; + private final byte[] receiverPubKeyForRemoveOperationBytes; - public MailboxPayload(PrefixedSealedAndSignedMessage prefixedSealedAndSignedMessage, PublicKey senderPubKeyForAddOperation, PublicKey receiverPubKeyForRemoveOperation) { + public MailboxStoragePayload(PrefixedSealedAndSignedMessage prefixedSealedAndSignedMessage, PublicKey senderPubKeyForAddOperation, PublicKey receiverPubKeyForRemoveOperation) { this.prefixedSealedAndSignedMessage = prefixedSealedAndSignedMessage; + this.senderPubKeyForAddOperation = senderPubKeyForAddOperation; + this.senderPubKeyForAddOperationBytes = new X509EncodedKeySpec(this.senderPubKeyForAddOperation.getEncoded()).getEncoded(); + this.receiverPubKeyForRemoveOperation = receiverPubKeyForRemoveOperation; + this.receiverPubKeyForRemoveOperationBytes = new X509EncodedKeySpec(this.receiverPubKeyForRemoveOperation.getEncoded()).getEncoded(); + } + + private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { + try { + in.defaultReadObject(); + senderPubKeyForAddOperation = KeyFactory.getInstance(Sig.KEY_ALGO, "BC").generatePublic(new X509EncodedKeySpec(senderPubKeyForAddOperationBytes)); + receiverPubKeyForRemoveOperation = KeyFactory.getInstance(Sig.KEY_ALGO, "BC").generatePublic(new X509EncodedKeySpec(receiverPubKeyForRemoveOperationBytes)); + } catch (Throwable t) { + log.error("Exception at readObject: " + t.getMessage()); + t.printStackTrace(); + } } @Override @@ -55,12 +79,17 @@ public final class MailboxPayload implements ExpirablePayload { return TTL; } + @Override + public PublicKey getOwnerPubKey() { + return receiverPubKeyForRemoveOperation; + } + @Override public boolean equals(Object o) { if (this == o) return true; - if (!(o instanceof MailboxPayload)) return false; + if (!(o instanceof MailboxStoragePayload)) return false; - MailboxPayload that = (MailboxPayload) o; + MailboxStoragePayload that = (MailboxStoragePayload) o; return !(prefixedSealedAndSignedMessage != null ? !prefixedSealedAndSignedMessage.equals(that.prefixedSealedAndSignedMessage) : that.prefixedSealedAndSignedMessage != null); diff --git a/network/src/main/java/io/bitsquare/p2p/storage/data/RequiresOwnerIsOnlinePayload.java b/network/src/main/java/io/bitsquare/p2p/storage/payload/RequiresOwnerIsOnlinePayload.java similarity index 67% rename from network/src/main/java/io/bitsquare/p2p/storage/data/RequiresOwnerIsOnlinePayload.java rename to network/src/main/java/io/bitsquare/p2p/storage/payload/RequiresOwnerIsOnlinePayload.java index d44ad1d5e2..90b51815e6 100644 --- a/network/src/main/java/io/bitsquare/p2p/storage/data/RequiresOwnerIsOnlinePayload.java +++ b/network/src/main/java/io/bitsquare/p2p/storage/payload/RequiresOwnerIsOnlinePayload.java @@ -1,4 +1,4 @@ -package io.bitsquare.p2p.storage.data; +package io.bitsquare.p2p.storage.payload; import io.bitsquare.common.wire.Payload; import io.bitsquare.p2p.NodeAddress; @@ -6,8 +6,8 @@ import io.bitsquare.p2p.NodeAddress; /** * Used for messages which require that the data owner is online. *

- * This is used for the offers to avoid dead offers in case the offerer is in sleep/hibernate mode or the app has - * terminated without sending the remove message (e.g. in case of a crash). + * This is used for the offers to avoid dead offers in case the offerer is in standby mode or the app has + * terminated without sending the remove message (e.g. network connection lost or in case of a crash). */ public interface RequiresOwnerIsOnlinePayload extends Payload { /** diff --git a/network/src/main/java/io/bitsquare/p2p/storage/data/StoragePayload.java b/network/src/main/java/io/bitsquare/p2p/storage/payload/StoragePayload.java similarity index 78% rename from network/src/main/java/io/bitsquare/p2p/storage/data/StoragePayload.java rename to network/src/main/java/io/bitsquare/p2p/storage/payload/StoragePayload.java index 3cee52c814..e07b0c4c5e 100644 --- a/network/src/main/java/io/bitsquare/p2p/storage/data/StoragePayload.java +++ b/network/src/main/java/io/bitsquare/p2p/storage/payload/StoragePayload.java @@ -1,6 +1,7 @@ -package io.bitsquare.p2p.storage.data; +package io.bitsquare.p2p.storage.payload; import io.bitsquare.p2p.NodeAddress; +import io.bitsquare.p2p.storage.storageentry.ProtectedStorageEntry; import java.security.PublicKey; @@ -19,9 +20,9 @@ public interface StoragePayload extends ExpirablePayload { * OwnerPubKey has to be equal to the ownerPubKey of the ProtectedData * * @return The public key of the data owner. - * @see ProtectedData#ownerPubKey - * @see io.bitsquare.p2p.storage.P2PDataStorage#add(ProtectedData, NodeAddress) - * @see io.bitsquare.p2p.storage.P2PDataStorage#remove(ProtectedData, NodeAddress) + * @see ProtectedStorageEntry#ownerPubKey + * @see io.bitsquare.p2p.storage.P2PDataStorage#add(ProtectedStorageEntry, NodeAddress) + * @see io.bitsquare.p2p.storage.P2PDataStorage#remove(ProtectedStorageEntry, NodeAddress) */ PublicKey getOwnerPubKey(); } diff --git a/network/src/main/java/io/bitsquare/p2p/storage/storageentry/ProtectedMailboxStorageEntry.java b/network/src/main/java/io/bitsquare/p2p/storage/storageentry/ProtectedMailboxStorageEntry.java new file mode 100644 index 0000000000..800b7dd2eb --- /dev/null +++ b/network/src/main/java/io/bitsquare/p2p/storage/storageentry/ProtectedMailboxStorageEntry.java @@ -0,0 +1,52 @@ +package io.bitsquare.p2p.storage.storageentry; + +import io.bitsquare.app.Version; +import io.bitsquare.common.crypto.Sig; +import io.bitsquare.p2p.storage.P2PDataStorage; +import io.bitsquare.p2p.storage.payload.MailboxStoragePayload; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.security.KeyFactory; +import java.security.PublicKey; +import java.security.spec.X509EncodedKeySpec; + +public class ProtectedMailboxStorageEntry extends ProtectedStorageEntry { + // That object is sent over the wire, so we need to take care of version compatibility. + private static final long serialVersionUID = Version.P2P_NETWORK_VERSION; + + private static final Logger log = LoggerFactory.getLogger(P2PDataStorage.class); + + public transient PublicKey receiversPubKey; + private final byte[] receiversPubKeyBytes; + + public MailboxStoragePayload getMailboxStoragePayload() { + return (MailboxStoragePayload) storagePayload; + } + + public ProtectedMailboxStorageEntry(MailboxStoragePayload mailboxStoragePayload, PublicKey ownerStoragePubKey, int sequenceNumber, byte[] signature, PublicKey receiversPubKey) { + super(mailboxStoragePayload, ownerStoragePubKey, sequenceNumber, signature); + + this.receiversPubKey = receiversPubKey; + this.receiversPubKeyBytes = new X509EncodedKeySpec(this.receiversPubKey.getEncoded()).getEncoded(); + } + + private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { + try { + in.defaultReadObject(); + receiversPubKey = KeyFactory.getInstance(Sig.KEY_ALGO, "BC").generatePublic(new X509EncodedKeySpec(receiversPubKeyBytes)); + updateTimeStamp(); + } catch (Throwable t) { + log.error("Exception at readObject: " + t.getMessage()); + t.printStackTrace(); + } + } + + @Override + public String toString() { + return "ProtectedMailboxData{" + + "receiversPubKey.hashCode()=" + receiversPubKey.hashCode() + + "} " + super.toString(); + } +} diff --git a/network/src/main/java/io/bitsquare/p2p/storage/storageentry/ProtectedStorageEntry.java b/network/src/main/java/io/bitsquare/p2p/storage/storageentry/ProtectedStorageEntry.java new file mode 100644 index 0000000000..06c9af3b3b --- /dev/null +++ b/network/src/main/java/io/bitsquare/p2p/storage/storageentry/ProtectedStorageEntry.java @@ -0,0 +1,82 @@ +package io.bitsquare.p2p.storage.storageentry; + +import com.google.common.annotations.VisibleForTesting; +import io.bitsquare.app.Version; +import io.bitsquare.common.crypto.Sig; +import io.bitsquare.common.wire.Payload; +import io.bitsquare.p2p.storage.payload.StoragePayload; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.security.KeyFactory; +import java.security.PublicKey; +import java.security.spec.X509EncodedKeySpec; +import java.util.Arrays; + +public class ProtectedStorageEntry implements Payload { + // That object is sent over the wire, so we need to take care of version compatibility. + private static final long serialVersionUID = Version.P2P_NETWORK_VERSION; + + private static final Logger log = LoggerFactory.getLogger(ProtectedStorageEntry.class); + + protected final StoragePayload storagePayload; + private final byte[] ownerPubKeyBytes; + public transient PublicKey ownerPubKey; + public int sequenceNumber; + public byte[] signature; + @VisibleForTesting + transient public long timeStamp; + + public ProtectedStorageEntry(StoragePayload storagePayload, PublicKey ownerPubKey, int sequenceNumber, byte[] signature) { + this.storagePayload = storagePayload; + this.ownerPubKey = ownerPubKey; + this.sequenceNumber = sequenceNumber; + this.signature = signature; + this.timeStamp = System.currentTimeMillis(); + this.ownerPubKeyBytes = new X509EncodedKeySpec(this.ownerPubKey.getEncoded()).getEncoded(); + } + + private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { + try { + in.defaultReadObject(); + ownerPubKey = KeyFactory.getInstance(Sig.KEY_ALGO, "BC").generatePublic(new X509EncodedKeySpec(ownerPubKeyBytes)); + updateTimeStamp(); + } catch (Throwable t) { + log.error("Exception at readObject: " + t.getMessage()); + t.printStackTrace(); + } + } + + public StoragePayload getStoragePayload() { + return storagePayload; + } + + public void updateTimeStamp() { + timeStamp = System.currentTimeMillis(); + } + + public void updateSequenceNumber(int sequenceNumber) { + this.sequenceNumber = sequenceNumber; + } + + public void updateSignature(byte[] signature) { + this.signature = signature; + } + + public boolean isExpired() { + return (System.currentTimeMillis() - timeStamp) > storagePayload.getTTL(); + } + + @Override + public String toString() { + return "ProtectedData{" + + "expirablePayload=" + storagePayload + + ", timeStamp=" + timeStamp + + ", sequenceNumber=" + sequenceNumber + + ", ownerPubKey.hashCode()=" + ownerPubKey.hashCode() + + ", signature.hashCode()=" + Arrays.toString(signature).hashCode() + + '}'; + } + +} diff --git a/network/src/test/java/io/bitsquare/crypto/EncryptionServiceTests.java b/network/src/test/java/io/bitsquare/crypto/EncryptionServiceTests.java index f7c0c2e000..1a63b6bd12 100644 --- a/network/src/test/java/io/bitsquare/crypto/EncryptionServiceTests.java +++ b/network/src/test/java/io/bitsquare/crypto/EncryptionServiceTests.java @@ -22,8 +22,8 @@ import io.bitsquare.app.Version; import io.bitsquare.common.crypto.*; import io.bitsquare.common.util.Utilities; import io.bitsquare.p2p.NodeAddress; -import io.bitsquare.p2p.messaging.DecryptedMsgWithPubKey; import io.bitsquare.p2p.messaging.MailboxMessage; +import io.bitsquare.p2p.messaging.PrefixedSealedAndSignedMessage; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.junit.After; import org.junit.Before; @@ -39,6 +39,7 @@ import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.Security; import java.security.cert.CertificateException; +import java.util.UUID; import static org.junit.Assert.assertEquals; @@ -84,9 +85,16 @@ public class EncryptionServiceTests { final class TestMessage implements MailboxMessage { public String data = "test"; private final int messageVersion = Version.getP2PMessageVersion(); + private String uid; public TestMessage(String data) { this.data = data; + uid = UUID.randomUUID().toString(); + } + + @Override + public String getUID() { + return uid; } @Override diff --git a/network/src/test/java/io/bitsquare/p2p/P2PServiceTest.java b/network/src/test/java/io/bitsquare/p2p/P2PServiceTest.java deleted file mode 100644 index a35a5be2d9..0000000000 --- a/network/src/test/java/io/bitsquare/p2p/P2PServiceTest.java +++ /dev/null @@ -1,382 +0,0 @@ -package io.bitsquare.p2p; - -import io.bitsquare.common.crypto.*; -import io.bitsquare.crypto.EncryptionService; -import io.bitsquare.crypto.PrefixedSealedAndSignedMessage; -import io.bitsquare.p2p.messaging.DecryptedMsgWithPubKey; -import io.bitsquare.p2p.messaging.MailboxMessage; -import io.bitsquare.p2p.messaging.SendMailboxMessageListener; -import io.bitsquare.p2p.mocks.MockMailboxPayload; -import io.bitsquare.p2p.network.LocalhostNetworkNode; -import io.bitsquare.p2p.peers.PeerManager; -import io.bitsquare.p2p.seed.SeedNode; -import io.bitsquare.p2p.storage.P2PDataStorage; -import io.bitsquare.p2p.storage.data.ProtectedData; -import io.bitsquare.p2p.storage.mocks.MockData; -import org.bouncycastle.jce.provider.BouncyCastleProvider; -import org.junit.*; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.io.IOException; -import java.security.*; -import java.security.cert.CertificateException; -import java.util.HashSet; -import java.util.Set; -import java.util.concurrent.CountDownLatch; -import java.util.stream.Collectors; - -// TorNode created. Took 6 sec. -// Hidden service created. Took 40-50 sec. -// Connection establishment takes about 4 sec. - -// need to define seed node addresses first before using tor version -// Ignored for automated tests - -//TODO P2P network tests are outdated -@Ignore -public class P2PServiceTest { - private static final Logger log = LoggerFactory.getLogger(P2PServiceTest.class); - - final boolean useLocalhost = true; - private Set seedNodes; - private int sleepTime; - private KeyRing keyRing1, keyRing2, keyRing3; - private EncryptionService encryptionService1, encryptionService2, encryptionService3; - private P2PService p2PService1, p2PService2, p2PService3; - private SeedNode seedNode1, seedNode2, seedNode3; - private File dir1, dir2, dir3; - - @Before - public void setup() throws InterruptedException, CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException, CryptoException { - Security.addProvider(new BouncyCastleProvider()); - dir1 = File.createTempFile("temp_tests1", ""); - dir1.delete(); - dir1.mkdir(); - dir2 = File.createTempFile("temp_tests2", ""); - dir2.delete(); - dir2.mkdir(); - dir3 = File.createTempFile("temp_tests3", ""); - dir3.delete(); - dir3.mkdir(); - - LocalhostNetworkNode.setSimulateTorDelayTorNode(10); - LocalhostNetworkNode.setSimulateTorDelayHiddenService(100); - PeerManager.setMaxConnections(8); - - keyRing1 = new KeyRing(new KeyStorage(dir1)); - keyRing2 = new KeyRing(new KeyStorage(dir2)); - keyRing3 = new KeyRing(new KeyStorage(dir3)); - encryptionService1 = new EncryptionService(keyRing1); - encryptionService2 = new EncryptionService(keyRing2); - encryptionService3 = new EncryptionService(keyRing3); - - seedNodes = new HashSet<>(); - if (useLocalhost) { - seedNodes.add(new NodeAddress("localhost:8001")); - seedNodes.add(new NodeAddress("localhost:8002")); - seedNodes.add(new NodeAddress("localhost:8003")); - sleepTime = 100; - - } else { - seedNodes.add(new NodeAddress("3omjuxn7z73pxoee.onion:8001")); - seedNodes.add(new NodeAddress("j24fxqyghjetgpdx.onion:8002")); - seedNodes.add(new NodeAddress("45367tl6unwec6kw.onion:8003")); - sleepTime = 1000; - } - - seedNode1 = TestUtils.getAndStartSeedNode(8001, useLocalhost, seedNodes); - p2PService1 = seedNode1.getSeedNodeP2PService(); - p2PService2 = TestUtils.getAndAuthenticateP2PService(8002, encryptionService2, keyRing2, useLocalhost, seedNodes); - } - - @After - public void tearDown() throws InterruptedException { - Thread.sleep(sleepTime); - - if (seedNode1 != null) { - CountDownLatch shutDownLatch = new CountDownLatch(1); - seedNode1.shutDown(() -> shutDownLatch.countDown()); - shutDownLatch.await(); - } - if (seedNode2 != null) { - CountDownLatch shutDownLatch = new CountDownLatch(1); - seedNode2.shutDown(() -> shutDownLatch.countDown()); - shutDownLatch.await(); - } - if (seedNode3 != null) { - CountDownLatch shutDownLatch = new CountDownLatch(1); - seedNode3.shutDown(() -> shutDownLatch.countDown()); - shutDownLatch.await(); - } - if (p2PService1 != null) { - CountDownLatch shutDownLatch = new CountDownLatch(1); - p2PService1.shutDown(() -> shutDownLatch.countDown()); - shutDownLatch.await(); - } - if (p2PService2 != null) { - CountDownLatch shutDownLatch = new CountDownLatch(1); - p2PService2.shutDown(() -> shutDownLatch.countDown()); - shutDownLatch.await(); - } - if (p2PService3 != null) { - CountDownLatch shutDownLatch = new CountDownLatch(1); - p2PService3.shutDown(() -> shutDownLatch.countDown()); - shutDownLatch.await(); - } - } - - @Test - public void testAdversaryAttacks() throws InterruptedException, NoSuchAlgorithmException, CertificateException, KeyStoreException, IOException, CryptoException, SignatureException, InvalidKeyException, NoSuchProviderException { - p2PService3 = TestUtils.getAndAuthenticateP2PService(8003, encryptionService3, keyRing3, useLocalhost, seedNodes); - - MockData origData = new MockData("mockData1", keyRing1.getSignatureKeyPair().getPublic()); - - p2PService1.addData(origData); - Assert.assertEquals(1, p2PService1.getDataMap().size()); - Assert.assertEquals(1, p2PService2.getDataMap().size()); - Assert.assertEquals(1, p2PService3.getDataMap().size()); - - - // p2PService3 is adversary - KeyPair msgSignatureKeyPairAdversary = keyRing3.getSignatureKeyPair(); - - // try to remove data -> fails - Assert.assertFalse(p2PService3.removeData(origData)); - Thread.sleep(sleepTime); - Assert.assertEquals(1, p2PService1.getDataMap().size()); - Assert.assertEquals(1, p2PService2.getDataMap().size()); - Assert.assertEquals(1, p2PService3.getDataMap().size()); - - - // try to add manipulated data -> fails - Assert.assertFalse(p2PService3.removeData(new MockData("mockData2", origData.publicKey))); - Thread.sleep(sleepTime); - Assert.assertEquals(1, p2PService1.getDataMap().size()); - Assert.assertEquals(1, p2PService2.getDataMap().size()); - Assert.assertEquals(1, p2PService3.getDataMap().size()); - - // try to manipulate seq nr. -> fails - Set dataSet = p2PService3.getDataMap().values().stream() - .filter(data -> data instanceof ProtectedData) - .map(data -> (ProtectedData) data) - .collect(Collectors.toSet()); - ProtectedData origProtectedData = dataSet.stream().findFirst().get(); - ProtectedData protectedDataManipulated = new ProtectedData(origProtectedData.expirablePayload, origProtectedData.ttl, origProtectedData.ownerPubKey, origProtectedData.sequenceNumber + 1, origProtectedData.signature); - Assert.assertFalse(p2PService3.removeData(protectedDataManipulated.expirablePayload)); - Thread.sleep(sleepTime); - Assert.assertEquals(1, p2PService1.getDataMap().size()); - Assert.assertEquals(1, p2PService2.getDataMap().size()); - Assert.assertEquals(1, p2PService3.getDataMap().size()); - - // try to manipulate seq nr. + pubKey -> fails - protectedDataManipulated = new ProtectedData(origProtectedData.expirablePayload, origProtectedData.ttl, msgSignatureKeyPairAdversary.getPublic(), origProtectedData.sequenceNumber + 1, origProtectedData.signature); - Assert.assertFalse(p2PService3.removeData(protectedDataManipulated.expirablePayload)); - Thread.sleep(sleepTime); - Assert.assertEquals(1, p2PService1.getDataMap().size()); - Assert.assertEquals(1, p2PService2.getDataMap().size()); - Assert.assertEquals(1, p2PService3.getDataMap().size()); - - // try to manipulate seq nr. + pubKey + sig -> fails - int sequenceNumberManipulated = origProtectedData.sequenceNumber + 1; - byte[] hashOfDataAndSeqNr = Hash.getHash(new P2PDataStorage.DataAndSeqNrPair(origProtectedData.expirablePayload, sequenceNumberManipulated)); - byte[] signature = Sig.sign(msgSignatureKeyPairAdversary.getPrivate(), hashOfDataAndSeqNr); - protectedDataManipulated = new ProtectedData(origProtectedData.expirablePayload, origProtectedData.ttl, msgSignatureKeyPairAdversary.getPublic(), sequenceNumberManipulated, signature); - Assert.assertFalse(p2PService3.removeData(protectedDataManipulated.expirablePayload)); - Thread.sleep(sleepTime); - Assert.assertEquals(1, p2PService1.getDataMap().size()); - Assert.assertEquals(1, p2PService2.getDataMap().size()); - Assert.assertEquals(1, p2PService3.getDataMap().size()); - - - // data owner removes -> ok - Assert.assertTrue(p2PService1.removeData(origData)); - Thread.sleep(sleepTime); - Assert.assertEquals(0, p2PService1.getDataMap().size()); - Assert.assertEquals(0, p2PService2.getDataMap().size()); - Assert.assertEquals(0, p2PService3.getDataMap().size()); - - // adversary manage to change data before it is broadcasted to others - // data owner is connected only to adversary -> he change data at onMessage and broadcast manipulated data - // first he tries to use the orig. pubKey in the data -> fails as pub keys not matching - MockData manipulatedData = new MockData("mockData1_manipulated", origData.publicKey); - sequenceNumberManipulated = 0; - hashOfDataAndSeqNr = Hash.getHash(new P2PDataStorage.DataAndSeqNrPair(manipulatedData, sequenceNumberManipulated)); - signature = Sig.sign(msgSignatureKeyPairAdversary.getPrivate(), hashOfDataAndSeqNr); - protectedDataManipulated = new ProtectedData(origProtectedData.expirablePayload, origProtectedData.ttl, msgSignatureKeyPairAdversary.getPublic(), sequenceNumberManipulated, signature); - Assert.assertFalse(p2PService3.addData(protectedDataManipulated.expirablePayload)); - Thread.sleep(sleepTime); - Assert.assertEquals(0, p2PService1.getDataMap().size()); - Assert.assertEquals(0, p2PService2.getDataMap().size()); - Assert.assertEquals(0, p2PService3.getDataMap().size()); - - // then he tries to use his pubKey but orig data payload -> fails as pub keys nto matching - manipulatedData = new MockData("mockData1_manipulated", msgSignatureKeyPairAdversary.getPublic()); - sequenceNumberManipulated = 0; - hashOfDataAndSeqNr = Hash.getHash(new P2PDataStorage.DataAndSeqNrPair(manipulatedData, sequenceNumberManipulated)); - signature = Sig.sign(msgSignatureKeyPairAdversary.getPrivate(), hashOfDataAndSeqNr); - protectedDataManipulated = new ProtectedData(origProtectedData.expirablePayload, origProtectedData.ttl, msgSignatureKeyPairAdversary.getPublic(), sequenceNumberManipulated, signature); - Assert.assertFalse(p2PService3.addData(protectedDataManipulated.expirablePayload)); - Thread.sleep(sleepTime); - Assert.assertEquals(0, p2PService1.getDataMap().size()); - Assert.assertEquals(0, p2PService2.getDataMap().size()); - Assert.assertEquals(0, p2PService3.getDataMap().size()); - - // then he tries to use his pubKey -> now he succeeds, but its same as adding a completely new msg and - // payload data has adversary's pubKey so he could hijack the owners data - manipulatedData = new MockData("mockData1_manipulated", msgSignatureKeyPairAdversary.getPublic()); - sequenceNumberManipulated = 0; - hashOfDataAndSeqNr = Hash.getHash(new P2PDataStorage.DataAndSeqNrPair(manipulatedData, sequenceNumberManipulated)); - signature = Sig.sign(msgSignatureKeyPairAdversary.getPrivate(), hashOfDataAndSeqNr); - protectedDataManipulated = new ProtectedData(manipulatedData, origProtectedData.ttl, msgSignatureKeyPairAdversary.getPublic(), sequenceNumberManipulated, signature); - Assert.assertTrue(p2PService3.addData(protectedDataManipulated.expirablePayload)); - Thread.sleep(sleepTime); - Assert.assertEquals(1, p2PService1.getDataMap().size()); - Assert.assertEquals(1, p2PService2.getDataMap().size()); - Assert.assertEquals(1, p2PService3.getDataMap().size()); - - // let clean up. he can remove his own data - Assert.assertTrue(p2PService3.removeData(manipulatedData)); - Thread.sleep(sleepTime); - Assert.assertEquals(0, p2PService1.getDataMap().size()); - Assert.assertEquals(0, p2PService2.getDataMap().size()); - Assert.assertEquals(0, p2PService3.getDataMap().size()); - - - // finally he tries both previous attempts with same data - > same as before - manipulatedData = new MockData("mockData1", origData.publicKey); - sequenceNumberManipulated = 0; - hashOfDataAndSeqNr = Hash.getHash(new P2PDataStorage.DataAndSeqNrPair(manipulatedData, sequenceNumberManipulated)); - signature = Sig.sign(msgSignatureKeyPairAdversary.getPrivate(), hashOfDataAndSeqNr); - protectedDataManipulated = new ProtectedData(origProtectedData.expirablePayload, origProtectedData.ttl, msgSignatureKeyPairAdversary.getPublic(), sequenceNumberManipulated, signature); - Assert.assertFalse(p2PService3.addData(protectedDataManipulated.expirablePayload)); - Thread.sleep(sleepTime); - Assert.assertEquals(0, p2PService1.getDataMap().size()); - Assert.assertEquals(0, p2PService2.getDataMap().size()); - Assert.assertEquals(0, p2PService3.getDataMap().size()); - - manipulatedData = new MockData("mockData1", msgSignatureKeyPairAdversary.getPublic()); - sequenceNumberManipulated = 0; - hashOfDataAndSeqNr = Hash.getHash(new P2PDataStorage.DataAndSeqNrPair(manipulatedData, sequenceNumberManipulated)); - signature = Sig.sign(msgSignatureKeyPairAdversary.getPrivate(), hashOfDataAndSeqNr); - protectedDataManipulated = new ProtectedData(manipulatedData, origProtectedData.ttl, msgSignatureKeyPairAdversary.getPublic(), sequenceNumberManipulated, signature); - Assert.assertTrue(p2PService3.addData(protectedDataManipulated.expirablePayload)); - Thread.sleep(sleepTime); - Assert.assertEquals(1, p2PService1.getDataMap().size()); - Assert.assertEquals(1, p2PService2.getDataMap().size()); - Assert.assertEquals(1, p2PService3.getDataMap().size()); - - // lets reset map - Assert.assertTrue(p2PService3.removeData(protectedDataManipulated.expirablePayload)); - Thread.sleep(sleepTime); - Assert.assertEquals(0, p2PService1.getDataMap().size()); - Assert.assertEquals(0, p2PService2.getDataMap().size()); - Assert.assertEquals(0, p2PService3.getDataMap().size()); - - // owner can add any time his data - Assert.assertTrue(p2PService1.addData(origData)); - Thread.sleep(sleepTime); - Assert.assertEquals(1, p2PService1.getDataMap().size()); - Assert.assertEquals(1, p2PService2.getDataMap().size()); - Assert.assertEquals(1, p2PService3.getDataMap().size()); - } - - //@Test - public void testSendMailboxMessageToOnlinePeer() throws InterruptedException, CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException, CryptoException { - LocalhostNetworkNode.setSimulateTorDelayTorNode(0); - LocalhostNetworkNode.setSimulateTorDelayHiddenService(0); - - // send to online peer - CountDownLatch latch2 = new CountDownLatch(2); - MockMailboxPayload mockMessage = new MockMailboxPayload("MockMailboxMessage", p2PService2.getAddress()); - p2PService2.getNetworkNode().addMessageListener((message, connection) -> { - log.trace("message " + message); - if (message instanceof PrefixedSealedAndSignedMessage) { - try { - PrefixedSealedAndSignedMessage prefixedSealedAndSignedMessage = (PrefixedSealedAndSignedMessage) message; - DecryptedMsgWithPubKey decryptedMsgWithPubKey = encryptionService2.decryptAndVerify(prefixedSealedAndSignedMessage.sealedAndSigned); - Assert.assertEquals(mockMessage, decryptedMsgWithPubKey.message); - Assert.assertEquals(p2PService2.getAddress(), ((MailboxMessage) decryptedMsgWithPubKey.message).getSenderNodeAddress()); - latch2.countDown(); - } catch (CryptoException e) { - e.printStackTrace(); - } - } - }); - - p2PService1.sendEncryptedMailboxMessage( - p2PService2.getAddress(), - keyRing2.getPubKeyRing(), - mockMessage, - new SendMailboxMessageListener() { - @Override - public void onArrived() { - log.trace("Message arrived at peer."); - latch2.countDown(); - } - - @Override - public void onStoredInMailbox() { - log.trace("Message stored in mailbox."); - } - - @Override - public void onFault(String errorMessage) { - log.error("onFault"); - } - } - ); - latch2.await(); - } - - //@Test - public void testSendMailboxMessageToOfflinePeer() throws InterruptedException, CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException, CryptoException { - LocalhostNetworkNode.setSimulateTorDelayTorNode(0); - LocalhostNetworkNode.setSimulateTorDelayHiddenService(0); - - // send msg to offline peer - MockMailboxPayload mockMessage = new MockMailboxPayload( - "MockMailboxMessage", - p2PService2.getAddress() - ); - CountDownLatch latch2 = new CountDownLatch(1); - p2PService2.sendEncryptedMailboxMessage( - new NodeAddress("localhost:8003"), - keyRing3.getPubKeyRing(), - mockMessage, - new SendMailboxMessageListener() { - @Override - public void onArrived() { - log.trace("Message arrived at peer."); - } - - @Override - public void onStoredInMailbox() { - log.trace("Message stored in mailbox."); - latch2.countDown(); - } - - @Override - public void onFault(String errorMessage) { - log.error("onFault"); - } - } - ); - latch2.await(); - Thread.sleep(2000); - - - // start node 3 - p2PService3 = TestUtils.getAndAuthenticateP2PService(8003, encryptionService3, keyRing3, useLocalhost, seedNodes); - Thread.sleep(sleepTime); - CountDownLatch latch3 = new CountDownLatch(1); - p2PService3.addDecryptedMailboxListener((decryptedMessageWithPubKey, senderAddress) -> { - log.debug("decryptedMessageWithPubKey " + decryptedMessageWithPubKey.toString()); - Assert.assertEquals(mockMessage, decryptedMessageWithPubKey.message); - Assert.assertEquals(p2PService2.getAddress(), ((MailboxMessage) decryptedMessageWithPubKey.message).getSenderNodeAddress()); - latch3.countDown(); - }); - latch3.await(); - } -} diff --git a/network/src/test/java/io/bitsquare/p2p/mocks/MockMailboxPayload.java b/network/src/test/java/io/bitsquare/p2p/mocks/MockMailboxPayload.java index df3f9605f5..fc47a32307 100644 --- a/network/src/test/java/io/bitsquare/p2p/mocks/MockMailboxPayload.java +++ b/network/src/test/java/io/bitsquare/p2p/mocks/MockMailboxPayload.java @@ -3,17 +3,21 @@ package io.bitsquare.p2p.mocks; import io.bitsquare.app.Version; import io.bitsquare.p2p.NodeAddress; import io.bitsquare.p2p.messaging.MailboxMessage; -import io.bitsquare.p2p.storage.data.ExpirablePayload; +import io.bitsquare.p2p.storage.payload.ExpirablePayload; + +import java.util.UUID; public final class MockMailboxPayload implements MailboxMessage, ExpirablePayload { private final int messageVersion = Version.getP2PMessageVersion(); public final String msg; public final NodeAddress senderNodeAddress; public long ttl; + private String uid; public MockMailboxPayload(String msg, NodeAddress senderNodeAddress) { this.msg = msg; this.senderNodeAddress = senderNodeAddress; + uid = UUID.randomUUID().toString(); } @Override @@ -21,6 +25,11 @@ public final class MockMailboxPayload implements MailboxMessage, ExpirablePayloa return messageVersion; } + @Override + public String getUID() { + return uid; + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/network/src/test/java/io/bitsquare/p2p/mocks/MockPayload.java b/network/src/test/java/io/bitsquare/p2p/mocks/MockPayload.java index f4665d3430..178cb31cba 100644 --- a/network/src/test/java/io/bitsquare/p2p/mocks/MockPayload.java +++ b/network/src/test/java/io/bitsquare/p2p/mocks/MockPayload.java @@ -2,7 +2,7 @@ package io.bitsquare.p2p.mocks; import io.bitsquare.app.Version; import io.bitsquare.p2p.Message; -import io.bitsquare.p2p.storage.data.ExpirablePayload; +import io.bitsquare.p2p.storage.payload.ExpirablePayload; public final class MockPayload implements Message, ExpirablePayload { public final String msg; diff --git a/network/src/test/java/io/bitsquare/p2p/storage/ProtectedDataStorageTest.java b/network/src/test/java/io/bitsquare/p2p/storage/ProtectedDataStorageTest.java index 1415e2497c..b886178fe6 100644 --- a/network/src/test/java/io/bitsquare/p2p/storage/ProtectedDataStorageTest.java +++ b/network/src/test/java/io/bitsquare/p2p/storage/ProtectedDataStorageTest.java @@ -9,9 +9,9 @@ import io.bitsquare.p2p.P2PService; import io.bitsquare.p2p.TestUtils; import io.bitsquare.p2p.network.NetworkNode; import io.bitsquare.p2p.peers.PeerManager; -import io.bitsquare.p2p.storage.data.ProtectedData; import io.bitsquare.p2p.storage.messages.RefreshTTLMessage; import io.bitsquare.p2p.storage.mocks.MockData; +import io.bitsquare.p2p.storage.storageentry.ProtectedStorageEntry; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.junit.*; import org.slf4j.Logger; @@ -98,14 +98,14 @@ public class ProtectedDataStorageTest { //@Test public void testAddAndRemove() throws InterruptedException, NoSuchAlgorithmException, CertificateException, KeyStoreException, IOException, CryptoException, SignatureException, InvalidKeyException, NoSuchProviderException { - ProtectedData data = dataStorage1.getProtectedData(mockData, storageSignatureKeyPair1); + ProtectedStorageEntry data = dataStorage1.getProtectedData(mockData, storageSignatureKeyPair1); Assert.assertTrue(dataStorage1.add(data, null)); Assert.assertEquals(1, dataStorage1.getMap().size()); int newSequenceNumber = data.sequenceNumber + 1; - byte[] hashOfDataAndSeqNr = Hash.getHash(new P2PDataStorage.DataAndSeqNrPair(data.expirablePayload, newSequenceNumber)); + byte[] hashOfDataAndSeqNr = Hash.getHash(new P2PDataStorage.DataAndSeqNrPair(data.getStoragePayload(), newSequenceNumber)); byte[] signature = Sig.sign(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr); - ProtectedData dataToRemove = new ProtectedData(data.expirablePayload, data.ttl, data.ownerPubKey, newSequenceNumber, signature); + ProtectedStorageEntry dataToRemove = new ProtectedStorageEntry(data.getStoragePayload(), data.ownerPubKey, newSequenceNumber, signature); Assert.assertTrue(dataStorage1.remove(dataToRemove, null)); Assert.assertEquals(0, dataStorage1.getMap().size()); } @@ -113,9 +113,8 @@ public class ProtectedDataStorageTest { // @Test public void testTTL() throws InterruptedException, NoSuchAlgorithmException, CertificateException, KeyStoreException, IOException, CryptoException, SignatureException, InvalidKeyException, NoSuchProviderException { mockData.ttl = (int) (P2PDataStorage.CHECK_TTL_INTERVAL_SEC * 1.5); - ProtectedData data = dataStorage1.getProtectedData(mockData, storageSignatureKeyPair1); - log.debug("data.date " + data.date); - log.debug("data.date " + data.date.getTime()); + ProtectedStorageEntry data = dataStorage1.getProtectedData(mockData, storageSignatureKeyPair1); + log.debug("data.date " + data.timeStamp); Assert.assertTrue(dataStorage1.add(data, null)); log.debug("test 1"); Assert.assertEquals(1, dataStorage1.getMap().size()); @@ -163,7 +162,7 @@ public class ProtectedDataStorageTest { @Test public void testRefreshTTL() throws InterruptedException, NoSuchAlgorithmException, CertificateException, KeyStoreException, IOException, CryptoException, SignatureException, InvalidKeyException, NoSuchProviderException { mockData.ttl = (int) (P2PDataStorage.CHECK_TTL_INTERVAL_SEC * 1.5); - ProtectedData data = dataStorage1.getProtectedData(mockData, storageSignatureKeyPair1); + ProtectedStorageEntry data = dataStorage1.getProtectedData(mockData, storageSignatureKeyPair1); Assert.assertTrue(dataStorage1.add(data, null)); Assert.assertEquals(1, dataStorage1.getMap().size()); Thread.sleep(P2PDataStorage.CHECK_TTL_INTERVAL_SEC); diff --git a/network/src/test/java/io/bitsquare/p2p/storage/mocks/MockData.java b/network/src/test/java/io/bitsquare/p2p/storage/mocks/MockData.java index cc5334929e..da823f9ce7 100644 --- a/network/src/test/java/io/bitsquare/p2p/storage/mocks/MockData.java +++ b/network/src/test/java/io/bitsquare/p2p/storage/mocks/MockData.java @@ -1,6 +1,6 @@ package io.bitsquare.p2p.storage.mocks; -import io.bitsquare.p2p.storage.data.StoragePayload; +import io.bitsquare.p2p.storage.payload.StoragePayload; import java.security.PublicKey;