Skip to content

Commit

Permalink
Merge pull request #1329 from ConsenSys/get-mandatory-api
Browse files Browse the repository at this point in the history
Get mandatory api
  • Loading branch information
Krish1979 authored Sep 7, 2021
2 parents 475928f + 317621c commit dcbf6d6
Show file tree
Hide file tree
Showing 7 changed files with 123 additions and 1 deletion.
2 changes: 1 addition & 1 deletion security/src/main/java/module-info.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module tessera.security {
// requires java.base;
requires java.xml.bind;
// requires cryptacular;
requires cryptacular;
requires org.slf4j;
requires tessera.config;
requires tessera.shared;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import com.quorum.tessera.encryption.PublicKey;
import java.util.List;
import java.util.ServiceLoader;
import java.util.Set;

public interface TransactionManager {

Expand All @@ -27,6 +28,8 @@ public interface TransactionManager {

List<PublicKey> getParticipants(MessageHash transactionHash);

Set<PublicKey> getMandatoryRecipients(MessageHash transactionHash);

/**
* @see Enclave#defaultPublicKey()
* @return
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,12 @@ public List<PublicKey> getParticipants(final MessageHash transactionHash) {
return payload.getRecipientKeys();
}

@Override
public Set<PublicKey> getMandatoryRecipients(MessageHash transactionHash) {
final EncodedPayload payload = this.fetchPayload(transactionHash);
return payload.getMandatoryRecipients();
}

@Override
public PublicKey defaultPublicKey() {
return enclave.defaultPublicKey();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1717,6 +1717,35 @@ public void getParticipantsReturnsAllRecipients() {
verify(encryptedTransactionDAO).retrieveByHash(any(MessageHash.class));
}

@Test
public void getMandatoryRecipients() {

MessageHash transactionHash = mock(MessageHash.class);
when(transactionHash.getHashBytes()).thenReturn("DUMMY_TRANSACTION".getBytes());

final PublicKey senderKey = mock(PublicKey.class);
final PublicKey recipientKey = mock(PublicKey.class);

final byte[] input = "SOMEDATA".getBytes();
final EncryptedTransaction encryptedTransaction = mock(EncryptedTransaction.class);
final EncodedPayload encodedPayload = mock(EncodedPayload.class);
when(encodedPayload.getRecipientKeys()).thenReturn(List.of(senderKey, recipientKey));
when(encodedPayload.getMandatoryRecipients()).thenReturn(Set.of(recipientKey));
when(encryptedTransaction.getEncodedPayload()).thenReturn(input);

when(encryptedTransactionDAO.retrieveByHash(transactionHash))
.thenReturn(Optional.of(encryptedTransaction));

when(payloadEncoder.decode(input)).thenReturn(encodedPayload);

final Set<PublicKey> participants = transactionManager.getMandatoryRecipients(transactionHash);

assertThat(participants).containsExactly(recipientKey);

verify(payloadEncoder).decode(input);
verify(encryptedTransactionDAO).retrieveByHash(any(MessageHash.class));
}

@Test
public void defaultPublicKey() {
transactionManager.defaultPublicKey();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.quorum.tessera.q2t;

import static com.quorum.tessera.version.MandatoryRecipientsVersion.MIME_TYPE_JSON_4;
import static javax.ws.rs.core.MediaType.TEXT_PLAIN;

import com.quorum.tessera.api.SendRequest;
import com.quorum.tessera.api.SendResponse;
Expand All @@ -12,6 +13,12 @@
import com.quorum.tessera.encryption.PublicKey;
import com.quorum.tessera.privacygroup.PrivacyGroupManager;
import com.quorum.tessera.transaction.TransactionManager;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.ExampleObject;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.net.URI;
import java.net.URLEncoder;
Expand Down Expand Up @@ -232,4 +239,42 @@ public Response sendSignedTransaction(

return Response.created(location).entity(responseEntity).build();
}

@Operation(
summary = "/transaction/{hash}/mandatory",
operationId = "getMandatoryRecipients",
description = "get list of mandatory recipient public keys for a transaction")
@ApiResponse(
responseCode = "200",
description = "comma-separated list of mandatory recipients",
content =
@Content(
schema =
@Schema(
type = "string",
description = "comma-separated list of mandatory recipients"),
examples =
@ExampleObject(
"ROAZBWtSacxXQrOe3FGAqJDyJjFePR5ce4TSIzmJ0Bc=,BULeR8JyUWhiuuCMU/HLA0Q5pzkYT+cHII3ZKBey3Bo=")))
@GET
@Path("/transaction/{hash}/mandatory")
@Produces(TEXT_PLAIN)
public Response getMandatoryRecipients(
@Parameter(
description = "hash indicating encrypted payload to get mandatory recipients for",
schema = @Schema(format = "base64"))
@PathParam("hash")
final String ptmHash) {
LOGGER.debug("Received mandatory recipients list API request for key {}", ptmHash);

MessageHash transactionHash =
Optional.of(ptmHash).map(Base64.getDecoder()::decode).map(MessageHash::new).get();

final String mandatoryRecipients =
transactionManager.getMandatoryRecipients(transactionHash).stream()
.map(PublicKey::encodeToBase64)
.collect(Collectors.joining(","));

return Response.ok(mandatoryRecipients).build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import com.quorum.tessera.privacygroup.PrivacyGroupManager;
import com.quorum.tessera.transaction.TransactionManager;
import java.util.Base64;
import java.util.Set;
import javax.ws.rs.core.Response;
import org.junit.After;
import org.junit.Before;
Expand Down Expand Up @@ -160,4 +161,23 @@ public void sendSignedTransactionWithMandatoryRecipients() {
.containsExactlyInAnyOrder(base64AffectedHash1, base64AffectedHash2);
assertThat(obj.getMandatoryRecipients()).hasSize(1);
}

@Test
public void getMandatoryRecipients() {
byte[] data = "DUMMY_HASH".getBytes();

final String dummyPtmHash = Base64.getEncoder().encodeToString(data);

PublicKey recipient = mock(PublicKey.class);
when(recipient.encodeToBase64()).thenReturn("BASE64ENCODEDKEY");

when(transactionManager.getMandatoryRecipients(any(MessageHash.class)))
.thenReturn(Set.of(recipient));

Response response = transactionResource.getMandatoryRecipients(dummyPtmHash);

assertThat(response.getStatus()).isEqualTo(200);
assertThat(response.getEntity()).isEqualTo("BASE64ENCODEDKEY");
verify(transactionManager).getMandatoryRecipients(any(MessageHash.class));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,25 @@ public void sendTransactionWithMandatoryRecipients() throws UnsupportedEncodingE
EncodedPayload payloadC = PayloadEncoder.create().decode(payloadOnC);
assertThat(payloadC.getMandatoryRecipients())
.containsExactly(PublicKey.from(Base64.getDecoder().decode(c.getPublicKey())));

// Validate recipients data in Node C using /mandatory call

final String encodedHash = URLEncoder.encode(hash, UTF_8.toString());

final Response getMandatoryResponse =
c.getRestClient()
.target(c.getQ2TUri())
.path("/transaction")
.path(encodedHash)
.path("/mandatory")
.request()
.buildGet()
.invoke();

assertThat(getMandatoryResponse).isNotNull();
assertThat(getMandatoryResponse.getStatus()).isEqualTo(200);
String mandatoryList = getMandatoryResponse.readEntity(String.class);
assertThat(mandatoryList).isEqualTo(c.getPublicKey());
}

@Test
Expand Down

0 comments on commit dcbf6d6

Please sign in to comment.