Fixed tests & bugs, removed Ack payload type (a GenericPayload is now used)
- SystemTest don't work yet, sending messages seems broken - ProofOfWorkService needs some work, the current solution is a hack (and might be the reason above tests are broken)
This commit is contained in:
parent
ea2cd7bf53
commit
c7594795f0
@ -164,6 +164,7 @@ public class BitmessageContext {
|
||||
if (msg.getFrom() == null || msg.getFrom().getPrivateKey() == null) {
|
||||
throw new IllegalArgumentException("'From' must be an identity, i.e. have a private key.");
|
||||
}
|
||||
msg.setStatus(Plaintext.Status.DRAFT);
|
||||
BitmessageAddress to = msg.getTo();
|
||||
if (to != null) {
|
||||
if (to.getPubkey() == null) {
|
||||
|
@ -175,10 +175,13 @@ public class InternalContext {
|
||||
object.sign(from.getPrivateKey());
|
||||
}
|
||||
if (payload instanceof Msg && recipient.has(Pubkey.Feature.DOES_ACK)) {
|
||||
ObjectMessage ackMessage = ((Msg) payload).getPlaintext().getAckMessage();
|
||||
final ObjectMessage ackMessage = ((Msg) payload).getPlaintext().getAckMessage();
|
||||
cryptography.doProofOfWork(ackMessage, NETWORK_NONCE_TRIALS_PER_BYTE, NETWORK_EXTRA_BYTES, new ProofOfWorkEngine.Callback() {
|
||||
@Override
|
||||
public void onNonceCalculated(byte[] initialHash, byte[] nonce) {
|
||||
// FIXME: the message gets lost if calculation is cancelled
|
||||
// (e.g. by terminating the application)
|
||||
ackMessage.setNonce(nonce);
|
||||
object.encrypt(recipient.getPubkey());
|
||||
proofOfWorkService.doProofOfWork(recipient, object);
|
||||
}
|
||||
|
@ -29,6 +29,8 @@ import ch.dissem.bitmessage.utils.Encode;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
import static ch.dissem.bitmessage.utils.Singleton.security;
|
||||
|
||||
@ -55,7 +57,7 @@ public class ObjectMessage implements MessagePayload {
|
||||
expiresTime = builder.expiresTime;
|
||||
objectType = builder.objectType;
|
||||
version = builder.payload.getVersion();
|
||||
stream = builder.streamNumber;
|
||||
stream = builder.streamNumber > 0 ? builder.streamNumber : builder.payload.getStream();
|
||||
payload = builder.payload;
|
||||
}
|
||||
|
||||
@ -230,4 +232,29 @@ public class ObjectMessage implements MessagePayload {
|
||||
return new ObjectMessage(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
ObjectMessage that = (ObjectMessage) o;
|
||||
|
||||
return expiresTime == that.expiresTime &&
|
||||
objectType == that.objectType &&
|
||||
version == that.version &&
|
||||
stream == that.stream &&
|
||||
Objects.equals(payload, that.payload);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = Arrays.hashCode(nonce);
|
||||
result = 31 * result + (int) (expiresTime ^ (expiresTime >>> 32));
|
||||
result = 31 * result + (int) (objectType ^ (objectType >>> 32));
|
||||
result = 31 * result + (int) (version ^ (version >>> 32));
|
||||
result = 31 * result + (int) (stream ^ (stream >>> 32));
|
||||
result = 31 * result + (payload != null ? payload.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -173,7 +173,7 @@ public class Plaintext implements Streamable {
|
||||
Encode.varInt(message.length, out);
|
||||
out.write(message);
|
||||
if (type == Type.MSG) {
|
||||
if (to.has(Pubkey.Feature.DOES_ACK)) {
|
||||
if (to.has(Pubkey.Feature.DOES_ACK) && getAckMessage() != null) {
|
||||
ByteArrayOutputStream ack = new ByteArrayOutputStream();
|
||||
getAckMessage().write(ack);
|
||||
byte[] data = ack.toByteArray();
|
||||
@ -255,7 +255,7 @@ public class Plaintext implements Streamable {
|
||||
return Objects.equals(encoding, plaintext.encoding) &&
|
||||
Objects.equals(from, plaintext.from) &&
|
||||
Arrays.equals(message, plaintext.message) &&
|
||||
Arrays.equals(ackData, plaintext.ackData) &&
|
||||
Objects.equals(getAckMessage(), plaintext.getAckMessage()) &&
|
||||
Arrays.equals(to.getRipe(), plaintext.to.getRipe()) &&
|
||||
Arrays.equals(signature, plaintext.signature) &&
|
||||
Objects.equals(status, plaintext.status) &&
|
||||
|
@ -1,33 +0,0 @@
|
||||
package ch.dissem.bitmessage.entity.payload;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* Created by chrigu on 06.11.15.
|
||||
*/
|
||||
public class Ack extends ObjectPayload {
|
||||
private final long stream;
|
||||
private final byte[] data;
|
||||
|
||||
public Ack(long version, long stream, byte[] data) {
|
||||
super(version);
|
||||
this.stream = stream;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectType getType() {
|
||||
return ObjectType.MSG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getStream() {
|
||||
return stream;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(OutputStream out) throws IOException {
|
||||
out.write(data);
|
||||
}
|
||||
}
|
@ -23,6 +23,7 @@ import ch.dissem.bitmessage.entity.PlaintextHolder;
|
||||
import ch.dissem.bitmessage.exception.DecryptionFailedException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
||||
import static ch.dissem.bitmessage.entity.Plaintext.Type.BROADCAST;
|
||||
import static ch.dissem.bitmessage.utils.Singleton.security;
|
||||
@ -96,4 +97,18 @@ public abstract class Broadcast extends ObjectPayload implements Encrypted, Plai
|
||||
public boolean isDecrypted() {
|
||||
return plaintext != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Broadcast broadcast = (Broadcast) o;
|
||||
return stream == broadcast.stream &&
|
||||
(Objects.equals(encrypted, broadcast.encrypted) || Objects.equals(plaintext, broadcast.plaintext));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(stream);
|
||||
}
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ public class GenericPayload extends ObjectPayload {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public static GenericPayload read(long version, InputStream is, long stream, int length) throws IOException {
|
||||
public static GenericPayload read(long version, long stream, InputStream is, int length) throws IOException {
|
||||
return new GenericPayload(version, stream, Decode.bytes(is, length));
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,7 @@ import ch.dissem.bitmessage.exception.DecryptionFailedException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Objects;
|
||||
|
||||
import static ch.dissem.bitmessage.entity.Plaintext.Type.MSG;
|
||||
|
||||
@ -108,4 +109,19 @@ public class Msg extends ObjectPayload implements Encrypted, PlaintextHolder {
|
||||
if (encrypted == null) throw new IllegalStateException("Msg must be signed and encrypted before writing it.");
|
||||
encrypted.write(out);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
if (!super.equals(o)) return false;
|
||||
Msg msg = (Msg) o;
|
||||
return stream == msg.stream &&
|
||||
(Objects.equals(encrypted, msg.encrypted) || Objects.equals(plaintext, msg.plaintext));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return (int) stream;
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ package ch.dissem.bitmessage.entity.payload;
|
||||
|
||||
import ch.dissem.bitmessage.entity.ObjectMessage;
|
||||
import ch.dissem.bitmessage.entity.Streamable;
|
||||
import sun.reflect.generics.reflectiveObjects.NotImplementedException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
@ -31,6 +31,7 @@ import java.io.InputStream;
|
||||
import java.net.SocketException;
|
||||
import java.net.SocketTimeoutException;
|
||||
|
||||
import static ch.dissem.bitmessage.entity.payload.ObjectType.MSG;
|
||||
import static ch.dissem.bitmessage.utils.Singleton.security;
|
||||
|
||||
/**
|
||||
@ -155,7 +156,7 @@ public class Factory {
|
||||
}
|
||||
// fallback: just store the message - we don't really care what it is
|
||||
LOG.trace("Unexpected object type: " + objectType);
|
||||
return GenericPayload.read(version, stream, streamNumber, length);
|
||||
return GenericPayload.read(version, streamNumber, stream, length);
|
||||
}
|
||||
|
||||
private static ObjectPayload parseGetPubkey(long version, long streamNumber, InputStream stream, int length) throws IOException {
|
||||
@ -177,7 +178,7 @@ public class Factory {
|
||||
|
||||
private static ObjectPayload parsePubkey(long version, long streamNumber, InputStream stream, int length) throws IOException {
|
||||
Pubkey pubkey = readPubkey(version, streamNumber, stream, length, true);
|
||||
return pubkey != null ? pubkey : GenericPayload.read(version, stream, streamNumber, length);
|
||||
return pubkey != null ? pubkey : GenericPayload.read(version, streamNumber, stream, length);
|
||||
}
|
||||
|
||||
private static ObjectPayload parseMsg(long version, long streamNumber, InputStream stream, int length) throws IOException {
|
||||
@ -192,7 +193,7 @@ public class Factory {
|
||||
return V5Broadcast.read(stream, streamNumber, length);
|
||||
default:
|
||||
LOG.debug("Encountered unknown broadcast version " + version);
|
||||
return GenericPayload.read(version, stream, streamNumber, length);
|
||||
return GenericPayload.read(version, streamNumber, stream, length);
|
||||
}
|
||||
}
|
||||
|
||||
@ -208,7 +209,7 @@ public class Factory {
|
||||
public static ObjectMessage createAck(Plaintext plaintext) {
|
||||
if (plaintext == null || plaintext.getAckData() == null)
|
||||
return null;
|
||||
Ack ack = new Ack(3, plaintext.getFrom().getStream(), plaintext.getAckData());
|
||||
return new ObjectMessage.Builder().payload(ack).build();
|
||||
GenericPayload ack = new GenericPayload(3, plaintext.getFrom().getStream(), plaintext.getAckData());
|
||||
return new ObjectMessage.Builder().objectType(MSG).payload(ack).build();
|
||||
}
|
||||
}
|
||||
|
@ -22,19 +22,22 @@ import ch.dissem.bitmessage.entity.ObjectMessage;
|
||||
import ch.dissem.bitmessage.entity.Plaintext;
|
||||
import ch.dissem.bitmessage.entity.payload.ObjectType;
|
||||
import ch.dissem.bitmessage.entity.payload.Pubkey;
|
||||
import ch.dissem.bitmessage.entity.valueobject.InventoryVector;
|
||||
import ch.dissem.bitmessage.ports.*;
|
||||
import ch.dissem.bitmessage.utils.MessageMatchers;
|
||||
import ch.dissem.bitmessage.utils.Singleton;
|
||||
import ch.dissem.bitmessage.utils.TestUtils;
|
||||
import ch.dissem.bitmessage.utils.*;
|
||||
import org.hamcrest.BaseMatcher;
|
||||
import org.hamcrest.Description;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Collections;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static ch.dissem.bitmessage.entity.payload.ObjectType.*;
|
||||
import static ch.dissem.bitmessage.utils.MessageMatchers.object;
|
||||
import static ch.dissem.bitmessage.utils.Singleton.security;
|
||||
import static ch.dissem.bitmessage.utils.UnixTime.MINUTE;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||
import static org.junit.Assert.*;
|
||||
@ -59,9 +62,41 @@ public class BitmessageContextTest {
|
||||
.messageRepo(mock(MessageRepository.class))
|
||||
.networkHandler(mock(NetworkHandler.class))
|
||||
.nodeRegistry(mock(NodeRegistry.class))
|
||||
.powRepo(mock(ProofOfWorkRepository.class))
|
||||
.proofOfWorkEngine(mock(ProofOfWorkEngine.class))
|
||||
.powRepo(spy(new ProofOfWorkRepository() {
|
||||
Map<InventoryVector, Item> items = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public Item getItem(byte[] initialHash) {
|
||||
return items.get(new InventoryVector(initialHash));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<byte[]> getItems() {
|
||||
List<byte[]> result = new LinkedList<>();
|
||||
for (InventoryVector iv : items.keySet()) {
|
||||
result.add(iv.getHash());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putObject(ObjectMessage object, long nonceTrialsPerByte, long extraBytes) {
|
||||
items.put(new InventoryVector(security().getInitialHash(object)), new Item(object, nonceTrialsPerByte, extraBytes));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeObject(byte[] initialHash) {
|
||||
items.remove(initialHash);
|
||||
}
|
||||
}))
|
||||
.proofOfWorkEngine(spy(new ProofOfWorkEngine() {
|
||||
@Override
|
||||
public void calculateNonce(byte[] initialHash, byte[] target, Callback callback) {
|
||||
callback.onNonceCalculated(initialHash, new byte[8]);
|
||||
}
|
||||
}))
|
||||
.build();
|
||||
TTL.msg(2 * MINUTE);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -161,6 +196,7 @@ public class BitmessageContextTest {
|
||||
public void ensureMessageIsSent() throws Exception {
|
||||
ctx.send(TestUtils.loadIdentity("BM-2cSqjfJ8xK6UUn5Rw3RpdGQ9RsDkBhWnS8"), TestUtils.loadContact(),
|
||||
"Subject", "Message");
|
||||
assertEquals(1, ctx.internals().getProofOfWorkRepository().getItems().size());
|
||||
verify(ctx.internals().getProofOfWorkRepository(), timeout(10000).atLeastOnce())
|
||||
.putObject(object(MSG), eq(1000L), eq(1000L));
|
||||
verify(ctx.messages(), timeout(10000).atLeastOnce()).save(MessageMatchers.plaintext(Plaintext.Type.MSG));
|
||||
|
@ -66,6 +66,7 @@ public class DefaultMessageListenerTest extends TestBase {
|
||||
when(ctx.getMessageRepository()).thenReturn(messageRepo);
|
||||
when(ctx.getInventory()).thenReturn(inventory);
|
||||
when(ctx.getNetworkHandler()).thenReturn(networkHandler);
|
||||
when(ctx.getLabeler()).thenReturn(mock(Labeler.class));
|
||||
|
||||
listener = new DefaultMessageListener(ctx, mock(Labeler.class), mock(BitmessageContext.Listener.class));
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ public class EncryptionTest extends TestBase {
|
||||
PrivateKey privateKey = new PrivateKey(false, 1, 1000, 1000);
|
||||
CryptoBox cryptoBox = new CryptoBox(before, privateKey.getPubkey().getEncryptionKey());
|
||||
|
||||
GenericPayload after = GenericPayload.read(0, cryptoBox.decrypt(privateKey.getPrivateEncryptionKey()), 1, 100);
|
||||
GenericPayload after = GenericPayload.read(0, 1, cryptoBox.decrypt(privateKey.getPrivateEncryptionKey()), 100);
|
||||
|
||||
assertEquals(before, after);
|
||||
}
|
||||
|
@ -65,6 +65,7 @@ public class ProofOfWorkServiceTest {
|
||||
when(ctx.getInventory()).thenReturn(inventory);
|
||||
when(ctx.getNetworkHandler()).thenReturn(networkHandler);
|
||||
when(ctx.getMessageRepository()).thenReturn(messageRepo);
|
||||
when(ctx.getLabeler()).thenReturn(mock(Labeler.class));
|
||||
|
||||
proofOfWorkService = new ProofOfWorkService();
|
||||
proofOfWorkService.setContext(ctx);
|
||||
|
@ -82,7 +82,7 @@ public class SerializationTest extends TestBase {
|
||||
.from(TestUtils.loadIdentity("BM-2cSqjfJ8xK6UUn5Rw3RpdGQ9RsDkBhWnS8"))
|
||||
.to(TestUtils.loadContact())
|
||||
.message("Subject", "Message")
|
||||
.ack("ack".getBytes())
|
||||
.ackData("ack".getBytes())
|
||||
.signature(new byte[0])
|
||||
.build();
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
|
@ -72,7 +72,7 @@ public class TestUtils {
|
||||
|
||||
public static BitmessageAddress loadContact() throws IOException, DecryptionFailedException {
|
||||
BitmessageAddress address = new BitmessageAddress("BM-2cXxfcSetKnbHJX2Y85rSkaVpsdNUZ5q9h");
|
||||
ObjectMessage object = TestUtils.loadObjectMessage(4, "V4Pubkey.payload");
|
||||
ObjectMessage object = TestUtils.loadObjectMessage(3, "V4Pubkey.payload");
|
||||
object.decrypt(address.getPublicDecryptionKey());
|
||||
address.setPubkey((V4Pubkey) object.getPayload());
|
||||
return address;
|
||||
|
@ -21,9 +21,7 @@ import java.io.IOException;
|
||||
import static ch.dissem.bitmessage.utils.UnixTime.DAY;
|
||||
import static ch.dissem.bitmessage.utils.UnixTime.MINUTE;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ -82,7 +80,7 @@ public class CryptographyTest {
|
||||
.nonce(new byte[8])
|
||||
.expiresTime(UnixTime.now(+28 * DAY))
|
||||
.objectType(0)
|
||||
.payload(GenericPayload.read(0, new ByteArrayInputStream(new byte[0]), 1, 0))
|
||||
.payload(GenericPayload.read(0, 1, new ByteArrayInputStream(new byte[0]), 0))
|
||||
.build();
|
||||
crypto.checkProofOfWork(objectMessage, 1000, 1000);
|
||||
}
|
||||
@ -93,7 +91,7 @@ public class CryptographyTest {
|
||||
.nonce(new byte[8])
|
||||
.expiresTime(UnixTime.now(+2 * MINUTE))
|
||||
.objectType(0)
|
||||
.payload(GenericPayload.read(0, new ByteArrayInputStream(new byte[0]), 1, 0))
|
||||
.payload(GenericPayload.read(0, 1, new ByteArrayInputStream(new byte[0]), 0))
|
||||
.build();
|
||||
final CallbackWaiter<byte[]> waiter = new CallbackWaiter<>();
|
||||
crypto.doProofOfWork(objectMessage, 1000, 1000,
|
||||
|
@ -52,7 +52,7 @@ public class CryptoCustomMessageTest extends TestBase {
|
||||
new CryptoCustomMessage.Reader<GenericPayload>() {
|
||||
@Override
|
||||
public GenericPayload read(BitmessageAddress ignore, InputStream in) throws IOException {
|
||||
return GenericPayload.read(0, in, 1, 100);
|
||||
return GenericPayload.read(0, 1, in, 100);
|
||||
}
|
||||
});
|
||||
GenericPayload payloadAfter = messageAfter.decrypt(sendingIdentity.getPublicDecryptionKey());
|
||||
|
Loading…
Reference in New Issue
Block a user