Skip to content

Commit

Permalink
Merge pull request #766 from jpmorganchase/fix/remove-recipient-data-…
Browse files Browse the repository at this point in the history
…on-resend

Remove recipient data on resend
  • Loading branch information
Krish1979 authored May 29, 2019
2 parents 2265c52 + ae01204 commit 7e61c1e
Show file tree
Hide file tree
Showing 2 changed files with 112 additions and 10 deletions.
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
package com.quorum.tessera.transaction;

import com.quorum.tessera.api.model.*;
import com.quorum.tessera.enclave.Enclave;
import com.quorum.tessera.enclave.EnclaveException;
import com.quorum.tessera.enclave.EncodedPayload;
import com.quorum.tessera.enclave.PayloadEncoder;
import com.quorum.tessera.enclave.RawTransaction;
import com.quorum.tessera.enclave.*;
import com.quorum.tessera.enclave.model.MessageHash;
import com.quorum.tessera.enclave.model.MessageHashFactory;
import com.quorum.tessera.encryption.PublicKey;
Expand Down Expand Up @@ -183,6 +179,9 @@ public ResendResponse resend(ResendRequest request) {
final boolean isSender = Objects.equals(payload.getSenderKey(), recipientPublicKey);
return isRecipient || isSender;
}).forEach(payload -> {

final EncodedPayload prunedPayload;

if (Objects.equals(payload.getSenderKey(), recipientPublicKey)) {
final PublicKey decryptedKey = searchForRecipientKey(payload).orElseThrow(
() -> {
Expand All @@ -192,10 +191,15 @@ public ResendResponse resend(ResendRequest request) {
}
);
payload.getRecipientKeys().add(decryptedKey);

// This payload does not need to be pruned as it was not sent by this node and so does not contain any other node's data
prunedPayload = payload;
} else {
prunedPayload = payloadEncoder.forRecipient(payload, recipientPublicKey);
}

try {
payloadPublisher.publishPayload(payload, recipientPublicKey);
payloadPublisher.publishPayload(prunedPayload, recipientPublicKey);
} catch (PublishPayloadException ex) {
LOGGER.warn("Unable to publish payload to recipient {} during resend", recipientPublicKey.encodeToBase64());
}
Expand Down Expand Up @@ -276,7 +280,7 @@ public ReceiveResponse receive(ReceiveRequest request) {

final MessageHash hash = new MessageHash(key);
LOGGER.info("Lookup transaction {}",hash);

final EncryptedTransaction encryptedTransaction = encryptedTransactionDAO
.retrieveByHash(hash)
.orElseThrow(() -> new TransactionNotFoundException("Message with hash " + hash + " was not found"));
Expand Down Expand Up @@ -327,7 +331,7 @@ public StoreRawResponse store(StoreRawRequest storeRequest) {

return new StoreRawResponse(encryptedRawTransaction.getHash().getHashBytes());
}





}
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ public void resendAllWhereRequestedIsSenderAndRecipientExists() {
verify(payloadPublisher).publishPayload(any(EncodedPayload.class), eq(senderKey));
verify(enclave).getPublicKeys();
verify(enclave).unencryptTransaction(payload, recipientKey);
verify(payloadEncoder, never()).forRecipient(any(EncodedPayload.class), any(PublicKey.class));
}

@Test
Expand Down Expand Up @@ -272,6 +273,7 @@ public void resendAllWhereRequestedIsRecipient() {

when(encryptedTransactionDAO.retrieveAllTransactions()).thenReturn(singletonList(tx));
when(payloadEncoder.decode(any(byte[].class))).thenReturn(payload);
when(payloadEncoder.forRecipient(payload, recipientKey)).thenReturn(payload);

final ResendRequest resendRequest = new ResendRequest();
resendRequest.setPublicKey(recipientKey.encodeToBase64());
Expand All @@ -283,9 +285,94 @@ public void resendAllWhereRequestedIsRecipient() {

verify(encryptedTransactionDAO).retrieveAllTransactions();
verify(payloadEncoder).decode(encodedData);
verify(payloadEncoder).forRecipient(payload, recipientKey);
verify(payloadPublisher).publishPayload(any(EncodedPayload.class), eq(recipientKey));
}

@Test
public void resendAllWhereRequestedIsRecipientThenPublishedPayloadDoesNotContainDataForOtherRecipients() {

final byte[] encodedData = "transaction".getBytes();
final EncryptedTransaction tx = new EncryptedTransaction(mock(MessageHash.class), encodedData);
final EncodedPayload payload = mock(EncodedPayload.class);

final List<PublicKey> recipients = new ArrayList<>();
final PublicKey recipientKey = PublicKey.from("RECIPIENTKEY".getBytes());
final PublicKey anotherRecipient = PublicKey.from("ANOTHERRECIPIENT".getBytes());
recipients.add(recipientKey);
recipients.add(anotherRecipient);

final List<byte[]> recipientBoxes = new ArrayList<>();
final byte[] recipientBox = "box1".getBytes();
final byte[] anotherRecipientBox = "box2".getBytes();
recipientBoxes.add(recipientBox);
recipientBoxes.add(anotherRecipientBox);

when(payload.getRecipientKeys()).thenReturn(recipients);
when(payload.getRecipientBoxes()).thenReturn(recipientBoxes);

when(encryptedTransactionDAO.retrieveAllTransactions()).thenReturn(singletonList(tx));
when(payloadEncoder.decode(any(byte[].class))).thenReturn(payload);

EncodedPayload prunedPayload = mock(EncodedPayload.class);
when(prunedPayload.getRecipientKeys()).thenReturn(singletonList(recipientKey));
when(prunedPayload.getRecipientBoxes()).thenReturn(singletonList(recipientBox));
when(payloadEncoder.forRecipient(payload, recipientKey)).thenReturn(prunedPayload);

final ResendRequest resendRequest = new ResendRequest();
resendRequest.setPublicKey(recipientKey.encodeToBase64());
resendRequest.setType(ResendRequestType.ALL);

ResendResponse result = transactionManager.resend(resendRequest);

assertThat(result).isNotNull();
verify(payloadPublisher).publishPayload(eq(prunedPayload), eq(recipientKey));

verify(encryptedTransactionDAO).retrieveAllTransactions();
verify(payloadEncoder).forRecipient(payload, recipientKey);
verify(payloadEncoder).decode(encodedData);
}

@Test
public void resendAllWhereRequestedIsSenderThenPublishedPayloadIsNotPruned() {

final byte[] encodedData = "transaction".getBytes();
final EncryptedTransaction tx = new EncryptedTransaction(mock(MessageHash.class), encodedData);
final EncodedPayload payload = mock(EncodedPayload.class);

final List<byte[]> recipientBoxes = new ArrayList<>();
final byte[] recipientBox = "box1".getBytes();
recipientBoxes.add(recipientBox);

final PublicKey localKey = PublicKey.from("LOCAL_KEY".getBytes());
final PublicKey senderKey = PublicKey.from("SENDER".getBytes());

final List<PublicKey> recipients = new ArrayList<>();

when(payload.getSenderKey()).thenReturn(senderKey);
when(payload.getRecipientKeys()).thenReturn(recipients);
when(payload.getRecipientBoxes()).thenReturn(recipientBoxes);

when(encryptedTransactionDAO.retrieveAllTransactions()).thenReturn(singletonList(tx));
when(payloadEncoder.decode(any(byte[].class))).thenReturn(payload);
when(enclave.getPublicKeys()).thenReturn(singleton(localKey));

final ResendRequest resendRequest = new ResendRequest();
resendRequest.setPublicKey(senderKey.encodeToBase64());
resendRequest.setType(ResendRequestType.ALL);

ResendResponse result = transactionManager.resend(resendRequest);

assertThat(result).isNotNull();
verify(payloadPublisher).publishPayload(eq(payload), eq(senderKey));
verify(payloadEncoder, never()).forRecipient(any(EncodedPayload.class), any(PublicKey.class));

verify(encryptedTransactionDAO).retrieveAllTransactions();
verify(payloadEncoder).decode(encodedData);
verify(enclave).getPublicKeys();
verify(enclave).unencryptTransaction(payload, localKey);
}

@Test
public void resendAllWhereRequestedIsSenderAndRecipientDoesntExist() {

Expand Down Expand Up @@ -339,13 +426,16 @@ public void resendAllWithOnePayloadAndOneRecipientThenPublishPayloadExceptionIsC
when(resendRequest.getPublicKey()).thenReturn(publicKeyEncoded);
when(resendRequest.getType()).thenReturn(ResendRequestType.ALL);

when(payloadEncoder.forRecipient(eq(encodedPayload), any(PublicKey.class))).thenReturn(encodedPayload);

doThrow(new PublishPayloadException("msg"))
.when(payloadPublisher).publishPayload(encodedPayload, publicKey);

transactionManager.resend(resendRequest);

verify(payloadPublisher).publishPayload(encodedPayload, publicKey);
verify(payloadEncoder).decode(any(byte[].class));
verify(payloadEncoder).forRecipient(any(EncodedPayload.class), any(PublicKey.class));
verify(encryptedTransactionDAO).retrieveAllTransactions();

}
Expand Down Expand Up @@ -378,6 +468,9 @@ public void resendAllIfTwoPayloadsAndFirstThrowsExceptionThenSecondIsStillPublis
when(resendRequest.getPublicKey()).thenReturn(publicKeyEncoded);
when(resendRequest.getType()).thenReturn(ResendRequestType.ALL);

when(payloadEncoder.forRecipient(eq(encodedPayload), any(PublicKey.class))).thenReturn(encodedPayload);
when(payloadEncoder.forRecipient(eq(otherEncodedPayload), any(PublicKey.class))).thenReturn(otherEncodedPayload);

doThrow(new PublishPayloadException("msg"))
.when(payloadPublisher).publishPayload(encodedPayload, publicKey);

Expand All @@ -386,6 +479,7 @@ public void resendAllIfTwoPayloadsAndFirstThrowsExceptionThenSecondIsStillPublis
verify(payloadPublisher).publishPayload(encodedPayload, publicKey);
verify(payloadPublisher).publishPayload(otherEncodedPayload, publicKey);
verify(payloadEncoder, times(2)).decode(any(byte[].class));
verify(payloadEncoder, times(2)).forRecipient(any(EncodedPayload.class), any(PublicKey.class));
verify(encryptedTransactionDAO).retrieveAllTransactions();
}

Expand Down Expand Up @@ -413,6 +507,9 @@ public void resendAllTwoPayloadsAndTwoRecipientsAllThrowExceptionButAllStillPubl
when(encodedPayload.getRecipientKeys()).thenReturn(Collections.singletonList(publicKey));
when(otherEncodedPayload.getRecipientKeys()).thenReturn(Collections.singletonList(publicKey));

when(payloadEncoder.forRecipient(encodedPayload, publicKey)).thenReturn(encodedPayload);
when(payloadEncoder.forRecipient(otherEncodedPayload, publicKey)).thenReturn(otherEncodedPayload);

ResendRequest resendRequest = mock(ResendRequest.class);
when(resendRequest.getPublicKey()).thenReturn(publicKeyEncoded);
when(resendRequest.getType()).thenReturn(ResendRequestType.ALL);
Expand All @@ -429,6 +526,7 @@ public void resendAllTwoPayloadsAndTwoRecipientsAllThrowExceptionButAllStillPubl
verify(payloadPublisher).publishPayload(encodedPayload, publicKey);
verify(payloadPublisher).publishPayload(otherEncodedPayload, publicKey);
verify(payloadEncoder, times(2)).decode(any(byte[].class));
verify(payloadEncoder, times(2)).forRecipient(any(EncodedPayload.class), any(PublicKey.class));
verify(payloadPublisher, times(2)).publishPayload(any(EncodedPayload.class), any(PublicKey.class));
}

Expand Down Expand Up @@ -792,7 +890,7 @@ public void storeRawWithEmptySender() {

verify(enclave).encryptRawPayload(eq(payload), eq(PublicKey.from(sender)));
verify(enclave).defaultPublicKey();

verify(encryptedRawTransactionDAO).save(argThat(et -> {
assertThat(et.getEncryptedKey()).containsExactly("SomeKey".getBytes());
assertThat(et.getEncryptedPayload()).containsExactly("CIPHERTEXT".getBytes());
Expand Down

0 comments on commit 7e61c1e

Please sign in to comment.