PAN-2723: Testing permissioning with static nodes behaviour (#1764)

* PAN-2723: Created Miner API transactions and conditions

* PAN-2723: Added static nodes options to permissioned node builder

* PAN-2723: Implemented permissioned node with static-nodes AT

* PAN-2723: Renaming test

* Refactoring test to use the waitForBlockHeight method

Signed-off-by: Adrian Sutton <adrian.sutton@consensys.net>
pull/2/head
Lucas Saldanha 5 years ago committed by GitHub
parent ef0f9793a9
commit ab52ba3fe1
  1. 3
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/AcceptanceTestBase.java
  2. 5
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/condition/eth/EthConditions.java
  3. 36
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/condition/miner/MiningStatusCondition.java
  4. 2
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/node/PantheonNode.java
  5. 1
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/node/configuration/PantheonFactoryConfigurationBuilder.java
  6. 20
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/node/configuration/PantheonNodeFactory.java
  7. 24
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/node/configuration/permissioning/PermissionedNodeBuilder.java
  8. 8
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/transaction/NodeRequests.java
  9. 38
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/transaction/eth/EthMiningTransaction.java
  10. 4
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/transaction/eth/EthTransactions.java
  11. 41
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/transaction/miner/MinerRequestFactory.java
  12. 29
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/transaction/miner/MinerStartTransaction.java
  13. 29
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/transaction/miner/MinerStopTransaction.java
  14. 24
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/transaction/miner/MinerTransactions.java
  15. 24
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/permissioning/NodeSmartContractPermissioningAcceptanceTestBase.java
  16. 21
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/permissioning/NodeSmartContractPermissioningOutOfSyncAcceptanceTest.java
  17. 81
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/permissioning/NodesSmartContractPermissioningStaticNodesAcceptanceTest.java

@ -32,6 +32,7 @@ import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.clique.CliqueTrans
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.contract.ContractTransactions;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.eth.EthTransactions;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.ibft2.Ibft2Transactions;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.miner.MinerTransactions;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.net.NetTransactions;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.perm.PermissioningTransactions;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.web3.Web3Transactions;
@ -60,6 +61,7 @@ public class AcceptanceTestBase {
protected final PermissioningConditions perm;
protected final PermissionedNodeBuilder permissionedNodeBuilder;
protected final PermissioningTransactions permissioningTransactions;
protected final MinerTransactions minerTransactions;
protected final Web3Conditions web3;
protected AcceptanceTestBase() {
@ -71,6 +73,7 @@ public class AcceptanceTestBase {
accountTransactions = new AccountTransactions(accounts);
permissioningTransactions = new PermissioningTransactions();
contractTransactions = new ContractTransactions();
minerTransactions = new MinerTransactions();
blockchain = new Blockchain(ethTransactions);
clique = new CliqueConditions(ethTransactions, cliqueTransactions);

@ -13,6 +13,7 @@
package tech.pegasys.pantheon.tests.acceptance.dsl.condition.eth;
import tech.pegasys.pantheon.tests.acceptance.dsl.condition.Condition;
import tech.pegasys.pantheon.tests.acceptance.dsl.condition.miner.MiningStatusCondition;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.eth.EthTransactions;
public class EthConditions {
@ -61,4 +62,8 @@ public class EthConditions {
return new ExpectSuccessfulEthGetTransactionReceiptWithoutReason(
transactions.getTransactionReceiptWithRevertReason(transactionHash));
}
public Condition miningStatus(final boolean isMining) {
return new MiningStatusCondition(transactions.mining(), isMining);
}
}

@ -0,0 +1,36 @@
/*
* Copyright 2018 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.condition.miner;
import static org.assertj.core.api.Assertions.assertThat;
import static tech.pegasys.pantheon.tests.acceptance.dsl.WaitUtils.waitFor;
import tech.pegasys.pantheon.tests.acceptance.dsl.condition.Condition;
import tech.pegasys.pantheon.tests.acceptance.dsl.node.Node;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.eth.EthMiningTransaction;
public class MiningStatusCondition implements Condition {
private final EthMiningTransaction transaction;
private final boolean expectedMiningStatus;
public MiningStatusCondition(final EthMiningTransaction transaction, final boolean miningStatus) {
this.transaction = transaction;
this.expectedMiningStatus = miningStatus;
}
@Override
public void verify(final Node node) {
waitFor(10, () -> assertThat(node.execute(transaction)).isEqualTo(expectedMiningStatus));
}
}

@ -37,6 +37,7 @@ import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.clique.CliqueReque
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.eea.EeaRequestFactory;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.ibft2.Ibft2RequestFactory;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.login.LoginRequestFactory;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.miner.MinerRequestFactory;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.net.CustomRequestFactory;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.perm.PermissioningJsonRpcRequestFactory;
@ -293,6 +294,7 @@ public class PantheonNode implements NodeConfiguration, RunnableNode, AutoClosea
new AdminRequestFactory(web3jService),
new EeaRequestFactory(web3jService),
new CustomRequestFactory(web3jService),
new MinerRequestFactory(web3jService),
websocketService,
loginRequestFactory());
}

@ -67,6 +67,7 @@ public class PantheonFactoryConfigurationBuilder {
public PantheonFactoryConfigurationBuilder miningEnabled() {
this.miningParameters = new MiningParametersTestBuilder().enabled(true).build();
this.jsonRpcConfiguration.addRpcApi(RpcApis.MINER);
return this;
}

@ -222,16 +222,30 @@ public class PantheonNodeFactory {
public PantheonNode createCustomGenesisNode(
final String name, final String genesisPath, final boolean canBeBootnode) throws IOException {
return createCustomGenesisNode(name, genesisPath, canBeBootnode, false);
}
public PantheonNode createCustomGenesisNode(
final String name,
final String genesisPath,
final boolean canBeBootnode,
final boolean mining)
throws IOException {
final String genesisFile = genesis.readGenesisFile(genesisPath);
return create(
final PantheonFactoryConfigurationBuilder builder =
new PantheonFactoryConfigurationBuilder()
.name(name)
.jsonRpcEnabled()
.webSocketEnabled()
.genesisConfigProvider((a) -> Optional.of(genesisFile))
.devMode(false)
.bootnodeEligible(canBeBootnode)
.build());
.bootnodeEligible(canBeBootnode);
if (mining) {
builder.miningEnabled();
}
return create(builder.build());
}
public PantheonNode createCliqueNodeWithValidators(final String name, final String... validators)

@ -68,6 +68,9 @@ public class PermissionedNodeBuilder {
private boolean accountSmartContractPermissioningEnabled = false;
private String accountPermissioningSmartContractAddress = null;
private List<String> staticNodes = new ArrayList<>();
private boolean mining = true;
public PermissionedNodeBuilder name(final String name) {
this.name = name;
return this;
@ -129,6 +132,16 @@ public class PermissionedNodeBuilder {
return this;
}
public PermissionedNodeBuilder staticNodes(final List<String> staticNodes) {
this.staticNodes = staticNodes;
return this;
}
public PermissionedNodeBuilder disableMining() {
this.mining = false;
return this;
}
@SuppressWarnings("UnstableApiUsage")
public PermissionedNodeBuilder genesisFile(final String path) {
try {
@ -163,8 +176,15 @@ public class PermissionedNodeBuilder {
.name(name)
.jsonRpcConfiguration(jsonRpcConfigWithPermApiEnabled())
.permissioningConfiguration(permissioningConfiguration)
.bootnodeEligible(false)
.miningEnabled();
.bootnodeEligible(false);
if (mining) {
builder.miningEnabled();
}
if (!staticNodes.isEmpty()) {
builder.staticNodes(staticNodes);
}
if (genesisFile != null) {
builder.genesisConfigProvider((a) -> Optional.of(genesisFile));

@ -17,6 +17,7 @@ import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.clique.CliqueReque
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.eea.EeaRequestFactory;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.ibft2.Ibft2RequestFactory;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.login.LoginRequestFactory;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.miner.MinerRequestFactory;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.net.CustomRequestFactory;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.perm.PermissioningJsonRpcRequestFactory;
@ -36,6 +37,7 @@ public class NodeRequests {
private final CustomRequestFactory custom;
private final Optional<WebSocketService> websocketService;
private final LoginRequestFactory login;
private final MinerRequestFactory miner;
public NodeRequests(
final Web3j netEth,
@ -45,6 +47,7 @@ public class NodeRequests {
final AdminRequestFactory admin,
final EeaRequestFactory eea,
final CustomRequestFactory custom,
final MinerRequestFactory miner,
final Optional<WebSocketService> websocketService,
final LoginRequestFactory login) {
this.netEth = netEth;
@ -54,6 +57,7 @@ public class NodeRequests {
this.admin = admin;
this.eea = eea;
this.custom = custom;
this.miner = miner;
this.websocketService = websocketService;
this.login = login;
}
@ -94,6 +98,10 @@ public class NodeRequests {
return login;
}
public MinerRequestFactory miner() {
return miner;
}
public void shutdown() {
netEth.shutdown();
websocketService.ifPresent(WebSocketService::close);

@ -0,0 +1,38 @@
/*
* Copyright 2018 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.transaction.eth;
import static org.assertj.core.api.Assertions.assertThat;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.NodeRequests;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.Transaction;
import java.io.IOException;
import org.web3j.protocol.core.methods.response.EthMining;
public class EthMiningTransaction implements Transaction<Boolean> {
EthMiningTransaction() {}
@Override
public Boolean execute(final NodeRequests node) {
try {
EthMining response = node.eth().ethMining().send();
assertThat(response).isNotNull();
return response.isMining();
} catch (final IOException e) {
throw new RuntimeException(e);
}
}
}

@ -59,4 +59,8 @@ public class EthTransactions {
final String transactionHash) {
return new EthGetTransactionReceiptWithRevertReason(transactionHash);
}
public EthMiningTransaction mining() {
return new EthMiningTransaction();
}
}

@ -0,0 +1,41 @@
/*
* 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.transaction.miner;
import org.web3j.protocol.Web3jService;
import org.web3j.protocol.core.Request;
public class MinerRequestFactory {
private final Web3jService web3jService;
public MinerRequestFactory(final Web3jService web3jService) {
this.web3jService = web3jService;
}
Request<?, org.web3j.protocol.core.methods.response.VoidResponse> minerStart() {
return new Request<>(
"miner_start",
null,
web3jService,
org.web3j.protocol.core.methods.response.VoidResponse.class);
}
Request<?, org.web3j.protocol.core.methods.response.VoidResponse> minerStop() {
return new Request<>(
"miner_stop",
null,
web3jService,
org.web3j.protocol.core.methods.response.VoidResponse.class);
}
}

@ -0,0 +1,29 @@
/*
* 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.transaction.miner;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.NodeRequests;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.Transaction;
public class MinerStartTransaction implements Transaction<Void> {
@Override
public Void execute(final NodeRequests node) {
try {
node.miner().minerStart().send();
} catch (Exception e) {
throw new RuntimeException(e);
}
return null;
}
}

@ -0,0 +1,29 @@
/*
* 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.transaction.miner;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.NodeRequests;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.Transaction;
public class MinerStopTransaction implements Transaction<Void> {
@Override
public Void execute(final NodeRequests node) {
try {
node.miner().minerStop().send();
} catch (Exception e) {
throw new RuntimeException(e);
}
return null;
}
}

@ -0,0 +1,24 @@
/*
* 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.transaction.miner;
public class MinerTransactions {
public MinerStartTransaction minerStart() {
return new MinerStartTransaction();
}
public MinerStopTransaction minerStop() {
return new MinerStopTransaction();
}
}

@ -12,8 +12,11 @@
*/
package tech.pegasys.pantheon.tests.acceptance.permissioning;
import static org.assertj.core.api.Assertions.assertThat;
import tech.pegasys.pantheon.ethereum.core.Hash;
import tech.pegasys.pantheon.tests.acceptance.dsl.AcceptanceTestBase;
import tech.pegasys.pantheon.tests.acceptance.dsl.WaitUtils;
import tech.pegasys.pantheon.tests.acceptance.dsl.condition.Condition;
import tech.pegasys.pantheon.tests.acceptance.dsl.condition.perm.NodeSmartContractPermissioningConditions;
import tech.pegasys.pantheon.tests.acceptance.dsl.node.Node;
@ -25,14 +28,15 @@ import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.Transaction;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.perm.NodeSmartContractPermissioningTransactions;
import java.io.IOException;
import java.math.BigInteger;
class NodeSmartContractPermissioningAcceptanceTestBase extends AcceptanceTestBase {
private final NodeSmartContractPermissioningTransactions smartContractNodePermissioning;
private final NodeSmartContractPermissioningConditions nodeSmartContractPermissioningConditions;
private static final String CONTRACT_ADDRESS = "0x0000000000000000000000000000000000009999";
private static final String GENESIS_FILE = "/permissioning/simple_permissioning_genesis.json";
protected static final String CONTRACT_ADDRESS = "0x0000000000000000000000000000000000009999";
protected static final String GENESIS_FILE = "/permissioning/simple_permissioning_genesis.json";
protected final Cluster permissionedCluster;
@ -78,6 +82,14 @@ class NodeSmartContractPermissioningAcceptanceTestBase extends AcceptanceTestBas
}
}
protected Node miner(final String name) {
try {
return pantheon.createCustomGenesisNode(name, GENESIS_FILE, false, true);
} catch (IOException e) {
throw new RuntimeException("Error creating node", e);
}
}
@Override
public void tearDownAcceptanceTestBase() {
permissionedCluster.stop();
@ -109,4 +121,12 @@ class NodeSmartContractPermissioningAcceptanceTestBase extends AcceptanceTestBas
return nodeSmartContractPermissioningConditions.connectionIsForbidden(
CONTRACT_ADDRESS, source, target);
}
protected void waitForBlockHeight(final Node node, final long blockchainHeight) {
WaitUtils.waitFor(
120,
() ->
assertThat(node.execute(ethTransactions.blockNumber()))
.isGreaterThanOrEqualTo(BigInteger.valueOf(blockchainHeight)));
}
}

@ -12,13 +12,8 @@
*/
package tech.pegasys.pantheon.tests.acceptance.permissioning;
import static org.assertj.core.api.Assertions.assertThat;
import tech.pegasys.pantheon.tests.acceptance.dsl.WaitUtils;
import tech.pegasys.pantheon.tests.acceptance.dsl.node.Node;
import java.math.BigInteger;
import org.junit.Before;
import org.junit.Test;
@ -47,11 +42,7 @@ public class NodeSmartContractPermissioningOutOfSyncAcceptanceTest
@Test
public void addNodeToClusterAndVerifyNonBootNodePeerConnectionWorksAfterSync() {
final long blockchainHeight = 50L;
WaitUtils.waitFor(
120,
() ->
assertThat(currentHeight(permissionedNodeA))
.isGreaterThanOrEqualTo(BigInteger.valueOf(blockchainHeight)));
waitForBlockHeight(permissionedNodeA, blockchainHeight);
// Add Node B
permissionedCluster.addNode(permissionedNodeB);
@ -62,15 +53,7 @@ public class NodeSmartContractPermissioningOutOfSyncAcceptanceTest
permissionedNodeB.verify(connectionIsForbidden(permissionedNodeA, permissionedNodeB));
// connection should be allowed after node B syncs
WaitUtils.waitFor(
() ->
assertThat(currentHeight(permissionedNodeB))
.isGreaterThanOrEqualTo(BigInteger.valueOf(blockchainHeight)));
waitForBlockHeight(permissionedNodeB, blockchainHeight);
permissionedNodeB.verify(connectionIsAllowed(permissionedNodeA, permissionedNodeB));
}
private BigInteger currentHeight(final Node node) {
return node.execute(ethTransactions.blockNumber());
}
}

@ -0,0 +1,81 @@
/*
* Copyright 2018 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.permissioning;
import static java.util.stream.Collectors.toList;
import tech.pegasys.pantheon.tests.acceptance.dsl.node.Node;
import tech.pegasys.pantheon.tests.acceptance.dsl.node.RunnableNode;
import java.net.URI;
import java.util.Arrays;
import java.util.List;
import org.jetbrains.annotations.NotNull;
import org.junit.Before;
import org.junit.Test;
public class NodesSmartContractPermissioningStaticNodesAcceptanceTest
extends NodeSmartContractPermissioningAcceptanceTestBase {
private Node miner;
private Node permissionedNode;
@Before
public void setUp() {
miner = miner("miner");
permissionedCluster.start(miner);
}
@Test
public void onlyTrustStaticNodesWhileOutOfSync() {
// wait for some blocks so the permissioned node has some syncing to do
waitForBlockHeight(miner, 50);
stopMining(miner);
// start permissioned node with miner node in the static nodes list
permissionedNode = permissionedNodeWithStaticNodes(Arrays.asList(miner));
permissionedCluster.addNode(permissionedNode);
// as soon as we start the node should connect to static nodes
permissionedNode.verify(net.awaitPeerCount(1));
waitForBlockHeight(permissionedNode, 50);
// after syncing up with the network the node won't trust static nodes anymore
permissionedNode.verify(net.awaitPeerCount(0));
}
private void stopMining(final Node node) {
node.execute(minerTransactions.minerStop());
node.verify(eth.miningStatus(false));
}
private Node permissionedNodeWithStaticNodes(final List<Node> staticNodes) {
return permissionedNodeBuilder
.name("node-with-static-nodes")
.genesisFile(GENESIS_FILE)
.nodesContractEnabled(CONTRACT_ADDRESS)
.staticNodes(mapNodesToEnodeURLs(staticNodes))
.disableMining()
.build();
}
@NotNull
private List<String> mapNodesToEnodeURLs(final List<Node> staticNodes) {
return staticNodes.stream()
.map(node -> (RunnableNode) node)
.map(RunnableNode::enodeUrl)
.map(URI::toASCIIString)
.collect(toList());
}
}
Loading…
Cancel
Save