Fixed system test and ProofOfWorkService
This commit is contained in:
@ -18,5 +18,6 @@ dependencies {
|
||||
testCompile 'junit:junit:4.12'
|
||||
testCompile 'com.h2database:h2:1.4.190'
|
||||
testCompile 'org.mockito:mockito-core:1.10.19'
|
||||
testCompile project(path: ':core', configuration: 'testArtifacts')
|
||||
testCompile project(':cryptography-bc')
|
||||
}
|
@ -117,6 +117,24 @@ public class JdbcMessageRepository extends JdbcHelper implements MessageReposito
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Plaintext getMessage(Object id) {
|
||||
if (id instanceof Long) {
|
||||
List<Plaintext> plaintexts = find("id=" + id);
|
||||
switch (plaintexts.size()) {
|
||||
case 0:
|
||||
return null;
|
||||
case 1:
|
||||
return plaintexts.get(0);
|
||||
default:
|
||||
throw new ApplicationException("This shouldn't happen, found " + plaintexts.size() +
|
||||
" messages, one or none was expected");
|
||||
}
|
||||
} else {
|
||||
throw new IllegalArgumentException("Long expected for ID");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Plaintext getMessage(byte[] initialHash) {
|
||||
List<Plaintext> plaintexts = find("initial_hash=X'" + Strings.hex(initialHash) + "'");
|
||||
|
@ -1,6 +1,8 @@
|
||||
package ch.dissem.bitmessage.repository;
|
||||
|
||||
import ch.dissem.bitmessage.InternalContext;
|
||||
import ch.dissem.bitmessage.entity.ObjectMessage;
|
||||
import ch.dissem.bitmessage.entity.Plaintext;
|
||||
import ch.dissem.bitmessage.exception.ApplicationException;
|
||||
import ch.dissem.bitmessage.factory.Factory;
|
||||
import ch.dissem.bitmessage.ports.ProofOfWorkRepository;
|
||||
@ -8,18 +10,21 @@ import ch.dissem.bitmessage.utils.Strings;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.sql.*;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import static ch.dissem.bitmessage.utils.Singleton.security;
|
||||
import static ch.dissem.bitmessage.utils.Singleton.cryptography;
|
||||
|
||||
/**
|
||||
* @author Christian Basler
|
||||
*/
|
||||
public class JdbcProofOfWorkRepository extends JdbcHelper implements ProofOfWorkRepository {
|
||||
public class JdbcProofOfWorkRepository extends JdbcHelper implements ProofOfWorkRepository, InternalContext.ContextHolder {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(JdbcProofOfWorkRepository.class);
|
||||
private InternalContext ctx;
|
||||
|
||||
public JdbcProofOfWorkRepository(JdbcConfig config) {
|
||||
super(config);
|
||||
@ -30,17 +35,27 @@ public class JdbcProofOfWorkRepository extends JdbcHelper implements ProofOfWork
|
||||
try (
|
||||
Connection connection = config.getConnection();
|
||||
PreparedStatement ps = connection.prepareStatement("SELECT data, version, nonce_trials_per_byte, " +
|
||||
"extra_bytes FROM POW WHERE initial_hash=?")
|
||||
"extra_bytes, expiration_time, message_id FROM POW WHERE initial_hash=?")
|
||||
) {
|
||||
ps.setBytes(1, initialHash);
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
if (rs.next()) {
|
||||
Blob data = rs.getBlob("data");
|
||||
return new Item(
|
||||
Factory.getObjectMessage(rs.getInt("version"), data.getBinaryStream(), (int) data.length()),
|
||||
rs.getLong("nonce_trials_per_byte"),
|
||||
rs.getLong("extra_bytes")
|
||||
);
|
||||
if (rs.getObject("message_id") == null) {
|
||||
return new Item(
|
||||
Factory.getObjectMessage(rs.getInt("version"), data.getBinaryStream(), (int) data.length()),
|
||||
rs.getLong("nonce_trials_per_byte"),
|
||||
rs.getLong("extra_bytes")
|
||||
);
|
||||
} else {
|
||||
return new Item(
|
||||
Factory.getObjectMessage(rs.getInt("version"), data.getBinaryStream(), (int) data.length()),
|
||||
rs.getLong("nonce_trials_per_byte"),
|
||||
rs.getLong("extra_bytes"),
|
||||
rs.getLong("expiration_time"),
|
||||
ctx.getMessageRepository().getMessage(rs.getLong("message_id"))
|
||||
);
|
||||
}
|
||||
} else {
|
||||
throw new IllegalArgumentException("Object requested that we don't have. Initial hash: " + Strings.hex(initialHash));
|
||||
}
|
||||
@ -70,24 +85,38 @@ public class JdbcProofOfWorkRepository extends JdbcHelper implements ProofOfWork
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putObject(ObjectMessage object, long nonceTrialsPerByte, long extraBytes) {
|
||||
public void putObject(Item item) {
|
||||
try (
|
||||
Connection connection = config.getConnection();
|
||||
PreparedStatement ps = connection.prepareStatement("INSERT INTO POW (initial_hash, data, version, " +
|
||||
"nonce_trials_per_byte, extra_bytes) VALUES (?, ?, ?, ?, ?)")
|
||||
"nonce_trials_per_byte, extra_bytes, expiration_time, message_id) " +
|
||||
"VALUES (?, ?, ?, ?, ?, ?, ?)")
|
||||
) {
|
||||
ps.setBytes(1, security().getInitialHash(object));
|
||||
writeBlob(ps, 2, object);
|
||||
ps.setLong(3, object.getVersion());
|
||||
ps.setLong(4, nonceTrialsPerByte);
|
||||
ps.setLong(5, extraBytes);
|
||||
ps.setBytes(1, cryptography().getInitialHash(item.object));
|
||||
writeBlob(ps, 2, item.object);
|
||||
ps.setLong(3, item.object.getVersion());
|
||||
ps.setLong(4, item.nonceTrialsPerByte);
|
||||
ps.setLong(5, item.extraBytes);
|
||||
|
||||
if (item.message == null) {
|
||||
ps.setObject(6, null);
|
||||
ps.setObject(7, null);
|
||||
} else {
|
||||
ps.setLong(6, item.expirationTime);
|
||||
ps.setLong(7, (Long) item.message.getId());
|
||||
}
|
||||
ps.executeUpdate();
|
||||
} catch (IOException | SQLException e) {
|
||||
LOG.debug("Error storing object of type " + object.getPayload().getClass().getSimpleName(), e);
|
||||
LOG.debug("Error storing object of type " + item.object.getPayload().getClass().getSimpleName(), e);
|
||||
throw new ApplicationException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putObject(ObjectMessage object, long nonceTrialsPerByte, long extraBytes) {
|
||||
putObject(new Item(object, nonceTrialsPerByte, extraBytes));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeObject(byte[] initialHash) {
|
||||
try (
|
||||
@ -100,4 +129,9 @@ public class JdbcProofOfWorkRepository extends JdbcHelper implements ProofOfWork
|
||||
LOG.debug(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContext(InternalContext context) {
|
||||
this.ctx = context;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,2 @@
|
||||
ALTER TABLE POW ADD COLUMN expiration_time BIGINT;
|
||||
ALTER TABLE POW ADD COLUMN message_id BIGINT;
|
@ -68,9 +68,11 @@ public class JdbcAddressRepositoryTest extends TestBase {
|
||||
public void testFindIdentity() throws Exception {
|
||||
BitmessageAddress identity = new BitmessageAddress(IDENTITY_A);
|
||||
assertEquals(4, identity.getVersion());
|
||||
assertEquals(identity, repo.findIdentity(identity.getTag()));
|
||||
assertNull(repo.findContact(identity.getTag()));
|
||||
assertTrue(identity.has(Pubkey.Feature.DOES_ACK));
|
||||
|
||||
BitmessageAddress storedIdentity = repo.findIdentity(identity.getTag());
|
||||
assertEquals(identity, storedIdentity);
|
||||
assertTrue(storedIdentity.has(Pubkey.Feature.DOES_ACK));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -32,7 +32,7 @@ import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static ch.dissem.bitmessage.entity.Plaintext.Type.MSG;
|
||||
import static ch.dissem.bitmessage.utils.Singleton.security;
|
||||
import static ch.dissem.bitmessage.utils.Singleton.cryptography;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
@ -54,7 +54,7 @@ public class JdbcMessageRepositoryTest extends TestBase {
|
||||
AddressRepository addressRepo = new JdbcAddressRepository(config);
|
||||
repo = new JdbcMessageRepository(config);
|
||||
new InternalContext(new BitmessageContext.Builder()
|
||||
.cryptography(security())
|
||||
.cryptography(cryptography())
|
||||
.addressRepo(addressRepo)
|
||||
.messageRepo(repo)
|
||||
);
|
||||
@ -146,7 +146,7 @@ public class JdbcMessageRepositoryTest extends TestBase {
|
||||
@Test
|
||||
public void testSave() throws Exception {
|
||||
Plaintext message = new Plaintext.Builder(MSG)
|
||||
.IV(new InventoryVector(security().randomBytes(32)))
|
||||
.IV(new InventoryVector(cryptography().randomBytes(32)))
|
||||
.from(identity)
|
||||
.to(contactA)
|
||||
.message("Subject", "Message")
|
||||
@ -169,7 +169,7 @@ public class JdbcMessageRepositoryTest extends TestBase {
|
||||
public void testUpdate() throws Exception {
|
||||
List<Plaintext> messages = repo.findMessages(Plaintext.Status.DRAFT, contactA);
|
||||
Plaintext message = messages.get(0);
|
||||
message.setInventoryVector(new InventoryVector(security().randomBytes(32)));
|
||||
message.setInventoryVector(new InventoryVector(cryptography().randomBytes(32)));
|
||||
repo.save(message);
|
||||
|
||||
messages = repo.findMessages(Plaintext.Status.DRAFT, contactA);
|
||||
|
@ -16,13 +16,24 @@
|
||||
|
||||
package ch.dissem.bitmessage.repository;
|
||||
|
||||
import ch.dissem.bitmessage.BitmessageContext;
|
||||
import ch.dissem.bitmessage.InternalContext;
|
||||
import ch.dissem.bitmessage.entity.BitmessageAddress;
|
||||
import ch.dissem.bitmessage.entity.ObjectMessage;
|
||||
import ch.dissem.bitmessage.entity.Plaintext;
|
||||
import ch.dissem.bitmessage.entity.payload.GenericPayload;
|
||||
import ch.dissem.bitmessage.entity.payload.GetPubkey;
|
||||
import ch.dissem.bitmessage.ports.ProofOfWorkRepository;
|
||||
import ch.dissem.bitmessage.ports.AddressRepository;
|
||||
import ch.dissem.bitmessage.ports.MessageRepository;
|
||||
import ch.dissem.bitmessage.ports.ProofOfWorkRepository.Item;
|
||||
import ch.dissem.bitmessage.utils.TestUtils;
|
||||
import ch.dissem.bitmessage.utils.UnixTime;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import static ch.dissem.bitmessage.entity.Plaintext.Type.MSG;
|
||||
import static ch.dissem.bitmessage.utils.Singleton.cryptography;
|
||||
import static ch.dissem.bitmessage.utils.UnixTime.MINUTE;
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
@ -33,17 +44,51 @@ import static org.junit.Assert.assertTrue;
|
||||
public class JdbcProofOfWorkRepositoryTest extends TestBase {
|
||||
private TestJdbcConfig config;
|
||||
private JdbcProofOfWorkRepository repo;
|
||||
private AddressRepository addressRepo;
|
||||
private MessageRepository messageRepo;
|
||||
|
||||
private byte[] initialHash1;
|
||||
private byte[] initialHash2;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
config = new TestJdbcConfig();
|
||||
config.reset();
|
||||
|
||||
addressRepo = new JdbcAddressRepository(config);
|
||||
messageRepo = new JdbcMessageRepository(config);
|
||||
repo = new JdbcProofOfWorkRepository(config);
|
||||
InternalContext ctx = new InternalContext(new BitmessageContext.Builder()
|
||||
.addressRepo(addressRepo)
|
||||
.messageRepo(messageRepo)
|
||||
.powRepo(repo)
|
||||
.cryptography(cryptography())
|
||||
);
|
||||
|
||||
repo.putObject(new ObjectMessage.Builder()
|
||||
.payload(new GetPubkey(new BitmessageAddress("BM-2DAjcCFrqFrp88FUxExhJ9kPqHdunQmiyn"))).build(),
|
||||
1000, 1000);
|
||||
initialHash1 = repo.getItems().get(0);
|
||||
|
||||
BitmessageAddress sender = TestUtils.loadIdentity("BM-2cSqjfJ8xK6UUn5Rw3RpdGQ9RsDkBhWnS8");
|
||||
BitmessageAddress recipient = TestUtils.loadContact();
|
||||
addressRepo.save(sender);
|
||||
addressRepo.save(recipient);
|
||||
Plaintext plaintext = new Plaintext.Builder(MSG)
|
||||
.ackData(cryptography().randomBytes(32))
|
||||
.from(sender)
|
||||
.to(recipient)
|
||||
.message("Subject", "Message")
|
||||
.status(Plaintext.Status.DOING_PROOF_OF_WORK)
|
||||
.build();
|
||||
messageRepo.save(plaintext);
|
||||
initialHash2 = cryptography().getInitialHash(plaintext.getAckMessage());
|
||||
repo.putObject(new Item(
|
||||
plaintext.getAckMessage(),
|
||||
1000, 1000,
|
||||
UnixTime.now(+10 * MINUTE),
|
||||
plaintext
|
||||
));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -55,16 +100,52 @@ public class JdbcProofOfWorkRepositoryTest extends TestBase {
|
||||
assertThat(repo.getItems().size(), is(sizeBefore + 1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ensureAckObjectsAreStored() throws Exception {
|
||||
int sizeBefore = repo.getItems().size();
|
||||
BitmessageAddress sender = TestUtils.loadIdentity("BM-2cSqjfJ8xK6UUn5Rw3RpdGQ9RsDkBhWnS8");
|
||||
BitmessageAddress recipient = TestUtils.loadContact();
|
||||
addressRepo.save(sender);
|
||||
addressRepo.save(recipient);
|
||||
Plaintext plaintext = new Plaintext.Builder(MSG)
|
||||
.ackData(cryptography().randomBytes(32))
|
||||
.from(sender)
|
||||
.to(recipient)
|
||||
.message("Subject", "Message")
|
||||
.status(Plaintext.Status.DOING_PROOF_OF_WORK)
|
||||
.build();
|
||||
messageRepo.save(plaintext);
|
||||
repo.putObject(new Item(
|
||||
plaintext.getAckMessage(),
|
||||
1000, 1000,
|
||||
UnixTime.now(+10 * MINUTE),
|
||||
plaintext
|
||||
));
|
||||
assertThat(repo.getItems().size(), is(sizeBefore + 1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ensureItemCanBeRetrieved() {
|
||||
byte[] initialHash = repo.getItems().get(0);
|
||||
ProofOfWorkRepository.Item item = repo.getItem(initialHash);
|
||||
Item item = repo.getItem(initialHash1);
|
||||
assertThat(item, notNullValue());
|
||||
assertThat(item.object.getPayload(), instanceOf(GetPubkey.class));
|
||||
assertThat(item.nonceTrialsPerByte, is(1000L));
|
||||
assertThat(item.extraBytes, is(1000L));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ensureAckItemCanBeRetrieved() {
|
||||
Item item = repo.getItem(initialHash2);
|
||||
assertThat(item, notNullValue());
|
||||
assertThat(item.object.getPayload(), instanceOf(GenericPayload.class));
|
||||
assertThat(item.nonceTrialsPerByte, is(1000L));
|
||||
assertThat(item.extraBytes, is(1000L));
|
||||
assertThat(item.expirationTime, not(0));
|
||||
assertThat(item.message, notNullValue());
|
||||
assertThat(item.message.getFrom().getPrivateKey(), notNullValue());
|
||||
assertThat(item.message.getTo().getPubkey(), notNullValue());
|
||||
}
|
||||
|
||||
@Test(expected = RuntimeException.class)
|
||||
public void ensureRetrievingNonexistingItemThrowsException() {
|
||||
repo.getItem(new byte[0]);
|
||||
@ -72,8 +153,8 @@ public class JdbcProofOfWorkRepositoryTest extends TestBase {
|
||||
|
||||
@Test
|
||||
public void ensureItemCanBeDeleted() {
|
||||
byte[] initialHash = repo.getItems().get(0);
|
||||
repo.removeObject(initialHash);
|
||||
repo.removeObject(initialHash1);
|
||||
repo.removeObject(initialHash2);
|
||||
assertTrue(repo.getItems().isEmpty());
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user