mirror of https://github.com/hyperledger/besu
[PAN-2789] Add ethSigner acceptance test (#1655)
Signed-off-by: Adrian Sutton <adrian.sutton@consensys.net>pull/2/head
parent
378821e36e
commit
0500d18950
@ -0,0 +1,107 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2019 ConsenSys AG. |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on |
||||||
|
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the |
||||||
|
* specific language governing permissions and limitations under the License. |
||||||
|
*/ |
||||||
|
package tech.pegasys.pantheon.tests.acceptance.dsl.ethsigner; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
import java.math.BigInteger; |
||||||
|
import java.net.URI; |
||||||
|
import java.util.Collections; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
import org.apache.logging.log4j.LogManager; |
||||||
|
import org.apache.logging.log4j.Logger; |
||||||
|
import org.web3j.protocol.Web3jService; |
||||||
|
import org.web3j.protocol.core.Request; |
||||||
|
import org.web3j.protocol.core.methods.request.Transaction; |
||||||
|
import org.web3j.protocol.core.methods.response.EthSendTransaction; |
||||||
|
import org.web3j.protocol.eea.Eea; |
||||||
|
import org.web3j.protocol.http.HttpService; |
||||||
|
|
||||||
|
public class EthSignerClient { |
||||||
|
private static final Logger LOG = LogManager.getLogger(); |
||||||
|
private final Web3jService web3jService; |
||||||
|
private final Eea web3j; |
||||||
|
private final String from; |
||||||
|
|
||||||
|
public EthSignerClient(final URI ethSignerUri) throws IOException { |
||||||
|
this.web3jService = new HttpService(ethSignerUri.toString()); |
||||||
|
this.web3j = Eea.build(web3jService); |
||||||
|
this.from = resolveFrom(ethSignerUri); |
||||||
|
} |
||||||
|
|
||||||
|
private String resolveFrom(final URI ethSignerUri) throws IOException { |
||||||
|
final List<String> accounts; |
||||||
|
try { |
||||||
|
accounts = ethAccounts(); |
||||||
|
return accounts.get(0); |
||||||
|
} catch (IOException e) { |
||||||
|
LOG.info("Failed to connect to EthSigner at {}", ethSignerUri); |
||||||
|
throw e; |
||||||
|
} catch (Exception e) { |
||||||
|
LOG.info("Falling back to signing with node key"); |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
public List<String> ethAccounts() throws IOException { |
||||||
|
return web3j.ethAccounts().send().getAccounts(); |
||||||
|
} |
||||||
|
|
||||||
|
public String ethSendTransaction( |
||||||
|
final String to, |
||||||
|
final BigInteger gas, |
||||||
|
final BigInteger gasPrice, |
||||||
|
final BigInteger value, |
||||||
|
final String data, |
||||||
|
final BigInteger nonce) |
||||||
|
throws IOException { |
||||||
|
return web3j |
||||||
|
.ethSendTransaction(new Transaction(from, nonce, gasPrice, gas, to, value, data)) |
||||||
|
.send() |
||||||
|
.getTransactionHash(); |
||||||
|
} |
||||||
|
|
||||||
|
public String eeaSendTransaction( |
||||||
|
final String to, |
||||||
|
final BigInteger gas, |
||||||
|
final BigInteger gasPrice, |
||||||
|
final String data, |
||||||
|
final BigInteger nonce, |
||||||
|
final String privateFrom, |
||||||
|
final List<String> privateFor, |
||||||
|
final String restriction) |
||||||
|
throws IOException { |
||||||
|
|
||||||
|
final PrivateTransactionRequest transaction = |
||||||
|
new PrivateTransactionRequest( |
||||||
|
from, |
||||||
|
nonce, |
||||||
|
gasPrice, |
||||||
|
gas, |
||||||
|
to, |
||||||
|
BigInteger.ZERO, |
||||||
|
data, |
||||||
|
privateFrom, |
||||||
|
privateFor, |
||||||
|
restriction); |
||||||
|
|
||||||
|
// temporary until implemented in web3j
|
||||||
|
return new Request<>( |
||||||
|
"eea_sendTransaction", |
||||||
|
Collections.singletonList(transaction), |
||||||
|
web3jService, |
||||||
|
EthSendTransaction.class) |
||||||
|
.send() |
||||||
|
.getTransactionHash(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,122 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2019 ConsenSys AG. |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on |
||||||
|
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the |
||||||
|
* specific language governing permissions and limitations under the License. |
||||||
|
*/ |
||||||
|
package tech.pegasys.pantheon.tests.acceptance.dsl.ethsigner; |
||||||
|
|
||||||
|
import static java.nio.charset.StandardCharsets.UTF_8; |
||||||
|
import static org.junit.Assert.assertEquals; |
||||||
|
|
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.ethsigner.testutil.EthSignerTestHarness; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.ethsigner.testutil.EthSignerTestHarnessFactory; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
import java.math.BigInteger; |
||||||
|
import java.net.HttpURLConnection; |
||||||
|
import java.net.InetSocketAddress; |
||||||
|
import java.util.Collections; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
import com.sun.net.httpserver.HttpServer; |
||||||
|
import org.junit.AfterClass; |
||||||
|
import org.junit.BeforeClass; |
||||||
|
import org.junit.ClassRule; |
||||||
|
import org.junit.Test; |
||||||
|
import org.junit.rules.TemporaryFolder; |
||||||
|
|
||||||
|
public class EthSignerClientTest { |
||||||
|
@ClassRule public static final TemporaryFolder folder = new TemporaryFolder(); |
||||||
|
private static final String MOCK_RESPONSE = "mock_transaction_hash"; |
||||||
|
private static final String MOCK_SEND_TRANSACTION_RESPONSE = |
||||||
|
"{\n" |
||||||
|
+ " \"id\":67,\n" |
||||||
|
+ " \"jsonrpc\":\"2.0\",\n" |
||||||
|
+ " \"result\": \"" |
||||||
|
+ MOCK_RESPONSE |
||||||
|
+ "\"\n" |
||||||
|
+ "}"; |
||||||
|
private static final String ENCLAVE_PUBLIC_KEY = "A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo="; |
||||||
|
|
||||||
|
private static EthSignerClient ethSignerClient; |
||||||
|
|
||||||
|
private static EthSignerTestHarness testHarness; |
||||||
|
|
||||||
|
// The downstream server EthSigner should proxy requests to
|
||||||
|
private static HttpServer mockServer; |
||||||
|
|
||||||
|
@BeforeClass |
||||||
|
public static void setUpOnce() throws Exception { |
||||||
|
folder.create(); |
||||||
|
|
||||||
|
testHarness = |
||||||
|
EthSignerTestHarnessFactory.create( |
||||||
|
folder.newFolder().toPath(), |
||||||
|
"ethSignerKey--fe3b557e8fb62b89f4916b721be55ceb828dbd73.json", |
||||||
|
1111, |
||||||
|
8545, |
||||||
|
2018); |
||||||
|
|
||||||
|
ethSignerClient = new EthSignerClient(testHarness.getHttpListeningUrl()); |
||||||
|
|
||||||
|
mockServer = HttpServer.create(new InetSocketAddress(1111), 0); |
||||||
|
mockServer.createContext( |
||||||
|
"/", |
||||||
|
exchange -> { |
||||||
|
byte[] response = MOCK_SEND_TRANSACTION_RESPONSE.getBytes(UTF_8); |
||||||
|
exchange.sendResponseHeaders(HttpURLConnection.HTTP_OK, response.length); |
||||||
|
exchange.getResponseBody().write(response); |
||||||
|
exchange.close(); |
||||||
|
}); |
||||||
|
mockServer.start(); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testEthAccounts() throws IOException { |
||||||
|
final List<String> accounts = ethSignerClient.ethAccounts(); |
||||||
|
assertEquals(1, accounts.size()); |
||||||
|
assertEquals("0xfe3b557e8fb62b89f4916b721be55ceb828dbd73", accounts.get(0)); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testEthSendTransaction() throws IOException { |
||||||
|
final String response = |
||||||
|
ethSignerClient.ethSendTransaction( |
||||||
|
"0xfe3b557e8fb62b89f4916b721be55ceb828dbd73", |
||||||
|
BigInteger.ZERO, |
||||||
|
BigInteger.ZERO, |
||||||
|
BigInteger.ZERO, |
||||||
|
"", |
||||||
|
BigInteger.ZERO); |
||||||
|
|
||||||
|
assertEquals(MOCK_RESPONSE, response); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testEeaSendTransaction() throws IOException { |
||||||
|
final String response = |
||||||
|
ethSignerClient.eeaSendTransaction( |
||||||
|
"0xfe3b557e8fb62b89f4916b721be55ceb828dbd73", |
||||||
|
BigInteger.ZERO, |
||||||
|
BigInteger.ZERO, |
||||||
|
"", |
||||||
|
BigInteger.ZERO, |
||||||
|
ENCLAVE_PUBLIC_KEY, |
||||||
|
Collections.emptyList(), |
||||||
|
""); |
||||||
|
|
||||||
|
assertEquals(MOCK_RESPONSE, response); |
||||||
|
} |
||||||
|
|
||||||
|
@AfterClass |
||||||
|
public static void bringDownOnce() { |
||||||
|
mockServer.stop(0); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,101 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2019 ConsenSys AG. |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on |
||||||
|
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the |
||||||
|
* specific language governing permissions and limitations under the License. |
||||||
|
*/ |
||||||
|
package tech.pegasys.pantheon.tests.acceptance.dsl.ethsigner; |
||||||
|
|
||||||
|
import java.math.BigInteger; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude; |
||||||
|
import org.web3j.utils.Numeric; |
||||||
|
|
||||||
|
@JsonInclude(JsonInclude.Include.NON_NULL) |
||||||
|
public class PrivateTransactionRequest { |
||||||
|
|
||||||
|
private final String from; |
||||||
|
private final BigInteger nonce; |
||||||
|
private final BigInteger gasPrice; |
||||||
|
private final BigInteger gas; |
||||||
|
private final String to; |
||||||
|
private final BigInteger value; |
||||||
|
private final String data; |
||||||
|
private final String privateFrom; |
||||||
|
private final List<String> privateFor; |
||||||
|
private final String restriction; |
||||||
|
|
||||||
|
public PrivateTransactionRequest( |
||||||
|
final String from, |
||||||
|
final BigInteger nonce, |
||||||
|
final BigInteger gasPrice, |
||||||
|
final BigInteger gasLimit, |
||||||
|
final String to, |
||||||
|
final BigInteger value, |
||||||
|
final String data, |
||||||
|
final String privateFrom, |
||||||
|
final List<String> privateFor, |
||||||
|
final String restriction) { |
||||||
|
this.from = from; |
||||||
|
this.to = to; |
||||||
|
this.gas = gasLimit; |
||||||
|
this.gasPrice = gasPrice; |
||||||
|
this.value = value; |
||||||
|
this.data = data == null ? null : Numeric.prependHexPrefix(data); |
||||||
|
this.nonce = nonce; |
||||||
|
this.privateFrom = privateFrom; |
||||||
|
this.privateFor = privateFor; |
||||||
|
this.restriction = restriction; |
||||||
|
} |
||||||
|
|
||||||
|
public String getFrom() { |
||||||
|
return from; |
||||||
|
} |
||||||
|
|
||||||
|
public String getTo() { |
||||||
|
return to; |
||||||
|
} |
||||||
|
|
||||||
|
public String getGas() { |
||||||
|
return convert(gas); |
||||||
|
} |
||||||
|
|
||||||
|
public String getGasPrice() { |
||||||
|
return convert(gasPrice); |
||||||
|
} |
||||||
|
|
||||||
|
public String getValue() { |
||||||
|
return convert(value); |
||||||
|
} |
||||||
|
|
||||||
|
public String getData() { |
||||||
|
return data; |
||||||
|
} |
||||||
|
|
||||||
|
public String getNonce() { |
||||||
|
return convert(nonce); |
||||||
|
} |
||||||
|
|
||||||
|
private String convert(final BigInteger value) { |
||||||
|
return value == null ? null : Numeric.encodeQuantity(value); |
||||||
|
} |
||||||
|
|
||||||
|
public String getPrivateFrom() { |
||||||
|
return privateFrom; |
||||||
|
} |
||||||
|
|
||||||
|
public List<String> getPrivateFor() { |
||||||
|
return privateFor; |
||||||
|
} |
||||||
|
|
||||||
|
public String getRestriction() { |
||||||
|
return restriction; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,93 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2019 ConsenSys AG. |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on |
||||||
|
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the |
||||||
|
* specific language governing permissions and limitations under the License. |
||||||
|
*/ |
||||||
|
package tech.pegasys.pantheon.tests.acceptance.dsl.ethsigner.testutil; |
||||||
|
|
||||||
|
import tech.pegasys.ethsigner.core.Config; |
||||||
|
import tech.pegasys.ethsigner.core.signing.ChainIdProvider; |
||||||
|
|
||||||
|
import java.net.InetAddress; |
||||||
|
import java.nio.file.Path; |
||||||
|
import java.time.Duration; |
||||||
|
|
||||||
|
import org.apache.logging.log4j.Level; |
||||||
|
|
||||||
|
public class EthSignerConfig implements Config { |
||||||
|
private final Level logLevel; |
||||||
|
private final InetAddress downstreamHttpHost; |
||||||
|
private final Integer downStreamHttpPort; |
||||||
|
private Duration downstreamHttpRequestTimeout; |
||||||
|
private final InetAddress httpListenHost; |
||||||
|
private final Integer httpListenPort; |
||||||
|
private final ChainIdProvider chainId; |
||||||
|
private final Path dataDirectory; |
||||||
|
|
||||||
|
public EthSignerConfig( |
||||||
|
final Level logLevel, |
||||||
|
final InetAddress downstreamHttpHost, |
||||||
|
final Integer downStreamHttpPort, |
||||||
|
final Duration downstreamHttpRequestTimeout, |
||||||
|
final InetAddress httpListenHost, |
||||||
|
final Integer httpListenPort, |
||||||
|
final ChainIdProvider chainId, |
||||||
|
final Path dataDirectory) { |
||||||
|
|
||||||
|
this.logLevel = logLevel; |
||||||
|
this.downstreamHttpHost = downstreamHttpHost; |
||||||
|
this.downStreamHttpPort = downStreamHttpPort; |
||||||
|
this.downstreamHttpRequestTimeout = downstreamHttpRequestTimeout; |
||||||
|
this.httpListenHost = httpListenHost; |
||||||
|
this.httpListenPort = httpListenPort; |
||||||
|
this.chainId = chainId; |
||||||
|
this.dataDirectory = dataDirectory; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Level getLogLevel() { |
||||||
|
return logLevel; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public InetAddress getDownstreamHttpHost() { |
||||||
|
return downstreamHttpHost; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Integer getDownstreamHttpPort() { |
||||||
|
return downStreamHttpPort; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Duration getDownstreamHttpRequestTimeout() { |
||||||
|
return downstreamHttpRequestTimeout; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public InetAddress getHttpListenHost() { |
||||||
|
return httpListenHost; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Integer getHttpListenPort() { |
||||||
|
return httpListenPort; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public ChainIdProvider getChainId() { |
||||||
|
return chainId; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Path getDataPath() { |
||||||
|
return dataDirectory; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,28 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2019 ConsenSys AG. |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on |
||||||
|
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the |
||||||
|
* specific language governing permissions and limitations under the License. |
||||||
|
*/ |
||||||
|
package tech.pegasys.pantheon.tests.acceptance.dsl.ethsigner.testutil; |
||||||
|
|
||||||
|
import java.net.URI; |
||||||
|
|
||||||
|
public class EthSignerTestHarness { |
||||||
|
private final EthSignerConfig config; |
||||||
|
|
||||||
|
public EthSignerTestHarness(final EthSignerConfig config) { |
||||||
|
this.config = config; |
||||||
|
} |
||||||
|
|
||||||
|
public URI getHttpListeningUrl() { |
||||||
|
return URI.create( |
||||||
|
"http://" + config.getHttpListenHost().getHostAddress() + ":" + config.getHttpListenPort()); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,84 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2019 ConsenSys AG. |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on |
||||||
|
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the |
||||||
|
* specific language governing permissions and limitations under the License. |
||||||
|
*/ |
||||||
|
package tech.pegasys.pantheon.tests.acceptance.dsl.ethsigner.testutil; |
||||||
|
|
||||||
|
import static net.consensys.cava.io.file.Files.copyResource; |
||||||
|
import static tech.pegasys.pantheon.tests.acceptance.dsl.WaitUtils.waitFor; |
||||||
|
|
||||||
|
import tech.pegasys.ethsigner.core.EthSigner; |
||||||
|
import tech.pegasys.ethsigner.core.signing.ConfigurationChainId; |
||||||
|
import tech.pegasys.ethsigner.signer.filebased.CredentialTransactionSigner; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
import java.net.InetAddress; |
||||||
|
import java.nio.file.Path; |
||||||
|
import java.time.Duration; |
||||||
|
|
||||||
|
import okhttp3.OkHttpClient; |
||||||
|
import okhttp3.Request; |
||||||
|
import org.apache.logging.log4j.Level; |
||||||
|
import org.apache.logging.log4j.LogManager; |
||||||
|
import org.apache.logging.log4j.Logger; |
||||||
|
import org.web3j.crypto.CipherException; |
||||||
|
import org.web3j.crypto.WalletUtils; |
||||||
|
|
||||||
|
public class EthSignerTestHarnessFactory { |
||||||
|
|
||||||
|
private static final Logger LOG = LogManager.getLogger(); |
||||||
|
private static final String HOST = "127.0.0.1"; |
||||||
|
|
||||||
|
public static EthSignerTestHarness create( |
||||||
|
final Path tempDir, |
||||||
|
final String keyPath, |
||||||
|
final Integer pantheonPort, |
||||||
|
final Integer ethsignerPort, |
||||||
|
final long chainId) |
||||||
|
throws IOException, CipherException { |
||||||
|
|
||||||
|
final Path keyFilePath = copyResource(keyPath, tempDir.resolve(keyPath)); |
||||||
|
|
||||||
|
final EthSignerConfig config = |
||||||
|
new EthSignerConfig( |
||||||
|
Level.DEBUG, |
||||||
|
InetAddress.getByName(HOST), |
||||||
|
pantheonPort, |
||||||
|
Duration.ofSeconds(10), |
||||||
|
InetAddress.getByName(HOST), |
||||||
|
ethsignerPort, |
||||||
|
new ConfigurationChainId(chainId), |
||||||
|
tempDir); |
||||||
|
|
||||||
|
final EthSigner ethSigner = |
||||||
|
new EthSigner( |
||||||
|
config, |
||||||
|
new CredentialTransactionSigner( |
||||||
|
WalletUtils.loadCredentials("", keyFilePath.toAbsolutePath().toFile()))); |
||||||
|
ethSigner.run(); |
||||||
|
|
||||||
|
final OkHttpClient client = new OkHttpClient.Builder().build(); |
||||||
|
final Request request = |
||||||
|
new Request.Builder() |
||||||
|
.url("http://" + HOST + ":" + ethsignerPort + "/upcheck") |
||||||
|
.get() |
||||||
|
.build(); |
||||||
|
|
||||||
|
waitFor( |
||||||
|
() -> { |
||||||
|
client.newCall(request).execute(); |
||||||
|
}); |
||||||
|
|
||||||
|
LOG.info("EthSigner port: {}", config.getHttpListenPort()); |
||||||
|
|
||||||
|
return new EthSignerTestHarness(config); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,81 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2019 ConsenSys AG. |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on |
||||||
|
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the |
||||||
|
* specific language governing permissions and limitations under the License. |
||||||
|
*/ |
||||||
|
package tech.pegasys.pantheon.tests.web3j.privacy; |
||||||
|
|
||||||
|
import static tech.pegasys.pantheon.tests.acceptance.dsl.transaction.eea.PrivateTransactionBuilder.EVENT_EMITTER_CONSTRUCTOR; |
||||||
|
import static tech.pegasys.pantheon.tests.web3j.privacy.PrivacyGroup.generatePrivacyGroup; |
||||||
|
|
||||||
|
import tech.pegasys.pantheon.ethereum.core.Address; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.ethsigner.EthSignerClient; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.ethsigner.testutil.EthSignerTestHarness; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.ethsigner.testutil.EthSignerTestHarnessFactory; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.privacy.PrivacyAcceptanceTestBase; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.privacy.PrivacyNet; |
||||||
|
import tech.pegasys.pantheon.util.bytes.BytesValue; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
import java.math.BigInteger; |
||||||
|
import java.util.Collections; |
||||||
|
|
||||||
|
import org.junit.Before; |
||||||
|
import org.junit.Test; |
||||||
|
|
||||||
|
public class EthSignerAcceptanceTest extends PrivacyAcceptanceTestBase { |
||||||
|
private PrivacyNet privacyNet; |
||||||
|
|
||||||
|
private EthSignerClient ethSignerClient; |
||||||
|
|
||||||
|
@Before |
||||||
|
public void setUp() throws Exception { |
||||||
|
privacyNet = |
||||||
|
PrivacyNet.builder(privacy, privacyPantheon, cluster, false).addMinerNode("Alice").build(); |
||||||
|
privacyNet.startPrivacyNet(); |
||||||
|
|
||||||
|
final EthSignerTestHarness ethsigner = |
||||||
|
EthSignerTestHarnessFactory.create( |
||||||
|
privacy.newFolder().toPath(), |
||||||
|
"ethSignerKey--fe3b557e8fb62b89f4916b721be55ceb828dbd73.json", |
||||||
|
privacyNet.getNode("Alice").getJsonRpcSocketPort().orElse(8545), |
||||||
|
23606, |
||||||
|
2018); |
||||||
|
ethSignerClient = new EthSignerClient(ethsigner.getHttpListeningUrl()); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void privateSmartContractMustDeploy() throws IOException { |
||||||
|
final BytesValue privacyGroupId = generatePrivacyGroup(privacyNet, "Alice"); |
||||||
|
final long nonce = privacyNet.getNode("Alice").nextNonce(privacyGroupId); |
||||||
|
|
||||||
|
final String transactionHash = |
||||||
|
ethSignerClient.eeaSendTransaction( |
||||||
|
null, |
||||||
|
BigInteger.valueOf(63992), |
||||||
|
BigInteger.valueOf(1000), |
||||||
|
EVENT_EMITTER_CONSTRUCTOR.toString(), |
||||||
|
BigInteger.valueOf(nonce), |
||||||
|
privacyNet.getEnclave("Alice").getPublicKeys().get(0), |
||||||
|
Collections.emptyList(), |
||||||
|
"restricted"); |
||||||
|
|
||||||
|
privacyNet.getNode("Alice").verify(eea.expectSuccessfulTransactionReceipt(transactionHash)); |
||||||
|
|
||||||
|
final String expectedContractAddress = |
||||||
|
Address.privateContractAddress( |
||||||
|
privacyNet.getNode("Alice").getAddress(), nonce, privacyGroupId) |
||||||
|
.toString(); |
||||||
|
|
||||||
|
privateTransactionVerifier |
||||||
|
.validPrivateContractDeployed(expectedContractAddress) |
||||||
|
.verify(privacyNet.getNode("Alice"), transactionHash); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1 @@ |
|||||||
|
{"address":"fe3b557e8fb62b89f4916b721be55ceb828dbd73","id":"004bac44-2955-40bf-8b1f-5376f428644f","version":3,"crypto":{"cipher":"aes-128-ctr","ciphertext":"28e23ffb25d1ef6a665a5a61866f353c2640b2ec55bd080f557ac4da8c8ba1d1","cipherparams":{"iv":"07bf8e210d7fbb5c4731ac15388a7939"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":4096,"p":6,"r":8,"salt":"8d454299a7ac29cbcd8817a8d1f12723592421d3e0a8bc56aff4719bf78bcec9"},"mac":"9073b2a8f454b0942b9350da96b1431e15edfdddb796ece0ab3fc6e14ca18190"}} |
Loading…
Reference in new issue