diff --git a/argon2/pom.xml b/argon2/pom.xml
index 4ad108a99e..719c8c18b2 100644
--- a/argon2/pom.xml
+++ b/argon2/pom.xml
@@ -11,7 +11,7 @@
tessera
com.quorum.tessera
- 0.7
+ 0.7.1-SNAPSHOT
diff --git a/config-cli/pom.xml b/config-cli/pom.xml
index 9ba0bde10b..1d1a2fd963 100644
--- a/config-cli/pom.xml
+++ b/config-cli/pom.xml
@@ -6,7 +6,7 @@
com.quorum.tessera
tessera
- 0.7
+ 0.7.1-SNAPSHOT
config-cli
diff --git a/config-cli/src/test/java/com/quorum/tessera/config/cli/DefaultCliAdapterTest.java b/config-cli/src/test/java/com/quorum/tessera/config/cli/DefaultCliAdapterTest.java
index d3563318e5..d34dbf3a60 100644
--- a/config-cli/src/test/java/com/quorum/tessera/config/cli/DefaultCliAdapterTest.java
+++ b/config-cli/src/test/java/com/quorum/tessera/config/cli/DefaultCliAdapterTest.java
@@ -25,6 +25,7 @@
import java.util.UUID;
import static com.quorum.tessera.test.util.ElUtil.createAndPopulatePaths;
+import java.util.Arrays;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.*;
@@ -102,7 +103,7 @@ public void withConstraintViolations() throws Exception {
cliDelegate.execute("-configfile", configFile.toString());
failBecauseExceptionWasNotThrown(ConstraintViolationException.class);
} catch (ConstraintViolationException ex) {
- assertThat(ex.getConstraintViolations()).hasSize(2);
+ assertThat(ex.getConstraintViolations()).hasSize(4);
}
@@ -113,7 +114,13 @@ public void keygenWithConfig() throws Exception {
KeyGenerator keyGenerator = MockKeyGeneratorFactory.getMockKeyGenerator();
- FilesystemKeyPair keypair = new FilesystemKeyPair(Paths.get(""), Paths.get(""));
+ Path publicKeyPath = Files.createTempFile(UUID.randomUUID().toString(), "");
+ Path privateKeyPath = Files.createTempFile(UUID.randomUUID().toString(), "");
+
+ Files.write(privateKeyPath, Arrays.asList("SOMEDATA"));
+ Files.write(publicKeyPath, Arrays.asList("SOMEDATA"));
+
+ FilesystemKeyPair keypair = new FilesystemKeyPair(publicKeyPath, privateKeyPath);
when(keyGenerator.generate(anyString(), eq(null))).thenReturn(keypair);
Path unixSocketPath = Files.createTempFile(UUID.randomUUID().toString(), ".ipc");
@@ -175,8 +182,14 @@ public void outputWithoutKeygenOrConfig() {
public void output() throws Exception {
KeyGenerator keyGenerator = MockKeyGeneratorFactory.getMockKeyGenerator();
-
- FilesystemKeyPair keypair = new FilesystemKeyPair(Paths.get(""), Paths.get(""));
+
+ Path publicKeyPath = Files.createTempFile(UUID.randomUUID().toString(), "");
+ Path privateKeyPath = Files.createTempFile(UUID.randomUUID().toString(), "");
+
+ Files.write(privateKeyPath, Arrays.asList("SOMEDATA"));
+ Files.write(publicKeyPath, Arrays.asList("SOMEDATA"));
+
+ FilesystemKeyPair keypair = new FilesystemKeyPair(publicKeyPath, privateKeyPath);
when(keyGenerator.generate(anyString(), eq(null))).thenReturn(keypair);
Path generatedKey = Paths.get("/tmp/" + UUID.randomUUID().toString());
@@ -355,7 +368,13 @@ public void suppressStartupForKeygenOption() throws Exception {
@Test
public void allowStartupForKeygenAndConfigfileOptions() throws Exception {
final KeyGenerator keyGenerator = MockKeyGeneratorFactory.getMockKeyGenerator();
- final FilesystemKeyPair keypair = new FilesystemKeyPair(Paths.get(""), Paths.get(""));
+ Path publicKeyPath = Files.createTempFile(UUID.randomUUID().toString(), "");
+ Path privateKeyPath = Files.createTempFile(UUID.randomUUID().toString(), "");
+
+ Files.write(privateKeyPath, Arrays.asList("SOMEDATA"));
+ Files.write(publicKeyPath, Arrays.asList("SOMEDATA"));
+
+ FilesystemKeyPair keypair = new FilesystemKeyPair(publicKeyPath, privateKeyPath);
when(keyGenerator.generate(anyString(), eq(null))).thenReturn(keypair);
final Path configFile = createAndPopulatePaths(getClass().getResource("/sample-config.json"));
diff --git a/config-migration/pom.xml b/config-migration/pom.xml
index 106c95cff3..78cd7c0d3d 100644
--- a/config-migration/pom.xml
+++ b/config-migration/pom.xml
@@ -4,7 +4,7 @@
com.quorum.tessera
tessera
- 0.7
+ 0.7.1-SNAPSHOT
config-migration
jar
diff --git a/config-migration/src/test/java/com/quorum/tessera/config/migration/LegacyCliAdapterTest.java b/config-migration/src/test/java/com/quorum/tessera/config/migration/LegacyCliAdapterTest.java
index dbe9e44230..b307a4656a 100644
--- a/config-migration/src/test/java/com/quorum/tessera/config/migration/LegacyCliAdapterTest.java
+++ b/config-migration/src/test/java/com/quorum/tessera/config/migration/LegacyCliAdapterTest.java
@@ -245,7 +245,8 @@ public void ifConfigParameterIsNotSetInTomlOrCliThenDefaultIsUsed() throws Excep
Path configFile = Files.createTempFile("emptyConfig", ".txt");
Path keysFile = Paths.get("abcxyz");
Files.deleteIfExists(keysFile);
- Files.createFile(Paths.get("abcxyz"));
+ Files.createFile(keysFile);
+ Files.write(keysFile, Arrays.asList("SOMEDATA"));
String[] requiredParams = {
"--tomlfile=" + configFile.toString(),
diff --git a/config/pom.xml b/config/pom.xml
index f645c87fed..fb72ecba4f 100644
--- a/config/pom.xml
+++ b/config/pom.xml
@@ -11,7 +11,7 @@
com.quorum.tessera
tessera
- 0.7
+ 0.7.1-SNAPSHOT
diff --git a/config/src/main/java/com/quorum/tessera/config/constraints/ValidContent.java b/config/src/main/java/com/quorum/tessera/config/constraints/ValidContent.java
new file mode 100644
index 0000000000..875255dcb6
--- /dev/null
+++ b/config/src/main/java/com/quorum/tessera/config/constraints/ValidContent.java
@@ -0,0 +1,27 @@
+package com.quorum.tessera.config.constraints;
+
+import java.lang.annotation.Documented;
+import static java.lang.annotation.ElementType.*;
+import java.lang.annotation.Retention;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import java.lang.annotation.Target;
+import javax.validation.Constraint;
+import javax.validation.Payload;
+
+@Target({FIELD, METHOD, PARAMETER, ANNOTATION_TYPE, TYPE_PARAMETER, TYPE_USE})
+@Retention(RUNTIME)
+@Constraint(validatedBy = ValidContentValidator.class)
+@Documented
+public @interface ValidContent {
+
+ String message() default "{ValidContent.message}";
+
+ Class>[] groups() default {};
+
+ Class extends Payload>[] payload() default {};
+
+ int minLines() default 0;
+
+ int maxLines() default Integer.MAX_VALUE;
+
+}
diff --git a/config/src/main/java/com/quorum/tessera/config/constraints/ValidContentValidator.java b/config/src/main/java/com/quorum/tessera/config/constraints/ValidContentValidator.java
new file mode 100644
index 0000000000..2677caceb5
--- /dev/null
+++ b/config/src/main/java/com/quorum/tessera/config/constraints/ValidContentValidator.java
@@ -0,0 +1,40 @@
+package com.quorum.tessera.config.constraints;
+
+import com.quorum.tessera.io.FilesDelegate;
+import java.nio.file.Files;
+import javax.validation.ConstraintValidator;
+import javax.validation.ConstraintValidatorContext;
+import java.nio.file.Path;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+public class ValidContentValidator implements ConstraintValidator {
+
+ private ValidContent config;
+
+ @Override
+ public void initialize(ValidContent constraintAnnotation) {
+ this.config = constraintAnnotation;
+ }
+
+ @Override
+ public boolean isValid(Path path, ConstraintValidatorContext context) {
+
+ if (Objects.isNull(path)) {
+ return true;
+ }
+
+ if (!Files.exists(path)) {
+ return true;
+ }
+
+ List lines = FilesDelegate.create().lines(path)
+ .filter(line -> !Objects.equals("", line))
+ .collect(Collectors.toList());
+
+ return lines.size() >= config.minLines() && lines.size() <= config.maxLines();
+
+ }
+
+}
diff --git a/config/src/main/java/com/quorum/tessera/config/keypairs/DirectKeyPair.java b/config/src/main/java/com/quorum/tessera/config/keypairs/DirectKeyPair.java
index 653c3f95c3..3324b5a597 100644
--- a/config/src/main/java/com/quorum/tessera/config/keypairs/DirectKeyPair.java
+++ b/config/src/main/java/com/quorum/tessera/config/keypairs/DirectKeyPair.java
@@ -3,15 +3,19 @@
import com.quorum.tessera.config.constraints.ValidBase64;
import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
import javax.xml.bind.annotation.XmlElement;
public class DirectKeyPair implements ConfigKeyPair {
+ @Size(min = 1)
@NotNull
@ValidBase64(message = "Invalid Base64 key provided")
@XmlElement
private final String publicKey;
+
+ @Size(min = 1)
@NotNull
@ValidBase64(message = "Invalid Base64 key provided")
@XmlElement
diff --git a/config/src/main/java/com/quorum/tessera/config/keypairs/FilesystemKeyPair.java b/config/src/main/java/com/quorum/tessera/config/keypairs/FilesystemKeyPair.java
index a55f4ddcfc..581b810152 100644
--- a/config/src/main/java/com/quorum/tessera/config/keypairs/FilesystemKeyPair.java
+++ b/config/src/main/java/com/quorum/tessera/config/keypairs/FilesystemKeyPair.java
@@ -2,6 +2,7 @@
import com.quorum.tessera.config.KeyDataConfig;
import com.quorum.tessera.config.adapters.PathAdapter;
+import com.quorum.tessera.config.constraints.ValidContent;
import com.quorum.tessera.config.constraints.ValidPath;
import com.quorum.tessera.config.util.JaxbUtil;
import com.quorum.tessera.io.IOCallback;
@@ -16,12 +17,14 @@
public class FilesystemKeyPair implements ConfigKeyPair {
+ @ValidContent(minLines = 1,maxLines = 1,message = "file expected to contain a single non empty value")
@NotNull
@ValidPath(checkExists = true, message = "File does not exist")
@XmlElement
@XmlJavaTypeAdapter(PathAdapter.class)
private final Path publicKeyPath;
+ @ValidContent(minLines = 1,message = "file expected to contain at least one line")
@NotNull
@ValidPath(checkExists = true, message = "File does not exist")
@XmlElement
diff --git a/config/src/main/java/com/quorum/tessera/config/keypairs/InlineKeypair.java b/config/src/main/java/com/quorum/tessera/config/keypairs/InlineKeypair.java
index d94744cd4c..1a7b902f97 100644
--- a/config/src/main/java/com/quorum/tessera/config/keypairs/InlineKeypair.java
+++ b/config/src/main/java/com/quorum/tessera/config/keypairs/InlineKeypair.java
@@ -13,10 +13,12 @@
import static com.quorum.tessera.config.PrivateKeyType.UNLOCKED;
import com.quorum.tessera.encryption.PrivateKey;
+import javax.validation.constraints.Size;
@ValidInlineKeypair
public class InlineKeypair implements ConfigKeyPair {
+ @Size(min = 1)
@NotNull
@ValidBase64(message = "Invalid Base64 key provided")
@XmlElement
diff --git a/config/src/main/java/com/quorum/tessera/config/keypairs/KeyPairConverter.java b/config/src/main/java/com/quorum/tessera/config/keypairs/KeyPairConverter.java
index 569ca1bfe1..0e0d560208 100644
--- a/config/src/main/java/com/quorum/tessera/config/keypairs/KeyPairConverter.java
+++ b/config/src/main/java/com/quorum/tessera/config/keypairs/KeyPairConverter.java
@@ -41,8 +41,8 @@ private KeyPair convert(ConfigKeyPair configKeyPair) {
}
return new KeyPair(
- PublicKey.from(Base64.getDecoder().decode(encodedPub)),
- PrivateKey.from(Base64.getDecoder().decode(encodedPriv))
+ PublicKey.from(Base64.getDecoder().decode(encodedPub.trim())),
+ PrivateKey.from(Base64.getDecoder().decode(encodedPriv.trim()))
);
}
diff --git a/config/src/test/java/com/quorum/tessera/config/constraints/ValidContentValidatorTest.java b/config/src/test/java/com/quorum/tessera/config/constraints/ValidContentValidatorTest.java
new file mode 100644
index 0000000000..2e65916906
--- /dev/null
+++ b/config/src/test/java/com/quorum/tessera/config/constraints/ValidContentValidatorTest.java
@@ -0,0 +1,141 @@
+package com.quorum.tessera.config.constraints;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.UUID;
+import javax.validation.ConstraintValidatorContext;
+import static org.assertj.core.api.Assertions.assertThat;
+import org.junit.Test;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class ValidContentValidatorTest {
+
+ @Test
+ public void ignoreNullPath() {
+ ValidContentValidator validator = new ValidContentValidator();
+ ValidContent validContent = mock(ValidContent.class);
+ validator.initialize(validContent);
+
+ ConstraintValidatorContext context = mock(ConstraintValidatorContext.class);
+
+ assertThat(validator.isValid(null, context)).isTrue();
+
+ }
+
+ @Test
+ public void ignoreNonExistPath() {
+ ValidContentValidator validator = new ValidContentValidator();
+ ValidContent validContent = mock(ValidContent.class);
+ validator.initialize(validContent);
+
+ ConstraintValidatorContext context = mock(ConstraintValidatorContext.class);
+
+ Path path = Paths.get(UUID.randomUUID().toString());
+
+ assertThat(path).doesNotExist();
+
+ assertThat(validator.isValid(path, context)).isTrue();
+
+ }
+
+ @Test
+ public void defaultValuesIgnoreEmptyFile() throws Exception {
+ ValidContentValidator validator = new ValidContentValidator();
+ ValidContent validContent = mock(ValidContent.class);
+
+ validator.initialize(validContent);
+
+ ConstraintValidatorContext context = mock(ConstraintValidatorContext.class);
+
+ Path path = Files.createTempFile(UUID.randomUUID().toString(), "");
+
+ assertThat(path).exists();
+
+ assertThat(validator.isValid(path, context)).isTrue();
+
+ }
+
+ @Test
+ public void expectSingleLineButFileIsEmpty() throws Exception {
+ ValidContentValidator validator = new ValidContentValidator();
+ ValidContent validContent = mock(ValidContent.class);
+ when(validContent.minLines()).thenReturn(1);
+ when(validContent.maxLines()).thenReturn(1);
+
+ validator.initialize(validContent);
+
+ ConstraintValidatorContext context = mock(ConstraintValidatorContext.class);
+
+ Path path = Files.createTempFile(UUID.randomUUID().toString(), "");
+
+ assertThat(path).exists();
+
+ assertThat(validator.isValid(path, context)).isFalse();
+
+ }
+
+ @Test
+ public void expectSingleLineFileIsValid() throws Exception {
+ ValidContentValidator validator = new ValidContentValidator();
+ ValidContent validContent = mock(ValidContent.class);
+ when(validContent.minLines()).thenReturn(1);
+ when(validContent.maxLines()).thenReturn(1);
+
+ validator.initialize(validContent);
+
+ ConstraintValidatorContext context = mock(ConstraintValidatorContext.class);
+
+ Path path = Files.createTempFile(UUID.randomUUID().toString(), "");
+ Files.write(path, "SOMEDATA".getBytes());
+
+ assertThat(path).exists();
+
+ assertThat(validator.isValid(path, context)).isTrue();
+
+ }
+
+ @Test
+ public void tooManyLines() throws Exception {
+ ValidContentValidator validator = new ValidContentValidator();
+ ValidContent validContent = mock(ValidContent.class);
+ when(validContent.minLines()).thenReturn(1);
+ when(validContent.maxLines()).thenReturn(1);
+
+ validator.initialize(validContent);
+
+ final ConstraintValidatorContext context = mock(ConstraintValidatorContext.class);
+
+ Path path = Files.createTempFile(UUID.randomUUID().toString(), "");
+ Files.write(path, Arrays.asList("SOMEDATA","SOMEMOREDATA"));
+
+ assertThat(path).exists();
+
+ assertThat(validator.isValid(path, context)).isFalse();
+
+ }
+
+ @Test
+ public void emptyLine() throws Exception {
+ ValidContentValidator validator = new ValidContentValidator();
+ ValidContent validContent = mock(ValidContent.class);
+ when(validContent.minLines()).thenReturn(1);
+ when(validContent.maxLines()).thenReturn(1);
+
+ validator.initialize(validContent);
+
+ final ConstraintValidatorContext context = mock(ConstraintValidatorContext.class);
+
+ Path path = Files.createTempFile(UUID.randomUUID().toString(), "");
+ Files.write(path, Arrays.asList(""));
+
+ assertThat(path).exists();
+
+ assertThat(validator.isValid(path, context)).isFalse();
+
+ }
+
+
+}
diff --git a/config/src/test/java/com/quorum/tessera/config/keypairs/KeyPairConverterTest.java b/config/src/test/java/com/quorum/tessera/config/keypairs/KeyPairConverterTest.java
index fc61e4d387..595fbd837a 100644
--- a/config/src/test/java/com/quorum/tessera/config/keypairs/KeyPairConverterTest.java
+++ b/config/src/test/java/com/quorum/tessera/config/keypairs/KeyPairConverterTest.java
@@ -117,4 +117,20 @@ public void convertMultipleKeyPairs() {
final KeyPair resultB = it.next();
assertThat(resultB).isEqualToComparingFieldByField(expectedB);
}
+
+ @Test
+ public void convertKeyPairWithNewlineOrSpace() {
+ final DirectKeyPair keyPair =
+ new DirectKeyPair("gybY1t9GOYiuN6QgwcrvM2+pQzIu4UrHwiMG7yKQnTg=\n",
+ " yTjqANGAvPCy8AfhcIZ+e4O8CHZPbHkIeOmae5W3srY=\n\n\n");
+
+ Collection result = converter.convert(Collections.singletonList(keyPair));
+
+ KeyPair expected = new KeyPair(
+ PublicKey.from(decodeBase64("gybY1t9GOYiuN6QgwcrvM2+pQzIu4UrHwiMG7yKQnTg=")),
+ PrivateKey.from(decodeBase64("yTjqANGAvPCy8AfhcIZ+e4O8CHZPbHkIeOmae5W3srY=")));
+
+ KeyPair resultKeyPair = result.iterator().next();
+ assertThat(resultKeyPair).isEqualToComparingFieldByField(expected);
+ }
}
diff --git a/data-migration/pom.xml b/data-migration/pom.xml
index a51696a3c3..2d4ee5cd84 100644
--- a/data-migration/pom.xml
+++ b/data-migration/pom.xml
@@ -4,7 +4,7 @@
com.quorum.tessera
tessera
- 0.7
+ 0.7.1-SNAPSHOT
data-migration
jar
diff --git a/encryption/encryption-api/pom.xml b/encryption/encryption-api/pom.xml
index dc81e38141..c15e9ebbab 100644
--- a/encryption/encryption-api/pom.xml
+++ b/encryption/encryption-api/pom.xml
@@ -9,7 +9,7 @@
com.quorum.tessera
encryption
- 0.7
+ 0.7.1-SNAPSHOT
\ No newline at end of file
diff --git a/encryption/encryption-jnacl/pom.xml b/encryption/encryption-jnacl/pom.xml
index 25a536dc76..81a4a259f1 100644
--- a/encryption/encryption-jnacl/pom.xml
+++ b/encryption/encryption-jnacl/pom.xml
@@ -11,7 +11,7 @@
com.quorum.tessera
encryption
- 0.7
+ 0.7.1-SNAPSHOT
diff --git a/encryption/encryption-kalium/pom.xml b/encryption/encryption-kalium/pom.xml
index 5395635bac..7df9cbb405 100644
--- a/encryption/encryption-kalium/pom.xml
+++ b/encryption/encryption-kalium/pom.xml
@@ -11,7 +11,7 @@
com.quorum.tessera
encryption
- 0.7
+ 0.7.1-SNAPSHOT
diff --git a/encryption/pom.xml b/encryption/pom.xml
index bac6c040a8..2603e7ca39 100644
--- a/encryption/pom.xml
+++ b/encryption/pom.xml
@@ -9,7 +9,7 @@
tessera
com.quorum.tessera
- 0.7
+ 0.7.1-SNAPSHOT
diff --git a/grpc-api/pom.xml b/grpc-api/pom.xml
index 0d8d0e621e..45302f56ec 100644
--- a/grpc-api/pom.xml
+++ b/grpc-api/pom.xml
@@ -3,7 +3,7 @@
tessera
com.quorum.tessera
- 0.7
+ 0.7.1-SNAPSHOT
4.0.0
diff --git a/grpc-service/pom.xml b/grpc-service/pom.xml
index 2bfefa3aed..7c1de59129 100644
--- a/grpc-service/pom.xml
+++ b/grpc-service/pom.xml
@@ -4,7 +4,7 @@
com.quorum.tessera
tessera
- 0.7
+ 0.7.1-SNAPSHOT
grpc-service
jar
diff --git a/grpc/pom.xml b/grpc/pom.xml
index 1478bfcc03..56a268f06b 100644
--- a/grpc/pom.xml
+++ b/grpc/pom.xml
@@ -3,7 +3,7 @@
tessera
com.quorum.tessera
- 0.7
+ 0.7.1-SNAPSHOT
4.0.0
diff --git a/jaxrs-client/pom.xml b/jaxrs-client/pom.xml
index cec7835a9a..3c758eb000 100644
--- a/jaxrs-client/pom.xml
+++ b/jaxrs-client/pom.xml
@@ -4,7 +4,7 @@
com.quorum.tessera
tessera
- 0.7
+ 0.7.1-SNAPSHOT
jaxrs-client
jar
diff --git a/jaxrs-service/pom.xml b/jaxrs-service/pom.xml
index 21380ab061..63dd21fbb0 100644
--- a/jaxrs-service/pom.xml
+++ b/jaxrs-service/pom.xml
@@ -4,7 +4,7 @@
com.quorum.tessera
tessera
- 0.7
+ 0.7.1-SNAPSHOT
jaxrs-service
jar
diff --git a/jaxrs-service/src/main/java/com/quorum/tessera/api/ConfigResource.java b/jaxrs-service/src/main/java/com/quorum/tessera/api/ConfigResource.java
index 2e33d1176a..b8e80f1c07 100644
--- a/jaxrs-service/src/main/java/com/quorum/tessera/api/ConfigResource.java
+++ b/jaxrs-service/src/main/java/com/quorum/tessera/api/ConfigResource.java
@@ -2,6 +2,9 @@
import com.quorum.tessera.config.Peer;
import com.quorum.tessera.core.config.ConfigService;
+import com.quorum.tessera.node.PartyInfoService;
+import com.quorum.tessera.node.model.Party;
+import com.quorum.tessera.node.model.PartyInfo;
import javax.validation.Valid;
import javax.ws.rs.*;
@@ -9,6 +12,7 @@
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import java.net.URI;
+import java.util.Collections;
import java.util.List;
import java.util.Objects;
import javax.ws.rs.core.GenericEntity;
@@ -20,9 +24,15 @@ public class ConfigResource {
private final ConfigService configService;
- public ConfigResource(final ConfigService configService) {
+ private final PartyInfoService partyInfoService;
+
+ public ConfigResource(ConfigService configService,
+ PartyInfoService partyInfoService) {
this.configService = Objects.requireNonNull(configService);
+ this.partyInfoService = Objects.requireNonNull(partyInfoService);
}
+
+
@PUT
@Path("/peers")
@@ -30,6 +40,10 @@ public Response addPeer(@Valid final Peer peer) {
this.configService.addPeer(peer.getUrl());
+ partyInfoService.updatePartyInfo(
+ new PartyInfo(peer.getUrl(),Collections.EMPTY_SET,
+ Collections.singleton(new Party(peer.getUrl()))));
+
//TODO: this seems a bit presumptuous, search for the peer instead?
final int index = this.configService.getPeers().size() - 1;
diff --git a/jaxrs-service/src/main/java/com/quorum/tessera/api/exception/KeyNotFoundExceptionMapper.java b/jaxrs-service/src/main/java/com/quorum/tessera/api/exception/KeyNotFoundExceptionMapper.java
index 9f49c8b7c4..a3cbe74533 100644
--- a/jaxrs-service/src/main/java/com/quorum/tessera/api/exception/KeyNotFoundExceptionMapper.java
+++ b/jaxrs-service/src/main/java/com/quorum/tessera/api/exception/KeyNotFoundExceptionMapper.java
@@ -16,7 +16,8 @@ public class KeyNotFoundExceptionMapper implements ExceptionMapper
+
diff --git a/jaxrs-service/src/test/java/com/quorum/tessera/api/ConfigResourceTest.java b/jaxrs-service/src/test/java/com/quorum/tessera/api/ConfigResourceTest.java
index 1946d46790..d48c6cd0a1 100644
--- a/jaxrs-service/src/test/java/com/quorum/tessera/api/ConfigResourceTest.java
+++ b/jaxrs-service/src/test/java/com/quorum/tessera/api/ConfigResourceTest.java
@@ -2,6 +2,8 @@
import com.quorum.tessera.config.Peer;
import com.quorum.tessera.core.config.ConfigService;
+import com.quorum.tessera.node.PartyInfoService;
+import com.quorum.tessera.node.model.PartyInfo;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -11,6 +13,7 @@
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import org.mockito.Mockito;
import static org.mockito.Mockito.mock;
@@ -24,15 +27,19 @@ public class ConfigResourceTest {
private ConfigService configService;
+ private PartyInfoService partyInfoService;
+
@Before
public void onSetUp() {
configService = mock(ConfigService.class);
- configResource = new ConfigResource(configService);
+ partyInfoService = mock(PartyInfoService.class);
+ configResource = new ConfigResource(configService,partyInfoService);
+
}
@After
public void onTearDown() {
- verifyNoMoreInteractions(configService);
+ verifyNoMoreInteractions(configService,partyInfoService);
}
@Test
@@ -53,6 +60,7 @@ public void addPeerIsSucessful() {
assertThat(peers).containsExactly(peer);
verify(configService).addPeer(peer.getUrl());
verify(configService).getPeers();
+ verify(partyInfoService).updatePartyInfo(any(PartyInfo.class));
}
@Test
@@ -66,7 +74,6 @@ public void getPeerIsSucessful() {
assertThat(response.getEntity()).isEqualTo(peer);
verify(configService).getPeers();
-
}
@Test
diff --git a/key-generation/pom.xml b/key-generation/pom.xml
index dfba05253d..02f0496ac0 100644
--- a/key-generation/pom.xml
+++ b/key-generation/pom.xml
@@ -3,7 +3,7 @@
tessera
com.quorum.tessera
- 0.7
+ 0.7.1-SNAPSHOT
4.0.0
diff --git a/key-generation/src/test/java/com/quorum/tessera/key/generation/AzureVaultKeyGeneratorTest.java b/key-generation/src/test/java/com/quorum/tessera/key/generation/AzureVaultKeyGeneratorTest.java
index a9bc09cf54..2d8bda2460 100644
--- a/key-generation/src/test/java/com/quorum/tessera/key/generation/AzureVaultKeyGeneratorTest.java
+++ b/key-generation/src/test/java/com/quorum/tessera/key/generation/AzureVaultKeyGeneratorTest.java
@@ -107,7 +107,7 @@ public void allowedCharactersUsedInVaultIdDoesNotThrowException() {
@Test
public void exceptionThrownIfDisallowedCharactersUsedInVaultId() {
- final String invalidId = "!@£$%^&*()";
+ final String invalidId = "/tmp/abc@+";
final Throwable throwable = catchThrowable(
() -> azureVaultKeyGenerator.generate(invalidId, null)
diff --git a/key-vault/azure-key-vault/pom.xml b/key-vault/azure-key-vault/pom.xml
index 94d9150eed..98c8ec6837 100644
--- a/key-vault/azure-key-vault/pom.xml
+++ b/key-vault/azure-key-vault/pom.xml
@@ -3,7 +3,7 @@
key-vault
com.quorum.tessera
- 0.7
+ 0.7.1-SNAPSHOT
4.0.0
diff --git a/key-vault/key-vault-api/pom.xml b/key-vault/key-vault-api/pom.xml
index cf31372b71..c91c6b1f06 100644
--- a/key-vault/key-vault-api/pom.xml
+++ b/key-vault/key-vault-api/pom.xml
@@ -3,7 +3,7 @@
key-vault
com.quorum.tessera
- 0.7
+ 0.7.1-SNAPSHOT
4.0.0
diff --git a/key-vault/pom.xml b/key-vault/pom.xml
index 3fedf92671..1192dcab4f 100644
--- a/key-vault/pom.xml
+++ b/key-vault/pom.xml
@@ -3,7 +3,7 @@
tessera
com.quorum.tessera
- 0.7
+ 0.7.1-SNAPSHOT
4.0.0
diff --git a/pom.xml b/pom.xml
index 9596e6d89f..66fe160be7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
com.quorum.tessera
tessera
- 0.7
+ 0.7.1-SNAPSHOT
tessera
pom
@@ -20,7 +20,7 @@
https://github.com/jpmorganchase/tessera
scm:git:git://github.com/jpmorganchase/tessera.git
scm:git:git@github.com:jpmorganchase/tessera.git
- tessera-0.7
+ patch-release-0.7.1
@@ -68,7 +68,7 @@
org.apache.maven.plugins
maven-surefire-plugin
- 2.22.0
+ 3.0.0-M1
true
@@ -269,148 +269,148 @@
com.quorum.tessera
encryption-api
- 0.7
+ 0.7.1-SNAPSHOT
com.quorum.tessera
argon2
- 0.7
+ 0.7.1-SNAPSHOT
com.quorum.tessera
config
- 0.7
+ 0.7.1-SNAPSHOT
com.quorum.tessera
config-cli
- 0.7
+ 0.7.1-SNAPSHOT
com.quorum.tessera
security
- 0.7
+ 0.7.1-SNAPSHOT
com.quorum.tessera
encryption-jnacl
- 0.7
+ 0.7.1-SNAPSHOT
runtime
com.quorum.tessera
encryption-kalium
- 0.7
+ 0.7.1-SNAPSHOT
runtime
com.quorum.tessera
service-locator-api
- 0.7
+ 0.7.1-SNAPSHOT
com.quorum.tessera
service-locator-spring
- 0.7
+ 0.7.1-SNAPSHOT
com.quorum.tessera
server-api
- 0.7
+ 0.7.1-SNAPSHOT
com.quorum.tessera
jersey-server
- 0.7
+ 0.7.1-SNAPSHOT
com.quorum.tessera
resteasy-server
- 0.7
+ 0.7.1-SNAPSHOT
com.quorum.tessera
grpc-server
- 0.7
+ 0.7.1-SNAPSHOT
com.quorum.tessera
grpc
- 0.7
+ 0.7.1-SNAPSHOT
com.quorum.tessera
grpc-api
- 0.7
+ 0.7.1-SNAPSHOT
com.quorum.tessera
test-util
- 0.7
+ 0.7.1-SNAPSHOT
test
com.quorum.tessera
shared
- 0.7
+ 0.7.1-SNAPSHOT
com.quorum.tessera
tessera-core
- 0.7
+ 0.7.1-SNAPSHOT
com.quorum.tessera
grpc-service
- 0.7
+ 0.7.1-SNAPSHOT
com.quorum.tessera
jaxrs-service
- 0.7
+ 0.7.1-SNAPSHOT
com.quorum.tessera
key-vault-api
- 0.7
+ 0.7.1-SNAPSHOT
com.quorum.tessera
azure-key-vault
- 0.7
+ 0.7.1-SNAPSHOT
com.quorum.tessera
key-generation
- 0.7
+ 0.7.1-SNAPSHOT
com.quorum.tessera
jaxrs-client
- 0.7
+ 0.7.1-SNAPSHOT
diff --git a/security/pom.xml b/security/pom.xml
index d04f53e69c..16a3cd2223 100644
--- a/security/pom.xml
+++ b/security/pom.xml
@@ -4,7 +4,7 @@
tessera
com.quorum.tessera
- 0.7
+ 0.7.1-SNAPSHOT
4.0.0
diff --git a/server/grpc-server/pom.xml b/server/grpc-server/pom.xml
index 30347e8f26..67fd0fe701 100644
--- a/server/grpc-server/pom.xml
+++ b/server/grpc-server/pom.xml
@@ -4,7 +4,7 @@
server
com.quorum.tessera
- 0.7
+ 0.7.1-SNAPSHOT
4.0.0
diff --git a/server/jersey-server/pom.xml b/server/jersey-server/pom.xml
index 8ba53679d5..e30bb52a85 100644
--- a/server/jersey-server/pom.xml
+++ b/server/jersey-server/pom.xml
@@ -11,7 +11,7 @@
com.quorum.tessera
server
- 0.7
+ 0.7.1-SNAPSHOT
diff --git a/server/pom.xml b/server/pom.xml
index c544ed13ab..bddb4fb58f 100644
--- a/server/pom.xml
+++ b/server/pom.xml
@@ -9,7 +9,7 @@
tessera
com.quorum.tessera
- 0.7
+ 0.7.1-SNAPSHOT
diff --git a/server/resteasy-server/pom.xml b/server/resteasy-server/pom.xml
index ac8282c6e4..879d12f678 100644
--- a/server/resteasy-server/pom.xml
+++ b/server/resteasy-server/pom.xml
@@ -4,7 +4,7 @@
com.quorum.tessera
server
- 0.7
+ 0.7.1-SNAPSHOT
resteasy-server
jar
diff --git a/server/server-api/pom.xml b/server/server-api/pom.xml
index a81baf9d9a..4be52a4c0e 100644
--- a/server/server-api/pom.xml
+++ b/server/server-api/pom.xml
@@ -9,7 +9,7 @@
com.quorum.tessera
server
- 0.7
+ 0.7.1-SNAPSHOT
diff --git a/server/unix-socket-server/pom.xml b/server/unix-socket-server/pom.xml
index 24dcc5e811..c30fd53ba4 100644
--- a/server/unix-socket-server/pom.xml
+++ b/server/unix-socket-server/pom.xml
@@ -9,7 +9,7 @@
server
com.quorum.tessera
- 0.7
+ 0.7.1-SNAPSHOT
diff --git a/service-locator/pom.xml b/service-locator/pom.xml
index ce06405b7b..f347ba7acc 100644
--- a/service-locator/pom.xml
+++ b/service-locator/pom.xml
@@ -9,7 +9,7 @@
tessera
com.quorum.tessera
- 0.7
+ 0.7.1-SNAPSHOT
diff --git a/service-locator/service-locator-api/pom.xml b/service-locator/service-locator-api/pom.xml
index cf309e0526..ce3ed87ec7 100644
--- a/service-locator/service-locator-api/pom.xml
+++ b/service-locator/service-locator-api/pom.xml
@@ -11,7 +11,7 @@
com.quorum.tessera
service-locator
- 0.7
+ 0.7.1-SNAPSHOT
\ No newline at end of file
diff --git a/service-locator/service-locator-spring/pom.xml b/service-locator/service-locator-spring/pom.xml
index dbee07f961..3be7ecacab 100644
--- a/service-locator/service-locator-spring/pom.xml
+++ b/service-locator/service-locator-spring/pom.xml
@@ -11,7 +11,7 @@
com.quorum.tessera
service-locator
- 0.7
+ 0.7.1-SNAPSHOT
diff --git a/shared/pom.xml b/shared/pom.xml
index 09ae8e8bec..e351ea7089 100644
--- a/shared/pom.xml
+++ b/shared/pom.xml
@@ -4,7 +4,7 @@
com.quorum.tessera
tessera
- 0.7
+ 0.7.1-SNAPSHOT
shared
jar
diff --git a/tessera-app/pom.xml b/tessera-app/pom.xml
index 881fc513f8..d44430fb88 100644
--- a/tessera-app/pom.xml
+++ b/tessera-app/pom.xml
@@ -8,7 +8,7 @@
com.quorum.tessera
tessera
- 0.7
+ 0.7.1-SNAPSHOT
@@ -54,7 +54,7 @@
com.quorum.tessera
unix-socket-server
- 0.7
+ 0.7.1-SNAPSHOT
runtime
diff --git a/tessera-core/pom.xml b/tessera-core/pom.xml
index f9f49a038c..2144a69eaf 100644
--- a/tessera-core/pom.xml
+++ b/tessera-core/pom.xml
@@ -4,7 +4,7 @@
com.quorum.tessera
tessera
- 0.7
+ 0.7.1-SNAPSHOT
tessera-core
jar
diff --git a/tessera-core/src/main/java/com/quorum/tessera/node/PartyInfoParser.java b/tessera-core/src/main/java/com/quorum/tessera/node/PartyInfoParser.java
index 405635e093..3f1cf9e447 100644
--- a/tessera-core/src/main/java/com/quorum/tessera/node/PartyInfoParser.java
+++ b/tessera-core/src/main/java/com/quorum/tessera/node/PartyInfoParser.java
@@ -5,6 +5,7 @@
import com.quorum.tessera.node.model.PartyInfo;
import com.quorum.tessera.node.model.Recipient;
import com.quorum.tessera.util.BinaryEncoder;
+import static java.lang.Math.toIntExact;
import org.apache.commons.lang3.ArrayUtils;
import java.nio.ByteBuffer;
@@ -15,6 +16,7 @@
import java.util.stream.Collectors;
import static java.nio.charset.StandardCharsets.UTF_8;
+import java.util.Optional;
/**
* A parser for PartyInfo node discovery information
@@ -32,24 +34,33 @@ default PartyInfo from(final byte[] encoded) {
final ByteBuffer byteBuffer = ByteBuffer.wrap(encoded);
- final int urlLength = (int) byteBuffer.getLong();
+ final int urlLength = (int) toIntExact(byteBuffer.getLong());
+ checkLength(urlLength);
+
final byte[] urlBytes = new byte[urlLength];
byteBuffer.get(urlBytes);
final String url = new String(urlBytes, UTF_8);
- final int numberOfRecipients = (int) byteBuffer.getLong();
+ final int numberOfRecipients = (int) toIntExact(byteBuffer.getLong());
+ checkLength(urlLength);
final Set recipients = new HashSet<>();
for (int i = 0; i < numberOfRecipients; i++) {
- final int recipientKeyLength = (int) byteBuffer.getLong();
+ final int recipientKeyLength = (int) toIntExact(byteBuffer.getLong());
+ checkLength(recipientKeyLength);
+
final byte[] recipientKeyBytes = new byte[recipientKeyLength];
byteBuffer.get(recipientKeyBytes);
- final int recipientUrlValueLength = (int) byteBuffer.getLong();
+ final int recipientUrlValueLength = (int) toIntExact(byteBuffer.getLong());
+ checkLength(recipientUrlValueLength);
+
final byte[] urlValueData = new byte[recipientUrlValueLength];
+
+
byteBuffer.get(urlValueData);
final String recipientUrl = new String(urlValueData, UTF_8);
@@ -57,12 +68,15 @@ default PartyInfo from(final byte[] encoded) {
}
- final int partyCount = (int) byteBuffer.getLong();
-
+ final int partyCount = (int) toIntExact(byteBuffer.getLong());
+ checkLength(partyCount);
+
final Party[] parties = new Party[partyCount];
for (int i = 0; i < partyCount; i++) {
long partyElementLength = byteBuffer.getLong();
- byte[] ptyData = new byte[(int) partyElementLength];
+ checkLength(partyElementLength);
+
+ byte[] ptyData = new byte[(int) toIntExact(partyElementLength)];
byteBuffer.get(ptyData);
String ptyURL = new String(ptyData, UTF_8);
parties[i] = new Party(ptyURL);
@@ -89,28 +103,28 @@ default byte[] to(final PartyInfo partyInfo) {
//each element in the list is one encoded element from the map
//so the prefix is always 2 (2 elements) and
final List recipients = partyInfo.getRecipients()
- .stream()
- .map(r -> {
- final byte[] encodedKey = encodeField(r.getKey().getKeyBytes());
- final byte[] encodedUrl = encodeField(r.getUrl().getBytes(UTF_8));
-
- //using Apache Commons array utils since it is already available
- //other concat the two arrays manually
- return ArrayUtils.addAll(encodedKey, encodedUrl);
- }).collect(Collectors.toList());
+ .stream()
+ .map(r -> {
+ final byte[] encodedKey = encodeField(r.getKey().getKeyBytes());
+ final byte[] encodedUrl = encodeField(r.getUrl().getBytes(UTF_8));
+
+ //using Apache Commons array utils since it is already available
+ //other concat the two arrays manually
+ return ArrayUtils.addAll(encodedKey, encodedUrl);
+ }).collect(Collectors.toList());
final int recipientLength = recipients.stream().mapToInt(r -> r.length).sum();
final List parties = partyInfo.getParties()
- .stream()
- .map(p -> p.getUrl().getBytes(UTF_8))
- .collect(Collectors.toList());
+ .stream()
+ .map(p -> p.getUrl().getBytes(UTF_8))
+ .collect(Collectors.toList());
final byte[] partiesBytes = encodeArray(parties);
final ByteBuffer byteBuffer = ByteBuffer
- .allocate(url.length + Long.BYTES + recipientLength + partiesBytes.length)
- .put(url)
- .putLong(partyInfo.getRecipients().size());
+ .allocate(url.length + Long.BYTES + recipientLength + partiesBytes.length)
+ .put(url)
+ .putLong(partyInfo.getRecipients().size());
recipients.forEach(byteBuffer::put);
byteBuffer.put(partiesBytes);
@@ -129,4 +143,19 @@ static PartyInfoParser create() {
};
}
+
+ static void checkLength(long value) {
+ Optional.of(value)
+ .filter(v -> v >= 0)
+ .filter(v -> v < Long.MAX_VALUE - 1)
+ .orElseThrow(() -> new PartyInfoParserException("Invalid length "+ value));
+ }
+
+ static void checkLength(int value) {
+ Optional.of(value)
+ .filter(v -> v >= 0)
+ .filter(v -> v < Integer.MAX_VALUE - 1)
+ .orElseThrow(() -> new PartyInfoParserException("Invalid length "+ value));
+ }
+
}
diff --git a/tessera-core/src/main/java/com/quorum/tessera/node/PartyInfoParserException.java b/tessera-core/src/main/java/com/quorum/tessera/node/PartyInfoParserException.java
new file mode 100644
index 0000000000..1c2b28b28c
--- /dev/null
+++ b/tessera-core/src/main/java/com/quorum/tessera/node/PartyInfoParserException.java
@@ -0,0 +1,13 @@
+
+package com.quorum.tessera.node;
+
+import com.quorum.tessera.exception.TesseraException;
+
+
+public class PartyInfoParserException extends TesseraException {
+
+ public PartyInfoParserException(String message) {
+ super(message);
+ }
+
+}
diff --git a/tessera-core/src/main/java/com/quorum/tessera/node/PartyInfoServiceImpl.java b/tessera-core/src/main/java/com/quorum/tessera/node/PartyInfoServiceImpl.java
index b39560cba7..6584eb6139 100644
--- a/tessera-core/src/main/java/com/quorum/tessera/node/PartyInfoServiceImpl.java
+++ b/tessera-core/src/main/java/com/quorum/tessera/node/PartyInfoServiceImpl.java
@@ -35,14 +35,22 @@ public PartyInfoServiceImpl(final PartyInfoStore partyInfoStore,
final String advertisedUrl = configService.getServerUri() + "/";
+ final Set initialParties = configService
+ .getPeers()
+ .stream()
+ .map(Peer::getUrl)
+ .map(Party::new)
+ .collect(toSet());
+
final Set ourKeys = keyManager
- .getPublicKeys()
- .stream()
- .map(key -> PublicKey.from(key.getKeyBytes()))
- .map(key -> new Recipient(key, advertisedUrl))
- .collect(toSet());
+ .getPublicKeys()
+ .stream()
+ .map(key -> PublicKey.from(key.getKeyBytes()))
+ .map(key -> new Recipient(key, advertisedUrl))
+ .collect(toSet());
+
+ partyInfoStore.store(new PartyInfo(advertisedUrl, ourKeys, initialParties));
- partyInfoStore.store(new PartyInfo(advertisedUrl, ourKeys, Collections.emptySet()));
}
@Override
@@ -105,7 +113,7 @@ public String getURLFromRecipientKey(final PublicKey key) {
.stream()
.filter(recipient -> key.equals(recipient.getKey()))
.findAny()
- .orElseThrow(() -> new KeyNotFoundException("Recipient not found"));
+ .orElseThrow(() -> new KeyNotFoundException("Recipient not found for key: "+ key.encodeToBase64()));
return retrievedRecipientFromStore.getUrl();
}
diff --git a/tessera-core/src/main/java/com/quorum/tessera/node/model/Party.java b/tessera-core/src/main/java/com/quorum/tessera/node/model/Party.java
index 1361f96233..4de2499b81 100644
--- a/tessera-core/src/main/java/com/quorum/tessera/node/model/Party.java
+++ b/tessera-core/src/main/java/com/quorum/tessera/node/model/Party.java
@@ -27,4 +27,11 @@ public int hashCode() {
return Objects.hash(url);
}
+ @Override
+ public String toString() {
+ return "Party{" + "url=" + url + '}';
+ }
+
+
+
}
diff --git a/tessera-core/src/main/resources/tessera-core-spring.xml b/tessera-core/src/main/resources/tessera-core-spring.xml
index fda9ca78dd..a9b7559ed7 100644
--- a/tessera-core/src/main/resources/tessera-core-spring.xml
+++ b/tessera-core/src/main/resources/tessera-core-spring.xml
@@ -40,25 +40,10 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
@@ -225,4 +210,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tessera-core/src/test/java/com/quorum/tessera/node/PartyInfoParserExceptionTest.java b/tessera-core/src/test/java/com/quorum/tessera/node/PartyInfoParserExceptionTest.java
new file mode 100644
index 0000000000..5884fb73d0
--- /dev/null
+++ b/tessera-core/src/test/java/com/quorum/tessera/node/PartyInfoParserExceptionTest.java
@@ -0,0 +1,19 @@
+
+package com.quorum.tessera.node;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import org.junit.Test;
+
+
+public class PartyInfoParserExceptionTest {
+
+ @Test
+ public void createWithMessage() {
+
+ PartyInfoParserException result = new PartyInfoParserException("OUCH");
+
+ assertThat(result).hasMessage("OUCH");
+
+ }
+
+}
diff --git a/tessera-core/src/test/java/com/quorum/tessera/node/PartyInfoParserTest.java b/tessera-core/src/test/java/com/quorum/tessera/node/PartyInfoParserTest.java
index 6deefb6a52..4eedfe22e1 100644
--- a/tessera-core/src/test/java/com/quorum/tessera/node/PartyInfoParserTest.java
+++ b/tessera-core/src/test/java/com/quorum/tessera/node/PartyInfoParserTest.java
@@ -14,7 +14,7 @@
public class PartyInfoParserTest {
- private final int[] sampleDataTwo = new int[]{0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 52, 58, 57, 48, 48, 52, 47, 0, 0, 0, 0, 0, 0, 0, 7,0, 0, 0, 0, 0, 0, 0, 32, 214, 36, 217, 117, 239, 231, 116, 17, 239, 206, 23, 37, 237, 94, 188, 199, 142, 21, 199, 186, 101, 242, 124, 49, 244, 186, 167, 51, 240, 31, 37, 72, 0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 51, 58, 57, 48, 48, 51, 47, 0, 0, 0, 0, 0, 0, 0, 32, 81, 243, 82, 121, 33, 178, 73, 226, 160, 215, 80, 213, 52, 73, 234, 173, 75, 113, 97, 21, 104, 175, 143, 130, 190, 91, 136, 242, 213, 111, 235, 102, 0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 54, 58, 57, 48, 48, 54, 47, 0, 0, 0, 0, 0, 0, 0, 32, 160, 219, 41, 60, 248, 44, 205, 85, 5, 195, 74, 166, 24, 87, 214, 194, 29, 110, 197, 85, 23, 130, 240, 113, 149, 229, 206, 68, 120, 244, 238, 15, 0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 52, 58, 57, 48, 48, 52, 47, 0, 0, 0, 0, 0, 0, 0, 32, 71, 158, 160, 203, 135, 103, 219, 134, 14, 143, 12, 158, 177, 55, 51, 97, 175, 38, 231, 24, 79, 234, 17, 118, 185, 51, 2, 142, 239, 245, 198, 70, 0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 53, 58, 57, 48, 48, 53, 47, 0, 0, 0, 0, 0, 0, 0, 32, 68, 224, 25, 5, 107, 82, 105, 204, 87, 66, 179, 158, 220, 81, 128, 168, 144, 242, 38, 49, 94, 61, 30, 92, 123, 132, 210, 35, 57, 137, 208, 23, 0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 55, 58, 57, 48, 48, 55, 47, 0, 0, 0, 0, 0, 0, 0, 32, 5, 66, 222, 71, 194, 114, 81, 104, 98, 186, 224, 140, 83, 241, 203, 3, 68, 57, 167, 57, 24, 79, 231, 7, 32, 141, 217, 40, 23, 178, 220, 26, 0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 49, 58, 57, 48, 48, 49, 47, 0, 0, 0, 0, 0, 0, 0, 32, 65, 247, 131, 3, 43, 61, 48, 240, 236, 217, 113, 196, 198, 215, 60, 226, 50, 134, 31, 22, 96, 253, 168, 249, 216, 52, 225, 210, 251, 64, 221, 119, 0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 50, 58, 57, 48, 48, 50, 47, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 49, 58, 57, 48, 48, 49, 47, 0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 55, 58, 57, 48, 48, 55, 47, 0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 54, 58, 57, 48, 48, 54, 47, 0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 52, 58, 57, 48, 48, 52, 47, 0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 50, 58, 57, 48, 48, 50, 47, 0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 53, 58, 57, 48, 48, 53, 47, 0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 51, 58, 57, 48, 48, 51, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ private final int[] sampleDataTwo = new int[]{0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 52, 58, 57, 48, 48, 52, 47, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 32, 214, 36, 217, 117, 239, 231, 116, 17, 239, 206, 23, 37, 237, 94, 188, 199, 142, 21, 199, 186, 101, 242, 124, 49, 244, 186, 167, 51, 240, 31, 37, 72, 0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 51, 58, 57, 48, 48, 51, 47, 0, 0, 0, 0, 0, 0, 0, 32, 81, 243, 82, 121, 33, 178, 73, 226, 160, 215, 80, 213, 52, 73, 234, 173, 75, 113, 97, 21, 104, 175, 143, 130, 190, 91, 136, 242, 213, 111, 235, 102, 0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 54, 58, 57, 48, 48, 54, 47, 0, 0, 0, 0, 0, 0, 0, 32, 160, 219, 41, 60, 248, 44, 205, 85, 5, 195, 74, 166, 24, 87, 214, 194, 29, 110, 197, 85, 23, 130, 240, 113, 149, 229, 206, 68, 120, 244, 238, 15, 0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 52, 58, 57, 48, 48, 52, 47, 0, 0, 0, 0, 0, 0, 0, 32, 71, 158, 160, 203, 135, 103, 219, 134, 14, 143, 12, 158, 177, 55, 51, 97, 175, 38, 231, 24, 79, 234, 17, 118, 185, 51, 2, 142, 239, 245, 198, 70, 0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 53, 58, 57, 48, 48, 53, 47, 0, 0, 0, 0, 0, 0, 0, 32, 68, 224, 25, 5, 107, 82, 105, 204, 87, 66, 179, 158, 220, 81, 128, 168, 144, 242, 38, 49, 94, 61, 30, 92, 123, 132, 210, 35, 57, 137, 208, 23, 0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 55, 58, 57, 48, 48, 55, 47, 0, 0, 0, 0, 0, 0, 0, 32, 5, 66, 222, 71, 194, 114, 81, 104, 98, 186, 224, 140, 83, 241, 203, 3, 68, 57, 167, 57, 24, 79, 231, 7, 32, 141, 217, 40, 23, 178, 220, 26, 0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 49, 58, 57, 48, 48, 49, 47, 0, 0, 0, 0, 0, 0, 0, 32, 65, 247, 131, 3, 43, 61, 48, 240, 236, 217, 113, 196, 198, 215, 60, 226, 50, 134, 31, 22, 96, 253, 168, 249, 216, 52, 225, 210, 251, 64, 221, 119, 0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 50, 58, 57, 48, 48, 50, 47, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 49, 58, 57, 48, 48, 49, 47, 0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 55, 58, 57, 48, 48, 55, 47, 0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 54, 58, 57, 48, 48, 54, 47, 0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 52, 58, 57, 48, 48, 52, 47, 0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 50, 58, 57, 48, 48, 50, 47, 0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 53, 58, 57, 48, 48, 53, 47, 0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 51, 58, 57, 48, 48, 51, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
private byte[] dataTwo;
@@ -139,7 +139,7 @@ public void toUsingSameInfoFromFixture() {
final byte[] keyData = new byte[32];
byteBuffer.get(keyData);
assertThat(keyData).hasSize(32)
- .isEqualTo(partyInfo.getRecipients().iterator().next().getKey().getKeyBytes());
+ .isEqualTo(partyInfo.getRecipients().iterator().next().getKey().getKeyBytes());
long recipientUrlLength = byteBuffer.getLong();
assertThat(recipientUrlLength).isEqualTo(21L);
@@ -164,4 +164,35 @@ public void toUsingSameInfoFromFixture() {
}
+ @Test
+ public void checkLengthZero() {
+ PartyInfoParser.checkLength(0);
+ //NO ERROR
+ }
+
+ @Test(expected = PartyInfoParserException.class)
+ public void checkLengthMinusValue() {
+ PartyInfoParser.checkLength(-1);
+ }
+
+ @Test
+ public void checkLengthZeroLong() {
+ PartyInfoParser.checkLength((long) 0);
+ }
+
+ @Test(expected = PartyInfoParserException.class)
+ public void checkLengthMaxValue() {
+ PartyInfoParser.checkLength(Integer.MAX_VALUE);
+ }
+
+ @Test(expected = PartyInfoParserException.class)
+ public void checkLengthMinusValueLong() {
+ PartyInfoParser.checkLength((long) -1);
+ }
+
+ @Test(expected = PartyInfoParserException.class)
+ public void checkLengthMaxValueLong() {
+ PartyInfoParser.checkLength(Long.MAX_VALUE);
+ }
+
}
diff --git a/tessera-core/src/test/java/com/quorum/tessera/node/PartyInfoServiceTest.java b/tessera-core/src/test/java/com/quorum/tessera/node/PartyInfoServiceTest.java
index 1b8eea1128..fd9cdcf47c 100644
--- a/tessera-core/src/test/java/com/quorum/tessera/node/PartyInfoServiceTest.java
+++ b/tessera-core/src/test/java/com/quorum/tessera/node/PartyInfoServiceTest.java
@@ -70,6 +70,7 @@ public void after() {
//Called in constructor
verify(keyManager).getPublicKeys();
verify(configService).getServerUri();
+ verify(configService,atLeast(1)).getPeers();
verify(partyInfoStore, atLeast(1)).store(any(PartyInfo.class));
verifyNoMoreInteractions(partyInfoStore);
@@ -120,7 +121,7 @@ public void getRecipientURLFromPartyInfoStoreFailsIfKeyDoesntExist() {
final PublicKey failingKey = PublicKey.from("otherKey".getBytes());
final Throwable throwable = catchThrowable(() -> partyInfoService.getURLFromRecipientKey(failingKey));
- assertThat(throwable).isInstanceOf(KeyNotFoundException.class).hasMessage("Recipient not found");
+ assertThat(throwable).isInstanceOf(KeyNotFoundException.class).hasMessage("Recipient not found for key: "+ failingKey.encodeToBase64());
verify(partyInfoStore).getPartyInfo();
}
@@ -205,7 +206,6 @@ public void autoDiscoveryDisabledUnknownPeer() {
.hasMessage("Peer SomeUnknownUri not found in known peer list");
verify(configService).isDisablePeerDiscovery();
- verify(configService).getPeers();
}
@@ -227,7 +227,7 @@ public void autoDiscoveryDisabledOnlyKnownKeysAdded() {
verify(configService).isDisablePeerDiscovery();
- verify(configService).getPeers();
+ verify(configService,times(2)).getPeers();
//check that the only added keys were from that node (and our own)
final ArgumentCaptor captor = ArgumentCaptor.forClass(PartyInfo.class);
@@ -263,27 +263,18 @@ public void autoDiscoveryDisabledNoIncomingPeersAdded() {
Stream.of(new Party("known"), new Party("unknown")).collect(toSet())
);
+
partyInfoService.updatePartyInfo(forUpdate);
verify(configService).isDisablePeerDiscovery();
- verify(configService).getPeers();
+ verify(configService,times(2)).getPeers();
//check that the only added keys were from that node (and our own)
final ArgumentCaptor captor = ArgumentCaptor.forClass(PartyInfo.class);
verify(partyInfoStore).getPartyInfo();
- verify(partyInfoStore, times(2)).store(captor.capture());
-
- final List allRegisteredParties = captor
- .getAllValues()
- .stream()
- .map(PartyInfo::getParties)
- .flatMap(Set::stream)
- .collect(toList());
+ verify(partyInfoStore,times(2)).store(captor.capture());
- assertThat(allRegisteredParties)
- .hasSize(1)
- .containsExactlyInAnyOrder(new Party("http://other-node.com:8080"));
}
diff --git a/tessera-core/src/test/java/com/quorum/tessera/node/PartyTest.java b/tessera-core/src/test/java/com/quorum/tessera/node/PartyTest.java
new file mode 100644
index 0000000000..af545fdd4f
--- /dev/null
+++ b/tessera-core/src/test/java/com/quorum/tessera/node/PartyTest.java
@@ -0,0 +1,20 @@
+
+package com.quorum.tessera.node;
+
+import com.quorum.tessera.node.model.Party;
+import static org.assertj.core.api.Assertions.assertThat;
+import org.junit.Test;
+
+
+public class PartyTest {
+
+ @Test
+ public void toStringContainsUrl() {
+ Party party = new Party("someurl");
+
+ assertThat(party.toString()).contains("someurl");
+
+ }
+
+
+}
diff --git a/tests/acceptance-test/pom.xml b/tests/acceptance-test/pom.xml
index af54337df9..822d092c24 100644
--- a/tests/acceptance-test/pom.xml
+++ b/tests/acceptance-test/pom.xml
@@ -9,7 +9,7 @@
com.quorum.tessera
tests
- 0.7
+ 0.7.1-SNAPSHOT
@@ -18,7 +18,7 @@
com.quorum.tessera
tessera-app
app
- 0.7
+ 0.7.1-SNAPSHOT
@@ -58,7 +58,7 @@
org.apache.maven.plugins
maven-failsafe-plugin
- 2.21.0
+ 3.0.0-M1
false
0
diff --git a/tests/acceptance-test/src/test/java/admin/cmd/ExecutionResult.java b/tests/acceptance-test/src/test/java/admin/cmd/ExecutionResult.java
new file mode 100644
index 0000000000..8386140d3c
--- /dev/null
+++ b/tests/acceptance-test/src/test/java/admin/cmd/ExecutionResult.java
@@ -0,0 +1,40 @@
+
+package admin.cmd;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+public class ExecutionResult {
+
+ private int exitCode;
+
+ private final List output = new ArrayList<>();
+
+ private final List errors = new ArrayList<>();
+
+ public int getExitCode() {
+ return exitCode;
+ }
+
+ public void setExitCode(int exitCode) {
+ this.exitCode = exitCode;
+ }
+
+ public void addOutputLine(String line) {
+ this.output.add(line);
+ }
+
+ public void addErrorLine(String line) {
+ this.errors.add(line);
+ }
+
+ public List getOutput() {
+ return output;
+ }
+
+ public List getErrors() {
+ return errors;
+ }
+
+}
diff --git a/tests/acceptance-test/src/test/java/admin/cmd/StartupSteps.java b/tests/acceptance-test/src/test/java/admin/cmd/StartupSteps.java
new file mode 100644
index 0000000000..791aebff3d
--- /dev/null
+++ b/tests/acceptance-test/src/test/java/admin/cmd/StartupSteps.java
@@ -0,0 +1,72 @@
+package admin.cmd;
+
+import com.quorum.tessera.config.Config;
+import com.quorum.tessera.test.Party;
+import com.quorum.tessera.test.util.ElUtil;
+import cucumber.api.java8.En;
+import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import static org.assertj.core.api.Assertions.*;
+
+public class StartupSteps implements En {
+
+ public StartupSteps() {
+
+ List partyHolder = new ArrayList<>();
+
+ Given("configuration file with empty public and private key values", () -> {
+ URL url = getClass().getResource("/empty-keys-config.json");
+
+ Party party = new Party("", url, "X");
+ Config config = party.getConfig();
+ assertThat(config.getKeys().getKeyData().get(0).getPrivateKey()).isEmpty();
+ assertThat(config.getKeys().getKeyData().get(0).getPublicKey()).isEmpty();
+ partyHolder.add(party);
+ });
+
+ Given("configuration file with with key paths containing empty values", () -> {
+ URL url = getClass().getResource("/empty-keyspath-config.json");
+ Path emptyKeyFile = Files.createTempFile(UUID.randomUUID().toString(), "");
+ Path ipcFile = Files.createTempFile(UUID.randomUUID().toString(), "");
+ Map params = new HashMap<>();
+ params.put("emptyKeyFilePath", emptyKeyFile.toAbsolutePath().toString());
+ params.put("unixSocketPath", ipcFile.toAbsolutePath().toString());
+ Path configFile = ElUtil.createTempFileFromTemplate(url, params);
+ Party party = new Party("", configFile.toUri().toURL(), "X");
+ Config config = party.getConfig();
+ assertThat(emptyKeyFile).exists();
+
+ partyHolder.add(party);
+ });
+
+ List results = new ArrayList<>();
+ When("admin user executes start", () -> {
+ assertThat(partyHolder).hasSize(1);
+ Party party = partyHolder.iterator().next();
+ ExecutionResult result = Utils.start(party);
+ results.add(result);
+ });
+
+ Then("node returns error message and exits", () -> {
+ assertThat(results).hasSize(1);
+ ExecutionResult result = results.get(0);
+ assertThat(result.getExitCode()).isNotEqualTo(0);
+ assertThat(result.getOutput()).hasSize(2);
+
+ assertThat(result.getOutput())
+ .anyMatch(m -> m.startsWith("Config validation issue: keys.keyData[0].privateKey"));
+
+ assertThat(result.getOutput())
+ .anyMatch(m -> m.startsWith("Config validation issue: keys.keyData[0].publicKey"));
+
+ });
+
+ }
+
+}
diff --git a/tests/acceptance-test/src/test/java/admin/cmd/Utils.java b/tests/acceptance-test/src/test/java/admin/cmd/Utils.java
index b17ced62a4..651d0133f0 100644
--- a/tests/acceptance-test/src/test/java/admin/cmd/Utils.java
+++ b/tests/acceptance-test/src/test/java/admin/cmd/Utils.java
@@ -1,12 +1,15 @@
package admin.cmd;
+import com.quorum.tessera.config.CommunicationType;
import com.quorum.tessera.test.Party;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
+import java.io.UncheckedIOException;
import java.util.*;
import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Stream;
import org.slf4j.Logger;
@@ -14,21 +17,86 @@
public class Utils {
- private static String jarPath = System.getProperty("application.jar", "../../tessera-app/target/tessera-app-0.7-SNAPSHOT-app.jar");
+ private static String jarPath = System.getProperty("application.jar", "../../tessera-app/target/tessera-app-0.7.1-SNAPSHOT-app.jar");
private static final Logger LOGGER = LoggerFactory.getLogger(Utils.class);
+ public static ExecutionResult start(Party party) throws IOException, InterruptedException {
+
+ List args = Arrays.asList(
+ "java",
+ "-Dspring.profiles.active=disable-unixsocket,disable-sync-poller",
+ "-Dnode.number=" + party.getAlias(),
+ "-jar",
+ jarPath,
+ "-configfile",
+ party.getConfigFilePath().toString(),
+ "-server.communicationType",
+ CommunicationType.REST.name()
+ );
+
+ ExecutorService executorService = Executors.newCachedThreadPool();
+
+ ProcessBuilder processBuilder = new ProcessBuilder(args);
+
+ processBuilder.redirectErrorStream(false);
+ Process process = processBuilder.start();
+
+ ExecutionResult executionResult = new ExecutionResult();
+
+ executorService.submit(() -> {
+
+ try (BufferedReader reader = Stream.of(process.getInputStream())
+ .map(InputStreamReader::new)
+ .map(BufferedReader::new)
+ .findAny().get()) {
+
+ String line = null;
+ while ((line = reader.readLine()) != null) {
+ System.out.println(line);
+ executionResult.addOutputLine(line);
+ }
+
+ } catch (IOException ex) {
+ throw new UncheckedIOException(ex);
+ }
+ });
+
+ executorService.submit(() -> {
+
+ try (BufferedReader reader = Stream.of(process.getErrorStream())
+ .map(InputStreamReader::new)
+ .map(BufferedReader::new)
+ .findAny().get()) {
+
+ String line = null;
+ while ((line = reader.readLine()) != null) {
+ System.err.println(line);
+ executionResult.addErrorLine(line);
+ }
+
+ } catch (IOException ex) {
+ throw new UncheckedIOException(ex);
+ }
+ });
+
+ executionResult.setExitCode(process.waitFor());
+
+ return executionResult;
+
+ }
+
public static int addPeer(Party party, String url) throws IOException, InterruptedException {
-
+
List args = Arrays.asList(
- "java",
- "-jar",
- jarPath,
- "-configfile",
- party.getConfigFilePath().toAbsolutePath().toString(),
- "admin",
- "-addpeer",
- url
+ "java",
+ "-jar",
+ jarPath,
+ "-configfile",
+ party.getConfigFilePath().toAbsolutePath().toString(),
+ "admin",
+ "-addpeer",
+ url
);
LOGGER.info("exec : {}", String.join(" ", args));
@@ -38,13 +106,12 @@ public static int addPeer(Party party, String url) throws IOException, Interrupt
Process process = processBuilder.start();
Collection streamConsumers = Arrays.asList(
- new StreamConsumer(process.getErrorStream(), true),
- new StreamConsumer(process.getInputStream(), false)
+ new StreamConsumer(process.getErrorStream(), true),
+ new StreamConsumer(process.getInputStream(), false)
);
Executors.newCachedThreadPool().invokeAll(streamConsumers);
-
return process.waitFor();
}
@@ -60,15 +127,14 @@ static class StreamConsumer implements Callable {
this.isError = isError;
}
-
@Override
public Void call() throws Exception {
try (BufferedReader reader = Stream.of(inputStream)
- .map(InputStreamReader::new)
- .map(BufferedReader::new)
- .findAny()
- .get()) {
+ .map(InputStreamReader::new)
+ .map(BufferedReader::new)
+ .findAny()
+ .get()) {
String line = null;
while ((line = reader.readLine()) != null) {
@@ -80,7 +146,7 @@ public Void call() throws Exception {
}
return null;
- }
+ }
}
diff --git a/tests/acceptance-test/src/test/java/com/quorum/tessera/test/Party.java b/tests/acceptance-test/src/test/java/com/quorum/tessera/test/Party.java
index c67fcf4edb..dc19d16fa3 100644
--- a/tests/acceptance-test/src/test/java/com/quorum/tessera/test/Party.java
+++ b/tests/acceptance-test/src/test/java/com/quorum/tessera/test/Party.java
@@ -104,6 +104,10 @@ public Path getConfigFilePath() {
return configFilePath;
}
+ public Config getConfig() {
+ return config;
+ }
+
public List getConfiguredPeers() {
return Collections.unmodifiableList(config.getPeers());
}
diff --git a/tests/acceptance-test/src/test/java/com/quorum/tessera/test/ProcessManager.java b/tests/acceptance-test/src/test/java/com/quorum/tessera/test/ProcessManager.java
index ec60d8dfef..acc00ea65b 100644
--- a/tests/acceptance-test/src/test/java/com/quorum/tessera/test/ProcessManager.java
+++ b/tests/acceptance-test/src/test/java/com/quorum/tessera/test/ProcessManager.java
@@ -56,7 +56,10 @@ public String findJarFilePath() {
}
public void startNodes() throws Exception {
- for (String nodeAlias : configFiles.keySet()) {
+ List nodeAliases = Arrays.asList(configFiles.keySet().toArray(new String[0]));
+ Collections.shuffle(nodeAliases);
+
+ for (String nodeAlias : nodeAliases) {
start(nodeAlias);
}
}
@@ -94,7 +97,7 @@ public void start(String nodeAlias) throws Exception {
List args = Arrays.asList(
"java",
- "-Dspring.profiles.active=disable-unixsocket",
+ "-Dspring.profiles.active=disable-unixsocket,disable-sync-poller",
"-Dnode.number=" + nodeAlias,
"-Dlogback.configurationFile=" + logbackConfigFile.getFile(),
"-Ddebug=true",
diff --git a/tests/acceptance-test/src/test/resources/empty-keys-config.json b/tests/acceptance-test/src/test/resources/empty-keys-config.json
new file mode 100644
index 0000000000..36d01e50eb
--- /dev/null
+++ b/tests/acceptance-test/src/test/resources/empty-keys-config.json
@@ -0,0 +1,28 @@
+{
+ "useWhiteList": false,
+ "jdbc": {
+ "username": "sa",
+ "password": "",
+ "url": "jdbc:h2:./target/h2/rest1;MODE=Oracle;TRACE_LEVEL_SYSTEM_OUT=0;AUTO_SERVER=TRUE;AUTO_SERVER_PORT=9090"
+ },
+ "server": {
+ "port": 8989,
+ "hostName": "http://localhost"
+ },
+ "peer": [
+ {
+ "url": "http://localhost:8990"
+ }
+ ],
+ "keys": {
+ "passwords": [],
+ "keyData": [
+ {
+ "privateKey": "",
+ "publicKey": ""
+ }
+ ]
+ },
+ "alwaysSendTo": [],
+ "unixSocketFile": "${unixSocketPath}"
+}
diff --git a/tests/acceptance-test/src/test/resources/empty-keyspath-config.json b/tests/acceptance-test/src/test/resources/empty-keyspath-config.json
new file mode 100644
index 0000000000..104eea5b69
--- /dev/null
+++ b/tests/acceptance-test/src/test/resources/empty-keyspath-config.json
@@ -0,0 +1,28 @@
+{
+ "useWhiteList": false,
+ "jdbc": {
+ "username": "sa",
+ "password": "",
+ "url": "jdbc:h2:./target/h2/rest1;MODE=Oracle;TRACE_LEVEL_SYSTEM_OUT=0;AUTO_SERVER=TRUE;AUTO_SERVER_PORT=9090"
+ },
+ "server": {
+ "port": 8989,
+ "hostName": "http://localhost"
+ },
+ "peer": [
+ {
+ "url": "http://localhost:8990"
+ }
+ ],
+ "keys": {
+ "passwords": [],
+ "keyData": [
+ {
+ "privateKeyPath": "${emptyKeyFilePath}",
+ "publicKeyPath": "${emptyKeyFilePath}"
+ }
+ ]
+ },
+ "alwaysSendTo": [],
+ "unixSocketFile": "${unixSocketPath}"
+}
diff --git a/tests/acceptance-test/src/test/resources/features/admin.feature b/tests/acceptance-test/src/test/resources/features/admin.feature
index 4a04e971b2..b7d32de717 100644
--- a/tests/acceptance-test/src/test/resources/features/admin.feature
+++ b/tests/acceptance-test/src/test/resources/features/admin.feature
@@ -4,3 +4,14 @@ Feature: Runtime Admin functions
Given any node is running
When admin user executes add peer
Then a peer is added to party
+
+ Scenario: Admin user starts node with empty key values
+ Given configuration file with empty public and private key values
+ When admin user executes start
+ Then node returns error message and exits
+
+ Scenario: Admin user starts node with key paths containing empty values
+ Given configuration file with with key paths containing empty values
+ When admin user executes start
+ Then node returns error message and exits
+
diff --git a/tests/acceptance-test/src/test/resources/grpc/config2.json b/tests/acceptance-test/src/test/resources/grpc/config2.json
index 850ce8c12a..e0afd49147 100644
--- a/tests/acceptance-test/src/test/resources/grpc/config2.json
+++ b/tests/acceptance-test/src/test/resources/grpc/config2.json
@@ -13,7 +13,7 @@
},
"peer": [
{
- "url": "http://localhost:50520"
+ "url": "http://localhost:50522"
}
],
"keys": {
diff --git a/tests/acceptance-test/src/test/resources/grpc/config3.json b/tests/acceptance-test/src/test/resources/grpc/config3.json
index c6189b4f20..8cac2e3c58 100644
--- a/tests/acceptance-test/src/test/resources/grpc/config3.json
+++ b/tests/acceptance-test/src/test/resources/grpc/config3.json
@@ -13,7 +13,7 @@
},
"peer": [
{
- "url": "http://localhost:50520"
+ "url": "http://localhost:50523"
}
],
"keys": {
diff --git a/tests/acceptance-test/src/test/resources/grpc/config4.json b/tests/acceptance-test/src/test/resources/grpc/config4.json
index 2f00c679b3..99ca58c05a 100644
--- a/tests/acceptance-test/src/test/resources/grpc/config4.json
+++ b/tests/acceptance-test/src/test/resources/grpc/config4.json
@@ -13,7 +13,7 @@
},
"peer": [
{
- "url": "http://localhost:50520"
+ "url": "http://localhost:50521"
}
],
"keys": {
diff --git a/tests/acceptance-test/src/test/resources/rest/config2.json b/tests/acceptance-test/src/test/resources/rest/config2.json
index 05579d1613..7151f9ee58 100644
--- a/tests/acceptance-test/src/test/resources/rest/config2.json
+++ b/tests/acceptance-test/src/test/resources/rest/config2.json
@@ -11,7 +11,7 @@
},
"peer": [
{
- "url": "http://localhost:8080"
+ "url": "http://localhost:8082"
}
],
"keys": {
diff --git a/tests/acceptance-test/src/test/resources/rest/config3.json b/tests/acceptance-test/src/test/resources/rest/config3.json
index da60aaf9cc..42ef9c13a6 100644
--- a/tests/acceptance-test/src/test/resources/rest/config3.json
+++ b/tests/acceptance-test/src/test/resources/rest/config3.json
@@ -11,7 +11,7 @@
},
"peer": [
{
- "url": "http://localhost:8080"
+ "url": "http://localhost:8083"
}
],
"keys": {
diff --git a/tests/acceptance-test/src/test/resources/rest/config4.json b/tests/acceptance-test/src/test/resources/rest/config4.json
index 6cc629db31..bbfb8b3f32 100644
--- a/tests/acceptance-test/src/test/resources/rest/config4.json
+++ b/tests/acceptance-test/src/test/resources/rest/config4.json
@@ -11,7 +11,7 @@
},
"peer": [
{
- "url": "http://localhost:8080"
+ "url": "http://localhost:8081"
}
],
"keys": {
diff --git a/tests/jmeter-test/pom.xml b/tests/jmeter-test/pom.xml
index f3dd51cfee..43c3fefdbc 100644
--- a/tests/jmeter-test/pom.xml
+++ b/tests/jmeter-test/pom.xml
@@ -5,7 +5,7 @@
com.quorum.tessera
tests
- 0.7-SNAPSHOT
+ 0.7.1-SNAPSHOT
4.0.0
@@ -71,7 +71,7 @@
org.apache.maven.plugins
maven-failsafe-plugin
- 2.21.0
+ 3.0.0-M1
false
0
diff --git a/tests/pom.xml b/tests/pom.xml
index ca0060f87a..16b4092b61 100644
--- a/tests/pom.xml
+++ b/tests/pom.xml
@@ -3,7 +3,7 @@
tessera
com.quorum.tessera
- 0.7
+ 0.7.1-SNAPSHOT
4.0.0
diff --git a/tests/test-util/pom.xml b/tests/test-util/pom.xml
index f0b4fa6fde..994c71a715 100644
--- a/tests/test-util/pom.xml
+++ b/tests/test-util/pom.xml
@@ -4,7 +4,7 @@
com.quorum.tessera
tests
- 0.7
+ 0.7.1-SNAPSHOT
test-util
jar