mirror of
https://github.com/haveno-dex/haveno.git
synced 2025-04-21 08:06:33 -04:00
Add mailbox service and message encryption
This commit is contained in:
parent
9dcce78d39
commit
b5e47716d6
@ -33,5 +33,6 @@ public class CryptoModule extends BitsquareModule {
|
||||
protected void configure() {
|
||||
bind(SignatureService.class).in(Singleton.class);
|
||||
bind(HashService.class).in(Singleton.class);
|
||||
bind(EncryptionService.class).in(Singleton.class);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* This file is part of Bitsquare.
|
||||
*
|
||||
* Bitsquare is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.crypto;
|
||||
|
||||
import io.bitsquare.util.Utilities;
|
||||
|
||||
import java.security.KeyPair;
|
||||
import java.security.KeyPairGenerator;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
|
||||
public class EncryptionService {
|
||||
private static final Logger log = LoggerFactory.getLogger(EncryptionService.class);
|
||||
|
||||
@Inject
|
||||
public EncryptionService() {
|
||||
}
|
||||
|
||||
public KeyPair getKeyPair() {
|
||||
KeyPair keyPair = null;
|
||||
try {
|
||||
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
|
||||
keyPairGenerator.initialize(1024);
|
||||
keyPair = keyPairGenerator.genKeyPair();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
log.error("Exception at init " + e.getMessage());
|
||||
}
|
||||
return keyPair;
|
||||
}
|
||||
|
||||
public byte[] encryptObject(PublicKey publicKey, Object object) {
|
||||
return encrypt(publicKey, Utilities.objectToBytArray(object));
|
||||
}
|
||||
|
||||
public Object decryptObject(PrivateKey privateKey, byte[] cipherMessage) {
|
||||
return Utilities.byteArrayToObject(decrypt(privateKey, cipherMessage));
|
||||
}
|
||||
|
||||
public byte[] encrypt(PublicKey publicKey, byte[] data) {
|
||||
byte[] cipherData = null;
|
||||
try {
|
||||
Cipher cipher = Cipher.getInstance("RSA");
|
||||
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
|
||||
cipherData = cipher.doFinal(data);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
log.error("Exception at encrypt " + e.getMessage());
|
||||
}
|
||||
return cipherData;
|
||||
}
|
||||
|
||||
public byte[] decrypt(PrivateKey privateKey, byte[] cipherText) {
|
||||
byte[] data = null;
|
||||
try {
|
||||
Cipher cipher = Cipher.getInstance("RSA");
|
||||
cipher.init(Cipher.DECRYPT_MODE, privateKey);
|
||||
data = cipher.doFinal(cipherText);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
log.error("Exception at decrypt " + e.getMessage());
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
}
|
@ -161,7 +161,7 @@ class MainViewModel implements ViewModel {
|
||||
// Set executor for all P2PServices
|
||||
BaseP2PService.setUserThread(Platform::runLater);
|
||||
|
||||
Observable<BootstrapState> bootstrapStateAsObservable = clientNode.bootstrap(user.getMessageKeyPair());
|
||||
Observable<BootstrapState> bootstrapStateAsObservable = clientNode.bootstrap(user.getP2pSigKeyPair());
|
||||
bootstrapStateAsObservable.publish();
|
||||
bootstrapStateAsObservable.subscribe(
|
||||
state -> Platform.runLater(() -> setBootstrapState(state)),
|
||||
@ -354,7 +354,7 @@ class MainViewModel implements ViewModel {
|
||||
}
|
||||
|
||||
private void addMockArbitrator() {
|
||||
if (accountSettings.getAcceptedArbitrators().isEmpty() && user.getMessageKeyPair() != null) {
|
||||
if (accountSettings.getAcceptedArbitrators().isEmpty() && user.getP2pSigKeyPair() != null) {
|
||||
byte[] pubKey = new ECKey().getPubKey();
|
||||
String messagePubKeyAsHex = DSAKeyUtil.getHexStringFromPublicKey(user.getMessagePubKey());
|
||||
List<Locale> languages = new ArrayList<>();
|
||||
|
@ -122,7 +122,7 @@ class IrcAccountDataModel implements Activatable, DataModel {
|
||||
}
|
||||
|
||||
private void addMockArbitrator() {
|
||||
if (accountSettings.getAcceptedArbitrators().isEmpty() && user.getMessageKeyPair() != null) {
|
||||
if (accountSettings.getAcceptedArbitrators().isEmpty() && user.getP2pSigKeyPair() != null) {
|
||||
byte[] pubKey = new ECKey().getPubKey();
|
||||
String messagePubKeyAsHex = DSAKeyUtil.getHexStringFromPublicKey(user.getMessagePubKey());
|
||||
List<Locale> languages = new ArrayList<>();
|
||||
|
@ -152,7 +152,7 @@ class RestrictionsDataModel implements Activatable, DataModel {
|
||||
|
||||
// TODO Remove mock later
|
||||
private void addMockArbitrator() {
|
||||
if (accountSettings.getAcceptedArbitrators().isEmpty() && user.getMessageKeyPair() != null) {
|
||||
if (accountSettings.getAcceptedArbitrators().isEmpty() && user.getP2pSigKeyPair() != null) {
|
||||
byte[] pubKey = new ECKey().getPubKey();
|
||||
String messagePubKeyAsHex = DSAKeyUtil.getHexStringFromPublicKey(user.getMessagePubKey());
|
||||
List<Locale> languages = new ArrayList<>();
|
||||
|
@ -50,8 +50,8 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class TomP2POfferBookService extends TomP2PDHTService implements OfferBookService {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(TomP2POfferBookService.class);
|
||||
private static final int TTL = 30 * 24 * 60 * 60; // the offer is default 30 days valid
|
||||
|
||||
private final List<Listener> offerRepositoryListeners = new ArrayList<>();
|
||||
private final LongProperty invalidationTimestamp = new SimpleLongProperty(0);
|
||||
@ -67,10 +67,7 @@ public class TomP2POfferBookService extends TomP2PDHTService implements OfferBoo
|
||||
Number160 locationKey = Number160.createHash(offer.getCurrency().getCurrencyCode());
|
||||
try {
|
||||
final Data offerData = new Data(offer);
|
||||
|
||||
// the offer is default 30 days valid
|
||||
int defaultOfferTTL = 30 * 24 * 60 * 60;
|
||||
offerData.ttlSeconds(defaultOfferTTL);
|
||||
offerData.ttlSeconds(TTL);
|
||||
log.trace("Add offer to DHT requested. Added data: [locationKey: " + locationKey +
|
||||
", hash: " + offerData.hash().toString() + "]");
|
||||
FuturePut futurePut = addProtectedDataToMap(locationKey, offerData);
|
||||
|
41
core/src/main/java/io/bitsquare/p2p/MailboxMessage.java
Normal file
41
core/src/main/java/io/bitsquare/p2p/MailboxMessage.java
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* This file is part of Bitsquare.
|
||||
*
|
||||
* Bitsquare is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.p2p;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/*
|
||||
Stores a message in encrypted form, so it never leaves the client in plain text.
|
||||
*/
|
||||
public class MailboxMessage implements Message, Serializable {
|
||||
private static final long serialVersionUID = -3111178895546299769L;
|
||||
private static final Logger log = LoggerFactory.getLogger(MailboxMessage.class);
|
||||
|
||||
private byte[] cipherMessage;
|
||||
|
||||
public MailboxMessage(byte[] cipherMessage) {
|
||||
this.cipherMessage = cipherMessage;
|
||||
}
|
||||
|
||||
public byte[] getCipherMessage() {
|
||||
return cipherMessage;
|
||||
}
|
||||
}
|
32
core/src/main/java/io/bitsquare/p2p/MailboxService.java
Normal file
32
core/src/main/java/io/bitsquare/p2p/MailboxService.java
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* This file is part of Bitsquare.
|
||||
*
|
||||
* Bitsquare is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.p2p;
|
||||
|
||||
import io.bitsquare.common.handlers.FaultHandler;
|
||||
import io.bitsquare.common.handlers.ResultHandler;
|
||||
import io.bitsquare.p2p.tomp2p.TomP2PMailboxService;
|
||||
|
||||
import java.security.PublicKey;
|
||||
|
||||
public interface MailboxService {
|
||||
void addMessage(PublicKey publicKey, MailboxMessage message, ResultHandler resultHandler, FaultHandler faultHandler);
|
||||
|
||||
void removeMessage(PublicKey publicKey, MailboxMessage message, ResultHandler resultHandler, FaultHandler faultHandler);
|
||||
|
||||
void getMessages(PublicKey publicKey, TomP2PMailboxService.MailboxMessagesResultHandler resultHandler);
|
||||
}
|
@ -66,7 +66,7 @@ public class TomP2PAddressService extends TomP2PDHTService implements AddressSer
|
||||
public TomP2PAddressService(TomP2PNode tomP2PNode, User user) {
|
||||
super(tomP2PNode, user);
|
||||
|
||||
locationKey = Utils.makeSHAHash(user.getMessageKeyPair().getPublic().getEncoded());
|
||||
locationKey = Utils.makeSHAHash(user.getP2pSigKeyPair().getPublic().getEncoded());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -49,7 +49,7 @@ public class TomP2PDHTService extends TomP2PService implements DHTService {
|
||||
@Inject
|
||||
public TomP2PDHTService(TomP2PNode tomP2PNode, User user) {
|
||||
super(tomP2PNode);
|
||||
keyPair = user.getMessageKeyPair();
|
||||
keyPair = user.getP2pSigKeyPair();
|
||||
pubKeyHashForMyDomain = Utils.makeSHAHash(keyPair.getPublic().getEncoded());
|
||||
}
|
||||
|
||||
|
@ -19,12 +19,9 @@ package io.bitsquare.p2p.tomp2p;
|
||||
|
||||
import io.bitsquare.common.handlers.FaultHandler;
|
||||
import io.bitsquare.common.handlers.ResultHandler;
|
||||
import io.bitsquare.offer.Offer;
|
||||
import io.bitsquare.offer.OfferBookService;
|
||||
import io.bitsquare.p2p.AddressService;
|
||||
import io.bitsquare.p2p.Message;
|
||||
import io.bitsquare.p2p.Peer;
|
||||
import io.bitsquare.p2p.listener.GetPeerAddressListener;
|
||||
import io.bitsquare.p2p.MailboxMessage;
|
||||
import io.bitsquare.p2p.MailboxService;
|
||||
import io.bitsquare.user.User;
|
||||
|
||||
import java.io.IOException;
|
||||
@ -46,21 +43,16 @@ import net.tomp2p.futures.BaseFutureListener;
|
||||
import net.tomp2p.peers.Number160;
|
||||
import net.tomp2p.peers.Number640;
|
||||
import net.tomp2p.storage.Data;
|
||||
import net.tomp2p.utils.Utils;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class TomP2PMailboxService extends TomP2PDHTService implements AddressService {
|
||||
public class TomP2PMailboxService extends TomP2PDHTService implements MailboxService {
|
||||
private static final Logger log = LoggerFactory.getLogger(TomP2PMailboxService.class);
|
||||
|
||||
private static final int TTL = 15 * 24 * 60 * 60; // the message is default 15 days valid, as a max trade period might be about 2 weeks.
|
||||
|
||||
private final List<OfferBookService.Listener> offerRepositoryListeners = new ArrayList<>();
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Inject
|
||||
public TomP2PMailboxService(TomP2PNode tomP2PNode, User user) {
|
||||
super(tomP2PNode, user);
|
||||
@ -76,69 +68,45 @@ public class TomP2PMailboxService extends TomP2PDHTService implements AddressSer
|
||||
super.shutDown();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Find peer address by publicKey
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// public void findPeerAddress(PublicKey publicKey, GetPeerAddressListener listener) {
|
||||
// final Number160 locationKey = Utils.makeSHAHash(publicKey.getEncoded());
|
||||
|
||||
public void saveMessage(PublicKey publicKey, Message message, ResultHandler resultHandler, FaultHandler faultHandler) {
|
||||
final Number160 locationKey = Utils.makeSHAHash(publicKey.getEncoded());
|
||||
|
||||
// Number160 locationKey = Number160.createHash(offer.getCurrency().getCurrencyCode());
|
||||
@Override
|
||||
public void addMessage(PublicKey publicKey, MailboxMessage message, ResultHandler resultHandler, FaultHandler faultHandler) {
|
||||
try {
|
||||
final Data offerData = new Data(message);
|
||||
final Data data = new Data(message);
|
||||
data.ttlSeconds(TTL);
|
||||
log.trace("Add message to DHT requested. Added data: [locationKey: " + getLocationKey(publicKey) +
|
||||
", hash: " + data.hash().toString() + "]");
|
||||
|
||||
// the offer is default 30 days valid
|
||||
int defaultOfferTTL = 30 * 24 * 60 * 60;
|
||||
offerData.ttlSeconds(defaultOfferTTL);
|
||||
log.trace("Add offer to DHT requested. Added data: [locationKey: " + locationKey +
|
||||
", hash: " + offerData.hash().toString() + "]");
|
||||
FuturePut futurePut = addProtectedDataToMap(locationKey, offerData);
|
||||
FuturePut futurePut = addDataToMapOfProtectedDomain(getLocationKey(publicKey), data, publicKey);
|
||||
futurePut.addListener(new BaseFutureListener<BaseFuture>() {
|
||||
@Override
|
||||
public void operationComplete(BaseFuture future) throws Exception {
|
||||
if (future.isSuccess()) {
|
||||
executor.execute(() -> {
|
||||
resultHandler.handleResult();
|
||||
offerRepositoryListeners.stream().forEach(listener -> {
|
||||
try {
|
||||
Object offerDataObject = offerData.object();
|
||||
if (offerDataObject instanceof Offer) {
|
||||
log.info("Added offer to DHT with ID: " + offerDataObject);
|
||||
listener.onOfferAdded((Offer) offerDataObject);
|
||||
}
|
||||
} catch (ClassNotFoundException | IOException e) {
|
||||
e.printStackTrace();
|
||||
log.error("Add offer to DHT failed: " + e.getMessage());
|
||||
}
|
||||
});
|
||||
|
||||
log.trace("Add offer to DHT was successful. Added data: [locationKey: " + locationKey +
|
||||
", value: " + offerData + "]");
|
||||
log.trace("Add message to mailbox was successful. Added data: [locationKey: " + getLocationKey(publicKey) +
|
||||
", value: " + data + "]");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(Throwable ex) throws Exception {
|
||||
executor.execute(() -> faultHandler.handleFault("Failed to add offer to DHT", ex));
|
||||
executor.execute(() -> faultHandler.handleFault("Add message to mailbox failed.", ex));
|
||||
}
|
||||
});
|
||||
} catch (IOException ex) {
|
||||
executor.execute(() -> faultHandler.handleFault("Failed to add offer to DHT", ex));
|
||||
executor.execute(() -> faultHandler.handleFault("Add message to mailbox failed.", ex));
|
||||
}
|
||||
}
|
||||
|
||||
public void removeOffer(Offer offer, ResultHandler resultHandler, FaultHandler faultHandler) {
|
||||
Number160 locationKey = Number160.createHash(offer.getCurrency().getCurrencyCode());
|
||||
@Override
|
||||
public void removeMessage(PublicKey publicKey, MailboxMessage message, ResultHandler resultHandler, FaultHandler faultHandler) {
|
||||
try {
|
||||
final Data offerData = new Data(offer);
|
||||
log.trace("Remove offer from DHT requested. Removed data: [locationKey: " + locationKey +
|
||||
", hash: " + offerData.hash().toString() + "]");
|
||||
FutureRemove futureRemove = removeProtectedDataFromMap(locationKey, offerData);
|
||||
final Data data = new Data(message);
|
||||
log.trace("Remove message from DHT requested. Removed data: [locationKey: " + getLocationKey(publicKey) +
|
||||
", hash: " + data.hash().toString() + "]");
|
||||
FutureRemove futureRemove = removeDataFromMapOfMyProtectedDomain(getLocationKey(publicKey), data);
|
||||
futureRemove.addListener(new BaseFutureListener<BaseFuture>() {
|
||||
@Override
|
||||
public void operationComplete(BaseFuture future) throws Exception {
|
||||
@ -148,109 +116,73 @@ public class TomP2PMailboxService extends TomP2PDHTService implements AddressSer
|
||||
log.trace("isRemoved? " + futureRemove.isRemoved());
|
||||
executor.execute(() -> {
|
||||
resultHandler.handleResult();
|
||||
offerRepositoryListeners.stream().forEach(listener -> {
|
||||
try {
|
||||
Object offerDataObject = offerData.object();
|
||||
if (offerDataObject instanceof Offer) {
|
||||
log.trace("Remove offer from DHT was successful. Removed data: [key: " +
|
||||
locationKey + ", " +
|
||||
"offer: " + offerDataObject + "]");
|
||||
listener.onOfferRemoved((Offer) offerDataObject);
|
||||
}
|
||||
} catch (ClassNotFoundException | IOException e) {
|
||||
e.printStackTrace();
|
||||
log.error("Remove offer from DHT failed. Error: " + e.getMessage());
|
||||
faultHandler.handleFault("Remove offer from DHT failed. Error: " + e.getMessage(), e);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(Throwable t) throws Exception {
|
||||
log.error("Remove offer from DHT failed. Error: " + t.getMessage());
|
||||
faultHandler.handleFault("Remove offer from DHT failed. Error: " + t.getMessage(), t);
|
||||
log.error("Remove message from DHT failed. Error: " + t.getMessage());
|
||||
faultHandler.handleFault("Remove message from DHT failed. Error: " + t.getMessage(), t);
|
||||
}
|
||||
});
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
log.error("Remove offer from DHT failed. Error: " + e.getMessage());
|
||||
faultHandler.handleFault("Remove offer from DHT failed. Error: " + e.getMessage(), e);
|
||||
log.error("Remove message from DHT failed. Error: " + e.getMessage());
|
||||
faultHandler.handleFault("Remove message from DHT failed. Error: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public void getOffers(String currencyCode) {
|
||||
Number160 locationKey = Number160.createHash(currencyCode);
|
||||
log.trace("Get offers from DHT requested for locationKey: " + locationKey);
|
||||
FutureGet futureGet = getMap(locationKey);
|
||||
@Override
|
||||
public void getMessages(PublicKey publicKey, MailboxMessagesResultHandler resultHandler) {
|
||||
log.trace("Get messages from DHT requested for locationKey: " + getLocationKey(publicKey));
|
||||
FutureGet futureGet = getDataFromMapOfMyProtectedDomain(getLocationKey(publicKey));
|
||||
futureGet.addListener(new BaseFutureAdapter<BaseFuture>() {
|
||||
@Override
|
||||
public void operationComplete(BaseFuture future) throws Exception {
|
||||
if (future.isSuccess()) {
|
||||
final Map<Number640, Data> dataMap = futureGet.dataMap();
|
||||
final List<Offer> offers = new ArrayList<>();
|
||||
List<MailboxMessage> messages = new ArrayList<>();
|
||||
if (dataMap != null) {
|
||||
for (Data offerData : dataMap.values()) {
|
||||
for (Data messageData : dataMap.values()) {
|
||||
try {
|
||||
Object offerDataObject = offerData.object();
|
||||
if (offerDataObject instanceof Offer) {
|
||||
offers.add((Offer) offerDataObject);
|
||||
Object messageDataObject = messageData.object();
|
||||
if (messageDataObject instanceof MailboxMessage) {
|
||||
messages.add((MailboxMessage) messageDataObject);
|
||||
}
|
||||
} catch (ClassNotFoundException | IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
executor.execute(() -> offerRepositoryListeners.stream().forEach(listener ->
|
||||
listener.onOffersReceived(offers)));
|
||||
executor.execute(() -> resultHandler.handleResult(messages));
|
||||
}
|
||||
|
||||
log.trace("Get offers from DHT was successful. Stored data: [key: " + locationKey
|
||||
log.trace("Get messages from DHT was successful. Stored data: [key: " + getLocationKey(publicKey)
|
||||
+ ", values: " + futureGet.dataMap() + "]");
|
||||
}
|
||||
else {
|
||||
final Map<Number640, Data> dataMap = futureGet.dataMap();
|
||||
if (dataMap == null || dataMap.size() == 0) {
|
||||
log.trace("Get offers from DHT delivered empty dataMap.");
|
||||
executor.execute(() -> offerRepositoryListeners.stream().forEach(listener ->
|
||||
listener.onOffersReceived(new ArrayList<>())));
|
||||
log.trace("Get messages from DHT delivered empty dataMap.");
|
||||
executor.execute(() -> resultHandler.handleResult(new ArrayList<>()));
|
||||
}
|
||||
else {
|
||||
log.error("Get offers from DHT was not successful with reason:" + future.failedReason());
|
||||
log.error("Get messages from DHT was not successful with reason:" + future.failedReason());
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void findPeerAddress(PublicKey publicKey, GetPeerAddressListener listener) {
|
||||
final Number160 locationKey = Utils.makeSHAHash(publicKey.getEncoded());
|
||||
FutureGet futureGet = getDataOfProtectedDomain(locationKey, publicKey);
|
||||
log.trace("findPeerAddress called");
|
||||
futureGet.addListener(new BaseFutureAdapter<BaseFuture>() {
|
||||
@Override
|
||||
public void operationComplete(BaseFuture baseFuture) throws Exception {
|
||||
if (baseFuture.isSuccess() && futureGet.data() != null) {
|
||||
final Peer peer = (Peer) futureGet.data().object();
|
||||
log.trace("Peer found in DHT. Peer = " + peer);
|
||||
executor.execute(() -> listener.onResult(peer));
|
||||
}
|
||||
else {
|
||||
log.error("getPeerAddress failed. failedReason = " + baseFuture.failedReason());
|
||||
executor.execute(listener::onFailed);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Private
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private Number160 getLocationKey(String currencyCode) {
|
||||
return Number160.createHash(currencyCode + "mailbox");
|
||||
private Number160 getLocationKey(PublicKey publicKey) {
|
||||
return Number160.createHash("mailbox" + publicKey.hashCode());
|
||||
}
|
||||
|
||||
}
|
||||
public interface MailboxMessagesResultHandler {
|
||||
void handleResult(List<MailboxMessage> messages);
|
||||
}
|
||||
}
|
@ -20,9 +20,10 @@ package io.bitsquare.p2p.tomp2p;
|
||||
import io.bitsquare.p2p.AddressService;
|
||||
import io.bitsquare.p2p.BootstrapNodes;
|
||||
import io.bitsquare.p2p.ClientNode;
|
||||
import io.bitsquare.p2p.MailboxService;
|
||||
import io.bitsquare.p2p.MessageService;
|
||||
import io.bitsquare.p2p.P2PModule;
|
||||
import io.bitsquare.p2p.Node;
|
||||
import io.bitsquare.p2p.P2PModule;
|
||||
|
||||
import com.google.inject.Injector;
|
||||
import com.google.inject.Singleton;
|
||||
@ -53,7 +54,8 @@ public class TomP2PModule extends P2PModule {
|
||||
|
||||
bind(AddressService.class).to(TomP2PAddressService.class).in(Singleton.class);
|
||||
bind(MessageService.class).to(TomP2PMessageService.class).in(Singleton.class);
|
||||
|
||||
bind(MailboxService.class).to(TomP2PMailboxService.class).in(Singleton.class);
|
||||
|
||||
bind(int.class).annotatedWith(Names.named(Node.PORT_KEY)).toInstance(env.getProperty(Node.PORT_KEY, int.class, Node.DEFAULT_PORT));
|
||||
bind(boolean.class).annotatedWith(Names.named(USE_MANUAL_PORT_FORWARDING_KEY)).toInstance(
|
||||
env.getProperty(USE_MANUAL_PORT_FORWARDING_KEY, boolean.class, false));
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
package io.bitsquare.user;
|
||||
|
||||
import io.bitsquare.crypto.EncryptionService;
|
||||
import io.bitsquare.fiat.FiatAccount;
|
||||
import io.bitsquare.util.DSAKeyUtil;
|
||||
|
||||
@ -30,6 +31,8 @@ import java.util.List;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
import javafx.beans.property.SimpleObjectProperty;
|
||||
import javafx.collections.FXCollections;
|
||||
@ -43,7 +46,8 @@ import javafx.collections.ObservableList;
|
||||
public class User implements Serializable {
|
||||
private static final long serialVersionUID = 7409078808248518638L;
|
||||
|
||||
private KeyPair messageKeyPair;
|
||||
private KeyPair p2pSigKeyPair;
|
||||
private KeyPair p2pEncryptKeyPair;
|
||||
private String accountID;
|
||||
|
||||
// Used for serialisation (ObservableList cannot be serialized) -> serialisation will change anyway so that is
|
||||
@ -53,8 +57,11 @@ public class User implements Serializable {
|
||||
|
||||
private final transient ObservableList<FiatAccount> fiatAccounts = FXCollections.observableArrayList();
|
||||
private final transient ObjectProperty<FiatAccount> currentBankAccount = new SimpleObjectProperty<>();
|
||||
transient private EncryptionService encryptionService;
|
||||
|
||||
public User() {
|
||||
@Inject
|
||||
public User(EncryptionService encryptionService) {
|
||||
this.encryptionService = encryptionService;
|
||||
// Used for serialisation (ObservableList cannot be serialized) -> serialisation will change anyway so that is
|
||||
// only temporary
|
||||
fiatAccounts.addListener((ListChangeListener<FiatAccount>) change -> _fiatAccounts = new ArrayList<>(fiatAccounts));
|
||||
@ -62,6 +69,9 @@ public class User implements Serializable {
|
||||
currentBankAccount.addListener((ov) -> _currentFiatAccount = currentBankAccount.get());
|
||||
}
|
||||
|
||||
// for unit tests
|
||||
public User() {
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Public Methods
|
||||
@ -71,13 +81,14 @@ public class User implements Serializable {
|
||||
if (persistedUser != null) {
|
||||
fiatAccounts.setAll(persistedUser.getSerializedBankAccounts());
|
||||
setCurrentBankAccount(persistedUser.getSerializedCurrentBankAccount());
|
||||
messageKeyPair = persistedUser.getMessageKeyPair();
|
||||
p2pSigKeyPair = persistedUser.getP2pSigKeyPair();
|
||||
p2pEncryptKeyPair = persistedUser.getP2pEncryptKeyPair();
|
||||
accountID = persistedUser.getAccountId();
|
||||
}
|
||||
else {
|
||||
// First time
|
||||
// TODO use separate thread. DSAKeyUtil.getKeyPair() runs in same thread now
|
||||
messageKeyPair = DSAKeyUtil.generateKeyPair();
|
||||
p2pSigKeyPair = DSAKeyUtil.generateKeyPair();
|
||||
p2pEncryptKeyPair = encryptionService.getKeyPair();
|
||||
}
|
||||
}
|
||||
|
||||
@ -160,12 +171,12 @@ public class User implements Serializable {
|
||||
return null;
|
||||
}
|
||||
|
||||
public KeyPair getMessageKeyPair() {
|
||||
return messageKeyPair;
|
||||
public KeyPair getP2pSigKeyPair() {
|
||||
return p2pSigKeyPair;
|
||||
}
|
||||
|
||||
public PublicKey getMessagePubKey() {
|
||||
return messageKeyPair.getPublic();
|
||||
return p2pSigKeyPair.getPublic();
|
||||
}
|
||||
|
||||
public ObjectProperty<FiatAccount> currentBankAccountProperty() {
|
||||
@ -181,4 +192,7 @@ public class User implements Serializable {
|
||||
return _currentFiatAccount;
|
||||
}
|
||||
|
||||
public KeyPair getP2pEncryptKeyPair() {
|
||||
return p2pEncryptKeyPair;
|
||||
}
|
||||
}
|
||||
|
@ -27,7 +27,9 @@ import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInput;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutput;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
|
||||
@ -145,6 +147,59 @@ public class Utilities {
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Object byteArrayToObject(byte[] data) {
|
||||
ByteArrayInputStream bis = new ByteArrayInputStream(data);
|
||||
ObjectInput in = null;
|
||||
Object result = null;
|
||||
try {
|
||||
in = new ObjectInputStream(bis);
|
||||
result = in.readObject();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
try {
|
||||
bis.close();
|
||||
} catch (IOException ex) {
|
||||
// ignore close exception
|
||||
}
|
||||
try {
|
||||
if (in != null) {
|
||||
in.close();
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
// ignore close exception
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static byte[] objectToBytArray(Object object) {
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
ObjectOutput out = null;
|
||||
byte[] result = null;
|
||||
try {
|
||||
out = new ObjectOutputStream(bos);
|
||||
out.writeObject(object);
|
||||
result = bos.toByteArray();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
try {
|
||||
if (out != null) {
|
||||
out.close();
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
// ignore close exception
|
||||
}
|
||||
try {
|
||||
bos.close();
|
||||
} catch (IOException ex) {
|
||||
// ignore close exception
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void printElapsedTime(String msg) {
|
||||
if (!msg.isEmpty()) {
|
||||
msg += " / ";
|
||||
|
@ -98,7 +98,7 @@ public class PlaceOfferProtocolTest {
|
||||
tomP2PNode = new TomP2PNode(bootstrappedPeerBuilder);
|
||||
messageService = new TomP2PMessageService(tomP2PNode);
|
||||
|
||||
Observable<BootstrapState> messageObservable = tomP2PNode.bootstrap(user.getMessageKeyPair());
|
||||
Observable<BootstrapState> messageObservable = tomP2PNode.bootstrap(user.getP2pSigKeyPair());
|
||||
messageObservable.publish();
|
||||
messageObservable.subscribe(
|
||||
state -> log.trace("state changed: " + state),
|
||||
|
Loading…
x
Reference in New Issue
Block a user