Skip to content

Commit 7772412

Browse files
authored
Added signing test for azure multikey (Consensys#193)
1 parent d8fdf52 commit 7772412

10 files changed

+271
-19
lines changed

acceptance-tests/src/test/java/tech/pegasys/ethsigner/tests/dsl/node/BesuNode.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ public void shutdown() {
135135
public void awaitStartupCompletion() {
136136
try {
137137
LOG.info("Waiting for Besu to become responsive...");
138-
waitFor(() -> assertThat(jsonRpc.ethBlockNumber().send().hasError()).isFalse());
138+
waitFor(60, () -> assertThat(jsonRpc.ethBlockNumber().send().hasError()).isFalse());
139139
LOG.info("Besu is now responsive");
140140
waitFor(
141141
() ->

acceptance-tests/src/test/java/tech/pegasys/ethsigner/tests/dsl/signer/SignerConfiguration.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
public class SignerConfiguration {
1818

1919
private static final Duration POLLING_INTERVAL = Duration.ofMillis(500);
20-
private static final Duration TIMEOUT = Duration.ofSeconds(1);
20+
private static final Duration TIMEOUT = Duration.ofSeconds(2);
2121
public static final int UNASSIGNED_PORT = 0;
2222

2323
private final String chainId;

acceptance-tests/src/test/java/tech/pegasys/ethsigner/tests/multikeysigner/AzureBasedTomlLoadingAcceptanceTest.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,7 @@ static void preChecks() {
3838
@Test
3939
void azureSignersAreCreatedAndExpectedAddressIsReported(@TempDir Path tomlDirectory) {
4040
createAzureTomlFileAt(
41-
tomlDirectory.resolve("arbitrary_prefix" + FILENAME + ".toml").toAbsolutePath(),
42-
clientId,
43-
clientSecret);
41+
tomlDirectory.resolve("arbitrary_prefix" + FILENAME + ".toml"), clientId, clientSecret);
4442

4543
setup(tomlDirectory);
4644

@@ -50,7 +48,7 @@ void azureSignersAreCreatedAndExpectedAddressIsReported(@TempDir Path tomlDirect
5048
@Test
5149
void incorrectlyNamedAzureFileIsNotLoaded(@TempDir Path tomlDirectory) {
5250
createAzureTomlFileAt(
53-
tomlDirectory.resolve("ffffffffffffffffffffffffffffffffffffffff.toml").toAbsolutePath(),
51+
tomlDirectory.resolve("ffffffffffffffffffffffffffffffffffffffff.toml"),
5452
clientId,
5553
clientSecret);
5654

acceptance-tests/src/test/java/tech/pegasys/ethsigner/tests/multikeysigner/HashicorpBasedTomlLoadingAcceptanceTest.java

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,18 +53,15 @@ static void setUpBase() throws IOException {
5353
@Test
5454
void hashicorpSignerIsCreatedAndExpectedAddressIsReported() {
5555
createHashicorpTomlFileAt(
56-
tempDir.resolve(FILENAME + ".toml").toAbsolutePath(),
57-
absKeyPath,
58-
authFilename,
59-
hashicorpVault);
56+
tempDir.resolve(FILENAME + ".toml"), absKeyPath, authFilename, hashicorpVault);
6057
setup(tempDir);
6158
assertThat(ethSigner.accounts().list()).containsOnly(HASHICORP_ETHEREUM_ADDRESS);
6259
}
6360

6461
@Test
6562
void incorrectlyNamedHashicorpConfigFileIsNotLoaded() {
6663
createHashicorpTomlFileAt(
67-
tempDir.resolve("ffffffffffffffffffffffffffffffffffffffff.toml").toAbsolutePath(),
64+
tempDir.resolve("ffffffffffffffffffffffffffffffffffffffff.toml"),
6865
absKeyPath,
6966
authFilename,
7067
hashicorpVault);

acceptance-tests/src/test/java/tech/pegasys/ethsigner/tests/multikeysigner/MultiKeyAcceptanceTestBase.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ void setup(final Path tomlDirectory) {
5151
ethSigner.awaitStartupCompletion();
5252
}
5353

54-
void createAzureTomlFileAt(
54+
public void createAzureTomlFileAt(
5555
final Path tomlPath, final String clientId, final String clientSecret) {
5656
try {
5757

@@ -70,7 +70,7 @@ void createAzureTomlFileAt(
7070
}
7171
}
7272

73-
void createFileBasedTomlFileAt(
73+
public void createFileBasedTomlFileAt(
7474
final Path tomlPath, final String keyPath, final String passwordPath) {
7575
try {
7676
final FileWriter writer = new FileWriter(tomlPath.toFile(), StandardCharsets.UTF_8);
@@ -85,7 +85,7 @@ void createFileBasedTomlFileAt(
8585
}
8686
}
8787

88-
void createHashicorpTomlFileAt(
88+
public void createHashicorpTomlFileAt(
8989
final Path tomlPath,
9090
final String keyPath,
9191
final String authFile,

acceptance-tests/src/test/java/tech/pegasys/ethsigner/tests/multikeysigner/MultiKeySigningAcceptanceTest.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,11 @@ static void preChecks() {
6464
void multipleSignersAreCreatedAndExpectedAddressAreReported() throws URISyntaxException {
6565

6666
createAzureTomlFileAt(
67-
tempDir.resolve(AzureBasedTomlLoadingAcceptanceTest.FILENAME + ".toml").toAbsolutePath(),
67+
tempDir.resolve(AzureBasedTomlLoadingAcceptanceTest.FILENAME + ".toml"),
6868
AzureBasedTomlLoadingAcceptanceTest.clientId,
6969
AzureBasedTomlLoadingAcceptanceTest.clientSecret);
7070
createFileBasedTomlFileAt(
71-
tempDir.resolve(FileBasedTomlLoadingAcceptanceTest.FILENAME + ".toml").toAbsolutePath(),
71+
tempDir.resolve(FileBasedTomlLoadingAcceptanceTest.FILENAME + ".toml"),
7272
new File(
7373
Resources.getResource(
7474
"UTC--2019-12-05T05-17-11.151993000Z--a01f618424b0113a9cebdc6cb66ca5b48e9120c5.key")
@@ -81,9 +81,7 @@ void multipleSignersAreCreatedAndExpectedAddressAreReported() throws URISyntaxEx
8181
.getAbsolutePath());
8282

8383
createHashicorpTomlFileAt(
84-
tempDir
85-
.resolve(HashicorpBasedTomlLoadingAcceptanceTest.FILENAME + ".toml")
86-
.toAbsolutePath(),
84+
tempDir.resolve(HashicorpBasedTomlLoadingAcceptanceTest.FILENAME + ".toml"),
8785
HashicorpVaultDocker.absKeyPath,
8886
authFilename,
8987
hashicorpVault);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* Copyright 2019 ConsenSys AG.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5+
* the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10+
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11+
* specific language governing permissions and limitations under the License.
12+
*/
13+
package tech.pegasys.ethsigner.tests.multikeysigner.transactionsigning;
14+
15+
import java.nio.file.Path;
16+
17+
import org.junit.jupiter.api.Assumptions;
18+
import org.junit.jupiter.api.BeforeAll;
19+
import org.junit.jupiter.api.Test;
20+
import org.junit.jupiter.api.io.TempDir;
21+
22+
public class MultiKeyAzureTransactionSignerAcceptanceTest
23+
extends MultiKeyTransactionSigningAcceptanceTestBase {
24+
25+
static final String clientId = System.getenv("ETHSIGNER_AZURE_CLIENT_ID");
26+
static final String clientSecret = System.getenv("ETHSIGNER_AZURE_CLIENT_SECRET");
27+
static final String FILENAME = "fe3b557e8fb62b89f4916b721be55ceb828dbd73";
28+
29+
@BeforeAll
30+
public static void checkAzureCredentials() {
31+
Assumptions.assumeTrue(
32+
clientId != null && clientSecret != null,
33+
"Ensure Azure client id and client secret env variables are set");
34+
}
35+
36+
@Test
37+
public void azureLoadedFromMultiKeyCanSignValueTransferTransaction(@TempDir Path tomlDirectory) {
38+
createAzureTomlFileAt(
39+
tomlDirectory.resolve("arbitrary_prefix" + FILENAME + ".toml"), clientId, clientSecret);
40+
41+
setup(tomlDirectory);
42+
43+
performTransaction();
44+
}
45+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* Copyright 2019 ConsenSys AG.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5+
* the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10+
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11+
* specific language governing permissions and limitations under the License.
12+
*/
13+
package tech.pegasys.ethsigner.tests.multikeysigner.transactionsigning;
14+
15+
import static java.nio.charset.StandardCharsets.UTF_8;
16+
17+
import java.io.File;
18+
import java.io.IOException;
19+
import java.net.URISyntaxException;
20+
import java.nio.file.Files;
21+
import java.nio.file.Path;
22+
23+
import com.google.common.io.Resources;
24+
import org.junit.jupiter.api.Test;
25+
import org.junit.jupiter.api.io.TempDir;
26+
27+
public class MultiKeyFileBasedTransactionSignerAcceptanceTest
28+
extends MultiKeyTransactionSigningAcceptanceTestBase {
29+
30+
static final String FILENAME = "fe3b557e8fb62b89f4916b721be55ceb828dbd73";
31+
32+
@Test
33+
public void fileBasedMultiKeyCanSignValueTransferTransaction(@TempDir Path tomlDirectory)
34+
throws URISyntaxException, IOException {
35+
final String keyPath =
36+
new File(Resources.getResource("rich_benefactor_one.json").toURI()).getAbsolutePath();
37+
38+
final Path passwordPath = tomlDirectory.resolve("password");
39+
Files.write(passwordPath, "pass".getBytes(UTF_8));
40+
41+
createFileBasedTomlFileAt(
42+
tomlDirectory.resolve("arbitrary_prefix" + FILENAME + ".toml"),
43+
keyPath,
44+
passwordPath.toString());
45+
46+
setup(tomlDirectory);
47+
performTransaction();
48+
}
49+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* Copyright 2019 ConsenSys AG.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5+
* the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10+
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11+
* specific language governing permissions and limitations under the License.
12+
*/
13+
package tech.pegasys.ethsigner.tests.multikeysigner.transactionsigning;
14+
15+
import static java.nio.charset.StandardCharsets.UTF_8;
16+
import static tech.pegasys.ethsigner.tests.hashicorpvault.HashicorpVaultDocker.absKeyPath;
17+
18+
import tech.pegasys.ethsigner.tests.dsl.DockerClientFactory;
19+
import tech.pegasys.ethsigner.tests.dsl.utils.HashicorpVault;
20+
21+
import java.io.IOException;
22+
import java.nio.file.Files;
23+
import java.nio.file.Path;
24+
25+
import org.junit.jupiter.api.AfterAll;
26+
import org.junit.jupiter.api.BeforeAll;
27+
import org.junit.jupiter.api.Test;
28+
import org.junit.jupiter.api.io.TempDir;
29+
30+
public class MultiKeyHashicorpTransactionSignerAcceptanceTest
31+
extends MultiKeyTransactionSigningAcceptanceTestBase {
32+
33+
static final String FILENAME = "fe3b557e8fb62b89f4916b721be55ceb828dbd73";
34+
35+
private static HashicorpVault hashicorpVault;
36+
37+
@BeforeAll
38+
static void preSetup() {
39+
hashicorpVault = HashicorpVault.createVault(new DockerClientFactory().create());
40+
}
41+
42+
@Test
43+
void hashicorpLoadedFromMultiKeyCanSignValueTransferTransaction(@TempDir Path tomlDirectory)
44+
throws IOException {
45+
46+
final Path authFilePath = tomlDirectory.resolve("hashicorpAuthFile");
47+
Files.write(authFilePath, hashicorpVault.getVaultToken().getBytes(UTF_8));
48+
final String authFilename = authFilePath.toAbsolutePath().toString();
49+
50+
createHashicorpTomlFileAt(
51+
tomlDirectory.resolve(FILENAME + ".toml"), absKeyPath, authFilename, hashicorpVault);
52+
53+
setup(tomlDirectory);
54+
performTransaction();
55+
}
56+
57+
@AfterAll
58+
static void tearDown() {
59+
if (hashicorpVault != null) {
60+
hashicorpVault.shutdown();
61+
hashicorpVault = null;
62+
}
63+
}
64+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/*
2+
* Copyright 2019 ConsenSys AG.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5+
* the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10+
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11+
* specific language governing permissions and limitations under the License.
12+
*/
13+
package tech.pegasys.ethsigner.tests.multikeysigner.transactionsigning;
14+
15+
import static org.assertj.core.api.Assertions.assertThat;
16+
import static tech.pegasys.ethsigner.tests.dsl.Gas.GAS_PRICE;
17+
import static tech.pegasys.ethsigner.tests.dsl.Gas.INTRINSIC_GAS;
18+
19+
import tech.pegasys.ethsigner.tests.dsl.Account;
20+
import tech.pegasys.ethsigner.tests.dsl.DockerClientFactory;
21+
import tech.pegasys.ethsigner.tests.dsl.node.BesuNode;
22+
import tech.pegasys.ethsigner.tests.dsl.node.Node;
23+
import tech.pegasys.ethsigner.tests.dsl.node.NodeConfiguration;
24+
import tech.pegasys.ethsigner.tests.dsl.node.NodeConfigurationBuilder;
25+
import tech.pegasys.ethsigner.tests.dsl.signer.Signer;
26+
import tech.pegasys.ethsigner.tests.dsl.signer.SignerConfiguration;
27+
import tech.pegasys.ethsigner.tests.dsl.signer.SignerConfigurationBuilder;
28+
import tech.pegasys.ethsigner.tests.multikeysigner.MultiKeyAcceptanceTestBase;
29+
30+
import java.math.BigInteger;
31+
import java.nio.file.Path;
32+
33+
import com.github.dockerjava.api.DockerClient;
34+
import org.junit.jupiter.api.AfterAll;
35+
import org.web3j.protocol.core.methods.request.Transaction;
36+
import org.web3j.utils.Convert;
37+
import org.web3j.utils.Convert.Unit;
38+
39+
public class MultiKeyTransactionSigningAcceptanceTestBase extends MultiKeyAcceptanceTestBase {
40+
41+
protected static final String RECIPIENT = "0x1b00ba00ca00bb00aa00bc00be00ac00ca00da00";
42+
protected static Node ethNode;
43+
protected static Signer ethSigner;
44+
45+
protected Account richBenefactor() {
46+
return ethSigner.accounts().richBenefactor();
47+
}
48+
49+
protected static void setup(final Path tomlDirectory) {
50+
Runtime.getRuntime()
51+
.addShutdownHook(new Thread(MultiKeyTransactionSigningAcceptanceTestBase::tearDownBase));
52+
53+
final DockerClient docker = new DockerClientFactory().create();
54+
final NodeConfiguration nodeConfig = new NodeConfigurationBuilder().build();
55+
56+
ethNode = new BesuNode(docker, nodeConfig);
57+
ethNode.start();
58+
ethNode.awaitStartupCompletion();
59+
60+
final SignerConfiguration signerConfig =
61+
new SignerConfigurationBuilder().withMultiKeySignerDirectory(tomlDirectory).build();
62+
63+
ethSigner = new Signer(signerConfig, nodeConfig, ethNode.ports());
64+
ethSigner.start();
65+
ethSigner.awaitStartupCompletion();
66+
}
67+
68+
void performTransaction() {
69+
final BigInteger transferAmountWei = Convert.toWei("1.75", Unit.ETHER).toBigIntegerExact();
70+
71+
final BigInteger startBalance = ethNode.accounts().balance(RECIPIENT);
72+
final Transaction transaction =
73+
Transaction.createEtherTransaction(
74+
richBenefactor().address(),
75+
null,
76+
GAS_PRICE,
77+
INTRINSIC_GAS,
78+
RECIPIENT,
79+
transferAmountWei);
80+
81+
final String hash = ethSigner.transactions().submit(transaction);
82+
ethNode.transactions().awaitBlockContaining(hash);
83+
84+
final BigInteger expectedEndBalance = startBalance.add(transferAmountWei);
85+
final BigInteger actualEndBalance = ethNode.accounts().balance(RECIPIENT);
86+
assertThat(actualEndBalance).isEqualTo(expectedEndBalance);
87+
}
88+
89+
@AfterAll
90+
public static void tearDownBase() {
91+
if (ethNode != null) {
92+
ethNode.shutdown();
93+
ethNode = null;
94+
}
95+
96+
if (ethSigner != null) {
97+
ethSigner.shutdown();
98+
ethSigner = null;
99+
}
100+
}
101+
}

0 commit comments

Comments
 (0)