diff --git a/briar-core/src/net/sf/briar/db/Database.java b/briar-core/src/net/sf/briar/db/Database.java
index f1031d7a9214628516aa8e1952473a51c212fea8..2c0987ef1ad0327618edc225ffd6f9a2cdba6075 100644
--- a/briar-core/src/net/sf/briar/db/Database.java
+++ b/briar-core/src/net/sf/briar/db/Database.java
@@ -715,23 +715,23 @@ interface Database<T> {
 
 	/**
 	 * Updates the remote transport properties for the given contact and the
-	 * given transport, replacing any existing properties, unless an update
-	 * with an equal or higher version number has already been received from
-	 * the contact.
+	 * given transport, replacing any existing properties, and returns true,
+	 * unless an update with an equal or higher version number has already been
+	 * received from the contact.
 	 * <p>
 	 * Locking: transport write.
 	 */
-	void setRemoteProperties(T txn, ContactId c, TransportId t,
+	boolean setRemoteProperties(T txn, ContactId c, TransportId t,
 			TransportProperties p, long version) throws DbException;
 
 	/**
-	 * Sets the retention time of the given contact's database, unless an
-	 * update with an equal or higher version number has already been received
-	 * from the contact.
+	 * Sets the retention time of the given contact's database and returns
+	 * true, unless an update with an equal or higher version number has
+	 * already been received from the contact.
 	 * <p>
 	 * Locking: retention write.
 	 */
-	void setRetentionTime(T txn, ContactId c, long retention, long version)
+	boolean setRetentionTime(T txn, ContactId c, long retention, long version)
 			throws DbException;
 
 	/**
@@ -761,17 +761,17 @@ interface Database<T> {
 			throws DbException;
 
 	/**
-	 * Updates the groups to which the given contact subscribes, unless an
-	 * update with an equal or higher version number has already been received
-	 * from the contact.
+	 * Updates the groups to which the given contact subscribes and returns
+	 * true, unless an update with an equal or higher version number has
+	 * already been received from the contact.
 	 * <p>
 	 * Locking: subscription write.
 	 */
-	void setSubscriptions(T txn, ContactId c, Collection<Group> subs,
+	boolean setSubscriptions(T txn, ContactId c, Collection<Group> subs,
 			long version) throws DbException;
 
 	/**
-	 * Records a retention ack from the given contact for the given version
+	 * Records a retention ack from the given contact for the given version,
 	 * unless the contact has already acked an equal or higher version.
 	 * <p>
 	 * Locking: retention write.
@@ -780,7 +780,7 @@ interface Database<T> {
 			throws DbException;
 
 	/**
-	 * Records a subscription ack from the given contact for the given version
+	 * Records a subscription ack from the given contact for the given version,
 	 * unless the contact has already acked an equal or higher version.
 	 * <p>
 	 * Locking: subscription write.
@@ -789,7 +789,7 @@ interface Database<T> {
 			throws DbException;
 
 	/**
-	 * Records a transport ack from the give contact for the given version
+	 * Records a transport ack from the give contact for the given version,
 	 * unless the contact has already acked an equal or higher version.
 	 * <p>
 	 * Locking: transport write.
diff --git a/briar-core/src/net/sf/briar/db/DatabaseComponentImpl.java b/briar-core/src/net/sf/briar/db/DatabaseComponentImpl.java
index 45568d4d61025c374818f49791a207c7c663b74c..4790da31fbc8ba81febeb858fe4254159d22cd6e 100644
--- a/briar-core/src/net/sf/briar/db/DatabaseComponentImpl.java
+++ b/briar-core/src/net/sf/briar/db/DatabaseComponentImpl.java
@@ -1613,6 +1613,7 @@ DatabaseCleaner.Callback {
 
 	public void receiveRetentionUpdate(ContactId c, RetentionUpdate u)
 			throws DbException {
+		boolean updated;
 		contactLock.readLock().lock();
 		try {
 			retentionLock.writeLock().lock();
@@ -1621,7 +1622,7 @@ DatabaseCleaner.Callback {
 				try {
 					if(!db.containsContact(txn, c))
 						throw new NoSuchContactException();
-					db.setRetentionTime(txn, c, u.getRetentionTime(),
+					updated = db.setRetentionTime(txn, c, u.getRetentionTime(),
 							u.getVersion());
 					db.commitTransaction(txn);
 				} catch(DbException e) {
@@ -1634,7 +1635,7 @@ DatabaseCleaner.Callback {
 		} finally {
 			contactLock.readLock().unlock();
 		}
-		callListeners(new RemoteRetentionTimeUpdatedEvent(c));
+		if(updated) callListeners(new RemoteRetentionTimeUpdatedEvent(c));
 	}
 
 	public void receiveSubscriptionAck(ContactId c, SubscriptionAck a)
@@ -1663,6 +1664,7 @@ DatabaseCleaner.Callback {
 
 	public void receiveSubscriptionUpdate(ContactId c, SubscriptionUpdate u)
 			throws DbException {
+		boolean updated;
 		contactLock.readLock().lock();
 		try {
 			subscriptionLock.writeLock().lock();
@@ -1671,7 +1673,9 @@ DatabaseCleaner.Callback {
 				try {
 					if(!db.containsContact(txn, c))
 						throw new NoSuchContactException();
-					db.setSubscriptions(txn, c, u.getGroups(), u.getVersion());
+					Collection<Group> groups = u.getGroups();
+					long version = u.getVersion();
+					updated = db.setSubscriptions(txn, c, groups, version);
 					db.commitTransaction(txn);
 				} catch(DbException e) {
 					db.abortTransaction(txn);
@@ -1683,7 +1687,7 @@ DatabaseCleaner.Callback {
 		} finally {
 			contactLock.readLock().unlock();
 		}
-		callListeners(new RemoteSubscriptionsUpdatedEvent(c));
+		if(updated) callListeners(new RemoteSubscriptionsUpdatedEvent(c));
 	}
 
 	public void receiveTransportAck(ContactId c, TransportAck a)
@@ -1715,6 +1719,7 @@ DatabaseCleaner.Callback {
 
 	public void receiveTransportUpdate(ContactId c, TransportUpdate u)
 			throws DbException {
+		boolean updated;
 		contactLock.readLock().lock();
 		try {
 			transportLock.writeLock().lock();
@@ -1723,8 +1728,10 @@ DatabaseCleaner.Callback {
 				try {
 					if(!db.containsContact(txn, c))
 						throw new NoSuchContactException();
-					db.setRemoteProperties(txn, c, u.getId(), u.getProperties(),
-							u.getVersion());
+					TransportId t = u.getId();
+					TransportProperties p = u.getProperties();
+					long version = u.getVersion();
+					updated = db.setRemoteProperties(txn, c, t, p, version);
 					db.commitTransaction(txn);
 				} catch(DbException e) {
 					db.abortTransaction(txn);
@@ -1736,7 +1743,8 @@ DatabaseCleaner.Callback {
 		} finally {
 			contactLock.readLock().unlock();
 		}
-		callListeners(new RemoteTransportsUpdatedEvent(c, u.getId()));
+		if(updated)
+			callListeners(new RemoteTransportsUpdatedEvent(c, u.getId()));
 	}
 
 	public void removeContact(ContactId c) throws DbException {
diff --git a/briar-tests/src/net/sf/briar/db/H2DatabaseTest.java b/briar-tests/src/net/sf/briar/db/H2DatabaseTest.java
index 1fae6c77fb45575705a90d1b040c721508d10733..aa0f778a3ddf9b14f9d982cfb8d4f23105a6eb74 100644
--- a/briar-tests/src/net/sf/briar/db/H2DatabaseTest.java
+++ b/briar-tests/src/net/sf/briar/db/H2DatabaseTest.java
@@ -839,21 +839,21 @@ public class H2DatabaseTest extends BriarTestCase {
 		// Initialise the transport properties with version 1
 		TransportProperties p = new TransportProperties(
 				Collections.singletonMap("foo", "bar"));
-		db.setRemoteProperties(txn, contactId, transportId, p, 1);
+		assertTrue(db.setRemoteProperties(txn, contactId, transportId, p, 1));
 		assertEquals(Collections.singletonMap(contactId, p),
 				db.getRemoteProperties(txn, transportId));
 
 		// Replace the transport properties with version 2
 		TransportProperties p1 = new TransportProperties(
 				Collections.singletonMap("baz", "bam"));
-		db.setRemoteProperties(txn, contactId, transportId, p1, 2);
+		assertTrue(db.setRemoteProperties(txn, contactId, transportId, p1, 2));
 		assertEquals(Collections.singletonMap(contactId, p1),
 				db.getRemoteProperties(txn, transportId));
 
 		// Try to replace the transport properties with version 1
 		TransportProperties p2 = new TransportProperties(
 				Collections.singletonMap("quux", "etc"));
-		db.setRemoteProperties(txn, contactId, transportId, p2, 1);
+		assertFalse(db.setRemoteProperties(txn, contactId, transportId, p2, 1));
 
 		// Version 2 of the properties should still be there
 		assertEquals(Collections.singletonMap(contactId, p1),