diff --git a/components/net/sf/briar/db/Database.java b/components/net/sf/briar/db/Database.java
index 0bf6e058b0eeeeb5386109709930f5706523352c..2d9015362cf38748c6ba34926222d72925b438cd 100644
--- a/components/net/sf/briar/db/Database.java
+++ b/components/net/sf/briar/db/Database.java
@@ -92,7 +92,7 @@ interface Database<T> {
 	 * <p>
 	 * Locking: messages write.
 	 */
-	boolean addMessage(T txn, Message m) throws DbException;
+	boolean addGroupMessage(T txn, Message m) throws DbException;
 
 	/**
 	 * Records a sent batch as needing to be acknowledged.
@@ -102,6 +102,14 @@ interface Database<T> {
 	void addOutstandingBatch(T txn, ContactId c, BatchId b,
 			Collection<MessageId> sent) throws DbException;
 
+	/**
+	 * Returns false if the given message is already in the database. Otherwise
+	 * stores the message and returns true.
+	 * <p>
+	 * Locking: contacts read, messages write.
+	 */
+	boolean addPrivateMessage(T txn, Message m, ContactId c) throws DbException;
+
 	/**
 	 * Subscribes to the given group.
 	 * <p>
@@ -360,8 +368,8 @@ interface Database<T> {
 	/**
 	 * Removes a contact (and all associated state) from the database.
 	 * <p>
-	 * Locking: contacts write, messageStatuses write, subscriptions write,
-	 * transports write.
+	 * Locking: contacts write, messages write, messageStatuses write,
+	 * subscriptions write, transports write.
 	 */
 	void removeContact(T txn, ContactId c) throws DbException;
 
diff --git a/components/net/sf/briar/db/DatabaseComponentImpl.java b/components/net/sf/briar/db/DatabaseComponentImpl.java
index 6d251245d74eea6e7e99b976e9bb4092a016ff84..55ca48a4bfc811e162f518b9550815be2f6dabd9 100644
--- a/components/net/sf/briar/db/DatabaseComponentImpl.java
+++ b/components/net/sf/briar/db/DatabaseComponentImpl.java
@@ -179,7 +179,7 @@ DatabaseCleaner.Callback {
 	protected boolean storeGroupMessage(Txn txn, Message m, ContactId sender)
 	throws DbException {
 		if(m.getGroup() == null) throw new IllegalArgumentException();
-		boolean stored = db.addMessage(txn, m);
+		boolean stored = db.addGroupMessage(txn, m);
 		// Mark the message as seen by the sender
 		MessageId id = m.getId();
 		if(sender != null) db.setStatus(txn, sender, id, Status.SEEN);
@@ -229,7 +229,7 @@ DatabaseCleaner.Callback {
 	protected boolean storePrivateMessage(Txn txn, Message m, ContactId c,
 			boolean incoming) throws DbException {
 		if(m.getGroup() != null) throw new IllegalArgumentException();
-		if(!db.addMessage(txn, m)) return false;
+		if(!db.addPrivateMessage(txn, m, c)) return false;
 		MessageId id = m.getId();
 		if(incoming) db.setStatus(txn, c, id, Status.SEEN);
 		else db.setStatus(txn, c, id, Status.NEW);
diff --git a/components/net/sf/briar/db/JdbcDatabase.java b/components/net/sf/briar/db/JdbcDatabase.java
index 099ac144f462ff199769d3785bc3936850a8e176..2ff792ff9f65c2e1537f26c0334313478773e2be 100644
--- a/components/net/sf/briar/db/JdbcDatabase.java
+++ b/components/net/sf/briar/db/JdbcDatabase.java
@@ -49,6 +49,12 @@ abstract class JdbcDatabase implements Database<Connection> {
 		+ " start BIGINT NOT NULL,"
 		+ " PRIMARY KEY (groupId))";
 
+	private static final String CREATE_CONTACTS =
+		"CREATE TABLE contacts"
+		+ " (contactId INT NOT NULL,"
+		+ " secret BINARY NOT NULL,"
+		+ " PRIMARY KEY (contactId))";
+
 	private static final String CREATE_MESSAGES =
 		"CREATE TABLE messages"
 		+ " (messageId HASH NOT NULL,"
@@ -58,9 +64,12 @@ abstract class JdbcDatabase implements Database<Connection> {
 		+ " timestamp BIGINT NOT NULL,"
 		+ " size INT NOT NULL,"
 		+ " raw BLOB NOT NULL,"
-		+ " sendability INT NOT NULL,"
+		+ " sendability INT,"
+		+ " contactId INT,"
 		+ " PRIMARY KEY (messageId),"
 		+ " FOREIGN KEY (groupId) REFERENCES subscriptions (groupId)"
+		+ " ON DELETE CASCADE,"
+		+ " FOREIGN KEY (contactId) REFERENCES contacts (contactId)"
 		+ " ON DELETE CASCADE)";
 
 	private static final String INDEX_MESSAGES_BY_PARENT =
@@ -75,12 +84,6 @@ abstract class JdbcDatabase implements Database<Connection> {
 	private static final String INDEX_MESSAGES_BY_SENDABILITY =
 		"CREATE INDEX messagesBySendability ON messages (sendability)";
 
-	private static final String CREATE_CONTACTS =
-		"CREATE TABLE contacts"
-		+ " (contactId INT NOT NULL,"
-		+ " secret BINARY NOT NULL,"
-		+ " PRIMARY KEY (contactId))";
-
 	private static final String CREATE_VISIBILITIES =
 		"CREATE TABLE visibilities"
 		+ " (groupId HASH NOT NULL,"
@@ -278,12 +281,12 @@ abstract class JdbcDatabase implements Database<Connection> {
 		try {
 			s = txn.createStatement();
 			s.executeUpdate(insertTypeNames(CREATE_SUBSCRIPTIONS));
+			s.executeUpdate(insertTypeNames(CREATE_CONTACTS));
 			s.executeUpdate(insertTypeNames(CREATE_MESSAGES));
 			s.executeUpdate(INDEX_MESSAGES_BY_PARENT);
 			s.executeUpdate(INDEX_MESSAGES_BY_AUTHOR);
 			s.executeUpdate(INDEX_MESSAGES_BY_BIGINT);
 			s.executeUpdate(INDEX_MESSAGES_BY_SENDABILITY);
-			s.executeUpdate(insertTypeNames(CREATE_CONTACTS));
 			s.executeUpdate(insertTypeNames(CREATE_VISIBILITIES));
 			s.executeUpdate(INDEX_VISIBILITIES_BY_GROUP);
 			s.executeUpdate(insertTypeNames(CREATE_BATCHES_TO_ACK));
@@ -527,14 +530,16 @@ abstract class JdbcDatabase implements Database<Connection> {
 		}
 	}
 
-	public boolean addMessage(Connection txn, Message m) throws DbException {
+	public boolean addGroupMessage(Connection txn, Message m)
+	throws DbException {
+		assert m.getGroup() != null;
 		if(containsMessage(txn, m.getId())) return false;
 		PreparedStatement ps = null;
 		try {
 			String sql = "INSERT INTO messages"
 				+ " (messageId, parentId, groupId, authorId, timestamp, size,"
 				+ " raw, sendability)"
-				+ " VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
+				+ " VALUES (?, ?, ?, ?, ?, ?, ?, ZERO())";
 			ps = txn.prepareStatement(sql);
 			ps.setBytes(1, m.getId().getBytes());
 			if(m.getParent() == null) ps.setNull(2, Types.BINARY);
@@ -546,7 +551,6 @@ abstract class JdbcDatabase implements Database<Connection> {
 			ps.setInt(6, m.getSize());
 			byte[] raw = m.getBytes();
 			ps.setBinaryStream(7, new ByteArrayInputStream(raw), raw.length);
-			ps.setInt(8, 0);
 			int affected = ps.executeUpdate();
 			if(affected != 1) throw new DbStateException();
 			ps.close();
@@ -616,6 +620,34 @@ abstract class JdbcDatabase implements Database<Connection> {
 		}
 	}
 
+	public boolean addPrivateMessage(Connection txn, Message m, ContactId c)
+	throws DbException {
+		assert m.getGroup() == null;
+		if(containsMessage(txn, m.getId())) return false;
+		PreparedStatement ps = null;
+		try {
+			String sql = "INSERT INTO messages"
+				+ " (messageId, parentId, timestamp, size, raw, contactId)"
+				+ " VALUES (?, ?, ?, ?, ?, ?)";
+			ps = txn.prepareStatement(sql);
+			ps.setBytes(1, m.getId().getBytes());
+			if(m.getParent() == null) ps.setNull(2, Types.BINARY);
+			else ps.setBytes(2, m.getParent().getBytes());
+			ps.setLong(3, m.getTimestamp());
+			ps.setInt(4, m.getSize());
+			byte[] raw = m.getBytes();
+			ps.setBinaryStream(5, new ByteArrayInputStream(raw), raw.length);
+			ps.setInt(6, c.getInt());
+			int affected = ps.executeUpdate();
+			if(affected != 1) throw new DbStateException();
+			ps.close();
+			return true;
+		} catch(SQLException e) {
+			tryToClose(ps);
+			throw new DbException(e);
+		}
+	}
+
 	public void addSubscription(Connection txn, Group g) throws DbException {
 		PreparedStatement ps = null;
 		try {
diff --git a/components/net/sf/briar/db/ReadWriteLockDatabaseComponent.java b/components/net/sf/briar/db/ReadWriteLockDatabaseComponent.java
index b4b3bfeeb9b312b89403c3b4a09090c80d91390c..f7c50d561935120326e6bca2044fdf38ee9d03ea 100644
--- a/components/net/sf/briar/db/ReadWriteLockDatabaseComponent.java
+++ b/components/net/sf/briar/db/ReadWriteLockDatabaseComponent.java
@@ -909,28 +909,33 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
 		if(LOG.isLoggable(Level.FINE)) LOG.fine("Removing contact " + c);
 		contactLock.writeLock().lock();
 		try {
-			messageStatusLock.writeLock().lock();
+			messageLock.writeLock().lock();
 			try {
-				subscriptionLock.writeLock().lock();
+				messageStatusLock.writeLock().lock();
 				try {
-					transportLock.writeLock().lock();
+					subscriptionLock.writeLock().lock();
 					try {
-						Txn txn = db.startTransaction();
+						transportLock.writeLock().lock();
 						try {
-							db.removeContact(txn, c);
-							db.commitTransaction(txn);
-						} catch(DbException e) {
-							db.abortTransaction(txn);
-							throw e;
+							Txn txn = db.startTransaction();
+							try {
+								db.removeContact(txn, c);
+								db.commitTransaction(txn);
+							} catch(DbException e) {
+								db.abortTransaction(txn);
+								throw e;
+							}
+						} finally {
+							transportLock.writeLock().unlock();
 						}
 					} finally {
-						transportLock.writeLock().unlock();
+						subscriptionLock.writeLock().unlock();
 					}
 				} finally {
-					subscriptionLock.writeLock().unlock();
+					messageStatusLock.writeLock().unlock();
 				}
 			} finally {
-				messageStatusLock.writeLock().unlock();
+				messageLock.writeLock().unlock();
 			}
 		} finally {
 			contactLock.writeLock().unlock();
diff --git a/components/net/sf/briar/db/SynchronizedDatabaseComponent.java b/components/net/sf/briar/db/SynchronizedDatabaseComponent.java
index 4c7728f021db87acbfad11bfa8fa2ff6cb918550..df3fccd33df8d19d139e6b2fe1280db5ba0a8fe9 100644
--- a/components/net/sf/briar/db/SynchronizedDatabaseComponent.java
+++ b/components/net/sf/briar/db/SynchronizedDatabaseComponent.java
@@ -689,16 +689,18 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
 	public void removeContact(ContactId c) throws DbException {
 		if(LOG.isLoggable(Level.FINE)) LOG.fine("Removing contact " + c);
 		synchronized(contactLock) {
-			synchronized(messageStatusLock) {
-				synchronized(subscriptionLock) {
-					synchronized(transportLock) {
-						Txn txn = db.startTransaction();
-						try {
-							db.removeContact(txn, c);
-							db.commitTransaction(txn);
-						} catch(DbException e) {
-							db.abortTransaction(txn);
-							throw e;
+			synchronized(messageLock) {
+				synchronized(messageStatusLock) {
+					synchronized(subscriptionLock) {
+						synchronized(transportLock) {
+							Txn txn = db.startTransaction();
+							try {
+								db.removeContact(txn, c);
+								db.commitTransaction(txn);
+							} catch(DbException e) {
+								db.abortTransaction(txn);
+								throw e;
+							}
 						}
 					}
 				}
diff --git a/test/net/sf/briar/db/DatabaseComponentTest.java b/test/net/sf/briar/db/DatabaseComponentTest.java
index ef0cc020fb708c4cd9fb7d12cca969d2c27fe885..a90b64e5b958a6439d7fc453eeeb1fba6b6a397a 100644
--- a/test/net/sf/briar/db/DatabaseComponentTest.java
+++ b/test/net/sf/briar/db/DatabaseComponentTest.java
@@ -367,7 +367,7 @@ public abstract class DatabaseComponentTest extends TestCase {
 		final Database<Object> database = context.mock(Database.class);
 		final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
 		context.checking(new Expectations() {{
-			// addLocallyGeneratedMessage(message)
+			// addLocalGroupMessage(message)
 			oneOf(database).startTransaction();
 			will(returnValue(txn));
 			oneOf(database).containsSubscription(txn, groupId, timestamp);
@@ -388,12 +388,12 @@ public abstract class DatabaseComponentTest extends TestCase {
 		final Database<Object> database = context.mock(Database.class);
 		final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
 		context.checking(new Expectations() {{
-			// addLocallyGeneratedMessage(message)
+			// addLocalGroupMessage(message)
 			oneOf(database).startTransaction();
 			will(returnValue(txn));
 			oneOf(database).containsSubscription(txn, groupId, timestamp);
 			will(returnValue(true));
-			oneOf(database).addMessage(txn, message);
+			oneOf(database).addGroupMessage(txn, message);
 			will(returnValue(false));
 			oneOf(database).commitTransaction(txn);
 		}});
@@ -405,18 +405,18 @@ public abstract class DatabaseComponentTest extends TestCase {
 	}
 
 	@Test
-	public void testAddLocallyGeneratedMessage() throws DbException {
+	public void testAddLocalGroupMessage() throws DbException {
 		Mockery context = new Mockery();
 		@SuppressWarnings("unchecked")
 		final Database<Object> database = context.mock(Database.class);
 		final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
 		context.checking(new Expectations() {{
-			// addLocallyGeneratedMessage(message)
+			// addLocalGroupMessage(message)
 			oneOf(database).startTransaction();
 			will(returnValue(txn));
 			oneOf(database).containsSubscription(txn, groupId, timestamp);
 			will(returnValue(true));
-			oneOf(database).addMessage(txn, message);
+			oneOf(database).addGroupMessage(txn, message);
 			will(returnValue(true));
 			oneOf(database).getContacts(txn);
 			will(returnValue(Collections.singletonList(contactId)));
@@ -444,12 +444,12 @@ public abstract class DatabaseComponentTest extends TestCase {
 		final Database<Object> database = context.mock(Database.class);
 		final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
 		context.checking(new Expectations() {{
-			// addLocallyGeneratedMessage(message)
+			// addLocalGroupMessage(message)
 			oneOf(database).startTransaction();
 			will(returnValue(txn));
 			oneOf(database).containsSubscription(txn, groupId, timestamp);
 			will(returnValue(true));
-			oneOf(database).addMessage(txn, message);
+			oneOf(database).addGroupMessage(txn, message);
 			will(returnValue(true));
 			oneOf(database).getContacts(txn);
 			will(returnValue(Collections.singletonList(contactId)));
@@ -896,7 +896,7 @@ public abstract class DatabaseComponentTest extends TestCase {
 					contactId, timestamp);
 			will(returnValue(true));
 			// The message is stored, but it's a duplicate
-			oneOf(database).addMessage(txn, message);
+			oneOf(database).addGroupMessage(txn, message);
 			will(returnValue(false));
 			oneOf(database).setStatus(txn, contactId, messageId, Status.SEEN);
 			// The batch needs to be acknowledged
@@ -931,7 +931,7 @@ public abstract class DatabaseComponentTest extends TestCase {
 					contactId, timestamp);
 			will(returnValue(true));
 			// The message is stored, and it's not a duplicate
-			oneOf(database).addMessage(txn, message);
+			oneOf(database).addGroupMessage(txn, message);
 			will(returnValue(true));
 			oneOf(database).setStatus(txn, contactId, messageId, Status.SEEN);
 			// Set the status to NEW for all other contacts (there are none)
@@ -975,7 +975,7 @@ public abstract class DatabaseComponentTest extends TestCase {
 					contactId, timestamp);
 			will(returnValue(true));
 			// The message is stored, and it's not a duplicate
-			oneOf(database).addMessage(txn, message);
+			oneOf(database).addGroupMessage(txn, message);
 			will(returnValue(true));
 			oneOf(database).setStatus(txn, contactId, messageId, Status.SEEN);
 			// Set the status to NEW for all other contacts (there are none)
@@ -1110,12 +1110,12 @@ public abstract class DatabaseComponentTest extends TestCase {
 		final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
 		final DatabaseListener listener = context.mock(DatabaseListener.class);
 		context.checking(new Expectations() {{
-			// addLocallyGeneratedMessage(message)
+			// addLocalGroupMessage(message)
 			oneOf(database).startTransaction();
 			will(returnValue(txn));
 			oneOf(database).containsSubscription(txn, groupId, timestamp);
 			will(returnValue(true));
-			oneOf(database).addMessage(txn, message);
+			oneOf(database).addGroupMessage(txn, message);
 			will(returnValue(true));
 			oneOf(database).getContacts(txn);
 			will(returnValue(Collections.singletonList(contactId)));
@@ -1145,12 +1145,12 @@ public abstract class DatabaseComponentTest extends TestCase {
 		final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
 		final DatabaseListener listener = context.mock(DatabaseListener.class);
 		context.checking(new Expectations() {{
-			// addLocallyGeneratedMessage(message)
+			// addLocalGroupMessage(message)
 			oneOf(database).startTransaction();
 			will(returnValue(txn));
 			oneOf(database).containsSubscription(txn, groupId, timestamp);
 			will(returnValue(true));
-			oneOf(database).addMessage(txn, message);
+			oneOf(database).addGroupMessage(txn, message);
 			will(returnValue(false));
 			oneOf(database).commitTransaction(txn);
 			// The message was not added, so the listener should not be called
diff --git a/test/net/sf/briar/db/H2DatabaseTest.java b/test/net/sf/briar/db/H2DatabaseTest.java
index 0698f8e1375725f586a49465f1b910754fd95b8d..09e8c52f3efc75a8554b70a3faadc77b0cf9ad7c 100644
--- a/test/net/sf/briar/db/H2DatabaseTest.java
+++ b/test/net/sf/briar/db/H2DatabaseTest.java
@@ -110,7 +110,7 @@ public class H2DatabaseTest extends TestCase {
 		db.addSubscription(txn, group);
 		assertTrue(db.containsSubscription(txn, groupId));
 		assertFalse(db.containsMessage(txn, messageId));
-		db.addMessage(txn, message);
+		db.addGroupMessage(txn, message);
 		assertTrue(db.containsMessage(txn, messageId));
 		db.commitTransaction(txn);
 		db.close();
@@ -195,7 +195,7 @@ public class H2DatabaseTest extends TestCase {
 
 		// Subscribe to a group and store a message
 		db.addSubscription(txn, group);
-		db.addMessage(txn, message);
+		db.addGroupMessage(txn, message);
 
 		// Unsubscribing from the group should delete the message
 		assertTrue(db.containsMessage(txn, messageId));
@@ -216,7 +216,7 @@ public class H2DatabaseTest extends TestCase {
 		db.addSubscription(txn, group);
 		db.setVisibility(txn, groupId, Collections.singleton(contactId));
 		db.setSubscriptions(txn, contactId, subscriptions, 1);
-		db.addMessage(txn, message);
+		db.addGroupMessage(txn, message);
 		db.setStatus(txn, contactId, messageId, Status.NEW);
 
 		// The message should not be sendable
@@ -254,7 +254,7 @@ public class H2DatabaseTest extends TestCase {
 		db.addSubscription(txn, group);
 		db.setVisibility(txn, groupId, Collections.singleton(contactId));
 		db.setSubscriptions(txn, contactId, subscriptions, 1);
-		db.addMessage(txn, message);
+		db.addGroupMessage(txn, message);
 		db.setSendability(txn, messageId, 1);
 
 		// The message has no status yet, so it should not be sendable
@@ -295,7 +295,7 @@ public class H2DatabaseTest extends TestCase {
 		assertEquals(contactId, db.addContact(txn, transports, secret));
 		db.addSubscription(txn, group);
 		db.setVisibility(txn, groupId, Collections.singleton(contactId));
-		db.addMessage(txn, message);
+		db.addGroupMessage(txn, message);
 		db.setSendability(txn, messageId, 1);
 		db.setStatus(txn, contactId, messageId, Status.NEW);
 
@@ -334,7 +334,7 @@ public class H2DatabaseTest extends TestCase {
 		assertEquals(contactId, db.addContact(txn, transports, secret));
 		db.addSubscription(txn, group);
 		db.setVisibility(txn, groupId, Collections.singleton(contactId));
-		db.addMessage(txn, message);
+		db.addGroupMessage(txn, message);
 		db.setSendability(txn, messageId, 1);
 		db.setStatus(txn, contactId, messageId, Status.NEW);
 
@@ -370,7 +370,7 @@ public class H2DatabaseTest extends TestCase {
 		db.addSubscription(txn, group);
 		db.setVisibility(txn, groupId, Collections.singleton(contactId));
 		db.setSubscriptions(txn, contactId, subscriptions, 1);
-		db.addMessage(txn, message);
+		db.addGroupMessage(txn, message);
 		db.setSendability(txn, messageId, 1);
 		db.setStatus(txn, contactId, messageId, Status.NEW);
 
@@ -400,7 +400,7 @@ public class H2DatabaseTest extends TestCase {
 		assertEquals(contactId, db.addContact(txn, transports, secret));
 		db.addSubscription(txn, group);
 		db.setSubscriptions(txn, contactId, subscriptions, 1);
-		db.addMessage(txn, message);
+		db.addGroupMessage(txn, message);
 		db.setSendability(txn, messageId, 1);
 		db.setStatus(txn, contactId, messageId, Status.NEW);
 
@@ -485,7 +485,7 @@ public class H2DatabaseTest extends TestCase {
 		// Add a contact, subscribe to a group and store a message
 		assertEquals(contactId, db.addContact(txn, transports, secret));
 		db.addSubscription(txn, group);
-		db.addMessage(txn, message);
+		db.addGroupMessage(txn, message);
 
 		// Add an outstanding batch
 		db.addOutstandingBatch(txn, contactId, batchId,
@@ -511,7 +511,7 @@ public class H2DatabaseTest extends TestCase {
 		assertEquals(contactId, db.addContact(txn, transports, secret));
 		ContactId contactId1 = db.addContact(txn, transports, secret);
 		db.addSubscription(txn, group);
-		db.addMessage(txn, message);
+		db.addGroupMessage(txn, message);
 
 		// Add an outstanding batch for the first contact
 		db.addOutstandingBatch(txn, contactId, batchId,
@@ -535,7 +535,7 @@ public class H2DatabaseTest extends TestCase {
 		db.addSubscription(txn, group);
 		db.setVisibility(txn, groupId, Collections.singleton(contactId));
 		db.setSubscriptions(txn, contactId, subscriptions, 1);
-		db.addMessage(txn, message);
+		db.addGroupMessage(txn, message);
 		db.setSendability(txn, messageId, 1);
 		db.setStatus(txn, contactId, messageId, Status.NEW);
 
@@ -572,7 +572,7 @@ public class H2DatabaseTest extends TestCase {
 		db.addSubscription(txn, group);
 		db.setVisibility(txn, groupId, Collections.singleton(contactId));
 		db.setSubscriptions(txn, contactId, subscriptions, 1);
-		db.addMessage(txn, message);
+		db.addGroupMessage(txn, message);
 		db.setSendability(txn, messageId, 1);
 		db.setStatus(txn, contactId, messageId, Status.NEW);
 
@@ -682,8 +682,8 @@ public class H2DatabaseTest extends TestCase {
 
 		// Subscribe to a group and store two messages
 		db.addSubscription(txn, group);
-		db.addMessage(txn, message);
-		db.addMessage(txn, message1);
+		db.addGroupMessage(txn, message);
+		db.addGroupMessage(txn, message1);
 
 		// Check that each message is retrievable via its author
 		Iterator<MessageId> it =
@@ -721,10 +721,10 @@ public class H2DatabaseTest extends TestCase {
 		// Subscribe to the groups and store the messages
 		db.addSubscription(txn, group);
 		db.addSubscription(txn, group1);
-		db.addMessage(txn, message);
-		db.addMessage(txn, child1);
-		db.addMessage(txn, child2);
-		db.addMessage(txn, child3);
+		db.addGroupMessage(txn, message);
+		db.addGroupMessage(txn, child1);
+		db.addGroupMessage(txn, child2);
+		db.addGroupMessage(txn, child3);
 		// Make all the children sendable
 		db.setSendability(txn, childId1, 1);
 		db.setSendability(txn, childId2, 5);
@@ -751,8 +751,8 @@ public class H2DatabaseTest extends TestCase {
 
 		// Subscribe to a group and store two messages
 		db.addSubscription(txn, group);
-		db.addMessage(txn, message);
-		db.addMessage(txn, message1);
+		db.addGroupMessage(txn, message);
+		db.addGroupMessage(txn, message1);
 
 		// Allowing enough capacity for one message should return the older one
 		Iterator<MessageId> it = db.getOldMessages(txn, size).iterator();
@@ -789,7 +789,7 @@ public class H2DatabaseTest extends TestCase {
 		// Storing a message should reduce the free space
 		Connection txn = db.startTransaction();
 		db.addSubscription(txn, group);
-		db.addMessage(txn, message1);
+		db.addGroupMessage(txn, message1);
 		db.commitTransaction(txn);
 		assertTrue(db.getFreeSpace() < free);
 
@@ -1036,7 +1036,7 @@ public class H2DatabaseTest extends TestCase {
 		assertEquals(contactId, db.addContact(txn, transports, secret));
 		db.addSubscription(txn, group);
 		db.setSubscriptions(txn, contactId, subscriptions, 1);
-		db.addMessage(txn, message);
+		db.addGroupMessage(txn, message);
 		// Set the sendability to > 0
 		db.setSendability(txn, messageId, 1);
 		// Set the status to SEEN
@@ -1059,7 +1059,7 @@ public class H2DatabaseTest extends TestCase {
 		assertEquals(contactId, db.addContact(txn, transports, secret));
 		db.addSubscription(txn, group);
 		db.setSubscriptions(txn, contactId, subscriptions, 1);
-		db.addMessage(txn, message);
+		db.addGroupMessage(txn, message);
 		// Set the sendability to 0
 		db.setSendability(txn, messageId, 0);
 		// Set the status to NEW
@@ -1084,7 +1084,7 @@ public class H2DatabaseTest extends TestCase {
 		// The message is older than the contact's subscription
 		Map<Group, Long> subs = Collections.singletonMap(group, timestamp + 1);
 		db.setSubscriptions(txn, contactId, subs, 1);
-		db.addMessage(txn, message);
+		db.addGroupMessage(txn, message);
 		// Set the sendability to > 0
 		db.setSendability(txn, messageId, 1);
 		// Set the status to NEW
@@ -1107,7 +1107,7 @@ public class H2DatabaseTest extends TestCase {
 		db.addSubscription(txn, group);
 		db.setVisibility(txn, groupId, Collections.singleton(contactId));
 		db.setSubscriptions(txn, contactId, subscriptions, 1);
-		db.addMessage(txn, message);
+		db.addGroupMessage(txn, message);
 		// Set the sendability to > 0
 		db.setSendability(txn, messageId, 1);
 		// Set the status to NEW
@@ -1166,7 +1166,7 @@ public class H2DatabaseTest extends TestCase {
 		// Add a contact, subscribe to a group and store a message
 		assertEquals(contactId, db.addContact(txn, transports, secret));
 		db.addSubscription(txn, group);
-		db.addMessage(txn, message);
+		db.addGroupMessage(txn, message);
 		db.setStatus(txn, contactId, messageId, Status.NEW);
 
 		// There's no contact subscription for the group
@@ -1185,7 +1185,7 @@ public class H2DatabaseTest extends TestCase {
 		// Add a contact, subscribe to a group and store a message
 		assertEquals(contactId, db.addContact(txn, transports, secret));
 		db.addSubscription(txn, group);
-		db.addMessage(txn, message);
+		db.addGroupMessage(txn, message);
 		db.setSubscriptions(txn, contactId, subscriptions, 1);
 		db.setStatus(txn, contactId, messageId, Status.NEW);
 
@@ -1207,7 +1207,7 @@ public class H2DatabaseTest extends TestCase {
 		db.addSubscription(txn, group);
 		db.setVisibility(txn, groupId, Collections.singleton(contactId));
 		db.setSubscriptions(txn, contactId, subscriptions, 1);
-		db.addMessage(txn, message);
+		db.addGroupMessage(txn, message);
 		// The message has already been seen by the contact
 		db.setStatus(txn, contactId, messageId, Status.SEEN);
 
@@ -1228,7 +1228,7 @@ public class H2DatabaseTest extends TestCase {
 		db.addSubscription(txn, group);
 		db.setVisibility(txn, groupId, Collections.singleton(contactId));
 		db.setSubscriptions(txn, contactId, subscriptions, 1);
-		db.addMessage(txn, message);
+		db.addGroupMessage(txn, message);
 		// The message has not been seen by the contact
 		db.setStatus(txn, contactId, messageId, Status.NEW);