Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Partyinfo communication-domain seperation #1117

Merged
merged 3 commits into from
Aug 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,7 @@ subprojects {
}

jacocoTestCoverageVerification.dependsOn jacocoTestReport
check.dependsOn checkstyleMain, checkstyleTest, dependencyCheckAnalyze, spotlessCheck, jacocoTestCoverageVerification
check.dependsOn checkstyleMain, checkstyleTest, spotlessCheck, jacocoTestCoverageVerification

}

Expand Down
3 changes: 3 additions & 0 deletions settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,10 @@ include(':tessera-jaxrs:common-jaxrs')
include(':tessera-jaxrs:thirdparty-jaxrs')
include(':tessera-jaxrs:sync-jaxrs')
include(':tessera-jaxrs:jaxrs-client')
include(":tessera-jaxrs:partyinfo-model")
include(':tessera-jaxrs')
include(':tessera-data')

project(':cli:cli-api').projectDir = file('cli/cli-api')
project(':cli:config-cli').projectDir = file('cli/config-cli')
project(':tests:acceptance-test').projectDir = file('tests/acceptance-test')
Expand Down Expand Up @@ -83,5 +85,6 @@ project(':tessera-jaxrs:common-jaxrs').projectDir = file('tessera-jaxrs/common-j
project(':tessera-jaxrs:thirdparty-jaxrs').projectDir = file('tessera-jaxrs/thirdparty-jaxrs')
project(':tessera-jaxrs:sync-jaxrs').projectDir = file('tessera-jaxrs/sync-jaxrs')
project(':tessera-jaxrs:jaxrs-client').projectDir = file('tessera-jaxrs/jaxrs-client')
project(':tessera-jaxrs:partyinfo-model').projectDir = file('tessera-jaxrs/partyinfo-model')
include 'tessera-context'

Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,16 @@

import com.quorum.tessera.data.MessageHash;
import com.quorum.tessera.encryption.PublicKey;
import com.quorum.tessera.partyinfo.ResendRequestType;

import java.util.Objects;

public interface ResendRequest {

// FIXME: also defined in jaxrs module
enum ResendRequestType {
ALL,INDIVIDUAL
}

PublicKey getRecipient();

ResendRequestType getType();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ public SendResponse sendSignedTransaction(final SendSignedRequest sendRequest) {
public ResendResponse resend(ResendRequest request) {

final PublicKey recipientPublicKey = request.getRecipient();
if (request.getType() == ResendRequestType.ALL) {
if (request.getType() == ResendRequest.ResendRequestType.ALL) {

int offset = 0;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
import com.quorum.tessera.encryption.EncryptorException;
import com.quorum.tessera.encryption.Nonce;
import com.quorum.tessera.encryption.PublicKey;
import com.quorum.tessera.partyinfo.*;
import com.quorum.tessera.partyinfo.PartyInfoService;
import com.quorum.tessera.partyinfo.PublishPayloadException;
import com.quorum.tessera.service.locator.ServiceLocator;
import com.quorum.tessera.transaction.exception.KeyNotFoundException;
import com.quorum.tessera.transaction.exception.TransactionNotFoundException;
Expand Down Expand Up @@ -385,7 +386,7 @@ public void resendAllWhereRequestedIsSenderAndRecipientExists() {
when(enclave.unencryptTransaction(payload, recipientKey)).thenReturn(new byte[0]);

final com.quorum.tessera.transaction.ResendRequest resendRequest =
ResendRequest.Builder.create().withRecipient(senderKey).withType(ResendRequestType.ALL).build();
ResendRequest.Builder.create().withRecipient(senderKey).withType(ResendRequest.ResendRequestType.ALL).build();

ResendResponse result = transactionManager.resend(resendRequest);

Expand Down Expand Up @@ -415,7 +416,7 @@ public void resendAllWithNoValidTransactions() {
when(payloadEncoder.decode(any(byte[].class))).thenReturn(payload);

final ResendRequest resendRequest =
ResendRequest.Builder.create().withRecipient(recipientKey).withType(ResendRequestType.ALL).build();
ResendRequest.Builder.create().withRecipient(recipientKey).withType(ResendRequest.ResendRequestType.ALL).build();

ResendResponse result = transactionManager.resend(resendRequest);

Expand All @@ -442,7 +443,8 @@ public void resendAllWhereRequestedIsRecipient() {
when(payloadEncoder.forRecipient(payload, recipientKey)).thenReturn(payload);

final ResendRequest resendRequest =
ResendRequest.Builder.create().withType(ResendRequestType.ALL).withRecipient(recipientKey).build();
ResendRequest.Builder.create()
.withType(ResendRequest.ResendRequestType.ALL).withRecipient(recipientKey).build();

ResendResponse result = transactionManager.resend(resendRequest);

Expand Down Expand Up @@ -487,7 +489,7 @@ public void resendAllWhereRequestedIsRecipientThenPublishedPayloadDoesNotContain
when(payloadEncoder.forRecipient(payload, recipientKey)).thenReturn(prunedPayload);

final ResendRequest resendRequest =
ResendRequest.Builder.create().withRecipient(recipientKey).withType(ResendRequestType.ALL).build();
ResendRequest.Builder.create().withRecipient(recipientKey).withType(ResendRequest.ResendRequestType.ALL).build();

ResendResponse result = transactionManager.resend(resendRequest);

Expand Down Expand Up @@ -525,7 +527,7 @@ public void resendAllWhereRequestedIsSenderThenPublishedPayloadIsNotPruned() {
when(enclave.getPublicKeys()).thenReturn(singleton(localKey));

final com.quorum.tessera.transaction.ResendRequest resendRequest =
ResendRequest.Builder.create().withType(ResendRequestType.ALL).withRecipient(senderKey).build();
ResendRequest.Builder.create().withType(ResendRequest.ResendRequestType.ALL).withRecipient(senderKey).build();

ResendResponse result = transactionManager.resend(resendRequest);

Expand Down Expand Up @@ -557,7 +559,7 @@ public void resendAllWhereRequestedIsSenderAndRecipientDoesntExist() {
when(enclave.getPublicKeys()).thenReturn(emptySet());

final ResendRequest resendRequest =
ResendRequest.Builder.create().withRecipient(senderKey).withType(ResendRequestType.ALL).build();
ResendRequest.Builder.create().withRecipient(senderKey).withType(ResendRequest.ResendRequestType.ALL).build();

final Throwable throwable = catchThrowable(() -> transactionManager.resend(resendRequest));

Expand Down Expand Up @@ -593,7 +595,7 @@ public void resendAllWithOnePayloadAndOneRecipientThenPublishPayloadExceptionIsC

ResendRequest resendRequest = mock(ResendRequest.class);
when(resendRequest.getRecipient()).thenReturn(publicKey);
when(resendRequest.getType()).thenReturn(ResendRequestType.ALL);
when(resendRequest.getType()).thenReturn(ResendRequest.ResendRequestType.ALL);

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

Expand Down Expand Up @@ -634,7 +636,9 @@ public void resendAllIfTwoPayloadsAndFirstThrowsExceptionThenSecondIsStillPublis
when(otherEncodedPayload.getRecipientKeys()).thenReturn(Collections.singletonList(publicKey));

final ResendRequest resendRequest =
ResendRequest.Builder.create().withRecipient(publicKey).withType(ResendRequestType.ALL).build();
ResendRequest.Builder.create()
.withRecipient(publicKey)
.withType(ResendRequest.ResendRequestType.ALL).build();

when(payloadEncoder.forRecipient(eq(encodedPayload), any(PublicKey.class))).thenReturn(encodedPayload);
when(payloadEncoder.forRecipient(eq(otherEncodedPayload), any(PublicKey.class)))
Expand Down Expand Up @@ -681,7 +685,9 @@ public void resendAllTwoPayloadsAndTwoRecipientsAllThrowExceptionButAllStillPubl
when(payloadEncoder.forRecipient(otherEncodedPayload, publicKey)).thenReturn(otherEncodedPayload);

final ResendRequest resendRequest =
ResendRequest.Builder.create().withRecipient(publicKey).withType(ResendRequestType.ALL).build();
ResendRequest.Builder.create()
.withRecipient(publicKey)
.withType(ResendRequest.ResendRequestType.ALL).build();

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

Expand Down Expand Up @@ -717,7 +723,7 @@ public void resendIndividualNoExistingTransactionFound() {
ResendRequest.Builder.create()
.withRecipient(recipientKey)
.withHash(transactionHash)
.withType(ResendRequestType.INDIVIDUAL)
.withType(ResendRequest.ResendRequestType.INDIVIDUAL)
.build();

try {
Expand Down Expand Up @@ -755,7 +761,7 @@ public void resendIndividual() {
ResendRequest.Builder.create()
.withRecipient(recipientKey)
.withHash(transactionHash)
.withType(ResendRequestType.INDIVIDUAL)
.withType(ResendRequest.ResendRequestType.INDIVIDUAL)
.build();

ResendResponse result = transactionManager.resend(resendRequest);
Expand Down Expand Up @@ -798,7 +804,7 @@ public void resendIndividualAsSender() {
ResendRequest.Builder.create()
.withRecipient(senderKey)
.withHash(transactionHash)
.withType(ResendRequestType.INDIVIDUAL)
.withType(ResendRequest.ResendRequestType.INDIVIDUAL)
.build();

final ResendResponse result = transactionManager.resend(resendRequest);
Expand Down
5 changes: 5 additions & 0 deletions tessera-jaxrs/partyinfo-model/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@

dependencies {
implementation project(':tessera-partyinfo')
implementation project(':encryption:encryption-api')
}
19 changes: 19 additions & 0 deletions tessera-jaxrs/partyinfo-model/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.jpmorgan.quorum</groupId>
<artifactId>tessera-jaxrs</artifactId>
<version>0.10.7-SNAPSHOT</version>
</parent>
<artifactId>partyinfo-model</artifactId>
<packaging>jar</packaging>

<dependencies>
<dependency>
<groupId>com.jpmorgan.quorum</groupId>
<artifactId>tessera-partyinfo</artifactId>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.quorum.tessera.partyinfo.model;

import com.quorum.tessera.partyinfo.node.NodeInfo;
import com.quorum.tessera.partyinfo.node.Recipient;

import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

public interface NodeInfoUtil {

static NodeInfo from(PartyInfo partyInfo, Collection<String> versions) {

List<Recipient> recipients = partyInfo.getRecipients().stream()
.map(r -> Recipient.of(r.getKey(),r.getUrl())).collect(Collectors.toList());

List<com.quorum.tessera.partyinfo.node.Party> parties = partyInfo.getParties().stream()
.map(Party::getUrl).map(com.quorum.tessera.partyinfo.node.Party::new).collect(Collectors.toList());

return NodeInfo.Builder.create()
.withUrl(partyInfo.getUrl())
.withRecipients(recipients)
.withParties(parties)
.withSupportedApiVersions(versions)
.build();

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.quorum.tessera.partyinfo.model;

import com.quorum.tessera.partyinfo.URLNormalizer;
import java.time.Instant;
import java.util.Objects;

/**
* Contains a URL of another known node on the network
*/
public class Party {

private final String url;

private Instant lastContacted;

public Party(final String url) {
this.url = URLNormalizer.create().normalize(url);
}

public String getUrl() {
return url;
}

@Override
public final boolean equals(final Object o) {
return (o instanceof Party) && Objects.equals(url, ((Party) o).url);
}

@Override
public final int hashCode() {
return Objects.hash(url);
}

@Override
public String toString() {
return "Party{" + "url=" + url + '}';
}

}
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package com.quorum.tessera.partyinfo.model;

import java.util.Collections;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import com.quorum.tessera.partyinfo.node.NodeInfo;

import java.util.*;
import java.util.stream.Collectors;

/**
* Contains all information that is transferred between two nodes on the
Expand All @@ -22,8 +22,8 @@ public class PartyInfo {

public PartyInfo(final String url, final Set<Recipient> recipients, final Set<Party> parties) {
this.url = Objects.requireNonNull(url);
this.recipients = Collections.unmodifiableSet(new HashSet<>(recipients));
this.parties = Collections.unmodifiableSet(new HashSet<>(parties));
this.recipients = Set.copyOf(recipients);
this.parties = Set.copyOf(parties);
}

public String getUrl() {
Expand All @@ -38,4 +38,18 @@ public Set<Party> getParties() {
return parties;
}


public static PartyInfo from(NodeInfo nodeInfo) {
Set<Recipient> recipients = nodeInfo.getRecipients().stream()
.map(r -> Recipient.of(r.getKey(), r.getUrl()))
.collect(Collectors.toUnmodifiableSet());

Set<Party> parties = nodeInfo.getParties().stream()
.map(com.quorum.tessera.partyinfo.node.Party::getUrl)
.map(Party::new)
.collect(Collectors.toUnmodifiableSet());

return new PartyInfo(nodeInfo.getUrl(),recipients,parties);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.quorum.tessera.partyinfo.model;

import com.quorum.tessera.encryption.PublicKey;
import com.quorum.tessera.partyinfo.node.NodeInfo;
import com.quorum.tessera.partyinfo.node.VersionInfo;
import org.junit.Test;

import java.util.Set;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

public class NodeInfoUtilTest {

@Test
public void from() {

PartyInfo partyInfo = mock(PartyInfo.class);
VersionInfo versionInfo = mock(VersionInfo.class);
Recipient recipient = Recipient.of(mock(PublicKey.class),"someurl");

when(partyInfo.getUrl()).thenReturn("someurl");
when(versionInfo.supportedApiVersions()).thenReturn(Set.of("v1","v3"));
when(partyInfo.getRecipients()).thenReturn(Set.of(recipient));


NodeInfo nodeInfo = NodeInfoUtil.from(partyInfo,Set.of("v1","v3"));

assertThat(nodeInfo).isNotNull();

assertThat(nodeInfo.getUrl()).isEqualTo("someurl");
assertThat(nodeInfo.supportedApiVersions()).isEqualTo(Set.of("v3","v1"));
assertThat(nodeInfo.getRecipients()).hasSize(1);
assertThat(nodeInfo.getRecipients().iterator().next().getUrl()).isEqualTo("someurl");

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.quorum.tessera.partyinfo.model;

import com.quorum.tessera.partyinfo.node.NodeInfo;
import org.junit.Test;

import java.util.List;
import java.util.Set;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;

public class PartyInfoTest {

@Test
public void createSimple() {
String url = "someurl";
Set<Recipient> recipients = Set.of(mock(Recipient.class));
Set<Party> parties = Set.of(mock(Party.class));

PartyInfo partyInfo = new PartyInfo(url,recipients,parties);

assertThat(partyInfo.getParties()).isEqualTo(parties);
assertThat(partyInfo.getRecipients()).isEqualTo(recipients);
assertThat(partyInfo.getUrl()).isSameAs(url);

}

@Test
public void fromNodeInfo() {
com.quorum.tessera.partyinfo.node.Recipient recipient = mock(com.quorum.tessera.partyinfo.node.Recipient.class);

NodeInfo nodeInfo = NodeInfo.Builder.create()
.withUrl("url")
.withRecipients(List.of(recipient))
.build();

PartyInfo partyInfo = PartyInfo.from(nodeInfo);
assertThat(partyInfo.getUrl()).isEqualTo("url");
}

}
Loading