mirror of
https://github.com/bisq-network/bisq.git
synced 2025-02-24 15:10:44 +01:00
Add payload safety checks in ProtectedStorageEntry
It is currently possible to construct a valid Payload object that implements both the ProtectedStoragePayload and PersistableNetworkPayload interfaces even though this combination is invalid. Instead of depending on future reviewers to catch an error, assert that ProtectedStoragePayloads and PersistableNetworkPayloads are incompatible as objects inside a ProtectedStorageEntry. This allows cleanup of removeExpiredEntries that branched on this behavior.
This commit is contained in:
parent
c81f8a6da3
commit
bdef1e46ea
5 changed files with 59 additions and 7 deletions
|
@ -192,11 +192,9 @@ public class P2PDataStorage implements MessageListener, ConnectionListener, Pers
|
|||
.forEach(entry -> {
|
||||
ByteArray hashOfPayload = entry.getKey();
|
||||
ProtectedStorageEntry protectedStorageEntry = map.get(hashOfPayload);
|
||||
if (!(protectedStorageEntry.getProtectedStoragePayload() instanceof PersistableNetworkPayload)) {
|
||||
toRemoveSet.add(protectedStorageEntry);
|
||||
log.debug("We found an expired data entry. We remove the protectedData:\n\t" + Utilities.toTruncatedString(protectedStorageEntry));
|
||||
map.remove(hashOfPayload);
|
||||
}
|
||||
toRemoveSet.add(protectedStorageEntry);
|
||||
log.debug("We found an expired data entry. We remove the protectedData:\n\t" + Utilities.toTruncatedString(protectedStorageEntry));
|
||||
map.remove(hashOfPayload);
|
||||
});
|
||||
|
||||
// Batch processing can cause performance issues, so we give listeners a chance to deal with it by notifying
|
||||
|
@ -570,7 +568,7 @@ public class P2PDataStorage implements MessageListener, ConnectionListener, Pers
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void maybeAddToRemoveAddOncePayloads(ProtectedStoragePayload protectedStoragePayload,
|
||||
ByteArray hashOfData) {
|
||||
if (protectedStoragePayload instanceof AddOncePayload) {
|
||||
|
|
|
@ -29,6 +29,8 @@ import bisq.common.util.Utilities;
|
|||
import com.google.protobuf.ByteString;
|
||||
import com.google.protobuf.Message;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
|
||||
import java.security.PublicKey;
|
||||
|
||||
import java.time.Clock;
|
||||
|
@ -70,6 +72,8 @@ public class ProtectedStorageEntry implements NetworkPayload, PersistablePayload
|
|||
long creationTimeStamp,
|
||||
Clock clock) {
|
||||
|
||||
Preconditions.checkArgument(!(protectedStoragePayload instanceof PersistableNetworkPayload));
|
||||
|
||||
this.protectedStoragePayload = protectedStoragePayload;
|
||||
this.ownerPubKeyBytes = ownerPubKeyBytes;
|
||||
this.ownerPubKey = ownerPubKey;
|
||||
|
|
|
@ -20,7 +20,9 @@ package bisq.network.p2p.storage;
|
|||
import bisq.network.p2p.TestUtils;
|
||||
import bisq.network.p2p.storage.mocks.ExpirableProtectedStoragePayloadStub;
|
||||
import bisq.network.p2p.storage.mocks.PersistableExpirableProtectedStoragePayloadStub;
|
||||
import bisq.network.p2p.storage.mocks.PersistableNetworkPayloadStub;
|
||||
import bisq.network.p2p.storage.mocks.ProtectedStoragePayloadStub;
|
||||
import bisq.network.p2p.storage.payload.PersistableNetworkPayload;
|
||||
import bisq.network.p2p.storage.payload.ProtectedStorageEntry;
|
||||
import bisq.network.p2p.storage.payload.ProtectedStoragePayload;
|
||||
|
||||
|
@ -67,6 +69,18 @@ public class P2PDataStorageRemoveExpiredTest {
|
|||
this.testState.verifyProtectedStorageRemove(beforeState, protectedStorageEntry, false, false, false, false);
|
||||
}
|
||||
|
||||
// TESTCASE: Correctly skips all PersistableNetworkPayloads since they are not expirable
|
||||
@Test
|
||||
public void removeExpiredEntries_skipsPersistableNetworkPayload() {
|
||||
PersistableNetworkPayload persistableNetworkPayload = new PersistableNetworkPayloadStub(true);
|
||||
|
||||
Assert.assertTrue(this.testState.mockedStorage.addPersistableNetworkPayload(persistableNetworkPayload,getTestNodeAddress(), true, true, false, false));
|
||||
|
||||
this.testState.mockedStorage.removeExpiredEntries();
|
||||
|
||||
Assert.assertTrue(this.testState.mockedStorage.getAppendOnlyDataStoreMap().containsKey(new P2PDataStorage.ByteArray(persistableNetworkPayload.getHash())));
|
||||
}
|
||||
|
||||
// TESTCASE: Correctly skips non-persistable entries that are not expired
|
||||
@Test
|
||||
public void removeExpiredEntries_SkipNonExpiredExpirableEntries() throws CryptoException, NoSuchAlgorithmException {
|
||||
|
|
|
@ -45,7 +45,7 @@ public class ProtectedStoragePayloadStub implements ProtectedStoragePayload {
|
|||
@Getter
|
||||
private PublicKey ownerPubKey;
|
||||
|
||||
private Message messageMock;
|
||||
protected Message messageMock;
|
||||
|
||||
public ProtectedStoragePayloadStub(PublicKey ownerPubKey) {
|
||||
this.ownerPubKey = ownerPubKey;
|
||||
|
|
|
@ -213,4 +213,40 @@ public class ProtectedStorageEntryTest {
|
|||
|
||||
Assert.assertFalse(protectedStorageEntryOne.matchesRelevantPubKey(protectedStorageEntryTwo));
|
||||
}
|
||||
|
||||
// TESTCASE: Payload implementing ProtectedStoragePayload & PersistableNetworkPayload is invalid
|
||||
// We rely on the fact that a payload is either a ProtectedStoragePayload OR PersistableNetworkPayload, but Java
|
||||
// does not have a clean way to specify mutually exclusive interfaces.
|
||||
//
|
||||
// We also want to guarantee that ONLY ProtectedStoragePayload objects are valid as payloads in
|
||||
// ProtectedStorageEntrys. This test will give a defense in case future development work breaks that expectation.
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void ProtectedStoragePayload_PersistableNetworkPayload_incompatible() throws NoSuchAlgorithmException {
|
||||
class IncompatiblePayload extends ProtectedStoragePayloadStub implements PersistableNetworkPayload {
|
||||
|
||||
private IncompatiblePayload(PublicKey ownerPubKey) {
|
||||
super(ownerPubKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getHash() {
|
||||
return new byte[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean verifyHashSize() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public protobuf.PersistableNetworkPayload toProtoMessage() {
|
||||
return (protobuf.PersistableNetworkPayload) this.messageMock;
|
||||
}
|
||||
}
|
||||
|
||||
KeyPair ownerKeys = TestUtils.generateKeyPair();
|
||||
IncompatiblePayload incompatiblePayload = new IncompatiblePayload(ownerKeys.getPublic());
|
||||
new ProtectedStorageEntry(incompatiblePayload,ownerKeys.getPublic(), 1,
|
||||
new byte[] { 0 }, Clock.systemDefaultZone());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue