use of com.quorum.tessera.version.MultiTenancyVersion.MIME_TYPE_JSON_2_1 in project tessera by ConsenSys.
the class SendIT method sendToMultipleRecipientsOnSameNode.
@Test
public void sendToMultipleRecipientsOnSameNode() throws UnsupportedEncodingException {
// Node C has 2 keys, use them both
final String[] recipientPublicKeys = ExecutionContext.currentContext().getConfigs().stream().filter(c -> c.getAlias() == NodeAlias.C).findFirst().map(ConfigDescriptor::getAllKeys).get().stream().map(ConfigKeyPair::getPublicKey).toArray(String[]::new);
final Party sendingParty = partyHelper.findByAlias(NodeAlias.A);
final Party recipientParty = partyHelper.findByAlias(NodeAlias.C);
final byte[] transactionData = utils.createTransactionData();
final SendRequest sendRequest = new SendRequest();
sendRequest.setFrom(sendingParty.getPublicKey());
sendRequest.setTo(recipientPublicKeys);
sendRequest.setPayload(transactionData);
final Response response = sendingParty.getRestClient().target(sendingParty.getQ2TUri()).path(SEND_PATH).request().post(Entity.entity(sendRequest, MIME_TYPE_JSON_2_1));
final SendResponse result = response.readEntity(SendResponse.class);
assertThat(result.getKey()).isNotNull().isNotBlank();
assertThat(result.getManagedParties()).containsExactlyInAnyOrder(sendingParty.getPublicKey());
assertThat(result.getSenderKey()).isEqualTo(sendingParty.getPublicKey());
assertThat(response).isNotNull();
assertThat(response.getStatus()).isEqualTo(201);
URI location = response.getLocation();
{
final Response checkPersistedTxnResponse = recipientParty.getRestClient().target(location).request().get();
assertThat(checkPersistedTxnResponse.getStatus()).isEqualTo(200);
ReceiveResponse receiveResponse = checkPersistedTxnResponse.readEntity(ReceiveResponse.class);
assertThat(receiveResponse.getPayload()).isEqualTo(transactionData);
assertThat(result.getManagedParties()).containsExactlyInAnyOrder(sendingParty.getPublicKey());
assertThat(result.getSenderKey()).isEqualTo(sendingParty.getPublicKey());
}
{
String encodedId = URLEncoder.encode(result.getKey(), StandardCharsets.UTF_8.toString());
Stream.of(recipientParty).map(Party::getRestClientWebTarget).map(target -> target.path("transaction")).map(target -> target.path(encodedId)).map(target -> target.request().accept(MIME_TYPE_JSON_2_1).get()).forEach(r -> {
assertThat(r.getStatus()).isEqualTo(200);
ReceiveResponse receiveResponse = r.readEntity(ReceiveResponse.class);
assertThat(receiveResponse.getManagedParties()).containsExactlyInAnyOrder(recipientPublicKeys);
assertThat(receiveResponse.getSenderKey()).isEqualTo(sendingParty.getPublicKey());
});
}
}
use of com.quorum.tessera.version.MultiTenancyVersion.MIME_TYPE_JSON_2_1 in project tessera by ConsenSys.
the class EncodedPayloadResource method createEncodedPayload21.
// path /encodedpayload/create is overloaded (application/json and
// application/vnd.tessera-2.1+json); swagger annotations cannot handle situations like this so
// this operation documents both
@POST
@Path("create")
@Operation(summary = "/encodedpayload/create", operationId = "encrypt", description = "encrypt a payload and return the result; does not store to the database or push to peers", requestBody = @RequestBody(content = { @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = SendRequest.class)), @Content(mediaType = MIME_TYPE_JSON_2_1, schema = @Schema(implementation = SendRequest.class)) }))
@ApiResponse(responseCode = "200", description = "encrypted payload", content = { @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = PayloadEncryptResponse.class)), @Content(mediaType = MIME_TYPE_JSON_2_1, schema = @Schema(implementation = PayloadEncryptResponse.class)) })
@Consumes(MIME_TYPE_JSON_2_1)
@Produces(MIME_TYPE_JSON_2_1)
public Response createEncodedPayload21(@NotNull @Valid final SendRequest sendRequest) {
LOGGER.info("Received request for custom payload encryption");
final PublicKey sender = Optional.ofNullable(sendRequest.getFrom()).map(base64Decoder::decode).map(PublicKey::from).orElseGet(transactionManager::defaultPublicKey);
final List<PublicKey> recipientList = Stream.of(sendRequest).filter(sr -> Objects.nonNull(sr.getTo())).flatMap(s -> Stream.of(s.getTo())).map(base64Decoder::decode).map(PublicKey::from).collect(Collectors.toList());
final Set<MessageHash> affectedTransactions = Stream.ofNullable(sendRequest.getAffectedContractTransactions()).flatMap(Arrays::stream).map(Base64.getDecoder()::decode).map(MessageHash::new).collect(Collectors.toSet());
final byte[] execHash = Optional.ofNullable(sendRequest.getExecHash()).map(String::getBytes).orElse(new byte[0]);
final com.quorum.tessera.transaction.SendRequest request = com.quorum.tessera.transaction.SendRequest.Builder.create().withRecipients(recipientList).withSender(sender).withPayload(sendRequest.getPayload()).withExecHash(execHash).withPrivacyMode(PrivacyMode.fromFlag(sendRequest.getPrivacyFlag())).withAffectedContractTransactions(affectedTransactions).build();
final EncodedPayload encodedPayload = encodedPayloadManager.create(request);
final Map<String, String> affectedContractTransactionMap = encodedPayload.getAffectedContractTransactions().entrySet().stream().collect(Collectors.toMap(e -> e.getKey().encodeToBase64(), e -> Base64.getEncoder().encodeToString(e.getValue().getData())));
final PayloadEncryptResponse response = new PayloadEncryptResponse();
response.setSenderKey(encodedPayload.getSenderKey().getKeyBytes());
response.setCipherText(encodedPayload.getCipherText());
response.setCipherTextNonce(encodedPayload.getCipherTextNonce().getNonceBytes());
response.setRecipientBoxes(encodedPayload.getRecipientBoxes().stream().map(RecipientBox::getData).collect(Collectors.toList()));
response.setRecipientNonce(encodedPayload.getRecipientNonce().getNonceBytes());
response.setRecipientKeys(encodedPayload.getRecipientKeys().stream().map(PublicKey::getKeyBytes).collect(Collectors.toList()));
response.setPrivacyMode(encodedPayload.getPrivacyMode().getPrivacyFlag());
response.setAffectedContractTransactions(affectedContractTransactionMap);
response.setExecHash(encodedPayload.getExecHash());
return Response.ok(response).type(MIME_TYPE_JSON_2_1).build();
}
use of com.quorum.tessera.version.MultiTenancyVersion.MIME_TYPE_JSON_2_1 in project tessera by ConsenSys.
the class EncodedPayloadResource method receive21.
// path /encodedpayload/decrypt is overloaded (application/json and
// application/vnd.tessera-2.1+json); swagger annotations cannot handle situations like this so
// this operation documents both
@POST
@Path("decrypt")
@Operation(summary = "/encodedpayload/decrypt", operationId = "decrypt", description = "decrypt an encrypted payload and return the result; does not store to the database or push to peers", requestBody = @RequestBody(content = { @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = PayloadDecryptRequest.class)), @Content(mediaType = MIME_TYPE_JSON_2_1, schema = @Schema(implementation = PayloadDecryptRequest.class)) }))
@ApiResponse(responseCode = "200", description = "decrypted payload", content = { @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ReceiveResponse.class)), @Content(mediaType = MIME_TYPE_JSON_2_1, schema = @Schema(implementation = ReceiveResponse.class)) })
@Consumes(MIME_TYPE_JSON_2_1)
@Produces(MIME_TYPE_JSON_2_1)
public Response receive21(@Valid @NotNull final PayloadDecryptRequest request) {
LOGGER.info("Received request to decrypt custom transaction");
final Base64.Decoder decoder = Base64.getDecoder();
final Map<TxHash, byte[]> affectedTxns = request.getAffectedContractTransactions().entrySet().stream().collect(Collectors.toMap(e -> TxHash.from(decoder.decode(e.getKey())), e -> decoder.decode(e.getValue())));
final EncodedPayload requestAsPayload = EncodedPayload.Builder.create().withSenderKey(PublicKey.from(request.getSenderKey())).withCipherText(request.getCipherText()).withCipherTextNonce(request.getCipherTextNonce()).withRecipientBoxes(request.getRecipientBoxes()).withRecipientNonce(request.getRecipientNonce()).withRecipientKeys(request.getRecipientKeys().stream().map(PublicKey::from).collect(Collectors.toList())).withPrivacyFlag(request.getPrivacyMode()).withAffectedContractTransactions(affectedTxns).withExecHash(request.getExecHash()).build();
final com.quorum.tessera.transaction.ReceiveResponse response = encodedPayloadManager.decrypt(requestAsPayload, null);
final ReceiveResponse receiveResponse = new ReceiveResponse();
receiveResponse.setPrivacyFlag(response.getPrivacyMode().getPrivacyFlag());
receiveResponse.setPayload(response.getUnencryptedTransactionData());
receiveResponse.setAffectedContractTransactions(response.getAffectedTransactions().stream().map(MessageHash::getHashBytes).map(Base64.getEncoder()::encodeToString).toArray(String[]::new));
Optional.ofNullable(response.getExecHash()).map(String::new).ifPresent(receiveResponse::setExecHash);
return Response.ok(receiveResponse).type(MIME_TYPE_JSON_2_1).build();
}
use of com.quorum.tessera.version.MultiTenancyVersion.MIME_TYPE_JSON_2_1 in project tessera by ConsenSys.
the class TransactionResource3 method send.
// path /send is overloaded (application/json and application/vnd.tessera-2.1+json); swagger
// annotations cannot
// handle situations like this so this operation documents both
@Operation(summary = "/send", operationId = "encryptStoreAndSendJson", description = "encrypts a payload, stores result in database, and publishes result to recipients", requestBody = @RequestBody(content = { @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = SendRequest.class)), @Content(mediaType = MIME_TYPE_JSON_2_1, schema = @Schema(implementation = SendRequest.class)) }))
@ApiResponse(responseCode = "201", description = "encrypted payload hash", content = { @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = SendResponse.class)), @Content(mediaType = MIME_TYPE_JSON_2_1, schema = @Schema(implementation = SendResponse.class)) })
@ApiResponse(responseCode = "200", description = "hash returned when running in orion mode", content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = SendResponse.class)))
@POST
@Path("send")
@Consumes({ MIME_TYPE_JSON_2_1, MIME_TYPE_JSON_3 })
@Produces({ MIME_TYPE_JSON_2_1, MIME_TYPE_JSON_3 })
public Response send(@NotNull @Valid @PrivacyValid final SendRequest sendRequest) {
final PublicKey sender = Optional.ofNullable(sendRequest.getFrom()).map(base64Decoder::decode).map(PublicKey::from).orElseGet(transactionManager::defaultPublicKey);
final Optional<PrivacyGroup.Id> privacyGroupId = Optional.ofNullable(sendRequest.getPrivacyGroupId()).map(PrivacyGroup.Id::fromBase64String);
final List<PublicKey> recipientList = privacyGroupId.map(privacyGroupManager::retrievePrivacyGroup).map(PrivacyGroup::getMembers).orElse(Stream.of(sendRequest).filter(sr -> Objects.nonNull(sr.getTo())).flatMap(s -> Stream.of(s.getTo())).map(base64Decoder::decode).map(PublicKey::from).collect(Collectors.toList()));
final Set<MessageHash> affectedTransactions = Stream.ofNullable(sendRequest.getAffectedContractTransactions()).flatMap(Arrays::stream).map(base64Decoder::decode).map(MessageHash::new).collect(Collectors.toSet());
final byte[] execHash = Optional.ofNullable(sendRequest.getExecHash()).map(String::getBytes).orElse(new byte[0]);
final PrivacyMode privacyMode = PrivacyMode.fromFlag(sendRequest.getPrivacyFlag());
final com.quorum.tessera.transaction.SendRequest.Builder requestBuilder = com.quorum.tessera.transaction.SendRequest.Builder.create().withRecipients(recipientList).withSender(sender).withPayload(sendRequest.getPayload()).withExecHash(execHash).withPrivacyMode(privacyMode).withAffectedContractTransactions(affectedTransactions);
privacyGroupId.ifPresent(requestBuilder::withPrivacyGroupId);
final com.quorum.tessera.transaction.SendResponse response = transactionManager.send(requestBuilder.build());
final String encodedKey = Optional.of(response).map(com.quorum.tessera.transaction.SendResponse::getTransactionHash).map(MessageHash::getHashBytes).map(base64Encoder::encodeToString).get();
final String[] managedParties = Optional.of(response).map(com.quorum.tessera.transaction.SendResponse::getManagedParties).orElse(Collections.emptySet()).stream().map(PublicKey::encodeToBase64).toArray(String[]::new);
final SendResponse sendResponse = Optional.of(response).map(com.quorum.tessera.transaction.SendResponse::getTransactionHash).map(MessageHash::getHashBytes).map(base64Encoder::encodeToString).map(messageHash -> new SendResponse(messageHash, managedParties, sender.encodeToBase64())).get();
final URI location = UriBuilder.fromPath("transaction").path(URLEncoder.encode(encodedKey, StandardCharsets.UTF_8)).build();
return Response.created(location).entity(sendResponse).build();
}
use of com.quorum.tessera.version.MultiTenancyVersion.MIME_TYPE_JSON_2_1 in project tessera by ConsenSys.
the class SendIT method senderAndRecipientOnSameNode.
@Test
public void senderAndRecipientOnSameNode() throws UnsupportedEncodingException {
// Node C has 2 keys, use them both
final String[] recipientPublicKeys = ExecutionContext.currentContext().getConfigs().stream().filter(c -> c.getAlias() == NodeAlias.C).findFirst().map(ConfigDescriptor::getAllKeys).get().stream().map(ConfigKeyPair::getPublicKey).toArray(String[]::new);
final Party party = partyHelper.findByAlias(NodeAlias.C);
final byte[] transactionData = utils.createTransactionData();
final SendRequest sendRequest = new SendRequest();
sendRequest.setFrom(recipientPublicKeys[0]);
sendRequest.setTo(recipientPublicKeys[1]);
sendRequest.setPayload(transactionData);
final Response response = party.getRestClient().target(party.getQ2TUri()).path(SEND_PATH).request().post(Entity.entity(sendRequest, MIME_TYPE_JSON_2_1));
final SendResponse result = response.readEntity(SendResponse.class);
assertThat(result.getKey()).isNotNull().isNotBlank();
assertThat(result.getManagedParties()).containsExactlyInAnyOrder(recipientPublicKeys);
assertThat(result.getSenderKey()).isEqualTo(recipientPublicKeys[0]);
assertThat(response).isNotNull();
assertThat(response.getStatus()).isEqualTo(201);
URI location = response.getLocation();
{
final Response checkPersistedTxnResponse = party.getRestClient().target(location).request().accept(MIME_TYPE_JSON_2_1).get();
assertThat(checkPersistedTxnResponse.getStatus()).isEqualTo(200);
ReceiveResponse receiveResponse = checkPersistedTxnResponse.readEntity(ReceiveResponse.class);
assertThat(receiveResponse.getPayload()).isEqualTo(transactionData);
assertThat(receiveResponse.getManagedParties()).containsExactlyInAnyOrder(recipientPublicKeys);
}
{
String encodedId = URLEncoder.encode(result.getKey(), StandardCharsets.UTF_8.toString());
Stream.of(party).map(Party::getRestClientWebTarget).map(target -> target.path("transaction")).map(target -> target.path(encodedId)).map(target -> target.request().accept(MIME_TYPE_JSON_2_1).get()).forEach(r -> {
assertThat(r.getStatus()).isEqualTo(200);
ReceiveResponse receiveResponse = r.readEntity(ReceiveResponse.class);
assertThat(receiveResponse.getManagedParties()).containsExactlyInAnyOrder(recipientPublicKeys);
assertThat(receiveResponse.getSenderKey()).isEqualTo(recipientPublicKeys[0]);
});
}
}
Aggregations